From 24e3c71111d2c377b9c408234e953c4f3c14f395 Mon Sep 17 00:00:00 2001 From: mikkopa Date: Mon, 18 Feb 2008 13:19:23 +0000 Subject: [PATCH] Remote copied curren trunk (3509) to 0.6b branch --- trunk/.nant/local.include | 41 + trunk/CONTRIBUTORS.txt | 77 + trunk/LICENSE.txt | 25 + trunk/OpenSim.FxCop | 7241 +++++++++++++++++ .../LoadRegions/LoadRegionsPlugin.cs | 108 + .../LoadRegions/Properties/AssemblyInfo.cs | 67 + .../RemoteController/RemoteAdminPlugin.cs | 391 + trunk/OpenSim/Framework/ACL.cs | 263 + trunk/OpenSim/Framework/AgentCircuitData.cs | 105 + .../OpenSim/Framework/AgentCircuitManager.cs | 127 + trunk/OpenSim/Framework/AgentInventory.cs | 258 + trunk/OpenSim/Framework/AssemblyInfo.cs | 64 + trunk/OpenSim/Framework/AssetBase.cs | 55 + trunk/OpenSim/Framework/AssetConfig.cs | 86 + trunk/OpenSim/Framework/AssetLandmark.cs | 59 + .../Filesystem/AssetLoaderFileSystem.cs | 164 + trunk/OpenSim/Framework/AssetRequest.cs | 38 + trunk/OpenSim/Framework/AssetStorage.cs | 48 + .../OpenSim/Framework/AuthenticateResponse.cs | 39 + trunk/OpenSim/Framework/AvatarWearable.cs | 71 + trunk/OpenSim/Framework/BlockingQueue.cs | 73 + .../OpenSim/Framework/ChildAgentDataUpdate.cs | 53 + trunk/OpenSim/Framework/ClientManager.cs | 182 + .../Framework/Communications/CAPSService.cs | 54 + .../Cache/AgentAssetTransactions.cs | 558 ++ .../Cache/AgentAssetTransactionsManager.cs | 206 + .../Communications/Cache/AssetCache.cs | 696 ++ .../Communications/Cache/AssetServer.cs | 145 + .../Communications/Cache/AssetServerBase.cs | 163 + .../Communications/Cache/CachedUserInfo.cs | 133 + .../Communications/Cache/GridAssetClient.cs | 125 + .../Cache/InventoryFolderImpl.cs | 156 + .../Communications/Cache/LibraryRootFolder.cs | 278 + .../Communications/Cache/SQLAssetServer.cs | 102 + .../Cache/UserProfileCacheService.cs | 308 + .../Communications/Capabilities/Caps.cs | 745 ++ .../Communications/Capabilities/LLSD.cs | 680 ++ .../Communications/Capabilities/LLSDArray.cs | 41 + .../Capabilities/LLSDAssetUploadComplete.cs | 45 + .../Capabilities/LLSDAssetUploadRequest.cs | 46 + .../Capabilities/LLSDAssetUploadResponse.cs | 41 + .../Capabilities/LLSDCapEvent.cs | 40 + .../Capabilities/LLSDCapsDetails.cs | 50 + .../Communications/Capabilities/LLSDEmpty.cs | 37 + .../Capabilities/LLSDHelpers.cs | 151 + .../Capabilities/LLSDItemUpdate.cs | 42 + .../Capabilities/LLSDMapLayer.cs | 45 + .../Capabilities/LLSDMapLayerResponse.cs | 40 + .../Capabilities/LLSDMapRequest.cs | 40 + .../Communications/Capabilities/LLSDMethod.cs | 32 + .../Capabilities/LLSDStreamHandler.cs | 69 + .../LLSDTaskInventoryUploadComplete.cs | 50 + .../Capabilities/LLSDTaskScriptUpdate.cs | 51 + .../Communications/Capabilities/LLSDTest.cs | 40 + .../Communications/Capabilities/LLSDType.cs | 55 + .../Communications/CommunicationsManager.cs | 244 + .../Framework/Communications/IGridServices.cs | 42 + .../IInterRegionCommunications.cs | 50 + .../Communications/IInventoryServices.cs | 100 + .../Communications/InventoryServiceBase.cs | 389 + .../Framework/Communications/LoginResponse.cs | 751 ++ .../Framework/Communications/LoginService.cs | 758 ++ .../Communications/Properties/AssemblyInfo.cs | 65 + .../RestClient/GenericAsyncResult.cs | 186 + .../Communications/RestClient/RestClient.cs | 446 + .../Communications/UserManagerBase.cs | 550 ++ .../Configuration/HTTP/HTTPConfiguration.cs | 117 + .../HTTP/RemoteConfigSettings.cs | 62 + .../Configuration/XML/XmlConfiguration.cs | 139 + .../OpenSim/Framework/ConfigurationMember.cs | 503 ++ .../OpenSim/Framework/ConfigurationOption.cs | 65 + .../OpenSim/Framework/Console/AssemblyInfo.cs | 58 + .../OpenSim/Framework/Console/ConsoleBase.cs | 423 + .../Framework/Console/ConsoleCallbacksBase.cs | 35 + .../OpenSim/Framework/Console/MainConsole.cs | 41 + .../Framework/Console/OpenSimAppender.cs | 115 + trunk/OpenSim/Framework/Constants.cs | 39 + trunk/OpenSim/Framework/Culture.cs | 54 + .../Framework/Data.DB4o/DB4oGridData.cs | 177 + .../Framework/Data.DB4o/DB4oManager.cs | 170 + .../Framework/Data.DB4o/DB4oUserData.cs | 270 + .../Data.DB4o/Properties/AssemblyInfo.cs | 66 + .../Framework/Data.MSSQL/MSSQLAssetData.cs | 222 + .../Framework/Data.MSSQL/MSSQLGridData.cs | 327 + .../Data.MSSQL/MSSQLInventoryData.cs | 728 ++ .../Framework/Data.MSSQL/MSSQLLogData.cs | 120 + .../Framework/Data.MSSQL/MSSQLManager.cs | 525 ++ .../Framework/Data.MSSQL/MSSQLUserData.cs | 771 ++ .../Data.MSSQL/Properties/AssemblyInfo.cs | 66 + .../Resources/CreateAssetsTable.sql | 19 + .../Resources/CreateFoldersTable.sql | 27 + .../Data.MSSQL/Resources/CreateItemsTable.sql | 39 + .../Resources/CreateUserFriendsTable.sql | 14 + .../Data.MSSQL/Resources/Mssql-agents.sql | 37 + .../Data.MSSQL/Resources/Mssql-logs.sql | 20 + .../Data.MSSQL/Resources/Mssql-regions.sql | 40 + .../Data.MSSQL/Resources/Mssql-users.sql | 42 + .../Framework/Data.MySQL/MySQLAssetData.cs | 199 + .../Framework/Data.MySQL/MySQLDataStore.cs | 1692 ++++ .../Data.MySQL/MySQLDatabaseMapper.cs | 54 + .../Framework/Data.MySQL/MySQLGridData.cs | 331 + .../Data.MySQL/MySQLInventoryData.cs | 653 ++ .../Framework/Data.MySQL/MySQLLogData.cs | 106 + .../Framework/Data.MySQL/MySQLManager.cs | 748 ++ .../Framework/Data.MySQL/MySQLUserData.cs | 644 ++ .../Data.MySQL/Properties/AssemblyInfo.cs | 66 + .../Data.MySQL/Resources/AvatarAppearance.sql | 42 + .../Resources/CreateAgentsTable.sql | 24 + .../Resources/CreateAssetsTable.sql | 11 + .../Resources/CreateFoldersTable.sql | 11 + .../Data.MySQL/Resources/CreateItemsTable.sql | 18 + .../Data.MySQL/Resources/CreateLogsTable.sql | 10 + .../Resources/CreateRegionsTable.sql | 30 + .../Resources/CreateUserFriendsTable.sql | 11 + .../Data.MySQL/Resources/CreateUsersTable.sql | 35 + .../UpgradeFoldersTableToVersion2.sql | 4 + .../Resources/UpgradeItemsTableToVersion2.sql | 9 + .../Resources/UpgradeUsersTableToVersion2.sql | 3 + .../Data.SQLite/Properties/AssemblyInfo.cs | 66 + .../Data.SQLite/Resources/001_AssetStore.sql | 13 + .../Resources/001_InventoryStore.sql | 26 + .../Data.SQLite/Resources/001_RegionStore.sql | 121 + .../Data.SQLite/Resources/001_UserStore.sql | 37 + .../Framework/Data.SQLite/SQLiteAssetData.cs | 300 + .../Framework/Data.SQLite/SQLiteBase.cs | 269 + .../Framework/Data.SQLite/SQLiteGridData.cs | 205 + .../Data.SQLite/SQLiteInventoryStore.cs | 634 ++ .../Framework/Data.SQLite/SQLiteManager.cs | 280 + .../Framework/Data.SQLite/SQLiteRegionData.cs | 1733 ++++ .../Framework/Data.SQLite/SQLiteUserData.cs | 835 ++ trunk/OpenSim/Framework/Data/GridData.cs | 122 + trunk/OpenSim/Framework/Data/ILogData.cs | 91 + trunk/OpenSim/Framework/Data/IniConfig.cs | 98 + .../Framework/Data/OpenSimDataReader.cs | 68 + .../Data/OpenSimDatabaseConnector.cs | 78 + .../Data/OpenSimObjectFieldMapper.cs | 103 + .../Framework/Data/OpenSimTableMapper.cs | 41 + .../Data/PrimitiveBaseShapeTableMapper.cs | 171 + .../Framework/Data/Properties/AssemblyInfo.cs | 66 + .../Framework/Data/RegionProfileData.cs | 219 + .../OpenSim/Framework/Data/ReservationData.cs | 47 + trunk/OpenSim/Framework/EstateSettings.cs | 1021 +++ trunk/OpenSim/Framework/FriendListItem.cs | 51 + trunk/OpenSim/Framework/GridConfig.cs | 149 + trunk/OpenSim/Framework/GridInstantMessage.cs | 64 + trunk/OpenSim/Framework/IAssetLoader.cs | 38 + trunk/OpenSim/Framework/IAssetProvider.cs | 41 + trunk/OpenSim/Framework/IAssetServer.cs | 57 + trunk/OpenSim/Framework/IClientAPI.cs | 657 ++ trunk/OpenSim/Framework/IGenericConfig.cs | 40 + trunk/OpenSim/Framework/IPlugin.cs | 53 + .../OpenSim/Framework/IRegionCommsListener.cs | 71 + trunk/OpenSim/Framework/IRegionLoader.cs | 38 + trunk/OpenSim/Framework/IScene.cs | 66 + trunk/OpenSim/Framework/IUserData.cs | 188 + trunk/OpenSim/Framework/IUserService.cs | 91 + trunk/OpenSim/Framework/InventoryConfig.cs | 103 + trunk/OpenSim/Framework/InventoryItemBase.cs | 294 + trunk/OpenSim/Framework/LandData.cs | 138 + trunk/OpenSim/Framework/Login.cs | 50 + trunk/OpenSim/Framework/MapBlockData.cs | 50 + .../OpenSim/Framework/MessageServerConfig.cs | 138 + trunk/OpenSim/Framework/NeighbourInfo.cs | 42 + trunk/OpenSim/Framework/NetworkServersInfo.cs | 104 + trunk/OpenSim/Framework/PacketPool.cs | 158 + trunk/OpenSim/Framework/PrimitiveBaseShape.cs | 237 + .../OpenSim/Framework/RegionCommsListener.cs | 195 + trunk/OpenSim/Framework/RegionHandle.cs | 150 + trunk/OpenSim/Framework/RegionInfo.cs | 414 + .../Filesystem/RegionLoaderFileSystem.cs | 66 + .../RegionLoader/Web/RegionLoaderWebServer.cs | 100 + trunk/OpenSim/Framework/Remoting.cs | 134 + .../Framework/SerializableRegionInfo.cs | 161 + .../Framework/Servers/BaseHttpServer.cs | 612 ++ .../Framework/Servers/BaseOpenSimServer.cs | 84 + .../Framework/Servers/BaseRequestHandler.cs | 63 + .../Framework/Servers/BaseStreamHandler.cs | 41 + .../Framework/Servers/BinaryStreamHandler.cs | 74 + .../Framework/Servers/CheckSumServer.cs | 127 + .../Framework/Servers/GenericHTTPMethod.cs | 34 + .../Framework/Servers/IStreamHandler.cs | 61 + trunk/OpenSim/Framework/Servers/LLSDMethod.cs | 33 + .../Framework/Servers/MessageServerInfo.cs | 48 + .../Servers/RestDeserialiseHandler.cs | 66 + trunk/OpenSim/Framework/Servers/RestMethod.cs | 31 + .../Framework/Servers/RestObjectPoster.cs | 81 + .../Servers/RestObjectPosterResponse.cs | 93 + .../Framework/Servers/RestStreamHandler.cs | 57 + .../Servers/SynchronousRestObjectPoster.cs | 74 + .../OpenSim/Framework/Servers/XmlRpcMethod.cs | 33 + .../Statistics/AssetStatsReporter.cs | 106 + .../Statistics/SimExtraStatsReporter.cs | 70 + .../Framework/Statistics/StatsManager.cs | 73 + .../Framework/Statistics/UserStatsReporter.cs | 94 + trunk/OpenSim/Framework/TaskInventoryItem.cs | 210 + trunk/OpenSim/Framework/UserConfig.cs | 136 + trunk/OpenSim/Framework/UserProfileData.cs | 230 + trunk/OpenSim/Framework/Util.cs | 499 ++ trunk/OpenSim/Framework/sLLVector3.cs | 52 + trunk/OpenSim/Grid/AssetServer/Main.cs | 195 + .../AssetServer/Properties/AssemblyInfo.cs | 63 + trunk/OpenSim/Grid/AssetServer/RestService.cs | 155 + .../Grid/GridServer.Config/AssemblyInfo.cs | 56 + .../Grid/GridServer.Config/DbGridConfig.cs | 172 + trunk/OpenSim/Grid/GridServer/GridManager.cs | 903 ++ trunk/OpenSim/Grid/GridServer/Main.cs | 220 + .../GridServer/Properties/AssemblyInfo.cs | 63 + .../InventoryServer/GridInventoryService.cs | 206 + .../Grid/InventoryServer/InventoryManager.cs | 212 + trunk/OpenSim/Grid/InventoryServer/Main.cs | 135 + .../Grid/Manager/OpenGridServices.Manager.mds | 16 + .../OpenGridServices.Manager.userprefs | 39 + .../OpenGridServices.Manager.usertasks | 2 + .../OpenGridServices.Manager/AssemblyInfo.cs | 60 + .../OpenGridServices.Manager/BlockingQueue.cs | 61 + .../ConnectToGridServer.cs | 41 + .../ConnectToGridServerDialog.cs | 54 + .../GridServerConnectionManager.cs | 134 + .../Manager/OpenGridServices.Manager/Main.cs | 123 + .../OpenGridServices.Manager/MainWindow.cs | 104 + .../OpenGridServices.Manager.mdp | 43 + .../OpenGridServices.Manager.pidb | Bin 0 -> 12308 bytes .../OpenGridServices.Manager/RegionBlock.cs | 63 + .../Manager/OpenGridServices.Manager/Util.cs | 161 + ...vices.Manager.ConnectToGridServerDialog.cs | 254 + .../OpenGridServices.Manager.MainWindow.cs | 284 + .../gtk-gui/generated.cs | 63 + .../gtk-gui/gui.stetic | 502 ++ trunk/OpenSim/Grid/MessagingServer/Main.cs | 157 + .../Grid/MessagingServer/MessageService.cs | 478 ++ .../Grid/MessagingServer/UserPresenceData.cs | 53 + .../Grid/MessagingServer/WorkUnitBase.cs | 37 + .../MessagingServer/WorkUnitPresenceUpdate.cs | 37 + .../Grid/ScriptEngine/Common/Executor.cs | 139 + .../Grid/ScriptEngine/Common/IScript.cs | 36 + .../Common/LSL_BuiltIn_Commands_Interface.cs | 636 ++ .../Grid/ScriptEngine/Common/LSL_Types.cs | 83 + .../Common/Properties/AssemblyInfo.cs | 64 + .../DotNetEngine/AppDomainManager.cs | 226 + .../Grid/ScriptEngine/DotNetEngine/Common.cs | 58 + .../DotNetEngine/Compiler/LSL/Compiler.cs | 146 + .../Compiler/LSL/LSL2CSConverter.cs | 316 + .../Compiler/LSL/LSL_BaseClass.cs | 2123 +++++ .../DotNetEngine/Compiler/LSO/Common.cs | 87 + .../DotNetEngine/Compiler/LSO/Engine.cs | 291 + .../Compiler/LSO/IL_common_functions.cs | 51 + .../Compiler/LSO/LSL_BaseClass.cs | 86 + .../Compiler/LSO/LSL_BaseClass_Builtins.cs | 401 + .../Compiler/LSO/LSL_BaseClass_OPCODES.cs | 394 + .../Compiler/LSO/LSL_CLRInterface.cs | 75 + .../Compiler/LSO/LSL_OPCODE_IL_processor.cs | 435 + .../DotNetEngine/Compiler/LSO/LSO_Enums.cs | 560 ++ .../DotNetEngine/Compiler/LSO/LSO_Parser.cs | 728 ++ .../DotNetEngine/Compiler/LSO/LSO_Struct.cs | 143 + .../Server_API/LSL_BuiltIn_Commands.cs | 2286 ++++++ .../DotNetEngine/Compiler/c_sharp_example.txt | 12 + .../ScriptEngine/DotNetEngine/EventManager.cs | 222 + .../DotNetEngine/EventQueueManager.cs | 336 + .../DotNetEngine/LSLLongCmdHandler.cs | 355 + .../DotNetEngine/Properties/AssemblyInfo.cs | 66 + .../ScriptEngine/DotNetEngine/ScriptEngine.cs | 119 + .../DotNetEngine/ScriptManager.cs | 421 + .../TempDotNetMicroThreadingCodeInjector.cs | 69 + .../OpenSim/Grid/ScriptServer/Application.cs | 60 + trunk/OpenSim/Grid/ScriptServer/FakeScene.cs | 55 + .../ScriptServer/Properties/AssemblyInfo.cs | 64 + .../Grid/ScriptServer/RemotingObject.cs | 47 + .../Grid/ScriptServer/RemotingServer.cs | 57 + .../ScriptServer/Region/RegionBase.cs | 244 + .../Region/RegionConnectionManager.cs | 57 + .../ScriptServer/RegionCommManager.cs | 101 + .../ScriptServer/ScriptEngineLoader.cs | 117 + .../ScriptServer/ScriptEnginesManager.cs | 63 + .../Grid/ScriptServer/ScriptServerMain.cs | 110 + .../Grid/UserServer.Config/AssemblyInfo.cs | 56 + .../Grid/UserServer.Config/DbUserConfig.cs | 106 + trunk/OpenSim/Grid/UserServer/Main.cs | 251 + .../UserServer/MessageServersConnector.cs | 180 + .../UserServer/Properties/AssemblyInfo.cs | 64 + .../Grid/UserServer/UserLoginService.cs | 294 + trunk/OpenSim/Grid/UserServer/UserManager.cs | 364 + .../OpenSim/Region/Application/Application.cs | 138 + .../Region/Application/IApplicationPlugin.cs | 41 + .../OpenSim/Region/Application/OpenSimMain.cs | 1126 +++ .../OpenSim/Region/Application/VersionInfo.cs | 36 + .../ClientStack/ClientStackNetworkHandler.cs | 38 + .../OpenSim/Region/ClientStack/ClientView.cs | 3848 +++++++++ .../OpenSim/Region/ClientStack/PacketQueue.cs | 487 ++ .../Region/ClientStack/PacketServer.cs | 151 + .../Region/ClientStack/PacketThrottle.cs | 93 + trunk/OpenSim/Region/ClientStack/QueItem.cs | 44 + .../ClientStack/RegionApplicationBase.cs | 161 + trunk/OpenSim/Region/ClientStack/UDPServer.cs | 402 + .../Local/CommunicationsLocal.cs | 53 + .../Local/LocalBackEndServices.cs | 462 ++ .../Local/LocalInventoryService.cs | 142 + .../Communications/Local/LocalLoginService.cs | 235 + .../Communications/Local/LocalUserServices.cs | 105 + .../Local/Properties/AssemblyInfo.cs | 66 + .../Communications/OGS1/CommunicationsOGS1.cs | 49 + .../Communications/OGS1/OGS1GridServices.cs | 1365 ++++ .../Communications/OGS1/OGS1InterSimComms.cs | 249 + .../OGS1/OGS1InventoryService.cs | 208 + .../Communications/OGS1/OGS1UserServices.cs | 465 ++ .../OGS1/Properties/AssemblyInfo.cs | 66 + .../Region/Environment/EstateManager.cs | 674 ++ .../Environment/InstantMessageReceiver.cs | 56 + .../Interfaces/IAgentAssetTransactions.cs | 45 + .../Environment/Interfaces/IAvatarFactory.cs | 40 + .../Interfaces/IDynamicTextureManager.cs | 56 + .../Environment/Interfaces/IHttpRequests.cs | 42 + .../Interfaces/IRegionDataStore.cs | 79 + .../Environment/Interfaces/IRegionModule.cs | 42 + .../Region/Environment/Interfaces/ISimChat.cs | 38 + .../Region/Environment/Interfaces/ITerrain.cs | 74 + .../Environment/Interfaces/ITerrainChannel.cs | 38 + .../Environment/Interfaces/IWorldComm.cs | 45 + .../Region/Environment/Interfaces/IXMLRPC.cs | 44 + .../Region/Environment/Interfaces/IXfer.cs | 35 + .../Region/Environment/LandManagement/Land.cs | 819 ++ .../Environment/LandManagement/LandManager.cs | 896 ++ .../Region/Environment/ModuleLoader.cs | 305 + .../Modules/AgentAssetTransactionModule.cs | 272 + .../Modules/AgentAssetsTransactions.cs | 408 + .../Modules/AppearanceTableMapper.cs | 244 + .../Modules/AssetDownloadModule.cs | 72 + .../Modules/AvatarFactoryModule.cs | 339 + .../Modules/AvatarProfilesModule.cs | 94 + .../Modules/BetaGridLikeMoneyModule.cs | 318 + .../Region/Environment/Modules/ChatModule.cs | 815 ++ .../Modules/DynamicTextureModule.cs | 190 + .../Region/Environment/Modules/EmailModule.cs | 34 + .../Environment/Modules/FriendsModule.cs | 222 + .../Environment/Modules/GroupsModule.cs | 62 + .../Modules/InstantMessageModule.cs | 127 + .../Environment/Modules/InventoryModule.cs | 62 + .../Environment/Modules/LoadImageURLModule.cs | 177 + .../Modules/ScriptsHttpRequests.cs | 343 + .../Region/Environment/Modules/SunModule.cs | 194 + .../Environment/Modules/TeleportModule.cs | 34 + .../Modules/Terrain/TerrainModule.cs | 132 + .../Modules/TextureDownloadModule.cs | 188 + .../Environment/Modules/TextureSender.cs | 166 + .../Modules/TreePopulatorModule.cs | 246 + .../Modules/UserTextureDownloadService.cs | 143 + .../Environment/Modules/WorldCommModule.cs | 515 ++ .../Environment/Modules/XMLRPCModule.cs | 431 + .../Region/Environment/Modules/XferModule.cs | 226 + .../Region/Environment/PermissionManager.cs | 620 ++ .../Environment/Scenes/AvatarAnimations.cs | 62 + .../Environment/Scenes/AvatarAppearance.cs | 153 + .../Region/Environment/Scenes/EntityBase.cs | 159 + .../Environment/Scenes/IScenePresenceBody.cs | 38 + .../Region/Environment/Scenes/InnerScene.cs | 1173 +++ .../Environment/Scenes/Scene.Inventory.cs | 865 ++ .../Scenes/Scene.PacketHandlers.cs | 218 + .../Region/Environment/Scenes/Scene.cs | 2637 ++++++ .../Region/Environment/Scenes/SceneBase.cs | 198 + .../Scenes/SceneCommunicationService.cs | 598 ++ .../Region/Environment/Scenes/SceneEvents.cs | 355 + .../Region/Environment/Scenes/SceneManager.cs | 429 + .../Scenes/SceneObjectGroup.Inventory.cs | 275 + .../Environment/Scenes/SceneObjectGroup.cs | 1781 ++++ .../Scenes/SceneObjectPart.Inventory.cs | 510 ++ .../Environment/Scenes/SceneObjectPart.cs | 1850 +++++ .../Environment/Scenes/ScenePresence.cs | 1767 ++++ .../Environment/Scenes/SceneXmlLoader.cs | 223 + .../Scenes/Scripting/IScriptHost.cs | 46 + .../Scenes/Scripting/NullScriptHost.cs | 88 + .../Scenes/Scripting/ScriptEngineInterface.cs | 40 + .../Scenes/Scripting/ScriptEngineLoader.cs | 119 + .../Environment/Scenes/SimStatsReporter.cs | 384 + .../Region/Environment/StorageManager.cs | 79 + .../Environment/Types/BasicQuadTreeNode.cs | 269 + .../Region/Environment/Types/UpdateQueue.cs | 79 + .../Examples/SimpleApp/ComplexObject.cs | 115 + .../Examples/SimpleApp/CpuCounterObject.cs | 60 + .../Examples/SimpleApp/FileSystemObject.cs | 52 + .../Examples/SimpleApp/MyNpcCharacter.cs | 531 ++ .../Region/Examples/SimpleApp/MyWorld.cs | 83 + .../Region/Examples/SimpleApp/Program.cs | 221 + .../SimpleApp/Properties/AssemblyInfo.cs | 64 + .../Engines/CSharp/CSharpScriptEngine.cs | 106 + .../CSharp/Examples/ExportRegionToLSL.cs | 94 + .../Engines/JScript/JScriptEngine.cs | 106 + .../Engines/JVMEngine/JVM/ClassInstance.cs | 43 + .../Engines/JVMEngine/JVM/ClassRecord.cs | 648 ++ .../Engines/JVMEngine/JVM/Heap.cs | 40 + .../JVMEngine/JVM/Interpreter.Logic.cs | 619 ++ .../JVMEngine/JVM/Interpreter.Methods.cs | 102 + .../JVMEngine/JVM/Interpreter.Return.cs | 36 + .../Engines/JVMEngine/JVM/Interpreter.cs | 132 + .../Engines/JVMEngine/JVM/MainMemory.cs | 41 + .../Engines/JVMEngine/JVM/MethodMemory.cs | 44 + .../Engines/JVMEngine/JVM/Object.cs | 33 + .../Engines/JVMEngine/JVM/OpCodes.cs | 80 + .../Engines/JVMEngine/JVM/Stack.cs | 40 + .../Engines/JVMEngine/JVM/StackFrame.cs | 46 + .../Engines/JVMEngine/JVM/Thread.cs | 111 + .../Engines/JVMEngine/JavaEngine.cs | 52 + .../Engines/JVMEngine/OpenSimJVM.cs | 166 + .../Engines/JVMEngine/Types/ArrayReference.cs | 34 + .../Engines/JVMEngine/Types/BaseType.cs | 36 + .../JVMEngine/Types/ObjectReference.cs | 39 + .../JVMEngine/Types/PrimitiveTypes/Byte.cs | 34 + .../JVMEngine/Types/PrimitiveTypes/Char.cs | 34 + .../JVMEngine/Types/PrimitiveTypes/Float.cs | 39 + .../JVMEngine/Types/PrimitiveTypes/Int.cs | 39 + .../Region/ExtensionsScriptModule/Script.cs | 64 + .../ExtensionsScriptModule/ScriptAPI.cs | 57 + .../ExtensionsScriptModule/ScriptInfo.cs | 67 + .../ScriptInterpretedAPI.cs | 302 + .../ScriptInterpretedEvents.cs | 46 + .../ExtensionsScriptModule/ScriptManager.cs | 151 + .../BasicPhysicsPlugin/AssemblyInfo.cs | 58 + .../BasicPhysicsPlugin/BasicPhysicsPlugin.cs | 365 + .../Physics/BulletXPlugin/AssemblyInfo.cs | 58 + .../Physics/BulletXPlugin/BulletXPlugin.cs | 1559 ++++ .../BulletXPlugin/TriangleIndexVertexArray.cs | 198 + .../Region/Physics/Manager/AssemblyInfo.cs | 58 + .../Region/Physics/Manager/CollisionLocker.cs | 74 + .../OpenSim/Region/Physics/Manager/IMesher.cs | 51 + .../Region/Physics/Manager/PhysicsActor.cs | 360 + .../Physics/Manager/PhysicsPluginManager.cs | 176 + .../Region/Physics/Manager/PhysicsScene.cs | 168 + .../Region/Physics/Manager/PhysicsSensor.cs | 86 + .../Region/Physics/Manager/PhysicsVector.cs | 158 + .../Region/Physics/Manager/ZeroMesher.cs | 69 + .../Region/Physics/Meshing/Extruder.cs | 125 + .../Region/Physics/Meshing/HelperTypes.cs | 304 + trunk/OpenSim/Region/Physics/Meshing/Mesh.cs | 235 + .../Region/Physics/Meshing/Meshmerizer.cs | 818 ++ .../Region/Physics/Meshing/SimpleHull.cs | 397 + .../OpenSim/Region/Physics/Meshing/Simplex.cs | 221 + .../Region/Physics/OdePlugin/AssemblyInfo.cs | 58 + .../Region/Physics/OdePlugin/ODECharacter.cs | 823 ++ .../Region/Physics/OdePlugin/ODEPrim.cs | 1425 ++++ .../Region/Physics/OdePlugin/OdePlugin.cs | 1710 ++++ .../Region/Physics/POSPlugin/AssemblyInfo.cs | 58 + .../Region/Physics/POSPlugin/POSPlugin.cs | 663 ++ .../Physics/PhysXPlugin/AssemblyInfo.cs | 58 + .../Region/Physics/PhysXPlugin/PhysXPlugin.cs | 599 ++ .../Region/ScriptEngine/Common/Executor.cs | 92 + .../ScriptEngine/Common/ExecutorBase.cs | 108 + .../Region/ScriptEngine/Common/IScript.cs | 41 + .../ScriptEngine/Common/LSL_BaseClass.cs | 2211 +++++ .../Common/LSL_BuiltIn_Commands.cs | 3709 +++++++++ .../Common/LSL_BuiltIn_Commands_Interface.cs | 646 ++ .../Region/ScriptEngine/Common/LSL_Types.cs | 1070 +++ .../Common/Properties/AssemblyInfo.cs | 64 + .../ScriptEngineBase/AppDomainManager.cs | 254 + .../AsyncLSLCommandManager.cs | 320 + .../Common/ScriptEngineBase/Common.cs | 57 + .../Common/ScriptEngineBase/EventManager.cs | 288 + .../ScriptEngineBase/EventQueueManager.cs | 467 ++ .../ScriptEngineBase/EventQueueThreadClass.cs | 337 + .../ScriptEngineBase/MaintenanceThread.cs | 190 + .../Common/ScriptEngineBase/ScriptEngine.cs | 189 + .../Common/ScriptEngineBase/ScriptManager.cs | 423 + .../iScriptEngineFunctionModule.cs | 40 + .../Common/ScriptServerInterfaces.cs | 90 + .../Region/ScriptEngine/Common/TRPC/MyBase.cs | 38 + .../ScriptEngine/Common/TRPC/TCPClient.cs | 153 + .../ScriptEngine/Common/TRPC/TCPCommon.cs | 61 + .../ScriptEngine/Common/TRPC/TCPServer.cs | 134 + .../ScriptEngine/Common/TRPC/TCPSocket.cs | 114 + .../Region/ScriptEngine/Common/TRPC_Remote.cs | 205 + .../DotNetEngine/Compiler/LSL/Compiler.cs | 441 + .../Compiler/LSL/LSL2CSConverter.cs | 311 + .../DotNetEngine/Compiler/c_sharp_example.txt | 12 + .../DotNetEngine/Properties/AssemblyInfo.cs | 66 + .../ScriptEngine/DotNetEngine/ScriptEngine.cs | 56 + .../DotNetEngine/ScriptManager.cs | 164 + .../ScriptEngine/LSOEngine/LSO/Common.cs | 86 + .../ScriptEngine/LSOEngine/LSO/Engine.cs | 293 + .../LSOEngine/LSO/IL_common_functions.cs | 51 + .../LSOEngine/LSO/LSL_BaseClass_OPCODES.cs | 395 + .../LSOEngine/LSO/LSL_CLRInterface.cs | 75 + .../LSOEngine/LSO/LSL_OPCODE_IL_processor.cs | 435 + .../ScriptEngine/LSOEngine/LSO/LSO_Enums.cs | 560 ++ .../ScriptEngine/LSOEngine/LSO/LSO_Parser.cs | 729 ++ .../ScriptEngine/LSOEngine/LSO/LSO_Struct.cs | 143 + .../ScriptEngine/LSOEngine/LSOScript.cs | 50 + .../LSOEngine/Properties/AssemblyInfo.cs | 66 + .../ScriptEngine/LSOEngine/ScriptEngine.cs | 61 + .../ScriptEngine/LSOEngine/ScriptManager.cs | 160 + .../ScriptEngine/RemoteServer/Common.cs | 58 + .../ScriptEngine/RemoteServer/EventManager.cs | 263 + .../RemoteServer/Properties/AssemblyInfo.cs | 66 + .../ScriptEngine/RemoteServer/RemoteServer.cs | 83 + .../ScriptEngine/RemoteServer/ScriptEngine.cs | 104 + .../OpenSim.DataStore.DB4o/DB4oDataStore.cs | 133 + .../Properties/AssemblyInfo.cs | 63 + .../OpenSim.DataStore.MSSQL/MSSQLDataStore.cs | 1100 +++ .../NullDataStore.cs | 89 + .../Properties/AssemblyInfo.cs | 66 + .../Properties/AssemblyInfo.cs | 65 + .../Terrain.BasicTerrain/TerrainEngine.cs | 1456 ++++ .../Terrain.BasicTerrain/TerrainFilter.cs | 125 + .../libTerrainBSD/Bitmap/Bitmap.cs | 86 + .../libTerrainBSD/Channel/Channel.cs | 60 + .../libTerrainBSD/Channel/Common.cs | 283 + .../libTerrainBSD/Channel/Editing/Flatten.cs | 144 + .../libTerrainBSD/Channel/Editing/Raise.cs | 131 + .../libTerrainBSD/Channel/File.cs | 76 + .../Channel/Generators/Cellular.cs | 29 + .../Channel/Generators/Fracture.cs | 143 + .../Channel/Generators/Gradient.cs | 61 + .../Channel/Generators/HillPlanter.cs | 282 + .../Channel/Generators/Midpoint.cs | 29 + .../Channel/Generators/Mountain.cs | 29 + .../libTerrainBSD/Channel/Generators/Noise.cs | 54 + .../Channel/Generators/Spiral.cs | 157 + .../Channel/Generators/Voronoi.cs | 212 + .../libTerrainBSD/Channel/Generators/Worms.cs | 72 + .../libTerrainBSD/Channel/Grid.cs | 377 + .../Channel/Manipulators/AerobicErosion.cs | 212 + .../Channel/Manipulators/HydraulicErosion.cs | 145 + .../Channel/Manipulators/NavierStokes.cs | 307 + .../Channel/Manipulators/ThermalWeathering.cs | 108 + .../libTerrainBSD/Channel/Neighbours.cs | 137 + .../libTerrainBSD/Channel/Operators.cs | 240 + .../libTerrainBSD/Tools/Point2D.cs | 42 + .../libTerrainBSD/Tools/Tools.cs | 60 + .../Common/ANumericalToleranceConstraint.cs | 57 + .../Tests/Common/DoubleToleranceConstraint.cs | 80 + trunk/OpenSim/Tests/Common/TestHelper.cs | 53 + .../Tests/Common/VectorToleranceConstraint.cs | 86 + .../Inventory/Properties/AssemblyInfo.cs | 63 + .../OpenSim/Tests/Inventory/TestInventory.cs | 1008 +++ .../Tests/OpenSim/Framework/UtilTest.cs | 143 + .../UserServer/Stress/UserServerStressTest.cs | 45 + trunk/OpenSim/Tools/Export/OpenSimExport.cs | 110 + .../Tools/LaunchSLClient/Form1.Designer.cs | 108 + trunk/OpenSim/Tools/LaunchSLClient/Form1.cs | 211 + trunk/OpenSim/Tools/LaunchSLClient/Form1.resx | 120 + .../Tools/LaunchSLClient/LauncherException.cs | 53 + trunk/OpenSim/Tools/LaunchSLClient/Program.cs | 56 + .../LaunchSLClient/Properties/AssemblyInfo.cs | 61 + .../Properties/Resources.Designer.cs | 71 + .../LaunchSLClient/Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 30 + .../Properties/Settings.settings | 7 + .../OpenSim.32BitLaunch.csproj | 63 + .../Tools/OpenSim.32BitLaunch/Program.cs | 60 + .../Properties/AssemblyInfo.cs | 64 + .../Tools/OpenSim.GUI/InputTextBoxControl.cs | 116 + .../Tools/OpenSim.GUI/Main.Designer.cs | 1436 ++++ trunk/OpenSim/Tools/OpenSim.GUI/Main.cs | 537 ++ trunk/OpenSim/Tools/OpenSim.GUI/Main.resx | 135 + .../Tools/OpenSim.GUI/OpenSim.GUI.csproj | 94 + .../Tools/OpenSim.GUI/ProcessManager.cs | 99 + trunk/OpenSim/Tools/OpenSim.GUI/Program.cs | 48 + .../OpenSim.GUI/Properties/AssemblyInfo.cs | 61 + .../Properties/Resources.Designer.cs | 71 + .../OpenSim.GUI/Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 30 + .../OpenSim.GUI/Properties/Settings.settings | 7 + .../OpenSim.GUI/frmConfiguration.Designer.cs | 89 + .../Tools/OpenSim.GUI/frmConfiguration.cs | 46 + .../Tools/OpenSim.GUI/frmConfiguration.resx | 129 + .../Tools/Windows/Installer/OpenSim.nsi | 151 + trunk/OpenSim/Tools/classaudit.pl | 133 + trunk/OpenSim/Tools/pCampBot/BotManager.cs | 235 + trunk/OpenSim/Tools/pCampBot/PhysicsBot.cs | 201 + trunk/OpenSim/Tools/pCampBot/README.txt | 44 + trunk/OpenSim/Tools/pCampBot/pCampBot.cs | 76 + trunk/Prebuild/README | 230 + trunk/Prebuild/TODO | 21 + trunk/Prebuild/doc/prebuild-example1.xml | 300 + trunk/Prebuild/doc/prebuild-example2.xml | 72 + trunk/Prebuild/doc/prebuild-example3.xml | 113 + trunk/Prebuild/doc/prebuild-example4.xml | 715 ++ trunk/Prebuild/doc/prebuild-example5.xml | 187 + trunk/Prebuild/prebuild | 2 + trunk/Prebuild/scripts/Clean.bat | 2 + trunk/Prebuild/scripts/Help.bat | 2 + trunk/Prebuild/scripts/MonoDevelop.sh | 2 + trunk/Prebuild/scripts/Prebuild.nsi | 231 + trunk/Prebuild/scripts/SharpDevelop.bat | 4 + trunk/Prebuild/scripts/SharpDevelop2.bat | 4 + trunk/Prebuild/scripts/VS2002.bat | 4 + trunk/Prebuild/scripts/VS2003.bat | 4 + trunk/Prebuild/scripts/VS2005.bat | 4 + trunk/Prebuild/scripts/autotools.bat | 4 + trunk/Prebuild/scripts/autotools.sh | 2 + trunk/Prebuild/scripts/nant.bat | 4 + trunk/Prebuild/scripts/nant.sh | 2 + trunk/Prebuild/src/App.ico | Bin 0 -> 4286 bytes .../src/Core/Attributes/DataNodeAttribute.cs | 81 + .../Core/Attributes/OptionNodeAttribute.cs | 80 + .../src/Core/Attributes/TargetAttribute.cs | 80 + trunk/Prebuild/src/Core/FatalException.cs | 94 + .../Prebuild/src/Core/Interfaces/IDataNode.cs | 56 + trunk/Prebuild/src/Core/Interfaces/ITarget.cs | 60 + trunk/Prebuild/src/Core/Kernel.cs | 758 ++ .../src/Core/Nodes/ConfigurationNode.cs | 187 + trunk/Prebuild/src/Core/Nodes/DataNode.cs | 82 + trunk/Prebuild/src/Core/Nodes/ExcludeNode.cs | 85 + trunk/Prebuild/src/Core/Nodes/FileNode.cs | 238 + trunk/Prebuild/src/Core/Nodes/FilesNode.cs | 223 + trunk/Prebuild/src/Core/Nodes/MatchNode.cs | 299 + trunk/Prebuild/src/Core/Nodes/OptionsNode.cs | 655 ++ trunk/Prebuild/src/Core/Nodes/ProcessNode.cs | 119 + trunk/Prebuild/src/Core/Nodes/ProjectNode.cs | 510 ++ .../Prebuild/src/Core/Nodes/ReferenceNode.cs | 153 + .../src/Core/Nodes/ReferencePathNode.cs | 108 + trunk/Prebuild/src/Core/Nodes/SolutionNode.cs | 302 + trunk/Prebuild/src/Core/Parse/IfContext.cs | 163 + trunk/Prebuild/src/Core/Parse/Preprocessor.cs | 519 ++ .../src/Core/Targets/AutotoolsTarget.cs | 926 +++ .../Prebuild/src/Core/Targets/DebugTarget.cs | 102 + .../src/Core/Targets/MonoDevelopTarget.cs | 458 ++ trunk/Prebuild/src/Core/Targets/NAntTarget.cs | 678 ++ .../src/Core/Targets/SharpDevelop2Target.cs | 71 + .../src/Core/Targets/SharpDevelopTarget.cs | 437 + .../Prebuild/src/Core/Targets/VS2002Target.cs | 96 + .../Prebuild/src/Core/Targets/VS2003Target.cs | 633 ++ .../Prebuild/src/Core/Targets/VS2005Target.cs | 882 ++ .../Prebuild/src/Core/Targets/VS2008Target.cs | 56 + .../src/Core/UnknownLanguageException.cs | 63 + .../Core/Utilities/CommandLineCollection.cs | 162 + .../src/Core/Utilities/CurrentDirectory.cs | 89 + trunk/Prebuild/src/Core/Utilities/Helper.cs | 661 ++ trunk/Prebuild/src/Core/Utilities/Log.cs | 279 + trunk/Prebuild/src/Core/WarningException.cs | 93 + trunk/Prebuild/src/Prebuild.cs | 165 + trunk/Prebuild/src/Prebuild.snk | Bin 0 -> 596 bytes trunk/Prebuild/src/Properties/AssemblyInfo.cs | 101 + trunk/Prebuild/src/data/dnpb-1.0.xsd | 183 + trunk/Prebuild/src/data/dnpb-1.1.xsd | 184 + trunk/Prebuild/src/data/dnpb-1.2.xsd | 198 + trunk/Prebuild/src/data/dnpb-1.3.xsd | 206 + trunk/Prebuild/src/data/dnpb-1.4.xsd | 212 + trunk/Prebuild/src/data/dnpb-1.5.xsd | 215 + trunk/Prebuild/src/data/prebuild-1.6.xsd | 231 + trunk/Prebuild/src/data/prebuild-1.7.xsd | 261 + trunk/README.txt | 69 + trunk/TESTING.txt | 24 + .../BaseDataReader.cs | 127 + .../BaseDatabaseConnector.cs | 142 + .../BaseFieldMapper.cs | 163 + .../BaseRowMapper.cs | 60 + .../TribalMedia.Framework.Data/BaseSchema.cs | 68 + .../BaseTableMapper.cs | 280 + .../Properties/AssemblyInfo.cs | 66 + .../TribalMedia.Framework.Data.snk | Bin 0 -> 596 bytes trunk/ThirdPartyLicenses/Axiom.txt | 141 + .../Bullet for Xna (ModifiedBulletX).txt | 19 + trunk/ThirdPartyLicenses/BulletLicense.txt | 17 + .../Mono.Xna (MonoXnaCompactMaths).txt | 22 + trunk/ThirdPartyLicenses/MySQL.txt | 78 + trunk/ThirdPartyLicenses/Nini.txt | 23 + trunk/ThirdPartyLicenses/ODE.txt | 13 + trunk/ThirdPartyLicenses/OpenJpeg.txt | 30 + trunk/ThirdPartyLicenses/XML-RPC.NET.txt | 27 + trunk/ThirdPartyLicenses/libsl.txt | 23 + trunk/add-copyright.sh | 73 + trunk/bin/Axiom.MathLib.dll | Bin 0 -> 69632 bytes trunk/bin/CookComputing.XmlRpcV2.dll | Bin 0 -> 110592 bytes trunk/bin/Db4objects.Db4o.dll | Bin 0 -> 593408 bytes trunk/bin/DotSets.dll | Bin 0 -> 24576 bytes trunk/bin/Kds.Serialization.dll | Bin 0 -> 40960 bytes trunk/bin/Modified.XnaDevRu.BulletX.dll | Bin 0 -> 208896 bytes trunk/bin/Mono.Addins.dll | Bin 0 -> 163840 bytes trunk/bin/Mono.Addins.dll.config | 6 + trunk/bin/Mono.Data.SqliteClient.dll | Bin 0 -> 52224 bytes trunk/bin/Mono.PEToolkit.dll | Bin 0 -> 131072 bytes trunk/bin/MonoXnaCompactMaths.dll | Bin 0 -> 36864 bytes trunk/bin/MySql.Data.dll | Bin 0 -> 266240 bytes trunk/bin/Nini.dll | Bin 0 -> 69632 bytes trunk/bin/Ode.NET.dll | Bin 0 -> 61440 bytes trunk/bin/OpenSim.32BitLaunch.exe | Bin 0 -> 5632 bytes trunk/bin/OpenSim.32BitLaunch.exe.config | 28 + trunk/bin/OpenSim.32BitLaunch.pdb | Bin 0 -> 11776 bytes trunk/bin/OpenSim.Grid.AssetServer.exe.config | 28 + trunk/bin/OpenSim.Grid.GridServer.exe.config | 28 + .../OpenSim.Grid.InventoryServer.exe.config | 28 + .../OpenSim.Grid.MessagingServer.exe.config | 28 + .../bin/OpenSim.Grid.ScriptServer.exe.config | 28 + trunk/bin/OpenSim.Grid.UserServer.exe.config | 28 + trunk/bin/OpenSim.exe.config | 28 + trunk/bin/OpenSim.ini.example | 265 + trunk/bin/OpenSimExport.exe.config | 28 + trunk/bin/PhysX-wrapper.dll | Bin 0 -> 57344 bytes trunk/bin/PhysX_Wrapper_Dotnet.dll | Bin 0 -> 8704 bytes trunk/bin/Prebuild.exe | Bin 0 -> 160768 bytes trunk/bin/RAIL.dll | Bin 0 -> 200704 bytes trunk/bin/ScriptEngines/Default.lsl | 104 + trunk/bin/SimpleApp.exe.config | 28 + trunk/bin/System.Data.SQLite.dll | Bin 0 -> 568832 bytes trunk/bin/TerrainFilters/demofilter.cs | 50 + trunk/bin/XMLRPC.dll | Bin 0 -> 40960 bytes .../AnimationsAssetSet/AnimationsAssetSet.xml | 3 + trunk/bin/assets/AssetSets.xml | 84 + trunk/bin/assets/Avatar/Newruth/Settings.txt | 120 + trunk/bin/assets/Avatar/Newruth/eyes.j2c | Bin 0 -> 28088 bytes .../bin/assets/Avatar/Newruth/female body.j2c | Bin 0 -> 49557 bytes .../assets/Avatar/Newruth/female bottom.j2c | Bin 0 -> 36212 bytes .../bin/assets/Avatar/Newruth/female face.j2c | Bin 0 -> 44749 bytes .../Avatar/Newruth/open sim hair base.j2c | Bin 0 -> 74339 bytes .../BodyPartsAssetSet/BodyPartsAssetSet.xml | 59 + .../assets/BodyPartsAssetSet/base_shape.dat | 105 + .../assets/BodyPartsAssetSet/base_skin.dat | 52 + .../assets/BodyPartsAssetSet/goblin_skin.dat | 49 + .../assets/BodyPartsAssetSet/jim_shape.dat | 105 + .../bin/assets/BodyPartsAssetSet/jim_skin.dat | 50 + .../BodyPartsAssetSet/little_goblin_shape.dat | 105 + .../bin/assets/BodyPartsAssetSet/newhair.dat | 63 + .../ClothingAssetSet/ClothingAssetSet.xml | 16 + .../bin/assets/ClothingAssetSet/newpants.dat | 33 + .../bin/assets/ClothingAssetSet/newshirt.dat | 34 + .../GesturesAssetSet/GesturesAssetSet.xml | 3 + .../LandmarksAssetSet/LandmarksAssetSet.xml | 3 + .../NotecardsAssetSet/NotecardsAssetSet.xml | 16 + .../assets/NotecardsAssetSet/exampleNote.txt | 1 + .../assets/NotecardsAssetSet/welcomeNote.txt | 4 + .../ObjectsAssetSet/ObjectsAssetSet.xml | 3 + trunk/bin/assets/OpenSimAssetSet/4-tile2.jp2 | Bin 0 -> 24410 bytes trunk/bin/assets/OpenSimAssetSet/4-tile3.jp2 | Bin 0 -> 98273 bytes .../OpenSimAssetSet/OpenSimAssetSet.xml | 62 + .../bin/assets/OpenSimAssetSet/base_shape.dat | 105 + .../bin/assets/OpenSimAssetSet/base_skin.dat | 52 + .../bin/assets/OpenSimAssetSet/brick1_256.jp2 | Bin 0 -> 24468 bytes .../bin/assets/OpenSimAssetSet/brick2_256.jp2 | Bin 0 -> 24455 bytes .../bin/assets/OpenSimAssetSet/brick_mono.jp2 | Bin 0 -> 23102 bytes trunk/bin/assets/OpenSimAssetSet/bricks.jp2 | 1 + trunk/bin/assets/OpenSimAssetSet/cedar.jp2 | Bin 0 -> 76710 bytes .../assets/OpenSimAssetSet/cement_block.jp2 | Bin 0 -> 24538 bytes trunk/bin/assets/OpenSimAssetSet/clear.jp2 | Bin 0 -> 330 bytes trunk/bin/assets/OpenSimAssetSet/cloud.jp2 | Bin 0 -> 23852 bytes trunk/bin/assets/OpenSimAssetSet/cobbles.jp2 | Bin 0 -> 98294 bytes trunk/bin/assets/OpenSimAssetSet/coffee.jp2 | Bin 0 -> 32756 bytes .../bin/assets/OpenSimAssetSet/creambrick.jp2 | Bin 0 -> 98132 bytes .../bin/assets/OpenSimAssetSet/femalebody.jp2 | Bin 0 -> 56124 bytes .../assets/OpenSimAssetSet/femalebottom.jp2 | Bin 0 -> 54574 bytes .../bin/assets/OpenSimAssetSet/femaleface.jp2 | Bin 0 -> 76425 bytes trunk/bin/assets/OpenSimAssetSet/fgrass.jp2 | Bin 0 -> 32597 bytes .../bin/assets/OpenSimAssetSet/glasstile2.jp2 | Bin 0 -> 393170 bytes .../assets/OpenSimAssetSet/goblin_skin.dat | 49 + trunk/bin/assets/OpenSimAssetSet/granite.jp2 | 1 + .../assets/OpenSimAssetSet/graniteblock.jp2 | Bin 0 -> 98271 bytes trunk/bin/assets/OpenSimAssetSet/grass.jp2 | Bin 0 -> 393153 bytes trunk/bin/assets/OpenSimAssetSet/grass2.jp2 | Bin 0 -> 98241 bytes trunk/bin/assets/OpenSimAssetSet/gravel.jp2 | Bin 0 -> 392995 bytes .../bin/assets/OpenSimAssetSet/greybrick.jp2 | Bin 0 -> 393124 bytes trunk/bin/assets/OpenSimAssetSet/hardwood.jp2 | Bin 0 -> 98231 bytes trunk/bin/assets/OpenSimAssetSet/ivy.jp2 | Bin 0 -> 393100 bytes .../bin/assets/OpenSimAssetSet/jim_shape.dat | 105 + trunk/bin/assets/OpenSimAssetSet/jim_skin.dat | 50 + trunk/bin/assets/OpenSimAssetSet/licenses.txt | 37 + .../OpenSimAssetSet/little_goblin_shape.dat | 105 + trunk/bin/assets/OpenSimAssetSet/mahogany.jp2 | Bin 0 -> 98250 bytes trunk/bin/assets/OpenSimAssetSet/map1.jp2 | Bin 0 -> 570 bytes trunk/bin/assets/OpenSimAssetSet/map_base.jp2 | Bin 0 -> 153 bytes trunk/bin/assets/OpenSimAssetSet/maple.jp2 | Bin 0 -> 98125 bytes trunk/bin/assets/OpenSimAssetSet/moon.jp2 | Bin 0 -> 32741 bytes trunk/bin/assets/OpenSimAssetSet/mosaic02.jp2 | Bin 0 -> 98286 bytes trunk/bin/assets/OpenSimAssetSet/newhair.dat | 63 + trunk/bin/assets/OpenSimAssetSet/newpants.dat | 33 + trunk/bin/assets/OpenSimAssetSet/newshirt.dat | 34 + trunk/bin/assets/OpenSimAssetSet/palm1.jp2 | Bin 0 -> 65526 bytes trunk/bin/assets/OpenSimAssetSet/papaya.jp2 | Bin 0 -> 65387 bytes .../assets/OpenSimAssetSet/papaya_bark.jp2 | Bin 0 -> 12254 bytes .../assets/OpenSimAssetSet/pastelbrick.jp2 | Bin 0 -> 196352 bytes trunk/bin/assets/OpenSimAssetSet/peaches.jp2 | Bin 0 -> 98845 bytes .../bin/assets/OpenSimAssetSet/pine1_10m.jp2 | Bin 0 -> 65485 bytes trunk/bin/assets/OpenSimAssetSet/plywood.jp2 | Bin 0 -> 79234 bytes trunk/bin/assets/OpenSimAssetSet/poplar.jp2 | Bin 0 -> 16375 bytes .../assets/OpenSimAssetSet/redtri_tile.jp2 | Bin 0 -> 98187 bytes .../assets/OpenSimAssetSet/rockbuilding.jp2 | Bin 0 -> 24251 bytes trunk/bin/assets/OpenSimAssetSet/rocks.jp2 | 1 + .../assets/OpenSimAssetSet/rockwallbig.jp2 | Bin 0 -> 98223 bytes trunk/bin/assets/OpenSimAssetSet/roof01.jp2 | Bin 0 -> 24310 bytes .../bin/assets/OpenSimAssetSet/rooftiles1.jp2 | Bin 0 -> 6121 bytes .../OpenSimAssetSet/rooftiles2_peach.jp2 | Bin 0 -> 24548 bytes .../assets/OpenSimAssetSet/rooftiles2_roy.jp2 | Bin 0 -> 24444 bytes .../bin/assets/OpenSimAssetSet/saguaro_8m.jp2 | Bin 0 -> 63056 bytes trunk/bin/assets/OpenSimAssetSet/seawater.jp2 | Bin 0 -> 98285 bytes trunk/bin/assets/OpenSimAssetSet/shingle.jp2 | Bin 0 -> 24560 bytes trunk/bin/assets/OpenSimAssetSet/snow1.jp2 | Bin 0 -> 97993 bytes trunk/bin/assets/OpenSimAssetSet/steel.jp2 | Bin 0 -> 98186 bytes .../bin/assets/OpenSimAssetSet/stone1wall.jp2 | Bin 0 -> 98251 bytes .../bin/assets/OpenSimAssetSet/stonetile.jp2 | Bin 0 -> 393159 bytes trunk/bin/assets/OpenSimAssetSet/street2.jp2 | Bin 0 -> 196334 bytes trunk/bin/assets/OpenSimAssetSet/testpic2.jp2 | Bin 0 -> 291 bytes trunk/bin/assets/OpenSimAssetSet/thatch.jp2 | Bin 0 -> 98178 bytes trunk/bin/assets/OpenSimAssetSet/water1.jp2 | Bin 0 -> 98298 bytes trunk/bin/assets/OpenSimAssetSet/water3.jp2 | Bin 0 -> 98190 bytes .../assets/OpenSimAssetSet/welcomeNote.dat | 9 + trunk/bin/assets/OpenSimAssetSet/wood1.jp2 | Bin 0 -> 24522 bytes .../assets/PhotosAssetSet/PhotosAssetSet.xml | 3 + trunk/bin/assets/README.txt | 12 + .../ScriptsAssetSet/ScriptsAssetSet.xml | 135 + trunk/bin/assets/ScriptsAssetSet/llAbs.lsl | 7 + trunk/bin/assets/ScriptsAssetSet/llAcos.lsl | 8 + .../ScriptsAssetSet/llAddToLandBanList.lsl | 84 + .../ScriptsAssetSet/llAddToLandPassList.lsl | 84 + .../ScriptsAssetSet/llAdjustSoundVolume.lsl | 13 + .../ScriptsAssetSet/llAllowInventoryDrop.lsl | 17 + .../assets/ScriptsAssetSet/llAngleBetween.lsl | 11 + .../assets/ScriptsAssetSet/llApplyImpulse.lsl | 16 + trunk/bin/assets/ScriptsAssetSet/llAsin.lsl | 9 + trunk/bin/assets/ScriptsAssetSet/llAtan2.lsl | 11 + .../ScriptsAssetSet/llAvatarOnSitTarget.lsl | 20 + .../ScriptsAssetSet/llBase64ToString.lsl | 8 + .../llRemoveFromLandBanList.lsl | 84 + .../llRemoveFromLandPassList.lsl | 84 + .../ScriptsAssetSet/llResetLandBanList.lsl | 84 + .../ScriptsAssetSet/llResetLandPassList.lsl | 84 + trunk/bin/assets/ScriptsAssetSet/llSay.lsl | 7 + .../ScriptsAssetSet/llSetParcelMusicURL.lsl | 7 + trunk/bin/assets/ScriptsAssetSet/llSetRot.lsl | 13 + .../assets/SoundsAssetSet/SoundsAssetSet.xml | 3 + trunk/bin/assets/TexturesAssetSet/4-tile2.jp2 | Bin 0 -> 24410 bytes trunk/bin/assets/TexturesAssetSet/4-tile3.jp2 | Bin 0 -> 98273 bytes .../TexturesAssetSet/TexturesAssetSet.xml | 416 + .../assets/TexturesAssetSet/brick1_256.jp2 | Bin 0 -> 24468 bytes .../assets/TexturesAssetSet/brick2_256.jp2 | Bin 0 -> 24455 bytes .../assets/TexturesAssetSet/brick_mono.jp2 | Bin 0 -> 23102 bytes trunk/bin/assets/TexturesAssetSet/bricks.jp2 | 1 + trunk/bin/assets/TexturesAssetSet/cedar.jp2 | Bin 0 -> 76710 bytes .../assets/TexturesAssetSet/cement_block.jp2 | Bin 0 -> 24538 bytes trunk/bin/assets/TexturesAssetSet/clear.jp2 | Bin 0 -> 330 bytes trunk/bin/assets/TexturesAssetSet/cloud.jp2 | Bin 0 -> 23852 bytes trunk/bin/assets/TexturesAssetSet/cobbles.jp2 | Bin 0 -> 98294 bytes trunk/bin/assets/TexturesAssetSet/coffee.jp2 | Bin 0 -> 32756 bytes .../assets/TexturesAssetSet/creambrick.jp2 | Bin 0 -> 98132 bytes trunk/bin/assets/TexturesAssetSet/fe_face.jp2 | Bin 0 -> 33716 bytes .../bin/assets/TexturesAssetSet/fe_lower.jp2 | Bin 0 -> 11949 bytes .../bin/assets/TexturesAssetSet/fe_upper.jp2 | Bin 0 -> 12445 bytes .../assets/TexturesAssetSet/femalebody.jp2 | Bin 0 -> 56124 bytes .../assets/TexturesAssetSet/femalebottom.jp2 | Bin 0 -> 54574 bytes .../assets/TexturesAssetSet/femaleface.jp2 | Bin 0 -> 76425 bytes trunk/bin/assets/TexturesAssetSet/fgrass.jp2 | Bin 0 -> 32597 bytes .../assets/TexturesAssetSet/glasstile2.jp2 | Bin 0 -> 393170 bytes trunk/bin/assets/TexturesAssetSet/granite.jp2 | 1 + .../assets/TexturesAssetSet/graniteblock.jp2 | Bin 0 -> 98271 bytes trunk/bin/assets/TexturesAssetSet/grass.jp2 | Bin 0 -> 393153 bytes trunk/bin/assets/TexturesAssetSet/grass2.jp2 | Bin 0 -> 98241 bytes trunk/bin/assets/TexturesAssetSet/gravel.jp2 | Bin 0 -> 392995 bytes .../bin/assets/TexturesAssetSet/greybrick.jp2 | Bin 0 -> 393124 bytes .../bin/assets/TexturesAssetSet/hardwood.jp2 | Bin 0 -> 98231 bytes trunk/bin/assets/TexturesAssetSet/ivy.jp2 | Bin 0 -> 393100 bytes trunk/bin/assets/TexturesAssetSet/le_face.jp2 | Bin 0 -> 45289 bytes .../bin/assets/TexturesAssetSet/le_lower.jp2 | Bin 0 -> 19628 bytes .../bin/assets/TexturesAssetSet/le_upper.jp2 | Bin 0 -> 18383 bytes .../bin/assets/TexturesAssetSet/licenses.txt | 37 + .../bin/assets/TexturesAssetSet/mahogany.jp2 | Bin 0 -> 98250 bytes trunk/bin/assets/TexturesAssetSet/map1.jp2 | Bin 0 -> 570 bytes .../bin/assets/TexturesAssetSet/map_base.jp2 | Bin 0 -> 153 bytes trunk/bin/assets/TexturesAssetSet/maple.jp2 | Bin 0 -> 98125 bytes trunk/bin/assets/TexturesAssetSet/moon.jp2 | Bin 0 -> 32741 bytes .../bin/assets/TexturesAssetSet/mosaic02.jp2 | Bin 0 -> 98286 bytes trunk/bin/assets/TexturesAssetSet/palm1.jp2 | Bin 0 -> 65526 bytes trunk/bin/assets/TexturesAssetSet/papaya.jp2 | Bin 0 -> 65387 bytes .../assets/TexturesAssetSet/papaya_bark.jp2 | Bin 0 -> 12254 bytes .../assets/TexturesAssetSet/pastelbrick.jp2 | Bin 0 -> 196352 bytes trunk/bin/assets/TexturesAssetSet/peaches.jp2 | Bin 0 -> 98845 bytes .../bin/assets/TexturesAssetSet/pine1_10m.jp2 | Bin 0 -> 65485 bytes trunk/bin/assets/TexturesAssetSet/plywood.jp2 | Bin 0 -> 79234 bytes trunk/bin/assets/TexturesAssetSet/poplar.jp2 | Bin 0 -> 16375 bytes trunk/bin/assets/TexturesAssetSet/re_face.jp2 | Bin 0 -> 43771 bytes .../bin/assets/TexturesAssetSet/re_lower.jp2 | Bin 0 -> 19314 bytes .../bin/assets/TexturesAssetSet/re_upper.jp2 | Bin 0 -> 22172 bytes .../assets/TexturesAssetSet/redtri_tile.jp2 | Bin 0 -> 98187 bytes .../assets/TexturesAssetSet/rockbuilding.jp2 | Bin 0 -> 24251 bytes trunk/bin/assets/TexturesAssetSet/rocks.jp2 | 1 + .../assets/TexturesAssetSet/rockwallbig.jp2 | Bin 0 -> 98223 bytes trunk/bin/assets/TexturesAssetSet/roof01.jp2 | Bin 0 -> 24310 bytes .../assets/TexturesAssetSet/rooftiles1.jp2 | Bin 0 -> 6121 bytes .../TexturesAssetSet/rooftiles2_peach.jp2 | Bin 0 -> 24548 bytes .../TexturesAssetSet/rooftiles2_roy.jp2 | Bin 0 -> 24444 bytes .../assets/TexturesAssetSet/saguaro_8m.jp2 | Bin 0 -> 63056 bytes trunk/bin/assets/TexturesAssetSet/se_face.jp2 | Bin 0 -> 40013 bytes .../bin/assets/TexturesAssetSet/se_lower.jp2 | Bin 0 -> 15661 bytes .../bin/assets/TexturesAssetSet/se_upper.jp2 | Bin 0 -> 15881 bytes .../bin/assets/TexturesAssetSet/seawater.jp2 | Bin 0 -> 98285 bytes trunk/bin/assets/TexturesAssetSet/shingle.jp2 | Bin 0 -> 24560 bytes .../assets/TexturesAssetSet/skins_license.txt | 5 + trunk/bin/assets/TexturesAssetSet/snow1.jp2 | Bin 0 -> 97993 bytes trunk/bin/assets/TexturesAssetSet/steel.jp2 | Bin 0 -> 98186 bytes .../assets/TexturesAssetSet/stone1wall.jp2 | Bin 0 -> 98251 bytes .../bin/assets/TexturesAssetSet/stonetile.jp2 | Bin 0 -> 393159 bytes trunk/bin/assets/TexturesAssetSet/street2.jp2 | Bin 0 -> 196334 bytes .../bin/assets/TexturesAssetSet/testpic2.jp2 | Bin 0 -> 291 bytes trunk/bin/assets/TexturesAssetSet/thatch.jp2 | Bin 0 -> 98178 bytes trunk/bin/assets/TexturesAssetSet/water1.jp2 | Bin 0 -> 98298 bytes trunk/bin/assets/TexturesAssetSet/water3.jp2 | Bin 0 -> 98190 bytes trunk/bin/assets/TexturesAssetSet/wood1.jp2 | Bin 0 -> 24522 bytes trunk/bin/avatar-texture.dat | Bin 0 -> 203 bytes trunk/bin/data/LICENSE-README-IMPORTANT.txt | 5 + trunk/bin/data/avataranimations.xml | 121 + trunk/bin/defaultstripe.png | Bin 0 -> 887 bytes trunk/bin/excuses | 460 ++ trunk/bin/http_404.html.example | 1 + trunk/bin/http_500.html.example | 1 + trunk/bin/http_loginform.html.example | 61 + .../AnimationsLibraryFolders.xml | 17 + .../AnimationsLibraryItems.xml | 19 + .../BodyPartsLibraryFolders.xml | 17 + .../BodyPartsLibraryItems.xml | 120 + .../ClothingLibraryFolders.xml | 17 + .../ClothingLibrary/ClothingLibraryItems.xml | 46 + .../GesturesLibraryFolders.xml | 17 + .../GesturesLibrary/GesturesLibraryItems.xml | 19 + .../LandmarksLibraryFolders.xml | 17 + .../LandmarksLibraryItems.xml | 19 + trunk/bin/inventory/Libraries.xml | 86 + .../NotecardsLibraryFolders.xml | 17 + .../NotecardsLibraryItems.xml | 45 + .../ObjectsLibrary/ObjectsLibraryFolders.xml | 17 + .../ObjectsLibrary/ObjectsLibraryItems.xml | 19 + .../OpenSimLibrary/OpenSimLibrary.xml | 20 + .../OpenSimLibrary/OpenSimLibraryFolders.xml | 14 + .../PhotosLibrary/PhotosLibraryFolders.xml | 17 + .../PhotosLibrary/PhotosLibraryItems.xml | 19 + trunk/bin/inventory/README.txt | 21 + .../ScriptsLibrary/ScriptsLibraryFolders.xml | 158 + .../ScriptsLibrary/ScriptsLibraryItems.xml | 289 + .../SoundsLibrary/SoundsLibraryFolders.xml | 17 + .../SoundsLibrary/SoundsLibraryItems.xml | 19 + .../TexturesLibraryFolders.xml | 17 + .../TexturesLibrary/TexturesLibraryItems.xml | 656 ++ .../bin/inventory/attic/Inventory_Default.xml | 62 + .../bin/inventory/attic/Inventory_Library.xml | 134 + trunk/bin/libdb_dotNET43.dll | Bin 0 -> 221184 bytes trunk/bin/libode.dylib | Bin 0 -> 5236736 bytes trunk/bin/libode.so | Bin 0 -> 2992241 bytes trunk/bin/libopenjpeg-1.0.0-x86_64.so | Bin 0 -> 117184 bytes trunk/bin/libopenjpeg-1.0.0.so | Bin 0 -> 111569 bytes trunk/bin/libopenjpeg-1.1.0.dylib | Bin 0 -> 238244 bytes trunk/bin/libopenjpeg-libsl-2.1.2.0.dylib | Bin 0 -> 131664 bytes trunk/bin/libopenjpeg-libsl-2.1.2.0.so | Bin 0 -> 124388 bytes trunk/bin/libsecondlife.dll | Bin 0 -> 1560576 bytes trunk/bin/libsecondlife.dll.config | 5 + trunk/bin/log4net.dll | Bin 0 -> 270336 bytes trunk/bin/mssql_connection.ini.example | 18 + trunk/bin/mysql_connection.ini.example | 18 + trunk/bin/nunit.framework.dll | Bin 0 -> 77824 bytes trunk/bin/ode.dll | Bin 0 -> 630784 bytes trunk/bin/openjpeg-libsl.dll | Bin 0 -> 765952 bytes trunk/bin/opensim-ode.sh | 5 + trunk/bin/pCampBot.exe.config | 28 + trunk/bin/pCampBotSentences.txt | 0 trunk/bin/shutdown_commands.txt | 1 + trunk/bin/sqlite-3.4.1.so | Bin 0 -> 277804 bytes trunk/bin/sqlite3.dll | Bin 0 -> 364544 bytes trunk/bin/startup_commands.txt.example | 4 + trunk/prebuild.xml | 1595 ++++ trunk/runprebuild.bat | 2 + trunk/runprebuild.sh | 6 + trunk/runprebuild2008.bat | 2 + .../HOWTO_REMOTE_REGION_LOADING.txt | 9 + trunk/share/RegionLoading/example_web.xml | 8 + trunk/share/php/generateUserFunction.php | 46 + trunk/share/ruby/README | 14 + trunk/share/ruby/aserv.rb | 35 + trunk/share/ruby/config.rb | 38 + trunk/share/ruby/gridserv.rb | 69 + trunk/share/ruby/userserv.rb | 135 + trunk/share/sql/mssql-CreateAssetsTable.sql | 19 + trunk/share/sql/mssql-CreateFoldersTable.sql | 27 + trunk/share/sql/mssql-CreateItemsTable.sql | 39 + trunk/share/sql/mssql-agents.sql | 37 + trunk/share/sql/mssql-logs.sql | 20 + trunk/share/sql/mssql-users.sql | 41 + trunk/share/sql/mysql_README.txt | 12 + trunk/update-svn-properties.py | 160 + 969 files changed, 164295 insertions(+) create mode 100644 trunk/.nant/local.include create mode 100644 trunk/CONTRIBUTORS.txt create mode 100644 trunk/LICENSE.txt create mode 100644 trunk/OpenSim.FxCop create mode 100644 trunk/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs create mode 100644 trunk/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs create mode 100644 trunk/OpenSim/Framework/ACL.cs create mode 100644 trunk/OpenSim/Framework/AgentCircuitData.cs create mode 100644 trunk/OpenSim/Framework/AgentCircuitManager.cs create mode 100644 trunk/OpenSim/Framework/AgentInventory.cs create mode 100644 trunk/OpenSim/Framework/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Framework/AssetBase.cs create mode 100644 trunk/OpenSim/Framework/AssetConfig.cs create mode 100644 trunk/OpenSim/Framework/AssetLandmark.cs create mode 100644 trunk/OpenSim/Framework/AssetLoader/Filesystem/AssetLoaderFileSystem.cs create mode 100644 trunk/OpenSim/Framework/AssetRequest.cs create mode 100644 trunk/OpenSim/Framework/AssetStorage.cs create mode 100644 trunk/OpenSim/Framework/AuthenticateResponse.cs create mode 100644 trunk/OpenSim/Framework/AvatarWearable.cs create mode 100644 trunk/OpenSim/Framework/BlockingQueue.cs create mode 100644 trunk/OpenSim/Framework/ChildAgentDataUpdate.cs create mode 100644 trunk/OpenSim/Framework/ClientManager.cs create mode 100644 trunk/OpenSim/Framework/Communications/CAPSService.cs create mode 100644 trunk/OpenSim/Framework/Communications/Cache/AgentAssetTransactions.cs create mode 100644 trunk/OpenSim/Framework/Communications/Cache/AgentAssetTransactionsManager.cs create mode 100644 trunk/OpenSim/Framework/Communications/Cache/AssetCache.cs create mode 100644 trunk/OpenSim/Framework/Communications/Cache/AssetServer.cs create mode 100644 trunk/OpenSim/Framework/Communications/Cache/AssetServerBase.cs create mode 100644 trunk/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs create mode 100644 trunk/OpenSim/Framework/Communications/Cache/GridAssetClient.cs create mode 100644 trunk/OpenSim/Framework/Communications/Cache/InventoryFolderImpl.cs create mode 100644 trunk/OpenSim/Framework/Communications/Cache/LibraryRootFolder.cs create mode 100644 trunk/OpenSim/Framework/Communications/Cache/SQLAssetServer.cs create mode 100644 trunk/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/Caps.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSD.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDArray.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDAssetUploadComplete.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDAssetUploadRequest.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDAssetUploadResponse.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDCapEvent.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDCapsDetails.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDEmpty.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDHelpers.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDItemUpdate.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDMapLayer.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDMapLayerResponse.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDMapRequest.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDMethod.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDStreamHandler.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDTaskInventoryUploadComplete.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDTaskScriptUpdate.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDTest.cs create mode 100644 trunk/OpenSim/Framework/Communications/Capabilities/LLSDType.cs create mode 100644 trunk/OpenSim/Framework/Communications/CommunicationsManager.cs create mode 100644 trunk/OpenSim/Framework/Communications/IGridServices.cs create mode 100644 trunk/OpenSim/Framework/Communications/IInterRegionCommunications.cs create mode 100644 trunk/OpenSim/Framework/Communications/IInventoryServices.cs create mode 100644 trunk/OpenSim/Framework/Communications/InventoryServiceBase.cs create mode 100644 trunk/OpenSim/Framework/Communications/LoginResponse.cs create mode 100644 trunk/OpenSim/Framework/Communications/LoginService.cs create mode 100644 trunk/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Framework/Communications/RestClient/GenericAsyncResult.cs create mode 100644 trunk/OpenSim/Framework/Communications/RestClient/RestClient.cs create mode 100644 trunk/OpenSim/Framework/Communications/UserManagerBase.cs create mode 100644 trunk/OpenSim/Framework/Configuration/HTTP/HTTPConfiguration.cs create mode 100644 trunk/OpenSim/Framework/Configuration/HTTP/RemoteConfigSettings.cs create mode 100644 trunk/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs create mode 100644 trunk/OpenSim/Framework/ConfigurationMember.cs create mode 100644 trunk/OpenSim/Framework/ConfigurationOption.cs create mode 100644 trunk/OpenSim/Framework/Console/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Framework/Console/ConsoleBase.cs create mode 100644 trunk/OpenSim/Framework/Console/ConsoleCallbacksBase.cs create mode 100644 trunk/OpenSim/Framework/Console/MainConsole.cs create mode 100644 trunk/OpenSim/Framework/Console/OpenSimAppender.cs create mode 100644 trunk/OpenSim/Framework/Constants.cs create mode 100644 trunk/OpenSim/Framework/Culture.cs create mode 100644 trunk/OpenSim/Framework/Data.DB4o/DB4oGridData.cs create mode 100644 trunk/OpenSim/Framework/Data.DB4o/DB4oManager.cs create mode 100644 trunk/OpenSim/Framework/Data.DB4o/DB4oUserData.cs create mode 100644 trunk/OpenSim/Framework/Data.DB4o/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/MSSQLAssetData.cs create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/MSSQLGridData.cs create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/MSSQLInventoryData.cs create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/MSSQLLogData.cs create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/MSSQLManager.cs create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/MSSQLUserData.cs create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateAssetsTable.sql create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateFoldersTable.sql create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateItemsTable.sql create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateUserFriendsTable.sql create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-agents.sql create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-logs.sql create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-regions.sql create mode 100644 trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-users.sql create mode 100644 trunk/OpenSim/Framework/Data.MySQL/MySQLAssetData.cs create mode 100644 trunk/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs create mode 100644 trunk/OpenSim/Framework/Data.MySQL/MySQLDatabaseMapper.cs create mode 100644 trunk/OpenSim/Framework/Data.MySQL/MySQLGridData.cs create mode 100644 trunk/OpenSim/Framework/Data.MySQL/MySQLInventoryData.cs create mode 100644 trunk/OpenSim/Framework/Data.MySQL/MySQLLogData.cs create mode 100644 trunk/OpenSim/Framework/Data.MySQL/MySQLManager.cs create mode 100644 trunk/OpenSim/Framework/Data.MySQL/MySQLUserData.cs create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Resources/AvatarAppearance.sql create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Resources/CreateAgentsTable.sql create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Resources/CreateAssetsTable.sql create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Resources/CreateFoldersTable.sql create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Resources/CreateItemsTable.sql create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Resources/CreateLogsTable.sql create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Resources/CreateRegionsTable.sql create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Resources/CreateUserFriendsTable.sql create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Resources/CreateUsersTable.sql create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Resources/UpgradeFoldersTableToVersion2.sql create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Resources/UpgradeItemsTableToVersion2.sql create mode 100644 trunk/OpenSim/Framework/Data.MySQL/Resources/UpgradeUsersTableToVersion2.sql create mode 100644 trunk/OpenSim/Framework/Data.SQLite/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Framework/Data.SQLite/Resources/001_AssetStore.sql create mode 100644 trunk/OpenSim/Framework/Data.SQLite/Resources/001_InventoryStore.sql create mode 100644 trunk/OpenSim/Framework/Data.SQLite/Resources/001_RegionStore.sql create mode 100644 trunk/OpenSim/Framework/Data.SQLite/Resources/001_UserStore.sql create mode 100644 trunk/OpenSim/Framework/Data.SQLite/SQLiteAssetData.cs create mode 100644 trunk/OpenSim/Framework/Data.SQLite/SQLiteBase.cs create mode 100644 trunk/OpenSim/Framework/Data.SQLite/SQLiteGridData.cs create mode 100644 trunk/OpenSim/Framework/Data.SQLite/SQLiteInventoryStore.cs create mode 100644 trunk/OpenSim/Framework/Data.SQLite/SQLiteManager.cs create mode 100644 trunk/OpenSim/Framework/Data.SQLite/SQLiteRegionData.cs create mode 100644 trunk/OpenSim/Framework/Data.SQLite/SQLiteUserData.cs create mode 100644 trunk/OpenSim/Framework/Data/GridData.cs create mode 100644 trunk/OpenSim/Framework/Data/ILogData.cs create mode 100644 trunk/OpenSim/Framework/Data/IniConfig.cs create mode 100644 trunk/OpenSim/Framework/Data/OpenSimDataReader.cs create mode 100644 trunk/OpenSim/Framework/Data/OpenSimDatabaseConnector.cs create mode 100644 trunk/OpenSim/Framework/Data/OpenSimObjectFieldMapper.cs create mode 100644 trunk/OpenSim/Framework/Data/OpenSimTableMapper.cs create mode 100644 trunk/OpenSim/Framework/Data/PrimitiveBaseShapeTableMapper.cs create mode 100644 trunk/OpenSim/Framework/Data/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Framework/Data/RegionProfileData.cs create mode 100644 trunk/OpenSim/Framework/Data/ReservationData.cs create mode 100644 trunk/OpenSim/Framework/EstateSettings.cs create mode 100644 trunk/OpenSim/Framework/FriendListItem.cs create mode 100644 trunk/OpenSim/Framework/GridConfig.cs create mode 100644 trunk/OpenSim/Framework/GridInstantMessage.cs create mode 100644 trunk/OpenSim/Framework/IAssetLoader.cs create mode 100644 trunk/OpenSim/Framework/IAssetProvider.cs create mode 100644 trunk/OpenSim/Framework/IAssetServer.cs create mode 100644 trunk/OpenSim/Framework/IClientAPI.cs create mode 100644 trunk/OpenSim/Framework/IGenericConfig.cs create mode 100644 trunk/OpenSim/Framework/IPlugin.cs create mode 100644 trunk/OpenSim/Framework/IRegionCommsListener.cs create mode 100644 trunk/OpenSim/Framework/IRegionLoader.cs create mode 100644 trunk/OpenSim/Framework/IScene.cs create mode 100644 trunk/OpenSim/Framework/IUserData.cs create mode 100644 trunk/OpenSim/Framework/IUserService.cs create mode 100644 trunk/OpenSim/Framework/InventoryConfig.cs create mode 100644 trunk/OpenSim/Framework/InventoryItemBase.cs create mode 100644 trunk/OpenSim/Framework/LandData.cs create mode 100644 trunk/OpenSim/Framework/Login.cs create mode 100644 trunk/OpenSim/Framework/MapBlockData.cs create mode 100644 trunk/OpenSim/Framework/MessageServerConfig.cs create mode 100644 trunk/OpenSim/Framework/NeighbourInfo.cs create mode 100644 trunk/OpenSim/Framework/NetworkServersInfo.cs create mode 100644 trunk/OpenSim/Framework/PacketPool.cs create mode 100644 trunk/OpenSim/Framework/PrimitiveBaseShape.cs create mode 100644 trunk/OpenSim/Framework/RegionCommsListener.cs create mode 100644 trunk/OpenSim/Framework/RegionHandle.cs create mode 100644 trunk/OpenSim/Framework/RegionInfo.cs create mode 100644 trunk/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs create mode 100644 trunk/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs create mode 100644 trunk/OpenSim/Framework/Remoting.cs create mode 100644 trunk/OpenSim/Framework/SerializableRegionInfo.cs create mode 100644 trunk/OpenSim/Framework/Servers/BaseHttpServer.cs create mode 100644 trunk/OpenSim/Framework/Servers/BaseOpenSimServer.cs create mode 100644 trunk/OpenSim/Framework/Servers/BaseRequestHandler.cs create mode 100644 trunk/OpenSim/Framework/Servers/BaseStreamHandler.cs create mode 100644 trunk/OpenSim/Framework/Servers/BinaryStreamHandler.cs create mode 100644 trunk/OpenSim/Framework/Servers/CheckSumServer.cs create mode 100644 trunk/OpenSim/Framework/Servers/GenericHTTPMethod.cs create mode 100644 trunk/OpenSim/Framework/Servers/IStreamHandler.cs create mode 100644 trunk/OpenSim/Framework/Servers/LLSDMethod.cs create mode 100644 trunk/OpenSim/Framework/Servers/MessageServerInfo.cs create mode 100644 trunk/OpenSim/Framework/Servers/RestDeserialiseHandler.cs create mode 100644 trunk/OpenSim/Framework/Servers/RestMethod.cs create mode 100644 trunk/OpenSim/Framework/Servers/RestObjectPoster.cs create mode 100644 trunk/OpenSim/Framework/Servers/RestObjectPosterResponse.cs create mode 100644 trunk/OpenSim/Framework/Servers/RestStreamHandler.cs create mode 100644 trunk/OpenSim/Framework/Servers/SynchronousRestObjectPoster.cs create mode 100644 trunk/OpenSim/Framework/Servers/XmlRpcMethod.cs create mode 100644 trunk/OpenSim/Framework/Statistics/AssetStatsReporter.cs create mode 100644 trunk/OpenSim/Framework/Statistics/SimExtraStatsReporter.cs create mode 100644 trunk/OpenSim/Framework/Statistics/StatsManager.cs create mode 100644 trunk/OpenSim/Framework/Statistics/UserStatsReporter.cs create mode 100644 trunk/OpenSim/Framework/TaskInventoryItem.cs create mode 100644 trunk/OpenSim/Framework/UserConfig.cs create mode 100644 trunk/OpenSim/Framework/UserProfileData.cs create mode 100644 trunk/OpenSim/Framework/Util.cs create mode 100644 trunk/OpenSim/Framework/sLLVector3.cs create mode 100644 trunk/OpenSim/Grid/AssetServer/Main.cs create mode 100644 trunk/OpenSim/Grid/AssetServer/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Grid/AssetServer/RestService.cs create mode 100644 trunk/OpenSim/Grid/GridServer.Config/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Grid/GridServer.Config/DbGridConfig.cs create mode 100644 trunk/OpenSim/Grid/GridServer/GridManager.cs create mode 100644 trunk/OpenSim/Grid/GridServer/Main.cs create mode 100644 trunk/OpenSim/Grid/GridServer/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Grid/InventoryServer/GridInventoryService.cs create mode 100644 trunk/OpenSim/Grid/InventoryServer/InventoryManager.cs create mode 100644 trunk/OpenSim/Grid/InventoryServer/Main.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager.mds create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager.userprefs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager.usertasks create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/BlockingQueue.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServer.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServerDialog.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/GridServerConnectionManager.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/Main.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/MainWindow.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/OpenGridServices.Manager.mdp create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/OpenGridServices.Manager.pidb create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/RegionBlock.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/Util.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/OpenGridServices.Manager.ConnectToGridServerDialog.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/OpenGridServices.Manager.MainWindow.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/generated.cs create mode 100644 trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/gui.stetic create mode 100644 trunk/OpenSim/Grid/MessagingServer/Main.cs create mode 100644 trunk/OpenSim/Grid/MessagingServer/MessageService.cs create mode 100644 trunk/OpenSim/Grid/MessagingServer/UserPresenceData.cs create mode 100644 trunk/OpenSim/Grid/MessagingServer/WorkUnitBase.cs create mode 100644 trunk/OpenSim/Grid/MessagingServer/WorkUnitPresenceUpdate.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/Common/Executor.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/Common/IScript.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/Common/LSL_Types.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/Common/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Common.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/Common.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/Engine.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/IL_common_functions.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_BaseClass.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_BaseClass_Builtins.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_BaseClass_OPCODES.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_CLRInterface.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_OPCODE_IL_processor.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSO_Enums.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSO_Parser.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSO_Struct.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/c_sharp_example.txt create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/EventManager.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/EventQueueManager.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/ScriptEngine.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/ScriptManager.cs create mode 100644 trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/TempDotNetMicroThreadingCodeInjector.cs create mode 100644 trunk/OpenSim/Grid/ScriptServer/Application.cs create mode 100644 trunk/OpenSim/Grid/ScriptServer/FakeScene.cs create mode 100644 trunk/OpenSim/Grid/ScriptServer/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Grid/ScriptServer/RemotingObject.cs create mode 100644 trunk/OpenSim/Grid/ScriptServer/RemotingServer.cs create mode 100644 trunk/OpenSim/Grid/ScriptServer/ScriptServer/Region/RegionBase.cs create mode 100644 trunk/OpenSim/Grid/ScriptServer/ScriptServer/Region/RegionConnectionManager.cs create mode 100644 trunk/OpenSim/Grid/ScriptServer/ScriptServer/RegionCommManager.cs create mode 100644 trunk/OpenSim/Grid/ScriptServer/ScriptServer/ScriptEngineLoader.cs create mode 100644 trunk/OpenSim/Grid/ScriptServer/ScriptServer/ScriptEnginesManager.cs create mode 100644 trunk/OpenSim/Grid/ScriptServer/ScriptServerMain.cs create mode 100644 trunk/OpenSim/Grid/UserServer.Config/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Grid/UserServer.Config/DbUserConfig.cs create mode 100644 trunk/OpenSim/Grid/UserServer/Main.cs create mode 100644 trunk/OpenSim/Grid/UserServer/MessageServersConnector.cs create mode 100644 trunk/OpenSim/Grid/UserServer/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Grid/UserServer/UserLoginService.cs create mode 100644 trunk/OpenSim/Grid/UserServer/UserManager.cs create mode 100644 trunk/OpenSim/Region/Application/Application.cs create mode 100644 trunk/OpenSim/Region/Application/IApplicationPlugin.cs create mode 100644 trunk/OpenSim/Region/Application/OpenSimMain.cs create mode 100644 trunk/OpenSim/Region/Application/VersionInfo.cs create mode 100644 trunk/OpenSim/Region/ClientStack/ClientStackNetworkHandler.cs create mode 100644 trunk/OpenSim/Region/ClientStack/ClientView.cs create mode 100644 trunk/OpenSim/Region/ClientStack/PacketQueue.cs create mode 100644 trunk/OpenSim/Region/ClientStack/PacketServer.cs create mode 100644 trunk/OpenSim/Region/ClientStack/PacketThrottle.cs create mode 100644 trunk/OpenSim/Region/ClientStack/QueItem.cs create mode 100644 trunk/OpenSim/Region/ClientStack/RegionApplicationBase.cs create mode 100644 trunk/OpenSim/Region/ClientStack/UDPServer.cs create mode 100644 trunk/OpenSim/Region/Communications/Local/CommunicationsLocal.cs create mode 100644 trunk/OpenSim/Region/Communications/Local/LocalBackEndServices.cs create mode 100644 trunk/OpenSim/Region/Communications/Local/LocalInventoryService.cs create mode 100644 trunk/OpenSim/Region/Communications/Local/LocalLoginService.cs create mode 100644 trunk/OpenSim/Region/Communications/Local/LocalUserServices.cs create mode 100644 trunk/OpenSim/Region/Communications/Local/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/Communications/OGS1/CommunicationsOGS1.cs create mode 100644 trunk/OpenSim/Region/Communications/OGS1/OGS1GridServices.cs create mode 100644 trunk/OpenSim/Region/Communications/OGS1/OGS1InterSimComms.cs create mode 100644 trunk/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs create mode 100644 trunk/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs create mode 100644 trunk/OpenSim/Region/Communications/OGS1/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/Environment/EstateManager.cs create mode 100644 trunk/OpenSim/Region/Environment/InstantMessageReceiver.cs create mode 100644 trunk/OpenSim/Region/Environment/Interfaces/IAgentAssetTransactions.cs create mode 100644 trunk/OpenSim/Region/Environment/Interfaces/IAvatarFactory.cs create mode 100644 trunk/OpenSim/Region/Environment/Interfaces/IDynamicTextureManager.cs create mode 100644 trunk/OpenSim/Region/Environment/Interfaces/IHttpRequests.cs create mode 100644 trunk/OpenSim/Region/Environment/Interfaces/IRegionDataStore.cs create mode 100644 trunk/OpenSim/Region/Environment/Interfaces/IRegionModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Interfaces/ISimChat.cs create mode 100644 trunk/OpenSim/Region/Environment/Interfaces/ITerrain.cs create mode 100644 trunk/OpenSim/Region/Environment/Interfaces/ITerrainChannel.cs create mode 100644 trunk/OpenSim/Region/Environment/Interfaces/IWorldComm.cs create mode 100644 trunk/OpenSim/Region/Environment/Interfaces/IXMLRPC.cs create mode 100644 trunk/OpenSim/Region/Environment/Interfaces/IXfer.cs create mode 100644 trunk/OpenSim/Region/Environment/LandManagement/Land.cs create mode 100644 trunk/OpenSim/Region/Environment/LandManagement/LandManager.cs create mode 100644 trunk/OpenSim/Region/Environment/ModuleLoader.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/AgentAssetTransactionModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/AgentAssetsTransactions.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/AppearanceTableMapper.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/AssetDownloadModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/AvatarProfilesModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/ChatModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/DynamicTextureModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/EmailModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/FriendsModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/GroupsModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/InstantMessageModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/InventoryModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/LoadImageURLModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/SunModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/TeleportModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/TextureSender.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/TreePopulatorModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/WorldCommModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/XMLRPCModule.cs create mode 100644 trunk/OpenSim/Region/Environment/Modules/XferModule.cs create mode 100644 trunk/OpenSim/Region/Environment/PermissionManager.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/AvatarAnimations.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/AvatarAppearance.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/EntityBase.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/IScenePresenceBody.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/InnerScene.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/Scene.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/SceneBase.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/SceneEvents.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/SceneManager.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/SceneObjectPart.Inventory.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/ScenePresence.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/SceneXmlLoader.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/Scripting/IScriptHost.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/Scripting/NullScriptHost.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineInterface.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineLoader.cs create mode 100644 trunk/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs create mode 100644 trunk/OpenSim/Region/Environment/StorageManager.cs create mode 100644 trunk/OpenSim/Region/Environment/Types/BasicQuadTreeNode.cs create mode 100644 trunk/OpenSim/Region/Environment/Types/UpdateQueue.cs create mode 100644 trunk/OpenSim/Region/Examples/SimpleApp/ComplexObject.cs create mode 100644 trunk/OpenSim/Region/Examples/SimpleApp/CpuCounterObject.cs create mode 100644 trunk/OpenSim/Region/Examples/SimpleApp/FileSystemObject.cs create mode 100644 trunk/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs create mode 100644 trunk/OpenSim/Region/Examples/SimpleApp/MyWorld.cs create mode 100644 trunk/OpenSim/Region/Examples/SimpleApp/Program.cs create mode 100644 trunk/OpenSim/Region/Examples/SimpleApp/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/CSharp/CSharpScriptEngine.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/CSharp/Examples/ExportRegionToLSL.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JScript/JScriptEngine.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/ClassInstance.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/ClassRecord.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Heap.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.Logic.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.Methods.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.Return.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/MainMemory.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/MethodMemory.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Object.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/OpCodes.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Stack.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/StackFrame.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Thread.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JavaEngine.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/OpenSimJVM.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/ArrayReference.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/BaseType.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/ObjectReference.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Byte.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Char.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Float.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Int.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/Script.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/ScriptAPI.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/ScriptInfo.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/ScriptInterpretedAPI.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/ScriptInterpretedEvents.cs create mode 100644 trunk/OpenSim/Region/ExtensionsScriptModule/ScriptManager.cs create mode 100644 trunk/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs create mode 100644 trunk/OpenSim/Region/Physics/BulletXPlugin/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs create mode 100644 trunk/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs create mode 100644 trunk/OpenSim/Region/Physics/Manager/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/Physics/Manager/CollisionLocker.cs create mode 100644 trunk/OpenSim/Region/Physics/Manager/IMesher.cs create mode 100644 trunk/OpenSim/Region/Physics/Manager/PhysicsActor.cs create mode 100644 trunk/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs create mode 100644 trunk/OpenSim/Region/Physics/Manager/PhysicsScene.cs create mode 100644 trunk/OpenSim/Region/Physics/Manager/PhysicsSensor.cs create mode 100644 trunk/OpenSim/Region/Physics/Manager/PhysicsVector.cs create mode 100644 trunk/OpenSim/Region/Physics/Manager/ZeroMesher.cs create mode 100644 trunk/OpenSim/Region/Physics/Meshing/Extruder.cs create mode 100644 trunk/OpenSim/Region/Physics/Meshing/HelperTypes.cs create mode 100644 trunk/OpenSim/Region/Physics/Meshing/Mesh.cs create mode 100644 trunk/OpenSim/Region/Physics/Meshing/Meshmerizer.cs create mode 100644 trunk/OpenSim/Region/Physics/Meshing/SimpleHull.cs create mode 100644 trunk/OpenSim/Region/Physics/Meshing/Simplex.cs create mode 100644 trunk/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs create mode 100644 trunk/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs create mode 100644 trunk/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs create mode 100644 trunk/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs create mode 100644 trunk/OpenSim/Region/Physics/PhysXPlugin/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/Executor.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/ExecutorBase.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/IScript.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/TRPC/MyBase.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPClient.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPCommon.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPServer.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPSocket.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/Common/TRPC_Remote.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/c_sharp_example.txt create mode 100644 trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Common.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Engine.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/IL_common_functions.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_BaseClass_OPCODES.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_CLRInterface.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_OPCODE_IL_processor.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Enums.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Parser.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Struct.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSOScript.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/ScriptEngine.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/LSOEngine/ScriptManager.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/RemoteServer/Common.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/RemoteServer/EventManager.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/RemoteServer/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/RemoteServer/RemoteServer.cs create mode 100644 trunk/OpenSim/Region/ScriptEngine/RemoteServer/ScriptEngine.cs create mode 100644 trunk/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/DB4oDataStore.cs create mode 100644 trunk/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/Storage/OpenSim.DataStore.MSSQL/MSSQLDataStore.cs create mode 100644 trunk/OpenSim/Region/Storage/OpenSim.DataStore.NullStorage/NullDataStore.cs create mode 100644 trunk/OpenSim/Region/Storage/OpenSim.DataStore.NullStorage/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/TerrainFilter.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Bitmap/Bitmap.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Channel.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Common.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Editing/Flatten.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Editing/Raise.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/File.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Cellular.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Fracture.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Gradient.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/HillPlanter.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Midpoint.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Mountain.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Noise.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Spiral.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Voronoi.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Worms.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Grid.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/AerobicErosion.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/HydraulicErosion.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/NavierStokes.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/ThermalWeathering.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Neighbours.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Operators.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Tools/Point2D.cs create mode 100644 trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Tools/Tools.cs create mode 100644 trunk/OpenSim/Tests/Common/ANumericalToleranceConstraint.cs create mode 100644 trunk/OpenSim/Tests/Common/DoubleToleranceConstraint.cs create mode 100644 trunk/OpenSim/Tests/Common/TestHelper.cs create mode 100644 trunk/OpenSim/Tests/Common/VectorToleranceConstraint.cs create mode 100644 trunk/OpenSim/Tests/Inventory/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Tests/Inventory/TestInventory.cs create mode 100644 trunk/OpenSim/Tests/OpenSim/Framework/UtilTest.cs create mode 100644 trunk/OpenSim/Tests/UserServer/Stress/UserServerStressTest.cs create mode 100644 trunk/OpenSim/Tools/Export/OpenSimExport.cs create mode 100644 trunk/OpenSim/Tools/LaunchSLClient/Form1.Designer.cs create mode 100644 trunk/OpenSim/Tools/LaunchSLClient/Form1.cs create mode 100644 trunk/OpenSim/Tools/LaunchSLClient/Form1.resx create mode 100644 trunk/OpenSim/Tools/LaunchSLClient/LauncherException.cs create mode 100644 trunk/OpenSim/Tools/LaunchSLClient/Program.cs create mode 100644 trunk/OpenSim/Tools/LaunchSLClient/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Tools/LaunchSLClient/Properties/Resources.Designer.cs create mode 100644 trunk/OpenSim/Tools/LaunchSLClient/Properties/Resources.resx create mode 100644 trunk/OpenSim/Tools/LaunchSLClient/Properties/Settings.Designer.cs create mode 100644 trunk/OpenSim/Tools/LaunchSLClient/Properties/Settings.settings create mode 100644 trunk/OpenSim/Tools/OpenSim.32BitLaunch/OpenSim.32BitLaunch.csproj create mode 100644 trunk/OpenSim/Tools/OpenSim.32BitLaunch/Program.cs create mode 100644 trunk/OpenSim/Tools/OpenSim.32BitLaunch/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/InputTextBoxControl.cs create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/Main.Designer.cs create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/Main.cs create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/Main.resx create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/OpenSim.GUI.csproj create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/ProcessManager.cs create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/Program.cs create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/Properties/AssemblyInfo.cs create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/Properties/Resources.Designer.cs create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/Properties/Resources.resx create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/Properties/Settings.Designer.cs create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/Properties/Settings.settings create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/frmConfiguration.Designer.cs create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/frmConfiguration.cs create mode 100644 trunk/OpenSim/Tools/OpenSim.GUI/frmConfiguration.resx create mode 100644 trunk/OpenSim/Tools/Windows/Installer/OpenSim.nsi create mode 100755 trunk/OpenSim/Tools/classaudit.pl create mode 100644 trunk/OpenSim/Tools/pCampBot/BotManager.cs create mode 100644 trunk/OpenSim/Tools/pCampBot/PhysicsBot.cs create mode 100644 trunk/OpenSim/Tools/pCampBot/README.txt create mode 100644 trunk/OpenSim/Tools/pCampBot/pCampBot.cs create mode 100644 trunk/Prebuild/README create mode 100644 trunk/Prebuild/TODO create mode 100644 trunk/Prebuild/doc/prebuild-example1.xml create mode 100644 trunk/Prebuild/doc/prebuild-example2.xml create mode 100644 trunk/Prebuild/doc/prebuild-example3.xml create mode 100644 trunk/Prebuild/doc/prebuild-example4.xml create mode 100644 trunk/Prebuild/doc/prebuild-example5.xml create mode 100644 trunk/Prebuild/prebuild create mode 100755 trunk/Prebuild/scripts/Clean.bat create mode 100755 trunk/Prebuild/scripts/Help.bat create mode 100755 trunk/Prebuild/scripts/MonoDevelop.sh create mode 100644 trunk/Prebuild/scripts/Prebuild.nsi create mode 100755 trunk/Prebuild/scripts/SharpDevelop.bat create mode 100755 trunk/Prebuild/scripts/SharpDevelop2.bat create mode 100755 trunk/Prebuild/scripts/VS2002.bat create mode 100755 trunk/Prebuild/scripts/VS2003.bat create mode 100755 trunk/Prebuild/scripts/VS2005.bat create mode 100755 trunk/Prebuild/scripts/autotools.bat create mode 100755 trunk/Prebuild/scripts/autotools.sh create mode 100755 trunk/Prebuild/scripts/nant.bat create mode 100755 trunk/Prebuild/scripts/nant.sh create mode 100644 trunk/Prebuild/src/App.ico create mode 100644 trunk/Prebuild/src/Core/Attributes/DataNodeAttribute.cs create mode 100644 trunk/Prebuild/src/Core/Attributes/OptionNodeAttribute.cs create mode 100644 trunk/Prebuild/src/Core/Attributes/TargetAttribute.cs create mode 100644 trunk/Prebuild/src/Core/FatalException.cs create mode 100644 trunk/Prebuild/src/Core/Interfaces/IDataNode.cs create mode 100644 trunk/Prebuild/src/Core/Interfaces/ITarget.cs create mode 100644 trunk/Prebuild/src/Core/Kernel.cs create mode 100644 trunk/Prebuild/src/Core/Nodes/ConfigurationNode.cs create mode 100644 trunk/Prebuild/src/Core/Nodes/DataNode.cs create mode 100644 trunk/Prebuild/src/Core/Nodes/ExcludeNode.cs create mode 100644 trunk/Prebuild/src/Core/Nodes/FileNode.cs create mode 100644 trunk/Prebuild/src/Core/Nodes/FilesNode.cs create mode 100644 trunk/Prebuild/src/Core/Nodes/MatchNode.cs create mode 100644 trunk/Prebuild/src/Core/Nodes/OptionsNode.cs create mode 100644 trunk/Prebuild/src/Core/Nodes/ProcessNode.cs create mode 100644 trunk/Prebuild/src/Core/Nodes/ProjectNode.cs create mode 100644 trunk/Prebuild/src/Core/Nodes/ReferenceNode.cs create mode 100644 trunk/Prebuild/src/Core/Nodes/ReferencePathNode.cs create mode 100644 trunk/Prebuild/src/Core/Nodes/SolutionNode.cs create mode 100644 trunk/Prebuild/src/Core/Parse/IfContext.cs create mode 100644 trunk/Prebuild/src/Core/Parse/Preprocessor.cs create mode 100644 trunk/Prebuild/src/Core/Targets/AutotoolsTarget.cs create mode 100644 trunk/Prebuild/src/Core/Targets/DebugTarget.cs create mode 100644 trunk/Prebuild/src/Core/Targets/MonoDevelopTarget.cs create mode 100644 trunk/Prebuild/src/Core/Targets/NAntTarget.cs create mode 100644 trunk/Prebuild/src/Core/Targets/SharpDevelop2Target.cs create mode 100644 trunk/Prebuild/src/Core/Targets/SharpDevelopTarget.cs create mode 100644 trunk/Prebuild/src/Core/Targets/VS2002Target.cs create mode 100644 trunk/Prebuild/src/Core/Targets/VS2003Target.cs create mode 100644 trunk/Prebuild/src/Core/Targets/VS2005Target.cs create mode 100644 trunk/Prebuild/src/Core/Targets/VS2008Target.cs create mode 100644 trunk/Prebuild/src/Core/UnknownLanguageException.cs create mode 100644 trunk/Prebuild/src/Core/Utilities/CommandLineCollection.cs create mode 100644 trunk/Prebuild/src/Core/Utilities/CurrentDirectory.cs create mode 100644 trunk/Prebuild/src/Core/Utilities/Helper.cs create mode 100644 trunk/Prebuild/src/Core/Utilities/Log.cs create mode 100644 trunk/Prebuild/src/Core/WarningException.cs create mode 100644 trunk/Prebuild/src/Prebuild.cs create mode 100644 trunk/Prebuild/src/Prebuild.snk create mode 100644 trunk/Prebuild/src/Properties/AssemblyInfo.cs create mode 100644 trunk/Prebuild/src/data/dnpb-1.0.xsd create mode 100644 trunk/Prebuild/src/data/dnpb-1.1.xsd create mode 100644 trunk/Prebuild/src/data/dnpb-1.2.xsd create mode 100644 trunk/Prebuild/src/data/dnpb-1.3.xsd create mode 100644 trunk/Prebuild/src/data/dnpb-1.4.xsd create mode 100644 trunk/Prebuild/src/data/dnpb-1.5.xsd create mode 100644 trunk/Prebuild/src/data/prebuild-1.6.xsd create mode 100644 trunk/Prebuild/src/data/prebuild-1.7.xsd create mode 100644 trunk/README.txt create mode 100644 trunk/TESTING.txt create mode 100644 trunk/ThirdParty/TribalMedia/TribalMedia.Framework.Data/BaseDataReader.cs create mode 100644 trunk/ThirdParty/TribalMedia/TribalMedia.Framework.Data/BaseDatabaseConnector.cs create mode 100644 trunk/ThirdParty/TribalMedia/TribalMedia.Framework.Data/BaseFieldMapper.cs create mode 100644 trunk/ThirdParty/TribalMedia/TribalMedia.Framework.Data/BaseRowMapper.cs create mode 100644 trunk/ThirdParty/TribalMedia/TribalMedia.Framework.Data/BaseSchema.cs create mode 100644 trunk/ThirdParty/TribalMedia/TribalMedia.Framework.Data/BaseTableMapper.cs create mode 100644 trunk/ThirdParty/TribalMedia/TribalMedia.Framework.Data/Properties/AssemblyInfo.cs create mode 100644 trunk/ThirdParty/TribalMedia/TribalMedia.Framework.Data/TribalMedia.Framework.Data.snk create mode 100644 trunk/ThirdPartyLicenses/Axiom.txt create mode 100644 trunk/ThirdPartyLicenses/Bullet for Xna (ModifiedBulletX).txt create mode 100644 trunk/ThirdPartyLicenses/BulletLicense.txt create mode 100644 trunk/ThirdPartyLicenses/Mono.Xna (MonoXnaCompactMaths).txt create mode 100644 trunk/ThirdPartyLicenses/MySQL.txt create mode 100644 trunk/ThirdPartyLicenses/Nini.txt create mode 100644 trunk/ThirdPartyLicenses/ODE.txt create mode 100644 trunk/ThirdPartyLicenses/OpenJpeg.txt create mode 100644 trunk/ThirdPartyLicenses/XML-RPC.NET.txt create mode 100644 trunk/ThirdPartyLicenses/libsl.txt create mode 100755 trunk/add-copyright.sh create mode 100644 trunk/bin/Axiom.MathLib.dll create mode 100644 trunk/bin/CookComputing.XmlRpcV2.dll create mode 100644 trunk/bin/Db4objects.Db4o.dll create mode 100644 trunk/bin/DotSets.dll create mode 100644 trunk/bin/Kds.Serialization.dll create mode 100644 trunk/bin/Modified.XnaDevRu.BulletX.dll create mode 100644 trunk/bin/Mono.Addins.dll create mode 100644 trunk/bin/Mono.Addins.dll.config create mode 100644 trunk/bin/Mono.Data.SqliteClient.dll create mode 100644 trunk/bin/Mono.PEToolkit.dll create mode 100644 trunk/bin/MonoXnaCompactMaths.dll create mode 100644 trunk/bin/MySql.Data.dll create mode 100644 trunk/bin/Nini.dll create mode 100644 trunk/bin/Ode.NET.dll create mode 100755 trunk/bin/OpenSim.32BitLaunch.exe create mode 100644 trunk/bin/OpenSim.32BitLaunch.exe.config create mode 100644 trunk/bin/OpenSim.32BitLaunch.pdb create mode 100644 trunk/bin/OpenSim.Grid.AssetServer.exe.config create mode 100644 trunk/bin/OpenSim.Grid.GridServer.exe.config create mode 100644 trunk/bin/OpenSim.Grid.InventoryServer.exe.config create mode 100644 trunk/bin/OpenSim.Grid.MessagingServer.exe.config create mode 100644 trunk/bin/OpenSim.Grid.ScriptServer.exe.config create mode 100644 trunk/bin/OpenSim.Grid.UserServer.exe.config create mode 100644 trunk/bin/OpenSim.exe.config create mode 100644 trunk/bin/OpenSim.ini.example create mode 100644 trunk/bin/OpenSimExport.exe.config create mode 100644 trunk/bin/PhysX-wrapper.dll create mode 100644 trunk/bin/PhysX_Wrapper_Dotnet.dll create mode 100755 trunk/bin/Prebuild.exe create mode 100644 trunk/bin/RAIL.dll create mode 100644 trunk/bin/ScriptEngines/Default.lsl create mode 100644 trunk/bin/SimpleApp.exe.config create mode 100644 trunk/bin/System.Data.SQLite.dll create mode 100644 trunk/bin/TerrainFilters/demofilter.cs create mode 100644 trunk/bin/XMLRPC.dll create mode 100644 trunk/bin/assets/AnimationsAssetSet/AnimationsAssetSet.xml create mode 100644 trunk/bin/assets/AssetSets.xml create mode 100644 trunk/bin/assets/Avatar/Newruth/Settings.txt create mode 100644 trunk/bin/assets/Avatar/Newruth/eyes.j2c create mode 100644 trunk/bin/assets/Avatar/Newruth/female body.j2c create mode 100644 trunk/bin/assets/Avatar/Newruth/female bottom.j2c create mode 100644 trunk/bin/assets/Avatar/Newruth/female face.j2c create mode 100644 trunk/bin/assets/Avatar/Newruth/open sim hair base.j2c create mode 100644 trunk/bin/assets/BodyPartsAssetSet/BodyPartsAssetSet.xml create mode 100644 trunk/bin/assets/BodyPartsAssetSet/base_shape.dat create mode 100644 trunk/bin/assets/BodyPartsAssetSet/base_skin.dat create mode 100644 trunk/bin/assets/BodyPartsAssetSet/goblin_skin.dat create mode 100644 trunk/bin/assets/BodyPartsAssetSet/jim_shape.dat create mode 100644 trunk/bin/assets/BodyPartsAssetSet/jim_skin.dat create mode 100644 trunk/bin/assets/BodyPartsAssetSet/little_goblin_shape.dat create mode 100644 trunk/bin/assets/BodyPartsAssetSet/newhair.dat create mode 100644 trunk/bin/assets/ClothingAssetSet/ClothingAssetSet.xml create mode 100644 trunk/bin/assets/ClothingAssetSet/newpants.dat create mode 100644 trunk/bin/assets/ClothingAssetSet/newshirt.dat create mode 100644 trunk/bin/assets/GesturesAssetSet/GesturesAssetSet.xml create mode 100644 trunk/bin/assets/LandmarksAssetSet/LandmarksAssetSet.xml create mode 100644 trunk/bin/assets/NotecardsAssetSet/NotecardsAssetSet.xml create mode 100644 trunk/bin/assets/NotecardsAssetSet/exampleNote.txt create mode 100644 trunk/bin/assets/NotecardsAssetSet/welcomeNote.txt create mode 100644 trunk/bin/assets/ObjectsAssetSet/ObjectsAssetSet.xml create mode 100644 trunk/bin/assets/OpenSimAssetSet/4-tile2.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/4-tile3.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/OpenSimAssetSet.xml create mode 100644 trunk/bin/assets/OpenSimAssetSet/base_shape.dat create mode 100644 trunk/bin/assets/OpenSimAssetSet/base_skin.dat create mode 100644 trunk/bin/assets/OpenSimAssetSet/brick1_256.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/brick2_256.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/brick_mono.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/bricks.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/cedar.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/cement_block.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/clear.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/cloud.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/cobbles.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/coffee.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/creambrick.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/femalebody.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/femalebottom.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/femaleface.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/fgrass.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/glasstile2.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/goblin_skin.dat create mode 100644 trunk/bin/assets/OpenSimAssetSet/granite.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/graniteblock.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/grass.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/grass2.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/gravel.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/greybrick.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/hardwood.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/ivy.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/jim_shape.dat create mode 100644 trunk/bin/assets/OpenSimAssetSet/jim_skin.dat create mode 100644 trunk/bin/assets/OpenSimAssetSet/licenses.txt create mode 100644 trunk/bin/assets/OpenSimAssetSet/little_goblin_shape.dat create mode 100644 trunk/bin/assets/OpenSimAssetSet/mahogany.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/map1.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/map_base.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/maple.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/moon.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/mosaic02.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/newhair.dat create mode 100644 trunk/bin/assets/OpenSimAssetSet/newpants.dat create mode 100644 trunk/bin/assets/OpenSimAssetSet/newshirt.dat create mode 100644 trunk/bin/assets/OpenSimAssetSet/palm1.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/papaya.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/papaya_bark.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/pastelbrick.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/peaches.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/pine1_10m.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/plywood.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/poplar.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/redtri_tile.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/rockbuilding.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/rocks.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/rockwallbig.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/roof01.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/rooftiles1.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/rooftiles2_peach.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/rooftiles2_roy.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/saguaro_8m.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/seawater.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/shingle.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/snow1.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/steel.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/stone1wall.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/stonetile.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/street2.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/testpic2.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/thatch.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/water1.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/water3.jp2 create mode 100644 trunk/bin/assets/OpenSimAssetSet/welcomeNote.dat create mode 100644 trunk/bin/assets/OpenSimAssetSet/wood1.jp2 create mode 100644 trunk/bin/assets/PhotosAssetSet/PhotosAssetSet.xml create mode 100644 trunk/bin/assets/README.txt create mode 100644 trunk/bin/assets/ScriptsAssetSet/ScriptsAssetSet.xml create mode 100644 trunk/bin/assets/ScriptsAssetSet/llAbs.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llAcos.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llAddToLandBanList.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llAddToLandPassList.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llAdjustSoundVolume.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llAllowInventoryDrop.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llAngleBetween.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llApplyImpulse.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llAsin.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llAtan2.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llAvatarOnSitTarget.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llBase64ToString.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llRemoveFromLandBanList.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llRemoveFromLandPassList.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llResetLandBanList.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llResetLandPassList.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llSay.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llSetParcelMusicURL.lsl create mode 100644 trunk/bin/assets/ScriptsAssetSet/llSetRot.lsl create mode 100644 trunk/bin/assets/SoundsAssetSet/SoundsAssetSet.xml create mode 100644 trunk/bin/assets/TexturesAssetSet/4-tile2.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/4-tile3.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/TexturesAssetSet.xml create mode 100644 trunk/bin/assets/TexturesAssetSet/brick1_256.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/brick2_256.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/brick_mono.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/bricks.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/cedar.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/cement_block.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/clear.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/cloud.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/cobbles.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/coffee.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/creambrick.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/fe_face.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/fe_lower.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/fe_upper.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/femalebody.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/femalebottom.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/femaleface.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/fgrass.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/glasstile2.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/granite.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/graniteblock.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/grass.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/grass2.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/gravel.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/greybrick.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/hardwood.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/ivy.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/le_face.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/le_lower.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/le_upper.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/licenses.txt create mode 100644 trunk/bin/assets/TexturesAssetSet/mahogany.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/map1.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/map_base.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/maple.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/moon.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/mosaic02.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/palm1.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/papaya.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/papaya_bark.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/pastelbrick.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/peaches.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/pine1_10m.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/plywood.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/poplar.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/re_face.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/re_lower.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/re_upper.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/redtri_tile.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/rockbuilding.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/rocks.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/rockwallbig.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/roof01.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/rooftiles1.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/rooftiles2_peach.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/rooftiles2_roy.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/saguaro_8m.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/se_face.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/se_lower.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/se_upper.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/seawater.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/shingle.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/skins_license.txt create mode 100644 trunk/bin/assets/TexturesAssetSet/snow1.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/steel.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/stone1wall.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/stonetile.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/street2.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/testpic2.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/thatch.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/water1.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/water3.jp2 create mode 100644 trunk/bin/assets/TexturesAssetSet/wood1.jp2 create mode 100644 trunk/bin/avatar-texture.dat create mode 100644 trunk/bin/data/LICENSE-README-IMPORTANT.txt create mode 100644 trunk/bin/data/avataranimations.xml create mode 100644 trunk/bin/defaultstripe.png create mode 100644 trunk/bin/excuses create mode 100644 trunk/bin/http_404.html.example create mode 100644 trunk/bin/http_500.html.example create mode 100644 trunk/bin/http_loginform.html.example create mode 100644 trunk/bin/inventory/AnimationsLibrary/AnimationsLibraryFolders.xml create mode 100644 trunk/bin/inventory/AnimationsLibrary/AnimationsLibraryItems.xml create mode 100644 trunk/bin/inventory/BodyPartsLibrary/BodyPartsLibraryFolders.xml create mode 100644 trunk/bin/inventory/BodyPartsLibrary/BodyPartsLibraryItems.xml create mode 100644 trunk/bin/inventory/ClothingLibrary/ClothingLibraryFolders.xml create mode 100644 trunk/bin/inventory/ClothingLibrary/ClothingLibraryItems.xml create mode 100644 trunk/bin/inventory/GesturesLibrary/GesturesLibraryFolders.xml create mode 100644 trunk/bin/inventory/GesturesLibrary/GesturesLibraryItems.xml create mode 100644 trunk/bin/inventory/LandmarksLibrary/LandmarksLibraryFolders.xml create mode 100644 trunk/bin/inventory/LandmarksLibrary/LandmarksLibraryItems.xml create mode 100644 trunk/bin/inventory/Libraries.xml create mode 100644 trunk/bin/inventory/NotecardsLibrary/NotecardsLibraryFolders.xml create mode 100644 trunk/bin/inventory/NotecardsLibrary/NotecardsLibraryItems.xml create mode 100644 trunk/bin/inventory/ObjectsLibrary/ObjectsLibraryFolders.xml create mode 100644 trunk/bin/inventory/ObjectsLibrary/ObjectsLibraryItems.xml create mode 100644 trunk/bin/inventory/OpenSimLibrary/OpenSimLibrary.xml create mode 100644 trunk/bin/inventory/OpenSimLibrary/OpenSimLibraryFolders.xml create mode 100644 trunk/bin/inventory/PhotosLibrary/PhotosLibraryFolders.xml create mode 100644 trunk/bin/inventory/PhotosLibrary/PhotosLibraryItems.xml create mode 100644 trunk/bin/inventory/README.txt create mode 100644 trunk/bin/inventory/ScriptsLibrary/ScriptsLibraryFolders.xml create mode 100644 trunk/bin/inventory/ScriptsLibrary/ScriptsLibraryItems.xml create mode 100644 trunk/bin/inventory/SoundsLibrary/SoundsLibraryFolders.xml create mode 100644 trunk/bin/inventory/SoundsLibrary/SoundsLibraryItems.xml create mode 100644 trunk/bin/inventory/TexturesLibrary/TexturesLibraryFolders.xml create mode 100644 trunk/bin/inventory/TexturesLibrary/TexturesLibraryItems.xml create mode 100644 trunk/bin/inventory/attic/Inventory_Default.xml create mode 100644 trunk/bin/inventory/attic/Inventory_Library.xml create mode 100644 trunk/bin/libdb_dotNET43.dll create mode 100644 trunk/bin/libode.dylib create mode 100644 trunk/bin/libode.so create mode 100644 trunk/bin/libopenjpeg-1.0.0-x86_64.so create mode 100644 trunk/bin/libopenjpeg-1.0.0.so create mode 100644 trunk/bin/libopenjpeg-1.1.0.dylib create mode 100644 trunk/bin/libopenjpeg-libsl-2.1.2.0.dylib create mode 100644 trunk/bin/libopenjpeg-libsl-2.1.2.0.so create mode 100644 trunk/bin/libsecondlife.dll create mode 100644 trunk/bin/libsecondlife.dll.config create mode 100644 trunk/bin/log4net.dll create mode 100644 trunk/bin/mssql_connection.ini.example create mode 100644 trunk/bin/mysql_connection.ini.example create mode 100644 trunk/bin/nunit.framework.dll create mode 100644 trunk/bin/ode.dll create mode 100644 trunk/bin/openjpeg-libsl.dll create mode 100755 trunk/bin/opensim-ode.sh create mode 100644 trunk/bin/pCampBot.exe.config create mode 100644 trunk/bin/pCampBotSentences.txt create mode 100644 trunk/bin/shutdown_commands.txt create mode 100644 trunk/bin/sqlite-3.4.1.so create mode 100644 trunk/bin/sqlite3.dll create mode 100644 trunk/bin/startup_commands.txt.example create mode 100644 trunk/prebuild.xml create mode 100755 trunk/runprebuild.bat create mode 100755 trunk/runprebuild.sh create mode 100755 trunk/runprebuild2008.bat create mode 100644 trunk/share/RegionLoading/HOWTO_REMOTE_REGION_LOADING.txt create mode 100644 trunk/share/RegionLoading/example_web.xml create mode 100755 trunk/share/php/generateUserFunction.php create mode 100644 trunk/share/ruby/README create mode 100755 trunk/share/ruby/aserv.rb create mode 100755 trunk/share/ruby/config.rb create mode 100755 trunk/share/ruby/gridserv.rb create mode 100755 trunk/share/ruby/userserv.rb create mode 100644 trunk/share/sql/mssql-CreateAssetsTable.sql create mode 100644 trunk/share/sql/mssql-CreateFoldersTable.sql create mode 100644 trunk/share/sql/mssql-CreateItemsTable.sql create mode 100644 trunk/share/sql/mssql-agents.sql create mode 100644 trunk/share/sql/mssql-logs.sql create mode 100644 trunk/share/sql/mssql-users.sql create mode 100644 trunk/share/sql/mysql_README.txt create mode 100755 trunk/update-svn-properties.py diff --git a/trunk/.nant/local.include b/trunk/.nant/local.include new file mode 100644 index 0000000000..48955aab6d --- /dev/null +++ b/trunk/.nant/local.include @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/trunk/CONTRIBUTORS.txt b/trunk/CONTRIBUTORS.txt new file mode 100644 index 0000000000..0c446dc38b --- /dev/null +++ b/trunk/CONTRIBUTORS.txt @@ -0,0 +1,77 @@ +The following people have contributed to OpenSim (Thank you +for your effort!) + +Add your name in here if you have committed to OpenSim + + +OpenSim Developers + +* MW (Tribal Media AB) +* Adam Frisby (DeepThink Pty Ltd) +* MingChen (DeepThink Pty Ltd) +* lbsa71 (Tribal Media AB) +* sdague (International Business Machines Corp.) +* Andy- +* Gareth +* MorphW +* CW +* Babblefrog +* Tedd +* justincc (International Business Machines Corp.) +* Teravus (w3z) +* Johan Berntsson (3Di) +* Ckrinke (Charles Krinke) +* Danx0r +* Dalien +* Darok +* chi11ken (3Di) +* adjohn (3Di) +* Alondria + + +Patches + +* BigFootAg +* CharlieO +* jhurliman (LLSD Login) +* kinoc +* daTwitch +* mikkopa/_someone - RealXtend +* openlifegrid.com +* Dr Scofield (International Business Machines Corp.) +* Daedius +* alex_carnell +* webmage (International Business Machines Corp.) +* jimbo2120 (International Business Machines Corp.) + + +LSL Devs + +* Alondria +* CharlieO +* Tedd + + +Testers + +* Ckrinke +* CharlieO (LSL) +* openlifegrid.com + + +This software uses components from the following developers: +* Sleepycat Software (Berkeley DB) +* DB4objects, Inc. (DB4o) +* SQLite (Public Domain) +* XmlRpcCS (http://xmlrpccs.sf.net/) +* MySQL, Inc. (MySQL Connector/NET) +* AGEIA Inc. (PhysX) +* Russel L. Smith (ODE) +* Prebuild ( http://sourceforge.net/projects/dnpb/ ) +* LibSecondLife ( http://www.libsecondlife.org/wiki/Main_Page ) + + +In addition, we would like to thank: +* The Mono Project +* The NANT Developers +* Microsoft (.NET, MSSQL-Adapters) diff --git a/trunk/LICENSE.txt b/trunk/LICENSE.txt new file mode 100644 index 0000000000..6d54d342f3 --- /dev/null +++ b/trunk/LICENSE.txt @@ -0,0 +1,25 @@ +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. diff --git a/trunk/OpenSim.FxCop b/trunk/OpenSim.FxCop new file mode 100644 index 0000000000..d07c26efbf --- /dev/null +++ b/trunk/OpenSim.FxCop @@ -0,0 +1,7241 @@ + + + + True + http://www.gotdotnet.com/team/fxcop//xsl/1.35/FxCopReport.xsl + + + + + + True + True + True + 10 + 1 + + False + False + + False + 120 + + + + $(ProjectDir)/lib/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sim + OpenSim + + + + + + + + + Sim + OpenSim.Assets + + + + + + + + + OpenSim.CAPS + + + + + Sim + OpenSim.CAPS + + + + + OpenSim.CAPS + + + + + + + + + Sim + OpenSim.Config.SimConfigDb4o + + + Sim + OpenSim.Config.SimConfigDb4o + + + + + + + + + OpenSim.Framework.Assets + + + + + Sim + OpenSim.Framework.Assets + + + + + + + + + Sim + OpenSim.Framework.Console + + + + + + + + + OpenSim.Framework.Grid + + + + + Sim + OpenSim.Framework.Grid + + + + + + + + + Sim + OpenSim.Framework.Interfaces + + + + + + + + + OpenSim.Framework.Inventory + + + + + Sim + OpenSim.Framework.Inventory + + + + + + + + + OpenSim.Framework.Sims + + + + + Sim + OpenSim.Framework.Sims + + + + + + + + + OpenSim.Framework.Terrain + + + + + Sim + OpenSim.Framework.Terrain + + + + + + + + + OpenSim.Framework.User + + + + + Sim + OpenSim.Framework.User + + + + + + + + + OpenSim.Framework.Utilities + + + + + Sim + OpenSim.Framework.Utilities + + + + + + + + + Sim + OpenSim.GridInterfaces.Local + + + + + + + + + OpenSim.GridInterfaces.Remote + + + + + Sim + OpenSim.GridInterfaces.Remote + + + + + + + + + Plugin + OpenSim.Physics.BasicPhysicsPlugin + + + + + Sim + OpenSim.Physics.BasicPhysicsPlugin + + + + + + + + + Sim + OpenSim.Physics.Manager + + + + + + + + + OpenSim.Physics.OdePlugin + + + + + Plugin + OpenSim.Physics.OdePlugin + + + + + Sim + OpenSim.Physics.OdePlugin + + + + + + + + + OpenSim.Physics.PhysXPlugin + + + + + Plugin + OpenSim.Physics.PhysXPlugin + + + + + Sim + OpenSim.Physics.PhysXPlugin + + + + + + + + + Sim + OpenSim.Storage.LocalStorageDb4o + + + + + + + + + OpenSim.types + + + + + OpenSim.types + + + + + Sim + OpenSim.types + + + + + + + + + OpenSim.UserServer + + + + + Sim + OpenSim.UserServer + + + + + + + + + OpenSim.world + + + + + Sim + OpenSim.world + + + + + + + + + OpenSim.world.scripting + + + + + OpenSim.world.scripting + + + OpenSim.world.scripting + + + + + Sim + OpenSim.world.scripting + + + + + + + + + + + + + OpenGridServices.ServerConsole + + + + + OpenGridServices.ServerConsole + + + + + OpenGridServices.ServerConsole + + + + + + + + + + + conscmd_callback + + + + + conscmd + ServerConsole.conscmd_callback + + + + + conscmd_callback + + + + + + + + + conscmd_callback.RunCmd(String, String[]):Void + cmdparams + cmdparams + + + + + + + + + ShowWhat + + + + + + + + + + + + + ConsoleBase.CmdPrompt(String, String):String + defaultresponse + defaultresponse + + + + + + + + + OptionA + + + + + OptionB + + + + + ConsoleBase.CmdPrompt(String, String, String, String):String + defaultresponse + defaultresponse + + + + + + + + + Passwd + ConsoleBase.PasswdPrompt(String):String + + + + + + + + + Cmd + + + + + ConsoleBase.RunCmd(String, String[]):Object + cmdparams + cmdparams + + + + + + + + + ShowWhat + + + + + + + + + Line + + + + + + + + + Line + + + + + + + + + + + + + Sim + ConsoleType.SimChat + + + + + + + + + ConsoleType.TCP + + + + + + + + + + + MainConsole + + + + + + + + + + + + + + + + + OpenSim.Config.SimConfigDb4o + + + + + OpenSim.Config.SimConfigDb4o + + + + + OpenSim.Config.SimConfigDb4o + + + + + + + + + + + Plugin + OpenSim.Config.SimConfigDb4o.Db40ConfigPlugin + + + + + + + + + Sim + OpenSim.Config.SimConfigDb4o.DbSimConfig + + + + + Db + OpenSim.Config.SimConfigDb4o.DbSimConfig + + + + + + + + + DbSimConfig.InitConfig(Boolean):Void + System.Exception + + + + + DbSimConfig.InitConfig(Boolean):Void + System.UInt32.ToString + System.UInt32.ToString(System.IFormatProvider) + + + + + DbSimConfig.InitConfig(Boolean):Void + System.UInt64.ToString + System.UInt64.ToString(System.IFormatProvider) + + + + + + + + + DbSimConfig.LoadDefaults():Void + System.Convert.ToInt32(System.String) + System.Convert.ToInt32(System.String,System.IFormatProvider) + + + DbSimConfig.LoadDefaults():Void + System.Convert.ToInt32(System.String) + System.Convert.ToInt32(System.String,System.IFormatProvider) + + + DbSimConfig.LoadDefaults():Void + System.Convert.ToInt32(System.String) + System.Convert.ToInt32(System.String,System.IFormatProvider) + + + + + + + + + + + + + Map + + + + + + + + + + + + + + + + + + + OpenSim + + + + + OpenSim + + + + + OpenSim + + + + + OpenSim + + + + + OpenSim + + + + + + + + + + + + + 'args' + RegionServer.Main(String[]):Void + + + 'args' + RegionServer.Main(String[]):Void + + + + + + + + + + + + + + + + + + + OpenSim.Framework.Console + + + + + OpenSim.Framework.Console + + + + + OpenSim.Framework.Console + + + + + + + + + + + + + ConsoleBase.CmdPrompt(String, String):String + defaultresponse + defaultresponse + + + + + + + + + OptionA + + + + + OptionB + + + + + ConsoleBase.CmdPrompt(String, String, String, String):String + defaultresponse + defaultresponse + + + + + + + + + Cmd + + + + + ConsoleBase.RunCmd(String, String[]):Object + cmdparams + cmdparams + + + + + + + + + ShowWhat + + + + + + + + + + + + + Sim + ConsoleType.SimChat + + + + + + + + + ConsoleType.TCP + + + + + + + + + + + MainConsole + + + + + + + + + + + + + + + + + OpenSim.Framework + + + + + OpenSim.Framework + + + + + OpenSim.Framework + + + + + + + + + + + + + Data + + + + + + + + + Description + + + + + + + + + FullID + + + + + + + + + InvType + + + + + + + + + Name + + + + + + + + + Type + + + + + + + + + + + + + PrimData.PrimData() + ParentID + System.UInt32 + 0 + + + + + + + + + FullID + + + + + + + + + LocalID + + + + + + + + + OwnerID + + + + + + + + + ParentID + + + + + + + + + PathBegin + + + + + + + + + PathCurve + + + + + + + + + PathEnd + + + + + + + + + PathRadiusOffset + + + + + + + + + PathRevolutions + + + + + + + + + PathScaleX + + + + + + + + + PathScaleY + + + + + + + + + PathShearX + + + + + + + + + PathShearY + + + + + + + + + PathSkew + + + + + + + + + PathTaperX + + + + + + + + + PathTaperY + + + + + + + + + PathTwist + + + + + + + + + PathTwistBegin + + + + + + + + + PCode + + + + + + + + + Position + + + + + + + + + ProfileBegin + + + + + + + + + ProfileCurve + + + + + + + + + ProfileEnd + + + + + + + + + ProfileHollow + + + + + + + + + Rotation + + + + + + + + + Scale + + + + + + + + + Texture + + + + + + + + + + + + + + + Login + LoginService + LogOn + + + + + + + + + + + + + + + AgentID + + + + + + + + + circuitcode + + + + + circuitcode + AgentCircuitData.circuitcode + + + + + + + + + firstname + + + + + firstname + AgentCircuitData.firstname + + + + + + + + + lastname + + + + + lastname + AgentCircuitData.lastname + + + + + + + + + SecureSessionID + + + + + + + + + SessionID + + + + + + + + + + + OpenSim.Framework.Interfaces.ARequest + + + OpenSim.Framework.Interfaces.ARequest + + + + + + + + + AssetID + + + + + + + + + IsTexture + + + + + + + + + + + + + Authorised + + + + + Authorised + AuthenticateResponse.Authorised + + + + + + + + + LoginInfo + + + + + Login + LoginInfo + LogOn + + + + + + + + + + + Plugin + OpenSim.Framework.Interfaces.IAssetPlugin + + + + + + + + + GetAssetServer + + + + + + + + + + + + + IsTexture + + + + + + + + + + + + + ID + assetID + Id + + + + + + + + + ServerUrl + + + + + ServerKey + + + + + ServerUrl + IAssetServer.SetServerInfo(String, String):Void + + + + + + + + + + + Plugin + OpenSim.Framework.Interfaces.IGridPlugin + + + + + + + + + GetGridServer + + + + + + + + + + + + + ID + sessionID + Id + + + + + ID + agentID + Id + + + + + + + + + GetName + + + + + + + + + ID + sessionID + Id + + + + + ID + agentID + Id + + + + + Logout + LogoutSession + LogOff + + + + + + + + + Neighbours + IGridServer.RequestNeighbours():NeighbourInfo[] + + + + + + + + + IGridServer.RequestUUIDBlock():UUIDBlock + + + + + + + + + ServerUrl + + + + + SendKey + + + + + RecvKey + + + + + IGridServer.SetServerInfo(String, String, String):Void + Recv + RecvKey + + + + + ServerUrl + IGridServer.SetServerInfo(String, String, String):Void + + + + + + + + + + + + + ID + primID + Id + + + + + + + + + ShutDown + method + ShutDown + Shutdown + + + + + + + + + + + Sim + OpenSim.Framework.Interfaces.ISimConfig + + + + + + + + + GetConfigObject + + + + + + + + + + + + + ID + agentID + Id + + + + + + + + + ServerUrl + + + + + SendKey + + + + + RecvKey + + + + + IUserServer.SetServerInfo(String, String, String):Void + Recv + RecvKey + + + + + ServerUrl + IUserServer.SetServerInfo(String, String, String):Void + + + + + + + + + + + + + Logout + LogoutSession + LogOff + + + + + + + + + + + Login + Login + LogOn + + + + + + + + + Agent + + + + + + + + + BaseFolder + + + + + + + + + First + + + + + + + + + InventoryFolder + + + + + + + + + Last + + + + + + + + + SecureSession + + + + + + + + + Session + + + + + + + + + + + Neighbour + OpenSim.Framework.Interfaces.NeighbourInfo + + + + + + + + + regionhandle + + + + + regionhandle + NeighbourInfo.regionhandle + + + + + + + + + RegionLocX + + + + + + + + + RegionLocY + + + + + + + + + sim_ip + + + + + sim + NeighbourInfo.sim_ip + + + + + sim_ip + + + + + + + + + sim_port + + + + + sim + NeighbourInfo.sim_port + + + + + sim_port + + + + + + + + + + + + + agentcircuits + + + + + agentcircuits + + + + + agentcircuits + RemoteGridBase.agentcircuits:Dictionary`2<System.UInt32,OpenSim.Framework.Interfaces.AgentCircuitData> + + + + + + + + + Logout + LogoutSession + LogOff + + + + + + + + + + + Sim + OpenSim.Framework.Interfaces.SimConfig + + + + + + + + + AssetSendKey + + + + + + + + + AssetURL + + + + + + + + + GridRecvKey + + + + + Recv + SimConfig.GridRecvKey + + + + + + + + + GridSendKey + + + + + + + + + GridURL + + + + + + + + + IPListenAddr + + + + + Addr + SimConfig.IPListenAddr + + + + + + + + + IPListenPort + + + + + + + + + RegionHandle + + + + + + + + + RegionLocX + + + + + + + + + RegionLocY + + + + + + + + + RegionName + + + + + + + + + SimConfig.SaveMap(Single[]):Void + heightmap + heightmap + + + + + + + + + UserRecvKey + + + + + Recv + SimConfig.UserRecvKey + + + + + + + + + UserSendKey + + + + + + + + + UserURL + + + + + + + + + + + UUIDBlock + + + + + OpenSim.Framework.Interfaces.UUIDBlock + + + OpenSim.Framework.Interfaces.UUIDBlock + + + + + + + + + BlockEnd + + + + + + + + + BlockStart + + + + + + + + + + + + + + + + + AgentInventory.AgentInventory() + AgentInventory.AgentInventory() AgentInventory.Initialise():Void + + + + + + + + + ID + folderID + Id + + + + + + + + + AgentID + + + + + + + + + ID + folderID + Id + + + + + + + + + Initialise + AgentInventory.Initialise():Void + + + + + + + + + InventoryFolders + + + + + + + + + InventoryItems + + + + + + + + + InventoryRoot + + + + + + + + + LastCached + + + + + + + + + ID + itemID + Id + + + + + + + + + Wearables + + + + + Wearables + AgentInventory.Wearables + + + + + + + + + + + + + AssetID + + + + + + + + + ItemID + + + + + + + + + + + + + DefaultType + + + + + + + + + FolderID + + + + + + + + + FolderName + + + + + + + + + Items + + + + + System.Collections.Generic.List`1<OpenSim.Framework.Inventory.InventoryItem> + InventoryFolder.Items + + + + + + + + + OwnerID + + + + + + + + + ParentID + + + + + + + + + Version + + + + + + + + + + + + + AssetID + + + + + + + + + CreatorID + + + + + + + + + Description + + + + + + + + + FolderID + + + + + + + + + InvType + + + + + + + + + ItemID + + + + + + + + + Name + + + + + + + + + OwnerID + + + + + + + + + Type + + + + + + + + + + + + + + + Sim + OpenSim.Framework.Sims.SimProfile + + + + + + + + + SimProfile.LoadFromGrid(UInt64, String, String, String):SimProfile + System.Exception + + + + + GridURL + + + + + SendKey + + + + + RecvKey + + + + + SimProfile.LoadFromGrid(UInt64, String, String, String):SimProfile + Recv + RecvKey + + + + + region_handle + + + + + GridURL + + + + + RecvKey + SimProfile.LoadFromGrid(UInt64, String, String, String):SimProfile + + + + + SimProfile.LoadFromGrid(UInt64, String, String, String):SimProfile + System.Convert.ToUInt16(System.Object) + System.Convert.ToUInt16(System.Object,System.IFormatProvider) + + + + + SimProfile.LoadFromGrid(UInt64, String, String, String):SimProfile + System.Convert.ToUInt32(System.Object) + System.Convert.ToUInt32(System.Object,System.IFormatProvider) + + + SimProfile.LoadFromGrid(UInt64, String, String, String):SimProfile + System.Convert.ToUInt32(System.Object) + System.Convert.ToUInt32(System.Object,System.IFormatProvider) + + + + + SimProfile.LoadFromGrid(UInt64, String, String, String):SimProfile + System.Convert.ToUInt64(System.Object) + System.Convert.ToUInt64(System.Object,System.IFormatProvider) + + + + + SimProfile.LoadFromGrid(UInt64, String, String, String):SimProfile + System.UInt64.ToString + System.UInt64.ToString(System.IFormatProvider) + + + + + + + + + + + Sim + OpenSim.Framework.Sims.SimProfileBase + + + + + + + + + caps_url + + + + + caps_url + + + + + + + + + recvkey + + + + + recvkey + SimProfileBase.recvkey + + + + + + + + + regionhandle + + + + + regionhandle + SimProfileBase.regionhandle + + + + + + + + + RegionLocX + + + + + + + + + RegionLocY + + + + + + + + + regionname + + + + + regionname + SimProfileBase.regionname + + + + + + + + + sendkey + + + + + sendkey + SimProfileBase.sendkey + + + + + + + + + sim_ip + + + + + sim + SimProfileBase.sim_ip + + + + + sim_ip + + + + + + + + + sim_port + + + + + sim + SimProfileBase.sim_port + + + + + sim_port + + + + + + + + + UUID + + + + + + + + + + + + + + + Heightmap + OpenSim.Framework.Terrain.HeightmapGenHills + + + + + + + + + HeightmapGenHills.GenerateHeightmap(Int32, Single, Single, Boolean):Single[] + num + numHills + + + + + Heightmap + HeightmapGenHills.GenerateHeightmap(Int32, Single, Single, Boolean):Single[] + + + + + + + + + HeightmapGenHills.NumHills + + + + + + + + + + + + + + + + + UserProfile.UserProfile() + IsGridGod + System.Boolean + false + + + + + + + + + Sim + UserProfile.AddSimCircuit(UInt32, LLUUID):Void + + + + + regionUUID + + + + + + + + + AssetURL + + + + + + + + + Circuits + + + + + + + + + CurrentSecureSessionID + + + + + + + + + CurrentSessionID + + + + + + + + + firstname + + + + + firstname + UserProfile.firstname + + + + + + + + + homelookat + + + + + homelookat + UserProfile.homelookat + + + + + + + + + homepos + + + + + homepos + UserProfile.homepos + + + + + + + + + homeregionhandle + + + + + homeregionhandle + UserProfile.homeregionhandle + + + + + + + + + Inventory + + + + + + + + + IsGridGod + + + + + + + + + IsLocal + + + + + + + + + lastname + + + + + lastname + UserProfile.lastname + + + + + + + + + MD5passwd + + + + + + + + + UUID + + + + + + + + + + + + + response + + + + + Customise + UserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + + + + + UserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + GridResp + Nwc.XmlRpc.XmlRpcResponse + + + + + UserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + + + UserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.UInt32.ToString + System.UInt32.ToString(System.IFormatProvider) + + + UserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.UInt32.ToString + System.UInt32.ToString(System.IFormatProvider) + + + + + + + + + DefaultStartupMsg + + + + + + + + + GridRecvKey + + + + + Recv + UserProfileManager.GridRecvKey + + + + + + + + + GridSendKey + + + + + + + + + GridURL + + + + + + + + + UserProfileManager.ParseXMLRPC(String):String + System.Exception + + + + + UserProfileManager.ParseXMLRPC(String):String + + + + + UserProfileManager.ParseXMLRPC(String):String + System.Int32.ToString + System.Int32.ToString(System.IFormatProvider) + + + UserProfileManager.ParseXMLRPC(String):String + System.Int32.ToString + System.Int32.ToString(System.IFormatProvider) + + + + + UserProfileManager.ParseXMLRPC(String):String + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.ParseXMLRPC(String):String + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.ParseXMLRPC(String):String + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.ParseXMLRPC(String):String + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.ParseXMLRPC(String):String + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.ParseXMLRPC(String):String + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.ParseXMLRPC(String):String + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.ParseXMLRPC(String):String + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + UserProfileManager.ParseXMLRPC(String):String + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + + + + + + + UserProfileManager.SetKeys(String, String, String, String):Void + recv + recvKey + + + + + url + UserProfileManager.SetKeys(String, String, String, String):Void + + + + + + + + + + + + + UserProfileManagerBase.AuthenticateUser(String, String, String):Boolean + firstname + firstname + + + + + UserProfileManagerBase.AuthenticateUser(String, String, String):Boolean + lastname + lastname + + + + + UserProfileManagerBase.AuthenticateUser(String, String, String):Boolean + passwd + passwd + + + + + + + + + MD5passwd + + + + + UserProfileManagerBase.CreateNewProfile(String, String, String):UserProfile + firstname + firstname + + + + + UserProfileManagerBase.CreateNewProfile(String, String, String):UserProfile + lastname + lastname + + + + + UserProfileManagerBase.CreateNewProfile(String, String, String):UserProfile + M + MD5passwd + + + + + + + + + ProfileLLUUID + + + + + ProfileLLUUID + + + + + UserProfileManagerBase.GetProfileByLLUUID(LLUUID):UserProfile + + + + + + + + + UserProfileManagerBase.GetProfileByName(String, String):UserProfile + firstname + firstname + + + + + UserProfileManagerBase.GetProfileByName(String, String):UserProfile + lastname + lastname + + + + + + + + + ID + agentID + Id + + + + + + + + + GodID + + + + + ID + GodID + Id + + + + + + + + + UserProfiles + + + + + + + + + + + + + + + OpenSim.Framework.Utilities.BlockingQueue`1 + Queue + + + + + + + + + Util + OpenSim.Framework.Utilities.Util + + + + + Util + + + + + Util + System.Web.Util + + + + + + + + + Xfer + Util.GetNextXferID():UInt32 + + + + + Util.GetNextXferID():UInt32 + + + + + GetNextXferID + + + + + + + + + X + + + + + Y + + + + + Util.UIntsToLong(UInt32, UInt32):UInt64 + X + + + + + Util.UIntsToLong(UInt32, UInt32):UInt64 + Y + + + + + Ints + Util.UIntsToLong(UInt32, UInt32):UInt64 + + + + + + + + + + + + + + + + + + + OpenSim.GridInterfaces.Local + + + + + OpenSim.GridInterfaces.Local + + + + + OpenSim.GridInterfaces.Local + + + + + + + + + + + + + Data + + + + + + + + + Name + + + + + + + + + Type + + + + + + + + + UUID + + + + + + + + + + + AssetUUIDQuery + + + + + + + + + 'asset' + AssetUUIDQuery.Match(AssetStorage):Boolean + + + + + + + + + + + Plugin + OpenSim.GridInterfaces.Local.LocalAssetPlugin + + + + + + + + + + + LocalAssetServer.LocalAssetServer() + System.Exception + + + + + + + + + LocalAssetServer.LoadAsset(AssetBase, Boolean, String):Void + + + + + image + LocalAssetServer.LoadAsset(AssetBase, Boolean, String):Void + + + + + + + + + 'asset' + LocalAssetServer.UploadNewAsset(AssetBase):Void + + + + + + + + + + + Plugin + OpenSim.GridInterfaces.Local.LocalGridPlugin + + + + + + + + + + + Logout + LogoutSession + LogOff + + + + + + + + + Sessions + + + + + System.Collections.Generic.List`1<OpenSim.Framework.Interfaces.Login> + LocalGridServer.Sessions + + + + + + + + + + + + + + + + + + + OpenSim.GridInterfaces.Remote + + + + + OpenSim.GridInterfaces.Remote + + + + + OpenSim.GridInterfaces.Remote + + + + + + + + + + + Plugin + OpenSim.GridInterfaces.Remote.RemoteAssetPlugin + + + + + + + + + Plugin + OpenSim.GridInterfaces.Remote.RemoteGridPlugin + + + + + + + + + + + agentcircuits + + + + + + + + + circuitcode + RemoteGridServer.AuthenticateSession(LLUUID, LLUUID, UInt32):AuthenticateResponse + circuitCode + IGridServer.AuthenticateSession(LLUUID, LLUUID, UInt32):AuthenticateResponse + + + + + + + + + RemoteGridServer.GridRecvKey + + + + + + + + + RemoteGridServer.GridSendKey + + + + + + + + + RemoteGridServer.LogoutSession(LLUUID, LLUUID, UInt32):Boolean + WebRequest.Create(Uri):WebRequest + WebRequest.Create(String):WebRequest + + + + + RemoteGridServer.LogoutSession(LLUUID, LLUUID, UInt32):Boolean + GridResponse + System.String + + + + + Logout + LogoutSession + LogOff + + + + + 'sessionID' + RemoteGridServer.LogoutSession(LLUUID, LLUUID, UInt32):Boolean + + + + + + + + + + + + + + + + + + + OpenSim.Physics.Manager + + + + + OpenSim.Physics.Manager + + + + + OpenSim.Physics.Manager + + + + + + + + + + + Plugin + OpenSim.Physics.Manager.IPhysicsPlugin + + + + + + + + + GetName + + + + + + + + + GetScene + + + + + + + + + + + + + 'heightMap' + NullPhysicsScene.SetTerrain(Single[]):Void + + + + + + + + + NullPhysicsScene.Simulate(Single):Void + System.Int32.ToString + System.Int32.ToString(System.IFormatProvider) + + + + + + + + + + + + + Kinematic + PhysicsActor.Kinematic:Boolean + + + + + + + + + + + + + PhysicsManager.GetPhysicsScene(String):PhysicsScene + System.String.Format(System.String,System.Object) + System.String.Format(System.IFormatProvider,System.String,System.Object[]) + + + + + + + + + Plugins + PhysicsManager.LoadPlugins():Void + + + + + + + + + + + + + PhysicsVector.PhysicsVector(Single, Single, Single) + x + + + + + PhysicsVector.PhysicsVector(Single, Single, Single) + y + + + + + PhysicsVector.PhysicsVector(Single, Single, Single) + z + + + + + + + + + X + + + + + X + PhysicsVector.X + + + + + + + + + Y + + + + + Y + PhysicsVector.Y + + + + + + + + + Z + + + + + Z + PhysicsVector.Z + + + + + + + + + PhysicsVector.Zero + OpenSim.Physics.Manager.PhysicsVector + + + + + + + + + + + + + + + + + + + OpenSim.RegionServer + + + + + OpenSim.RegionServer + + + + + OpenSim.RegionServer + + + + + OpenSim.RegionServer + + + + + OpenSim.RegionServer + + + + + + + + + + + + + ID + transactionID + Id + + + + + + + + + ID + transactionID + Id + + + + + + + + + ID + transactionID + Id + + + + + + + + + ID + assetID + Id + + + + + AgentAssetUpload.HandleUploadPacket(AssetUploadRequestPacket, LLUUID):Void + System.Int32.ToString(System.String) + System.Int32.ToString(System.String,System.IFormatProvider) + + + AgentAssetUpload.HandleUploadPacket(AssetUploadRequestPacket, LLUUID):Void + System.Int32.ToString(System.String) + System.Int32.ToString(System.String,System.IFormatProvider) + + + + + 'assetID' + AgentAssetUpload.HandleUploadPacket(AssetUploadRequestPacket, LLUUID):Void + + + 'pack' + AgentAssetUpload.HandleUploadPacket(AssetUploadRequestPacket, LLUUID):Void + + + + + + + + + AgentAssetUpload.HandleXferPacket(SendXferPacketPacket):Void + xfer + xferPacket + + + + + Xfer + AgentAssetUpload.HandleXferPacket(SendXferPacketPacket):Void + + + + + + + + + + + + + AssetTransaction.AssetTransaction() + UploadComplete + System.Boolean + false + + + + + + + + + AddToInventory + + + + + + + + + Asset + + + + + + + + + InventFolder + + + + + + + + + TransactionID + + + + + + + + + UploadComplete + + + + + + + + + XferID + + + + + Xfer + AssetTransaction.XferID + + + + + + + + + + + Grid + OpenSim.Framework.Grid + + + + + + + + + AssetDll + + + + + + + + + AssetServer + + + + + + + + + GridDll + + + + + + + + + GridServer + + + + + + + + + Initialise + Grid.Initialise():Void + + + + + + + + + Grid.LoadAssetDll(String):IAssetServer + + + + + + + + + Grid.LoadGridDll(String):IGridServer + + + + + + + + + + + Sim + OpenSim.OpenSimApplication + + + + + + + + + OpenSimApplication.RemoveClientCircuit(UInt32):Void + circuitcode + circuitcode + + + + + + + + + OpenSimApplication.SendPacketTo(Byte[], Int32, SocketFlags, UInt32):Void + circuitcode + circuitcode + + + + + + + + + StartUp + method + StartUp + Startup + + + + + + + + + + + Sim + OpenSim.OpenSimMain + + + + + OpenSim.OpenSimMain + System.Timers.Timer, System.Net.Sockets.Socket + + + + + + + + + OpenSimMain.OpenSimMain() + loginserver + System.Boolean + false + + + OpenSimMain.OpenSimMain() + sandbox + System.Boolean + false + + + + + + + + + _physicsEngine + + + + + _physicsEngine + + + + + + + + + OpenSimMain.LoadConfigDll(String):SimConfig + + + + + + + + + loginserver + + + + + loginserver + OpenSimMain.loginserver + + + + + + + + + sandbox + + + + + + + + + Server + + + + + + + + + Timer.set_Interval(Double):Void + OpenSimMain.StartUp():Void + + + + + OpenSimMain.StartUp():Void + System.UInt32.ToString + System.UInt32.ToString(System.IFormatProvider) + + + OpenSimMain.StartUp():Void + System.UInt32.ToString + System.UInt32.ToString(System.IFormatProvider) + + + + + + + + + + + Sim + OpenSim.OpenSimRoot + + + + + + + + + OpenSimRoot.OpenSimRoot() + Sandbox + System.Boolean + false + + + + + + + + + Application + + + + + + + + + AssetCache + + + + + + + + + Cfg + + + + + Cfg + OpenSimRoot.Cfg + + + + + + + + + ClientThreads + + + + + + + + + GridServers + + + + + + + + + HttpServer + + + + + + + + + InventoryCache + + + + + + + + + LocalWorld + + + + + + + + + Sandbox + + + + + + + + + StartUp + method + StartUp + Startup + + + + + + + + + startuptime + + + + + startuptime + OpenSimRoot.startuptime + + + + + + + + + + + Que + OpenSim.QueItem + + + + + + + + + Incoming + + + + + + + + + Packet + + + + + + + + + + + Sim + OpenSim.SimClient + + + + + OpenSim.SimClient + System.Timers.Timer + + + + + + + + + SimClient.SimClient(EndPoint, UseCircuitCodePacket) + Sequence + System.UInt32 + 0 + + + SimClient.SimClient(EndPoint, UseCircuitCodePacket) + debug + System.Boolean + false + + + + + Timer.Timer(Double) + SimClient.SimClient(EndPoint, UseCircuitCodePacket) + + + + + SimClient.SimClient(EndPoint, UseCircuitCodePacket) + initialcirpack + initialcirpack + + + + + + + + + AgentID + + + + + + + + + CircuitCode + + + + + + + + + ClientAvatar + + + + + + + + + NewPack + + + + + + + + + SimClient.newAssetFolder + + + + + + + + + NewPack + + + + + + + + + Pack + + + + + SimClient.ProcessInPacket(Packet):Void + wear + libsecondlife.Packets.AgentIsNowWearingPacket + + + + + op_Equality + "" + SimClient.ProcessInPacket(Packet):Void + + + + + + + + + SimClient.ProcessOutPacket(Packet):Void + System.Exception + + + + + Pack + + + + + + + + + SecureSessionID + + + + + + + + + SessionID + + + + + + + + + userEP + + + + + + + + + + + OpenSim.SimConsole + OpenSim.Framework.Console.ConsoleBase + + + + + Sim + OpenSim.SimConsole + + + + + + + + + SimConsole.SimConsole(ConsoleType, String, Int32) + constype + constype + + + + + SimConsole.SimConsole(ConsoleType, String, Int32) + sparam + sparam + + + + + SimConsole.SimConsole(ConsoleType, String, Int32) + iparam + iparam + + + + + iparam + SimConsole.SimConsole(ConsoleType, String, Int32) + + + + + sparam + SimConsole.SimConsole(ConsoleType, String, Int32) + + + + + + + + + op_Equality + "" + SimConsole.CmdPrompt(String, String):String + + + + + + + + + SimConsole.ConsType + + + + + + + + + SimConsole.MainConsolePrompt():Void + System.UInt64.ToString + System.UInt64.ToString(System.IFormatProvider) + + + + + + + + + 'cmdparams' + SimConsole.RunCmd(String, String[]):Object + + + + + + + + + SimConsole.ShowCommands(String):Void + System.String.Format(System.String,System.Object[]) + System.String.Format(System.IFormatProvider,System.String,System.Object[]) + + + SimConsole.ShowCommands(String):Void + System.String.Format(System.String,System.Object[]) + System.String.Format(System.IFormatProvider,System.String,System.Object[]) + + + + + + + + + + + + + Version + + + + + + + + + + + + + + + + + ID + imageID + Id + + + + + + + + + AssetRequests + + + + + System.Collections.Generic.List`1<OpenSim.Assets.AssetRequest> + AssetCache.AssetRequests + + + + + + + + + Assets + + + + + + + + + sourceAsset + AssetCache.CloneAsset(LLUUID, AssetInfo):AssetInfo + OpenSim.Assets.AssetInfo + OpenSim.Framework.Assets.AssetBase + + + + + AssetCache.CloneAsset(LLUUID, AssetInfo):AssetInfo + + + + + newOwner + AssetCache.CloneAsset(LLUUID, AssetInfo):AssetInfo + + + + + 'sourceAsset' + AssetCache.CloneAsset(LLUUID, AssetInfo):AssetInfo + + + + + + + + + source + AssetCache.CloneImage(LLUUID, TextureImage):TextureImage + OpenSim.Assets.TextureImage + OpenSim.Framework.Assets.AssetBase + + + + + AssetCache.CloneImage(LLUUID, TextureImage):TextureImage + + + + + newOwner + AssetCache.CloneImage(LLUUID, TextureImage):TextureImage + + + + + 'source' + AssetCache.CloneImage(LLUUID, TextureImage):TextureImage + + + + + + + + + ID + agentID + Id + + + + + + + + + ID + assetID + Id + + + + + + + + + RequestedAssets + + + + + + + + + RequestedTextures + + + + + + + + + AssetCache.RunAssetManager():Void + System.Exception + + + + + + + + + TextureRequests + + + + + System.Collections.Generic.List`1<OpenSim.Assets.AssetRequest> + AssetCache.TextureRequests + + + + + + + + + Textures + + + + + + + + + + + OpenSim.Assets.AssetInfo + OpenSim.Framework.Assets.AssetBase + + + + + + + + + AssetInfo.AssetInfo(AssetBase) + a + aBase + + + + + 'aBase' + AssetInfo.AssetInfo(AssetBase) + + + + + + + + + + + + + AssetRequest.AssetRequest() + DataPointer + System.Int64 + 0 + + + AssetRequest.AssetRequest() + NumPackets + System.Int32 + 0 + + + AssetRequest.AssetRequest() + PacketCounter + System.Int32 + 0 + + + + + + + + + AssetInf + + + + + + + + + DataPointer + + + + + + + + + ImageInfo + + + + + + + + + IsTextureRequest + + + + + + + + + NumPackets + + + + + Num + AssetRequest.NumPackets + + + + + + + + + PacketCounter + + + + + + + + + RequestAssetID + + + + + + + + + RequestUser + + + + + + + + + TransferRequestID + + + + + + + + + + + + + ID + folderID + Id + + + + + + + + + ID + clientID + Id + + + + + + + + + ID + folderID + Id + + + + + + + + + ID + folderID + Id + + + + + + + + + FetchItems + + + + + + + + + FetchDescend + + + + + + + + + ID + agentID + Id + + + + + + + + + ID + itemID + Id + + + + + + + + + + + OpenSim.Assets.TextureImage + OpenSim.Framework.Assets.AssetBase + + + + + + + + + TextureImage.TextureImage(AssetBase) + a + aBase + + + + + 'aBase' + TextureImage.TextureImage(AssetBase) + + + + + + + + + + + + + + + Sim + OpenSim.CAPS.SimCAPSHTTPServer + + + + + SimCAPSHTTPServer + + + + + OpenSim.CAPS.SimCAPSHTTPServer + System.Net.HttpListener + + + + + + + + + SimCAPSHTTPServer.HandleRequest(Object):Void + stateinfo + stateinfo + + + + + + + + + HTTPD + + + + + + + + + Listener + + + + + + + + + SimCAPSHTTPServer.LoadAdminPage():Void + System.Exception + + + + + + + + + SimCAPSHTTPServer.ParseLLSDXML(String):String + + + + + requestBody + SimCAPSHTTPServer.ParseLLSDXML(String):String + + + + + + + + + SimCAPSHTTPServer.ParseREST(String, String, String):String + System.Exception + + + + + SimCAPSHTTPServer.ParseREST(String, String, String):String + System.String.Format(System.String,System.Object[]) + System.String.Format(System.IFormatProvider,System.String,System.Object[]) + + + + + + + + + SimCAPSHTTPServer.ParseXMLRPC(String):String + System.Exception + + + + + SimCAPSHTTPServer.ParseXMLRPC(String):String + + + + + SimCAPSHTTPServer.ParseXMLRPC(String):String + System.Convert.ToUInt32(System.Object) + System.Convert.ToUInt32(System.Object,System.IFormatProvider) + + + + + + + + + SimCAPSHTTPServer.StartHTTP():Void + System.Exception + + + + + SimCAPSHTTPServer.StartHTTP():Void + + + + + + + + + + + + + + + + + mesh + + + + + System.Collections.Generic.List`1<OpenSim.types.Triangle> + Mesh.mesh + + + + + + + + + Mesh.op_Addition(Mesh, Mesh):Mesh + a + + + + + Mesh.op_Addition(Mesh, Mesh):Mesh + b + + + + + Add + Mesh.op_Addition(Mesh, Mesh):Mesh + + + + + Mesh + Mesh.op_Addition(Mesh, Mesh):Mesh + + + + + + + + + + + + + A + + + + + B + + + + + C + + + + + Triangle.Triangle(Vector3, Vector3, Vector3) + A + + + + + Triangle.Triangle(Vector3, Vector3, Vector3) + B + + + + + Triangle.Triangle(Vector3, Vector3, Vector3) + C + + + + + + + + + + + + + + + + + LocalUserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Int32.ToString + System.Int32.ToString(System.IFormatProvider) + + + LocalUserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Int32.ToString + System.Int32.ToString(System.IFormatProvider) + + + + + LocalUserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + LocalUserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + LocalUserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + LocalUserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + LocalUserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + LocalUserProfileManager.CustomiseResponse(Hashtable&, UserProfile):Void + System.Single.ToString + System.Single.ToString(System.IFormatProvider) + + + + + + + + + + + OpenSim.UserServer.LoginServer + OpenSim.Framework.Grid.LoginService + + + + + OpenSim.UserServer.LoginServer + System.Net.Sockets.Socket + + + + + Login + LoginServer + LogOn + + + + + + + + + LoginServer.LoginServer(IGridServer) + _needPasswd + System.Boolean + false + + + LoginServer.LoginServer(IGridServer) + userAccounts + System.Boolean + false + + + + + + + + + LoginServer.Authenticate(String, String, String):Boolean + passwd + passwd + + + + + + + + + clientAddress + + + + + + + + + Customise + LoginServer.CustomiseLoginResponse(Hashtable, String, String):Void + + + + + Login + CustomiseLoginResponse + LogOn + + + + + + + + + LoginServer.EncodePassword(String):String + System.String.ToLower + System.String.ToLower(System.Globalization.CultureInfo) + + + + + + + + + LoginServer.GetAgentId(String, String):LLUUID + System.Int32.ToString(System.String) + System.Int32.ToString(System.String,System.IFormatProvider) + + + + + + + + + LoginServer.InitializeLogin():Void + 4 + UserProfileManager.SetKeys(String, String, String, String):Void + Welcome to OpenSim + + + + + Sim + OpenSim + + + + + + + + + LoginServer.LoginRequest(StreamReader, StreamWriter):Void + System.Exception + + + + + LoginServer.LoginRequest(StreamReader, StreamWriter):Void + System.Convert.ToInt32(System.String) + System.Convert.ToInt32(System.String,System.IFormatProvider) + + + + + op_Inequality + "" + LoginServer.LoginRequest(StreamReader, StreamWriter):Void + + + + + + + + + writer + LoginServer.ProcessXmlRequest(XmlRpcRequest, StreamWriter):Boolean + System.IO.StreamWriter + System.IO.TextWriter + + + + + LoginServer.ProcessXmlRequest(XmlRpcRequest, StreamWriter):Boolean + System.Int32.ToString + System.Int32.ToString(System.IFormatProvider) + + + + + LoginServer.ProcessXmlRequest(XmlRpcRequest, StreamWriter):Boolean + System.Int32.ToString(System.String) + System.Int32.ToString(System.String,System.IFormatProvider) + + + + + 'request' + LoginServer.ProcessXmlRequest(XmlRpcRequest, StreamWriter):Boolean + + + 'writer' + LoginServer.ProcessXmlRequest(XmlRpcRequest, StreamWriter):Boolean + + + 'writer' + LoginServer.ProcessXmlRequest(XmlRpcRequest, StreamWriter):Boolean + + + + + + + + + remoteAddress + + + + + + + + + LoginServer.RunLogin():Void + System.Exception + + + LoginServer.RunLogin():Void + System.Exception + + + + + LoginServer.RunLogin():Void + clientEndPoint + System.Net.IPEndPoint + + + + + + + + + + + + + + + + + Avatar.Avatar() + PhysicsEngineFlying + System.Boolean + false + + + + + + + + + Avatar.Avatar(SimClient) + _updateCount + System.Int16 + 0 + + + Avatar.Avatar(SimClient) + avatarAppearanceTexture + libsecondlife.LLObject+TextureEntry + null + + + Avatar.Avatar(SimClient) + movementflag + System.Byte + 0 + + + Avatar.Avatar(SimClient) + updateflag + System.Boolean + false + + + + + TheClient + + + + + + + + + anim_seq + + + + + anim + Avatar.anim_seq + + + + + anim_seq + + + + + + + + + Animations + + + + + + + + + RegionInfo + + + + + RegionInfo + Avatar.CompleteMovement(World):Void + + + + + + + + + ControllingClient + + + + + + + + + current_anim + + + + + anim + Avatar.current_anim + + + + + current_anim + + + + + + + + + firstname + + + + + firstname + Avatar.firstname + + + + + + + + + lastname + + + + + lastname + Avatar.lastname + + + + + + + + + Anims + Avatar.LoadAnims():Void + + + + + + + + + PhysActor + + + + + + + + + PhysicsEngineFlying + + + + + + + + + Anim + Avatar.SendAnimPack():Void + + + + + + + + + 'userInfo' + Avatar.SendAppearanceToOtherAgent(SimClient):Void + + + + + + + + + RegionInfo + + + + + RegionInfo + Avatar.SendRegionHandshake(World):Void + + + + + + + + + + + + + AnimsLLUUID + + + + + Anims + AvatarAnimations.AnimsLLUUID + + + + + + + + + AnimsNames + + + + + Anims + AvatarAnimations.AnimsNames + + + + + + + + + Anims + AvatarAnimations.LoadAnims():Void + + + + + + + + + + + + + Entity.Entity() + localid + System.UInt32 + 0 + + + + + + + + + addForces + + + + + + + + + BackUp + method + BackUp + Backup + + + + + + + + + children + + + + + System.Collections.Generic.List`1<OpenSim.world.Entity> + Entity.children + + + + + + + + + getMesh + + + + + + + + + getName + + + + + + + + + localid + + + + + localid + Entity.localid + + + + + + + + + name + + + + + + + + + position + + + + + + + + + rotation + + + + + + + + + update + + + + + + + + + uuid + + + + + uuid + Entity.uuid + + + + + + + + + velocity + + + + + + + + + + + + + X + + + + + X + NewForce.X + + + + + + + + + Y + + + + + Y + NewForce.Y + + + + + + + + + Z + + + + + Z + NewForce.Z + + + + + + + + + + + 'UpdateFlag' + updateFlag + + + + + + + + + Primitive.Primitive() + dirtyFlag + System.Boolean + false + + + Primitive.Primitive() + mesh_cutbegin + System.Single + 0.0 + + + Primitive.Primitive() + newPrimFlag + System.Boolean + false + + + Primitive.Primitive() + physicsEnabled + System.Boolean + false + + + Primitive.Primitive() + physicstest + System.Boolean + false + + + Primitive.Primitive() + updateFlag + System.Boolean + false + + + + + + + + + localID-702000 + Primitive.CreateFromPacket(ObjectAddPacket, LLUUID, UInt32):Void + + + + + ID + agentID + Id + + + + + ID + localID + Id + + + + + Primitive.CreateFromPacket(ObjectAddPacket, LLUUID, UInt32):Void + System.UInt32.ToString(System.String) + System.UInt32.ToString(System.String,System.IFormatProvider) + + + + + 'addPacket' + Primitive.CreateFromPacket(ObjectAddPacket, LLUUID, UInt32):Void + + + + + + + + + 'store' + Primitive.CreateFromStorage(PrimData):Void + + + + + + + + + dirtyFlag + + + + + + + + + mesh_cutbegin + + + + + cutbegin + Primitive.mesh_cutbegin + + + + + mesh_cutbegin + + + + + + + + + mesh_cutend + + + + + cutend + Primitive.mesh_cutend + + + + + mesh_cutend + + + + + + + + + newPrimFlag + + + + + + + + + PhysActor + + + + + + + + + primData + + + + + + + + + RemoteClient + + + + + 'RemoteClient' + Primitive.UpdateClient(SimClient):Void + + + + + + + + + updateFlag + + + + + + + + + 'pack' + Primitive.UpdateObjectFlags(ObjectFlagUpdatePacket):Void + + + + + + + + + 'addPacket' + Primitive.UpdateShape(ObjectDataBlock):Void + + + + + + + + + + + + + ScriptEngine.ScriptEngine(World) + env + env + + + + + env + ScriptEngine.ScriptEngine(World) + + + + + + + + + ScriptEngine.LoadScript():Void + + + + + + + + + + + + + HeightMap + + + + + + + + + + + World + OpenSim.world + + + + + + + + + World.World() + _localNumber + System.UInt32 + 0 + + + + + + + + + _localNumber + + + + + _localNumber + + + + + + + + + AgentClient + + + + + + + + + AgentClient + + + + + + + + + DeRezPacket + + + + + AgentClient + + + + + World.DeRezObject(DeRezObjectPacket, SimClient):Void + Rez + DeRezPacket + + + + + Rez + World.DeRezObject(DeRezObjectPacket, SimClient):Void + + + + + AgentClient + World.DeRezObject(DeRezObjectPacket, SimClient):Void + + + + + De + World.DeRezObject(DeRezObjectPacket, SimClient):Void + + + + + + + + + Entities + + + + + + + + + RemoteClient + + + + + Prims + World.GetInitialPrims(SimClient):Void + + + + + + + + + LandMap + + + + + + + + + Prims + World.LoadPrimsFromStorage():Void + + + + + + + + + World.LoadStorageDLL(String):Boolean + + + + + + + + + localStorage + + + + + + + + + World.Rand + + + + + + + + + Scripts + + + + + + + + + RemoteClient + + + + + 'RemoteClient' + World.SendLayerData(SimClient):Void + + + 'RemoteClient' + World.SendLayerData(SimClient):Void + + + 'RemoteClient' + World.SendLayerData(SimClient):Void + + + + + + + + + + + + + + + + + IScriptHost.Register(IScript):Boolean + iscript + iscript + + + + + + + + + + + + + + + + + + + OpenSim.Storage.LocalStorageDb4o + + + + + OpenSim.Storage.LocalStorageDb4o + + + + + OpenSim.Storage.LocalStorageDb4o + + + + + + + + + + + + + Db4LocalStorage.Db4LocalStorage() + System.Exception + + + + + + + + + 'receiver' + Db4LocalStorage.LoadPrimitives(ILocalStorageReceiver):Void + + + + + + + + + 'prim' + Db4LocalStorage.StorePrim(PrimData):Void + + + + + + + + + + + UUIDQuery + + + + + + + + + 'prim' + UUIDQuery.Match(PrimData):Boolean + + + + + + + + + + + + + + + + + + + OpenSim.Physics.BasicPhysicsPlugin + + + + + + + + + + OpenSim.Physics.BasicPhysicsPlugin + + + + + + + + + + OpenSim.Physics.BasicPhysicsPlugin + + + + + + + + + + + + + + + + + + BasicActor.flying + + + + + + + + + BasicActor.SetAcceleration(PhysicsVector):Void + accel + accel + + + + + + + + + + + Plugin + OpenSim.Physics.BasicPhysicsPlugin.BasicPhysicsPlugin + + + + + BasicPhysicsPlugin + OpenSim.Physics.BasicPhysicsPlugin + + + + + + + + + + + + + + + + + OpenSim.Physics.OdePlugin + + + + + OpenSim.Physics.OdePlugin + + + + + OpenSim.Physics.OdePlugin + + + + + + + + + + + OdeCharacter + + + + + + + + + parent_scene + OdeCharacter.OdeCharacter(OdeScene, PhysicsVector) + + + + + 'pos' + OdeCharacter.OdeCharacter(OdeScene, PhysicsVector) + + + + + + + + + OdeCharacter.capsule_geom + + + + + + + + + OdeCharacter.gravityAccel + + + + + + + + + OdeCharacter.SetAcceleration(PhysicsVector):Void + accel + accel + + + + + + + + + + + Plugin + OpenSim.Physics.OdePlugin.OdePlugin + + + + + OdePlugin + OpenSim.Physics.OdePlugin + + + + + + + + + + + OdePrim._position + + + + + + + + + OdePrim.SetAcceleration(PhysicsVector):Void + accel + accel + + + + + + + + + + + + + 'position' + OdeScene.AddPrim(PhysicsVector, PhysicsVector):PhysicsActor + + + 'size' + OdeScene.AddPrim(PhysicsVector, PhysicsVector):PhysicsActor + + + + + + + + + OdeScene.Land + + + + + + + + + OdeScene.LandGeom + + + + + + + + + 'heightMap' + OdeScene.SetTerrain(Single[]):Void + + + 'heightMap' + OdeScene.SetTerrain(Single[]):Void + + + + + + + + + space + + + + + space + + + + + + + + + world + + + + + world + + + + + + + + + + + + + + + + + + + OpenSim.Physics.PhysXPlugin + + + + + OpenSim.Physics.PhysXPlugin + + + + + OpenSim.Physics.PhysXPlugin + + + + + + + + + + + + + PhysXCharacter.SetAcceleration(PhysicsVector):Void + accel + accel + + + + + + + + + + + Plugin + OpenSim.Physics.PhysXPlugin.PhysXPlugin + + + + + PhysXPlugin + OpenSim.Physics.PhysXPlugin + + + + + + + + + + + PhysXPrim._position + + + + + + + + + PhysXPrim.SetAcceleration(PhysicsVector):Void + accel + accel + + + + + + + + + + + + + + + + Save it for a rainy day. + Save it for a rainy day. + Save it for a rainy day. + + + + + No valid permission requests were found for assembly '{0}'. You should always specify the minimum security permissions using SecurityAction.RequestMinimum. + + + Sign '{0}' with a strong name key. + + + Consider merging the types defined in '{0}' with another namespace. + + + It appears that field '{0}' is never used or is only ever assigned to. Use this field or remove it. + + + Change '{0}' to be read-only by removing the property setter. + + + The compound word '{0}' in {1} '{2}' exists as a discrete term. If your usage is intended to be single word, case it as '{3}'. + + + '{0}' is marked ComVisible(true) but has the following ComVisible(false) types in its object hierarchy: {1} + + + Consider changing the type of parameter '{0}' in {1} from {2} to its base type {3}. This method appears to only require base class members in its implementation. Suppress this violation if there is a compelling reason to require the more derived type in the method signature. + + + '{0}' contains a call chain that results in a call to a virtual method defined by the class. Review the following call stack for unintended consequences: {1} + + + Modify '{0}' to catch a more specific exception than '{1}' or rethrow the exception. + + + Remove the readonly declaration from '{0}' or change the field to one that is an immutable reference type. If the reference type '{1}' is, in fact, immutable, exclude this message. + + + Make '{0}' private or internal (Friend in VB, public private in C++) and provide a public or protected property to access it. + + + Change '{0}' in {1} to use Collection<T>, ReadOnlyCollection<T> or KeyedCollection<K,V> + + + {0} initializes field {1} of type {2} to {3}. Remove this initialization as it will be done automatically by the runtime. + + + {0} passes a literal as parameter {1} of a call to {2}. Retrieve the following string argument from a resource table instead: '{3}' + + + Consider a design that does not require that '{0}' be a reference parameter. + + + {0} creates an exception of type '{1}', an exception type that is not sufficiently specific and should never be raised by user code. If this exception instance might be thrown, use a different exception type. + + + Modify the call to {0} in method {1} to set the timer interval to a value that's greater than or equal to one second. + + + Correct the casing of member name '{0}'. + Correct the casing of namespace name '{0}'. + Correct the casing of parameter name '{0}'. + Correct the casing of type name '{0}'. + + + Correct the spelling of the unrecognized token '{0}' in member name '{1}'. + Consider providing a more meaningful name than the one-letter token '{0}' in member name '{1}'. + Correct the spelling of the unrecognized token '{0}' in namespace '{1}'. + In method {0}, correct the spelling of the unrecognized token '{1}' in parameter name '{2}' or strip it entirely if it represents any sort of hungarian notation. + In method {0}, consider providing a more meaningful name than the one-letter parameter name '{1}'. + Correct the spelling of the unrecognized token '{0}' in type name '{1}'. + + + Change member names {0} and '{1}' so that they differ by more than case. + + + Remove all underscores from member '{0}'. + Remove all underscores from parameter '{0}'. + Remove all underscores from type '{0}'. + + + Rename '{0}' so that it does not end in '{1}'. + + + Correct the spelling of the unrecognized token '{0}' in the literal '{1}'. + + + Correct the capitalization of member name '{0}'. + Correct the capitalization of namespace name '{0}'. + Correct the capitalization of parameter name '{0}'. + Correct the capitalization of type name '{0}'. + + + Add an AssemblyVersion attribute to '{0}'. + + + '{0}' should be marked with CLSCompliantAttribute and its value should be true. + + + Mark '{0}' as ComVisible(false) at the assembly level, then mark all types within the assembly that should be exposed to Com clients as ComVisible(true). + + + The 'this' parameter (or 'Me' in VB) of {0} is never used. Mark the member as static (or Shared in VB) or use 'this'/'Me' in the method body or at least one property accessor, if appropriate. + + + Consider making '{0}' non-public or a constant. + + + Correct the potential overflow in the operation '{0}' in '{1}'. + + + Provide a method named '{0}' as a friendly alternate for operator {1}. + + + Consider adding an overload of the equality operator for '{0}' that takes the same parameters as {1}. + + + '{0}' should override Equals. + '{0}' should override the equality (==) and inequality (!=) operators. + + + Change parameter name '{0}' of method {1} to '{2}' in order to match the identifier as it has been declared in {3}. + + + Modify {0} to call {1} instead of {2}. + + + Make '{0}' private. + + + Add a property getter to '{0}'. + + + {0} declares a local, '{1}', of type {2}, which is never used or is only assigned to. Use this local or remove it. + + + Parameter '{0}' of {1} is never used. Remove the parameter or use it in the method body. + + + Correct the capitalization of '{0}' in member name '{1}'. + 'Id' is an abbreviation and therefore is not subject to acronym casing guidelines. Correct the capitalization of 'ID' in member name '{0}' by changing it to 'Id'. + 'Id' is an abbreviation and therefore is not subject to acronym casing guidelines. Correct the capitalization of '{0}' in parameter name '{1}' by changing it to '{2}'. + Correct the capitalization of '{0}' in type name '{1}'. + + + {0} makes a call to {1} that does not explicitly provide a CultureInfo. This should be replaced with a call to {2}. + + + {0} makes a call to {1} that does not explicitly provide an IFormatProvider. This should be replaced with a call to {2}. + + + Remove the public constructors from '{0}'. + + + Replace the call to String.{0}({1}) in '{2}' with a call to String.IsNullOrEmpty. + + + The type name '{0}' conflicts in whole or in part with the namespace name '{1}'. Change either name to eliminate the conflict. + + + Implement IDisposable on '{0}' as it instantiates members of the following IDisposable types: {1} + + + Implement IDisposable on '{0}'. + + + Change the type of parameter '{0}' of method {1} from string to System.Uri, or provide an overload of {1}, that allows '{0}' to be passed as a System.Uri object. + + + Replace the term '{0}' in member name '{1}' with the preferred alternate '{2}'. + Replace the term '{0}' in type name '{1}' with the preferred alternate '{2}'. + + + Change '{0}' to a property if appropriate. + + + Validate parameter {0} passed to externally visible method {1}. + + + + diff --git a/trunk/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs b/trunk/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs new file mode 100644 index 0000000000..ff8802121e --- /dev/null +++ b/trunk/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs @@ -0,0 +1,108 @@ +/* +* 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 Mono.Addins; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.RegionLoader.Filesystem; +using OpenSim.Framework.RegionLoader.Web; + +[assembly : Addin] +[assembly : AddinDependency("OpenSim", "0.5")] + +namespace OpenSim.ApplicationPlugins.LoadRegions +{ + [Extension("/OpenSim/Startup")] + public class LoadRegionsPlugin : IApplicationPlugin + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public void Initialise(OpenSimMain openSim) + { + m_log.Info("[LOADREGIONS]: Load Regions addin being initialised"); + + IRegionLoader regionLoader; + if (openSim.ConfigSource.Configs["Startup"].GetString("region_info_source", "filesystem") == "filesystem") + { + m_log.Info("[LOADREGIONS]: Loading Region Info from filesystem"); + regionLoader = new RegionLoaderFileSystem(); + } + else + { + m_log.Info("[LOADREGIONSPLUGIN]: Loading Region Info from web"); + regionLoader = new RegionLoaderWebServer(); + } + + regionLoader.SetIniConfigSource(openSim.ConfigSource); + RegionInfo[] regionsToLoad = regionLoader.LoadRegions(); + + openSim.ModuleLoader.LoadDefaultSharedModules(); + + for (int i = 0; i < regionsToLoad.Length; i++) + { + m_log.Debug("[LOADREGIONS]: Creating Region: " + regionsToLoad[i].RegionName + " (ThreadID: " + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + ")"); + openSim.CreateRegion(regionsToLoad[i]); + } + + openSim.ModuleLoader.PostInitialise(); + openSim.ModuleLoader.ClearCache(); + } + + public void LoadRegionFromConfig(OpenSimMain openSim, ulong regionhandle) + { + m_log.Info("[LOADREGIONS]: Load Regions addin being initialised"); + + IRegionLoader regionLoader; + if (openSim.ConfigSource.Configs["Startup"].GetString("region_info_source", "filesystem") == "filesystem") + { + m_log.Info("[LOADREGIONS]: Loading Region Info from filesystem"); + regionLoader = new RegionLoaderFileSystem(); + } + else + { + m_log.Info("[LOADREGIONS]: Loading Region Info from web"); + regionLoader = new RegionLoaderWebServer(); + } + + regionLoader.SetIniConfigSource(openSim.ConfigSource); + RegionInfo[] regionsToLoad = regionLoader.LoadRegions(); + for (int i = 0; i < regionsToLoad.Length; i++) + { + if (regionhandle == regionsToLoad[i].RegionHandle) + { + m_log.Debug("[LOADREGIONS]: Creating Region: " + regionsToLoad[i].RegionName + " (ThreadID: " + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + ")"); + openSim.CreateRegion(regionsToLoad[i]); + } + } + } + + public void Close() + { + } + } +} diff --git a/trunk/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs b/trunk/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..9476f172eb --- /dev/null +++ b/trunk/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs @@ -0,0 +1,67 @@ +/* +* 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.Addin")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Addin")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("45b979d9-d8d4-42fd-9780-fe9ac7e86cb4")] + +// 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("1.0.*")] + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] diff --git a/trunk/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/trunk/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs new file mode 100644 index 0000000000..a6d508939a --- /dev/null +++ b/trunk/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -0,0 +1,391 @@ +/* +* 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; +using System.Collections; +using System.Net; +using System.Timers; +using libsecondlife; +using Mono.Addins; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Region.Environment.Scenes; + +[assembly : Addin] +[assembly : AddinDependency("OpenSim", "0.5")] + +namespace OpenSim.ApplicationPlugins.LoadRegions +{ + [Extension("/OpenSim/Startup")] + public class RemoteAdminPlugin : IApplicationPlugin + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private OpenSimMain m_app; + private BaseHttpServer m_httpd; + private string requiredPassword = String.Empty; + + public void Initialise(OpenSimMain openSim) + { + try + { + if (openSim.ConfigSource.Configs["RemoteAdmin"].GetBoolean("enabled", false)) + { + m_log.Info("[RADMIN]: Remote Admin Plugin Enabled"); + requiredPassword = openSim.ConfigSource.Configs["RemoteAdmin"].GetString("access_password", String.Empty); + + m_app = openSim; + m_httpd = openSim.HttpServer; + + m_httpd.AddXmlRPCHandler("admin_create_region", XmlRpcCreateRegionMethod); + m_httpd.AddXmlRPCHandler("admin_shutdown", XmlRpcShutdownMethod); + m_httpd.AddXmlRPCHandler("admin_broadcast", XmlRpcAlertMethod); + m_httpd.AddXmlRPCHandler("admin_restart", XmlRpcRestartMethod); + m_httpd.AddXmlRPCHandler("admin_load_heightmap", XmlRpcLoadHeightmapMethod); + m_httpd.AddXmlRPCHandler("admin_create_user", XmlRpcCreateUserMethod); + m_httpd.AddXmlRPCHandler("admin_load_xml", XmlRpcLoadXMLMethod); + } + } + catch (NullReferenceException) + { + // Ignore. + } + } + + public XmlRpcResponse XmlRpcRestartMethod(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable) request.Params[0]; + + LLUUID regionID = new LLUUID((string) requestData["regionID"]); + + Hashtable responseData = new Hashtable(); + if (requiredPassword != String.Empty && + (!requestData.Contains("password") || (string) requestData["password"] != requiredPassword)) + { + responseData["accepted"] = "false"; + response.Value = responseData; + } + else + { + responseData["accepted"] = "true"; + response.Value = responseData; + + Scene RebootedScene; + + if (m_app.SceneManager.TryGetScene(regionID, out RebootedScene)) + { + responseData["rebooting"] = "true"; + RebootedScene.Restart(30); + } + else + { + responseData["rebooting"] = "false"; + } + } + + return response; + } + + public XmlRpcResponse XmlRpcAlertMethod(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable) request.Params[0]; + + Hashtable responseData = new Hashtable(); + if (requiredPassword != String.Empty && + (!requestData.Contains("password") || (string) requestData["password"] != requiredPassword)) + { + responseData["accepted"] = "false"; + response.Value = responseData; + } + else + { + string message = (string) requestData["message"]; + m_log.Info("[RADMIN]: Broadcasting: " + message); + + responseData["accepted"] = "true"; + response.Value = responseData; + + m_app.SceneManager.SendGeneralMessage(message); + } + + return response; + } + + public XmlRpcResponse XmlRpcLoadHeightmapMethod(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + + Hashtable responseData = new Hashtable(); + if (requiredPassword != String.Empty && + (!requestData.Contains("password") || (string)requestData["password"] != requiredPassword)) + { + responseData["accepted"] = "false"; + response.Value = responseData; + } + else + { + string file = (string)requestData["filename"]; + LLUUID regionID = LLUUID.Parse((string)requestData["regionid"]); + m_log.Info("[RADMIN]: Terrain Loading: " + file); + + responseData["accepted"] = "true"; + + Scene region = null; + + if (m_app.SceneManager.TryGetScene(regionID, out region)) + { + region.LoadWorldMap(file); + responseData["success"] = "true"; + } + else + { + responseData["success"] = "false"; + responseData["error"] = "1: Unable to get a scene with that name."; + } + response.Value = responseData; + } + + return response; + } + + public XmlRpcResponse XmlRpcShutdownMethod(XmlRpcRequest request) + { + m_log.Info("[RADMIN]: Received Shutdown Administrator Request"); + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable) request.Params[0]; + Hashtable responseData = new Hashtable(); + if (requiredPassword != String.Empty && + (!requestData.Contains("password") || (string) requestData["password"] != requiredPassword)) + { + responseData["accepted"] = "false"; + response.Value = responseData; + } + else + { + if ((string) requestData["shutdown"] == "delayed") + { + int timeout = (Int32) requestData["milliseconds"]; + + responseData["accepted"] = "true"; + response.Value = responseData; + + m_app.SceneManager.SendGeneralMessage("Region is going down in " + ((int) (timeout/1000)).ToString() + + " second(s). Please save what you are doing and log out."); + + // Perform shutdown + Timer shutdownTimer = new Timer(timeout); // Wait before firing + shutdownTimer.AutoReset = false; + shutdownTimer.Elapsed += new ElapsedEventHandler(shutdownTimer_Elapsed); + shutdownTimer.Start(); + + return response; + } + else + { + responseData["accepted"] = "true"; + response.Value = responseData; + + m_app.SceneManager.SendGeneralMessage("Region is going down now."); + + // Perform shutdown + Timer shutdownTimer = new Timer(2000); // Wait 2 seconds before firing + shutdownTimer.AutoReset = false; + shutdownTimer.Elapsed += new ElapsedEventHandler(shutdownTimer_Elapsed); + shutdownTimer.Start(); + + return response; + } + } + return response; + } + + private void shutdownTimer_Elapsed(object sender, ElapsedEventArgs e) + { + m_app.Shutdown(); + } + + public XmlRpcResponse XmlRpcCreateRegionMethod(XmlRpcRequest request) + { + m_log.Info("[RADMIN]: Received Create Region Administrator Request"); + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable) request.Params[0]; + Hashtable responseData = new Hashtable(); + if (requiredPassword != System.String.Empty && + (!requestData.Contains("password") || (string) requestData["password"] != requiredPassword)) + { + responseData["created"] = "false"; + response.Value = responseData; + } + else + { + RegionInfo newRegionData = new RegionInfo(); + + try + { + newRegionData.RegionID = (string) requestData["region_id"]; + newRegionData.RegionName = (string) requestData["region_name"]; + newRegionData.RegionLocX = Convert.ToUInt32((Int32) requestData["region_x"]); + newRegionData.RegionLocY = Convert.ToUInt32((Int32) requestData["region_y"]); + + // Security risk + newRegionData.DataStore = (string) requestData["datastore"]; + + newRegionData.InternalEndPoint = new IPEndPoint( + IPAddress.Parse((string) requestData["listen_ip"]), 0); + + newRegionData.InternalEndPoint.Port = (Int32) requestData["listen_port"]; + newRegionData.ExternalHostName = (string) requestData["external_address"]; + + newRegionData.MasterAvatarFirstName = (string) requestData["region_master_first"]; + newRegionData.MasterAvatarLastName = (string) requestData["region_master_last"]; + + m_app.CreateRegion(newRegionData); + + responseData["created"] = "true"; + response.Value = responseData; + } + catch (Exception e) + { + responseData["created"] = "false"; + responseData["error"] = e.ToString(); + response.Value = responseData; + } + } + + return response; + } + + public XmlRpcResponse XmlRpcCreateUserMethod(XmlRpcRequest request) + { + m_log.Info("[RADMIN]: Received Create User Administrator Request"); + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable) request.Params[0]; + Hashtable responseData = new Hashtable(); + if (requiredPassword != System.String.Empty && + (!requestData.Contains("password") || (string) requestData["password"] != requiredPassword)) + { + responseData["created"] = "false"; + response.Value = responseData; + } + else + { + try + { + string tempfirstname = (string) requestData["user_firstname"]; + string templastname = (string) requestData["user_lastname"]; + string tempPasswd = (string) requestData["user_password"]; + uint regX = Convert.ToUInt32((Int32) requestData["start_region_x"]); + uint regY = Convert.ToUInt32((Int32) requestData["start_region_y"]); + + LLUUID tempuserID = m_app.CreateUser(tempfirstname, templastname, tempPasswd, regX, regY); + + if (tempuserID == LLUUID.Zero) + { + responseData["created"] = "false"; + responseData["error"] = "Error creating user"; + responseData["avatar_uuid"] = LLUUID.Zero; + response.Value = responseData; + m_log.Error("[RADMIN]: Error creating user (" + tempfirstname + " " + templastname + ") :"); + } + else + { + responseData["created"] = "true"; + responseData["avatar_uuid"] = tempuserID; + response.Value = responseData; + m_log.Info("[RADMIN]: User " + tempfirstname + " " + templastname + " created. Userid " + tempuserID + " assigned."); + } + } + catch (Exception e) + { + responseData["created"] = "false"; + responseData["error"] = e.ToString(); + responseData["avatar_uuid"] = LLUUID.Zero; + response.Value = responseData; + } + } + + return response; + } + + public XmlRpcResponse XmlRpcLoadXMLMethod(XmlRpcRequest request) + { + m_log.Info("[RADMIN]: Received Load XML Administrator Request"); + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable) request.Params[0]; + Hashtable responseData = new Hashtable(); + if (requiredPassword != System.String.Empty && + (!requestData.Contains("password") || (string) requestData["password"] != requiredPassword)) + { + responseData["loaded"] = "false"; + responseData["switched"] = "false"; + response.Value = responseData; + } + else + { + try + { + string region_name = (string) requestData["region_name"]; + string filename = (string) requestData["filename"]; + + if (m_app.SceneManager.TrySetCurrentScene(region_name)) + { + m_log.Info("[RADMIN] Switched to region "+region_name); + responseData["switched"] = "true"; + m_app.SceneManager.LoadCurrentSceneFromXml(filename, true, new LLVector3(0, 0, 0)); + responseData["loaded"] = "true"; + response.Value = responseData; + } + else + { + m_log.Info("[RADMIN] Failed to switch to region "+region_name); + responseData["loaded"] = "false"; + responseData["switched"] = "false"; + response.Value = responseData; + } + } + catch (Exception e) + { + responseData["loaded"] = "false"; + responseData["error"] = e.ToString(); + response.Value = responseData; + } + } + + return response; + } + + public void Close() + { + } + } +} diff --git a/trunk/OpenSim/Framework/ACL.cs b/trunk/OpenSim/Framework/ACL.cs new file mode 100644 index 0000000000..8f9c6e7f48 --- /dev/null +++ b/trunk/OpenSim/Framework/ACL.cs @@ -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 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; +using System.Collections.Generic; + +namespace OpenSim.Framework +{ + // ACL Class + // Modelled after the structure of the Zend ACL Framework Library + // with one key difference - the tree will search for all matching + // permissions rather than just the first. Deny permissions will + // override all others. + + #region ACL Core Class + + /// + /// Access Control List Engine + /// + public class ACL + { + private Dictionary Roles = new Dictionary(); + private Dictionary Resources = new Dictionary(); + + public ACL AddRole(Role role) + { + if (Roles.ContainsKey(role.Name)) + throw new AlreadyContainsRoleException(role); + + Roles.Add(role.Name, role); + + return this; + } + + public ACL AddResource(Resource resource) + { + Resources.Add(resource.Name, resource); + + return this; + } + + public Permission HasPermission(string role, string resource) + { + if (!Roles.ContainsKey(role)) + throw new KeyNotFoundException(); + + if (!Resources.ContainsKey(resource)) + throw new KeyNotFoundException(); + + return Roles[role].RequestPermission(resource); + } + + public ACL GrantPermission(string role, string resource) + { + if (!Roles.ContainsKey(role)) + throw new KeyNotFoundException(); + + if (!Resources.ContainsKey(resource)) + throw new KeyNotFoundException(); + + Roles[role].GivePermission(resource, Permission.Allow); + + return this; + } + + public ACL DenyPermission(string role, string resource) + { + if (!Roles.ContainsKey(role)) + throw new KeyNotFoundException(); + + if (!Resources.ContainsKey(resource)) + throw new KeyNotFoundException(); + + Roles[role].GivePermission(resource, Permission.Deny); + + return this; + } + + public ACL ResetPermission(string role, string resource) + { + if (!Roles.ContainsKey(role)) + throw new KeyNotFoundException(); + + if (!Resources.ContainsKey(resource)) + throw new KeyNotFoundException(); + + Roles[role].GivePermission(resource, Permission.None); + + return this; + } + } + + #endregion + + #region Exceptions + + /// + /// Thrown when an ACL attempts to add a duplicate role. + /// + public class AlreadyContainsRoleException : Exception + { + protected Role m_role; + + public Role ErrorRole + { + get { return m_role; } + } + + public AlreadyContainsRoleException(Role role) + { + m_role = role; + } + + public override string ToString() + { + return "This ACL already contains a role called '" + m_role.Name + "'."; + } + } + + #endregion + + #region Roles and Resources + + /// + /// Does this Role have permission to access a specified Resource? + /// + public enum Permission + { + Deny, + None, + Allow + } ; + + /// + /// A role class, for use with Users or Groups + /// + public class Role + { + private string m_name; + private Role[] m_parents; + private Dictionary m_resources = new Dictionary(); + + public string Name + { + get { return m_name; } + } + + public Permission RequestPermission(string resource) + { + return RequestPermission(resource, Permission.None); + } + + public Permission RequestPermission(string resource, Permission current) + { + // Deny permissions always override any others + if (current == Permission.Deny) + return current; + + Permission temp = Permission.None; + + // Pickup non-None permissions + if (m_resources.ContainsKey(resource) && m_resources[resource] != Permission.None) + temp = m_resources[resource]; + + if (m_parents != null) + { + foreach (Role parent in m_parents) + { + temp = parent.RequestPermission(resource, temp); + } + } + + return temp; + } + + public void GivePermission(string resource, Permission perm) + { + m_resources[resource] = perm; + } + + public Role(string name) + { + m_name = name; + m_parents = null; + } + + public Role(string name, Role[] parents) + { + m_name = name; + m_parents = parents; + } + } + + public class Resource + { + private string m_name; + + public string Name + { + get { return m_name; } + } + + public Resource(string name) + { + m_name = name; + } + } + + #endregion + + #region Tests + + internal class ACLTester + { + public ACLTester() + { + ACL acl = new ACL(); + + Role Guests = new Role("Guests"); + acl.AddRole(Guests); + + Role[] parents = new Role[0]; + parents[0] = Guests; + + Role JoeGuest = new Role("JoeGuest", parents); + acl.AddRole(JoeGuest); + + Resource CanBuild = new Resource("CanBuild"); + acl.AddResource(CanBuild); + + + acl.GrantPermission("Guests", "CanBuild"); + + acl.HasPermission("JoeGuest", "CanBuild"); + } + } + + #endregion +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/AgentCircuitData.cs b/trunk/OpenSim/Framework/AgentCircuitData.cs new file mode 100644 index 0000000000..43ade3635b --- /dev/null +++ b/trunk/OpenSim/Framework/AgentCircuitData.cs @@ -0,0 +1,105 @@ +/* +* 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; +using libsecondlife; + +namespace OpenSim.Framework +{ + public class AgentCircuitData + { + public AgentCircuitData() + { + } + + public AgentCircuitData(sAgentCircuitData cAgent) + { + AgentID = new LLUUID(cAgent.AgentID); + SessionID = new LLUUID(cAgent.SessionID); + SecureSessionID = new LLUUID(cAgent.SecureSessionID); + startpos = new LLVector3(cAgent.startposx, cAgent.startposy, cAgent.startposz); + firstname = cAgent.firstname; + lastname = cAgent.lastname; + circuitcode = cAgent.circuitcode; + child = cAgent.child; + InventoryFolder = new LLUUID(cAgent.InventoryFolder); + BaseFolder = new LLUUID(cAgent.BaseFolder); + CapsPath = cAgent.CapsPath; + } + + public LLUUID AgentID; + public LLUUID SessionID; + public LLUUID SecureSessionID; + public LLVector3 startpos; + public string firstname; + public string lastname; + public uint circuitcode; + public bool child; + public LLUUID InventoryFolder; + public LLUUID BaseFolder; + public string CapsPath = String.Empty; + } + + [Serializable] + public class sAgentCircuitData + { + public sAgentCircuitData() + { + } + + public sAgentCircuitData(AgentCircuitData cAgent) + { + AgentID = cAgent.AgentID.UUID; + SessionID = cAgent.SessionID.UUID; + SecureSessionID = cAgent.SecureSessionID.UUID; + startposx = cAgent.startpos.X; + startposy = cAgent.startpos.Y; + startposz = cAgent.startpos.Z; + firstname = cAgent.firstname; + lastname = cAgent.lastname; + circuitcode = cAgent.circuitcode; + child = cAgent.child; + InventoryFolder = cAgent.InventoryFolder.UUID; + BaseFolder = cAgent.BaseFolder.UUID; + CapsPath = cAgent.CapsPath; + } + + public Guid AgentID; + public Guid SessionID; + public Guid SecureSessionID; + public float startposx; + public float startposy; + public float startposz; + public string firstname; + public string lastname; + public uint circuitcode; + public bool child; + public Guid InventoryFolder; + public Guid BaseFolder; + public string CapsPath = String.Empty; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/AgentCircuitManager.cs b/trunk/OpenSim/Framework/AgentCircuitManager.cs new file mode 100644 index 0000000000..938dce8db9 --- /dev/null +++ b/trunk/OpenSim/Framework/AgentCircuitManager.cs @@ -0,0 +1,127 @@ +/* +* 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.Collections.Generic; +using libsecondlife; + +namespace OpenSim.Framework +{ + public class AgentCircuitManager + { + public Dictionary AgentCircuits = new Dictionary(); + + public AgentCircuitManager() + { + } + + public virtual AuthenticateResponse AuthenticateSession(LLUUID sessionID, LLUUID agentID, uint circuitcode) + { + AgentCircuitData validcircuit = null; + if (AgentCircuits.ContainsKey(circuitcode)) + { + validcircuit = AgentCircuits[circuitcode]; + } + AuthenticateResponse user = new AuthenticateResponse(); + if (validcircuit == null) + { + //don't have this circuit code in our list + user.Authorised = false; + return (user); + } + + if ((sessionID == validcircuit.SessionID) && (agentID == validcircuit.AgentID)) + { + user.Authorised = true; + user.LoginInfo = new Login(); + user.LoginInfo.Agent = agentID; + user.LoginInfo.Session = sessionID; + user.LoginInfo.SecureSession = validcircuit.SecureSessionID; + user.LoginInfo.First = validcircuit.firstname; + user.LoginInfo.Last = validcircuit.lastname; + user.LoginInfo.InventoryFolder = validcircuit.InventoryFolder; + user.LoginInfo.BaseFolder = validcircuit.BaseFolder; + } + else + { + // Invalid + user.Authorised = false; + } + + return (user); + } + + public virtual void AddNewCircuit(uint circuitCode, AgentCircuitData agentData) + { + if (AgentCircuits.ContainsKey(circuitCode)) + { + AgentCircuits[circuitCode] = agentData; + } + else + { + AgentCircuits.Add(circuitCode, agentData); + } + } + + public LLVector3 GetPosition(uint circuitCode) + { + LLVector3 vec = new LLVector3(); + if (AgentCircuits.ContainsKey(circuitCode)) + { + vec = AgentCircuits[circuitCode].startpos; + } + return vec; + } + + public void UpdateAgentData(AgentCircuitData agentData) + { + if (AgentCircuits.ContainsKey((uint) agentData.circuitcode)) + { + AgentCircuits[(uint) agentData.circuitcode].firstname = agentData.firstname; + AgentCircuits[(uint) agentData.circuitcode].lastname = agentData.lastname; + AgentCircuits[(uint) agentData.circuitcode].startpos = agentData.startpos; + // Console.WriteLine("update user start pos is " + agentData.startpos.X + " , " + agentData.startpos.Y + " , " + agentData.startpos.Z); + } + } + + public void UpdateAgentChildStatus(uint circuitcode, bool childstatus) + { + if (AgentCircuits.ContainsKey(circuitcode)) + { + AgentCircuits[circuitcode].child = childstatus; + } + } + + public bool GetAgentChildStatus(uint circuitcode) + { + if (AgentCircuits.ContainsKey(circuitcode)) + { + return AgentCircuits[circuitcode].child; + } + return false; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/AgentInventory.cs b/trunk/OpenSim/Framework/AgentInventory.cs new file mode 100644 index 0000000000..83040a30ef --- /dev/null +++ b/trunk/OpenSim/Framework/AgentInventory.cs @@ -0,0 +1,258 @@ +/* +* 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.Collections.Generic; +using libsecondlife; +using libsecondlife.Packets; + +namespace OpenSim.Framework +{ + public class AgentInventory + { + //Holds the local copy of Inventory info for a agent + public Dictionary InventoryFolders; + public Dictionary InventoryItems; + public InventoryFolder InventoryRoot; + public int LastCached; //maybe used by opensim app, time this was last stored/compared to user server + public LLUUID AgentID; + public AvatarWearable[] Wearables; + + public AgentInventory() + { + InventoryFolders = new Dictionary(); + InventoryItems = new Dictionary(); + Initialise(); + } + + public virtual void Initialise() + { + Wearables = new AvatarWearable[13]; + for (int i = 0; i < 13; i++) + { + Wearables[i] = new AvatarWearable(); + } + } + + public bool CreateNewFolder(LLUUID folderID, ushort type) + { + InventoryFolder Folder = new InventoryFolder(); + Folder.FolderID = folderID; + Folder.OwnerID = AgentID; + Folder.DefaultType = type; + InventoryFolders.Add(Folder.FolderID, Folder); + return (true); + } + + public void CreateRootFolder(LLUUID newAgentID, bool createTextures) + { + AgentID = newAgentID; + InventoryRoot = new InventoryFolder(); + InventoryRoot.FolderID = LLUUID.Random(); + InventoryRoot.ParentID = LLUUID.Zero; + InventoryRoot.Version = 1; + InventoryRoot.DefaultType = 8; + InventoryRoot.OwnerID = AgentID; + InventoryRoot.FolderName = "My Inventory"; + InventoryFolders.Add(InventoryRoot.FolderID, InventoryRoot); + InventoryRoot.OwnerID = AgentID; + if (createTextures) + { + CreateNewFolder(LLUUID.Random(), 0, "Textures", InventoryRoot.FolderID); + } + } + + public bool CreateNewFolder(LLUUID folderID, ushort type, string folderName) + { + InventoryFolder Folder = new InventoryFolder(); + Folder.FolderID = folderID; + Folder.OwnerID = AgentID; + Folder.DefaultType = type; + Folder.FolderName = folderName; + InventoryFolders.Add(Folder.FolderID, Folder); + return (true); + } + + public bool CreateNewFolder(LLUUID folderID, ushort type, string folderName, LLUUID parentID) + { + if (!InventoryFolders.ContainsKey(folderID)) + { + System.Console.WriteLine("creating new folder called " + folderName + " in agents inventory"); + InventoryFolder Folder = new InventoryFolder(); + Folder.FolderID = folderID; + Folder.OwnerID = AgentID; + Folder.DefaultType = type; + Folder.FolderName = folderName; + Folder.ParentID = parentID; + InventoryFolders.Add(Folder.FolderID, Folder); + } + return (true); + } + + public bool HasFolder(LLUUID folderID) + { + if (InventoryFolders.ContainsKey(folderID)) + { + return true; + } + return false; + } + + public LLUUID GetFolderID(string folderName) + { + foreach (InventoryFolder inv in InventoryFolders.Values) + { + if (inv.FolderName == folderName) + { + return inv.FolderID; + } + } + return LLUUID.Zero; + } + + public bool UpdateItemAsset(LLUUID itemID, AssetBase asset) + { + if (InventoryItems.ContainsKey(itemID)) + { + InventoryItem Item = InventoryItems[itemID]; + Item.AssetID = asset.FullID; + System.Console.WriteLine("updated inventory item " + itemID.ToString() + + " so it now is set to asset " + asset.FullID.ToString()); + //TODO need to update the rest of the info + } + return true; + } + + public bool UpdateItemDetails(LLUUID itemID, UpdateInventoryItemPacket.InventoryDataBlock packet) + { + System.Console.WriteLine("updating inventory item details"); + if (InventoryItems.ContainsKey(itemID)) + { + System.Console.WriteLine("changing name to " + Util.FieldToString(packet.Name)); + InventoryItem Item = InventoryItems[itemID]; + Item.Name = Util.FieldToString(packet.Name); + System.Console.WriteLine("updated inventory item " + itemID.ToString()); + //TODO need to update the rest of the info + } + return true; + } + + public LLUUID AddToInventory(LLUUID folderID, AssetBase asset) + { + if (InventoryFolders.ContainsKey(folderID)) + { + LLUUID NewItemID = LLUUID.Random(); + + InventoryItem Item = new InventoryItem(); + Item.FolderID = folderID; + Item.OwnerID = AgentID; + Item.AssetID = asset.FullID; + Item.ItemID = NewItemID; + Item.Type = asset.Type; + Item.Name = asset.Name; + Item.Description = asset.Description; + Item.InvType = asset.InvType; + InventoryItems.Add(Item.ItemID, Item); + InventoryFolder Folder = InventoryFolders[Item.FolderID]; + Folder.Items.Add(Item); + return (Item.ItemID); + } + else + { + return (null); + } + } + + public bool DeleteFromInventory(LLUUID itemID) + { + bool res = false; + if (InventoryItems.ContainsKey(itemID)) + { + InventoryItem item = InventoryItems[itemID]; + InventoryItems.Remove(itemID); + foreach (InventoryFolder fold in InventoryFolders.Values) + { + if (fold.Items.Contains(item)) + { + fold.Items.Remove(item); + break; + } + } + res = true; + } + return res; + } + } + + public class InventoryFolder + { + public List Items; + //public List Subfolders; + public LLUUID FolderID; + public LLUUID OwnerID; + public LLUUID ParentID = LLUUID.Zero; + public string FolderName; + public ushort DefaultType; + public ushort Version; + + public InventoryFolder() + { + Items = new List(); + //Subfolders = new List(); + } + } + + public class InventoryItem + { + public LLUUID FolderID; + public LLUUID OwnerID; + public LLUUID ItemID; + public LLUUID AssetID; + public LLUUID CreatorID; + public sbyte InvType; + public sbyte Type; + public string Name = System.String.Empty; + public string Description; + + public InventoryItem() + { + CreatorID = LLUUID.Zero; + } + + public string ExportString() + { + string typ = "notecard"; + string result = System.String.Empty; + result += "\tinv_object\t0\n\t{\n"; + result += "\t\tobj_id\t%s\n"; + result += "\t\tparent_id\t" + ItemID.ToString() + "\n"; + result += "\t\ttype\t" + typ + "\n"; + result += "\t\tname\t" + Name + "|\n"; + result += "\t}\n"; + return result; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/AssemblyInfo.cs b/trunk/OpenSim/Framework/AssemblyInfo.cs new file mode 100644 index 0000000000..60c9024dfc --- /dev/null +++ b/trunk/OpenSim/Framework/AssemblyInfo.cs @@ -0,0 +1,64 @@ +/* +* 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.FrameWork")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.FrameWork")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("a08e20c7-f191-4137-b1f0-9291408fa521")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] diff --git a/trunk/OpenSim/Framework/AssetBase.cs b/trunk/OpenSim/Framework/AssetBase.cs new file mode 100644 index 0000000000..aa33f63805 --- /dev/null +++ b/trunk/OpenSim/Framework/AssetBase.cs @@ -0,0 +1,55 @@ +/* +* 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; +using libsecondlife; + +namespace OpenSim.Framework +{ + [Serializable] + public class AssetBase + { + public byte[] Data; + public LLUUID FullID; + public sbyte Type; + public sbyte InvType; + public string Name = String.Empty; + public string Description = String.Empty; + public bool Local = false; + public bool Temporary = false; + + public AssetBase() + { + } + + public AssetBase(LLUUID assetId, string name) + { + FullID = assetId; + Name = name; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/AssetConfig.cs b/trunk/OpenSim/Framework/AssetConfig.cs new file mode 100644 index 0000000000..a83981a076 --- /dev/null +++ b/trunk/OpenSim/Framework/AssetConfig.cs @@ -0,0 +1,86 @@ +/* +* 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; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework +{ + /// + /// UserConfig -- For User Server Configuration + /// + public class AssetConfig + { + public string DefaultStartupMsg = String.Empty; + + public string DatabaseProvider = String.Empty; + + public static uint DefaultHttpPort = 8003; + public uint HttpPort = DefaultHttpPort; + + private ConfigurationMember configMember; + + public AssetConfig(string description, string filename) + { + configMember = + new ConfigurationMember(filename, description, loadConfigurationOptions, handleIncomingConfiguration, true); + configMember.performConfigurationRetrieve(); + } + + public void loadConfigurationOptions() + { + configMember.addConfigurationOption("default_startup_message", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "Default Startup Message", "Welcome to OGS", false); + + configMember.addConfigurationOption("database_provider", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "DLL for database provider", "OpenSim.Framework.Data.MySQL.dll", false); + + configMember.addConfigurationOption("http_port", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Http Listener port", DefaultHttpPort.ToString(), false); + } + + public bool handleIncomingConfiguration(string configuration_key, object configuration_result) + { + switch (configuration_key) + { + case "default_startup_message": + DefaultStartupMsg = (string) configuration_result; + break; + case "database_provider": + DatabaseProvider = (string) configuration_result; + break; + case "http_port": + HttpPort = (uint) configuration_result; + break; + } + + return true; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/AssetLandmark.cs b/trunk/OpenSim/Framework/AssetLandmark.cs new file mode 100644 index 0000000000..050b80f27f --- /dev/null +++ b/trunk/OpenSim/Framework/AssetLandmark.cs @@ -0,0 +1,59 @@ +/* +* 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.Text; +using libsecondlife; + +namespace OpenSim.Framework +{ + public class AssetLandmark : AssetBase + { + public int Version; + public LLVector3 Position; + public LLUUID RegionID; + + public AssetLandmark(AssetBase a) + { + Data = a.Data; + FullID = a.FullID; + Type = a.Type; + InvType = a.InvType; + Name = a.Name; + Description = a.Description; + InternData(); + } + + private void InternData() + { + string temp = Encoding.UTF8.GetString(Data).Trim(); + string[] parts = temp.Split('\n'); + int.TryParse(parts[0].Substring(17, 1), out Version); + LLUUID.TryParse(parts[1].Substring(10, 36), out RegionID); + LLVector3.TryParse(parts[2].Substring(11, parts[2].Length - 11), out Position); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/AssetLoader/Filesystem/AssetLoaderFileSystem.cs b/trunk/OpenSim/Framework/AssetLoader/Filesystem/AssetLoaderFileSystem.cs new file mode 100644 index 0000000000..d1f704402d --- /dev/null +++ b/trunk/OpenSim/Framework/AssetLoader/Filesystem/AssetLoaderFileSystem.cs @@ -0,0 +1,164 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Xml; + +using libsecondlife; +using Nini.Config; + +using OpenSim.Framework; +using OpenSim.Framework.Console; + +/// +/// Loads assets from the filesystem location. Not yet a plugin, though it should be. +/// +namespace OpenSim.Framework.AssetLoader.Filesystem +{ + public class AssetLoaderFileSystem : IAssetLoader + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected AssetBase CreateAsset(string assetIdStr, string name, string path, bool isImage) + { + AssetBase asset = new AssetBase( + new LLUUID(assetIdStr), + name + ); + + if (!String.IsNullOrEmpty(path)) + { + m_log.InfoFormat("[ASSETS]: Loading: [{0}][{1}]", name, path); + + LoadAsset(asset, isImage, path); + } + else + { + m_log.InfoFormat("[ASSETS]: Instantiated: [{0}]", name); + } + + return asset; + } + + protected void LoadAsset(AssetBase info, bool image, string path) + { + FileInfo fInfo = new FileInfo(path); + long numBytes = fInfo.Length; + FileStream fStream = new FileStream(path, FileMode.Open, FileAccess.Read); + byte[] idata = new byte[numBytes]; + BinaryReader br = new BinaryReader(fStream); + idata = br.ReadBytes((int) numBytes); + br.Close(); + fStream.Close(); + info.Data = idata; + //info.loaded=true; + } + + public void ForEachDefaultXmlAsset(Action action) + { + string assetSetFilename = Path.Combine(Util.assetsDir(), "AssetSets.xml"); + + ForEachDefaultXmlAsset(assetSetFilename, action); + } + + public void ForEachDefaultXmlAsset(string assetSetFilename, Action action) + { + List assets = new List(); + if (File.Exists(assetSetFilename)) + { + string assetSetPath = "ERROR"; + + try + { + XmlConfigSource source = new XmlConfigSource(assetSetFilename); + + for (int i = 0; i < source.Configs.Count; i++) + { + assetSetPath = source.Configs[i].GetString("file", String.Empty); + + LoadXmlAssetSet(Path.Combine(Util.assetsDir(), assetSetPath), assets); + } + } + catch (XmlException e) + { + m_log.ErrorFormat("[ASSETS]: Error loading {0} : {1}", assetSetPath, e); + } + } + else + { + m_log.Error("[ASSETS]: Asset set control file assets/AssetSets.xml does not exist! No assets loaded."); + } + + assets.ForEach(action); + } + + /// + /// Use the asset set information at path to load assets + /// + /// + /// + protected void LoadXmlAssetSet(string assetSetPath, List assets) + { + m_log.InfoFormat("[ASSETS]: Loading asset set {0}", assetSetPath); + + if (File.Exists(assetSetPath)) + { + try + { + XmlConfigSource source = new XmlConfigSource(assetSetPath); + String dir = Path.GetDirectoryName(assetSetPath); + + for (int i = 0; i < source.Configs.Count; i++) + { + string assetIdStr = source.Configs[i].GetString("assetID", LLUUID.Random().ToString()); + string name = source.Configs[i].GetString("name", String.Empty); + sbyte type = (sbyte) source.Configs[i].GetInt("assetType", 0); + sbyte invType = (sbyte) source.Configs[i].GetInt("inventoryType", 0); + string assetPath = Path.Combine(dir, source.Configs[i].GetString("fileName", String.Empty)); + + AssetBase newAsset = CreateAsset(assetIdStr, name, assetPath, false); + + newAsset.Type = type; + newAsset.InvType = invType; + assets.Add(newAsset); + } + } + catch (XmlException e) + { + m_log.ErrorFormat("[ASSETS]: Error loading {0} : {1}", assetSetPath, e); + } + } + else + { + m_log.ErrorFormat("[ASSETS]: Asset set file {0} does not exist!", assetSetPath); + } + } + } +} diff --git a/trunk/OpenSim/Framework/AssetRequest.cs b/trunk/OpenSim/Framework/AssetRequest.cs new file mode 100644 index 0000000000..c5b7d74dd1 --- /dev/null +++ b/trunk/OpenSim/Framework/AssetRequest.cs @@ -0,0 +1,38 @@ +/* +* 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 libsecondlife; + +namespace OpenSim.Framework +{ + public struct AssetRequest + { + public LLUUID AssetID; + public bool IsTexture; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/AssetStorage.cs b/trunk/OpenSim/Framework/AssetStorage.cs new file mode 100644 index 0000000000..7d6cdf0a5e --- /dev/null +++ b/trunk/OpenSim/Framework/AssetStorage.cs @@ -0,0 +1,48 @@ +/* +* 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 libsecondlife; + +namespace OpenSim.Framework +{ + public class AssetStorage + { + public AssetStorage() + { + } + + public AssetStorage(LLUUID assetUUID) + { + UUID = assetUUID; + } + + public byte[] Data; + public sbyte Type; + public string Name; + public LLUUID UUID; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/AuthenticateResponse.cs b/trunk/OpenSim/Framework/AuthenticateResponse.cs new file mode 100644 index 0000000000..90c9acd863 --- /dev/null +++ b/trunk/OpenSim/Framework/AuthenticateResponse.cs @@ -0,0 +1,39 @@ +/* +* 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. +* +*/ +namespace OpenSim.Framework +{ + public class AuthenticateResponse + { + public bool Authorised; + public Login LoginInfo; + + public AuthenticateResponse() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/AvatarWearable.cs b/trunk/OpenSim/Framework/AvatarWearable.cs new file mode 100644 index 0000000000..c7083f39b9 --- /dev/null +++ b/trunk/OpenSim/Framework/AvatarWearable.cs @@ -0,0 +1,71 @@ +/* +* 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 libsecondlife; + +namespace OpenSim.Framework +{ + public class AvatarWearable + { + public LLUUID AssetID = new LLUUID("00000000-0000-0000-0000-000000000000"); + public LLUUID ItemID = new LLUUID("00000000-0000-0000-0000-000000000000"); + + public AvatarWearable() + { + } + + public AvatarWearable(LLUUID itemId, LLUUID assetId) + { + AssetID = assetId; + ItemID = itemId; + } + + public static AvatarWearable[] DefaultWearables + { + get + { + AvatarWearable[] defaultWearables = new AvatarWearable[13]; //should be 13 of these + for (int i = 0; i < 13; i++) + { + defaultWearables[i] = new AvatarWearable(); + } + defaultWearables[0].AssetID = new LLUUID("66c41e39-38f9-f75a-024e-585989bfab73"); + defaultWearables[0].ItemID = new LLUUID("66c41e39-38f9-f75a-024e-585989bfaba9"); + + defaultWearables[1].ItemID = new LLUUID("77c41e39-38f9-f75a-024e-585989bfabc9"); + defaultWearables[1].AssetID = new LLUUID("77c41e39-38f9-f75a-024e-585989bbabbb"); + + defaultWearables[4].ItemID = new LLUUID("77c41e39-38f9-f75a-0000-585989bf0000"); + defaultWearables[4].AssetID = new LLUUID("00000000-38f9-1111-024e-222222111110"); + + defaultWearables[5].ItemID = new LLUUID("77c41e39-38f9-f75a-0000-5859892f1111"); + defaultWearables[5].AssetID = new LLUUID("00000000-38f9-1111-024e-222222111120"); + return defaultWearables; + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/BlockingQueue.cs b/trunk/OpenSim/Framework/BlockingQueue.cs new file mode 100644 index 0000000000..e72884c013 --- /dev/null +++ b/trunk/OpenSim/Framework/BlockingQueue.cs @@ -0,0 +1,73 @@ +/* +* 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.Collections.Generic; +using System.Threading; + +namespace OpenSim.Framework +{ + public class BlockingQueue + { + private readonly Queue m_queue = new Queue(); + private readonly object m_queueSync = new object(); + + public void Enqueue(T value) + { + lock (m_queueSync) + { + m_queue.Enqueue(value); + Monitor.Pulse(m_queueSync); + } + } + + public T Dequeue() + { + lock (m_queueSync) + { + if (m_queue.Count < 1) + { + Monitor.Wait(m_queueSync); + } + + return m_queue.Dequeue(); + } + } + + public bool Contains(T item) + { + lock (m_queueSync) + { + return m_queue.Contains(item); + } + } + + public int Count() + { + return m_queue.Count; + } + } +} diff --git a/trunk/OpenSim/Framework/ChildAgentDataUpdate.cs b/trunk/OpenSim/Framework/ChildAgentDataUpdate.cs new file mode 100644 index 0000000000..4bb33f99cf --- /dev/null +++ b/trunk/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -0,0 +1,53 @@ +/* +* 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; + +namespace OpenSim.Framework +{ + [Serializable] + public class ChildAgentDataUpdate + { + public ChildAgentDataUpdate() + { + } + + public sLLVector3 Position; + public ulong regionHandle; + public float drawdistance; + public sLLVector3 cameraPosition; + public sLLVector3 Velocity; + public float AVHeight; + public Guid AgentID; + public float godlevel; + public byte[] throttles; + public bool alwaysrun; + public Guid ActiveGroupID; + public uint GroupAccess; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/ClientManager.cs b/trunk/OpenSim/Framework/ClientManager.cs new file mode 100644 index 0000000000..51ebc9b324 --- /dev/null +++ b/trunk/OpenSim/Framework/ClientManager.cs @@ -0,0 +1,182 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using libsecondlife.Packets; + +namespace OpenSim.Framework +{ + public delegate void ForEachClientDelegate(IClientAPI client); + + public class ClientManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private Dictionary m_clients; + + public void ForEachClient(ForEachClientDelegate whatToDo) + { + // Wasteful, I know + IClientAPI[] LocalClients = new IClientAPI[0]; + lock (m_clients) + { + LocalClients = new IClientAPI[m_clients.Count]; + m_clients.Values.CopyTo(LocalClients, 0); + } + + for (int i = 0; i < LocalClients.Length; i++) + { + try + { + whatToDo(LocalClients[i]); + } + catch (System.Exception e) + { + m_log.Warn("[CLIENT]: Unable to do ForEachClient for one of the clients" + "\n Reason: " + e.ToString()); + } + } + } + + public ClientManager() + { + m_clients = new Dictionary(); + } + + public void Remove(uint id) + { + //m_log.InfoFormat("[CLIENT]: Removing client with code {0}, current count {1}", id, m_clients.Count); + m_clients.Remove(id); + m_log.InfoFormat("[CLIENT]: Removed client with code {0}, new client count {1}", id, m_clients.Count); + } + + public void Add(uint id, IClientAPI client) + { + m_clients.Add(id, client); + } + + public void InPacket(uint circuitCode, Packet packet) + { + IClientAPI client; + + if (m_clients.TryGetValue(circuitCode, out client)) + { + client.InPacket(packet); + } + } + + public void CloseAllAgents(uint circuitCode) + { + IClientAPI client; + + if (m_clients.TryGetValue(circuitCode, out client)) + { + CloseAllCircuits(client.AgentId); + } + } + + public void CloseAllCircuits(LLUUID agentId) + { + uint[] circuits = GetAllCircuits(agentId); + // We're using a for loop here so changes to the circuits don't cause it to completely fail. + + for (int i = 0; i < circuits.Length; i++) + { + IClientAPI client; + try + { + + if (m_clients.TryGetValue(circuits[i], out client)) + { + Remove(client.CircuitCode); + client.Close(false); + } + } + catch (System.Exception e) + { + m_log.Error(string.Format("[CLIENT]: Unable to shutdown circuit for: {0}\n Reason: {1}", agentId, e)); + } + } + } + + private uint[] GetAllCircuits(LLUUID agentId) + { + List circuits = new List(); + // Wasteful, I know + IClientAPI[] LocalClients = new IClientAPI[0]; + lock (m_clients) + { + LocalClients = new IClientAPI[m_clients.Count]; + m_clients.Values.CopyTo(LocalClients, 0); + } + + for (int i = 0; i < LocalClients.Length; i++ ) + { + if (LocalClients[i].AgentId == agentId) + { + circuits.Add(LocalClients[i].CircuitCode); + } + } + return circuits.ToArray(); + } + + + public void ViewerEffectHandler(IClientAPI sender, ViewerEffectPacket.EffectBlock[] effectBlock) + { + ViewerEffectPacket packet = (ViewerEffectPacket) PacketPool.Instance.GetPacket(PacketType.ViewerEffect); + // TODO: don't create new blocks if recycling an old packet + packet.Effect = effectBlock; + + // Wasteful, I know + IClientAPI[] LocalClients = new IClientAPI[0]; + lock (m_clients) + { + LocalClients = new IClientAPI[m_clients.Count]; + m_clients.Values.CopyTo(LocalClients, 0); + } + + for (int i = 0; i < LocalClients.Length; i++) + { + if (LocalClients[i].AgentId != sender.AgentId) + { + packet.AgentData.AgentID = LocalClients[i].AgentId; + packet.AgentData.SessionID = LocalClients[i].SessionId; + packet.Header.Reliable = false; + LocalClients[i].OutPacket(packet, ThrottleOutPacketType.Task); + } + + } + } + + public bool TryGetClient(uint circuitId, out IClientAPI user) + { + return m_clients.TryGetValue(circuitId, out user); + } + } +} diff --git a/trunk/OpenSim/Framework/Communications/CAPSService.cs b/trunk/OpenSim/Framework/Communications/CAPSService.cs new file mode 100644 index 0000000000..9cb04a9917 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/CAPSService.cs @@ -0,0 +1,54 @@ +/* +* 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 OpenSim.Framework.Servers; + +namespace OpenSim.Framework.Communications +{ + public class CAPSService + { + private readonly BaseHttpServer m_server; + + public CAPSService(BaseHttpServer httpServer) + { + m_server = httpServer; + AddCapsSeedHandler("/CapsSeed/", CapsRequest); + } + + private void AddCapsSeedHandler(string path, RestMethod restMethod) + { + m_server.AddStreamHandler(new RestStreamHandler("POST", path, restMethod)); + } + + public string CapsRequest(string request, string path, string param) + { + System.Console.WriteLine("new caps request " + request + " from path " + path); + return System.String.Empty; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Cache/AgentAssetTransactions.cs b/trunk/OpenSim/Framework/Communications/Cache/AgentAssetTransactions.cs new file mode 100644 index 0000000000..4aefe833da --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Cache/AgentAssetTransactions.cs @@ -0,0 +1,558 @@ +/* +* 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. +* +*/ +//moved to a module, left here until the module is found to have no problems +/* +using System; +using System.Collections.Generic; +using System.IO; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework.Servers; +using OpenSim.Region.Capabilities; + +namespace OpenSim.Framework.Communications.Cache +{ + /// + /// Manage asset transactions for a single agent. + /// + public class AgentAssetTransactions + { + private static readonly log4net.ILog m_log + = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Fields + public List CapsUploaders = new List(); + public List NotecardUpdaters = new List(); + public LLUUID UserID; + public Dictionary XferUploaders = new Dictionary(); + public AgentAssetTransactionsManager Manager; + private bool m_dumpAssetsToFile; + + // Methods + public AgentAssetTransactions(LLUUID agentID, AgentAssetTransactionsManager manager, bool dumpAssetsToFile) + { + UserID = agentID; + Manager = manager; + m_dumpAssetsToFile = dumpAssetsToFile; + } + + public AssetCapsUploader RequestCapsUploader() + { + AssetCapsUploader uploader = new AssetCapsUploader(); + CapsUploaders.Add(uploader); + return uploader; + } + + public NoteCardCapsUpdate RequestNoteCardUpdater() + { + NoteCardCapsUpdate update = new NoteCardCapsUpdate(); + NotecardUpdaters.Add(update); + return update; + } + + public AssetXferUploader RequestXferUploader(LLUUID transactionID) + { + if (!XferUploaders.ContainsKey(transactionID)) + { + AssetXferUploader uploader = new AssetXferUploader(this, m_dumpAssetsToFile); + + lock (XferUploaders) + { + XferUploaders.Add(transactionID, uploader); + } + + return uploader; + } + return null; + } + + public void HandleXfer(ulong xferID, uint packetID, byte[] data) + { + AssetXferUploader uploaderFound = null; + + lock (XferUploaders) + { + foreach (AssetXferUploader uploader in XferUploaders.Values) + { + if (uploader.XferID == xferID) + { + if (uploader.HandleXferPacket(xferID, packetID, data)) + { + uploaderFound = uploader; + } + + break; + } + } + + // Remove the uploader once the uploader is complete + //[don't think we can be sure a upload has finished from here, uploads are multi part things] + // [or maybe we can if we do more checking like data lenght checks] + if (uploaderFound != null) + { +// m_log.InfoFormat( +// "[ASSET TRANSACTIONS] Removing asset xfer uploader with transfer id {0}, transaction {1}", +// xferID, uploaderFound.TransactionID); + + // XferUploaders.Remove(uploaderFound.TransactionID); + + //m_log.InfoFormat("[ASSET TRANSACTIONS] Current uploaders: {0}", XferUploaders.Count); + } + } + } + + public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + if (XferUploaders.ContainsKey(transactionID)) + { + XferUploaders[transactionID].RequestCreateInventoryItem(remoteClient, transactionID, folderID, + callbackID, description, name, invType, type, + wearableType, nextOwnerMask); + } + } + + public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, + InventoryItemBase item) + { + if (XferUploaders.ContainsKey(transactionID)) + { + XferUploaders[transactionID].RequestUpdateInventoryItem(remoteClient, transactionID, item); + } + } + + /// + /// Get an uploaded asset. If the data is successfully retrieved, the transaction will be removed. + /// + /// + /// The asset if the upload has completed, null if it has not. + public AssetBase GetTransactionAsset(LLUUID transactionID) + { + if (XferUploaders.ContainsKey(transactionID)) + { + AssetXferUploader uploader = XferUploaders[transactionID]; + AssetBase asset = uploader.GetAssetData(); + + lock (XferUploaders) + { + XferUploaders.Remove(transactionID); + } + + return asset; + } + + return null; + } + + // Nested Types + public class AssetXferUploader + { + // Fields + public bool AddToInventory; + public AssetBase Asset; + public LLUUID InventFolder = LLUUID.Zero; + private IClientAPI ourClient; + public LLUUID TransactionID = LLUUID.Zero; + public bool UploadComplete; + public ulong XferID; + private string m_name = String.Empty; + private string m_description = String.Empty; + private sbyte type = 0; + private sbyte invType = 0; + private uint nextPerm = 0; + private bool m_finished = false; + private bool m_createItem = false; + private AgentAssetTransactions m_userTransactions; + private bool m_storeLocal; + private bool m_dumpAssetToFile; + + public AssetXferUploader(AgentAssetTransactions transactions, bool dumpAssetToFile) + { + m_userTransactions = transactions; + m_dumpAssetToFile = dumpAssetToFile; + } + + /// + /// Process transfer data received from the client. + /// + /// + /// + /// + /// True if the transfer is complete, false otherwise or if the xferID was not valid + public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) + { + if (XferID == xferID) + { + if (Asset.Data.Length > 1) + { + byte[] destinationArray = new byte[Asset.Data.Length + data.Length]; + Array.Copy(Asset.Data, 0, destinationArray, 0, Asset.Data.Length); + Array.Copy(data, 0, destinationArray, Asset.Data.Length, data.Length); + Asset.Data = destinationArray; + } + else + { + byte[] buffer2 = new byte[data.Length - 4]; + Array.Copy(data, 4, buffer2, 0, data.Length - 4); + Asset.Data = buffer2; + } + ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket(); + newPack.XferID.ID = xferID; + newPack.XferID.Packet = packetID; + ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); + if ((packetID & 0x80000000) != 0) + { + SendCompleteMessage(); + return true; + } + } + + return false; + } + + /// + /// Initialise asset transfer from the client + /// + /// + /// + /// + /// True if the transfer is complete, false otherwise + public bool Initialise(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data, + bool storeLocal, bool tempFile) + { + ourClient = remoteClient; + Asset = new AssetBase(); + Asset.FullID = assetID; + Asset.InvType = type; + Asset.Type = type; + Asset.Data = data; + Asset.Name = "blank"; + Asset.Description = "empty"; + Asset.Local = storeLocal; + Asset.Temporary = tempFile; + + TransactionID = transaction; + m_storeLocal = storeLocal; + if (Asset.Data.Length > 2) + { + SendCompleteMessage(); + return true; + } + else + { + RequestStartXfer(); + } + + return false; + } + + protected void RequestStartXfer() + { + UploadComplete = false; + XferID = Util.GetNextXferID(); + RequestXferPacket newPack = new RequestXferPacket(); + newPack.XferID.ID = XferID; + newPack.XferID.VFileType = Asset.Type; + newPack.XferID.VFileID = Asset.FullID; + newPack.XferID.FilePath = 0; + newPack.XferID.Filename = new byte[0]; + ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); + } + + protected void SendCompleteMessage() + { + UploadComplete = true; + AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); + newPack.AssetBlock.Type = Asset.Type; + newPack.AssetBlock.Success = true; + newPack.AssetBlock.UUID = Asset.FullID; + ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); + m_finished = true; + if (m_createItem) + { + DoCreateItem(); + } + else if (m_storeLocal) + { + m_userTransactions.Manager.CommsManager.AssetCache.AddAsset(Asset); + } + + // Console.WriteLine("upload complete "+ this.TransactionID); + + if (m_dumpAssetToFile) + { + DateTime now = DateTime.Now; + string filename = + String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", now.Year, now.Month, now.Day, + now.Hour, now.Minute, now.Second, Asset.Name, Asset.Type); + SaveAssetToFile(filename, Asset.Data); + } + } + + ///Left this in and commented in case there are unforseen issues + //private void SaveAssetToFile(string filename, byte[] data) + //{ + // FileStream fs = File.Create(filename); + // BinaryWriter bw = new BinaryWriter(fs); + // bw.Write(data); + // bw.Close(); + // fs.Close(); + //} + private void SaveAssetToFile(string filename, byte[] data) + { + string assetPath = "UserAssets"; + if (!Directory.Exists(assetPath)) + { + Directory.CreateDirectory(assetPath); + } + FileStream fs = File.Create(Path.Combine(assetPath, filename)); + BinaryWriter bw = new BinaryWriter(fs); + bw.Write(data); + bw.Close(); + fs.Close(); + } + + public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + if (TransactionID == transactionID) + { + InventFolder = folderID; + m_name = name; + m_description = description; + this.type = type; + this.invType = invType; + nextPerm = nextOwnerMask; + Asset.Name = name; + Asset.Description = description; + Asset.Type = type; + Asset.InvType = invType; + m_createItem = true; + if (m_finished) + { + DoCreateItem(); + } + } + } + + public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, + InventoryItemBase item) + { + if (TransactionID == transactionID) + { + CachedUserInfo userInfo = + m_userTransactions.Manager.CommsManager.UserProfileCacheService.GetUserDetails( + remoteClient.AgentId); + + if (userInfo != null) + { + LLUUID assetID = LLUUID.Combine(transactionID, remoteClient.SecureSessionId); + + AssetBase asset + = m_userTransactions.Manager.CommsManager.AssetCache.GetAsset( + assetID, (item.assetType == (int) AssetType.Texture ? true : false)); + + if (asset == null) + { + asset = m_userTransactions.GetTransactionAsset(transactionID); + } + + if (asset != null && asset.FullID == assetID) + { + asset.Name = item.inventoryName; + asset.Description = item.inventoryDescription; + asset.InvType = (sbyte) item.invType; + asset.Type = (sbyte) item.assetType; + item.assetID = asset.FullID; + + m_userTransactions.Manager.CommsManager.AssetCache.AddAsset(Asset); + } + + userInfo.UpdateItem(remoteClient.AgentId, item); + } + } + } + + private void DoCreateItem() + { + //really need to fix this call, if lbsa71 saw this he would die. + m_userTransactions.Manager.CommsManager.AssetCache.AddAsset(Asset); + CachedUserInfo userInfo = + m_userTransactions.Manager.CommsManager.UserProfileCacheService.GetUserDetails(ourClient.AgentId); + if (userInfo != null) + { + InventoryItemBase item = new InventoryItemBase(); + item.avatarID = ourClient.AgentId; + item.creatorsID = ourClient.AgentId; + item.inventoryID = LLUUID.Random(); + item.assetID = Asset.FullID; + item.inventoryDescription = m_description; + item.inventoryName = m_name; + item.assetType = type; + item.invType = invType; + item.parentFolderID = InventFolder; + item.inventoryBasePermissions = 2147483647; + item.inventoryCurrentPermissions = 2147483647; + item.inventoryNextPermissions = nextPerm; + + userInfo.AddItem(ourClient.AgentId, item); + ourClient.SendInventoryItemCreateUpdate(item); + } + } + + public AssetBase GetAssetData() + { + if (m_finished) + { + return Asset; + } + return null; + } + } + + #region Nested Classes currently not in use (waiting for them to be enabled) + + public class AssetCapsUploader + { + // Fields + private BaseHttpServer httpListener; + private LLUUID inventoryItemID; + private string m_assetDescription = String.Empty; + private string m_assetName = String.Empty; + private LLUUID m_folderID; + private LLUUID newAssetID; + private bool m_dumpImageToFile; + private string uploaderPath = String.Empty; + + // Events + public event UpLoadedAsset OnUpLoad; + + // Methods + public void Initialise(string assetName, string assetDescription, LLUUID assetID, LLUUID inventoryItem, + LLUUID folderID, string path, BaseHttpServer httpServer, bool dumpImageToFile) + { + m_assetName = assetName; + m_assetDescription = assetDescription; + m_folderID = folderID; + newAssetID = assetID; + inventoryItemID = inventoryItem; + uploaderPath = path; + httpListener = httpServer; + m_dumpImageToFile = dumpImageToFile; + } + + private void SaveImageToFile(string filename, byte[] data) + { + FileStream output = File.Create(filename); + BinaryWriter writer = new BinaryWriter(output); + writer.Write(data); + writer.Close(); + output.Close(); + } + + public string uploaderCaps(byte[] data, string path, string param) + { + LLUUID inventoryItemID = this.inventoryItemID; + string text = String.Empty; + LLSDAssetUploadComplete complete = new LLSDAssetUploadComplete(); + complete.new_asset = newAssetID.ToString(); + complete.new_inventory_item = inventoryItemID; + complete.state = "complete"; + text = LLSDHelpers.SerialiseLLSDReply(complete); + httpListener.RemoveStreamHandler("POST", uploaderPath); + if (m_dumpImageToFile) + { + SaveImageToFile(m_assetName + ".jp2", data); + } + if (OnUpLoad != null) + { + OnUpLoad(m_assetName, "description", newAssetID, inventoryItemID, LLUUID.Zero, data, String.Empty, String.Empty); + } + return text; + } + } + + public class NoteCardCapsUpdate + { + // Fields + private BaseHttpServer httpListener; + private LLUUID inventoryItemID; + private string m_assetName = String.Empty; + private LLUUID newAssetID; + private bool SaveImages = false; + private string uploaderPath = String.Empty; + + // Events + public event UpLoadedAsset OnUpLoad; + + // Methods + public void Initialise(LLUUID inventoryItem, string path, BaseHttpServer httpServer) + { + inventoryItemID = inventoryItem; + uploaderPath = path; + httpListener = httpServer; + newAssetID = LLUUID.Random(); + } + + private void SaveImageToFile(string filename, byte[] data) + { + FileStream output = File.Create(filename); + BinaryWriter writer = new BinaryWriter(output); + writer.Write(data); + writer.Close(); + output.Close(); + } + + public string uploaderCaps(byte[] data, string path, string param) + { + LLUUID inventoryItemID = this.inventoryItemID; + string text = String.Empty; + LLSDAssetUploadComplete complete = new LLSDAssetUploadComplete(); + complete.new_asset = newAssetID.ToString(); + complete.new_inventory_item = inventoryItemID; + complete.state = "complete"; + text = LLSDHelpers.SerialiseLLSDReply(complete); + httpListener.RemoveStreamHandler("POST", uploaderPath); + if (SaveImages) + { + SaveImageToFile(m_assetName + "notecard.txt", data); + } + if (OnUpLoad != null) + { + OnUpLoad(m_assetName, "description", newAssetID, inventoryItemID, LLUUID.Zero, data, String.Empty, String.Empty); + } + return text; + } + } + + #endregion + } +} +*/ \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Cache/AgentAssetTransactionsManager.cs b/trunk/OpenSim/Framework/Communications/Cache/AgentAssetTransactionsManager.cs new file mode 100644 index 0000000000..97b716c87e --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Cache/AgentAssetTransactionsManager.cs @@ -0,0 +1,206 @@ +/* +* 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. +* +*/ + +//moved to a module, left here until the module is found to have no problems +/* +using System; +using System.Collections.Generic; + +using libsecondlife; + +namespace OpenSim.Framework.Communications.Cache +{ + /// + /// Provider handlers for processing asset transactions originating from the agent. This encompasses + /// clothing creation and update as well as asset uploads. + /// + public class AgentAssetTransactionsManager + { + private static readonly log4net.ILog m_log + = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Fields + public CommunicationsManager CommsManager; + + /// + /// Each agent has its own singleton collection of transactions + /// + private Dictionary AgentTransactions = + new Dictionary(); + + /// + /// Should we dump uploaded assets to the filesystem? + /// + private bool m_dumpAssetsToFile; + + public AgentAssetTransactionsManager(CommunicationsManager commsManager, bool dumpAssetsToFile) + { + CommsManager = commsManager; + m_dumpAssetsToFile = dumpAssetsToFile; + } + + /// + /// Get the collection of asset transactions for the given user. If one does not already exist, it + /// is created. + /// + /// + /// + private AgentAssetTransactions GetUserTransactions(LLUUID userID) + { + lock (AgentTransactions) + { + if (!AgentTransactions.ContainsKey(userID)) + { + AgentAssetTransactions transactions + = new AgentAssetTransactions(userID, this, m_dumpAssetsToFile); + AgentTransactions.Add(userID, transactions); + } + + return AgentTransactions[userID]; + } + } + + /// + /// Remove the given agent asset transactions. This should be called when a client is departing + /// from a scene (and hence won't be making any more transactions here). + /// + /// + public void RemoveAgentAssetTransactions(LLUUID userID) + { + m_log.DebugFormat("Removing agent asset transactions structure for agent {0}", userID); + + lock (AgentTransactions) + { + AgentTransactions.Remove(userID); + } + } + + /// + /// Create an inventory item from data that has been received through a transaction. + /// + /// This is called when new clothing or body parts are created. It may also be called in other + /// situations. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + m_log.DebugFormat( + "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name); + + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.RequestCreateInventoryItem( + remoteClient, transactionID, folderID, callbackID, description, + name, invType, type, wearableType, nextOwnerMask); + } + + /// + /// Update an inventory item with data that has been received through a transaction. + /// + /// This is called when clothing or body parts are updated (for instance, with new textures or + /// colours). It may also be called in other situations. + /// + /// + /// + /// + public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID, + InventoryItemBase item) + { + m_log.DebugFormat( + "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", + item.inventoryName); + + AgentAssetTransactions transactions + = CommsManager.TransactionsManager.GetUserTransactions(remoteClient.AgentId); + + transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item); + } + + /// + /// Request that a client (agent) begin an asset transfer. + /// + /// + /// + /// + /// + /// + /// + public void HandleUDPUploadRequest(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, + byte[] data, bool storeLocal, bool tempFile) + { + // Console.WriteLine("asset upload of " + assetID); + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + AgentAssetTransactions.AssetXferUploader uploader = transactions.RequestXferUploader(transaction); + if (uploader != null) + { + // Upload has already compelted uploading... + + if (uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile)) + { + //[commenting out as this removal breaks uploads] + /*lock (transactions.XferUploaders) + { + + // XXX Weak ass way of doing this by directly manipulating this public dictionary, purely temporary + transactions.XferUploaders.Remove(uploader.TransactionID); + + //m_log.InfoFormat("[ASSET TRANSACTIONS] Current uploaders: {0}", transactions.XferUploaders.Count); + }*/ + /* } + } + } + + /// + /// Handle asset transfer data packets received in response to the asset upload request in + /// HandleUDPUploadRequest() + /// + /// + /// + /// + /// + public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) + { + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.HandleXfer(xferID, packetID, data); + } + } +} +*/ \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Cache/AssetCache.cs b/trunk/OpenSim/Framework/Communications/Cache/AssetCache.cs new file mode 100644 index 0000000000..effaa82b5c --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Cache/AssetCache.cs @@ -0,0 +1,696 @@ +/* +* 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; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using libsecondlife.Packets; + +using OpenSim.Framework.Console; +using OpenSim.Framework.Statistics; + +namespace OpenSim.Framework.Communications.Cache +{ + public delegate void AssetRequestCallback(LLUUID assetID, AssetBase asset); + + /// + /// Manages local cache of assets and their sending to viewers. + /// + public class AssetCache : IAssetReceiver + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public Dictionary Assets; + public Dictionary Textures; + + public List AssetRequests; //assets ready to be sent to viewers + public List TextureRequests; //textures ready to be sent + + public Dictionary RequestedAssets; + //Assets requested from the asset server + + public Dictionary RequestedTextures; + //Textures requested from the asset server + + public Dictionary RequestLists; + + private readonly IAssetServer m_assetServer; + + private readonly Thread m_assetCacheThread; + + public void ShowState() + { + m_log.InfoFormat("Assets:{0} Textures:{1} AssetRequests:{2} TextureRequests:{3} RequestedAssets:{4} RequestedTextures:{5} RequestLists:{6}", + Assets.Count, + Textures.Count, + AssetRequests.Count, + TextureRequests.Count, + RequestedAssets.Count, + RequestedTextures.Count, + RequestLists.Count); + + int temporaryImages = 0; + int temporaryAssets = 0; + + long imageBytes = 0; + long assetBytes = 0; + + + + + foreach (TextureImage texture in Textures.Values) + { + if (texture.Temporary) + { + temporaryImages++; + } + + imageBytes += texture.Data.GetLongLength(0); + } + + foreach (AssetInfo asset in Assets.Values) + { + if (asset.Temporary) + { + temporaryAssets++; + } + + assetBytes += asset.Data.GetLongLength(0); + } + + m_log.InfoFormat("Temporary Images: {0} Temporary Assets: {1}", + temporaryImages, + temporaryAssets); + + m_log.InfoFormat("Image data: {0}kb Asset data: {1}kb", + imageBytes/1024, + assetBytes/1024); + + } + + public void Clear() + { + m_log.Info("[ASSETSTORAGE]: Clearing Asset cache"); + Initialize(); + } + + private void Initialize() + { + Assets = new Dictionary(); + Textures = new Dictionary(); + AssetRequests = new List(); //assets ready to be sent to viewers + TextureRequests = new List(); //textures ready to be sent + + RequestedAssets = new Dictionary(); + RequestedTextures = new Dictionary(); + RequestLists = new Dictionary(); + } + + + public AssetCache(IAssetServer assetServer) + { + m_log.Info("[ASSETSTORAGE]: Creating Asset cache"); + Initialize(); + + m_assetServer = assetServer; + m_assetServer.SetReceiver(this); + + + m_assetCacheThread = new Thread(new ThreadStart(RunAssetManager)); + m_assetCacheThread.IsBackground = true; + m_assetCacheThread.Start(); + } + + /// + /// + /// + public void RunAssetManager() + { + while (true) + { + try + { + ProcessAssetQueue(); + Thread.Sleep(500); + } + catch (Exception e) + { + m_log.Error("[ASSETCACHE]: " + e.ToString()); + } + } + } + + /// + /// Only get an asset if we already have it in the cache. + /// + /// + /// + private AssetBase GetCachedAsset(LLUUID assetID) + { + AssetBase asset = null; + if (Textures.ContainsKey(assetID)) + { + asset = Textures[assetID]; + } + else if (Assets.ContainsKey(assetID)) + { + asset = Assets[assetID]; + } + return asset; + } + + public void GetAsset(LLUUID assetID, AssetRequestCallback callback) + { + AssetBase asset = null; + if (Textures.ContainsKey(assetID)) + { + asset = Textures[assetID]; + } + else if (Assets.ContainsKey(assetID)) + { + asset = Assets[assetID]; + } + + if (asset != null) + { + callback(assetID, asset); + } + else + { + NewAssetRequest req = new NewAssetRequest(assetID, callback); + + AssetRequestsList requestList; + + lock (RequestLists) + { + if (RequestLists.TryGetValue(assetID, out requestList)) + { + } + else + { + requestList = new AssetRequestsList(assetID); + RequestLists.Add(assetID, requestList); + } + } + + requestList.Requests.Add(req); + + m_assetServer.RequestAsset(assetID, false); + } + } + + /// + /// Get an asset. If the asset isn't in the cache, a request will be made to the persistent store to + /// load it into the cache. + /// + /// XXX We'll keep polling the cache until we get the asset or we exceed + /// the allowed number of polls. This isn't a very good way of doing things since a single thread + /// is processing inbound packets, so if the asset server is slow, we could block this for up to + /// the timeout period. What we might want to do is register asynchronous callbacks on asset + /// receipt in the same manner as the nascent (but not yet active) TextureDownloadModule. Of course, + /// a timeout before asset receipt usually isn't fatal, the operation will work on the retry when the + /// asset is much more likely to have made it into the cache. + /// + /// + /// + /// null if the asset could not be retrieved + public AssetBase GetAsset(LLUUID assetID, bool isTexture) + { + // I'm not going over 3 seconds since this will be blocking processing of all the other inbound + // packets from the client. + int pollPeriod = 200; + int maxPolls = 15; + + AssetBase asset = GetCachedAsset(assetID); + if (asset != null) + { + return asset; + } + + m_assetServer.RequestAsset(assetID, isTexture); + + do + { + Thread.Sleep(pollPeriod); + + asset = GetCachedAsset(assetID); + if (asset != null) + { + return asset; + } + } while (--maxPolls > 0); + + m_log.WarnFormat("[ASSETCACHE]: Asset {0} was not received before the retrieval timeout was reached", assetID.ToString()); + + return null; + } + + /// + /// Add an asset to both the persistent store and the cache. + /// + /// + public void AddAsset(AssetBase asset) + { + string temporary = asset.Temporary ? "temporary" : String.Empty; + string type = asset.Type == 0 ? "texture" : "asset"; + + string result = "Ignored"; + + if (asset.Type == 0) + { + if (Textures.ContainsKey(asset.FullID)) + { + result = "Duplicate ignored."; + } + else + { + TextureImage textur = new TextureImage(asset); + Textures.Add(textur.FullID, textur); + + if (StatsManager.SimExtraStats != null) + StatsManager.SimExtraStats.AddTexture(textur); + + if (asset.Temporary) + { + result = "Added to cache"; + } + else + { + m_assetServer.StoreAndCommitAsset(asset); + result = "Added to server"; + } + } + } + else + { + if (Assets.ContainsKey(asset.FullID)) + { + result = "Duplicate ignored."; + } + else + { + AssetInfo assetInf = new AssetInfo(asset); + Assets.Add(assetInf.FullID, assetInf); + + if (StatsManager.SimExtraStats != null) + StatsManager.SimExtraStats.AddAsset(assetInf); + + if (asset.Temporary) + { + result = "Added to cache"; + } + else + { + m_assetServer.StoreAndCommitAsset(asset); + result = "Added to server"; + } + } + } + + m_log.InfoFormat("[ASSETCACHE]: Adding {0} {1} [{2}]: {3}.", temporary, type, asset.FullID, result); + } + + public void DeleteAsset(LLUUID assetID) + { + // this.m_assetServer.DeleteAsset(assetID); + + //Todo should delete it from memory too + } + + public AssetBase CopyAsset(LLUUID assetID) + { + AssetBase asset = GetCachedAsset(assetID); + if (asset == null) + return null; + + asset.FullID = LLUUID.Random(); // TODO: check for conflicts + AddAsset(asset); + return asset; + } + + public void AssetReceived(AssetBase asset, bool IsTexture) + { + if (asset.FullID != LLUUID.Zero) // if it is set to zero then the asset wasn't found by the server + { + //check if it is a texture or not + //then add to the correct cache list + //then check for waiting requests for this asset/texture (in the Requested lists) + //and move those requests into the Requests list. + + if (IsTexture) + { + //Console.WriteLine("asset received from asset server"); + + TextureImage image = new TextureImage(asset); + if (!Textures.ContainsKey(image.FullID)) + { + Textures.Add(image.FullID, image); + + if (StatsManager.SimExtraStats != null) + StatsManager.SimExtraStats.AddTexture(image); + + if (RequestedTextures.ContainsKey(image.FullID)) + { + AssetRequest req = RequestedTextures[image.FullID]; + req.ImageInfo = image; + + req.NumPackets = CalculateNumPackets(image.Data); + + RequestedTextures.Remove(image.FullID); + TextureRequests.Add(req); + } + } + } + else + { + AssetInfo assetInf = new AssetInfo(asset); + if (!Assets.ContainsKey(assetInf.FullID)) + { + Assets.Add(assetInf.FullID, assetInf); + + if (StatsManager.SimExtraStats != null) + StatsManager.SimExtraStats.AddAsset(assetInf); + + if (RequestedAssets.ContainsKey(assetInf.FullID)) + { + AssetRequest req = RequestedAssets[assetInf.FullID]; + req.AssetInf = assetInf; + req.NumPackets = CalculateNumPackets(assetInf.Data); + RequestedAssets.Remove(assetInf.FullID); + AssetRequests.Add(req); + } + } + } + + if (RequestLists.ContainsKey(asset.FullID)) + { + AssetRequestsList reqList = RequestLists[asset.FullID]; + foreach (NewAssetRequest req in reqList.Requests) + { + req.Callback(asset.FullID, asset); + } + + lock (RequestLists) + { + RequestLists.Remove(asset.FullID); + reqList.Requests.Clear(); + } + } + } + } + + public void AssetNotFound(LLUUID assetID) + { + //if (this.RequestedTextures.ContainsKey(assetID)) + //{ + // m_log.WarnFormat("[ASSET CACHE]: sending image not found for {0}", assetID); + // AssetRequest req = this.RequestedTextures[assetID]; + // ImageNotInDatabasePacket notFound = new ImageNotInDatabasePacket(); + // notFound.ImageID.ID = assetID; + // req.RequestUser.OutPacket(notFound); + // this.RequestedTextures.Remove(assetID); + //} + //else + //{ + // m_log.ErrorFormat("[ASSET CACHE]: Cound not send image not found for {0}", assetID); + //} + } + + private int CalculateNumPackets(byte[] data) + { + const uint m_maxPacketSize = 600; + int numPackets = 1; + + if (data.LongLength > m_maxPacketSize) + { + // over max number of bytes so split up file + long restData = data.LongLength - m_maxPacketSize; + int restPackets = (int)((restData + m_maxPacketSize - 1) / m_maxPacketSize); + numPackets += restPackets; + } + + return numPackets; + } + + #region Assets + + /// + /// + /// + /// + /// + public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest) + { + LLUUID requestID = null; + byte source = 2; + if (transferRequest.TransferInfo.SourceType == 2) + { + //direct asset request + requestID = new LLUUID(transferRequest.TransferInfo.Params, 0); + } + else if (transferRequest.TransferInfo.SourceType == 3) + { + //inventory asset request + requestID = new LLUUID(transferRequest.TransferInfo.Params, 80); + source = 3; + //Console.WriteLine("asset request " + requestID); + } + //check to see if asset is in local cache, if not we need to request it from asset server. + //Console.WriteLine("asset request " + requestID); + if (!Assets.ContainsKey(requestID)) + { + //not found asset + // so request from asset server + if (!RequestedAssets.ContainsKey(requestID)) + { + AssetRequest request = new AssetRequest(); + request.RequestUser = userInfo; + request.RequestAssetID = requestID; + request.TransferRequestID = transferRequest.TransferInfo.TransferID; + request.AssetRequestSource = source; + request.Params = transferRequest.TransferInfo.Params; + RequestedAssets.Add(requestID, request); + m_assetServer.RequestAsset(requestID, false); + } + return; + } + //it is in our cache + AssetInfo asset = Assets[requestID]; + + // add to the AssetRequests list + AssetRequest req = new AssetRequest(); + req.RequestUser = userInfo; + req.RequestAssetID = requestID; + req.TransferRequestID = transferRequest.TransferInfo.TransferID; + req.AssetRequestSource = source; + req.Params = transferRequest.TransferInfo.Params; + req.AssetInf = asset; + req.NumPackets = CalculateNumPackets(asset.Data); + AssetRequests.Add(req); + } + + /// + /// + /// + private void ProcessAssetQueue() + { + //should move the asset downloading to a module, like has been done with texture downloading + if (AssetRequests.Count == 0) + { + //no requests waiting + return; + } + // if less than 5, do all of them + int num = Math.Min(5, AssetRequests.Count); + + AssetRequest req; + for (int i = 0; i < num; i++) + { + req = (AssetRequest)AssetRequests[i]; + //Console.WriteLine("sending asset " + req.RequestAssetID); + TransferInfoPacket Transfer = new TransferInfoPacket(); + Transfer.TransferInfo.ChannelType = 2; + Transfer.TransferInfo.Status = 0; + Transfer.TransferInfo.TargetType = 0; + if (req.AssetRequestSource == 2) + { + Transfer.TransferInfo.Params = new byte[20]; + Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); + int assType = (int)req.AssetInf.Type; + Array.Copy(Helpers.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4); + } + else if (req.AssetRequestSource == 3) + { + Transfer.TransferInfo.Params = req.Params; + // Transfer.TransferInfo.Params = new byte[100]; + //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16); + //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16); + } + Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length; + Transfer.TransferInfo.TransferID = req.TransferRequestID; + req.RequestUser.OutPacket(Transfer, ThrottleOutPacketType.Asset); + + if (req.NumPackets == 1) + { + TransferPacketPacket TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = 0; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = req.TransferRequestID; + TransferPacket.TransferData.Data = req.AssetInf.Data; + TransferPacket.TransferData.Status = 1; + req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset); + } + else + { + int processedLength = 0; + // libsecondlife hardcodes 1500 as the maximum data chunk size + int maxChunkSize = 1250; + int packetNumber = 0; + + while (processedLength < req.AssetInf.Data.Length) + { + TransferPacketPacket TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = packetNumber; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = req.TransferRequestID; + + int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize); + byte[] chunk = new byte[chunkSize]; + Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length); + + TransferPacket.TransferData.Data = chunk; + + // 0 indicates more packets to come, 1 indicates last packet + if (req.AssetInf.Data.Length - processedLength > maxChunkSize) + { + TransferPacket.TransferData.Status = 0; + } + else + { + TransferPacket.TransferData.Status = 1; + } + + req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset); + + processedLength += chunkSize; + packetNumber++; + } + } + } + + //remove requests that have been completed + for (int i = 0; i < num; i++) + { + AssetRequests.RemoveAt(0); + } + } + + #endregion + + public class AssetRequest + { + public IClientAPI RequestUser; + public LLUUID RequestAssetID; + public AssetInfo AssetInf; + public TextureImage ImageInfo; + public LLUUID TransferRequestID; + public long DataPointer = 0; + public int NumPackets = 0; + public int PacketCounter = 0; + public bool IsTextureRequest; + public byte AssetRequestSource = 2; + public byte[] Params = null; + //public bool AssetInCache; + //public int TimeRequested; + public int DiscardLevel = -1; + + public AssetRequest() + { + } + } + + public class AssetInfo : AssetBase + { + public AssetInfo() + { + } + + public AssetInfo(AssetBase aBase) + { + Data = aBase.Data; + FullID = aBase.FullID; + Type = aBase.Type; + InvType = aBase.InvType; + Name = aBase.Name; + Description = aBase.Description; + } + } + + public class TextureImage : AssetBase + { + public TextureImage() + { + } + + public TextureImage(AssetBase aBase) + { + Data = aBase.Data; + FullID = aBase.FullID; + Type = aBase.Type; + InvType = aBase.InvType; + Name = aBase.Name; + Description = aBase.Description; + } + } + + + public class AssetRequestsList + { + public LLUUID AssetID; + public List Requests = new List(); + + public AssetRequestsList(LLUUID assetID) + { + AssetID = assetID; + } + } + + public class NewAssetRequest + { + public LLUUID AssetID; + public AssetRequestCallback Callback; + + public NewAssetRequest(LLUUID assetID, AssetRequestCallback callback) + { + AssetID = assetID; + Callback = callback; + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Cache/AssetServer.cs b/trunk/OpenSim/Framework/Communications/Cache/AssetServer.cs new file mode 100644 index 0000000000..c1cf100c67 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Cache/AssetServer.cs @@ -0,0 +1,145 @@ +/* +* 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.IO; +using Db4objects.Db4o; +using Db4objects.Db4o.Query; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Communications.Cache +{ + public class LocalAssetServer : AssetServerBase + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private IObjectContainer db; + + public LocalAssetServer() + { + bool yapfile; + yapfile = File.Exists(Path.Combine(Util.dataDir(), "regionassets.yap")); + + db = Db4oFactory.OpenFile(Path.Combine(Util.dataDir(), "regionassets.yap")); + m_log.Info("[ASSETS]: Db4 Asset database creation"); + + if (!yapfile) + { + SetUpAssetDatabase(); + } + } + + public void CreateAndCommitAsset(AssetBase asset) + { + AssetStorage store = new AssetStorage(); + store.Data = asset.Data; + store.Name = asset.Name; + store.UUID = asset.FullID; + db.Set(store); + db.Commit(); + } + + public override void Close() + { + base.Close(); + + if (db != null) + { + m_log.Info("[ASSETSERVER]: Closing local asset server database"); + db.Close(); + } + } + + protected override AssetBase GetAsset(AssetRequest req) + { + byte[] idata = null; + bool found = false; + AssetStorage foundAsset = null; + IObjectSet result = db.Query(new AssetUUIDQuery(req.AssetID)); + if (result.Count > 0) + { + foundAsset = (AssetStorage) result.Next(); + found = true; + } + + AssetBase asset = new AssetBase(); + if (found) + { + asset.FullID = foundAsset.UUID; + asset.Type = foundAsset.Type; + asset.InvType = foundAsset.Type; + asset.Name = foundAsset.Name; + idata = foundAsset.Data; + asset.Data = idata; + + return asset; + } + else + { + return null; + } + } + + protected override void StoreAsset(AssetBase asset) + { + AssetStorage store = new AssetStorage(); + store.Data = asset.Data; + store.Name = asset.Name; + store.UUID = asset.FullID; + db.Set(store); + + CommitAssets(); + } + + protected override void CommitAssets() + { + db.Commit(); + } + + protected virtual void SetUpAssetDatabase() + { + m_log.Info("[LOCAL ASSET SERVER]: Setting up asset database"); + + base.LoadDefaultAssets(); + } + } + + public class AssetUUIDQuery : Predicate + { + private LLUUID _findID; + + public AssetUUIDQuery(LLUUID find) + { + _findID = find; + } + + public bool Match(AssetStorage asset) + { + return (asset.UUID == _findID); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Cache/AssetServerBase.cs b/trunk/OpenSim/Framework/Communications/Cache/AssetServerBase.cs new file mode 100644 index 0000000000..6820027fcb --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Cache/AssetServerBase.cs @@ -0,0 +1,163 @@ +/* +* 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; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using OpenSim.Framework.Console; +using OpenSim.Framework.AssetLoader.Filesystem; + +namespace OpenSim.Framework.Communications.Cache +{ + public abstract class AssetServerBase : IAssetServer + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected IAssetReceiver m_receiver; + protected BlockingQueue m_assetRequests; + protected Thread m_localAssetServerThread; + protected IAssetProvider m_assetProvider; + protected object m_syncLock = new object(); + + // Temporarily hardcoded - should be a plugin + protected IAssetLoader assetLoader = new AssetLoaderFileSystem(); + + protected abstract void StoreAsset(AssetBase asset); + protected abstract void CommitAssets(); + + /// + /// This method must be implemented by a subclass to retrieve the asset named in the + /// AssetRequest. If the asset is not found, null should be returned. + /// + /// + /// + protected abstract AssetBase GetAsset(AssetRequest req); + + /// + /// Process an asset request. This method will call GetAsset(AssetRequest req) + /// on the subclass. + /// + /// + protected virtual void ProcessRequest(AssetRequest req) + { + AssetBase asset = GetAsset(req); + + if (asset != null) + { + //m_log.InfoFormat("[ASSET]: Asset {0} received from asset server", req.AssetID); + + m_receiver.AssetReceived(asset, req.IsTexture); + } + else + { + m_log.ErrorFormat("[ASSET]: Asset {0} not found by asset server", req.AssetID); + + m_receiver.AssetNotFound(req.AssetID); + } + } + + public virtual void LoadDefaultAssets() + { + m_log.Info("[ASSETSERVER]: Setting up asset database"); + + assetLoader.ForEachDefaultXmlAsset(StoreAsset); + + CommitAssets(); + } + + public AssetServerBase() + { + m_log.Info("[ASSETSERVER]: Starting asset storage system"); + m_assetRequests = new BlockingQueue(); + + m_localAssetServerThread = new Thread(RunRequests); + m_localAssetServerThread.IsBackground = true; + m_localAssetServerThread.Start(); + } + + private void RunRequests() + { + while (true) // Since it's a 'blocking queue' + { + try + { + AssetRequest req = m_assetRequests.Dequeue(); + + ProcessRequest(req); + } + catch (Exception e) + { + m_log.Error("[ASSETSERVER]: " + e.Message); + } + } + } + + public void SetReceiver(IAssetReceiver receiver) + { + m_receiver = receiver; + } + + public void RequestAsset(LLUUID assetID, bool isTexture) + { + AssetRequest req = new AssetRequest(); + req.AssetID = assetID; + req.IsTexture = isTexture; + m_assetRequests.Enqueue(req); + + m_log.InfoFormat("[ASSET]: Added {0} to request queue", assetID); + } + + public virtual void UpdateAsset(AssetBase asset) + { + lock (m_syncLock) + { + m_assetProvider.UpdateAsset(asset); + m_assetProvider.CommitAssets(); + } + } + + public void StoreAndCommitAsset(AssetBase asset) + { + lock (m_syncLock) + { + StoreAsset(asset); + CommitAssets(); + } + } + + public virtual void Close() + { + m_localAssetServerThread.Abort(); + } + + public void SetServerInfo(string ServerUrl, string ServerKey) + { + } + } +} diff --git a/trunk/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs b/trunk/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs new file mode 100644 index 0000000000..1cf95b7989 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs @@ -0,0 +1,133 @@ +/* +* 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 libsecondlife; + +namespace OpenSim.Framework.Communications.Cache +{ + public class CachedUserInfo + { + private readonly CommunicationsManager m_parentCommsManager; + // Fields + public InventoryFolderImpl RootFolder = null; + public UserProfileData UserProfile = null; + + public CachedUserInfo(CommunicationsManager commsManager) + { + m_parentCommsManager = commsManager; + } + + // Methods + public void FolderReceive(LLUUID userID, InventoryFolderImpl folderInfo) + { + if (userID == UserProfile.UUID) + { + if (RootFolder == null) + { + if (folderInfo.parentID == LLUUID.Zero) + { + RootFolder = folderInfo; + } + } + else if (RootFolder.folderID == folderInfo.parentID) + { + if (!RootFolder.SubFolders.ContainsKey(folderInfo.folderID)) + { + RootFolder.SubFolders.Add(folderInfo.folderID, folderInfo); + } + } + else + { + InventoryFolderImpl folder = RootFolder.HasSubFolder(folderInfo.parentID); + if (folder != null) + { + if (!folder.SubFolders.ContainsKey(folderInfo.folderID)) + { + folder.SubFolders.Add(folderInfo.folderID, folderInfo); + } + } + } + } + } + + public void ItemReceive(LLUUID userID, InventoryItemBase itemInfo) + { + if ((userID == UserProfile.UUID) && (RootFolder != null)) + { + if (itemInfo.parentFolderID == RootFolder.folderID) + { + if (!RootFolder.Items.ContainsKey(itemInfo.inventoryID)) + { + RootFolder.Items.Add(itemInfo.inventoryID, itemInfo); + } + } + else + { + InventoryFolderImpl folder = RootFolder.HasSubFolder(itemInfo.parentFolderID); + if (folder != null) + { + if (!folder.Items.ContainsKey(itemInfo.inventoryID)) + { + folder.Items.Add(itemInfo.inventoryID, itemInfo); + } + } + } + } + } + + public void AddItem(LLUUID userID, InventoryItemBase itemInfo) + { + if ((userID == UserProfile.UUID) && (RootFolder != null)) + { + ItemReceive(userID, itemInfo); + m_parentCommsManager.InventoryService.AddNewInventoryItem(userID, itemInfo); + } + } + + public void UpdateItem(LLUUID userID, InventoryItemBase itemInfo) + { + if ((userID == UserProfile.UUID) && (RootFolder != null)) + { + m_parentCommsManager.InventoryService.AddNewInventoryItem(userID, itemInfo); + } + } + + public bool DeleteItem(LLUUID userID, InventoryItemBase item) + { + bool result = false; + if ((userID == UserProfile.UUID) && (RootFolder != null)) + { + result = RootFolder.DeleteItem(item.inventoryID); + if (result) + { + m_parentCommsManager.InventoryService.DeleteInventoryItem(userID, item); + } + } + return result; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Cache/GridAssetClient.cs b/trunk/OpenSim/Framework/Communications/Cache/GridAssetClient.cs new file mode 100644 index 0000000000..8114eb041d --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Cache/GridAssetClient.cs @@ -0,0 +1,125 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.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; +using System.IO; +using System.Xml.Serialization; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; + +namespace OpenSim.Framework.Communications.Cache +{ + public class GridAssetClient : AssetServerBase + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private string _assetServerUrl; + + public GridAssetClient(string serverUrl) + { + _assetServerUrl = serverUrl; + } + + #region IAssetServer Members + + protected override AssetBase GetAsset(AssetRequest req) + { + Stream s = null; + try + { + m_log.DebugFormat("[ASSETCACHE]: Querying for {0}", req.AssetID.ToString()); + + RestClient rc = new RestClient(_assetServerUrl); + rc.AddResourcePath("assets"); + rc.AddResourcePath(req.AssetID.ToString()); + if (req.IsTexture) + rc.AddQueryParameter("texture"); + + rc.RequestMethod = "GET"; + s = rc.Request(); + + if (s.Length > 0) + { + XmlSerializer xs = new XmlSerializer(typeof (AssetBase)); + + return (AssetBase) xs.Deserialize(s); + } + } + catch (Exception e) + { + m_log.Error("[ASSETCACHE]: " + e.Message); + m_log.DebugFormat("[ASSETCACHE]: Getting asset {0}", req.AssetID.ToString()); + m_log.Error("[ASSETCACHE]: " + e.StackTrace); + } + + return null; + } + + + public override void UpdateAsset(AssetBase asset) + { + throw new Exception("The method or operation is not implemented."); + } + + protected override void StoreAsset(AssetBase asset) + { + try + { + // MemoryStream s = new MemoryStream(); + + // XmlSerializer xs = new XmlSerializer(typeof(AssetBase)); + // xs.Serialize(s, asset); + // RestClient rc = new RestClient(_assetServerUrl); + m_log.Info("[ASSET]: Storing asset"); + //rc.AddResourcePath("assets"); + + // rc.RequestMethod = "POST"; + // rc.Request(s); + //m_log.InfoFormat("[ASSET]: Stored {0}", rc); + m_log.Info("[ASSET]: Sending to " + _assetServerUrl + "/assets/"); + RestObjectPoster.BeginPostObject(_assetServerUrl + "/assets/", asset); + + } + catch (Exception e) + { + m_log.Error("[ASSETS]: " + e.Message); + } + } + + protected override void CommitAssets() + { + } + + public override void Close() + { + throw new Exception("The method or operation is not implemented."); + } + + #endregion + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Cache/InventoryFolderImpl.cs b/trunk/OpenSim/Framework/Communications/Cache/InventoryFolderImpl.cs new file mode 100644 index 0000000000..a1e79b22b5 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Cache/InventoryFolderImpl.cs @@ -0,0 +1,156 @@ +/* +* 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.Collections.Generic; +using libsecondlife; + +namespace OpenSim.Framework.Communications.Cache +{ + public class InventoryFolderImpl : InventoryFolderBase + { + // Fields + public Dictionary Items = new Dictionary(); + public Dictionary SubFolders = new Dictionary(); + + // Accessors + public int SubFoldersCount + { + get { return SubFolders.Count; } + } + + // Constructors + public InventoryFolderImpl(InventoryFolderBase folderbase) + { + agentID = folderbase.agentID; + folderID = folderbase.folderID; + name = folderbase.name; + parentID = folderbase.parentID; + type = folderbase.type; + version = folderbase.version; + } + + public InventoryFolderImpl() + { + } + + // Methods + public InventoryFolderImpl CreateNewSubFolder(LLUUID folderID, string folderName, ushort type) + { + if (!SubFolders.ContainsKey(folderID)) + { + InventoryFolderImpl subFold = new InventoryFolderImpl(); + subFold.name = folderName; + subFold.folderID = folderID; + subFold.type = (short) type; + subFold.parentID = this.folderID; + subFold.agentID = agentID; + SubFolders.Add(subFold.folderID, subFold); + return subFold; + } + return null; + } + + public InventoryItemBase HasItem(LLUUID itemID) + { + InventoryItemBase base2 = null; + if (Items.ContainsKey(itemID)) + { + return Items[itemID]; + } + foreach (InventoryFolderImpl folder in SubFolders.Values) + { + base2 = folder.HasItem(itemID); + if (base2 != null) + { + break; + } + } + return base2; + } + + public bool DeleteItem(LLUUID itemID) + { + bool found = false; + if (Items.ContainsKey(itemID)) + { + Items.Remove(itemID); + return true; + } + foreach (InventoryFolderImpl folder in SubFolders.Values) + { + found = folder.DeleteItem(itemID); + if (found == true) + { + break; + } + } + return found; + } + + + public InventoryFolderImpl HasSubFolder(LLUUID folderID) + { + InventoryFolderImpl returnFolder = null; + if (SubFolders.ContainsKey(folderID)) + { + returnFolder = SubFolders[folderID]; + } + else + { + foreach (InventoryFolderImpl folder in SubFolders.Values) + { + returnFolder = folder.HasSubFolder(folderID); + if (returnFolder != null) + { + break; + } + } + } + return returnFolder; + } + + public List RequestListOfItems() + { + List itemList = new List(); + foreach (InventoryItemBase item in Items.Values) + { + itemList.Add(item); + } + return itemList; + } + + public List RequestListOfFolders() + { + List folderList = new List(); + foreach (InventoryFolderBase folder in SubFolders.Values) + { + folderList.Add(folder); + } + return folderList; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Cache/LibraryRootFolder.cs b/trunk/OpenSim/Framework/Communications/Cache/LibraryRootFolder.cs new file mode 100644 index 0000000000..b3d3c7cc5c --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Cache/LibraryRootFolder.cs @@ -0,0 +1,278 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Communications.Cache +{ + /// + /// Basically a hack to give us a Inventory library while we don't have a inventory server + /// once the server is fully implemented then should read the data from that + /// + public class LibraryRootFolder : InventoryFolderImpl + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private LLUUID libOwner = new LLUUID("11111111-1111-0000-0000-000100bba000"); + + /// + /// Holds the root library folder and all its descendents. This is really only used during inventory + /// setup so that we don't have to repeatedly search the tree of library folders. + /// + protected Dictionary libraryFolders + = new Dictionary(); + + public LibraryRootFolder() + { + m_log.Info("[LIBRARY INVENTORY]: Loading library inventory"); + + agentID = libOwner; + folderID = new LLUUID("00000112-000f-0000-0000-000100bba000"); + name = "OpenSim Library"; + parentID = LLUUID.Zero; + type = (short) 8; + version = (ushort) 1; + + libraryFolders.Add(folderID, this); + + LoadLibraries(Path.Combine(Util.inventoryDir(), "Libraries.xml")); + + // CreateLibraryItems(); + } + + /// + /// Hardcoded item creation. Please don't add any more items here - future items should be created + /// in the xml in the bin/inventory folder. + /// + /// + /// Commented the following out due to sending it all through xml, remove this section once this is provin to work stable. + /// + //private void CreateLibraryItems() + //{ + // InventoryItemBase item = + // CreateItem(new LLUUID("66c41e39-38f9-f75a-024e-585989bfaba9"), + // new LLUUID("66c41e39-38f9-f75a-024e-585989bfab73"), "Default Shape", "Default Shape", + // (int) AssetType.Bodypart, (int) InventoryType.Wearable, folderID); + // item.inventoryCurrentPermissions = 0; + // item.inventoryNextPermissions = 0; + // Items.Add(item.inventoryID, item); + + // item = + // CreateItem(new LLUUID("77c41e39-38f9-f75a-024e-585989bfabc9"), + // new LLUUID("77c41e39-38f9-f75a-024e-585989bbabbb"), "Default Skin", "Default Skin", + // (int) AssetType.Bodypart, (int) InventoryType.Wearable, folderID); + // item.inventoryCurrentPermissions = 0; + // item.inventoryNextPermissions = 0; + // Items.Add(item.inventoryID, item); + + // item = + // CreateItem(new LLUUID("77c41e39-38f9-f75a-0000-585989bf0000"), + // new LLUUID("00000000-38f9-1111-024e-222222111110"), "Default Shirt", "Default Shirt", + // (int) AssetType.Clothing, (int) InventoryType.Wearable, folderID); + // item.inventoryCurrentPermissions = 0; + // item.inventoryNextPermissions = 0; + // Items.Add(item.inventoryID, item); + + // item = + // CreateItem(new LLUUID("77c41e39-38f9-f75a-0000-5859892f1111"), + // new LLUUID("00000000-38f9-1111-024e-222222111120"), "Default Pants", "Default Pants", + // (int) AssetType.Clothing, (int) InventoryType.Wearable, folderID); + // item.inventoryCurrentPermissions = 0; + // item.inventoryNextPermissions = 0; + // Items.Add(item.inventoryID, item); + //} + + public InventoryItemBase CreateItem(LLUUID inventoryID, LLUUID assetID, string name, string description, + int assetType, int invType, LLUUID parentFolderID) + { + InventoryItemBase item = new InventoryItemBase(); + item.avatarID = libOwner; + item.creatorsID = libOwner; + item.inventoryID = inventoryID; + item.assetID = assetID; + item.inventoryDescription = description; + item.inventoryName = name; + item.assetType = assetType; + item.invType = invType; + item.parentFolderID = parentFolderID; + item.inventoryBasePermissions = 0x7FFFFFFF; + item.inventoryEveryOnePermissions = 0x7FFFFFFF; + item.inventoryCurrentPermissions = 0x7FFFFFFF; + item.inventoryNextPermissions = 0x7FFFFFFF; + return item; + } + + /// + /// Use the asset set information at path to load assets + /// + /// + /// + protected void LoadLibraries(string librariesControlPath) + { + m_log.InfoFormat( + "[LIBRARY INVENTORY]: Loading libraries control file {0}", librariesControlPath); + + LoadFromFile(librariesControlPath, "Libraries control", ReadLibraryFromConfig); + } + + /// + /// Read a library set from config + /// + /// + protected void ReadLibraryFromConfig(IConfig config) + { + string foldersPath + = Path.Combine( + Util.inventoryDir(), config.GetString("foldersFile", System.String.Empty)); + + LoadFromFile(foldersPath, "Library folders", ReadFolderFromConfig); + + string itemsPath + = Path.Combine( + Util.inventoryDir(), config.GetString("itemsFile", System.String.Empty)); + + LoadFromFile(itemsPath, "Library items", ReadItemFromConfig); + } + + /// + /// Read a library inventory folder from a loaded configuration + /// + /// + private void ReadFolderFromConfig(IConfig config) + { + InventoryFolderImpl folderInfo = new InventoryFolderImpl(); + + folderInfo.folderID = new LLUUID(config.GetString("folderID", folderID.ToString())); + folderInfo.name = config.GetString("name", "unknown"); + folderInfo.parentID = new LLUUID(config.GetString("parentFolderID", folderID.ToString())); + folderInfo.type = (short)config.GetInt("type", 8); + + folderInfo.agentID = libOwner; + folderInfo.version = 1; + + if (libraryFolders.ContainsKey(folderInfo.parentID)) + { + InventoryFolderImpl parentFolder = libraryFolders[folderInfo.parentID]; + + libraryFolders.Add(folderInfo.folderID, folderInfo); + parentFolder.SubFolders.Add(folderInfo.folderID, folderInfo); + +// m_log.InfoFormat("[LIBRARY INVENTORY]: Adding folder {0} ({1})", folderInfo.name, folderInfo.folderID); + } + else + { + m_log.WarnFormat( + "[LIBRARY INVENTORY]: Couldn't add folder {0} ({1}) since parent folder with ID {2} does not exist!", + folderInfo.name, folderInfo.folderID, folderInfo.parentID); + } + } + + /// + /// Read a library inventory item metadata from a loaded configuration + /// + /// + private void ReadItemFromConfig(IConfig config) + { + InventoryItemBase item = new InventoryItemBase(); + item.avatarID = libOwner; + item.creatorsID = libOwner; + item.inventoryID = new LLUUID(config.GetString("inventoryID", folderID.ToString())); + item.assetID = new LLUUID(config.GetString("assetID", LLUUID.Random().ToString())); + item.parentFolderID = new LLUUID(config.GetString("folderID", folderID.ToString())); + item.inventoryDescription = config.GetString("description", System.String.Empty); + item.inventoryName = config.GetString("name", System.String.Empty); + item.assetType = config.GetInt("assetType", 0); + item.invType = config.GetInt("inventoryType", 0); + item.inventoryCurrentPermissions = (uint)config.GetLong("currentPermissions", 0x7FFFFFFF); + item.inventoryNextPermissions = (uint)config.GetLong("nextPermissions", 0x7FFFFFFF); + item.inventoryEveryOnePermissions = (uint)config.GetLong("everyonePermissions", 0x7FFFFFFF); + item.inventoryBasePermissions = (uint)config.GetLong("basePermissions", 0x7FFFFFFF); + + if (libraryFolders.ContainsKey(item.parentFolderID)) + { + InventoryFolderImpl parentFolder = libraryFolders[item.parentFolderID]; + + parentFolder.Items.Add(item.inventoryID, item); + } + else + { + m_log.WarnFormat( + "[LIBRARY INVENTORY]: Couldn't add item {0} ({1}) since parent folder with ID {2} does not exist!", + item.inventoryName, item.inventoryID, item.parentFolderID); + } + } + + private delegate void ConfigAction(IConfig config); + + /// + /// Load the given configuration at a path and perform an action on each Config contained within it + /// + /// + /// + /// + private void LoadFromFile(string path, string fileDescription, ConfigAction action) + { + if (File.Exists(path)) + { + try + { + XmlConfigSource source = new XmlConfigSource(path); + + for (int i = 0; i < source.Configs.Count; i++) + { + action(source.Configs[i]); + } + } + catch (XmlException e) + { + m_log.ErrorFormat("[LIBRARY INVENTORY]: Error loading {0} : {1}", path, e); + } + } + else + { + m_log.ErrorFormat("[LIBRARY INVENTORY]: {0} file {1} does not exist!", fileDescription, path); + } + } + + /// + /// Looks like a simple getter, but is written like this for some consistency with the other Request + /// methods in the superclass + /// + /// + public Dictionary RequestSelfAndDescendentFolders() + { + return libraryFolders; + } + } +} diff --git a/trunk/OpenSim/Framework/Communications/Cache/SQLAssetServer.cs b/trunk/OpenSim/Framework/Communications/Cache/SQLAssetServer.cs new file mode 100644 index 0000000000..d3a283ad67 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Cache/SQLAssetServer.cs @@ -0,0 +1,102 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.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; +using System.Reflection; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Communications.Cache +{ + public class SQLAssetServer : AssetServerBase + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public SQLAssetServer(string pluginName) + { + AddPlugin(pluginName); + } + + public SQLAssetServer(IAssetProvider assetProvider) + { + m_assetProvider = assetProvider; + } + + public void AddPlugin(string FileName) + { + m_log.Info("[SQLAssetServer]: AssetStorage: Attempting to load " + FileName); + Assembly pluginAssembly = Assembly.LoadFrom(FileName); + + foreach (Type pluginType in pluginAssembly.GetTypes()) + { + if (!pluginType.IsAbstract) + { + Type typeInterface = pluginType.GetInterface("IAssetProvider", true); + + if (typeInterface != null) + { + IAssetProvider plug = + (IAssetProvider) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + m_assetProvider = plug; + m_assetProvider.Initialise(); + + m_log.Info("[AssetStorage]: " + + "Added " + m_assetProvider.Name + " " + + m_assetProvider.Version); + } + } + } + } + + public override void Close() + { + base.Close(); + + m_assetProvider.CommitAssets(); + } + + protected override AssetBase GetAsset(AssetRequest req) + { + AssetBase asset; + lock (m_syncLock) + { + asset = m_assetProvider.FetchAsset(req.AssetID); + } + + return asset; + } + + protected override void StoreAsset(AssetBase asset) + { + m_assetProvider.CreateAsset(asset); + } + + protected override void CommitAssets() + { + m_assetProvider.CommitAssets(); + } + } +} diff --git a/trunk/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs b/trunk/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs new file mode 100644 index 0000000000..455f72226d --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs @@ -0,0 +1,308 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Communications.Cache +{ + public class UserProfileCacheService + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Fields + private readonly CommunicationsManager m_parent; + private readonly Dictionary m_userProfiles = new Dictionary(); + + public LibraryRootFolder libraryRoot = new LibraryRootFolder(); + + // Methods + public UserProfileCacheService(CommunicationsManager parent) + { + m_parent = parent; + } + + /// + /// A new user has moved into a region in this instance + /// so get info from servers + /// + /// + public void AddNewUser(LLUUID userID) + { + // Potential fix - Multithreading issue. + lock (m_userProfiles) + { + if (!m_userProfiles.ContainsKey(userID)) + { + CachedUserInfo userInfo = new CachedUserInfo(m_parent); + userInfo.UserProfile = m_parent.UserService.GetUserProfile(userID); + + if (userInfo.UserProfile != null) + { + // The request itself will occur when the agent finishes logging on to the region + // so there's no need to do it here. + //RequestInventoryForUser(userID, userInfo); + m_userProfiles.Add(userID, userInfo); + } + else + { + m_log.ErrorFormat("[USERCACHE]: User profile for user {0} not found", userID); + } + } + } + } + + public void UpdateUserInventory(LLUUID userID) + { + CachedUserInfo userInfo = GetUserDetails(userID); + if (userInfo != null) + { + RequestInventoryForUser(userID, userInfo); + } + } + + public CachedUserInfo GetUserDetails(LLUUID userID) + { + if (m_userProfiles.ContainsKey(userID)) + return m_userProfiles[userID]; + else + return null; + } + + public void HandleCreateInventoryFolder(IClientAPI remoteClient, LLUUID folderID, ushort folderType, + string folderName, LLUUID parentID) + { + CachedUserInfo userProfile; + + if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile)) + { + if (userProfile.RootFolder != null) + { + if (userProfile.RootFolder.folderID == parentID) + { + InventoryFolderImpl createdFolder = + userProfile.RootFolder.CreateNewSubFolder(folderID, folderName, folderType); + + if (createdFolder != null) + { + InventoryFolderBase createdBaseFolder = new InventoryFolderBase(); + createdBaseFolder.agentID = createdFolder.agentID; + createdBaseFolder.folderID = createdFolder.folderID; + createdBaseFolder.name = createdFolder.name; + createdBaseFolder.parentID = createdFolder.parentID; + createdBaseFolder.type = createdFolder.type; + createdBaseFolder.version = createdFolder.version; + m_parent.InventoryService.AddNewInventoryFolder(remoteClient.AgentId, createdBaseFolder); + } + } + else + { + InventoryFolderImpl folder = userProfile.RootFolder.HasSubFolder(parentID); + if (folder != null) + { + folder.CreateNewSubFolder(folderID, folderName, folderType); + } + } + } + } + } + + public void HandleUpdateInventoryFolder(IClientAPI remoteClient, LLUUID folderID, ushort type, string name, + LLUUID parentID) + { + CachedUserInfo userProfile; + + if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile)) + { + if (userProfile.RootFolder != null) + { + InventoryFolderBase baseFolder = new InventoryFolderBase(); + baseFolder.agentID = remoteClient.AgentId; + baseFolder.folderID = folderID; + baseFolder.name = name; + baseFolder.parentID = parentID; + baseFolder.type = (short) type; + baseFolder.version = userProfile.RootFolder.version; + m_parent.InventoryService.AddNewInventoryFolder(remoteClient.AgentId, baseFolder); + } + } + } + + public void HandleMoveInventoryFolder(IClientAPI remoteClient, LLUUID folderID, LLUUID parentID) + { + CachedUserInfo userProfile; + + if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile)) + { + if (userProfile.RootFolder != null) + { + InventoryFolderBase baseFolder = new InventoryFolderBase(); + baseFolder.agentID = remoteClient.AgentId; + baseFolder.folderID = folderID; + baseFolder.parentID = parentID; + m_parent.InventoryService.MoveInventoryFolder(remoteClient.AgentId, baseFolder); + } + } + } + + /// + /// Tell the client about the various child items and folders contained in the requested folder. + /// + /// + /// + /// + /// + /// + /// + public void HandleFetchInventoryDescendents(IClientAPI remoteClient, LLUUID folderID, LLUUID ownerID, + bool fetchFolders, bool fetchItems, int sortOrder) + { + // XXX We're not handling sortOrder yet! + + InventoryFolderImpl fold = null; + if (folderID == libraryRoot.folderID) + { + remoteClient.SendInventoryFolderDetails( + libraryRoot.agentID, libraryRoot.folderID, libraryRoot.RequestListOfItems(), + libraryRoot.RequestListOfFolders(), fetchFolders, fetchItems); + + return; + } + + if ((fold = libraryRoot.HasSubFolder(folderID)) != null) + { + remoteClient.SendInventoryFolderDetails( + libraryRoot.agentID, folderID, fold.RequestListOfItems(), + fold.RequestListOfFolders(), fetchFolders, fetchItems); + + return; + } + + CachedUserInfo userProfile; + if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile)) + { + if (userProfile.RootFolder != null) + { + if (userProfile.RootFolder.folderID == folderID) + { + remoteClient.SendInventoryFolderDetails( + remoteClient.AgentId, folderID, userProfile.RootFolder.RequestListOfItems(), + userProfile.RootFolder.RequestListOfFolders(), + fetchFolders, fetchItems); + + return; + } + else + { + if ((fold = userProfile.RootFolder.HasSubFolder(folderID)) != null) + { + remoteClient.SendInventoryFolderDetails( + remoteClient.AgentId, folderID, fold.RequestListOfItems(), + fold.RequestListOfFolders(), fetchFolders, fetchItems); + + return; + } + } + } + else + { + m_log.ErrorFormat("[INVENTORYCACHE]: Could not find root folder for user {0}", remoteClient.Name); + + return; + } + } + else + { + m_log.ErrorFormat("[INVENTORYCACHE]: " + + "Could not find user profile for {0} for folder {1}", + remoteClient.Name, folderID); + + return; + } + + // If we've reached this point then we couldn't find the folder, even though the client thinks + // it exists + m_log.ErrorFormat("[INVENTORYCACHE]: " + + "Could not find folder {0} for user {1}", + folderID, remoteClient.Name); + } + + public void HandlePurgeInventoryDescendents(IClientAPI remoteClient, LLUUID folderID) + { +// m_log.InfoFormat("[INVENTORYCACHE]: Purging folder {0} for {1} uuid {2}", +// folderID, remoteClient.Name, remoteClient.AgentId); + + CachedUserInfo userProfile; + if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile)) + { + if (userProfile.RootFolder != null) + { + InventoryFolderImpl subFolder = userProfile.RootFolder.HasSubFolder(folderID); + if (subFolder != null) + { + List items = subFolder.RequestListOfItems(); + foreach (InventoryItemBase item in items) + { + userProfile.DeleteItem(remoteClient.AgentId, item); + } + } + } + } + } + + public void HandleFetchInventory(IClientAPI remoteClient, LLUUID itemID, LLUUID ownerID) + { + if (ownerID == libraryRoot.agentID) + { + //Console.WriteLine("request info for library item"); + + return; + } + + CachedUserInfo userProfile; + if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile)) + { + if (userProfile.RootFolder != null) + { + InventoryItemBase item = userProfile.RootFolder.HasItem(itemID); + if (item != null) + { + remoteClient.SendInventoryItemDetails(ownerID, item); + } + } + } + } + + private void RequestInventoryForUser(LLUUID userID, CachedUserInfo userInfo) + { + m_parent.InventoryService.RequestInventoryForUser(userID, userInfo.FolderReceive, userInfo.ItemReceive); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/Caps.cs b/trunk/OpenSim/Framework/Communications/Capabilities/Caps.cs new file mode 100644 index 0000000000..a360dc3ea0 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/Caps.cs @@ -0,0 +1,745 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; + +namespace OpenSim.Region.Capabilities +{ + public delegate void UpLoadedAsset( + string assetName, string description, LLUUID assetID, LLUUID inventoryItem, LLUUID parentFolder, + byte[] data, string inventoryType, string assetType); + + public delegate LLUUID UpdateItem(LLUUID itemID, byte[] data); + + public delegate void UpdateTaskScript(LLUUID itemID, LLUUID primID, bool isScriptRunning, byte[] data); + + public delegate void NewInventoryItem(LLUUID userID, InventoryItemBase item); + + public delegate LLUUID ItemUpdatedCallback(LLUUID userID, LLUUID itemID, byte[] data); + + public delegate void TaskScriptUpdatedCallback(LLUUID userID, LLUUID itemID, LLUUID primID, + bool isScriptRunning, byte[] data); + + public class Caps + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private string m_httpListenerHostName; + private uint m_httpListenPort; + + private string m_capsObjectPath = "00001-"; + private string m_requestPath = "0000/"; + private string m_mapLayerPath = "0001/"; + private string m_newInventory = "0002/"; + //private string m_requestTexture = "0003/"; + private string m_notecardUpdatePath = "0004/"; + private string m_notecardTaskUpdatePath = "0005/"; + + //private string eventQueue = "0100/"; + private BaseHttpServer m_httpListener; + private LLUUID m_agentID; + private AssetCache m_assetCache; + private int m_eventQueueCount = 1; + private Queue m_capsEventQueue = new Queue(); + private bool m_dumpAssetsToFile; + + // These are callbacks which will be setup by the scene so that we can update scene data when we + // receive capability calls + public NewInventoryItem AddNewInventoryItem = null; + public ItemUpdatedCallback ItemUpdatedCall = null; + public TaskScriptUpdatedCallback TaskScriptUpdatedCall = null; + + public Caps(AssetCache assetCache, BaseHttpServer httpServer, string httpListen, uint httpPort, string capsPath, + LLUUID agent, bool dumpAssetsToFile) + { + m_assetCache = assetCache; + m_capsObjectPath = capsPath; + m_httpListener = httpServer; + m_httpListenerHostName = httpListen; + m_httpListenPort = httpPort; + m_agentID = agent; + m_dumpAssetsToFile = dumpAssetsToFile; + } + + /// + /// + /// + public void RegisterHandlers() + { + m_log.Info("[CAPS]: Registering CAPS handlers"); + string capsBase = "/CAPS/" + m_capsObjectPath; + try + { + m_httpListener.AddStreamHandler( + new LLSDStreamhandler("POST", capsBase + m_mapLayerPath, + GetMapLayer)); + m_httpListener.AddStreamHandler( + new LLSDStreamhandler("POST", + capsBase + m_newInventory, + NewAgentInventoryRequest)); + + AddLegacyCapsHandler(m_httpListener, m_requestPath, CapsRequest); + //AddLegacyCapsHandler(m_httpListener, m_requestTexture , RequestTexture); + AddLegacyCapsHandler(m_httpListener, m_notecardUpdatePath, NoteCardAgentInventory); + AddLegacyCapsHandler(m_httpListener, m_notecardTaskUpdatePath, ScriptTaskInventory); + } + catch (Exception e) + { + m_log.Error("[CAPS]: " + e.ToString()); + } + } + + + //[Obsolete("Use BaseHttpServer.AddStreamHandler(new LLSDStreamHandler( LLSDMethod delegate )) instead.")] + //Commented out the obsolete as at this time the first caps request can not use the new Caps method + //as the sent type is a array and not a map and the deserialising doesn't deal properly with arrays. + private void AddLegacyCapsHandler(BaseHttpServer httpListener, string path, RestMethod restMethod) + { + string capsBase = "/CAPS/" + m_capsObjectPath; + httpListener.AddStreamHandler(new RestStreamHandler("POST", capsBase + path, restMethod)); + } + + /// + /// Construct a client response detailing all the capabilities this server can provide. + /// + /// + /// + /// + /// + public string CapsRequest(string request, string path, string param) + { + //Console.WriteLine("caps request " + request); + string result = LLSDHelpers.SerialiseLLSDReply(GetCapabilities()); + return result; + } + + /// + /// Return an LLSDCapsDetails listing all the capabilities this server can provide + /// + /// + protected LLSDCapsDetails GetCapabilities() + { + LLSDCapsDetails caps = new LLSDCapsDetails(); + string capsBaseUrl = "http://" + m_httpListenerHostName + ":" + m_httpListenPort.ToString() + "/CAPS/" + + m_capsObjectPath; + caps.MapLayer = capsBaseUrl + m_mapLayerPath; + // caps.RequestTextureDownload = capsBaseUrl + m_requestTexture; + caps.NewFileAgentInventory = capsBaseUrl + m_newInventory; + caps.UpdateNotecardAgentInventory = capsBaseUrl + m_notecardUpdatePath; + caps.UpdateScriptAgentInventory = capsBaseUrl + m_notecardUpdatePath; + caps.UpdateScriptTaskInventory = capsBaseUrl + m_notecardTaskUpdatePath; + return caps; + } + + /// + /// + /// + /// + /// + public LLSDMapLayerResponse GetMapLayer(LLSDMapRequest mapReq) + { + LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); + mapResponse.LayerData.Array.Add(GetLLSDMapLayerResponse()); + return mapResponse; + } + + /// + /// + /// + /// + protected LLSDMapLayer GetLLSDMapLayerResponse() + { + LLSDMapLayer mapLayer = new LLSDMapLayer(); + mapLayer.Right = 5000; + mapLayer.Top = 5000; + mapLayer.ImageID = new LLUUID("00000000-0000-0000-9999-000000000006"); + return mapLayer; + } + + /// + /// + /// + /// + /// + /// + /// + public string RequestTexture(string request, string path, string param) + { + Console.WriteLine("texture request " + request); + // Needs implementing (added to remove compiler warning) + return String.Empty; + } + + #region EventQueue (Currently not enabled) + + /// + /// + /// + /// + /// + /// + /// + public string ProcessEventQueue(string request, string path, string param) + { + string res = String.Empty; + + if (m_capsEventQueue.Count > 0) + { + lock (m_capsEventQueue) + { + string item = m_capsEventQueue.Dequeue(); + res = item; + } + } + else + { + res = CreateEmptyEventResponse(); + } + return res; + } + + /// + /// + /// + /// + /// + /// + public string CreateEstablishAgentComms(string caps, string ipAddressPort) + { + LLSDCapEvent eventItem = new LLSDCapEvent(); + eventItem.id = m_eventQueueCount; + //should be creating a EstablishAgentComms item, but there isn't a class for it yet + eventItem.events.Array.Add(new LLSDEmpty()); + string res = LLSDHelpers.SerialiseLLSDReply(eventItem); + m_eventQueueCount++; + + m_capsEventQueue.Enqueue(res); + return res; + } + + /// + /// + /// + /// + public string CreateEmptyEventResponse() + { + LLSDCapEvent eventItem = new LLSDCapEvent(); + eventItem.id = m_eventQueueCount; + eventItem.events.Array.Add(new LLSDEmpty()); + string res = LLSDHelpers.SerialiseLLSDReply(eventItem); + m_eventQueueCount++; + return res; + } + + #endregion + + /// + /// Callback for a client request for an upload url for a script task + /// inventory update + /// + /// + /// + /// + /// + public string ScriptTaskInventory(string request, string path, string param) + { + try + { +// m_log.DebugFormat("[CAPS]: request: {0}, path: {1}, param: {2}", request, path, param); + + Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(Helpers.StringToField(request)); + LLSDTaskScriptUpdate llsdUpdateRequest = new LLSDTaskScriptUpdate(); + LLSDHelpers.DeserialiseLLSDMap(hash, llsdUpdateRequest); + + string capsBase = "/CAPS/" + m_capsObjectPath; + string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); + + TaskInventoryScriptUpdater uploader = + new TaskInventoryScriptUpdater( + llsdUpdateRequest.item_id, + llsdUpdateRequest.task_id, + llsdUpdateRequest.is_script_running, + capsBase + uploaderPath, + m_httpListener, + m_dumpAssetsToFile); + uploader.OnUpLoad += TaskScriptUpdated; + + m_httpListener.AddStreamHandler( + new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps)); + string uploaderURL = "http://" + m_httpListenerHostName + ":" + m_httpListenPort.ToString() + capsBase + + uploaderPath; + + LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); + uploadResponse.uploader = uploaderURL; + uploadResponse.state = "upload"; + +// m_log.InfoFormat("[CAPS]: " + +// "ScriptTaskInventory response: {0}", +// LLSDHelpers.SerialiseLLSDReply(uploadResponse))); + + return LLSDHelpers.SerialiseLLSDReply(uploadResponse); + } + catch (Exception e) + { + m_log.Error("[CAPS]: " + e.ToString()); + } + + return null; + } + + /// + /// Callback for a client request for an upload url for a notecard (or script) + /// agent inventory update + /// + /// + /// + /// + /// + public string NoteCardAgentInventory(string request, string path, string param) + { + //libsecondlife.StructuredData.LLSDMap hash = (libsecondlife.StructuredData.LLSDMap)libsecondlife.StructuredData.LLSDParser.DeserializeBinary(Helpers.StringToField(request)); + Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(Helpers.StringToField(request)); + LLSDItemUpdate llsdRequest = new LLSDItemUpdate(); + LLSDHelpers.DeserialiseLLSDMap(hash, llsdRequest); + + string capsBase = "/CAPS/" + m_capsObjectPath; + string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); + + ItemUpdater uploader = + new ItemUpdater(llsdRequest.item_id, capsBase + uploaderPath, m_httpListener, m_dumpAssetsToFile); + uploader.OnUpLoad += ItemUpdated; + + m_httpListener.AddStreamHandler( + new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps)); + string uploaderURL = "http://" + m_httpListenerHostName + ":" + m_httpListenPort.ToString() + capsBase + + uploaderPath; + + LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); + uploadResponse.uploader = uploaderURL; + uploadResponse.state = "upload"; + +// m_log.InfoFormat("[CAPS]: " + +// "NoteCardAgentInventory response: {0}", +// LLSDHelpers.SerialiseLLSDReply(uploadResponse))); + + return LLSDHelpers.SerialiseLLSDReply(uploadResponse); + } + + /// + /// + /// + /// + /// + public LLSDAssetUploadResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest) + { + //Console.WriteLine("asset upload request via CAPS" + llsdRequest.inventory_type +" , "+ llsdRequest.asset_type); + + string assetName = llsdRequest.name; + string assetDes = llsdRequest.description; + string capsBase = "/CAPS/" + m_capsObjectPath; + LLUUID newAsset = LLUUID.Random(); + LLUUID newInvItem = LLUUID.Random(); + LLUUID parentFolder = llsdRequest.folder_id; + string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); + + AssetUploader uploader = + new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, + llsdRequest.asset_type, capsBase + uploaderPath, m_httpListener, m_dumpAssetsToFile); + m_httpListener.AddStreamHandler( + new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps)); + string uploaderURL = "http://" + m_httpListenerHostName + ":" + m_httpListenPort.ToString() + capsBase + + uploaderPath; + + LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); + uploadResponse.uploader = uploaderURL; + uploadResponse.state = "upload"; + uploader.OnUpLoad += UploadCompleteHandler; + return uploadResponse; + } + + /// + /// + /// + /// + /// + /// + public void UploadCompleteHandler(string assetName, string assetDescription, LLUUID assetID, + LLUUID inventoryItem, LLUUID parentFolder, byte[] data, string inventoryType, + string assetType) + { + sbyte assType = 0; + sbyte inType = 0; + + if (inventoryType == "sound") + { + inType = 1; + assType = 1; + } + else if (inventoryType == "animation") + { + inType = 19; + assType = 20; + } + + AssetBase asset; + asset = new AssetBase(); + asset.FullID = assetID; + asset.Type = assType; + asset.InvType = inType; + asset.Name = assetName; + asset.Data = data; + m_assetCache.AddAsset(asset); + + InventoryItemBase item = new InventoryItemBase(); + item.avatarID = m_agentID; + item.creatorsID = m_agentID; + item.inventoryID = inventoryItem; + item.assetID = asset.FullID; + item.inventoryDescription = assetDescription; + item.inventoryName = assetName; + item.assetType = assType; + item.invType = inType; + item.parentFolderID = parentFolder; + item.inventoryCurrentPermissions = 2147483647; + item.inventoryNextPermissions = 2147483647; + + if (AddNewInventoryItem != null) + { + AddNewInventoryItem(m_agentID, item); + } + } + + /// + /// Called when new asset data for an agent inventory item update has been uploaded. + /// + /// Item to update + /// New asset data + /// + public LLUUID ItemUpdated(LLUUID itemID, byte[] data) + { + if (ItemUpdatedCall != null) + { + return ItemUpdatedCall(m_agentID, itemID, data); + } + + return LLUUID.Zero; + } + + /// + /// Called when new asset data for an agent inventory item update has been uploaded. + /// + /// Item to update + /// Prim containing item to update + /// Signals whether the script to update is currently running + /// New asset data + public void TaskScriptUpdated(LLUUID itemID, LLUUID primID, bool isScriptRunning, byte[] data) + { + if (TaskScriptUpdatedCall != null) + { + TaskScriptUpdatedCall(m_agentID, itemID, primID, isScriptRunning, data); + } + } + + public class AssetUploader + { + public event UpLoadedAsset OnUpLoad; + + private string uploaderPath = String.Empty; + private LLUUID newAssetID; + private LLUUID inventoryItemID; + private LLUUID parentFolder; + private BaseHttpServer httpListener; + private bool m_dumpAssetsToFile; + private string m_assetName = String.Empty; + private string m_assetDes = String.Empty; + + private string m_invType = String.Empty; + private string m_assetType = String.Empty; + + public AssetUploader(string assetName, string description, LLUUID assetID, LLUUID inventoryItem, + LLUUID parentFolderID, string invType, string assetType, string path, + BaseHttpServer httpServer, bool dumpAssetsToFile) + { + m_assetName = assetName; + m_assetDes = description; + newAssetID = assetID; + inventoryItemID = inventoryItem; + uploaderPath = path; + httpListener = httpServer; + parentFolder = parentFolderID; + m_assetType = assetType; + m_invType = invType; + m_dumpAssetsToFile = dumpAssetsToFile; + } + + /// + /// + /// + /// + /// + /// + /// + public string uploaderCaps(byte[] data, string path, string param) + { + LLUUID inv = inventoryItemID; + string res = String.Empty; + LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); + uploadComplete.new_asset = newAssetID.ToString(); + uploadComplete.new_inventory_item = inv; + uploadComplete.state = "complete"; + + res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); + + httpListener.RemoveStreamHandler("POST", uploaderPath); + + if (m_dumpAssetsToFile) + { + SaveAssetToFile(m_assetName + ".jp2", data); + } + + if (OnUpLoad != null) + { + OnUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType); + } + + return res; + } + ///Left this in and commented in case there are unforseen issues + //private void SaveAssetToFile(string filename, byte[] data) + //{ + // FileStream fs = File.Create(filename); + // BinaryWriter bw = new BinaryWriter(fs); + // bw.Write(data); + // bw.Close(); + // fs.Close(); + //} + private void SaveAssetToFile(string filename, byte[] data) + { + string assetPath = "UserAssets"; + if (!Directory.Exists(assetPath)) + { + Directory.CreateDirectory(assetPath); + } + FileStream fs = File.Create(Path.Combine(assetPath, filename)); + BinaryWriter bw = new BinaryWriter(fs); + bw.Write(data); + bw.Close(); + fs.Close(); + } + } + + /// + /// This class is a callback invoked when a client sends asset data to + /// an agent inventory notecard update url + /// + public class ItemUpdater + { + public event UpdateItem OnUpLoad; + + private string uploaderPath = String.Empty; + private LLUUID inventoryItemID; + private BaseHttpServer httpListener; + private bool m_dumpAssetToFile; + + public ItemUpdater(LLUUID inventoryItem, string path, BaseHttpServer httpServer, bool dumpAssetToFile) + { + m_dumpAssetToFile = dumpAssetToFile; + + inventoryItemID = inventoryItem; + uploaderPath = path; + httpListener = httpServer; + } + + /// + /// + /// + /// + /// + /// + /// + public string uploaderCaps(byte[] data, string path, string param) + { + LLUUID inv = inventoryItemID; + string res = String.Empty; + LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); + LLUUID assetID = LLUUID.Zero; + + if (OnUpLoad != null) + { + assetID = OnUpLoad(inv, data); + } + + uploadComplete.new_asset = assetID.ToString(); + uploadComplete.new_inventory_item = inv; + uploadComplete.state = "complete"; + + res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); + + httpListener.RemoveStreamHandler("POST", uploaderPath); + + if (m_dumpAssetToFile) + { + SaveAssetToFile("updateditem" + Util.RandomClass.Next(1, 1000) + ".dat", data); + } + + return res; + } + ///Left this in and commented in case there are unforseen issues + //private void SaveAssetToFile(string filename, byte[] data) + //{ + // FileStream fs = File.Create(filename); + // BinaryWriter bw = new BinaryWriter(fs); + // bw.Write(data); + // bw.Close(); + // fs.Close(); + //} + private void SaveAssetToFile(string filename, byte[] data) + { + string assetPath = "UserAssets"; + if (!Directory.Exists(assetPath)) + { + Directory.CreateDirectory(assetPath); + } + FileStream fs = File.Create(Path.Combine(assetPath, filename)); + BinaryWriter bw = new BinaryWriter(fs); + bw.Write(data); + bw.Close(); + fs.Close(); + } + } + + /// + /// This class is a callback invoked when a client sends asset data to + /// a task inventory script update url + /// + public class TaskInventoryScriptUpdater + { + public event UpdateTaskScript OnUpLoad; + + private string uploaderPath = String.Empty; + private LLUUID inventoryItemID; + private LLUUID primID; + private bool isScriptRunning; + private BaseHttpServer httpListener; + private bool m_dumpAssetToFile; + + public TaskInventoryScriptUpdater(LLUUID inventoryItemID, LLUUID primID, int isScriptRunning, + string path, BaseHttpServer httpServer, bool dumpAssetToFile) + { + m_dumpAssetToFile = dumpAssetToFile; + + this.inventoryItemID = inventoryItemID; + this.primID = primID; + + // This comes in over the packet as an integer, but actually appears to be treated as a bool + this.isScriptRunning = (0 == isScriptRunning ? false : true); + + uploaderPath = path; + httpListener = httpServer; + } + + /// + /// + /// + /// + /// + /// + /// + public string uploaderCaps(byte[] data, string path, string param) + { + try + { +// m_log.InfoFormat("[CAPS]: " + +// "TaskInventoryScriptUpdater received data: {0}, path: {1}, param: {2}", +// data, path, param)); + + string res = String.Empty; + LLSDTaskInventoryUploadComplete uploadComplete = new LLSDTaskInventoryUploadComplete(); + + if (OnUpLoad != null) + { + OnUpLoad(inventoryItemID, primID, isScriptRunning, data); + } + + uploadComplete.item_id = inventoryItemID; + uploadComplete.task_id = primID; + uploadComplete.state = "complete"; + + res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); + + httpListener.RemoveStreamHandler("POST", uploaderPath); + + if (m_dumpAssetToFile) + { + SaveAssetToFile("updatedtaskscript" + Util.RandomClass.Next(1, 1000) + ".dat", data); + } + +// m_log.InfoFormat("[CAPS]: TaskInventoryScriptUpdater.uploaderCaps res: {0}", res); + + return res; + } + catch (Exception e) + { + m_log.Error("[CAPS]: " + e.ToString()); + } + + // XXX Maybe this should be some meaningful error packet + return null; + } + ///Left this in and commented in case there are unforseen issues + //private void SaveAssetToFile(string filename, byte[] data) + //{ + // FileStream fs = File.Create(filename); + // BinaryWriter bw = new BinaryWriter(fs); + // bw.Write(data); + // bw.Close(); + // fs.Close(); + //} + private void SaveAssetToFile(string filename, byte[] data) + { + string assetPath = "UserAssets"; + if (!Directory.Exists(assetPath)) + { + Directory.CreateDirectory(assetPath); + } + FileStream fs = File.Create(Path.Combine(assetPath, filename)); + BinaryWriter bw = new BinaryWriter(fs); + bw.Write(data); + bw.Close(); + fs.Close(); + } + } + } +} diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSD.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSD.cs new file mode 100644 index 0000000000..dab926c39b --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSD.cs @@ -0,0 +1,680 @@ +/* +* 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; +using System.Collections; +using System.Globalization; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using System.Xml; +using libsecondlife; + +namespace OpenSim.Region.Capabilities +{ + /// + /// Borrowed from (a older version of ) libsl for now, as their new llsd code doesn't work we our decoding code. + /// + public static class LLSD + { + /// + /// + /// + public class LLSDParseException : Exception + { + public LLSDParseException(string message) : base(message) + { + } + } + + /// + /// + /// + public class LLSDSerializeException : Exception + { + public LLSDSerializeException(string message) : base(message) + { + } + } + + /// + /// + /// + /// + /// + public static object LLSDDeserialize(byte[] b) + { + return LLSDDeserialize(new MemoryStream(b, false)); + } + + /// + /// + /// + /// + /// + public static object LLSDDeserialize(Stream st) + { + XmlTextReader reader = new XmlTextReader(st); + reader.Read(); + SkipWS(reader); + + if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "llsd") + throw new LLSDParseException("Expected "); + + reader.Read(); + object ret = LLSDParseOne(reader); + SkipWS(reader); + + if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "llsd") + throw new LLSDParseException("Expected "); + + return ret; + } + + /// + /// + /// + /// + /// + public static byte[] LLSDSerialize(object obj) + { + StringWriter sw = new StringWriter(); + XmlTextWriter writer = new XmlTextWriter(sw); + writer.Formatting = Formatting.None; + + writer.WriteStartElement(String.Empty, "llsd", String.Empty); + LLSDWriteOne(writer, obj); + writer.WriteEndElement(); + + writer.Close(); + + return Encoding.UTF8.GetBytes(sw.ToString()); + } + + /// + /// + /// + /// + /// + public static void LLSDWriteOne(XmlTextWriter writer, object obj) + { + if (obj == null) + { + writer.WriteStartElement(String.Empty, "undef", String.Empty); + writer.WriteEndElement(); + return; + } + + if (obj is string) + { + writer.WriteStartElement(String.Empty, "string", String.Empty); + writer.WriteString((string) obj); + writer.WriteEndElement(); + } + else if (obj is int) + { + writer.WriteStartElement(String.Empty, "integer", String.Empty); + writer.WriteString(obj.ToString()); + writer.WriteEndElement(); + } + else if (obj is double) + { + writer.WriteStartElement(String.Empty, "real", String.Empty); + writer.WriteString(obj.ToString()); + writer.WriteEndElement(); + } + else if (obj is bool) + { + bool b = (bool) obj; + writer.WriteStartElement(String.Empty, "boolean", String.Empty); + writer.WriteString(b ? "1" : "0"); + writer.WriteEndElement(); + } + else if (obj is ulong) + { + throw new Exception("ulong in LLSD is currently not implemented, fix me!"); + } + else if (obj is LLUUID) + { + LLUUID u = (LLUUID) obj; + writer.WriteStartElement(String.Empty, "uuid", String.Empty); + writer.WriteString(u.ToString()); + writer.WriteEndElement(); + } + else if (obj is Hashtable) + { + Hashtable h = obj as Hashtable; + writer.WriteStartElement(String.Empty, "map", String.Empty); + foreach (string key in h.Keys) + { + writer.WriteStartElement(String.Empty, "key", String.Empty); + writer.WriteString(key); + writer.WriteEndElement(); + LLSDWriteOne(writer, h[key]); + } + writer.WriteEndElement(); + } + else if (obj is ArrayList) + { + ArrayList a = obj as ArrayList; + writer.WriteStartElement(String.Empty, "array", String.Empty); + foreach (object item in a) + { + LLSDWriteOne(writer, item); + } + writer.WriteEndElement(); + } + else if (obj is byte[]) + { + byte[] b = obj as byte[]; + writer.WriteStartElement(String.Empty, "binary", String.Empty); + + writer.WriteStartAttribute(String.Empty, "encoding", String.Empty); + writer.WriteString("base64"); + writer.WriteEndAttribute(); + + //// Calculate the length of the base64 output + //long length = (long)(4.0d * b.Length / 3.0d); + //if (length % 4 != 0) length += 4 - (length % 4); + + //// Create the char[] for base64 output and fill it + //char[] tmp = new char[length]; + //int i = Convert.ToBase64CharArray(b, 0, b.Length, tmp, 0); + + //writer.WriteString(new String(tmp)); + + writer.WriteString(Convert.ToBase64String(b)); + writer.WriteEndElement(); + } + else + { + throw new LLSDSerializeException("Unknown type " + obj.GetType().Name); + } + } + + /// + /// + /// + /// + /// + public static object LLSDParseOne(XmlTextReader reader) + { + SkipWS(reader); + if (reader.NodeType != XmlNodeType.Element) + throw new LLSDParseException("Expected an element"); + + string dtype = reader.LocalName; + object ret = null; + + switch (dtype) + { + case "undef": + { + if (reader.IsEmptyElement) + { + reader.Read(); + return null; + } + + reader.Read(); + SkipWS(reader); + ret = null; + break; + } + case "boolean": + { + if (reader.IsEmptyElement) + { + reader.Read(); + return false; + } + + reader.Read(); + string s = reader.ReadString().Trim(); + + if (s == String.Empty || s == "false" || s == "0") + ret = false; + else if (s == "true" || s == "1") + ret = true; + else + throw new LLSDParseException("Bad boolean value " + s); + + break; + } + case "integer": + { + if (reader.IsEmptyElement) + { + reader.Read(); + return 0; + } + + reader.Read(); + ret = Convert.ToInt32(reader.ReadString().Trim()); + break; + } + case "real": + { + if (reader.IsEmptyElement) + { + reader.Read(); + return 0.0f; + } + + reader.Read(); + ret = Convert.ToDouble(reader.ReadString().Trim()); + break; + } + case "uuid": + { + if (reader.IsEmptyElement) + { + reader.Read(); + return LLUUID.Zero; + } + + reader.Read(); + ret = new LLUUID(reader.ReadString().Trim()); + break; + } + case "string": + { + if (reader.IsEmptyElement) + { + reader.Read(); + return String.Empty; + } + + reader.Read(); + ret = reader.ReadString(); + break; + } + case "binary": + { + if (reader.IsEmptyElement) + { + reader.Read(); + return new byte[0]; + } + + if (reader.GetAttribute("encoding") != null && + reader.GetAttribute("encoding") != "base64") + { + throw new LLSDParseException("Unknown encoding: " + reader.GetAttribute("encoding")); + } + + reader.Read(); + FromBase64Transform b64 = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces); + byte[] inp = Encoding.ASCII.GetBytes(reader.ReadString()); + ret = b64.TransformFinalBlock(inp, 0, inp.Length); + break; + } + case "date": + { + reader.Read(); + throw new Exception("LLSD TODO: date"); + } + case "map": + { + return LLSDParseMap(reader); + } + case "array": + { + return LLSDParseArray(reader); + } + default: + throw new LLSDParseException("Unknown element <" + dtype + ">"); + } + + if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != dtype) + { + throw new LLSDParseException("Expected "); + } + + reader.Read(); + return ret; + } + + /// + /// + /// + /// + /// + public static Hashtable LLSDParseMap(XmlTextReader reader) + { + Hashtable ret = new Hashtable(); + + if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "map") + throw new LLSDParseException("Expected "); + + if (reader.IsEmptyElement) + { + reader.Read(); + return ret; + } + + reader.Read(); + + while (true) + { + SkipWS(reader); + if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "map") + { + reader.Read(); + break; + } + + if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "key") + throw new LLSDParseException("Expected "); + + string key = reader.ReadString(); + + if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "key") + throw new LLSDParseException("Expected "); + + reader.Read(); + object val = LLSDParseOne(reader); + ret[key] = val; + } + + return ret; // TODO + } + + /// + /// + /// + /// + /// + public static ArrayList LLSDParseArray(XmlTextReader reader) + { + ArrayList ret = new ArrayList(); + + if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "array") + throw new LLSDParseException("Expected "); + + if (reader.IsEmptyElement) + { + reader.Read(); + return ret; + } + + reader.Read(); + + while (true) + { + SkipWS(reader); + + if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "array") + { + reader.Read(); + break; + } + + ret.Insert(ret.Count, LLSDParseOne(reader)); + } + + return ret; // TODO + } + + /// + /// + /// + /// + /// + private static string GetSpaces(int count) + { + StringBuilder b = new StringBuilder(); + for (int i = 0; i < count; i++) b.Append(" "); + return b.ToString(); + } + + /// + /// + /// + /// + /// + /// + public static String LLSDDump(object obj, int indent) + { + if (obj == null) + { + return GetSpaces(indent) + "- undef\n"; + } + else if (obj is string) + { + return GetSpaces(indent) + "- string \"" + (string) obj + "\"\n"; + } + else if (obj is int) + { + return GetSpaces(indent) + "- integer " + obj.ToString() + "\n"; + } + else if (obj is double) + { + return GetSpaces(indent) + "- float " + obj.ToString() + "\n"; + } + else if (obj is LLUUID) + { + return GetSpaces(indent) + "- uuid " + ((LLUUID) obj).ToString() + Environment.NewLine; + } + else if (obj is Hashtable) + { + StringBuilder ret = new StringBuilder(); + ret.Append(GetSpaces(indent) + "- map" + Environment.NewLine); + Hashtable map = (Hashtable) obj; + + foreach (string key in map.Keys) + { + ret.Append(GetSpaces(indent + 2) + "- key \"" + key + "\"" + Environment.NewLine); + ret.Append(LLSDDump(map[key], indent + 3)); + } + + return ret.ToString(); + } + else if (obj is ArrayList) + { + StringBuilder ret = new StringBuilder(); + ret.Append(GetSpaces(indent) + "- array\n"); + ArrayList list = (ArrayList) obj; + + foreach (object item in list) + { + ret.Append(LLSDDump(item, indent + 2)); + } + + return ret.ToString(); + } + else if (obj is byte[]) + { + return GetSpaces(indent) + "- binary\n" + Helpers.FieldToHexString((byte[]) obj, GetSpaces(indent)) + + Environment.NewLine; + } + else + { + return GetSpaces(indent) + "- unknown type " + obj.GetType().Name + Environment.NewLine; + } + } + + public static object ParseTerseLLSD(string llsd) + { + int notused; + return ParseTerseLLSD(llsd, out notused); + } + + public static object ParseTerseLLSD(string llsd, out int endPos) + { + if (llsd.Length == 0) + { + endPos = 0; + return null; + } + + // Identify what type of object this is + switch (llsd[0]) + { + case '!': + throw new LLSDParseException("Undefined value type encountered"); + case '1': + endPos = 1; + return true; + case '0': + endPos = 1; + return false; + case 'i': + { + if (llsd.Length < 2) throw new LLSDParseException("Integer value type with no value"); + int value; + endPos = FindEnd(llsd, 1); + + if (Int32.TryParse(llsd.Substring(1, endPos - 1), out value)) + return value; + else + throw new LLSDParseException("Failed to parse integer value type"); + } + case 'r': + { + if (llsd.Length < 2) throw new LLSDParseException("Real value type with no value"); + double value; + endPos = FindEnd(llsd, 1); + + if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float, + Helpers.EnUsCulture.NumberFormat, out value)) + return value; + else + throw new LLSDParseException("Failed to parse double value type"); + } + case 'u': + { + if (llsd.Length < 17) throw new LLSDParseException("LLUUID value type with no value"); + LLUUID value; + endPos = FindEnd(llsd, 1); + + if (LLUUID.TryParse(llsd.Substring(1, endPos - 1), out value)) + return value; + else + throw new LLSDParseException("Failed to parse LLUUID value type"); + } + case 'b': + //byte[] value = new byte[llsd.Length - 1]; + // This isn't the actual binary LLSD format, just the terse format sent + // at login so I don't even know if there is a binary type + throw new LLSDParseException("Binary value type is unimplemented"); + case 's': + case 'l': + if (llsd.Length < 2) throw new LLSDParseException("String value type with no value"); + endPos = FindEnd(llsd, 1); + return llsd.Substring(1, endPos - 1); + case 'd': + // Never seen one before, don't know what the format is + throw new LLSDParseException("Date value type is unimplemented"); + case '[': + { + if (llsd.IndexOf(']') == -1) throw new LLSDParseException("Invalid array"); + + int pos = 0; + ArrayList array = new ArrayList(); + + while (llsd[pos] != ']') + { + ++pos; + + // Advance past comma if need be + if (llsd[pos] == ',') ++pos; + + // Allow a single whitespace character + if (pos < llsd.Length && llsd[pos] == ' ') ++pos; + + int end; + array.Add(ParseTerseLLSD(llsd.Substring(pos), out end)); + pos += end; + } + + endPos = pos + 1; + return array; + } + case '{': + { + if (llsd.IndexOf('}') == -1) throw new LLSDParseException("Invalid map"); + + int pos = 0; + Hashtable hashtable = new Hashtable(); + + while (llsd[pos] != '}') + { + ++pos; + + // Advance past comma if need be + if (llsd[pos] == ',') ++pos; + + // Allow a single whitespace character + if (pos < llsd.Length && llsd[pos] == ' ') ++pos; + + if (llsd[pos] != '\'') throw new LLSDParseException("Expected a map key"); + int endquote = llsd.IndexOf('\'', pos + 1); + if (endquote == -1 || (endquote + 1) >= llsd.Length || llsd[endquote + 1] != ':') + throw new LLSDParseException("Invalid map format"); + string key = llsd.Substring(pos, endquote - pos); + key = key.Replace("'", String.Empty); + pos += (endquote - pos) + 2; + + int end; + hashtable.Add(key, ParseTerseLLSD(llsd.Substring(pos), out end)); + pos += end; + } + + endPos = pos + 1; + return hashtable; + } + default: + throw new Exception("Unknown value type"); + } + } + + private static int FindEnd(string llsd, int start) + { + int end = llsd.IndexOfAny(new char[] {',', ']', '}'}); + if (end == -1) end = llsd.Length - 1; + return end; + } + + /// + /// + /// + /// + private static void SkipWS(XmlTextReader reader) + { + while ( + reader.NodeType == XmlNodeType.Comment || + reader.NodeType == XmlNodeType.Whitespace || + reader.NodeType == XmlNodeType.SignificantWhitespace || + reader.NodeType == XmlNodeType.XmlDeclaration) + { + reader.Read(); + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDArray.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDArray.cs new file mode 100644 index 0000000000..d641b5c380 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDArray.cs @@ -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. +* +*/ +using System.Collections; + +namespace OpenSim.Region.Capabilities +{ + [LLSDType("ARRAY")] + public class LLSDArray + { + public ArrayList Array = new ArrayList(); + + public LLSDArray() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDAssetUploadComplete.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDAssetUploadComplete.cs new file mode 100644 index 0000000000..e0afa5ca4b --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDAssetUploadComplete.cs @@ -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. +* +*/ +using libsecondlife; +using System; + +namespace OpenSim.Region.Capabilities +{ + [LLSDType("MAP")] + public class LLSDAssetUploadComplete + { + public string new_asset = String.Empty; + public LLUUID new_inventory_item = LLUUID.Zero; + public string state = String.Empty; + //public bool success = false; + + public LLSDAssetUploadComplete() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDAssetUploadRequest.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDAssetUploadRequest.cs new file mode 100644 index 0000000000..e611eeaa75 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDAssetUploadRequest.cs @@ -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. +* +*/ + +using libsecondlife; + +namespace OpenSim.Region.Capabilities +{ + [LLSDMap] + public class LLSDAssetUploadRequest + { + public string asset_type = System.String.Empty; + public string description = System.String.Empty; + public LLUUID folder_id = LLUUID.Zero; + public string inventory_type = System.String.Empty; + public string name = System.String.Empty; + + public LLSDAssetUploadRequest() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDAssetUploadResponse.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDAssetUploadResponse.cs new file mode 100644 index 0000000000..7744ffb19b --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDAssetUploadResponse.cs @@ -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. +* +*/ + +namespace OpenSim.Region.Capabilities +{ + [LLSDMap] + public class LLSDAssetUploadResponse + { + public string uploader = System.String.Empty; + public string state = System.String.Empty; + + public LLSDAssetUploadResponse() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDCapEvent.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDCapEvent.cs new file mode 100644 index 0000000000..3b8c07791e --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDCapEvent.cs @@ -0,0 +1,40 @@ +/* +* 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. +* +*/ +namespace OpenSim.Region.Capabilities +{ + [LLSDType("MAP")] + public class LLSDCapEvent + { + public int id = 0; + public LLSDArray events = new LLSDArray(); + + public LLSDCapEvent() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDCapsDetails.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDCapsDetails.cs new file mode 100644 index 0000000000..7006b44acb --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDCapsDetails.cs @@ -0,0 +1,50 @@ +/* +* 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; + +namespace OpenSim.Region.Capabilities +{ + [LLSDType("MAP")] + public class LLSDCapsDetails + { + public string MapLayer = String.Empty; + public string NewFileAgentInventory = String.Empty; + //public string EventQueueGet = String.Empty; + // public string RequestTextureDownload = String.Empty; + // public string ChatSessionRequest = String.Empty; + public string UpdateNotecardAgentInventory = String.Empty; + public string UpdateScriptAgentInventory = String.Empty; + public string UpdateScriptTaskInventory = String.Empty; + // public string ParcelVoiceInfoRequest = String.Empty; + + public LLSDCapsDetails() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDEmpty.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDEmpty.cs new file mode 100644 index 0000000000..5e6e9178ef --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDEmpty.cs @@ -0,0 +1,37 @@ +/* +* 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. +* +*/ +namespace OpenSim.Region.Capabilities +{ + [LLSDType("MAP")] + public class LLSDEmpty + { + public LLSDEmpty() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDHelpers.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDHelpers.cs new file mode 100644 index 0000000000..28f838de65 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDHelpers.cs @@ -0,0 +1,151 @@ +/* +* 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; +using System.Collections; +using System.IO; +using System.Reflection; +using System.Xml; + +namespace OpenSim.Region.Capabilities +{ + public class LLSDHelpers + { + public static string SerialiseLLSDReply(object obj) + { + StringWriter sw = new StringWriter(); + XmlTextWriter writer = new XmlTextWriter(sw); + writer.Formatting = Formatting.None; + writer.WriteStartElement(String.Empty, "llsd", String.Empty); + SerializeLLSDType(writer, obj); + writer.WriteEndElement(); + writer.Close(); + return sw.ToString(); + } + + private static void SerializeLLSDType(XmlTextWriter writer, object obj) + { + Type myType = obj.GetType(); + LLSDType[] llsdattributes = (LLSDType[]) myType.GetCustomAttributes(typeof (LLSDType), false); + if (llsdattributes.Length > 0) + { + switch (llsdattributes[0].ObjectType) + { + case "MAP": + writer.WriteStartElement(String.Empty, "map", String.Empty); + FieldInfo[] fields = myType.GetFields(); + for (int i = 0; i < fields.Length; i++) + { + object fieldValue = fields[i].GetValue(obj); + LLSDType[] fieldAttributes = + (LLSDType[]) fieldValue.GetType().GetCustomAttributes(typeof (LLSDType), false); + if (fieldAttributes.Length > 0) + { + writer.WriteStartElement(String.Empty, "key", String.Empty); + writer.WriteString(fields[i].Name); + writer.WriteEndElement(); + SerializeLLSDType(writer, fieldValue); + } + else + { + writer.WriteStartElement(String.Empty, "key", String.Empty); + writer.WriteString(fields[i].Name); + writer.WriteEndElement(); + LLSD.LLSDWriteOne(writer, fieldValue); + // libsecondlife.StructuredData.LLSDParser.SerializeXmlElement( + // writer, libsecondlife.StructuredData.LLSD.FromObject(fieldValue)); + } + } + writer.WriteEndElement(); + break; + case "ARRAY": + // LLSDArray arrayObject = obj as LLSDArray; + // ArrayList a = arrayObject.Array; + ArrayList a = (ArrayList) obj.GetType().GetField("Array").GetValue(obj); + if (a != null) + { + writer.WriteStartElement(String.Empty, "array", String.Empty); + foreach (object item in a) + { + SerializeLLSDType(writer, item); + } + writer.WriteEndElement(); + } + break; + } + } + else + { + LLSD.LLSDWriteOne(writer, obj); + //libsecondlife.StructuredData.LLSDParser.SerializeXmlElement( + // writer, libsecondlife.StructuredData.LLSD.FromObject(obj)); + } + } + + public static object DeserialiseLLSDMap(Hashtable llsd, object obj) + { + Type myType = obj.GetType(); + LLSDType[] llsdattributes = (LLSDType[]) myType.GetCustomAttributes(typeof (LLSDType), false); + if (llsdattributes.Length > 0) + { + switch (llsdattributes[0].ObjectType) + { + case "MAP": + IDictionaryEnumerator enumerator = llsd.GetEnumerator(); + while (enumerator.MoveNext()) + { + FieldInfo field = myType.GetField((string) enumerator.Key); + if (field != null) + { + // if (enumerator.Value is libsecondlife.StructuredData.LLSDMap) + if (enumerator.Value is Hashtable) + { + object fieldValue = field.GetValue(obj); + DeserialiseLLSDMap((Hashtable) enumerator.Value, fieldValue); + // DeserialiseLLSDMap((libsecondlife.StructuredData.LLSDMap) enumerator.Value, fieldValue); + } + else if (enumerator.Value is ArrayList) + { + object fieldValue = field.GetValue(obj); + fieldValue.GetType().GetField("Array").SetValue(fieldValue, enumerator.Value); + //TODO + // the LLSD map/array types in the array need to be deserialised + // but first we need to know the right class to deserialise them into. + } + else + { + field.SetValue(obj, enumerator.Value); + } + } + } + break; + } + } + return obj; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDItemUpdate.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDItemUpdate.cs new file mode 100644 index 0000000000..3842058b70 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDItemUpdate.cs @@ -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 libsecondlife; + +namespace OpenSim.Region.Capabilities +{ + [LLSDMap] + public class LLSDItemUpdate + { + public LLUUID item_id; + + public LLSDItemUpdate() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDMapLayer.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDMapLayer.cs new file mode 100644 index 0000000000..121b36a4dc --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDMapLayer.cs @@ -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. +* +*/ +using libsecondlife; + +namespace OpenSim.Region.Capabilities +{ + [LLSDType("MAP")] + public class LLSDMapLayer + { + public int Left = 0; + public int Right = 0; + public int Top = 0; + public int Bottom = 0; + public LLUUID ImageID = LLUUID.Zero; + + public LLSDMapLayer() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDMapLayerResponse.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDMapLayerResponse.cs new file mode 100644 index 0000000000..93b0f83b95 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDMapLayerResponse.cs @@ -0,0 +1,40 @@ +/* +* 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. +* +*/ +namespace OpenSim.Region.Capabilities +{ + [LLSDType("MAP")] + public class LLSDMapLayerResponse + { + public LLSDMapRequest AgentData = new LLSDMapRequest(); + public LLSDArray LayerData = new LLSDArray(); + + public LLSDMapLayerResponse() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDMapRequest.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDMapRequest.cs new file mode 100644 index 0000000000..935f81df06 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDMapRequest.cs @@ -0,0 +1,40 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.Capabilities +{ + [LLSDType("MAP")] + public class LLSDMapRequest + { + public int Flags = 0; + + public LLSDMapRequest() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDMethod.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDMethod.cs new file mode 100644 index 0000000000..6bd47e1620 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDMethod.cs @@ -0,0 +1,32 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.Capabilities +{ + public delegate TResponse LLSDMethod(TRequest request); +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDStreamHandler.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDStreamHandler.cs new file mode 100644 index 0000000000..4321d7b914 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDStreamHandler.cs @@ -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 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.Collections; +using System.IO; +using System.Text; +using OpenSim.Framework.Servers; + +namespace OpenSim.Region.Capabilities +{ + public class LLSDStreamhandler : BaseStreamHandler + where TRequest : new() + { + private LLSDMethod m_method; + + public LLSDStreamhandler(string httpMethod, string path, LLSDMethod method) + : base(httpMethod, path) + { + m_method = method; + } + + public override byte[] Handle(string path, Stream request) + { + //Encoding encoding = Encoding.UTF8; + //StreamReader streamReader = new StreamReader(request, false); + + //string requestBody = streamReader.ReadToEnd(); + //streamReader.Close(); + + // libsecondlife.StructuredData.LLSDMap hash = (libsecondlife.StructuredData.LLSDMap) + // libsecondlife.StructuredData.LLSDParser.DeserializeXml(new XmlTextReader(request)); + + Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(request); + TRequest llsdRequest = new TRequest(); + LLSDHelpers.DeserialiseLLSDMap(hash, llsdRequest); + + TResponse response = m_method(llsdRequest); + + Encoding encoding = new UTF8Encoding(false); + + return encoding.GetBytes(LLSDHelpers.SerialiseLLSDReply(response)); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDTaskInventoryUploadComplete.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDTaskInventoryUploadComplete.cs new file mode 100644 index 0000000000..6454ad756b --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDTaskInventoryUploadComplete.cs @@ -0,0 +1,50 @@ +/* +* 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 libsecondlife; + +namespace OpenSim.Region.Capabilities +{ + [LLSDMap] + public class LLSDTaskInventoryUploadComplete + { + /// + /// The task inventory item that was updated + /// + public LLUUID item_id; + + /// + /// The task that was updated + /// + public LLUUID task_id; + + /// + /// State of the upload. So far have only even seen this set to "complete" + /// + public string state; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDTaskScriptUpdate.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDTaskScriptUpdate.cs new file mode 100644 index 0000000000..52e13a7c1b --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDTaskScriptUpdate.cs @@ -0,0 +1,51 @@ +/* +* 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 libsecondlife; + +namespace OpenSim.Region.Capabilities +{ + [LLSDMap] + public class LLSDTaskScriptUpdate + { + /// + /// The item containing the script to update + /// + public LLUUID item_id; + + /// + /// The task containing the script + /// + public LLUUID task_id; + + /// + /// Signals whether the script is currently active + /// + public int is_script_running; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDTest.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDTest.cs new file mode 100644 index 0000000000..d10b0c0c8c --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDTest.cs @@ -0,0 +1,40 @@ +/* +* 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. +* +*/ +namespace OpenSim.Region.Capabilities +{ + [LLSDType("MAP")] + public class LLSDTest + { + public int Test1 = 20; + public int Test2 = 10; + + public LLSDTest() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/Capabilities/LLSDType.cs b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDType.cs new file mode 100644 index 0000000000..e85174248b --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Capabilities/LLSDType.cs @@ -0,0 +1,55 @@ +/* +* 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; + +namespace OpenSim.Region.Capabilities +{ + [AttributeUsage(AttributeTargets.Class)] + public class LLSDType : Attribute + { + protected string myType; + + public LLSDType(string type) + { + myType = type; + } + + public string ObjectType + { + get { return myType; } + } + } + + [AttributeUsage(AttributeTargets.Class)] + public class LLSDMap : LLSDType + { + public LLSDMap() : base("MAP") + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/CommunicationsManager.cs b/trunk/OpenSim/Framework/Communications/CommunicationsManager.cs new file mode 100644 index 0000000000..eb820c168e --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/CommunicationsManager.cs @@ -0,0 +1,244 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; + +namespace OpenSim.Framework.Communications +{ + public class CommunicationsManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected IUserService m_userService; + + public IUserService UserService + { + get { return m_userService; } + } + + protected IGridServices m_gridService; + + public IGridServices GridService + { + get { return m_gridService; } + } + + protected IInventoryServices m_inventoryService; + + public IInventoryServices InventoryService + { + get { return m_inventoryService; } + } + + protected IInterRegionCommunications m_interRegion; + + public IInterRegionCommunications InterRegion + { + get { return m_interRegion; } + } + + protected UserProfileCacheService m_userProfileCacheService; + + public UserProfileCacheService UserProfileCacheService + { + get { return m_userProfileCacheService; } + } + + // protected AgentAssetTransactionsManager m_transactionsManager; + + // public AgentAssetTransactionsManager TransactionsManager + // { + // get { return m_transactionsManager; } + // } + + protected AssetCache m_assetCache; + + public AssetCache AssetCache + { + get { return m_assetCache; } + } + + protected NetworkServersInfo m_networkServersInfo; + + public NetworkServersInfo NetworkServersInfo + { + get { return m_networkServersInfo; } + } + + public CommunicationsManager(NetworkServersInfo serversInfo, BaseHttpServer httpServer, AssetCache assetCache, + bool dumpAssetsToFile) + { + m_networkServersInfo = serversInfo; + m_assetCache = assetCache; + m_userProfileCacheService = new UserProfileCacheService(this); + // m_transactionsManager = new AgentAssetTransactionsManager(this, dumpAssetsToFile); + } + + public void doCreate(string[] cmmdParams) + { + switch (cmmdParams[0]) + { + case "user": + string firstName; + string lastName; + string password; + uint regX = 1000; + uint regY = 1000; + + if (cmmdParams.Length < 2) + { + firstName = MainConsole.Instance.CmdPrompt("First name", "Default"); + lastName = MainConsole.Instance.CmdPrompt("Last name", "User"); + password = MainConsole.Instance.PasswdPrompt("Password"); + regX = Convert.ToUInt32(MainConsole.Instance.CmdPrompt("Start Region X", "1000")); + regY = Convert.ToUInt32(MainConsole.Instance.CmdPrompt("Start Region Y", "1000")); + } + else + { + firstName = cmmdParams[1]; + lastName = cmmdParams[2]; + password = cmmdParams[3]; + regX = Convert.ToUInt32(cmmdParams[4]); + regY = Convert.ToUInt32(cmmdParams[5]); + } + + AddUser(firstName, lastName, password, regX, regY); + break; + } + } + + public LLUUID AddUser(string firstName, string lastName, string password, uint regX, uint regY) + { + string md5PasswdHash = Util.Md5Hash(Util.Md5Hash(password) + ":" + String.Empty); + + m_userService.AddUserProfile(firstName, lastName, md5PasswdHash, regX, regY); + UserProfileData userProf = UserService.GetUserProfile(firstName, lastName); + if (userProf == null) + { + return LLUUID.Zero; + } + else + { + m_inventoryService.CreateNewUserInventory(userProf.UUID); + System.Console.WriteLine("Created new inventory set for " + firstName + " " + lastName); + return userProf.UUID; + } + } + + #region Friend Methods + /// + /// Adds a new friend to the database for XUser + /// + /// The agent that who's friends list is being added to + /// The agent that being added to the friends list of the friends list owner + /// A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects + public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms) + { + m_userService.AddNewUserFriend(friendlistowner, friend, perms); + } + /// + /// Logs off a user and does the appropriate communications + /// + /// + /// + /// + /// + /// + /// + public void LogOffUser(LLUUID userid, LLUUID regionid, ulong regionhandle, float posx, float posy, float posz) + { + m_userService.LogOffUser(userid, regionid, regionhandle, posx, posy, posz); + + } + + /// + /// Delete friend on friendlistowner's friendlist. + /// + /// The agent that who's friends list is being updated + /// The Ex-friend agent + public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend) + { + m_userService.RemoveUserFriend(friendlistowner, friend); + } + + /// + /// Update permissions for friend on friendlistowner's friendlist. + /// + /// The agent that who's friends list is being updated + /// The agent that is getting or loosing permissions + /// A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects + public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms) + { + m_userService.UpdateUserFriendPerms(friendlistowner, friend, perms); + } + /// + /// Returns a list of FriendsListItems that describe the friends and permissions in the friend relationship for LLUUID friendslistowner + /// + /// The agent that we're retreiving the friends Data. + public List GetUserFriendList(LLUUID friendlistowner) + { + return m_userService.GetUserFriendList(friendlistowner); + } + + #endregion + + #region Packet Handlers + + public void HandleUUIDNameRequest(LLUUID uuid, IClientAPI remote_client) + { + if (uuid == m_userProfileCacheService.libraryRoot.agentID) + { + remote_client.SendNameReply(uuid, "Mr", "OpenSim"); + } + else + { + UserProfileData profileData = m_userService.GetUserProfile(uuid); + if (profileData != null) + { + LLUUID profileId = profileData.UUID; + string firstname = profileData.username; + string lastname = profileData.surname; + + remote_client.SendNameReply(profileId, firstname, lastname); + } + } + } + + public List GenerateAgentPickerRequestResponse(LLUUID queryID, string query) + { + List pickerlist = m_userService.GenerateAgentPickerRequestResponse(queryID, query); + return pickerlist; + } + + #endregion + } +} diff --git a/trunk/OpenSim/Framework/Communications/IGridServices.cs b/trunk/OpenSim/Framework/Communications/IGridServices.cs new file mode 100644 index 0000000000..e2c2661947 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/IGridServices.cs @@ -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 System.Collections.Generic; + +namespace OpenSim.Framework.Communications +{ + public interface IGridServices + { + string gdebugRegionName { get; set; } + RegionCommsListener RegisterRegion(RegionInfo regionInfos); + bool DeregisterRegion(RegionInfo regionInfo); + List RequestNeighbours(uint x, uint y); + RegionInfo RequestNeighbourInfo(ulong regionHandle); + Dictionary GetGridSettings(); + List RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/IInterRegionCommunications.cs b/trunk/OpenSim/Framework/Communications/IInterRegionCommunications.cs new file mode 100644 index 0000000000..e93719ed09 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/IInterRegionCommunications.cs @@ -0,0 +1,50 @@ +/* +* 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 libsecondlife; + +namespace OpenSim.Framework.Communications +{ + public interface IInterRegionCommunications + { + string rdebugRegionName { get; set; } + bool Available { get; } + void CheckRegion(string address, uint port); + bool InformRegionOfChildAgent(ulong regionHandle, AgentCircuitData agentData); + bool InformRegionOfPrimCrossing(ulong regionHandle, LLUUID primID, string objData); + bool RegionUp(SearializableRegionInfo region, ulong regionhandle); + bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData); + + bool ExpectAvatarCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying); + bool ExpectPrimCrossing(ulong regionHandle, LLUUID primID, LLVector3 position, bool isFlying); + + bool AcknowledgeAgentCrossed(ulong regionHandle, LLUUID agentId); + bool AcknowledgePrimCrossed(ulong regionHandle, LLUUID primID); + + bool TellRegionToCloseChildConnection(ulong regionHandle, LLUUID agentID); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/IInventoryServices.cs b/trunk/OpenSim/Framework/Communications/IInventoryServices.cs new file mode 100644 index 0000000000..0e0961368b --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/IInventoryServices.cs @@ -0,0 +1,100 @@ +/* +* 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.Collections.Generic; +using libsecondlife; +using OpenSim.Framework.Communications.Cache; + +namespace OpenSim.Framework.Communications +{ + public delegate void InventoryFolderInfo(LLUUID userID, InventoryFolderImpl folderInfo); + + public delegate void InventoryItemInfo(LLUUID userID, InventoryItemBase itemInfo); + + /// + /// Defines all the operations one can perform on a user's inventory. + /// + public interface IInventoryServices + { + void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, InventoryItemInfo itemCallBack); + + /// + /// Add a new folder to the given user's inventory + /// + /// + /// + void AddNewInventoryFolder(LLUUID userID, InventoryFolderBase folder); + + void MoveInventoryFolder(LLUUID userID, InventoryFolderBase folder); + + /// + /// Add a new item to the given user's inventory + /// + /// + /// + void AddNewInventoryItem(LLUUID userID, InventoryItemBase item); + + /// + /// Delete an item from the given user's inventory + /// + /// + /// + void DeleteInventoryItem(LLUUID userID, InventoryItemBase item); + + /// + /// Create a new inventory for the given user + /// + /// + void CreateNewUserInventory(LLUUID user); + + bool HasInventoryForUser(LLUUID userID); + + /// + /// Retrieve the root inventory folder for the given user. + /// + /// + /// null if no root folder was found + InventoryFolderBase RequestRootFolder(LLUUID userID); + + /// + /// Returns the root folder plus any folders in root (so down one level in the Inventory folders tree) + /// for the given user. + /// + /// + /// + List RequestFirstLevelFolders(LLUUID userID); + + /// + /// Returns the named folder in that users inventory, returns null if folder is not found. + /// + /// + /// + /// + InventoryFolderBase RequestNamedFolder(LLUUID userID, string folderName); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/InventoryServiceBase.cs b/trunk/OpenSim/Framework/Communications/InventoryServiceBase.cs new file mode 100644 index 0000000000..c8748fa03c --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/InventoryServiceBase.cs @@ -0,0 +1,389 @@ +/* +* 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; +using System.Collections.Generic; +using System.Reflection; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Communications +{ + public abstract class InventoryServiceBase : IInventoryServices + { + private static readonly log4net.ILog m_log + = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected Dictionary m_plugins = new Dictionary(); + + #region Plugin methods + + /// + /// Adds a new user server plugin - plugins will be requested in the order they were loaded. + /// + /// The filename to the user server plugin DLL + public void AddPlugin(string FileName) + { + if (!String.IsNullOrEmpty(FileName)) + { + m_log.Info("[AGENTINVENTORY]: Inventorystorage: Attempting to load " + FileName); + Assembly pluginAssembly = Assembly.LoadFrom(FileName); + + foreach (Type pluginType in pluginAssembly.GetTypes()) + { + if (!pluginType.IsAbstract) + { + Type typeInterface = pluginType.GetInterface("IInventoryData", true); + + if (typeInterface != null) + { + IInventoryData plug = + (IInventoryData) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + plug.Initialise(); + m_plugins.Add(plug.getName(), plug); + m_log.Info("[AGENTINVENTORY]: Added IInventoryData Interface"); + } + } + } + } + } + + #endregion + + #region IInventoryServices methods + + // See IInventoryServices + public List RequestFirstLevelFolders(Guid rawUserID) + { + LLUUID userID = new LLUUID(rawUserID); + return RequestFirstLevelFolders(userID); + } + + // See IInventoryServices + public List RequestFirstLevelFolders(LLUUID userID) + { + List inventoryList = new List(); + InventoryFolderBase rootFolder = null; + + foreach (KeyValuePair plugin in m_plugins) + { + rootFolder = plugin.Value.getUserRootFolder(userID); + if (rootFolder != null) + { + m_log.Info( + "[INVENTORY]: Found root folder for user with ID " + userID + ". Retrieving inventory contents."); + + inventoryList = plugin.Value.getInventoryFolders(rootFolder.folderID); + inventoryList.Insert(0, rootFolder); + return inventoryList; + } + } + + m_log.Warn( + "[INVENTORY]: Could not find a root folder belonging to user with ID " + userID); + + return inventoryList; + } + + // See IInventoryServices + public InventoryFolderBase RequestUsersRoot(LLUUID userID) + { + foreach (KeyValuePair plugin in m_plugins) + { + return plugin.Value.getUserRootFolder(userID); + } + return null; + } + + // See IInventoryServices + public void MoveInventoryFolder(LLUUID userID, InventoryFolderBase folder) + { + foreach (KeyValuePair plugin in m_plugins) + { + plugin.Value.moveInventoryFolder(folder); + } + } + + public virtual bool HasInventoryForUser(LLUUID userID) + { + return false; + } + + // See IInventoryServices + public InventoryFolderBase RequestRootFolder(LLUUID userID) + { + return RequestUsersRoot(userID); + } + + // See IInventoryServices + public virtual InventoryFolderBase RequestNamedFolder(LLUUID userID, string folderName) + { + return null; + } + + // See IInventoryServices + public void CreateNewUserInventory(LLUUID user) + { + InventoryFolderBase existingRootFolder = RequestUsersRoot(user); + + if (null != existingRootFolder) + { + m_log.ErrorFormat("[AGENTINVENTORY]: " + + "Did not create a new inventory for user {0} since they already have " + + "a root inventory folder with id {1}", user, existingRootFolder); + } + else + { + UsersInventory inven = new UsersInventory(); + inven.CreateNewInventorySet(user); + AddNewInventorySet(inven); + } + } + + public abstract void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, + InventoryItemInfo itemCallBack); + public abstract void AddNewInventoryFolder(LLUUID userID, InventoryFolderBase folder); + public abstract void MoveExistingInventoryFolder(InventoryFolderBase folder); + public abstract void AddNewInventoryItem(LLUUID userID, InventoryItemBase item); + public abstract void DeleteInventoryItem(LLUUID userID, InventoryItemBase item); + + #endregion + + #region Methods used by GridInventoryService + + public List RequestSubFolders(LLUUID parentFolderID) + { + List inventoryList = new List(); + foreach (KeyValuePair plugin in m_plugins) + { + return plugin.Value.getInventoryFolders(parentFolderID); + } + return inventoryList; + } + + public List RequestFolderItems(LLUUID folderID) + { + List itemsList = new List(); + foreach (KeyValuePair plugin in m_plugins) + { + itemsList = plugin.Value.getInventoryInFolder(folderID); + return itemsList; + } + return itemsList; + } + + #endregion + + protected void AddFolder(InventoryFolderBase folder) + { + foreach (KeyValuePair plugin in m_plugins) + { + plugin.Value.addInventoryFolder(folder); + } + } + + protected void MoveFolder(InventoryFolderBase folder) + { + foreach (KeyValuePair plugin in m_plugins) + { + plugin.Value.moveInventoryFolder(folder); + } + } + + protected void AddItem(InventoryItemBase item) + { + foreach (KeyValuePair plugin in m_plugins) + { + plugin.Value.addInventoryItem(item); + } + } + + protected void DeleteItem(InventoryItemBase item) + { + foreach (KeyValuePair plugin in m_plugins) + { + plugin.Value.deleteInventoryItem(item.inventoryID); + } + } + + private void AddNewInventorySet(UsersInventory inventory) + { + foreach (InventoryFolderBase folder in inventory.Folders.Values) + { + AddFolder(folder); + } + } + + private class UsersInventory + { + public Dictionary Folders = new Dictionary(); + public Dictionary Items = new Dictionary(); + + public virtual void CreateNewInventorySet(LLUUID user) + { + InventoryFolderBase folder = new InventoryFolderBase(); + + folder.parentID = LLUUID.Zero; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "My Inventory"; + folder.type = 8; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + LLUUID rootFolder = folder.folderID; + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Accessories"; + folder.type = 8; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Animations"; + folder.type = 20; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "BodyParts"; + folder.type = 13; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Clothing"; + folder.type = 5; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Gestures"; + folder.type = 21; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Landmarks"; + folder.type = 3; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Lost And Found"; + folder.type = 3; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Notecards"; + folder.type = 7; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Objects"; + folder.type = 6; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Photo Album"; + folder.type = 15; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Scripts"; + folder.type = 10; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Sounds"; + folder.type = 1; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Textures"; + folder.type = 0; + folder.version = 1; + Folders.Add(folder.folderID, folder); + + folder = new InventoryFolderBase(); + folder.parentID = rootFolder; + folder.agentID = user; + folder.folderID = LLUUID.Random(); + folder.name = "Trash"; + folder.type = 14; + folder.version = 1; + Folders.Add(folder.folderID, folder); + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/LoginResponse.cs b/trunk/OpenSim/Framework/Communications/LoginResponse.cs new file mode 100644 index 0000000000..baf07e8037 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/LoginResponse.cs @@ -0,0 +1,751 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using libsecondlife; +using libsecondlife.StructuredData; +using Nwc.XmlRpc; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.UserManagement +{ + /// + /// A temp class to handle login response. + /// Should make use of UserProfileManager where possible. + /// + public class LoginResponse + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private Hashtable loginFlagsHash; + private Hashtable globalTexturesHash; + private Hashtable loginError; + private Hashtable uiConfigHash; + + private ArrayList loginFlags; + private ArrayList globalTextures; + private ArrayList eventCategories; + private ArrayList uiConfig; + private ArrayList classifiedCategories; + private ArrayList inventoryRoot; + private ArrayList initialOutfit; + private ArrayList agentInventory; + private ArrayList inventoryLibraryOwner; + private ArrayList inventoryLibRoot; + private ArrayList inventoryLibrary; + + private UserInfo userProfile; + + private LLUUID agentID; + private LLUUID sessionID; + private LLUUID secureSessionID; + + // Login Flags + private string dst; + private string stipendSinceLogin; + private string gendered; + private string everLoggedIn; + private string login; + private uint simPort; + private string simAddress; + private string agentAccess; + private Int32 circuitCode; + private uint regionX; + private uint regionY; + + // Login + private string firstname; + private string lastname; + + // Global Textures + private string sunTexture; + private string cloudTexture; + private string moonTexture; + + // Error Flags + private string errorReason; + private string errorMessage; + + // Response + private XmlRpcResponse xmlRpcResponse; + private XmlRpcResponse defaultXmlRpcResponse; + + private string welcomeMessage; + private string startLocation; + private string allowFirstLife; + private string home; + private string seedCapability; + private string lookAt; + + private BuddyList m_buddyList = null; + + public LoginResponse() + { + loginFlags = new ArrayList(); + globalTextures = new ArrayList(); + eventCategories = new ArrayList(); + uiConfig = new ArrayList(); + classifiedCategories = new ArrayList(); + + loginError = new Hashtable(); + uiConfigHash = new Hashtable(); + + defaultXmlRpcResponse = new XmlRpcResponse(); + userProfile = new UserInfo(); + inventoryRoot = new ArrayList(); + initialOutfit = new ArrayList(); + agentInventory = new ArrayList(); + inventoryLibrary = new ArrayList(); + inventoryLibraryOwner = new ArrayList(); + + xmlRpcResponse = new XmlRpcResponse(); + defaultXmlRpcResponse = new XmlRpcResponse(); + + SetDefaultValues(); + } // LoginServer + + public void SetDefaultValues() + { + DST = "N"; + StipendSinceLogin = "N"; + Gendered = "Y"; + EverLoggedIn = "Y"; + login = "false"; + firstname = "Test"; + lastname = "User"; + agentAccess = "M"; + startLocation = "last"; + allowFirstLife = "Y"; + + SunTexture = "cce0f112-878f-4586-a2e2-a8f104bba271"; + CloudTexture = "dc4b9f0b-d008-45c6-96a4-01dd947ac621"; + MoonTexture = "ec4b9f0b-d008-45c6-96a4-01dd947ac621"; + + ErrorMessage = "You have entered an invalid name/password combination. Check Caps/lock."; + ErrorReason = "key"; + welcomeMessage = "Welcome to OpenSim!"; + seedCapability = String.Empty; + home = "{'region_handle':[r" + (1000*Constants.RegionSize).ToString() + ",r" + (1000*Constants.RegionSize).ToString() + "], 'position':[r" + + userProfile.homepos.X.ToString() + ",r" + userProfile.homepos.Y.ToString() + ",r" + + userProfile.homepos.Z.ToString() + "], 'look_at':[r" + userProfile.homelookat.X.ToString() + ",r" + + userProfile.homelookat.Y.ToString() + ",r" + userProfile.homelookat.Z.ToString() + "]}"; + lookAt = "[r0.99949799999999999756,r0.03166859999999999814,r0]"; + RegionX = (uint) 255232; + RegionY = (uint) 254976; + + // Classifieds; + AddClassifiedCategory((Int32) 1, "Shopping"); + AddClassifiedCategory((Int32) 2, "Land Rental"); + AddClassifiedCategory((Int32) 3, "Property Rental"); + AddClassifiedCategory((Int32) 4, "Special Attraction"); + AddClassifiedCategory((Int32) 5, "New Products"); + AddClassifiedCategory((Int32) 6, "Employment"); + AddClassifiedCategory((Int32) 7, "Wanted"); + AddClassifiedCategory((Int32) 8, "Service"); + AddClassifiedCategory((Int32) 9, "Personal"); + + + SessionID = LLUUID.Random(); + SecureSessionID = LLUUID.Random(); + AgentID = LLUUID.Random(); + + Hashtable InitialOutfitHash = new Hashtable(); + InitialOutfitHash["folder_name"] = "Nightclub Female"; + InitialOutfitHash["gender"] = "female"; + initialOutfit.Add(InitialOutfitHash); + } // SetDefaultValues + + #region Login Failure Methods + + public XmlRpcResponse GenerateFailureResponse(string reason, string message, string login) + { + // Overwrite any default values; + xmlRpcResponse = new XmlRpcResponse(); + + // Ensure Login Failed message/reason; + ErrorMessage = message; + ErrorReason = reason; + + loginError["reason"] = ErrorReason; + loginError["message"] = ErrorMessage; + loginError["login"] = login; + xmlRpcResponse.Value = loginError; + return (xmlRpcResponse); + } // GenerateResponse + + public LLSD GenerateFailureResponseLLSD(string reason, string message, string login) + { + LLSDMap map = new LLSDMap(); + + // Ensure Login Failed message/reason; + ErrorMessage = message; + ErrorReason = reason; + + map["reason"] = LLSD.FromString(ErrorReason); + map["message"] = LLSD.FromString(ErrorMessage); + map["login"] = LLSD.FromString(login); + + return map; + } + + public XmlRpcResponse CreateFailedResponse() + { + return (CreateLoginFailedResponse()); + } // CreateErrorConnectingToGridResponse() + + public LLSD CreateFailedResponseLLSD() + { + return CreateLoginFailedResponseLLSD(); + } + + public XmlRpcResponse CreateLoginFailedResponse() + { + return + (GenerateFailureResponse("key", + "Could not authenticate your avatar. Please check your username and password, and check the grid if problems persist.", + "false")); + } // LoginFailedResponse + + public LLSD CreateLoginFailedResponseLLSD() + { + return GenerateFailureResponseLLSD( + "key", + "Could not authenticate your avatar. Please check your username and password, and check the grid if problems persist.", + "false"); + } + + public XmlRpcResponse CreateAlreadyLoggedInResponse() + { + return + (GenerateFailureResponse("presence", + "You appear to be already logged in, if this is not the case please wait for your session to timeout, if this takes longer than a few minutes please contact the grid owner", + "false")); + } // CreateAlreadyLoggedInResponse() + + public LLSD CreateAlreadyLoggedInResponseLLSD() + { + return GenerateFailureResponseLLSD( + "presence", + "You appear to be already logged in, if this is not the case please wait for your session to timeout, if this takes longer than a few minutes please contact the grid owner", + "false"); + } + + public XmlRpcResponse CreateDeadRegionResponse() + { + return + (GenerateFailureResponse("key", + "The region you are attempting to log into is not responding. Please select another region and try again.", + "false")); + } + + public LLSD CreateDeadRegionResponseLLSD() + { + return GenerateFailureResponseLLSD( + "key", + "The region you are attempting to log into is not responding. Please select another region and try again.", + "false"); + } + + public XmlRpcResponse CreateGridErrorResponse() + { + return + (GenerateFailureResponse("key", + "Error connecting to grid. Could not percieve credentials from login XML.", + "false")); + } + + public LLSD CreateGridErrorResponseLLSD() + { + return GenerateFailureResponseLLSD( + "key", + "Error connecting to grid. Could not percieve credentials from login XML.", + "false"); + } + + #endregion + + public XmlRpcResponse ToXmlRpcResponse() + { + try + { + Hashtable responseData = new Hashtable(); + + loginFlagsHash = new Hashtable(); + loginFlagsHash["daylight_savings"] = DST; + loginFlagsHash["stipend_since_login"] = StipendSinceLogin; + loginFlagsHash["gendered"] = Gendered; + loginFlagsHash["ever_logged_in"] = EverLoggedIn; + loginFlags.Add(loginFlagsHash); + + responseData["first_name"] = Firstname; + responseData["last_name"] = Lastname; + responseData["agent_access"] = agentAccess; + + globalTexturesHash = new Hashtable(); + globalTexturesHash["sun_texture_id"] = SunTexture; + globalTexturesHash["cloud_texture_id"] = CloudTexture; + globalTexturesHash["moon_texture_id"] = MoonTexture; + globalTextures.Add(globalTexturesHash); + // this.eventCategories.Add(this.eventCategoriesHash); + + AddToUIConfig("allow_first_life", allowFirstLife); + uiConfig.Add(uiConfigHash); + + responseData["sim_port"] = (Int32) SimPort; + responseData["sim_ip"] = SimAddress; + + responseData["agent_id"] = AgentID.ToString(); + responseData["session_id"] = SessionID.ToString(); + responseData["secure_session_id"] = SecureSessionID.ToString(); + responseData["circuit_code"] = CircuitCode; + responseData["seconds_since_epoch"] = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; + responseData["login-flags"] = loginFlags; + responseData["global-textures"] = globalTextures; + responseData["seed_capability"] = seedCapability; + + responseData["event_categories"] = eventCategories; + responseData["event_notifications"] = new ArrayList(); // todo + responseData["classified_categories"] = classifiedCategories; + responseData["ui-config"] = uiConfig; + + responseData["inventory-skeleton"] = agentInventory; + responseData["inventory-skel-lib"] = inventoryLibrary; + responseData["inventory-root"] = inventoryRoot; + responseData["inventory-lib-root"] = inventoryLibRoot; + responseData["gestures"] = new ArrayList(); // todo + responseData["inventory-lib-owner"] = inventoryLibraryOwner; + responseData["initial-outfit"] = initialOutfit; + responseData["start_location"] = startLocation; + responseData["seed_capability"] = seedCapability; + responseData["home"] = home; + responseData["look_at"] = lookAt; + responseData["message"] = welcomeMessage; + responseData["region_x"] = (Int32)(RegionX * Constants.RegionSize); + responseData["region_y"] = (Int32)(RegionY * Constants.RegionSize); + + //responseData["inventory-lib-root"] = new ArrayList(); // todo + + if (m_buddyList != null) + { + responseData["buddy-list"] = m_buddyList.ToArray(); + } + + responseData["login"] = "true"; + xmlRpcResponse.Value = responseData; + + return (xmlRpcResponse); + } + catch (Exception e) + { + m_log.Warn("[CLIENT]: LoginResponse: Error creating XML-RPC Response: " + e.Message); + + return (GenerateFailureResponse("Internal Error", "Error generating Login Response", "false")); + } + } // ToXmlRpcResponse + + public LLSD ToLLSDResponse() + { + try + { + LLSDMap map = new LLSDMap(); + + map["first_name"] = LLSD.FromString(Firstname); + map["last_name"] = LLSD.FromString(Lastname); + map["agent_access"] = LLSD.FromString(agentAccess); + + map["sim_port"] = LLSD.FromInteger(SimPort); + map["sim_ip"] = LLSD.FromString(SimAddress); + + map["agent_id"] = LLSD.FromUUID(AgentID); + map["session_id"] = LLSD.FromUUID(SessionID); + map["secure_session_id"] = LLSD.FromUUID(SecureSessionID); + map["circuit_code"] = LLSD.FromInteger(CircuitCode); + map["seconds_since_epoch"] = LLSD.FromInteger((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds); + + #region Login Flags + + LLSDMap loginFlagsLLSD = new LLSDMap(); + loginFlagsLLSD["daylight_savings"] = LLSD.FromString(DST); + loginFlagsLLSD["stipend_since_login"] = LLSD.FromString(StipendSinceLogin); + loginFlagsLLSD["gendered"] = LLSD.FromString(Gendered); + loginFlagsLLSD["ever_logged_in"] = LLSD.FromString(EverLoggedIn); + map["login-flags"] = WrapLLSDMap(loginFlagsLLSD); + + #endregion Login Flags + + #region Global Textures + + LLSDMap globalTexturesLLSD = new LLSDMap(); + globalTexturesLLSD["sun_texture_id"] = LLSD.FromString(SunTexture); + globalTexturesLLSD["cloud_texture_id"] = LLSD.FromString(CloudTexture); + globalTexturesLLSD["moon_texture_id"] = LLSD.FromString(MoonTexture); + + map["global-textures"] = WrapLLSDMap(globalTexturesLLSD); + + #endregion Global Textures + + map["seed_capability"] = LLSD.FromString(seedCapability); + + // FIXME: Need a function that will convert these ArrayLists in to LLSDArrays, + // and convert the data inside them to LLSD objects as well + + //map["event_categories"] = eventCategories; + //map["event_notifications"] = new LLSDArray(); // todo + //map["classified_categories"] = classifiedCategories; + + #region UI Config + + LLSDMap uiConfigLLSD = new LLSDMap(); + uiConfigLLSD["allow_first_life"] = LLSD.FromString(allowFirstLife); + map["ui-config"] = WrapLLSDMap(uiConfigLLSD); + + #endregion UI Config + + #region Inventory + + //map["inventory-skeleton"] = agentInventory; + //map["inventory-skel-lib"] = inventoryLibrary; + //map["inventory-root"] = inventoryRoot; + //map["inventory-lib-root"] = inventoryLibRoot; + //map["inventory-lib-owner"] = inventoryLibraryOwner; + + #endregion Inventory + + map["gestures"] = new LLSDArray(); // todo + + //responseData["initial-outfit"] = initialOutfit; + //responseData["start_location"] = startLocation; + + map["seed_capability"] = LLSD.FromString(seedCapability); + map["home"] = LLSD.FromString(home); + map["look_at"] = LLSD.FromString(lookAt); + map["message"] = LLSD.FromString(welcomeMessage); + map["region_x"] = LLSD.FromInteger(RegionX * Constants.RegionSize); + map["region_y"] = LLSD.FromInteger(RegionY * Constants.RegionSize); + + if (m_buddyList != null) + { + //map["buddy-list"] = m_buddyList.ToArray(); + } + + map["login"] = LLSD.FromString("true"); + + return map; + } + catch (Exception e) + { + m_log.Warn("[CLIENT]: LoginResponse: Error creating XML-RPC Response: " + e.Message); + + return GenerateFailureResponseLLSD("Internal Error", "Error generating Login Response", "false"); + } + } + + private LLSDArray WrapLLSDMap(LLSDMap wrapMe) + { + LLSDArray array = new LLSDArray(); + array.Add(wrapMe); + return array; + } + + public void SetEventCategories(string category, string value) + { + // this.eventCategoriesHash[category] = value; + //TODO + } // SetEventCategories + + public void AddToUIConfig(string itemName, string item) + { + uiConfigHash[itemName] = item; + } // SetUIConfig + + public void AddClassifiedCategory(Int32 ID, string categoryName) + { + Hashtable hash = new Hashtable(); + hash["category_name"] = categoryName; + hash["category_id"] = ID; + classifiedCategories.Add(hash); + // this.classifiedCategoriesHash.Clear(); + } // SetClassifiedCategory + + #region Properties + + public string Login + { + get { return login; } + set { login = value; } + } // Login + + public string DST + { + get { return dst; } + set { dst = value; } + } // DST + + public string StipendSinceLogin + { + get { return stipendSinceLogin; } + set { stipendSinceLogin = value; } + } // StipendSinceLogin + + public string Gendered + { + get { return gendered; } + set { gendered = value; } + } // Gendered + + public string EverLoggedIn + { + get { return everLoggedIn; } + set { everLoggedIn = value; } + } // EverLoggedIn + + public uint SimPort + { + get { return simPort; } + set { simPort = value; } + } // SimPort + + public string SimAddress + { + get { return simAddress; } + set { simAddress = value; } + } // SimAddress + + public LLUUID AgentID + { + get { return agentID; } + set { agentID = value; } + } // AgentID + + public LLUUID SessionID + { + get { return sessionID; } + set { sessionID = value; } + } // SessionID + + public LLUUID SecureSessionID + { + get { return secureSessionID; } + set { secureSessionID = value; } + } // SecureSessionID + + public Int32 CircuitCode + { + get { return circuitCode; } + set { circuitCode = value; } + } // CircuitCode + + public uint RegionX + { + get { return regionX; } + set { regionX = value; } + } // RegionX + + public uint RegionY + { + get { return regionY; } + set { regionY = value; } + } // RegionY + + public string SunTexture + { + get { return sunTexture; } + set { sunTexture = value; } + } // SunTexture + + public string CloudTexture + { + get { return cloudTexture; } + set { cloudTexture = value; } + } // CloudTexture + + public string MoonTexture + { + get { return moonTexture; } + set { moonTexture = value; } + } // MoonTexture + + public string Firstname + { + get { return firstname; } + set { firstname = value; } + } // Firstname + + public string Lastname + { + get { return lastname; } + set { lastname = value; } + } // Lastname + + public string AgentAccess + { + get { return agentAccess; } + set { agentAccess = value; } + } + + public string StartLocation + { + get { return startLocation; } + set { startLocation = value; } + } // StartLocation + + public string LookAt + { + get { return lookAt; } + set { lookAt = value; } + } + + public string SeedCapability + { + get { return seedCapability; } + set { seedCapability = value; } + } // SeedCapability + + public string ErrorReason + { + get { return errorReason; } + set { errorReason = value; } + } // ErrorReason + + public string ErrorMessage + { + get { return errorMessage; } + set { errorMessage = value; } + } // ErrorMessage + + public ArrayList InventoryRoot + { + get { return inventoryRoot; } + set { inventoryRoot = value; } + } + + public ArrayList InventorySkeleton + { + get { return agentInventory; } + set { agentInventory = value; } + } + + public ArrayList InventoryLibrary + { + get { return inventoryLibrary; } + set { inventoryLibrary = value; } + } + + public ArrayList InventoryLibraryOwner + { + get { return inventoryLibraryOwner; } + set { inventoryLibraryOwner = value; } + } + + public ArrayList InventoryLibRoot + { + get { return inventoryLibRoot; } + set { inventoryLibRoot = value; } + } + + public string Home + { + get { return home; } + set { home = value; } + } + + public string Message + { + get { return welcomeMessage; } + set { welcomeMessage = value; } + } + + public BuddyList BuddList + { + get { return m_buddyList; } + set { m_buddyList = value; } + } + + #endregion + + public class UserInfo + { + public string firstname; + public string lastname; + public ulong homeregionhandle; + public LLVector3 homepos; + public LLVector3 homelookat; + } + + public class BuddyList + { + public List Buddies = new List(); + + public void AddNewBuddy(BuddyInfo buddy) + { + if (!Buddies.Contains(buddy)) + { + Buddies.Add(buddy); + } + } + + public ArrayList ToArray() + { + ArrayList buddyArray = new ArrayList(); + foreach (BuddyInfo buddy in Buddies) + { + buddyArray.Add(buddy.ToHashTable()); + } + return buddyArray; + } + + public class BuddyInfo + { + public int BuddyRightsHave = 1; + public int BuddyRightsGiven = 1; + public LLUUID BuddyID; + + public BuddyInfo(string buddyID) + { + BuddyID = new LLUUID(buddyID); + } + + public BuddyInfo(LLUUID buddyID) + { + BuddyID = buddyID; + } + + public Hashtable ToHashTable() + { + Hashtable hTable = new Hashtable(); + hTable["buddy_rights_has"] = BuddyRightsHave; + hTable["buddy_rights_given"] = BuddyRightsGiven; + hTable["buddy_id"] = BuddyID.ToString(); + return hTable; + } + } + } + } +} diff --git a/trunk/OpenSim/Framework/Communications/LoginService.cs b/trunk/OpenSim/Framework/Communications/LoginService.cs new file mode 100644 index 0000000000..e14eccf31e --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/LoginService.cs @@ -0,0 +1,758 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using System.Threading; +using libsecondlife; +using libsecondlife.StructuredData; +using Nwc.XmlRpc; + +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Statistics; + +namespace OpenSim.Framework.UserManagement +{ + public class LoginService + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected string m_welcomeMessage = "Welcome to OpenSim"; + protected UserManagerBase m_userManager = null; + protected Mutex m_loginMutex = new Mutex(false); + + /// + /// Used during login to send the skeleton of the OpenSim Library to the client. + /// + protected LibraryRootFolder m_libraryRootFolder; + + /// + /// Constructor + /// + /// + /// + /// + public LoginService(UserManagerBase userManager, LibraryRootFolder libraryRootFolder, + string welcomeMess) + { + m_userManager = userManager; + m_libraryRootFolder = libraryRootFolder; + + if (welcomeMess != String.Empty) + { + m_welcomeMessage = welcomeMess; + } + } + + /// + /// Main user login function + /// + /// The XMLRPC request + /// The response to send + public XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request) + { + // Temporary fix + m_loginMutex.WaitOne(); + try + { + //CFK: CustomizeResponse contains sufficient strings to alleviate the need for this. + //CKF: m_log.Info("[LOGIN]: Attempting login now..."); + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable) request.Params[0]; + + bool GoodXML = (requestData.Contains("first") && requestData.Contains("last") && + (requestData.Contains("passwd") || requestData.Contains("web_login_key"))); + bool GoodLogin = false; + + UserProfileData userProfile; + LoginResponse logResponse = new LoginResponse(); + + if (GoodXML) + { + string firstname = (string) requestData["first"]; + string lastname = (string) requestData["last"]; + + if( requestData.Contains("version")) + { + string clientversion = (string)requestData["version"]; + m_log.Info("[LOGIN]: Client Version " + clientversion + " for " + firstname + " " + lastname); + } + + + userProfile = GetTheUser(firstname, lastname); + if (userProfile == null) + { + m_log.Info("[LOGIN]: Could not find a profile for " + firstname + " " + lastname); + + return logResponse.CreateLoginFailedResponse(); + } + if (requestData.Contains("passwd")) + { + string passwd = (string)requestData["passwd"]; + GoodLogin = AuthenticateUser(userProfile, passwd); + } + else if (requestData.Contains("web_login_key")) + { + LLUUID webloginkey = null; + try + { + webloginkey = new LLUUID((string)requestData["web_login_key"]); + } + catch (System.Exception) + { + return logResponse.CreateFailedResponse(); + } + GoodLogin = AuthenticateUser(userProfile, webloginkey); + + } + else + { + return logResponse.CreateFailedResponse(); + } + } + else + { + return logResponse.CreateGridErrorResponse(); + } + + if (!GoodLogin) + { + return logResponse.CreateLoginFailedResponse(); + } + else + { + // If we already have a session... + + if (userProfile.currentAgent != null && userProfile.currentAgent.agentOnline) + { + userProfile.currentAgent = null; + m_userManager.CommitAgent(ref userProfile); + + // Reject the login + return logResponse.CreateAlreadyLoggedInResponse(); + } + // Otherwise... + // Create a new agent session + CreateAgent(userProfile, request); + + try + { + LLUUID agentID = userProfile.UUID; + + // Inventory Library Section + InventoryData inventData = CreateInventoryData(agentID); + ArrayList AgentInventoryArray = inventData.InventoryArray; + + Hashtable InventoryRootHash = new Hashtable(); + InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString(); + ArrayList InventoryRoot = new ArrayList(); + InventoryRoot.Add(InventoryRootHash); + userProfile.rootInventoryFolderID = inventData.RootFolderID; + + // Circuit Code + uint circode = (uint) (Util.RandomClass.Next()); + + logResponse.Lastname = userProfile.surname; + logResponse.Firstname = userProfile.username; + logResponse.AgentID = agentID.ToString(); + logResponse.SessionID = userProfile.currentAgent.sessionID.ToString(); + logResponse.SecureSessionID = userProfile.currentAgent.secureSessionID.ToString(); + logResponse.InventoryRoot = InventoryRoot; + logResponse.InventorySkeleton = AgentInventoryArray; + logResponse.InventoryLibrary = GetInventoryLibrary(); + + Hashtable InventoryLibRootHash = new Hashtable(); + InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000"; + ArrayList InventoryLibRoot = new ArrayList(); + InventoryLibRoot.Add(InventoryLibRootHash); + logResponse.InventoryLibRoot = InventoryLibRoot; + + logResponse.InventoryLibraryOwner = GetLibraryOwner(); + logResponse.CircuitCode = (Int32) circode; + //logResponse.RegionX = 0; //overwritten + //logResponse.RegionY = 0; //overwritten + logResponse.Home = "!!null temporary value {home}!!"; // Overwritten + //logResponse.LookAt = "\n[r" + TheUser.homeLookAt.X.ToString() + ",r" + TheUser.homeLookAt.Y.ToString() + ",r" + TheUser.homeLookAt.Z.ToString() + "]\n"; + //logResponse.SimAddress = "127.0.0.1"; //overwritten + //logResponse.SimPort = 0; //overwritten + logResponse.Message = GetMessage(); + logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID)); + + try + { + CustomiseResponse(logResponse, userProfile); + } + catch (Exception e) + { + m_log.Info("[LOGIN]: " + e.ToString()); + return logResponse.CreateDeadRegionResponse(); + //return logResponse.ToXmlRpcResponse(); + } + CommitAgent(ref userProfile); + + // If we reach this point, then the login has successfully logged onto the grid + if (StatsManager.UserStats != null) + StatsManager.UserStats.AddSuccessfulLogin(); + + return logResponse.ToXmlRpcResponse(); + } + catch (Exception e) + { + m_log.Info("[LOGIN]: " + e.ToString()); + } + //} + } + return response; + } + finally + { + m_loginMutex.ReleaseMutex(); + } + } + + public LLSD LLSDLoginMethod(LLSD request) + { + // Temporary fix + m_loginMutex.WaitOne(); + + try + { + bool GoodLogin = false; + + UserProfileData userProfile = null; + LoginResponse logResponse = new LoginResponse(); + + if (request.Type == LLSDType.Map) + { + LLSDMap map = (LLSDMap)request; + + if (map.ContainsKey("first") && map.ContainsKey("last") && map.ContainsKey("passwd")) + { + string firstname = map["first"].AsString(); + string lastname = map["last"].AsString(); + string passwd = map["passwd"].AsString(); + + userProfile = GetTheUser(firstname, lastname); + if (userProfile == null) + { + m_log.Info("[LOGIN]: Could not find a profile for " + firstname + " " + lastname); + + return logResponse.CreateLoginFailedResponseLLSD(); + } + + GoodLogin = AuthenticateUser(userProfile, passwd); + } + } + + if (!GoodLogin) + { + return logResponse.CreateLoginFailedResponseLLSD(); + } + else + { + // If we already have a session... + if (userProfile.currentAgent != null && userProfile.currentAgent.agentOnline) + { + userProfile.currentAgent = null; + m_userManager.CommitAgent(ref userProfile); + + // Reject the login + return logResponse.CreateAlreadyLoggedInResponseLLSD(); + } + + // Otherwise... + // Create a new agent session + CreateAgent(userProfile, request); + + try + { + LLUUID agentID = userProfile.UUID; + + // Inventory Library Section + InventoryData inventData = CreateInventoryData(agentID); + ArrayList AgentInventoryArray = inventData.InventoryArray; + + Hashtable InventoryRootHash = new Hashtable(); + InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString(); + ArrayList InventoryRoot = new ArrayList(); + InventoryRoot.Add(InventoryRootHash); + userProfile.rootInventoryFolderID = inventData.RootFolderID; + + // Circuit Code + uint circode = (uint)(Util.RandomClass.Next()); + + logResponse.Lastname = userProfile.surname; + logResponse.Firstname = userProfile.username; + logResponse.AgentID = agentID.ToString(); + logResponse.SessionID = userProfile.currentAgent.sessionID.ToString(); + logResponse.SecureSessionID = userProfile.currentAgent.secureSessionID.ToString(); + logResponse.InventoryRoot = InventoryRoot; + logResponse.InventorySkeleton = AgentInventoryArray; + logResponse.InventoryLibrary = GetInventoryLibrary(); + + Hashtable InventoryLibRootHash = new Hashtable(); + InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000"; + ArrayList InventoryLibRoot = new ArrayList(); + InventoryLibRoot.Add(InventoryLibRootHash); + logResponse.InventoryLibRoot = InventoryLibRoot; + + logResponse.InventoryLibraryOwner = GetLibraryOwner(); + logResponse.CircuitCode = (Int32)circode; + //logResponse.RegionX = 0; //overwritten + //logResponse.RegionY = 0; //overwritten + logResponse.Home = "!!null temporary value {home}!!"; // Overwritten + //logResponse.LookAt = "\n[r" + TheUser.homeLookAt.X.ToString() + ",r" + TheUser.homeLookAt.Y.ToString() + ",r" + TheUser.homeLookAt.Z.ToString() + "]\n"; + //logResponse.SimAddress = "127.0.0.1"; //overwritten + //logResponse.SimPort = 0; //overwritten + logResponse.Message = GetMessage(); + logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID)); + + try + { + CustomiseResponse(logResponse, userProfile); + } + catch (Exception ex) + { + m_log.Info("[LOGIN]: " + ex.ToString()); + return logResponse.CreateDeadRegionResponseLLSD(); + } + + CommitAgent(ref userProfile); + + // If we reach this point, then the login has successfully logged onto the grid + if (StatsManager.UserStats != null) + StatsManager.UserStats.AddSuccessfulLogin(); + + return logResponse.ToLLSDResponse(); + } + catch (Exception ex) + { + m_log.Info("[LOGIN]: " + ex.ToString()); + return logResponse.CreateFailedResponseLLSD(); + } + } + } + finally + { + m_loginMutex.ReleaseMutex(); + } + } + + /// + /// Customises the login response and fills in missing values. + /// + /// The existing response + /// The user profile + public virtual void CustomiseResponse(LoginResponse response, UserProfileData theUser) + { + } + + public Hashtable ProcessHTMLLogin(Hashtable keysvals) + { + + // Matches all unspecified characters + // Currently specified,; lowercase letters, upper case letters, numbers, underline + // period, space, parens, and dash. + + Regex wfcut = new Regex("[^a-zA-Z0-9_\\.\\$ \\(\\)\\-]"); + + Hashtable returnactions = new Hashtable(); + int statuscode = 200; + + string firstname = String.Empty; + string lastname = String.Empty; + string location = String.Empty; + string region =String.Empty; + string grid = String.Empty; + string channel = String.Empty; + string version = String.Empty; + string lang = String.Empty; + string password = String.Empty; + string errormessages = String.Empty; + + // the client requires the HTML form field be named 'username' + // however, the data it sends when it loads the first time is 'firstname' + // another one of those little nuances. + + + if (keysvals.Contains("firstname")) + firstname = wfcut.Replace((string)keysvals["firstname"],String.Empty,99999); + if (keysvals.Contains("username")) + firstname = wfcut.Replace((string)keysvals["username"],String.Empty,99999); + + if (keysvals.Contains("lastname")) + lastname = wfcut.Replace((string)keysvals["lastname"],String.Empty,99999); + + if (keysvals.Contains("location")) + location = wfcut.Replace((string)keysvals["location"],String.Empty,99999); + + if (keysvals.Contains("region")) + region = wfcut.Replace((string)keysvals["region"],String.Empty,99999); + + if (keysvals.Contains("grid")) + grid = wfcut.Replace((string)keysvals["grid"],String.Empty,99999); + + if (keysvals.Contains("channel")) + channel = wfcut.Replace((string)keysvals["channel"],String.Empty,99999); + + if (keysvals.Contains("version")) + version = wfcut.Replace((string)keysvals["version"],String.Empty,99999); + + if (keysvals.Contains("lang")) + lang = wfcut.Replace((string)keysvals["lang"],String.Empty,99999); + + if (keysvals.Contains("password")) + password = wfcut.Replace((string)keysvals["password"], String.Empty, 99999); + + + // load our login form. + string loginform = GetLoginForm(firstname,lastname,location,region,grid,channel,version,lang,password,errormessages); + + if (keysvals.ContainsKey("show_login_form")) + { + + UserProfileData user = GetTheUser(firstname, lastname); + bool goodweblogin = false; + + if (user != null) + goodweblogin = AuthenticateUser(user, password); + + if (goodweblogin) + { + LLUUID webloginkey = LLUUID.Random(); + m_userManager.StoreWebLoginKey(user.UUID, webloginkey); + statuscode = 301; + + string redirectURL = "about:blank?redirect-http-hack=" + System.Web.HttpUtility.UrlEncode("secondlife:///app/login?first_name=" + firstname + "&last_name=" + + lastname + + "&location=" + location + "&grid=Other&web_login_key=" + webloginkey.ToString()); + //m_log.Info("[WEB]: R:" + redirectURL); + returnactions["int_response_code"] = statuscode; + returnactions["str_redirect_location"] = redirectURL; + returnactions["str_response_string"] = "GoodLogin"; + } + else + { + errormessages = "The Username and password supplied did not match our records. Check your caps lock and try again"; + + loginform = GetLoginForm(firstname, lastname, location, region, grid, channel, version, lang, password, errormessages); + returnactions["int_response_code"] = statuscode; + returnactions["str_response_string"] = loginform; + + } + + + + } + else + { + returnactions["int_response_code"] = statuscode; + returnactions["str_response_string"] = loginform; + } + return returnactions; + + } + + public string GetLoginForm(string firstname, string lastname, string location, string region, + string grid, string channel, string version, string lang, + string password, string errormessages) + { + // inject our values in the form at the markers + + string loginform=String.Empty; + string file = Path.Combine(Util.configDir(), "http_loginform.html"); + if (!File.Exists(file)) + { + loginform = GetDefaultLoginForm(); + } + else + { + StreamReader sr = File.OpenText(file); + loginform = sr.ReadToEnd(); + sr.Close(); + } + + loginform = loginform.Replace("[$firstname]", firstname); + loginform = loginform.Replace("[$lastname]", lastname); + loginform = loginform.Replace("[$location]", location); + loginform = loginform.Replace("[$region]", region); + loginform = loginform.Replace("[$grid]", grid); + loginform = loginform.Replace("[$channel]", channel); + loginform = loginform.Replace("[$version]", version); + loginform = loginform.Replace("[$lang]", lang); + loginform = loginform.Replace("[$password]", password); + loginform = loginform.Replace("[$errors]", errormessages); + return loginform; + } + + public string GetDefaultLoginForm() + { + string responseString = + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + "OpenSim Login"; + responseString = responseString + "
"; + responseString = responseString + "
"; + + responseString = responseString + "
"; + + responseString = responseString + "
[$errors]
"; + responseString = responseString + "
"; + responseString = responseString + "First Name:"; + responseString = responseString + ""; + responseString = responseString + "
"; + responseString = responseString + "
"; + responseString = responseString + "Last Name:"; + responseString = responseString + ""; + responseString = responseString + "
"; + responseString = responseString + "
"; + responseString = responseString + "Password:"; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + "
"; + responseString = responseString + "
"; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + "
"; + responseString = responseString + ""; + responseString = responseString + "
"; + responseString = responseString + "
Connecting...
"; + + responseString = responseString + "
"; + responseString = responseString + " | "; + responseString = responseString + ""; + responseString = responseString + "
"; + + responseString = responseString + "
[$channel] | [$version]=[$lang]
"; + responseString = responseString + "
"; + responseString = responseString + ""; + responseString = responseString + "
"; + responseString = responseString + ""; + responseString = responseString + ""; + responseString = responseString + ""; + return responseString; + } + + /// + /// Saves a target agent to the database + /// + /// The users profile + /// Successful? + public bool CommitAgent(ref UserProfileData profile) + { + return m_userManager.CommitAgent(ref profile); + } + + + /// + /// Checks a user against it's password hash + /// + /// The users profile + /// The supplied password + /// Authenticated? + public virtual bool AuthenticateUser(UserProfileData profile, string password) + { + bool passwordSuccess = false; + m_log.InfoFormat("[LOGIN]: Authenticating {0} {1} ({2})", profile.username, profile.surname, profile.UUID); + + // Web Login method seems to also occasionally send the hashed password itself + + // we do this to get our hash in a form that the server password code can consume + // when the web-login-form submits the password in the clear (supposed to be over SSL!) + if (!password.StartsWith("$1$")) + password = "$1$" + Util.Md5Hash(password); + + password = password.Remove(0, 3); //remove $1$ + + string s = Util.Md5Hash(password + ":" + profile.passwordSalt); + // Testing... + //m_log.Info("[LOGIN]: SubHash:" + s + " userprofile:" + profile.passwordHash); + //m_log.Info("[LOGIN]: userprofile:" + profile.passwordHash + " SubCT:" + password); + + passwordSuccess = (profile.passwordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase) + || profile.passwordHash.Equals(password,StringComparison.InvariantCultureIgnoreCase)); + + return passwordSuccess; + } + + public virtual bool AuthenticateUser(UserProfileData profile, LLUUID webloginkey) + { + bool passwordSuccess = false; + m_log.InfoFormat("[LOGIN]: Authenticating {0} {1} ({2})", profile.username, profile.surname, profile.UUID); + + // Match web login key unless it's the default weblogin key LLUUID.Zero + passwordSuccess = ((profile.webLoginKey==webloginkey) && profile.webLoginKey != LLUUID.Zero); + + return passwordSuccess; + } + + /// + /// + /// + /// + /// + public void CreateAgent(UserProfileData profile, XmlRpcRequest request) + { + m_userManager.CreateAgent(profile, request); + } + + public void CreateAgent(UserProfileData profile, LLSD request) + { + m_userManager.CreateAgent(profile, request); + } + + /// + /// + /// + /// + /// + /// + public virtual UserProfileData GetTheUser(string firstname, string lastname) + { + return m_userManager.GetUserProfile(firstname, lastname); + } + + /// + /// + /// + /// + public virtual string GetMessage() + { + return m_welcomeMessage; + } + + private LoginResponse.BuddyList ConvertFriendListItem(List LFL) + { + LoginResponse.BuddyList buddylistreturn = new LoginResponse.BuddyList(); + foreach (FriendListItem fl in LFL) + { + LoginResponse.BuddyList.BuddyInfo buddyitem = new LoginResponse.BuddyList.BuddyInfo(fl.Friend); + buddyitem.BuddyID = fl.Friend; + buddyitem.BuddyRightsHave = (int)fl.FriendListOwnerPerms; + buddyitem.BuddyRightsGiven = (int) fl.FriendPerms; + buddylistreturn.AddNewBuddy(buddyitem); + + } + return buddylistreturn; + } + + /// + /// Converts the inventory library skeleton into the form required by the rpc request. + /// + /// + protected virtual ArrayList GetInventoryLibrary() + { + Dictionary rootFolders + = m_libraryRootFolder.RequestSelfAndDescendentFolders(); + ArrayList folderHashes = new ArrayList(); + + foreach (InventoryFolderBase folder in rootFolders.Values) + { + Hashtable TempHash = new Hashtable(); + TempHash["name"] = folder.name; + TempHash["parent_id"] = folder.parentID.ToString(); + TempHash["version"] = (Int32)folder.version; + TempHash["type_default"] = (Int32)folder.type; + TempHash["folder_id"] = folder.folderID.ToString(); + folderHashes.Add(TempHash); + } + + return folderHashes; + } + + /// + /// + /// + /// + protected virtual ArrayList GetLibraryOwner() + { + //for now create random inventory library owner + Hashtable TempHash = new Hashtable(); + TempHash["agent_id"] = "11111111-1111-0000-0000-000100bba000"; + ArrayList inventoryLibOwner = new ArrayList(); + inventoryLibOwner.Add(TempHash); + return inventoryLibOwner; + } + + protected virtual InventoryData CreateInventoryData(LLUUID userID) + { + AgentInventory userInventory = new AgentInventory(); + userInventory.CreateRootFolder(userID, false); + + ArrayList AgentInventoryArray = new ArrayList(); + Hashtable TempHash; + foreach (InventoryFolder InvFolder in userInventory.InventoryFolders.Values) + { + TempHash = new Hashtable(); + TempHash["name"] = InvFolder.FolderName; + TempHash["parent_id"] = InvFolder.ParentID.ToString(); + TempHash["version"] = (Int32) InvFolder.Version; + TempHash["type_default"] = (Int32) InvFolder.DefaultType; + TempHash["folder_id"] = InvFolder.FolderID.ToString(); + AgentInventoryArray.Add(TempHash); + } + + return new InventoryData(AgentInventoryArray, userInventory.InventoryRoot.FolderID); + } + + public class InventoryData + { + public ArrayList InventoryArray = null; + public LLUUID RootFolderID = LLUUID.Zero; + + public InventoryData(ArrayList invList, LLUUID rootID) + { + InventoryArray = invList; + RootFolderID = rootID; + } + } + } +} diff --git a/trunk/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs b/trunk/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..8b6d937f8c --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs @@ -0,0 +1,65 @@ +/* +* 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("OpenGrid.Framework.Communications")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenGrid.Framework.Communications")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("13e7c396-78a9-4a5c-baf2-6f980ea75d95")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/RestClient/GenericAsyncResult.cs b/trunk/OpenSim/Framework/Communications/RestClient/GenericAsyncResult.cs new file mode 100644 index 0000000000..b67aad9796 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/RestClient/GenericAsyncResult.cs @@ -0,0 +1,186 @@ +/* +* 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; +using System.Threading; + +namespace OpenSim.Framework.Communications +{ + internal class SimpleAsyncResult : IAsyncResult + { + private readonly AsyncCallback m_callback; + + /// + /// Is process completed? + /// + /// Should really be boolean, but VolatileRead has no boolean method + private byte m_completed; + + /// + /// Did process complete synchroneously? + /// + /// I have a hard time imagining a scenario where this is the case, again, same issue about + /// booleans and VolatileRead as m_completed + /// + private byte m_completedSynchronously; + + private readonly object m_asyncState; + private ManualResetEvent m_waitHandle; + private Exception m_exception; + + internal SimpleAsyncResult(AsyncCallback cb, object state) + { + m_callback = cb; + m_asyncState = state; + m_completed = 0; + m_completedSynchronously = 1; + } + + #region IAsyncResult Members + + public object AsyncState + { + get { return m_asyncState; } + } + + + public WaitHandle AsyncWaitHandle + { + get + { + if (m_waitHandle == null) + { + bool done = IsCompleted; + ManualResetEvent mre = new ManualResetEvent(done); + if (Interlocked.CompareExchange(ref m_waitHandle, mre, null) != null) + { + mre.Close(); + } + else + { + if (!done && IsCompleted) + { + m_waitHandle.Set(); + } + } + } + return m_waitHandle; + } + } + + + public bool CompletedSynchronously + { + get { return Thread.VolatileRead(ref m_completedSynchronously) == 1; } + } + + + public bool IsCompleted + { + get { return Thread.VolatileRead(ref m_completed) == 1; } + } + + #endregion + + #region class Methods + + internal void SetAsCompleted(bool completedSynchronously) + { + m_completed = 1; + if (completedSynchronously) + m_completedSynchronously = 1; + else + m_completedSynchronously = 0; + + SignalCompletion(); + } + + internal void HandleException(Exception e, bool completedSynchronously) + { + m_completed = 1; + if (completedSynchronously) + m_completedSynchronously = 1; + else + m_completedSynchronously = 0; + m_exception = e; + + SignalCompletion(); + } + + private void SignalCompletion() + { + if (m_waitHandle != null) m_waitHandle.Set(); + + if (m_callback != null) m_callback(this); + } + + public void EndInvoke() + { + // This method assumes that only 1 thread calls EndInvoke + if (!IsCompleted) + { + // If the operation isn't done, wait for it + AsyncWaitHandle.WaitOne(); + AsyncWaitHandle.Close(); + m_waitHandle = null; // Allow early GC + } + + // Operation is done: if an exception occured, throw it + if (m_exception != null) throw m_exception; + } + + #endregion + } + + internal class AsyncResult : SimpleAsyncResult + { + private T m_result = default(T); + + public AsyncResult(AsyncCallback asyncCallback, Object state) : + base(asyncCallback, state) + { + } + + + public void SetAsCompleted(T result, bool completedSynchronously) + { + // Save the asynchronous operation's result + m_result = result; + + // Tell the base class that the operation completed + // sucessfully (no exception) + base.SetAsCompleted(completedSynchronously); + } + + public new T EndInvoke() + { + base.EndInvoke(); + return m_result; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/RestClient/RestClient.cs b/trunk/OpenSim/Framework/Communications/RestClient/RestClient.cs new file mode 100644 index 0000000000..bf815652e6 --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/RestClient/RestClient.cs @@ -0,0 +1,446 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text; +using System.Threading; +using System.Web; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Communications +{ + /// + /// Implementation of a generic REST client + /// + /// + /// This class is a generic implementation of a REST (Representational State Transfer) web service. This + /// class is designed to execute both synchroneously and asynchroneously. + /// + /// Internally the implementation works as a two stage asynchroneous web-client. + /// When the request is initiated, RestClient will query asynchroneously for for a web-response, + /// sleeping until the initial response is returned by the server. Once the initial response is retrieved + /// the second stage of asynchroneous requests will be triggered, in an attempt to read of the response + /// object into a memorystream as a sequence of asynchroneous reads. + /// + /// The asynchronisity of RestClient is designed to move as much processing into the back-ground, allowing + /// other threads to execute, while it waits for a response from the web-service. RestClient it self, can be + /// invoked by the caller in either synchroneous mode or asynchroneous mode. + /// + public class RestClient + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private string realuri; + + #region member variables + + /// + /// The base Uri of the web-service e.g. http://www.google.com + /// + private string _url; + + /// + /// Path elements of the query + /// + private List _pathElements = new List(); + + /// + /// Parameter elements of the query, e.g. min=34 + /// + private Dictionary _parameterElements = new Dictionary(); + + /// + /// Request method. E.g. GET, POST, PUT or DELETE + /// + private string _method; + + /// + /// Temporary buffer used to store bytes temporarily as they come in from the server + /// + private byte[] _readbuf; + + /// + /// MemoryStream representing the resultiong resource + /// + private Stream _resource; + + /// + /// WebRequest object, held as a member variable + /// + private HttpWebRequest _request; + + /// + /// WebResponse object, held as a member variable, so we can close it + /// + private HttpWebResponse _response; + + /// + /// This flag will help block the main synchroneous method, in case we run in synchroneous mode + /// + public static ManualResetEvent _allDone = new ManualResetEvent(false); + + /// + /// Default time out period + /// + private const int DefaultTimeout = 10*1000; // 10 seconds timeout + + /// + /// Default Buffer size of a block requested from the web-server + /// + private const int BufferSize = 4096; // Read blocks of 4 KB. + + + /// + /// if an exception occours during async processing, we need to save it, so it can be + /// rethrown on the primary thread; + /// + private Exception _asyncException; + + #endregion member variables + + #region constructors + + /// + /// Instantiate a new RestClient + /// + /// Web-service to query, e.g. http://osgrid.org:8003 + public RestClient(string url) + { + _url = url; + _readbuf = new byte[BufferSize]; + _resource = new MemoryStream(); + _request = null; + _response = null; + _lock = new object(); + } + + private object _lock; + + #endregion constructors + + /// + /// Add a path element to the query, e.g. assets + /// + /// path entry + public void AddResourcePath(string element) + { + if (isSlashed(element)) + _pathElements.Add(element.Substring(0, element.Length - 1)); + else + _pathElements.Add(element); + } + + /// + /// Add a query parameter to the Url + /// + /// Name of the parameter, e.g. min + /// Value of the parameter, e.g. 42 + public void AddQueryParameter(string name, string value) + { + _parameterElements.Add(HttpUtility.UrlEncode(name), HttpUtility.UrlEncode(value)); + } + + /// + /// Add a query parameter to the Url + /// + /// Name of the parameter, e.g. min + public void AddQueryParameter(string name) + { + _parameterElements.Add(HttpUtility.UrlEncode(name), null); + } + + /// + /// Web-Request method, e.g. GET, PUT, POST, DELETE + /// + public string RequestMethod + { + get { return _method; } + set { _method = value; } + } + + /// + /// True if string contains a trailing slash '/' + /// + /// string to be examined + /// true if slash is present + private bool isSlashed(string s) + { + return s.Substring(s.Length - 1, 1) == "/"; + } + + /// + /// return a slash or blank. A slash will be returned if the string does not contain one + /// + /// stromg to be examined + /// slash '/' if not already present + private string slash(string s) + { + return isSlashed(s) ? String.Empty : "/"; + } + + /// + /// Build a Uri based on the initial Url, path elements and parameters + /// + /// fully constructed Uri + private Uri buildUri() + { + StringBuilder sb = new StringBuilder(); + sb.Append(_url); + + foreach (string e in _pathElements) + { + sb.Append("/"); + sb.Append(e); + } + + bool firstElement = true; + foreach (KeyValuePair kv in _parameterElements) + { + if (firstElement) + { + sb.Append("?"); + firstElement = false; + } + else + sb.Append("&"); + + sb.Append(kv.Key); + if (kv.Value != null && kv.Value.Length != 0) + { + sb.Append("="); + sb.Append(kv.Value); + } + } + realuri = sb.ToString(); + m_log.InfoFormat("[REST]: RestURL: {0}", realuri); + return new Uri(sb.ToString()); + } + + #region Async communications with server + + /// + /// Async method, invoked when a block of data has been received from the service + /// + /// + private void StreamIsReadyDelegate(IAsyncResult ar) + { + try + { + Stream s = (Stream) ar.AsyncState; + int read = s.EndRead(ar); + + if (read > 0) + { + _resource.Write(_readbuf, 0, read); + IAsyncResult asynchronousResult = + s.BeginRead(_readbuf, 0, BufferSize, new AsyncCallback(StreamIsReadyDelegate), s); + + // TODO! Implement timeout, without killing the server + //ThreadPool.RegisterWaitForSingleObject(asynchronousResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); + } + else + { + s.Close(); + _allDone.Set(); + } + } + catch (Exception e) + { + _allDone.Set(); + _asyncException = e; + } + } + + /// + /// Async method, invoked when the initial response if received from the server + /// + /// + private void ResponseIsReadyDelegate(IAsyncResult ar) + { + try + { + // grab response + WebRequest wr = (WebRequest) ar.AsyncState; + _response = (HttpWebResponse) wr.EndGetResponse(ar); + + // get response stream, and setup async reading + Stream s = _response.GetResponseStream(); + IAsyncResult asynchronousResult = + s.BeginRead(_readbuf, 0, BufferSize, new AsyncCallback(StreamIsReadyDelegate), s); + + // TODO! Implement timeout, without killing the server + // wait until completed, or we timed out + // ThreadPool.RegisterWaitForSingleObject(asynchronousResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); + } + catch (Exception e) + { + _allDone.Set(); + _asyncException = e; + } + } + + // Abort the request if the timer fires. + private static void TimeoutCallback(object state, bool timedOut) + { + if (timedOut) + { + HttpWebRequest request = state as HttpWebRequest; + if (request != null) + { + request.Abort(); + } + } + } + + #endregion Async communications with server + + /// + /// Perform synchroneous request + /// + public Stream Request() + { + lock (_lock) + { + _request = (HttpWebRequest) WebRequest.Create(buildUri()); + _request.KeepAlive = false; + _request.ContentType = "application/xml"; + _request.Timeout = 200000; + _asyncException = null; + +// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); + _response = (HttpWebResponse) _request.GetResponse(); + Stream src = _response.GetResponseStream(); + int length = src.Read(_readbuf, 0, BufferSize); + while (length > 0) + { + _resource.Write(_readbuf, 0, length); + length = src.Read(_readbuf, 0, BufferSize); + } + + + // TODO! Implement timeout, without killing the server + // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted + //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); + +// _allDone.WaitOne(); + if (_response != null) + _response.Close(); + if (_asyncException != null) + throw _asyncException; + + if (_resource != null) + { + _resource.Flush(); + _resource.Seek(0, SeekOrigin.Begin); + } + + return _resource; + } + } + + public Stream Request(Stream src) + { + _request = (HttpWebRequest) WebRequest.Create(buildUri()); + _request.KeepAlive = false; + _request.ContentType = "application/xml"; + _request.Timeout = 900000; + _request.Method = RequestMethod; + _asyncException = null; + _request.ContentLength = src.Length; + + m_log.InfoFormat("[REST]: Request Length {0}", _request.ContentLength); + m_log.InfoFormat("[REST]: Sending Web Request {0}", buildUri()); + src.Seek(0, SeekOrigin.Begin); + m_log.Info("[REST]: Seek is ok"); + Stream dst = _request.GetRequestStream(); + m_log.Info("[REST]: GetRequestStream is ok"); + + byte[] buf = new byte[1024]; + int length = src.Read(buf, 0, 1024); + m_log.Info("[REST]: First Read is ok"); + while (length > 0) + { + dst.Write(buf, 0, length); + length = src.Read(buf, 0, 1024); + } + + _response = (HttpWebResponse) _request.GetResponse(); + +// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); + + // TODO! Implement timeout, without killing the server + // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted + //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); + + return null; + } + + #region Async Invocation + + public IAsyncResult BeginRequest(AsyncCallback callback, object state) + { + /// + /// In case, we are invoked asynchroneously this object will keep track of the state + /// + AsyncResult ar = new AsyncResult(callback, state); + ThreadPool.QueueUserWorkItem(RequestHelper, ar); + return ar; + } + + public Stream EndRequest(IAsyncResult asyncResult) + { + AsyncResult ar = (AsyncResult) asyncResult; + + // Wait for operation to complete, then return result or + // throw exception + return ar.EndInvoke(); + } + + private void RequestHelper(Object asyncResult) + { + // We know that it's really an AsyncResult object + AsyncResult ar = (AsyncResult) asyncResult; + try + { + // Perform the operation; if sucessful set the result + Stream s = Request(); + ar.SetAsCompleted(s, false); + } + catch (Exception e) + { + // If operation fails, set the exception + ar.HandleException(e, false); + } + } + + #endregion Async Invocation + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Communications/UserManagerBase.cs b/trunk/OpenSim/Framework/Communications/UserManagerBase.cs new file mode 100644 index 0000000000..dbf92767af --- /dev/null +++ b/trunk/OpenSim/Framework/Communications/UserManagerBase.cs @@ -0,0 +1,550 @@ +/* +* 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; +using System.Collections.Generic; +using System.Reflection; +using System.Security.Cryptography; +using libsecondlife; +using libsecondlife.StructuredData; +using Nwc.XmlRpc; +using OpenSim.Framework.Console; +using OpenSim.Framework.Statistics; + +namespace OpenSim.Framework.UserManagement +{ + /// + /// Base class for user management (create, read, etc) + /// + public abstract class UserManagerBase : IUserService + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public UserConfig _config; + private Dictionary _plugins = new Dictionary(); + + /// + /// Adds a new user server plugin - user servers will be requested in the order they were loaded. + /// + /// The filename to the user server plugin DLL + public void AddPlugin(string FileName) + { + if (!String.IsNullOrEmpty(FileName)) + { + m_log.Info("[USERSTORAGE]: Attempting to load " + FileName); + Assembly pluginAssembly = Assembly.LoadFrom(FileName); + + m_log.Info("[USERSTORAGE]: Found " + pluginAssembly.GetTypes().Length + " interfaces."); + foreach (Type pluginType in pluginAssembly.GetTypes()) + { + if (!pluginType.IsAbstract) + { + Type typeInterface = pluginType.GetInterface("IUserData", true); + + if (typeInterface != null) + { + IUserData plug = + (IUserData) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + AddPlugin(plug); + } + } + } + } + } + + public void AddPlugin(IUserData plug) + { + plug.Initialise(); + _plugins.Add(plug.getName(), plug); + m_log.Info("[USERSTORAGE]: Added IUserData Interface"); + } + + #region Get UserProfile + + /// + /// Loads a user profile from a database by UUID + /// + /// The target UUID + /// A user profile. Returns null if no user profile is found. + public UserProfileData GetUserProfile(LLUUID uuid) + { + foreach (KeyValuePair plugin in _plugins) + { + UserProfileData profile = plugin.Value.GetUserByUUID(uuid); + + if (null != profile) + { + profile.currentAgent = getUserAgent(profile.UUID); + return profile; + } + } + + return null; + } + + public List GenerateAgentPickerRequestResponse(LLUUID queryID, string query) + { + List pickerlist = new List(); + foreach (KeyValuePair plugin in _plugins) + { + try + { + pickerlist = plugin.Value.GeneratePickerResults(queryID, query); + } + catch (Exception) + { + m_log.Info("[USERSTORAGE]: Unable to generate AgentPickerData via " + plugin.Key + "(" + query + ")"); + return new List(); + } + } + return pickerlist; + } + + /// + /// Loads a user profile by name + /// + /// First name + /// Last name + /// A user profile. Returns null if no profile is found + public UserProfileData GetUserProfile(string fname, string lname) + { + foreach (KeyValuePair plugin in _plugins) + { + UserProfileData profile = plugin.Value.GetUserByName(fname, lname); + + if (profile != null) + { + profile.currentAgent = getUserAgent(profile.UUID); + return profile; + } + } + + return null; + } + + /// + /// Set's user profile from object + /// + /// First name + /// Last name + /// A user profile + public bool setUserProfile(UserProfileData data) + { + foreach (KeyValuePair plugin in _plugins) + { + try + { + plugin.Value.UpdateUserProfile(data); + return true; + } + catch (Exception e) + { + m_log.Info("[USERSTORAGE]: Unable to set user via " + plugin.Key + "(" + e.ToString() + ")"); + } + } + + return false; + } + + #endregion + + #region Get UserAgent + + /// + /// Loads a user agent by uuid (not called directly) + /// + /// The agent's UUID + /// Agent profiles + public UserAgentData getUserAgent(LLUUID uuid) + { + foreach (KeyValuePair plugin in _plugins) + { + try + { + return plugin.Value.GetAgentByUUID(uuid); + } + catch (Exception e) + { + m_log.Info("[USERSTORAGE]: Unable to find user via " + plugin.Key + "(" + e.ToString() + ")"); + } + } + + return null; + } + + /// + /// Loads a user's friend list + /// + /// the UUID of the friend list owner + /// A List of FriendListItems that contains info about the user's friends + public List GetUserFriendList(LLUUID ownerID) + { + + foreach (KeyValuePair plugin in _plugins) + { + try + { + return plugin.Value.GetUserFriendList(ownerID); + } + catch (Exception e) + { + m_log.Info("[USERSTORAGE]: Unable to GetUserFriendList via " + plugin.Key + "(" + e.ToString() + ")"); + } + } + + return null; + + } + + public void StoreWebLoginKey(LLUUID agentID, LLUUID webLoginKey) + { + + foreach (KeyValuePair plugin in _plugins) + { + try + { + plugin.Value.StoreWebLoginKey(agentID, webLoginKey); + } + catch (Exception e) + { + m_log.Info("[USERSTORAGE]: Unable to Store WebLoginKey via " + plugin.Key + "(" + e.ToString() + ")"); + } + } + } + + public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms) + { + foreach (KeyValuePair plugin in _plugins) + { + try + { + plugin.Value.AddNewUserFriend(friendlistowner,friend,perms); + } + catch (Exception e) + { + m_log.Info("[USERSTORAGE]: Unable to AddNewUserFriend via " + plugin.Key + "(" + e.ToString() + ")"); + } + } + + } + + + public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend) + { + foreach (KeyValuePair plugin in _plugins) + { + try + { + plugin.Value.RemoveUserFriend(friendlistowner, friend); + } + catch (Exception e) + { + m_log.Info("[USERSTORAGE]: Unable to RemoveUserFriend via " + plugin.Key + "(" + e.ToString() + ")"); + } + } + } + + public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms) + { + foreach (KeyValuePair plugin in _plugins) + { + try + { + plugin.Value.UpdateUserFriendPerms(friendlistowner, friend, perms); + } + catch (Exception e) + { + m_log.Info("[USERSTORAGE]: Unable to UpdateUserFriendPerms via " + plugin.Key + "(" + e.ToString() + ")"); + } + } + } + /// + /// Loads a user agent by name (not called directly) + /// + /// The agent's name + /// A user agent + public UserAgentData getUserAgent(string name) + { + foreach (KeyValuePair plugin in _plugins) + { + try + { + return plugin.Value.GetAgentByName(name); + } + catch (Exception e) + { + m_log.Info("[USERSTORAGE]: Unable to find user via " + plugin.Key + "(" + e.ToString() + ")"); + } + } + + return null; + } + + // TODO: document + public void clearUserAgent(LLUUID agentID) + { + UserProfileData profile = GetUserProfile(agentID); + profile.currentAgent = null; + + setUserProfile(profile); + } + + /// + /// Loads a user agent by name (not called directly) + /// + /// The agent's firstname + /// The agent's lastname + /// A user agent + public UserAgentData getUserAgent(string fname, string lname) + { + foreach (KeyValuePair plugin in _plugins) + { + try + { + return plugin.Value.GetAgentByName(fname, lname); + } + catch (Exception e) + { + m_log.Info("[USERSTORAGE]: Unable to find user via " + plugin.Key + "(" + e.ToString() + ")"); + } + } + + return null; + } + + #endregion + + #region CreateAgent + + /// + /// Creates and initialises a new user agent - make sure to use CommitAgent when done to submit to the DB + /// + /// The users profile + /// The users loginrequest + public void CreateAgent(UserProfileData profile, XmlRpcRequest request) + { + //Hashtable requestData = (Hashtable) request.Params[0]; + + UserAgentData agent = new UserAgentData(); + + // User connection + agent.agentOnline = true; + + // Generate sessions + RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider(); + byte[] randDataS = new byte[16]; + byte[] randDataSS = new byte[16]; + rand.GetBytes(randDataS); + rand.GetBytes(randDataSS); + + agent.secureSessionID = new LLUUID(randDataSS, 0); + agent.sessionID = new LLUUID(randDataS, 0); + + // Profile UUID + agent.UUID = profile.UUID; + + // Current position (from Home) + agent.currentHandle = profile.homeRegion; + agent.currentPos = profile.homeLocation; + + // If user specified additional start, use that +// if (requestData.ContainsKey("start")) +// { +// string startLoc = ((string) requestData["start"]).Trim(); +// if (!(startLoc == "last" || startLoc == "home")) +// { +// // Format: uri:Ahern&162&213&34 +// try +// { +// string[] parts = startLoc.Remove(0, 4).Split('&'); +// //string region = parts[0]; +// +// //////////////////////////////////////////////////// +// //SimProfile SimInfo = new SimProfile(); +// //SimInfo = SimInfo.LoadFromGrid(theUser.currentAgent.currentHandle, _config.GridServerURL, _config.GridSendKey, _config.GridRecvKey); +// } +// catch (Exception) +// { +// } +// } +// } + + // What time did the user login? + agent.loginTime = Util.UnixTimeSinceEpoch(); + agent.logoutTime = 0; + + // Current location + agent.regionID = LLUUID.Zero; // Fill in later + agent.currentRegion = LLUUID.Zero; // Fill in later + + profile.currentAgent = agent; + } + + /// + /// Process a user logoff from OpenSim. + /// + /// + /// + /// + /// + /// + /// + public void LogOffUser(LLUUID userid, LLUUID regionid, ulong regionhandle, float posx, float posy, float posz) + { + if (StatsManager.UserStats != null) + StatsManager.UserStats.AddLogout(); + + UserProfileData userProfile; + UserAgentData userAgent; + LLVector3 currentPos = new LLVector3(posx, posy, posz); + + userProfile = GetUserProfile(userid); + + if (userProfile != null) + { + // This line needs to be in side the above if statement or the UserServer will crash on some logouts. + m_log.Info("[LOGOUT]: " + userProfile.username + " " + userProfile.surname + " from " + regionhandle + "(" + posx + "," + posy + "," + posz + ")"); + + userAgent = userProfile.currentAgent; + if (userAgent != null) + { + userAgent.agentOnline = false; + userAgent.logoutTime = Util.UnixTimeSinceEpoch(); + userAgent.sessionID = LLUUID.Zero; + if (regionid != null) + { + userAgent.currentRegion = regionid; + } + userAgent.currentHandle = regionhandle; + + userAgent.currentPos = currentPos; + + userProfile.currentAgent = userAgent; + + + CommitAgent(ref userProfile); + } + else + { + // If currentagent is null, we can't reference it here or the UserServer crashes! + m_log.Info("[LOGOUT]: didn't save logout position: " + userid.ToString()); + } + + } + else + { + m_log.Warn("[LOGOUT]: Unknown User logged out"); + } + } + + public void CreateAgent(UserProfileData profile, LLSD request) + { + UserAgentData agent = new UserAgentData(); + + // User connection + agent.agentOnline = true; + + // Generate sessions + RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider(); + byte[] randDataS = new byte[16]; + byte[] randDataSS = new byte[16]; + rand.GetBytes(randDataS); + rand.GetBytes(randDataSS); + + agent.secureSessionID = new LLUUID(randDataSS, 0); + agent.sessionID = new LLUUID(randDataS, 0); + + // Profile UUID + agent.UUID = profile.UUID; + + // Current position (from Home) + agent.currentHandle = profile.homeRegion; + agent.currentPos = profile.homeLocation; + + // What time did the user login? + agent.loginTime = Util.UnixTimeSinceEpoch(); + agent.logoutTime = 0; + + // Current location + agent.regionID = LLUUID.Zero; // Fill in later + agent.currentRegion = LLUUID.Zero; // Fill in later + + profile.currentAgent = agent; + } + + /// + /// Saves a target agent to the database + /// + /// The users profile + /// Successful? + public bool CommitAgent(ref UserProfileData profile) + { + // TODO: how is this function different from setUserProfile? + return setUserProfile(profile); + } + + #endregion + + /// + /// + /// + /// + public LLUUID AddUserProfile(string firstName, string lastName, string pass, uint regX, uint regY) + { + UserProfileData user = new UserProfileData(); + user.homeLocation = new LLVector3(128, 128, 100); + user.UUID = LLUUID.Random(); + user.username = firstName; + user.surname = lastName; + user.passwordHash = pass; + user.passwordSalt = String.Empty; + user.created = Util.UnixTimeSinceEpoch(); + user.homeLookAt = new LLVector3(100, 100, 100); + user.homeRegionX = regX; + user.homeRegionY = regY; + + foreach (KeyValuePair plugin in _plugins) + { + try + { + plugin.Value.AddNewUserProfile(user); + } + catch (Exception e) + { + m_log.Info("[USERSTORAGE]: Unable to add user via " + plugin.Key + "(" + e.ToString() + ")"); + } + } + + return user.UUID; + } + + public abstract UserProfileData SetupMasterUser(string firstName, string lastName); + public abstract UserProfileData SetupMasterUser(string firstName, string lastName, string password); + public abstract UserProfileData SetupMasterUser(LLUUID uuid); + } +} diff --git a/trunk/OpenSim/Framework/Configuration/HTTP/HTTPConfiguration.cs b/trunk/OpenSim/Framework/Configuration/HTTP/HTTPConfiguration.cs new file mode 100644 index 0000000000..a657c3a66b --- /dev/null +++ b/trunk/OpenSim/Framework/Configuration/HTTP/HTTPConfiguration.cs @@ -0,0 +1,117 @@ +/* +* 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.IO; +using System.Net; +using System.Text; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Configuration.HTTP +{ + public class HTTPConfiguration : IGenericConfig + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private RemoteConfigSettings remoteConfigSettings; + + private XmlConfiguration xmlConfig; + + private string configFileName = System.String.Empty; + + public HTTPConfiguration() + { + remoteConfigSettings = new RemoteConfigSettings("remoteconfig.xml"); + xmlConfig = new XmlConfiguration(); + } + + public void SetFileName(string fileName) + { + configFileName = fileName; + } + + public void LoadData() + { + try + { + StringBuilder sb = new StringBuilder(); + + byte[] buf = new byte[8192]; + HttpWebRequest request = + (HttpWebRequest) WebRequest.Create(remoteConfigSettings.baseConfigURL + configFileName); + HttpWebResponse response = (HttpWebResponse) request.GetResponse(); + + Stream resStream = response.GetResponseStream(); + + string tempString = null; + int count = 0; + + do + { + count = resStream.Read(buf, 0, buf.Length); + if (count != 0) + { + tempString = Encoding.ASCII.GetString(buf, 0, count); + sb.Append(tempString); + } + } while (count > 0); + LoadDataFromString(sb.ToString()); + } + catch (WebException) + { + m_log.Warn("Unable to connect to remote configuration file (" + + remoteConfigSettings.baseConfigURL + configFileName + + "). Creating local file instead."); + xmlConfig.SetFileName(configFileName); + xmlConfig.LoadData(); + } + } + + public void LoadDataFromString(string data) + { + xmlConfig.LoadDataFromString(data); + } + + public string GetAttribute(string attributeName) + { + return xmlConfig.GetAttribute(attributeName); + } + + public bool SetAttribute(string attributeName, string attributeValue) + { + return true; + } + + public void Commit() + { + } + + public void Close() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Configuration/HTTP/RemoteConfigSettings.cs b/trunk/OpenSim/Framework/Configuration/HTTP/RemoteConfigSettings.cs new file mode 100644 index 0000000000..8575d3b064 --- /dev/null +++ b/trunk/OpenSim/Framework/Configuration/HTTP/RemoteConfigSettings.cs @@ -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. +* +*/ + +namespace OpenSim.Framework.Configuration.HTTP +{ + public class RemoteConfigSettings + { + private ConfigurationMember configMember; + + public string baseConfigURL = System.String.Empty; + + public RemoteConfigSettings(string filename) + { + configMember = + new ConfigurationMember(filename, "REMOTE CONFIG SETTINGS", loadConfigurationOptions, + handleIncomingConfiguration,true); + configMember.forceConfigurationPluginLibrary("OpenSim.Framework.Configuration.XML.dll"); + configMember.performConfigurationRetrieve(); + } + + public void loadConfigurationOptions() + { + configMember.addConfigurationOption("base_config_url", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "URL Containing Configuration Files", "http://localhost/", false); + } + + public bool handleIncomingConfiguration(string configuration_key, object configuration_result) + { + if (configuration_key == "base_config_url") + { + baseConfigURL = (string) configuration_result; + } + return true; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs b/trunk/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs new file mode 100644 index 0000000000..4c50e53404 --- /dev/null +++ b/trunk/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs @@ -0,0 +1,139 @@ +/* +* 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; +using System.IO; +using System.Xml; + +namespace OpenSim.Framework.Configuration +{ + public class XmlConfiguration : IGenericConfig + { + private XmlDocument doc; + private XmlNode rootNode; + private XmlNode configNode; + private string fileName; + private bool createdFile = false; + + public void SetFileName(string file) + { + fileName = file; + } + + private void LoadDataToClass() + { + rootNode = doc.FirstChild; + if (rootNode.Name != "Root") + throw new Exception("Error: Invalid .xml File. Missing "); + + configNode = rootNode.FirstChild; + if (configNode.Name != "Config") + throw new Exception("Error: Invalid .xml File. first child should be "); + } + + public void LoadData() + { + lock (this) + { + doc = new XmlDocument(); + if (File.Exists(fileName)) + { + XmlTextReader reader = new XmlTextReader(fileName); + reader.WhitespaceHandling = WhitespaceHandling.None; + doc.Load(reader); + reader.Close(); + } + else + { + createdFile = true; + rootNode = doc.CreateNode(XmlNodeType.Element, "Root", String.Empty); + doc.AppendChild(rootNode); + configNode = doc.CreateNode(XmlNodeType.Element, "Config", String.Empty); + rootNode.AppendChild(configNode); + } + + LoadDataToClass(); + + if (createdFile) + { + Commit(); + } + } + } + + public void LoadDataFromString(string data) + { + doc = new XmlDocument(); + doc.LoadXml(data); + + LoadDataToClass(); + } + + public string GetAttribute(string attributeName) + { + string result = null; + if (configNode.Attributes[attributeName] != null) + { + result = ((XmlAttribute) configNode.Attributes.GetNamedItem(attributeName)).Value; + } + return result; + } + + public bool SetAttribute(string attributeName, string attributeValue) + { + if (configNode.Attributes[attributeName] != null) + { + ((XmlAttribute) configNode.Attributes.GetNamedItem(attributeName)).Value = attributeValue; + } + else + { + XmlAttribute attri; + attri = doc.CreateAttribute(attributeName); + attri.Value = attributeValue; + configNode.Attributes.Append(attri); + } + return true; + } + + public void Commit() + { + if (!Directory.Exists(Util.configDir())) + { + Directory.CreateDirectory(Util.configDir()); + } + doc.Save(fileName); + } + + public void Close() + { + configNode = null; + rootNode = null; + doc = null; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/ConfigurationMember.cs b/trunk/OpenSim/Framework/ConfigurationMember.cs new file mode 100644 index 0000000000..921fb66229 --- /dev/null +++ b/trunk/OpenSim/Framework/ConfigurationMember.cs @@ -0,0 +1,503 @@ +/* +* 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; +using System.Collections.Generic; +using System.Globalization; +using System.Net; +using System.Reflection; +using System.Xml; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework +{ + public class ConfigurationMember + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public delegate bool ConfigurationOptionResult(string configuration_key, object configuration_result); + + public delegate void ConfigurationOptionsLoad(); + + private List configurationOptions = new List(); + private string configurationFilename = String.Empty; + private string configurationDescription = String.Empty; + private XmlNode configurationFromXMLNode = null; + private ConfigurationOptionsLoad loadFunction; + private ConfigurationOptionResult resultFunction; + + private IGenericConfig configurationPlugin = null; + private bool useConsoleToPromptOnError = true; + /// + /// This is the default configuration DLL loaded + /// + private string configurationPluginFilename = "OpenSim.Framework.Configuration.XML.dll"; + + public ConfigurationMember(string configuration_filename, string configuration_description, + ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error) + { + configurationFilename = configuration_filename; + configurationDescription = configuration_description; + loadFunction = load_function; + resultFunction = result_function; + useConsoleToPromptOnError = use_console_to_prompt_on_error; + } + + public ConfigurationMember(XmlNode configuration_xml, string configuration_description, + ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error) + { + configurationFilename = String.Empty; + configurationFromXMLNode = configuration_xml; + configurationDescription = configuration_description; + loadFunction = load_function; + resultFunction = result_function; + useConsoleToPromptOnError = use_console_to_prompt_on_error; + } + + public void setConfigurationFilename(string filename) + { + configurationFilename = filename; + } + + public void setConfigurationDescription(string desc) + { + configurationDescription = desc; + } + + public void setConfigurationResultFunction(ConfigurationOptionResult result) + { + resultFunction = result; + } + + public void forceConfigurationPluginLibrary(string dll_filename) + { + configurationPluginFilename = dll_filename; + } + + private void checkAndAddConfigOption(ConfigurationOption option) + { + if ((option.configurationKey != String.Empty && option.configurationQuestion != String.Empty) || + (option.configurationKey != String.Empty && option.configurationUseDefaultNoPrompt)) + { + if (!configurationOptions.Contains(option)) + { + configurationOptions.Add(option); + } + } + else + { + m_log.Info( + "Required fields for adding a configuration option is invalid. Will not add this option (" + + option.configurationKey + ")"); + } + } + + public void addConfigurationOption(string configuration_key, + ConfigurationOption.ConfigurationTypes configuration_type, + string configuration_question, string configuration_default, + bool use_default_no_prompt) + { + ConfigurationOption configOption = new ConfigurationOption(); + configOption.configurationKey = configuration_key; + configOption.configurationQuestion = configuration_question; + configOption.configurationDefault = configuration_default; + configOption.configurationType = configuration_type; + configOption.configurationUseDefaultNoPrompt = use_default_no_prompt; + configOption.shouldIBeAsked = null; //Assumes true, I can ask whenever + checkAndAddConfigOption(configOption); + } + + public void addConfigurationOption(string configuration_key, + ConfigurationOption.ConfigurationTypes configuration_type, + string configuration_question, string configuration_default, + bool use_default_no_prompt, + ConfigurationOption.ConfigurationOptionShouldBeAsked shouldIBeAskedDelegate) + { + ConfigurationOption configOption = new ConfigurationOption(); + configOption.configurationKey = configuration_key; + configOption.configurationQuestion = configuration_question; + configOption.configurationDefault = configuration_default; + configOption.configurationType = configuration_type; + configOption.configurationUseDefaultNoPrompt = use_default_no_prompt; + configOption.shouldIBeAsked = shouldIBeAskedDelegate; + checkAndAddConfigOption(configOption); + } + + // TEMP - REMOVE + private int cE = 0; + public void performConfigurationRetrieve() + { + if (cE > 1) + m_log.Error("READING CONFIGURATION COUT: " + cE.ToString()); + + + configurationPlugin = LoadConfigDll(configurationPluginFilename); + configurationOptions.Clear(); + if (loadFunction == null) + { + m_log.Error("Load Function for '" + configurationDescription + + "' is null. Refusing to run configuration."); + return; + } + + if (resultFunction == null) + { + m_log.Error("Result Function for '" + configurationDescription + + "' is null. Refusing to run configuration."); + return; + } + + m_log.Info("[CONFIG]: Calling Configuration Load Function..."); + loadFunction(); + + if (configurationOptions.Count <= 0) + { + m_log.Error("[CONFIG]: No configuration options were specified for '" + configurationOptions + + "'. Refusing to continue configuration."); + return; + } + + bool useFile = true; + if (configurationPlugin == null) + { + m_log.Error("[CONFIG]: Configuration Plugin NOT LOADED!"); + return; + } + + if (configurationFilename.Trim() != String.Empty) + { + configurationPlugin.SetFileName(configurationFilename); + try + { + configurationPlugin.LoadData(); + useFile = true; + } + catch (XmlException e) + { + m_log.Error("Error loading " + configurationFilename + ": " + e.ToString()); + useFile = false; + } + } + else + { + if (configurationFromXMLNode != null) + { + m_log.Info("Loading from XML Node, will not save to the file"); + configurationPlugin.LoadDataFromString(configurationFromXMLNode.OuterXml); + } + + m_log.Info("XML Configuration Filename is not valid; will not save to the file."); + useFile = false; + } + + foreach (ConfigurationOption configOption in configurationOptions) + { + bool convertSuccess = false; + object return_result = null; + string errorMessage = String.Empty; + bool ignoreNextFromConfig = false; + while (convertSuccess == false) + { + string console_result = String.Empty; + string attribute = null; + if (useFile || configurationFromXMLNode != null) + { + if (!ignoreNextFromConfig) + { + attribute = configurationPlugin.GetAttribute(configOption.configurationKey); + } + else + { + ignoreNextFromConfig = false; + } + } + + if (attribute == null) + { + if (configOption.configurationUseDefaultNoPrompt || useConsoleToPromptOnError == false) + { + console_result = configOption.configurationDefault; + } + else + { + if ((configOption.shouldIBeAsked != null && + configOption.shouldIBeAsked(configOption.configurationKey)) || + configOption.shouldIBeAsked == null) + { + if (configurationDescription.Trim() != String.Empty) + { + console_result = + MainConsole.Instance.CmdPrompt( + configurationDescription + ": " + configOption.configurationQuestion, + configOption.configurationDefault); + } + else + { + console_result = + MainConsole.Instance.CmdPrompt(configOption.configurationQuestion, + configOption.configurationDefault); + } + } + else + { + //Dont Ask! Just use default + console_result = configOption.configurationDefault; + } + } + } + else + { + console_result = attribute; + } + + switch (configOption.configurationType) + { + case ConfigurationOption.ConfigurationTypes.TYPE_STRING: + return_result = console_result; + convertSuccess = true; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY: + if (console_result.Length > 0) + { + return_result = console_result; + convertSuccess = true; + } + errorMessage = "a string that is not empty"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN: + bool boolResult; + if (Boolean.TryParse(console_result, out boolResult)) + { + convertSuccess = true; + return_result = boolResult; + } + errorMessage = "'true' or 'false' (Boolean)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_BYTE: + byte byteResult; + if (Byte.TryParse(console_result, out byteResult)) + { + convertSuccess = true; + return_result = byteResult; + } + errorMessage = "a byte (Byte)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_CHARACTER: + char charResult; + if (Char.TryParse(console_result, out charResult)) + { + convertSuccess = true; + return_result = charResult; + } + errorMessage = "a character (Char)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_INT16: + short shortResult; + if (Int16.TryParse(console_result, out shortResult)) + { + convertSuccess = true; + return_result = shortResult; + } + errorMessage = "a signed 32 bit integer (short)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_INT32: + int intResult; + if (Int32.TryParse(console_result, out intResult)) + { + convertSuccess = true; + return_result = intResult; + } + errorMessage = "a signed 32 bit integer (int)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_INT64: + long longResult; + if (Int64.TryParse(console_result, out longResult)) + { + convertSuccess = true; + return_result = longResult; + } + errorMessage = "a signed 32 bit integer (long)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS: + IPAddress ipAddressResult; + if (IPAddress.TryParse(console_result, out ipAddressResult)) + { + convertSuccess = true; + return_result = ipAddressResult; + } + errorMessage = "an IP Address (IPAddress)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_LLUUID: + LLUUID uuidResult; + if (LLUUID.TryParse(console_result, out uuidResult)) + { + convertSuccess = true; + return_result = uuidResult; + } + errorMessage = "a UUID (LLUUID)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_LLVECTOR3: + LLVector3 vectorResult; + if (LLVector3.TryParse(console_result, out vectorResult)) + { + convertSuccess = true; + return_result = vectorResult; + } + errorMessage = "a vector (LLVector3)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_UINT16: + ushort ushortResult; + if (UInt16.TryParse(console_result, out ushortResult)) + { + convertSuccess = true; + return_result = ushortResult; + } + errorMessage = "an unsigned 16 bit integer (ushort)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_UINT32: + uint uintResult; + if (UInt32.TryParse(console_result, out uintResult)) + { + convertSuccess = true; + return_result = uintResult; + } + errorMessage = "an unsigned 32 bit integer (uint)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_UINT64: + ulong ulongResult; + if (UInt64.TryParse(console_result, out ulongResult)) + { + convertSuccess = true; + return_result = ulongResult; + } + errorMessage = "an unsigned 64 bit integer (ulong)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_FLOAT: + float floatResult; + if ( + float.TryParse(console_result, NumberStyles.AllowDecimalPoint, Culture.NumberFormatInfo, + out floatResult)) + { + convertSuccess = true; + return_result = floatResult; + } + errorMessage = "a single-precision floating point number (float)"; + break; + case ConfigurationOption.ConfigurationTypes.TYPE_DOUBLE: + double doubleResult; + if ( + Double.TryParse(console_result, NumberStyles.AllowDecimalPoint, Culture.NumberFormatInfo, + out doubleResult)) + { + convertSuccess = true; + return_result = doubleResult; + } + errorMessage = "an double-precision floating point number (double)"; + break; + } + + if (convertSuccess) + { + if (useFile) + { + configurationPlugin.SetAttribute(configOption.configurationKey, console_result); + } + + if (!resultFunction(configOption.configurationKey, return_result)) + { + m_log.Info( + "The handler for the last configuration option denied that input, please try again."); + convertSuccess = false; + ignoreNextFromConfig = true; + } + } + else + { + if (configOption.configurationUseDefaultNoPrompt) + { + m_log.Error(string.Format( + "[CONFIG]: [{3}]:[{1}] is not valid default for parameter [{0}].\nThe configuration result must be parsable to {2}.\n", + configOption.configurationKey, console_result, errorMessage, + configurationFilename)); + convertSuccess = true; + } + else + { + m_log.Warn(string.Format( + "[CONFIG]: [{3}]:[{1}] is not a valid value [{0}].\nThe configuration result must be parsable to {2}.\n", + configOption.configurationKey, console_result, errorMessage, + configurationFilename)); + ignoreNextFromConfig = true; + } + } + } + } + + if (useFile) + { + configurationPlugin.Commit(); + configurationPlugin.Close(); + } + } + + private IGenericConfig LoadConfigDll(string dllName) + { + Assembly pluginAssembly = Assembly.LoadFrom(dllName); + IGenericConfig plug = null; + + foreach (Type pluginType in pluginAssembly.GetTypes()) + { + if (pluginType.IsPublic) + { + if (!pluginType.IsAbstract) + { + Type typeInterface = pluginType.GetInterface("IGenericConfig", true); + + if (typeInterface != null) + { + plug = + (IGenericConfig) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + } + } + } + } + + pluginAssembly = null; + return plug; + } + + public void forceSetConfigurationOption(string configuration_key, string configuration_value) + { + configurationPlugin.LoadData(); + configurationPlugin.SetAttribute(configuration_key, configuration_value); + configurationPlugin.Commit(); + configurationPlugin.Close(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/ConfigurationOption.cs b/trunk/OpenSim/Framework/ConfigurationOption.cs new file mode 100644 index 0000000000..d8be6f8763 --- /dev/null +++ b/trunk/OpenSim/Framework/ConfigurationOption.cs @@ -0,0 +1,65 @@ +/* +* 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; + +namespace OpenSim.Framework +{ + public class ConfigurationOption + { + public delegate bool ConfigurationOptionShouldBeAsked(string configuration_key); + + public enum ConfigurationTypes + { + TYPE_STRING, + TYPE_STRING_NOT_EMPTY, + TYPE_UINT16, + TYPE_UINT32, + TYPE_UINT64, + TYPE_INT16, + TYPE_INT32, + TYPE_INT64, + TYPE_IP_ADDRESS, + TYPE_CHARACTER, + TYPE_BOOLEAN, + TYPE_BYTE, + TYPE_LLUUID, + TYPE_LLVECTOR3, + TYPE_FLOAT, + TYPE_DOUBLE + } ; + + public string configurationKey = String.Empty; + public string configurationQuestion = String.Empty; + public string configurationDefault = String.Empty; + + public ConfigurationTypes configurationType = ConfigurationTypes.TYPE_STRING; + public bool configurationUseDefaultNoPrompt = false; + public ConfigurationOptionShouldBeAsked shouldIBeAsked; //Should I be asked now? Based on previous answers + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Console/AssemblyInfo.cs b/trunk/OpenSim/Framework/Console/AssemblyInfo.cs new file mode 100644 index 0000000000..b3211701ce --- /dev/null +++ b/trunk/OpenSim/Framework/Console/AssemblyInfo.cs @@ -0,0 +1,58 @@ +/* +* 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; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly : AssemblyTitle("ServerConsole")] +[assembly : AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly : AssemblyProduct("ServerConsole")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. + +[assembly : ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly : AssemblyVersion("1.0.*")] \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Console/ConsoleBase.cs b/trunk/OpenSim/Framework/Console/ConsoleBase.cs new file mode 100644 index 0000000000..829d6c7302 --- /dev/null +++ b/trunk/OpenSim/Framework/Console/ConsoleBase.cs @@ -0,0 +1,423 @@ +/* +* 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; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Net; + +namespace OpenSim.Framework.Console +{ + public class ConsoleBase + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private object m_syncRoot = new object(); + + public conscmd_callback m_cmdParser; + public string m_componentName; + + public ConsoleBase(string componentname, conscmd_callback cmdparser) + { + m_componentName = componentname; + m_cmdParser = cmdparser; + + System.Console.WriteLine("Creating new local console"); + + m_log.Info("[" + m_componentName + "]: Started at " + DateTime.Now.ToString()); + } + + public void Close() + { + m_log.Info("[" + m_componentName + "]: Shutdown at " + DateTime.Now.ToString()); + } + + /// + /// derive an ansi color from a string, ignoring the darker colors. + /// This is used to help automatically bin component tags with colors + /// in various print functions. + /// + /// arbitrary string for input + /// an ansii color + private ConsoleColor DeriveColor(string input) + { + int colIdx = (input.ToUpper().GetHashCode() % 6) + 9; + return (ConsoleColor) colIdx; + } + + /// + /// Sends a warning to the current console output + /// + /// The message to send + /// WriteLine-style message arguments + public void Warn(string format, params object[] args) + { + WriteNewLine(ConsoleColor.Yellow, format, args); + } + + /// + /// Sends a warning to the current console output + /// + /// The module that sent this message + /// The message to send + /// WriteLine-style message arguments + public void Warn(string sender, string format, params object[] args) + { + WritePrefixLine(DeriveColor(sender), sender); + WriteNewLine(ConsoleColor.Yellow, format, args); + } + + /// + /// Sends a notice to the current console output + /// + /// The message to send + /// WriteLine-style message arguments + public void Notice(string format, params object[] args) + { + WriteNewLine(ConsoleColor.White, format, args); + } + + /// + /// Sends a notice to the current console output + /// + /// The module that sent this message + /// The message to send + /// WriteLine-style message arguments + public void Notice(string sender, string format, params object[] args) + { + WritePrefixLine(DeriveColor(sender), sender); + WriteNewLine(ConsoleColor.White, format, args); + } + + /// + /// Sends an error to the current console output + /// + /// The message to send + /// WriteLine-style message arguments + public void Error(string format, params object[] args) + { + WriteNewLine(ConsoleColor.Red, format, args); + } + + /// + /// Sends an error to the current console output + /// + /// The module that sent this message + /// The message to send + /// WriteLine-style message arguments + public void Error(string sender, string format, params object[] args) + { + WritePrefixLine(DeriveColor(sender), sender); + Error(format, args); + } + + /// + /// Sends a status message to the current console output + /// + /// The message to send + /// WriteLine-style message arguments + public void Status(string format, params object[] args) + { + WriteNewLine(ConsoleColor.Blue, format, args); + } + + /// + /// Sends a status message to the current console output + /// + /// The module that sent this message + /// The message to send + /// WriteLine-style message arguments + public void Status(string sender, string format, params object[] args) + { + WritePrefixLine(DeriveColor(sender), sender); + WriteNewLine(ConsoleColor.Blue, format, args); + } + + [Conditional("DEBUG")] + public void Debug(string format, params object[] args) + { + WriteNewLine(ConsoleColor.Gray, format, args); + } + + [Conditional("DEBUG")] + public void Debug(string sender, string format, params object[] args) + { + WritePrefixLine(DeriveColor(sender), sender); + WriteNewLine(ConsoleColor.Gray, format, args); + } + + private void WriteNewLine(ConsoleColor color, string format, params object[] args) + { + try + { + lock (m_syncRoot) + { + try + { + if (color != ConsoleColor.White) + System.Console.ForegroundColor = color; + + System.Console.WriteLine(format, args); + System.Console.ResetColor(); + } + catch (ArgumentNullException) + { + // Some older systems dont support coloured text. + System.Console.WriteLine(format, args); + } + catch (FormatException) + { + System.Console.WriteLine(args); + } + } + } + catch (ObjectDisposedException) + { + } + } + + private void WritePrefixLine(ConsoleColor color, string sender) + { + try + { + lock (m_syncRoot) + { + sender = sender.ToUpper(); + + System.Console.WriteLine("[" + sender + "] "); + + System.Console.Write("["); + + try + { + System.Console.ForegroundColor = color; + System.Console.Write(sender); + System.Console.ResetColor(); + } + catch (ArgumentNullException) + { + // Some older systems dont support coloured text. + System.Console.WriteLine(sender); + } + + System.Console.Write("] \t"); + } + } + catch (ObjectDisposedException) + { + } + } + + public string ReadLine() + { + try + { + return System.Console.ReadLine(); + } + catch (Exception e) + { + m_log.Error("[Console]: System.Console.ReadLine exception " + e.ToString()); + return String.Empty; + } + } + + public int Read() + { + return System.Console.Read(); + } + + public IPAddress CmdPromptIPAddress(string prompt, string defaultvalue) + { + IPAddress address; + string addressStr; + + while (true) + { + addressStr = CmdPrompt(prompt, defaultvalue); + if (IPAddress.TryParse(addressStr, out address)) + { + break; + } + else + { + m_log.Error("Illegal address. Please re-enter."); + } + } + + return address; + } + + public uint CmdPromptIPPort(string prompt, string defaultvalue) + { + uint port; + string portStr; + + while (true) + { + portStr = CmdPrompt(prompt, defaultvalue); + if (uint.TryParse(portStr, out port)) + { + if (port >= IPEndPoint.MinPort && port <= IPEndPoint.MaxPort) + { + break; + } + } + + m_log.Error("Illegal address. Please re-enter."); + } + + return port; + } + + // Displays a prompt and waits for the user to enter a string, then returns that string + // Done with no echo and suitable for passwords + public string PasswdPrompt(string prompt) + { + // FIXME: Needs to be better abstracted + System.Console.WriteLine(String.Format("{0}: ", prompt)); + ConsoleColor oldfg = System.Console.ForegroundColor; + System.Console.ForegroundColor = System.Console.BackgroundColor; + string temp = System.Console.ReadLine(); + System.Console.ForegroundColor = oldfg; + return temp; + } + + // Displays a command prompt and waits for the user to enter a string, then returns that string + public string CmdPrompt(string prompt) + { + System.Console.WriteLine(String.Format("{0}: ", prompt)); + return ReadLine(); + } + + // Displays a command prompt and returns a default value if the user simply presses enter + public string CmdPrompt(string prompt, string defaultresponse) + { + string temp = CmdPrompt(String.Format("{0} [{1}]", prompt, defaultresponse)); + if (temp == String.Empty) + { + return defaultresponse; + } + else + { + return temp; + } + } + + // Displays a command prompt and returns a default value, user may only enter 1 of 2 options + public string CmdPrompt(string prompt, string defaultresponse, string OptionA, string OptionB) + { + bool itisdone = false; + string temp = CmdPrompt(prompt, defaultresponse); + while (itisdone == false) + { + if ((temp == OptionA) || (temp == OptionB)) + { + itisdone = true; + } + else + { + System.Console.WriteLine("Valid options are " + OptionA + " or " + OptionB); + temp = CmdPrompt(prompt, defaultresponse); + } + } + return temp; + } + + // Runs a command with a number of parameters + public Object RunCmd(string Cmd, string[] cmdparams) + { + m_cmdParser.RunCmd(Cmd, cmdparams); + return null; + } + + // Shows data about something + public void ShowCommands(string ShowWhat) + { + m_cmdParser.Show(ShowWhat); + } + + public void Prompt() + { + string tempstr = CmdPrompt(m_componentName + "# "); + RunCommand(tempstr); + } + + public void RunCommand(string command) + { + string[] tempstrarray; + tempstrarray = command.Split(' '); + string cmd = tempstrarray[0]; + Array.Reverse(tempstrarray); + Array.Resize(ref tempstrarray, tempstrarray.Length - 1); + Array.Reverse(tempstrarray); + string[] cmdparams = (string[]) tempstrarray; + try + { + RunCmd(cmd, cmdparams); + } + catch (Exception e) + { + m_log.Error("[Console]: Command failed with exception " + e.ToString()); + } + } + + public string LineInfo + { + get + { + string result = String.Empty; + + string stacktrace = Environment.StackTrace; + List lines = new List(stacktrace.Split(new string[] {"at "}, StringSplitOptions.None)); + + if (lines.Count > 4) + { + lines.RemoveRange(0, 4); + + string tmpLine = lines[0]; + + int inIndex = tmpLine.IndexOf(" in "); + + if (inIndex > -1) + { + result = tmpLine.Substring(0, inIndex); + + int lineIndex = tmpLine.IndexOf(":line "); + + if (lineIndex > -1) + { + lineIndex += 6; + result += ", line " + tmpLine.Substring(lineIndex, (tmpLine.Length - lineIndex) - 5); + } + } + } + return result; + } + } + } +} diff --git a/trunk/OpenSim/Framework/Console/ConsoleCallbacksBase.cs b/trunk/OpenSim/Framework/Console/ConsoleCallbacksBase.cs new file mode 100644 index 0000000000..606469d50c --- /dev/null +++ b/trunk/OpenSim/Framework/Console/ConsoleCallbacksBase.cs @@ -0,0 +1,35 @@ +/* +* 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. +* +*/ +namespace OpenSim.Framework.Console +{ + public interface conscmd_callback + { + void RunCmd(string cmd, string[] cmdparams); + void Show(string ShowWhat); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Console/MainConsole.cs b/trunk/OpenSim/Framework/Console/MainConsole.cs new file mode 100644 index 0000000000..fb88d04c00 --- /dev/null +++ b/trunk/OpenSim/Framework/Console/MainConsole.cs @@ -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. +* +*/ + +namespace OpenSim.Framework.Console +{ + public class MainConsole + { + private static ConsoleBase instance; + + public static ConsoleBase Instance + { + get { return instance; } + set { instance = value; } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Console/OpenSimAppender.cs b/trunk/OpenSim/Framework/Console/OpenSimAppender.cs new file mode 100644 index 0000000000..e451d98aee --- /dev/null +++ b/trunk/OpenSim/Framework/Console/OpenSimAppender.cs @@ -0,0 +1,115 @@ +/* +* 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; +using System.Text; +using System.Text.RegularExpressions; +using System.Globalization; + +using log4net.Core; +using log4net.Layout; +using log4net.Appender; +using log4net.Util; + +namespace OpenSim.Framework.Console +{ + public class OpenSimAppender : AnsiColorTerminalAppender + { + override protected void Append(LoggingEvent le) + { + try { + string loggingMessage = RenderLoggingEvent(le); + string regex = @"^(?.*?)\[(?[^\]]+)\]:?(?.*)"; + + Regex RE = new Regex(regex, RegexOptions.Multiline); + MatchCollection matches = RE.Matches(loggingMessage); + // Get some direct matches $1 $4 is a + if (matches.Count == 1) + { + System.Console.Write(matches[0].Groups["Front"].Value); + System.Console.Write("["); + + WriteColorText(DeriveColor(matches[0].Groups["Category"].Value), matches[0].Groups["Category"].Value); + System.Console.Write("]:"); + + if (le.Level == Level.Error) + { + WriteColorText(ConsoleColor.Red, matches[0].Groups["End"].Value); + } + else if (le.Level == Level.Warn) + { + WriteColorText(ConsoleColor.Yellow, matches[0].Groups["End"].Value); + } + else + { + System.Console.Write(matches[0].Groups["End"].Value); + } + System.Console.WriteLine(); + } + else + { + System.Console.Write(loggingMessage); + } + } + catch (Exception e) + { + System.Console.WriteLine("Couldn't write out log message", e.ToString()); + } + } + + private void WriteColorText(ConsoleColor color, string sender) + { + try + { + lock (this) + { + try + { + System.Console.ForegroundColor = color; + System.Console.Write(sender); + System.Console.ResetColor(); + } + catch (ArgumentNullException) + { + // Some older systems dont support coloured text. + System.Console.WriteLine(sender); + } + } + } + catch (ObjectDisposedException) + { + } + } + + private ConsoleColor DeriveColor(string input) + { + int colIdx = (input.ToUpper().GetHashCode() % 6) + 9; + return (ConsoleColor) colIdx; + } + } +} diff --git a/trunk/OpenSim/Framework/Constants.cs b/trunk/OpenSim/Framework/Constants.cs new file mode 100644 index 0000000000..9eca152e3d --- /dev/null +++ b/trunk/OpenSim/Framework/Constants.cs @@ -0,0 +1,39 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Framework +{ + public class Constants + { + public const uint RegionSize = 256; + } +} diff --git a/trunk/OpenSim/Framework/Culture.cs b/trunk/OpenSim/Framework/Culture.cs new file mode 100644 index 0000000000..f8cadfe96b --- /dev/null +++ b/trunk/OpenSim/Framework/Culture.cs @@ -0,0 +1,54 @@ +/* +* 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; +using System.Globalization; +using System.Threading; + +namespace OpenSim.Framework +{ + public class Culture + { + private static readonly CultureInfo m_cultureInfo = new CultureInfo("en-US", true); + + public static NumberFormatInfo NumberFormatInfo + { + get { return m_cultureInfo.NumberFormat; } + } + + public static IFormatProvider FormatProvider + { + get { return m_cultureInfo; } + } + + public static void SetCurrentCulture() + { + Thread.CurrentThread.CurrentCulture = m_cultureInfo; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.DB4o/DB4oGridData.cs b/trunk/OpenSim/Framework/Data.DB4o/DB4oGridData.cs new file mode 100644 index 0000000000..263716640c --- /dev/null +++ b/trunk/OpenSim/Framework/Data.DB4o/DB4oGridData.cs @@ -0,0 +1,177 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; + +namespace OpenSim.Framework.Data.DB4o +{ + /// + /// A grid server storage mechanism employing the DB4o database system + /// + internal class DB4oGridData : IGridData + { + /// + /// The database manager object + /// + private DB4oGridManager manager; + + /// + /// Called when the plugin is first loaded (as constructors are not called) + /// + public void Initialise() + { + manager = new DB4oGridManager("gridserver.yap"); + } + + /// + /// Returns a list of regions within the specified ranges + /// + /// minimum X coordinate + /// minimum Y coordinate + /// maximum X coordinate + /// maximum Y coordinate + /// An array of region profiles + public RegionProfileData[] GetProfilesInRange(uint a, uint b, uint c, uint d) + { + return null; + } + + /// + /// Returns a region located at the specified regionHandle (warning multiple regions may occupy the one spot, first found is returned) + /// + /// The handle to search for + /// A region profile + public RegionProfileData GetProfileByHandle(ulong handle) + { + lock (manager.simProfiles) + { + foreach (LLUUID UUID in manager.simProfiles.Keys) + { + if (manager.simProfiles[UUID].regionHandle == handle) + { + return manager.simProfiles[UUID]; + } + } + } + throw new Exception("Unable to find profile with handle (" + handle.ToString() + ")"); + } + + /// + /// Returns a specific region + /// + /// The region ID code + /// A region profile + public RegionProfileData GetProfileByLLUUID(LLUUID uuid) + { + lock (manager.simProfiles) + { + if (manager.simProfiles.ContainsKey(uuid)) + return manager.simProfiles[uuid]; + } + throw new Exception("Unable to find profile with UUID (" + uuid.ToString() + + "). Total Registered Regions: " + manager.simProfiles.Count); + } + + /// + /// Adds a new specified region to the database + /// + /// The profile to add + /// A dataresponse enum indicating success + public DataResponse AddProfile(RegionProfileData profile) + { + lock (manager.simProfiles) + { + if (manager.AddRow(profile)) + { + return DataResponse.RESPONSE_OK; + } + else + { + return DataResponse.RESPONSE_ERROR; + } + } + } + + /// + /// Authenticates a new region using the shared secrets. NOT SECURE. + /// + /// The UUID the region is authenticating with + /// The location the region is logging into (unused in Db4o) + /// The shared secret + /// Authenticated? + public bool AuthenticateSim(LLUUID uuid, ulong handle, string key) + { + if (manager.simProfiles[uuid].regionRecvKey == key) + return true; + return false; + } + + /// + /// Shuts down the database + /// + public void Close() + { + manager = null; + } + + /// + /// // Returns a list of avatar and UUIDs that match the query + /// + public List GeneratePickerResults(LLUUID queryID, string query) + { + //Do nothing yet + List returnlist = new List(); + return returnlist; + } + + /// + /// Returns the providers name + /// + /// The name of the storage system + public string getName() + { + return "DB4o Grid Provider"; + } + + /// + /// Returns the providers version + /// + /// The version of the storage system + public string getVersion() + { + return "0.1"; + } + + public ReservationData GetReservationAtPoint(uint x, uint y) + { + return null; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.DB4o/DB4oManager.cs b/trunk/OpenSim/Framework/Data.DB4o/DB4oManager.cs new file mode 100644 index 0000000000..4b1b451c7d --- /dev/null +++ b/trunk/OpenSim/Framework/Data.DB4o/DB4oManager.cs @@ -0,0 +1,170 @@ +/* +* 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; +using System.Collections.Generic; +using Db4objects.Db4o; +using libsecondlife; + +namespace OpenSim.Framework.Data.DB4o +{ + /// + /// A Database manager for Db4o + /// + internal class DB4oGridManager + { + /// + /// A list of the current regions connected (in-memory cache) + /// + public Dictionary simProfiles = new Dictionary(); + + /// + /// Database File Name + /// + private string dbfl; + + /// + /// Creates a new grid storage manager + /// + /// Filename to the database file + public DB4oGridManager(string db4odb) + { + dbfl = db4odb; + IObjectContainer database; + database = Db4oFactory.OpenFile(dbfl); + IObjectSet result = database.Get(typeof (RegionProfileData)); + // Loads the file into the in-memory cache + foreach (RegionProfileData row in result) + { + simProfiles.Add(row.UUID, row); + } + database.Close(); + } + + /// + /// Adds a new profile to the database (Warning: Probably slow.) + /// + /// The profile to add + /// Successful? + public bool AddRow(RegionProfileData row) + { + if (simProfiles.ContainsKey(row.UUID)) + { + simProfiles[row.UUID] = row; + } + else + { + simProfiles.Add(row.UUID, row); + } + + try + { + IObjectContainer database; + database = Db4oFactory.OpenFile(dbfl); + database.Set(row); + database.Close(); + return true; + } + catch (Exception) + { + return false; + } + } + } + + /// + /// A manager for the DB4o database (user profiles) + /// + internal class DB4oUserManager + { + /// + /// A list of the user profiles (in memory cache) + /// + public Dictionary userProfiles = new Dictionary(); + + /// + /// Database filename + /// + private string dbfl; + + /// + /// Initialises a new DB manager + /// + /// The filename to the database + public DB4oUserManager(string db4odb) + { + dbfl = db4odb; + IObjectContainer database; + database = Db4oFactory.OpenFile(dbfl); + // Load to cache + IObjectSet result = database.Get(typeof (UserProfileData)); + foreach (UserProfileData row in result) + { + if (userProfiles.ContainsKey(row.UUID)) + userProfiles[row.UUID] = row; + else + userProfiles.Add(row.UUID, row); + } + database.Close(); + } + + /// + /// Adds or updates a record to the user database. Do this when changes are needed + /// in the user profile that need to be persistant. + /// + /// TODO: the logic here is not ACID, the local cache will be + /// updated even if the persistant data is not. This may lead + /// to unexpected results. + /// + /// The profile to update + /// true on success, false on fail to persist to db + public bool UpdateRecord(UserProfileData record) + { + if (userProfiles.ContainsKey(record.UUID)) + { + userProfiles[record.UUID] = record; + } + else + { + userProfiles.Add(record.UUID, record); + } + + try + { + IObjectContainer database; + database = Db4oFactory.OpenFile(dbfl); + database.Set(record); + database.Close(); + return true; + } + catch (Exception) + { + return false; + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.DB4o/DB4oUserData.cs b/trunk/OpenSim/Framework/Data.DB4o/DB4oUserData.cs new file mode 100644 index 0000000000..35a363587a --- /dev/null +++ b/trunk/OpenSim/Framework/Data.DB4o/DB4oUserData.cs @@ -0,0 +1,270 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using libsecondlife; + +namespace OpenSim.Framework.Data.DB4o +{ + /// + /// A User storage interface for the DB4o database system + /// + public class DB4oUserData : IUserData + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The database manager + /// + private DB4oUserManager manager; + + /// + /// Artificial constructor called upon plugin load + /// + public void Initialise() + { + manager = new DB4oUserManager(Path.Combine(Util.dataDir(), "userprofiles.yap")); + } + + /// + /// Loads a specified user profile from a UUID + /// + /// The users UUID + /// A user profile + public UserProfileData GetUserByUUID(LLUUID uuid) + { + if (manager.userProfiles.ContainsKey(uuid)) + return manager.userProfiles[uuid]; + return null; + } + + /// + /// Returns a user by searching for its name + /// + /// The users account name + /// A matching users profile + public UserProfileData GetUserByName(string name) + { + return GetUserByName(name.Split(' ')[0], name.Split(' ')[1]); + } + + /// + /// Returns a user by searching for its name + /// + /// The first part of the users account name + /// The second part of the users account name + /// A matching users profile + public UserProfileData GetUserByName(string fname, string lname) + { + foreach (UserProfileData profile in manager.userProfiles.Values) + { + if (profile.username == fname && profile.surname == lname) + return profile; + } + return null; + } + + /// + /// Returns a user by UUID direct + /// + /// The users account ID + /// A matching users profile + public UserAgentData GetAgentByUUID(LLUUID uuid) + { + try + { + return GetUserByUUID(uuid).currentAgent; + } + catch (Exception) + { + return null; + } + } + + /// + /// Returns a session by account name + /// + /// The account name + /// The users session agent + public UserAgentData GetAgentByName(string name) + { + return GetAgentByName(name.Split(' ')[0], name.Split(' ')[1]); + } + + /// + /// Returns a session by account name + /// + /// The first part of the users account name + /// The second part of the users account name + /// A user agent + public UserAgentData GetAgentByName(string fname, string lname) + { + try + { + return GetUserByName(fname, lname).currentAgent; + } + catch (Exception) + { + return null; + } + } + public void StoreWebLoginKey(LLUUID AgentID, LLUUID WebLoginKey) + { + UserProfileData user = GetUserByUUID(AgentID); + user.webLoginKey = WebLoginKey; + UpdateUserProfile(user); + + } + #region User Friends List Data + + public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms) + { + //m_log.Info("[FRIEND]: Stub AddNewUserFriend called"); + } + + public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend) + { + //m_log.Info("[FRIEND]: Stub RemoveUserFriend called"); + } + public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms) + { + //m_log.Info("[FRIEND]: Stub UpdateUserFriendPerms called"); + } + + + public List GetUserFriendList(LLUUID friendlistowner) + { + //m_log.Info("[FRIEND]: Stub GetUserFriendList called"); + return new List(); + } + + #endregion + + public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid) + { + //m_log.Info("[USER]: Stub UpdateUserCUrrentRegion called"); + } + + + + public List GeneratePickerResults(LLUUID queryID, string query) + { + //Do nothing yet + List returnlist = new List(); + return returnlist; + } + + /// + /// Creates a new user profile + /// + /// The profile to add to the database + public void AddNewUserProfile(UserProfileData user) + { + try + { + manager.UpdateRecord(user); + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + } + } + + /// + /// Creates a new user profile + /// + /// The profile to add to the database + /// True on success, false on error + public bool UpdateUserProfile(UserProfileData user) + { + try + { + return manager.UpdateRecord(user); + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + return false; + } + } + + + /// + /// Creates a new user agent + /// + /// The agent to add to the database + public void AddNewUserAgent(UserAgentData agent) + { + // Do nothing. yet. + } + + /// + /// Transfers money between two user accounts + /// + /// Starting account + /// End account + /// The amount to move + /// Success? + public bool MoneyTransferRequest(LLUUID from, LLUUID to, uint amount) + { + return true; + } + + /// + /// Transfers inventory between two accounts + /// + /// Move to inventory server + /// Senders account + /// Receivers account + /// Inventory item + /// Success? + public bool InventoryTransferRequest(LLUUID from, LLUUID to, LLUUID item) + { + return true; + } + + /// + /// Returns the name of the storage provider + /// + /// Storage provider name + public string getName() + { + return "DB4o Userdata"; + } + + /// + /// Returns the version of the storage provider + /// + /// Storage provider version + public string GetVersion() + { + return "0.1"; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.DB4o/Properties/AssemblyInfo.cs b/trunk/OpenSim/Framework/Data.DB4o/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..af181e4edc --- /dev/null +++ b/trunk/OpenSim/Framework/Data.DB4o/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* 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.Framework.Data.DB4o")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Framework.Data.DB4o")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("57991e15-79da-41b7-aa06-2e6b49165a63")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MSSQL/MSSQLAssetData.cs b/trunk/OpenSim/Framework/Data.MSSQL/MSSQLAssetData.cs new file mode 100644 index 0000000000..4d5e4c7bb4 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/MSSQLAssetData.cs @@ -0,0 +1,222 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.MSSQL +{ + internal class MSSQLAssetData : IAssetProvider + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private MSSQLManager database; + + #region IAssetProvider Members + + private void UpgradeAssetsTable(string tableName) + { + // null as the version, indicates that the table didn't exist + if (tableName == null) + { + m_log.Info("[ASSETS]: Creating new database tables"); + database.ExecuteResourceSql("CreateAssetsTable.sql"); + return; + } + } + + /// + /// Ensure that the assets related tables exists and are at the latest version + /// + private void TestTables() + { + Dictionary tableList = new Dictionary(); + + tableList["assets"] = null; + database.GetTableVersion(tableList); + + UpgradeAssetsTable(tableList["assets"]); + } + + public AssetBase FetchAsset(LLUUID assetID) + { + AssetBase asset = null; + + Dictionary param = new Dictionary(); + param["id"] = assetID.ToString(); + + IDbCommand result = database.Query("SELECT * FROM assets WHERE id = @id", param); + IDataReader reader = result.ExecuteReader(); + + asset = database.getAssetRow(reader); + reader.Close(); + result.Dispose(); + + return asset; + } + + public void CreateAsset(AssetBase asset) + { + if (ExistsAsset((LLUUID) asset.FullID)) + { + return; + } + + + SqlCommand cmd = + new SqlCommand( + "INSERT INTO assets ([id], [name], [description], [assetType], [invType], [local], [temporary], [data])" + + " VALUES " + + "(@id, @name, @description, @assetType, @invType, @local, @temporary, @data)", + database.getConnection()); + + using (cmd) + { + //SqlParameter p = cmd.Parameters.Add("id", SqlDbType.NVarChar); + //p.Value = asset.FullID.ToString(); + cmd.Parameters.AddWithValue("id", asset.FullID.ToString()); + cmd.Parameters.AddWithValue("name", asset.Name); + cmd.Parameters.AddWithValue("description", asset.Description); + SqlParameter e = cmd.Parameters.Add("assetType", SqlDbType.TinyInt); + e.Value = asset.Type; + SqlParameter f = cmd.Parameters.Add("invType", SqlDbType.TinyInt); + f.Value = asset.InvType; + SqlParameter g = cmd.Parameters.Add("local", SqlDbType.TinyInt); + g.Value = asset.Local; + SqlParameter h = cmd.Parameters.Add("temporary", SqlDbType.TinyInt); + h.Value = asset.Temporary; + SqlParameter i = cmd.Parameters.Add("data", SqlDbType.Image); + i.Value = asset.Data; + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception) + { + throw; + } + + cmd.Dispose(); + } + } + + + public void UpdateAsset(AssetBase asset) + { + SqlCommand command = new SqlCommand("UPDATE assets set id = @id, " + + "name = @name, " + + "description = @description," + + "assetType = @assetType," + + "invType = @invType," + + "local = @local," + + "temporary = @temporary," + + "data = @data where " + + "id = @keyId;", database.getConnection()); + SqlParameter param1 = new SqlParameter("@id", asset.FullID.ToString()); + SqlParameter param2 = new SqlParameter("@name", asset.Name); + SqlParameter param3 = new SqlParameter("@description", asset.Description); + SqlParameter param4 = new SqlParameter("@assetType", asset.Type); + SqlParameter param5 = new SqlParameter("@invType", asset.InvType); + SqlParameter param6 = new SqlParameter("@local", asset.Local); + SqlParameter param7 = new SqlParameter("@temporary", asset.Temporary); + SqlParameter param8 = new SqlParameter("@data", asset.Data); + SqlParameter param9 = new SqlParameter("@keyId", asset.FullID.ToString()); + command.Parameters.Add(param1); + command.Parameters.Add(param2); + command.Parameters.Add(param3); + command.Parameters.Add(param4); + command.Parameters.Add(param5); + command.Parameters.Add(param6); + command.Parameters.Add(param7); + command.Parameters.Add(param8); + command.Parameters.Add(param9); + + try + { + command.ExecuteNonQuery(); + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + } + + public bool ExistsAsset(LLUUID uuid) + { + if (FetchAsset(uuid) != null) + { + return true; + } + return false; + } + + /// + /// All writes are immediately commited to the database, so this is a no-op + /// + public void CommitAssets() + { + } + + #endregion + + #region IPlugin Members + + public void Initialise() + { + IniFile GridDataMySqlFile = new IniFile("mssql_connection.ini"); + string settingDataSource = GridDataMySqlFile.ParseFileReadValue("data_source"); + string settingInitialCatalog = GridDataMySqlFile.ParseFileReadValue("initial_catalog"); + string settingPersistSecurityInfo = GridDataMySqlFile.ParseFileReadValue("persist_security_info"); + string settingUserId = GridDataMySqlFile.ParseFileReadValue("user_id"); + string settingPassword = GridDataMySqlFile.ParseFileReadValue("password"); + + database = + new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId, + settingPassword); + + TestTables(); + } + + public string Version + { +// get { return database.getVersion(); } + get { return database.getVersion(); } + } + + public string Name + { + get { return "MSSQL Asset storage engine"; } + } + + #endregion + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MSSQL/MSSQLGridData.cs b/trunk/OpenSim/Framework/Data.MSSQL/MSSQLGridData.cs new file mode 100644 index 0000000000..36484373c1 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/MSSQLGridData.cs @@ -0,0 +1,327 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Security.Cryptography; +using System.Text; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.MSSQL +{ + /// + /// A grid data interface for Microsoft SQL Server + /// + public class MSSQLGridData : IGridData + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Database manager + /// + private MSSQLManager database; + + private string m_regionsTableName; + + /// + /// Initialises the Grid Interface + /// + public void Initialise() + { + IniFile iniFile = new IniFile("mssql_connection.ini"); + + string settingDataSource = iniFile.ParseFileReadValue("data_source"); + string settingInitialCatalog = iniFile.ParseFileReadValue("initial_catalog"); + string settingPersistSecurityInfo = iniFile.ParseFileReadValue("persist_security_info"); + string settingUserId = iniFile.ParseFileReadValue("user_id"); + string settingPassword = iniFile.ParseFileReadValue("password"); + + m_regionsTableName = iniFile.ParseFileReadValue("regionstablename"); + if (m_regionsTableName == null) + { + m_regionsTableName = "regions"; + } + + database = + new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId, + settingPassword); + + TestTables(); + } + + private void TestTables() + { + IDbCommand cmd = database.Query("SELECT TOP 1 * FROM "+m_regionsTableName, new Dictionary()); + + try + { + cmd.ExecuteNonQuery(); + cmd.Dispose(); + } + catch (Exception) + { + m_log.Info("[DATASTORE]: MSSQL Database doesn't exist... creating"); + database.ExecuteResourceSql("Mssql-regions.sql"); + } + } + + /// + /// Shuts down the grid interface + /// + public void Close() + { + database.Close(); + } + + /// + /// Returns the storage system name + /// + /// A string containing the storage system name + public string getName() + { + return "Sql OpenGridData"; + } + + /// + /// Returns the storage system version + /// + /// A string containing the storage system version + public string getVersion() + { + return "0.1"; + } + + /// + /// Returns a list of regions within the specified ranges + /// + /// minimum X coordinate + /// minimum Y coordinate + /// maximum X coordinate + /// maximum Y coordinate + /// An array of region profiles + public RegionProfileData[] GetProfilesInRange(uint a, uint b, uint c, uint d) + { + return null; + } + + /// + /// Returns a sim profile from it's location + /// + /// Region location handle + /// Sim profile + public RegionProfileData GetProfileByHandle(ulong handle) + { + IDataReader reader = null; + try + { + Dictionary param = new Dictionary(); + param["handle"] = handle.ToString(); + IDbCommand result = database.Query("SELECT * FROM " + m_regionsTableName + " WHERE regionHandle = @handle", param); + reader = result.ExecuteReader(); + + RegionProfileData row = database.getRegionRow(reader); + reader.Close(); + result.Dispose(); + + return row; + } + catch (Exception) + { + if (reader != null) + { + reader.Close(); + } + } + return null; + } + + + /// + /// Returns a sim profile from it's UUID + /// + /// The region UUID + /// The sim profile + public RegionProfileData GetProfileByLLUUID(LLUUID uuid) + { + Dictionary param = new Dictionary(); + param["uuid"] = uuid.ToString(); + IDbCommand result = database.Query("SELECT * FROM " + m_regionsTableName + " WHERE uuid = @uuid", param); + IDataReader reader = result.ExecuteReader(); + + RegionProfileData row = database.getRegionRow(reader); + reader.Close(); + result.Dispose(); + + return row; + } + + /// + /// Adds a new specified region to the database + /// + /// The profile to add + /// A dataresponse enum indicating success + public DataResponse AddProfile(RegionProfileData profile) + { + try + { + if (GetProfileByLLUUID(profile.UUID) != null) + { + return DataResponse.RESPONSE_OK; + } + } + catch (Exception) + { + System.Console.WriteLine("No regions found. Create new one."); + } + + if ( insertRegionRow(profile)) + { + return DataResponse.RESPONSE_OK; + } + else + { + return DataResponse.RESPONSE_ERROR; + } + } + + + /// + /// Creates a new region in the database + /// + /// The region profile to insert + /// Successful? + public bool insertRegionRow(RegionProfileData profile) + { + //Insert new region + string sql = + "INSERT INTO " + m_regionsTableName + " ([regionHandle], [regionName], [uuid], [regionRecvKey], [regionSecret], [regionSendKey], [regionDataURI], "; + sql += + "[serverIP], [serverPort], [serverURI], [locX], [locY], [locZ], [eastOverrideHandle], [westOverrideHandle], [southOverrideHandle], [northOverrideHandle], [regionAssetURI], [regionAssetRecvKey], "; + sql += + "[regionAssetSendKey], [regionUserURI], [regionUserRecvKey], [regionUserSendKey], [regionMapTexture], [serverHttpPort], [serverRemotingPort]) VALUES "; + + sql += "(@regionHandle, @regionName, @uuid, @regionRecvKey, @regionSecret, @regionSendKey, @regionDataURI, "; + sql += + "@serverIP, @serverPort, @serverURI, @locX, @locY, @locZ, @eastOverrideHandle, @westOverrideHandle, @southOverrideHandle, @northOverrideHandle, @regionAssetURI, @regionAssetRecvKey, "; + sql += + "@regionAssetSendKey, @regionUserURI, @regionUserRecvKey, @regionUserSendKey, @regionMapTexture, @serverHttpPort, @serverRemotingPort);"; + + Dictionary parameters = new Dictionary(); + + parameters["regionHandle"] = profile.regionHandle.ToString(); + parameters["regionName"] = profile.regionName; + parameters["uuid"] = profile.UUID.ToString(); + parameters["regionRecvKey"] = profile.regionRecvKey; + parameters["regionSecret"] = profile.regionSecret; + parameters["regionSendKey"] = profile.regionSendKey; + parameters["regionDataURI"] = profile.regionDataURI; + parameters["serverIP"] = profile.serverIP; + parameters["serverPort"] = profile.serverPort.ToString(); + parameters["serverURI"] = profile.serverURI; + parameters["locX"] = profile.regionLocX.ToString(); + parameters["locY"] = profile.regionLocY.ToString(); + parameters["locZ"] = profile.regionLocZ.ToString(); + parameters["eastOverrideHandle"] = profile.regionEastOverrideHandle.ToString(); + parameters["westOverrideHandle"] = profile.regionWestOverrideHandle.ToString(); + parameters["northOverrideHandle"] = profile.regionNorthOverrideHandle.ToString(); + parameters["southOverrideHandle"] = profile.regionSouthOverrideHandle.ToString(); + parameters["regionAssetURI"] = profile.regionAssetURI; + parameters["regionAssetRecvKey"] = profile.regionAssetRecvKey; + parameters["regionAssetSendKey"] = profile.regionAssetSendKey; + parameters["regionUserURI"] = profile.regionUserURI; + parameters["regionUserRecvKey"] = profile.regionUserRecvKey; + parameters["regionUserSendKey"] = profile.regionUserSendKey; + parameters["regionMapTexture"] = profile.regionMapTextureID.ToString(); + parameters["serverHttpPort"] = profile.httpPort.ToString(); + parameters["serverRemotingPort"] = profile.remotingPort.ToString(); + + + bool returnval = false; + + try + { + IDbCommand result = database.Query(sql, parameters); + + if (result.ExecuteNonQuery() == 1) + returnval = true; + + result.Dispose(); + } + catch (Exception e) + { + m_log.Error("MSSQLManager : " + e.ToString()); + } + + return returnval; + } + + /// + /// DEPRECIATED. Attempts to authenticate a region by comparing a shared secret. + /// + /// The UUID of the challenger + /// The attempted regionHandle of the challenger + /// The secret + /// Whether the secret and regionhandle match the database entry for UUID + public bool AuthenticateSim(LLUUID uuid, ulong handle, string authkey) + { + bool throwHissyFit = false; // Should be true by 1.0 + + if (throwHissyFit) + throw new Exception("CRYPTOWEAK AUTHENTICATE: Refusing to authenticate due to replay potential."); + + RegionProfileData data = GetProfileByLLUUID(uuid); + + return (handle == data.regionHandle && authkey == data.regionSecret); + } + + /// + /// NOT YET FUNCTIONAL. Provides a cryptographic authentication of a region + /// + /// This requires a security audit. + /// + /// + /// + /// + /// + public bool AuthenticateSim(LLUUID uuid, ulong handle, string authhash, string challenge) + { + SHA512Managed HashProvider = new SHA512Managed(); + ASCIIEncoding TextProvider = new ASCIIEncoding(); + + byte[] stream = TextProvider.GetBytes(uuid.ToString() + ":" + handle.ToString() + ":" + challenge); + byte[] hash = HashProvider.ComputeHash(stream); + return false; + } + + public ReservationData GetReservationAtPoint(uint x, uint y) + { + return null; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MSSQL/MSSQLInventoryData.cs b/trunk/OpenSim/Framework/Data.MSSQL/MSSQLInventoryData.cs new file mode 100644 index 0000000000..d79d369f6c --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/MSSQLInventoryData.cs @@ -0,0 +1,728 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.MSSQL +{ + /// + /// A MySQL interface for the inventory server + /// + public class MSSQLInventoryData : IInventoryData + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The database manager + /// + private MSSQLManager database; + + /// + /// Loads and initialises this database plugin + /// + public void Initialise() + { + IniFile GridDataMySqlFile = new IniFile("mssql_connection.ini"); + string settingDataSource = GridDataMySqlFile.ParseFileReadValue("data_source"); + string settingInitialCatalog = GridDataMySqlFile.ParseFileReadValue("initial_catalog"); + string settingPersistSecurityInfo = GridDataMySqlFile.ParseFileReadValue("persist_security_info"); + string settingUserId = GridDataMySqlFile.ParseFileReadValue("user_id"); + string settingPassword = GridDataMySqlFile.ParseFileReadValue("password"); + + database = + new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId, + settingPassword); + TestTables(); + } + + #region Test and initialization code + + private void UpgradeFoldersTable(string tableName) + { + // null as the version, indicates that the table didn't exist + if (tableName == null) + { + database.ExecuteResourceSql("CreateFoldersTable.sql"); + //database.ExecuteResourceSql("UpgradeFoldersTableToVersion2.sql"); + return; + } + } + + private void UpgradeItemsTable(string tableName) + { + // null as the version, indicates that the table didn't exist + if (tableName == null) + { + database.ExecuteResourceSql("CreateItemsTable.sql"); + //database.ExecuteResourceSql("UpgradeItemsTableToVersion2.sql"); + return; + } + } + + private void TestTables() + { + Dictionary tableList = new Dictionary(); + + tableList["inventoryfolders"] = null; + tableList["inventoryitems"] = null; + + database.GetTableVersion(tableList); + + UpgradeFoldersTable(tableList["inventoryfolders"]); + UpgradeItemsTable(tableList["inventoryitems"]); + } + + #endregion + + /// + /// The name of this DB provider + /// + /// Name of DB provider + public string getName() + { + return "MSSQL Inventory Data Interface"; + } + + /// + /// Closes this DB provider + /// + public void Close() + { + // Do nothing. + } + + /// + /// Returns the version of this DB provider + /// + /// A string containing the DB provider + public string getVersion() + { + return database.getVersion(); + } + + /// + /// Returns a list of items in a specified folder + /// + /// The folder to search + /// A list containing inventory items + public List getInventoryInFolder(LLUUID folderID) + { + try + { + lock (database) + { + List items = new List(); + + Dictionary param = new Dictionary(); + param["parentFolderID"] = folderID.ToString(); + + IDbCommand result = + database.Query("SELECT * FROM inventoryitems WHERE parentFolderID = @parentFolderID", param); + IDataReader reader = result.ExecuteReader(); + + while (reader.Read()) + items.Add(readInventoryItem(reader)); + + reader.Close(); + result.Dispose(); + + return items; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Returns a list of the root folders within a users inventory + /// + /// The user whos inventory is to be searched + /// A list of folder objects + public List getUserRootFolders(LLUUID user) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["uuid"] = user.ToString(); + param["zero"] = LLUUID.Zero.ToString(); + + IDbCommand result = + database.Query( + "SELECT * FROM inventoryfolders WHERE parentFolderID = @zero AND agentID = @uuid", param); + IDataReader reader = result.ExecuteReader(); + + List items = new List(); + while (reader.Read()) + items.Add(readInventoryFolder(reader)); + + + reader.Close(); + result.Dispose(); + + return items; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + // see InventoryItemBase.getUserRootFolder + public InventoryFolderBase getUserRootFolder(LLUUID user) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["uuid"] = user.ToString(); + param["zero"] = LLUUID.Zero.ToString(); + + IDbCommand result = + database.Query( + "SELECT * FROM inventoryfolders WHERE parentFolderID = @zero AND agentID = @uuid", param); + IDataReader reader = result.ExecuteReader(); + + List items = new List(); + while (reader.Read()) + items.Add(readInventoryFolder(reader)); + + InventoryFolderBase rootFolder = null; + + // There should only ever be one root folder for a user. However, if there's more + // than one we'll simply use the first one rather than failing. It would be even + // nicer to print some message to this effect, but this feels like it's too low a + // to put such a message out, and it's too minor right now to spare the time to + // suitably refactor. + if (items.Count > 0) + { + rootFolder = items[0]; + } + + reader.Close(); + result.Dispose(); + + return rootFolder; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Returns a list of folders in a users inventory contained within the specified folder + /// + /// The folder to search + /// A list of inventory folders + public List getInventoryFolders(LLUUID parentID) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["parentFolderID"] = parentID.ToString(); + + + IDbCommand result = + database.Query("SELECT * FROM inventoryfolders WHERE parentFolderID = @parentFolderID", param); + IDataReader reader = result.ExecuteReader(); + + List items = new List(); + + while (reader.Read()) + items.Add(readInventoryFolder(reader)); + + reader.Close(); + result.Dispose(); + + return items; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Reads a one item from an SQL result + /// + /// The SQL Result + /// the item read + private InventoryItemBase readInventoryItem(IDataReader reader) + { + try + { + InventoryItemBase item = new InventoryItemBase(); + + item.inventoryID = new LLUUID((string) reader["inventoryID"]); + item.assetID = new LLUUID((string) reader["assetID"]); + item.assetType = (int) reader["assetType"]; + item.parentFolderID = new LLUUID((string) reader["parentFolderID"]); + item.avatarID = new LLUUID((string) reader["avatarID"]); + item.inventoryName = (string) reader["inventoryName"]; + item.inventoryDescription = (string) reader["inventoryDescription"]; + item.inventoryNextPermissions = Convert.ToUInt32(reader["inventoryNextPermissions"]); + item.inventoryCurrentPermissions = Convert.ToUInt32(reader["inventoryCurrentPermissions"]); + item.invType = (int) reader["invType"]; + item.creatorsID = new LLUUID((string) reader["creatorID"]); + item.inventoryBasePermissions = Convert.ToUInt32(reader["inventoryBasePermissions"]); + item.inventoryEveryOnePermissions = Convert.ToUInt32(reader["inventoryEveryOnePermissions"]); + return item; + } + catch (SqlException e) + { + m_log.Error(e.ToString()); + } + + return null; + } + + /// + /// Returns a specified inventory item + /// + /// The item to return + /// An inventory item + public InventoryItemBase getInventoryItem(LLUUID itemID) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["inventoryID"] = itemID.ToString(); + + IDbCommand result = + database.Query("SELECT * FROM inventoryitems WHERE inventoryID = @inventoryID", param); + IDataReader reader = result.ExecuteReader(); + + InventoryItemBase item = null; + if (reader.Read()) + item = readInventoryItem(reader); + + reader.Close(); + result.Dispose(); + + return item; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + } + return null; + } + + /// + /// Reads a list of inventory folders returned by a query. + /// + /// A MySQL Data Reader + /// A List containing inventory folders + protected InventoryFolderBase readInventoryFolder(IDataReader reader) + { + try + { + InventoryFolderBase folder = new InventoryFolderBase(); + folder.agentID = new LLUUID((string) reader["agentID"]); + folder.parentID = new LLUUID((string) reader["parentFolderID"]); + folder.folderID = new LLUUID((string) reader["folderID"]); + folder.name = (string) reader["folderName"]; + folder.type = (short) reader["type"]; + folder.version = (ushort) ((int) reader["version"]); + return folder; + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + + return null; + } + + + /// + /// Returns a specified inventory folder + /// + /// The folder to return + /// A folder class + public InventoryFolderBase getInventoryFolder(LLUUID folderID) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["uuid"] = folderID.ToString(); + + IDbCommand result = database.Query("SELECT * FROM inventoryfolders WHERE folderID = @uuid", param); + IDataReader reader = result.ExecuteReader(); + + reader.Read(); + InventoryFolderBase folder = readInventoryFolder(reader); + reader.Close(); + result.Dispose(); + + return folder; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Adds a specified item to the database + /// + /// The inventory item + public void addInventoryItem(InventoryItemBase item) + { + string sql = "INSERT INTO inventoryitems"; + sql += + "([inventoryID], [assetID], [assetType], [parentFolderID], [avatarID], [inventoryName], [inventoryDescription], [inventoryNextPermissions], [inventoryCurrentPermissions], [invType], [creatorID], [inventoryBasePermissions], [inventoryEveryOnePermissions]) VALUES "; + sql += + "(@inventoryID, @assetID, @assetType, @parentFolderID, @avatarID, @inventoryName, @inventoryDescription, @inventoryNextPermissions, @inventoryCurrentPermissions, @invType, @creatorID, @inventoryBasePermissions, @inventoryEveryOnePermissions);"; + + try + { + Dictionary param = new Dictionary(); + param["inventoryID"] = item.inventoryID.ToString(); + param["assetID"] = item.assetID.ToString(); + param["assetType"] = item.assetType.ToString(); + param["parentFolderID"] = item.parentFolderID.ToString(); + param["avatarID"] = item.avatarID.ToString(); + param["inventoryName"] = item.inventoryName; + param["inventoryDescription"] = item.inventoryDescription; + param["inventoryNextPermissions"] = item.inventoryNextPermissions.ToString(); + param["inventoryCurrentPermissions"] = item.inventoryCurrentPermissions.ToString(); + param["invType"] = Convert.ToString(item.invType); + param["creatorID"] = item.creatorsID.ToString(); + param["inventoryBasePermissions"] = Convert.ToString(item.inventoryBasePermissions); + param["inventoryEveryOnePermissions"] = Convert.ToString(item.inventoryEveryOnePermissions); + + IDbCommand result = database.Query(sql, param); + result.ExecuteNonQuery(); + result.Dispose(); + } + catch (SqlException e) + { + m_log.Error(e.ToString()); + } + } + + /// + /// Updates the specified inventory item + /// + /// Inventory item to update + public void updateInventoryItem(InventoryItemBase item) + { + SqlCommand command = new SqlCommand("UPDATE inventoryitems set inventoryID = @inventoryID, " + + "assetID = @assetID, " + + "assetType = @assetType" + + "parentFolderID = @parentFolderID" + + "avatarID = @avatarID" + + "inventoryName = @inventoryName" + + "inventoryDescription = @inventoryDescription" + + "inventoryNextPermissions = @inventoryNextPermissions" + + "inventoryCurrentPermissions = @inventoryCurrentPermissions" + + "invType = @invType" + + "creatorID = @creatorID" + + "inventoryBasePermissions = @inventoryBasePermissions" + + "inventoryEveryOnePermissions = @inventoryEveryOnePermissions) where " + + "inventoryID = @keyInventoryID;", database.getConnection()); + SqlParameter param1 = new SqlParameter("@inventoryID", item.inventoryID.ToString()); + SqlParameter param2 = new SqlParameter("@assetID", item.assetID); + SqlParameter param3 = new SqlParameter("@assetType", item.assetType); + SqlParameter param4 = new SqlParameter("@parentFolderID", item.parentFolderID); + SqlParameter param5 = new SqlParameter("@avatarID", item.avatarID); + SqlParameter param6 = new SqlParameter("@inventoryName", item.inventoryName); + SqlParameter param7 = new SqlParameter("@inventoryDescription", item.inventoryDescription); + SqlParameter param8 = new SqlParameter("@inventoryNextPermissions", item.inventoryNextPermissions); + SqlParameter param9 = new SqlParameter("@inventoryCurrentPermissions", item.inventoryCurrentPermissions); + SqlParameter param10 = new SqlParameter("@invType", item.invType); + SqlParameter param11 = new SqlParameter("@creatorID", item.creatorsID); + SqlParameter param12 = new SqlParameter("@inventoryBasePermissions", item.inventoryBasePermissions); + SqlParameter param13 = new SqlParameter("@inventoryEveryOnePermissions", item.inventoryEveryOnePermissions); + SqlParameter param14 = new SqlParameter("@keyInventoryID", item.inventoryID.ToString()); + command.Parameters.Add(param1); + command.Parameters.Add(param2); + command.Parameters.Add(param3); + command.Parameters.Add(param4); + command.Parameters.Add(param5); + command.Parameters.Add(param6); + command.Parameters.Add(param7); + command.Parameters.Add(param8); + command.Parameters.Add(param9); + command.Parameters.Add(param10); + command.Parameters.Add(param11); + command.Parameters.Add(param12); + command.Parameters.Add(param13); + command.Parameters.Add(param14); + + try + { + command.ExecuteNonQuery(); + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + } + + /// + /// + /// + /// + public void deleteInventoryItem(LLUUID itemID) + { + try + { + Dictionary param = new Dictionary(); + param["uuid"] = itemID.ToString(); + + IDbCommand cmd = database.Query("DELETE FROM inventoryitems WHERE inventoryID=@uuid", param); + cmd.ExecuteNonQuery(); + cmd.Dispose(); + } + catch (SqlException e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + } + } + + /// + /// Creates a new inventory folder + /// + /// Folder to create + public void addInventoryFolder(InventoryFolderBase folder) + { + string sql = + "INSERT INTO inventoryfolders ([folderID], [agentID], [parentFolderID], [folderName], [type], [version]) VALUES "; + sql += "(@folderID, @agentID, @parentFolderID, @folderName, @type, @version);"; + + + Dictionary param = new Dictionary(); + param["folderID"] = folder.folderID.ToString(); + param["agentID"] = folder.agentID.ToString(); + param["parentFolderID"] = folder.parentID.ToString(); + param["folderName"] = folder.name; + param["type"] = Convert.ToString(folder.type); + param["version"] = Convert.ToString(folder.version); + + try + { + IDbCommand result = database.Query(sql, param); + result.ExecuteNonQuery(); + result.Dispose(); + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + } + + /// + /// Updates an inventory folder + /// + /// Folder to update + public void updateInventoryFolder(InventoryFolderBase folder) + { + SqlCommand command = new SqlCommand("UPDATE inventoryfolders set folderID = @folderID, " + + "agentID = @agentID, " + + "parentFolderID = @parentFolderID," + + "folderName = @folderName," + + "type = @type," + + "version = @version where " + + "folderID = @keyFolderID;", database.getConnection()); + SqlParameter param1 = new SqlParameter("@folderID", folder.folderID.ToString()); + SqlParameter param2 = new SqlParameter("@agentID", folder.agentID.ToString()); + SqlParameter param3 = new SqlParameter("@parentFolderID", folder.parentID.ToString()); + SqlParameter param4 = new SqlParameter("@folderName", folder.name); + SqlParameter param5 = new SqlParameter("@type", folder.type); + SqlParameter param6 = new SqlParameter("@version", folder.version); + SqlParameter param7 = new SqlParameter("@keyFolderID", folder.folderID.ToString()); + command.Parameters.Add(param1); + command.Parameters.Add(param2); + command.Parameters.Add(param3); + command.Parameters.Add(param4); + command.Parameters.Add(param5); + command.Parameters.Add(param6); + command.Parameters.Add(param7); + + try + { + command.ExecuteNonQuery(); + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + } + + /// + /// Updates an inventory folder + /// + /// Folder to update + public void moveInventoryFolder(InventoryFolderBase folder) + { + SqlCommand command = new SqlCommand("UPDATE inventoryfolders set folderID = @folderID, " + + "parentFolderID = @parentFolderID," + + "folderID = @keyFolderID;", database.getConnection()); + SqlParameter param1 = new SqlParameter("@folderID", folder.folderID.ToString()); + SqlParameter param2 = new SqlParameter("@parentFolderID", folder.parentID.ToString()); + SqlParameter param3 = new SqlParameter("@keyFolderID", folder.folderID.ToString()); + command.Parameters.Add(param1); + command.Parameters.Add(param2); + command.Parameters.Add(param3); + + try + { + command.ExecuteNonQuery(); + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + } + + /// + /// Append a list of all the child folders of a parent folder + /// + /// list where folders will be appended + /// ID of parent + protected void getInventoryFolders(ref List folders, LLUUID parentID) + { + List subfolderList = getInventoryFolders(parentID); + + foreach (InventoryFolderBase f in subfolderList) + folders.Add(f); + } + + /// + /// Returns all child folders in the hierarchy from the parent folder and down + /// + /// The folder to get subfolders for + /// A list of inventory folders + protected List getFolderHierarchy(LLUUID parentID) + { + List folders = new List(); + getInventoryFolders(ref folders, parentID); + + for (int i = 0; i < folders.Count; i++) + getInventoryFolders(ref folders, folders[i].folderID); + + return folders; + } + + protected void deleteOneFolder(LLUUID folderID) + { + try + { + Dictionary param = new Dictionary(); + param["folderID"] = folderID.ToString(); + + IDbCommand cmd = database.Query("DELETE FROM inventoryfolders WHERE folderID=@folderID", param); + cmd.ExecuteNonQuery(); + cmd.Dispose(); + } + catch (SqlException e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + } + } + + protected void deleteItemsInFolder(LLUUID folderID) + { + try + { + Dictionary param = new Dictionary(); + param["parentFolderID"] = folderID.ToString(); + + + IDbCommand cmd = + database.Query("DELETE FROM inventoryitems WHERE parentFolderID=@parentFolderID", param); + cmd.ExecuteNonQuery(); + cmd.Dispose(); + } + catch (SqlException e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + } + } + + + /// + /// Delete an inventory folder + /// + /// Id of folder to delete + public void deleteInventoryFolder(LLUUID folderID) + { + lock (database) + { + List subFolders = getFolderHierarchy(folderID); + + //Delete all sub-folders + foreach (InventoryFolderBase f in subFolders) + { + deleteOneFolder(f.folderID); + deleteItemsInFolder(f.folderID); + } + + //Delete the actual row + deleteOneFolder(folderID); + deleteItemsInFolder(folderID); + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MSSQL/MSSQLLogData.cs b/trunk/OpenSim/Framework/Data.MSSQL/MSSQLLogData.cs new file mode 100644 index 0000000000..1e83496294 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/MSSQLLogData.cs @@ -0,0 +1,120 @@ +/* +* 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.Collections.Generic; +using System.Data; + +namespace OpenSim.Framework.Data.MSSQL +{ + /// + /// An interface to the log database for MySQL + /// + internal class MSSQLLogData : ILogData + { + /// + /// The database manager + /// + public MSSQLManager database; + + /// + /// Artificial constructor called when the plugin is loaded + /// + public void Initialise() + { + IniFile GridDataMySqlFile = new IniFile("mssql_connection.ini"); + string settingDataSource = GridDataMySqlFile.ParseFileReadValue("data_source"); + string settingInitialCatalog = GridDataMySqlFile.ParseFileReadValue("initial_catalog"); + string settingPersistSecurityInfo = GridDataMySqlFile.ParseFileReadValue("persist_security_info"); + string settingUserId = GridDataMySqlFile.ParseFileReadValue("user_id"); + string settingPassword = GridDataMySqlFile.ParseFileReadValue("password"); + + database = + new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId, + settingPassword); + + IDbCommand cmd = database.Query("select top 1 * from logs", new Dictionary()); + try + { + cmd.ExecuteNonQuery(); + cmd.Dispose(); + } + catch + { + database.ExecuteResourceSql("Mssql-logs.sql"); + } + + } + + /// + /// Saves a log item to the database + /// + /// The daemon triggering the event + /// The target of the action (region / agent UUID, etc) + /// The method call where the problem occured + /// The arguments passed to the method + /// How critical is this? + /// The message to log + public void saveLog(string serverDaemon, string target, string methodCall, string arguments, int priority, + string logMessage) + { + try + { + database.insertLogRow(serverDaemon, target, methodCall, arguments, priority, logMessage); + } + catch + { + database.Reconnect(); + } + } + + /// + /// Returns the name of this DB provider + /// + /// A string containing the DB provider name + public string getName() + { + return "MSSQL Logdata Interface"; + } + + /// + /// Closes the database provider + /// + public void Close() + { + // Do nothing. + } + + /// + /// Returns the version of this DB provider + /// + /// A string containing the provider version + public string getVersion() + { + return "0.1"; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MSSQL/MSSQLManager.cs b/trunk/OpenSim/Framework/Data.MSSQL/MSSQLManager.cs new file mode 100644 index 0000000000..085cf57fd1 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/MSSQLManager.cs @@ -0,0 +1,525 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.IO; +using System.Reflection; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.MSSQL +{ + /// + /// A management class for the MS SQL Storage Engine + /// + public class MSSQLManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The database connection object + /// + private IDbConnection dbcon; + + /// + /// Connection string for ADO.net + /// + private readonly string connectionString; + + public MSSQLManager(string dataSource, string initialCatalog, string persistSecurityInfo, string userId, + string password) + { + connectionString = "Data Source=" + dataSource + ";Initial Catalog=" + initialCatalog + + ";Persist Security Info=" + persistSecurityInfo + ";User ID=" + userId + ";Password=" + + password + ";"; + dbcon = new SqlConnection(connectionString); + dbcon.Open(); + } + + //private DataTable createRegionsTable() + //{ + // DataTable regions = new DataTable("regions"); + + // createCol(regions, "regionHandle", typeof (ulong)); + // createCol(regions, "regionName", typeof (String)); + // createCol(regions, "uuid", typeof (String)); + + // createCol(regions, "regionRecvKey", typeof (String)); + // createCol(regions, "regionSecret", typeof (String)); + // createCol(regions, "regionSendKey", typeof (String)); + + // createCol(regions, "regionDataURI", typeof (String)); + // createCol(regions, "serverIP", typeof (String)); + // createCol(regions, "serverPort", typeof (String)); + // createCol(regions, "serverURI", typeof (String)); + + + // createCol(regions, "locX", typeof (uint)); + // createCol(regions, "locY", typeof (uint)); + // createCol(regions, "locZ", typeof (uint)); + + // createCol(regions, "eastOverrideHandle", typeof (ulong)); + // createCol(regions, "westOverrideHandle", typeof (ulong)); + // createCol(regions, "southOverrideHandle", typeof (ulong)); + // createCol(regions, "northOverrideHandle", typeof (ulong)); + + // createCol(regions, "regionAssetURI", typeof (String)); + // createCol(regions, "regionAssetRecvKey", typeof (String)); + // createCol(regions, "regionAssetSendKey", typeof (String)); + + // createCol(regions, "regionUserURI", typeof (String)); + // createCol(regions, "regionUserRecvKey", typeof (String)); + // createCol(regions, "regionUserSendKey", typeof (String)); + + // createCol(regions, "regionMapTexture", typeof (String)); + // createCol(regions, "serverHttpPort", typeof (String)); + // createCol(regions, "serverRemotingPort", typeof (uint)); + + // // Add in contraints + // regions.PrimaryKey = new DataColumn[] {regions.Columns["UUID"]}; + // return regions; + //} + + protected static void createCol(DataTable dt, string name, Type type) + { + DataColumn col = new DataColumn(name, type); + dt.Columns.Add(col); + } + + protected static string defineTable(DataTable dt) + { + string sql = "create table " + dt.TableName + "("; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ",\n"; + } + + subsql += col.ColumnName + " " + SqlType(col.DataType); + if (col == dt.PrimaryKey[0]) + { + subsql += " primary key"; + } + } + sql += subsql; + sql += ")"; + return sql; + } + + + // this is something we'll need to implement for each db + // slightly differently. + private static string SqlType(Type type) + { + if (type == typeof(String)) + { + return "varchar(255)"; + } + else if (type == typeof(Int32)) + { + return "integer"; + } + else if (type == typeof(Double)) + { + return "float"; + } + else if (type == typeof(Byte[])) + { + return "image"; + } + else + { + return "varchar(255)"; + } + } + + /// + /// Shuts down the database connection + /// + public void Close() + { + dbcon.Close(); + dbcon = null; + } + + /// + /// Reconnects to the database + /// + public void Reconnect() + { + lock (dbcon) + { + try + { + // Close the DB connection + dbcon.Close(); + // Try reopen it + dbcon = new SqlConnection(connectionString); + dbcon.Open(); + } + catch (Exception e) + { + m_log.Error("Unable to reconnect to database " + e.ToString()); + } + } + } + + /// + /// Runs a query with protection against SQL Injection by using parameterised input. + /// + /// The SQL string - replace any variables such as WHERE x = "y" with WHERE x = @y + /// The parameters - index so that @y is indexed as 'y' + /// A Sql DB Command + public IDbCommand Query(string sql, Dictionary parameters) + { + SqlCommand dbcommand = (SqlCommand)dbcon.CreateCommand(); + dbcommand.CommandText = sql; + foreach (KeyValuePair param in parameters) + { + dbcommand.Parameters.AddWithValue(param.Key, param.Value); + } + + return (IDbCommand)dbcommand; + } + + /// + /// Runs a database reader object and returns a region row + /// + /// An active database reader + /// A region row + public RegionProfileData getRegionRow(IDataReader reader) + { + RegionProfileData regionprofile = new RegionProfileData(); + + if (reader.Read()) + { + // Region Main + regionprofile.regionHandle = Convert.ToUInt64(reader["regionHandle"]); + regionprofile.regionName = (string)reader["regionName"]; + regionprofile.UUID = new LLUUID((string)reader["uuid"]); + + // Secrets + regionprofile.regionRecvKey = (string)reader["regionRecvKey"]; + regionprofile.regionSecret = (string)reader["regionSecret"]; + regionprofile.regionSendKey = (string)reader["regionSendKey"]; + + // Region Server + regionprofile.regionDataURI = (string)reader["regionDataURI"]; + regionprofile.regionOnline = false; // Needs to be pinged before this can be set. + regionprofile.serverIP = (string)reader["serverIP"]; + regionprofile.serverPort = Convert.ToUInt32(reader["serverPort"]); + regionprofile.serverURI = (string)reader["serverURI"]; + regionprofile.httpPort = Convert.ToUInt32(reader["serverHttpPort"]); + regionprofile.remotingPort = Convert.ToUInt32(reader["serverRemotingPort"]); + + + // Location + regionprofile.regionLocX = Convert.ToUInt32(reader["locX"]); + regionprofile.regionLocY = Convert.ToUInt32(reader["locY"]); + regionprofile.regionLocZ = Convert.ToUInt32(reader["locZ"]); + + // Neighbours - 0 = No Override + regionprofile.regionEastOverrideHandle = Convert.ToUInt64(reader["eastOverrideHandle"]); + regionprofile.regionWestOverrideHandle = Convert.ToUInt64(reader["westOverrideHandle"]); + regionprofile.regionSouthOverrideHandle = Convert.ToUInt64(reader["southOverrideHandle"]); + regionprofile.regionNorthOverrideHandle = Convert.ToUInt64(reader["northOverrideHandle"]); + + // Assets + regionprofile.regionAssetURI = (string)reader["regionAssetURI"]; + regionprofile.regionAssetRecvKey = (string)reader["regionAssetRecvKey"]; + regionprofile.regionAssetSendKey = (string)reader["regionAssetSendKey"]; + + // Userserver + regionprofile.regionUserURI = (string)reader["regionUserURI"]; + regionprofile.regionUserRecvKey = (string)reader["regionUserRecvKey"]; + regionprofile.regionUserSendKey = (string)reader["regionUserSendKey"]; + + // World Map Addition + string tempRegionMap = reader["regionMapTexture"].ToString(); + if (tempRegionMap != String.Empty) + { + regionprofile.regionMapTextureID = new LLUUID(tempRegionMap); + } + else + { + regionprofile.regionMapTextureID = new LLUUID(); + } + } + else + { + reader.Close(); + throw new Exception("No rows to return"); + } + return regionprofile; + } + + /// + /// Reads a user profile from an active data reader + /// + /// An active database reader + /// A user profile + public UserProfileData readUserRow(IDataReader reader) + { + UserProfileData retval = new UserProfileData(); + + if (reader.Read()) + { + retval.UUID = new LLUUID((string)reader["UUID"]); + retval.username = (string)reader["username"]; + retval.surname = (string)reader["lastname"]; + + retval.passwordHash = (string)reader["passwordHash"]; + retval.passwordSalt = (string)reader["passwordSalt"]; + + retval.homeRegion = Convert.ToUInt64(reader["homeRegion"].ToString()); + retval.homeLocation = new LLVector3( + Convert.ToSingle(reader["homeLocationX"].ToString()), + Convert.ToSingle(reader["homeLocationY"].ToString()), + Convert.ToSingle(reader["homeLocationZ"].ToString())); + retval.homeLookAt = new LLVector3( + Convert.ToSingle(reader["homeLookAtX"].ToString()), + Convert.ToSingle(reader["homeLookAtY"].ToString()), + Convert.ToSingle(reader["homeLookAtZ"].ToString())); + + retval.created = Convert.ToInt32(reader["created"].ToString()); + retval.lastLogin = Convert.ToInt32(reader["lastLogin"].ToString()); + + retval.userInventoryURI = (string)reader["userInventoryURI"]; + retval.userAssetURI = (string)reader["userAssetURI"]; + + retval.profileCanDoMask = Convert.ToUInt32(reader["profileCanDoMask"].ToString()); + retval.profileWantDoMask = Convert.ToUInt32(reader["profileWantDoMask"].ToString()); + + retval.profileAboutText = (string)reader["profileAboutText"]; + retval.profileFirstText = (string)reader["profileFirstText"]; + + retval.profileImage = new LLUUID((string)reader["profileImage"]); + retval.profileFirstImage = new LLUUID((string)reader["profileFirstImage"]); + retval.webLoginKey = new LLUUID((string)reader["webLoginKey"]); + } + else + { + return null; + } + return retval; + } + + /// + /// Reads an agent row from a database reader + /// + /// An active database reader + /// A user session agent + public UserAgentData readAgentRow(IDataReader reader) + { + UserAgentData retval = new UserAgentData(); + + if (reader.Read()) + { + // Agent IDs + retval.UUID = new LLUUID((string)reader["UUID"]); + retval.sessionID = new LLUUID((string)reader["sessionID"]); + retval.secureSessionID = new LLUUID((string)reader["secureSessionID"]); + + // Agent Who? + retval.agentIP = (string)reader["agentIP"]; + retval.agentPort = Convert.ToUInt32(reader["agentPort"].ToString()); + retval.agentOnline = Convert.ToBoolean(reader["agentOnline"].ToString()); + + // Login/Logout times (UNIX Epoch) + retval.loginTime = Convert.ToInt32(reader["loginTime"].ToString()); + retval.logoutTime = Convert.ToInt32(reader["logoutTime"].ToString()); + + // Current position + retval.currentRegion = (string)reader["currentRegion"]; + retval.currentHandle = Convert.ToUInt64(reader["currentHandle"].ToString()); + LLVector3.TryParse((string)reader["currentPos"], out retval.currentPos); + } + else + { + return null; + } + return retval; + } + + public AssetBase getAssetRow(IDataReader reader) + { + AssetBase asset = new AssetBase(); + if (reader.Read()) + { + // Region Main + + asset = new AssetBase(); + asset.Data = (byte[])reader["data"]; + asset.Description = (string)reader["description"]; + asset.FullID = new LLUUID((string)reader["id"]); + asset.InvType = Convert.ToSByte(reader["invType"]); + asset.Local = Convert.ToBoolean(reader["local"]); // ((sbyte)reader["local"]) != 0 ? true : false; + asset.Name = (string)reader["name"]; + asset.Type = Convert.ToSByte(reader["assetType"]); + } + else + { + return null; // throw new Exception("No rows to return"); + } + return asset; + } + + + /// + /// Inserts a new row into the log database + /// + /// The daemon which triggered this event + /// Who were we operating on when this occured (region UUID, user UUID, etc) + /// The method call where the problem occured + /// The arguments passed to the method + /// How critical is this? + /// Extra message info + /// Saved successfully? + public bool insertLogRow(string serverDaemon, string target, string methodCall, string arguments, int priority, + string logMessage) + { + string sql = "INSERT INTO logs ([target], [server], [method], [arguments], [priority], [message]) VALUES "; + sql += "(@target, @server, @method, @arguments, @priority, @message);"; + + Dictionary parameters = new Dictionary(); + parameters["server"] = serverDaemon; + parameters["target"] = target; + parameters["method"] = methodCall; + parameters["arguments"] = arguments; + parameters["priority"] = priority.ToString(); + parameters["message"] = logMessage; + + bool returnval = false; + + try + { + IDbCommand result = Query(sql, parameters); + + if (result.ExecuteNonQuery() == 1) + returnval = true; + + result.Dispose(); + } + catch (Exception e) + { + m_log.Error(e.ToString()); + return false; + } + + return returnval; + } + + /// + /// Execute a SQL statement stored in a resource, as a string + /// + /// + public void ExecuteResourceSql(string name) + { + SqlCommand cmd = new SqlCommand(getResourceString(name), (SqlConnection)dbcon); + cmd.ExecuteNonQuery(); + cmd.Dispose(); + } + + public SqlConnection getConnection() + { + return (SqlConnection)dbcon; + } + + /// + /// Given a list of tables, return the version of the tables, as seen in the database + /// + /// + public void GetTableVersion(Dictionary tableList) + { + lock (dbcon) + { + Dictionary param = new Dictionary(); + param["dbname"] = dbcon.Database; + IDbCommand tablesCmd = + Query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_CATALOG=@dbname", param); + using (IDataReader tables = tablesCmd.ExecuteReader()) + { + while (tables.Read()) + { + try + { + string tableName = (string)tables["TABLE_NAME"]; + if (tableList.ContainsKey(tableName)) + tableList[tableName] = tableName; + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + } + tables.Close(); + } + } + } + + private string getResourceString(string name) + { + Assembly assem = GetType().Assembly; + string[] names = assem.GetManifestResourceNames(); + + foreach (string s in names) + if (s.EndsWith(name)) + using (Stream resource = assem.GetManifestResourceStream(s)) + { + using (StreamReader resourceReader = new StreamReader(resource)) + { + string resourceString = resourceReader.ReadToEnd(); + return resourceString; + } + } + throw new Exception(string.Format("Resource '{0}' was not found", name)); + } + + /// + /// Returns the version of this DB provider + /// + /// A string containing the DB provider + public string getVersion() + { + Module module = GetType().Module; + string dllName = module.Assembly.ManifestModule.Name; + Version dllVersion = module.Assembly.GetName().Version; + + + return + string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build, + dllVersion.Revision); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MSSQL/MSSQLUserData.cs b/trunk/OpenSim/Framework/Data.MSSQL/MSSQLUserData.cs new file mode 100644 index 0000000000..402a88f4b7 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/MSSQLUserData.cs @@ -0,0 +1,771 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.MSSQL +{ + /// + /// A database interface class to a user profile storage system + /// + public class MSSQLUserData : IUserData + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Database manager for MySQL + /// + public MSSQLManager database; + + private string m_agentsTableName; + private string m_usersTableName; + private string m_userFriendsTableName; + + /// + /// Loads and initialises the MySQL storage plugin + /// + public void Initialise() + { + // Load from an INI file connection details + // TODO: move this to XML? + IniFile iniFile = new IniFile("mssql_connection.ini"); + string settingDataSource = iniFile.ParseFileReadValue("data_source"); + string settingInitialCatalog = iniFile.ParseFileReadValue("initial_catalog"); + string settingPersistSecurityInfo = iniFile.ParseFileReadValue("persist_security_info"); + string settingUserId = iniFile.ParseFileReadValue("user_id"); + string settingPassword = iniFile.ParseFileReadValue("password"); + + m_usersTableName = iniFile.ParseFileReadValue("userstablename"); + if (m_usersTableName == null) + { + m_usersTableName = "users"; + } + + m_userFriendsTableName = iniFile.ParseFileReadValue("userfriendstablename"); + if (m_userFriendsTableName == null) + { + m_userFriendsTableName = "userfriends"; + } + + m_agentsTableName = iniFile.ParseFileReadValue("agentstablename"); + if (m_agentsTableName == null) + { + m_agentsTableName = "agents"; + } + + database = + new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId, + settingPassword); + + TestTables(); + } + + private bool TestTables() + { + IDbCommand cmd; + + cmd = database.Query("select top 1 * from " + m_usersTableName, new Dictionary()); + try + { + cmd.ExecuteNonQuery(); + } + catch + { + database.ExecuteResourceSql("Mssql-users.sql"); + } + + cmd = database.Query("select top 1 * from " + m_agentsTableName, new Dictionary()); + try + { + cmd.ExecuteNonQuery(); + } + catch + { + database.ExecuteResourceSql("Mssql-agents.sql"); + } + + cmd = database.Query("select top 1 * from " + m_userFriendsTableName, new Dictionary()); + try + { + cmd.ExecuteNonQuery(); + } + catch + { + database.ExecuteResourceSql("CreateUserFriendsTable.sql"); + } + + return true; + } + /// + /// Searches the database for a specified user profile by name components + /// + /// The first part of the account name + /// The second part of the account name + /// A user profile + public UserProfileData GetUserByName(string user, string last) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["first"] = user; + param["second"] = last; + + IDbCommand result = + database.Query("SELECT * FROM " + m_usersTableName + " WHERE username = @first AND lastname = @second", param); + IDataReader reader = result.ExecuteReader(); + + UserProfileData row = database.readUserRow(reader); + + reader.Close(); + result.Dispose(); + + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + #region User Friends List Data + + public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms) + { + int dtvalue = Util.UnixTimeSinceEpoch(); + + Dictionary param = new Dictionary(); + param["@ownerID"] = friendlistowner.UUID.ToString(); + param["@friendID"] = friend.UUID.ToString(); + param["@friendPerms"] = perms.ToString(); + param["@datetimestamp"] = dtvalue.ToString(); + + try + { + lock (database) + { + IDbCommand adder = + database.Query( + "INSERT INTO " + m_userFriendsTableName + " " + + "(ownerID,friendID,friendPerms,datetimestamp) " + + "VALUES " + + "(@ownerID,@friendID,@friendPerms,@datetimestamp)", + param); + + adder.ExecuteNonQuery(); + + adder = + database.Query( + "INSERT INTO " + m_userFriendsTableName + " " + + "(ownerID,friendID,friendPerms,datetimestamp) " + + "VALUES " + + "(@friendID,@ownerID,@friendPerms,@datetimestamp)", + param); + adder.ExecuteNonQuery(); + + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return; + } + } + + public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend) + { + Dictionary param = new Dictionary(); + param["@ownerID"] = friendlistowner.UUID.ToString(); + param["@friendID"] = friend.UUID.ToString(); + + + try + { + lock (database) + { + IDbCommand updater = + database.Query( + "delete from " + m_userFriendsTableName + " where ownerID = @ownerID and friendID = @friendID", + param); + updater.ExecuteNonQuery(); + + updater = + database.Query( + "delete from " + m_userFriendsTableName + " where ownerID = @friendID and friendID = @ownerID", + param); + updater.ExecuteNonQuery(); + + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return; + } + } + + public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms) + { + Dictionary param = new Dictionary(); + param["@ownerID"] = friendlistowner.UUID.ToString(); + param["@friendID"] = friend.UUID.ToString(); + param["@friendPerms"] = perms.ToString(); + + + try + { + lock (database) + { + IDbCommand updater = + database.Query( + "update " + m_userFriendsTableName + + " SET friendPerms = @friendPerms " + + "where ownerID = @ownerID and friendID = @friendID", + param); + + updater.ExecuteNonQuery(); + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return; + } + } + + + public List GetUserFriendList(LLUUID friendlistowner) + { + List Lfli = new List(); + + Dictionary param = new Dictionary(); + param["@ownerID"] = friendlistowner.UUID.ToString(); + + try + { + lock (database) + { + //Left Join userfriends to itself + IDbCommand result = + database.Query( + "select a.ownerID,a.friendID,a.friendPerms,b.friendPerms as ownerperms from " + m_userFriendsTableName + " as a, " + m_userFriendsTableName + " as b" + + " where a.ownerID = @ownerID and b.ownerID = a.friendID and b.friendID = a.ownerID", + param); + IDataReader reader = result.ExecuteReader(); + + + while (reader.Read()) + { + FriendListItem fli = new FriendListItem(); + fli.FriendListOwner = new LLUUID((string)reader["ownerID"]); + fli.Friend = new LLUUID((string)reader["friendID"]); + fli.FriendPerms = (uint)Convert.ToInt32(reader["friendPerms"]); + + // This is not a real column in the database table, it's a joined column from the opposite record + fli.FriendListOwnerPerms = (uint)Convert.ToInt32(reader["ownerperms"]); + + Lfli.Add(fli); + } + reader.Close(); + result.Dispose(); + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return Lfli; + } + + return Lfli; + } + + #endregion + + public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid) + { + m_log.Info("[USER]: Stub UpdateUserCUrrentRegion called"); + } + + + + public List GeneratePickerResults(LLUUID queryID, string query) + { + List returnlist = new List(); + string[] querysplit; + querysplit = query.Split(' '); + if (querysplit.Length == 2) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["first"] = querysplit[0]; + param["second"] = querysplit[1]; + + IDbCommand result = + database.Query( + "SELECT UUID,username,lastname FROM " + m_usersTableName + " WHERE username = @first AND lastname = @second", + param); + IDataReader reader = result.ExecuteReader(); + + + while (reader.Read()) + { + Framework.AvatarPickerAvatar user = new Framework.AvatarPickerAvatar(); + user.AvatarID = new LLUUID((string)reader["UUID"]); + user.firstName = (string)reader["username"]; + user.lastName = (string)reader["lastname"]; + returnlist.Add(user); + } + reader.Close(); + result.Dispose(); + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return returnlist; + } + } + else if (querysplit.Length == 1) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["first"] = querysplit[0]; + + IDbCommand result = + database.Query( + "SELECT UUID,username,lastname FROM " + m_usersTableName + " WHERE username = @first OR lastname = @first", + param); + IDataReader reader = result.ExecuteReader(); + + + while (reader.Read()) + { + Framework.AvatarPickerAvatar user = new Framework.AvatarPickerAvatar(); + user.AvatarID = new LLUUID((string)reader["UUID"]); + user.firstName = (string)reader["username"]; + user.lastName = (string)reader["lastname"]; + returnlist.Add(user); + } + reader.Close(); + result.Dispose(); + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return returnlist; + } + } + return returnlist; + } + + // See IUserData + public UserProfileData GetUserByUUID(LLUUID uuid) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["uuid"] = uuid.ToString(); + + IDbCommand result = database.Query("SELECT * FROM " + m_usersTableName + " WHERE UUID = @uuid", param); + IDataReader reader = result.ExecuteReader(); + + UserProfileData row = database.readUserRow(reader); + + reader.Close(); + result.Dispose(); + + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Returns a user session searching by name + /// + /// The account name + /// The users session + public UserAgentData GetAgentByName(string name) + { + return GetAgentByName(name.Split(' ')[0], name.Split(' ')[1]); + } + + /// + /// Returns a user session by account name + /// + /// First part of the users account name + /// Second part of the users account name + /// The users session + public UserAgentData GetAgentByName(string user, string last) + { + UserProfileData profile = GetUserByName(user, last); + return GetAgentByUUID(profile.UUID); + } + + /// + /// Returns an agent session by account UUID + /// + /// The accounts UUID + /// The users session + public UserAgentData GetAgentByUUID(LLUUID uuid) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["uuid"] = uuid.ToString(); + + IDbCommand result = database.Query("SELECT * FROM " + m_agentsTableName + " WHERE UUID = @uuid", param); + IDataReader reader = result.ExecuteReader(); + + UserAgentData row = database.readAgentRow(reader); + + reader.Close(); + result.Dispose(); + + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + public void StoreWebLoginKey(LLUUID AgentID, LLUUID WebLoginKey) + { + UserProfileData user = GetUserByUUID(AgentID); + user.webLoginKey = WebLoginKey; + UpdateUserProfile(user); + + } + /// + /// Creates a new users profile + /// + /// The user profile to create + public void AddNewUserProfile(UserProfileData user) + { + try + { + lock (database) + { + InsertUserRow(user.UUID, user.username, user.surname, user.passwordHash, user.passwordSalt, + user.homeRegion, user.homeLocation.X, user.homeLocation.Y, + user.homeLocation.Z, + user.homeLookAt.X, user.homeLookAt.Y, user.homeLookAt.Z, user.created, + user.lastLogin, user.userInventoryURI, user.userAssetURI, + user.profileCanDoMask, user.profileWantDoMask, + user.profileAboutText, user.profileFirstText, user.profileImage, + user.profileFirstImage, user.webLoginKey); + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + } + } + + /// + /// Creates a new user and inserts it into the database + /// + /// User ID + /// First part of the login + /// Second part of the login + /// A salted hash of the users password + /// The salt used for the password hash + /// A regionHandle of the users home region + /// Home region position vector + /// Home region position vector + /// Home region position vector + /// Home region 'look at' vector + /// Home region 'look at' vector + /// Home region 'look at' vector + /// Account created (unix timestamp) + /// Last login (unix timestamp) + /// Users inventory URI + /// Users asset URI + /// I can do mask + /// I want to do mask + /// Profile text + /// Firstlife text + /// UUID for profile image + /// UUID for firstlife image + /// Success? + private bool InsertUserRow(LLUUID uuid, string username, string lastname, string passwordHash, + string passwordSalt, UInt64 homeRegion, float homeLocX, float homeLocY, float homeLocZ, + float homeLookAtX, float homeLookAtY, float homeLookAtZ, int created, int lastlogin, + string inventoryURI, string assetURI, uint canDoMask, uint wantDoMask, + string aboutText, string firstText, + LLUUID profileImage, LLUUID firstImage, LLUUID webLoginKey) + { + string sql = "INSERT INTO "+m_usersTableName; + sql += " ([UUID], [username], [lastname], [passwordHash], [passwordSalt], [homeRegion], "; + sql += + "[homeLocationX], [homeLocationY], [homeLocationZ], [homeLookAtX], [homeLookAtY], [homeLookAtZ], [created], "; + sql += + "[lastLogin], [userInventoryURI], [userAssetURI], [profileCanDoMask], [profileWantDoMask], [profileAboutText], "; + sql += "[profileFirstText], [profileImage], [profileFirstImage], [webLoginKey]) VALUES "; + + sql += "(@UUID, @username, @lastname, @passwordHash, @passwordSalt, @homeRegion, "; + sql += + "@homeLocationX, @homeLocationY, @homeLocationZ, @homeLookAtX, @homeLookAtY, @homeLookAtZ, @created, "; + sql += + "@lastLogin, @userInventoryURI, @userAssetURI, @profileCanDoMask, @profileWantDoMask, @profileAboutText, "; + sql += "@profileFirstText, @profileImage, @profileFirstImage, @webLoginKey);"; + + Dictionary parameters = new Dictionary(); + parameters["UUID"] = uuid.ToString(); + parameters["username"] = username.ToString(); + parameters["lastname"] = lastname.ToString(); + parameters["passwordHash"] = passwordHash.ToString(); + parameters["passwordSalt"] = passwordSalt.ToString(); + parameters["homeRegion"] = homeRegion.ToString(); + parameters["homeLocationX"] = homeLocX.ToString(); + parameters["homeLocationY"] = homeLocY.ToString(); + parameters["homeLocationZ"] = homeLocZ.ToString(); + parameters["homeLookAtX"] = homeLookAtX.ToString(); + parameters["homeLookAtY"] = homeLookAtY.ToString(); + parameters["homeLookAtZ"] = homeLookAtZ.ToString(); + parameters["created"] = created.ToString(); + parameters["lastLogin"] = lastlogin.ToString(); + parameters["userInventoryURI"] = String.Empty; + parameters["userAssetURI"] = String.Empty; + parameters["profileCanDoMask"] = "0"; + parameters["profileWantDoMask"] = "0"; + parameters["profileAboutText"] = String.Empty; + parameters["profileFirstText"] = String.Empty; + parameters["profileImage"] = LLUUID.Zero.ToString(); + parameters["profileFirstImage"] = LLUUID.Zero.ToString(); + parameters["webLoginKey"] = LLUUID.Random().ToString(); + + bool returnval = false; + + try + { + IDbCommand result = database.Query(sql, parameters); + + if (result.ExecuteNonQuery() == 1) + returnval = true; + + result.Dispose(); + } + catch (Exception e) + { + m_log.Error(e.ToString()); + return false; + } + + return returnval; + } + + /// + /// Creates a new agent + /// + /// The agent to create + public void AddNewUserAgent(UserAgentData agent) + { + // Do nothing. + } + + + public bool UpdateUserProfile(UserProfileData user) + { + SqlCommand command = new SqlCommand("UPDATE " + m_usersTableName + " set UUID = @uuid, " + + "username = @username, " + + "lastname = @lastname," + + "passwordHash = @passwordHash," + + "passwordSalt = @passwordSalt," + + "homeRegion = @homeRegion," + + "homeLocationX = @homeLocationX," + + "homeLocationY = @homeLocationY," + + "homeLocationZ = @homeLocationZ," + + "homeLookAtX = @homeLookAtX," + + "homeLookAtY = @homeLookAtY," + + "homeLookAtZ = @homeLookAtZ," + + "created = @created," + + "lastLogin = @lastLogin," + + "userInventoryURI = @userInventoryURI," + + "userAssetURI = @userAssetURI," + + "profileCanDoMask = @profileCanDoMask," + + "profileWantDoMask = @profileWantDoMask," + + "profileAboutText = @profileAboutText," + + "profileFirstText = @profileFirstText," + + "profileImage = @profileImage," + + "profileFirstImage = @profileFirstImage, " + + "webLoginKey = @webLoginKey where " + + "UUID = @keyUUUID;", database.getConnection()); + SqlParameter param1 = new SqlParameter("@uuid", user.UUID.ToString()); + SqlParameter param2 = new SqlParameter("@username", user.username); + SqlParameter param3 = new SqlParameter("@lastname", user.surname); + SqlParameter param4 = new SqlParameter("@passwordHash", user.passwordHash); + SqlParameter param5 = new SqlParameter("@passwordSalt", user.passwordSalt); + SqlParameter param6 = new SqlParameter("@homeRegion", Convert.ToInt64(user.homeRegion)); + SqlParameter param7 = new SqlParameter("@homeLocationX", user.homeLocation.X); + SqlParameter param8 = new SqlParameter("@homeLocationY", user.homeLocation.Y); + SqlParameter param9 = new SqlParameter("@homeLocationZ", user.homeLocation.Y); + SqlParameter param10 = new SqlParameter("@homeLookAtX", user.homeLookAt.X); + SqlParameter param11 = new SqlParameter("@homeLookAtY", user.homeLookAt.Y); + SqlParameter param12 = new SqlParameter("@homeLookAtZ", user.homeLookAt.Z); + SqlParameter param13 = new SqlParameter("@created", Convert.ToInt32(user.created)); + SqlParameter param14 = new SqlParameter("@lastLogin", Convert.ToInt32(user.lastLogin)); + SqlParameter param15 = new SqlParameter("@userInventoryURI", user.userInventoryURI); + SqlParameter param16 = new SqlParameter("@userAssetURI", user.userAssetURI); + SqlParameter param17 = new SqlParameter("@profileCanDoMask", Convert.ToInt32(user.profileCanDoMask)); + SqlParameter param18 = new SqlParameter("@profileWantDoMask", Convert.ToInt32(user.profileWantDoMask)); + SqlParameter param19 = new SqlParameter("@profileAboutText", user.profileAboutText); + SqlParameter param20 = new SqlParameter("@profileFirstText", user.profileFirstText); + SqlParameter param21 = new SqlParameter("@profileImage", LLUUID.Zero.ToString()); + SqlParameter param22 = new SqlParameter("@profileFirstImage", LLUUID.Zero.ToString()); + SqlParameter param23 = new SqlParameter("@keyUUUID", user.UUID.ToString()); + SqlParameter param24 = new SqlParameter("@webLoginKey", user.webLoginKey.UUID.ToString()); + command.Parameters.Add(param1); + command.Parameters.Add(param2); + command.Parameters.Add(param3); + command.Parameters.Add(param4); + command.Parameters.Add(param5); + command.Parameters.Add(param6); + command.Parameters.Add(param7); + command.Parameters.Add(param8); + command.Parameters.Add(param9); + command.Parameters.Add(param10); + command.Parameters.Add(param11); + command.Parameters.Add(param12); + command.Parameters.Add(param13); + command.Parameters.Add(param14); + command.Parameters.Add(param15); + command.Parameters.Add(param16); + command.Parameters.Add(param17); + command.Parameters.Add(param18); + command.Parameters.Add(param19); + command.Parameters.Add(param20); + command.Parameters.Add(param21); + command.Parameters.Add(param22); + command.Parameters.Add(param23); + command.Parameters.Add(param24); + try + { + int affected = command.ExecuteNonQuery(); + if (affected != 0) + { + return true; + } + else + { + return false; + } + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + return false; + } + + /// + /// Performs a money transfer request between two accounts + /// + /// The senders account ID + /// The receivers account ID + /// The amount to transfer + /// Success? + public bool MoneyTransferRequest(LLUUID from, LLUUID to, uint amount) + { + return false; + } + + /// + /// Performs an inventory transfer request between two accounts + /// + /// TODO: Move to inventory server + /// The senders account ID + /// The receivers account ID + /// The item to transfer + /// Success? + public bool InventoryTransferRequest(LLUUID from, LLUUID to, LLUUID item) + { + return false; + } + + /// + /// Database provider name + /// + /// Provider name + public string getName() + { + return "MSSQL Userdata Interface"; + } + + /// + /// Database provider version + /// + /// provider version + public string GetVersion() + { + return database.getVersion(); + } + + /// + /// Not implemented + /// + /// + public void runQuery(string query) + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MSSQL/Properties/AssemblyInfo.cs b/trunk/OpenSim/Framework/Data.MSSQL/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..a91ce62ea4 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* 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.Framework.Data.MSSQL")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Framework.Data.MSSQL")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("0e1c1ca4-2cf2-4315-b0e7-432c02feea8a")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateAssetsTable.sql b/trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateAssetsTable.sql new file mode 100644 index 0000000000..c7cb21adf5 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateAssetsTable.sql @@ -0,0 +1,19 @@ +SET ANSI_NULLS ON +SET QUOTED_IDENTIFIER ON +SET ANSI_PADDING ON +CREATE TABLE [assets] ( + [id] [varchar](36) NOT NULL, + [name] [varchar](64) NOT NULL, + [description] [varchar](64) NOT NULL, + [assetType] [tinyint] NOT NULL, + [invType] [tinyint] NOT NULL, + [local] [tinyint] NOT NULL, + [temporary] [tinyint] NOT NULL, + [data] [image] NOT NULL, +PRIMARY KEY CLUSTERED +( + [id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] + +SET ANSI_PADDING OFF diff --git a/trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateFoldersTable.sql b/trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateFoldersTable.sql new file mode 100644 index 0000000000..95d183ad99 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateFoldersTable.sql @@ -0,0 +1,27 @@ +SET ANSI_NULLS ON +SET QUOTED_IDENTIFIER ON +SET ANSI_PADDING ON +CREATE TABLE [inventoryfolders] ( + [folderID] [varchar](36) NOT NULL default '', + [agentID] [varchar](36) default NULL, + [parentFolderID] [varchar](36) default NULL, + [folderName] [varchar](64) default NULL, + [type] [smallint] NOT NULL default 0, + [version] [int] NOT NULL default 0, + PRIMARY KEY CLUSTERED +( + [folderID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] + +CREATE NONCLUSTERED INDEX [owner] ON [inventoryfolders] +( + [agentID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + +CREATE NONCLUSTERED INDEX [parent] ON [inventoryfolders] +( + [parentFolderID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + +SET ANSI_PADDING OFF diff --git a/trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateItemsTable.sql b/trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateItemsTable.sql new file mode 100644 index 0000000000..40c047ea37 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateItemsTable.sql @@ -0,0 +1,39 @@ +SET ANSI_NULLS ON + +SET QUOTED_IDENTIFIER ON + +SET ANSI_PADDING ON + +CREATE TABLE [inventoryitems] ( + [inventoryID] [varchar](36) NOT NULL default '', + [assetID] [varchar](36) default NULL, + [assetType] [int] default NULL, + [parentFolderID] [varchar](36) default NULL, + [avatarID] [varchar](36) default NULL, + [inventoryName] [varchar](64) default NULL, + [inventoryDescription] [varchar](64) default NULL, + [inventoryNextPermissions] [int] default NULL, + [inventoryCurrentPermissions] [int] default NULL, + [invType] [int] default NULL, + [creatorID] [varchar](36) default NULL, + [inventoryBasePermissions] [int] NOT NULL default 0, + [inventoryEveryOnePermissions] [int] NOT NULL default 0, + PRIMARY KEY CLUSTERED +( + [inventoryID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] + + +CREATE NONCLUSTERED INDEX [owner] ON [inventoryitems] +( + [avatarID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + +CREATE NONCLUSTERED INDEX [folder] ON [inventoryitems] +( + [parentFolderID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + +SET ANSI_PADDING OFF + diff --git a/trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateUserFriendsTable.sql b/trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateUserFriendsTable.sql new file mode 100644 index 0000000000..6f5885ef2c --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/Resources/CreateUserFriendsTable.sql @@ -0,0 +1,14 @@ +SET ANSI_NULLS ON + +SET QUOTED_IDENTIFIER ON + +SET ANSI_PADDING ON + +CREATE TABLE [dbo].[userfriends]( +[ownerID] [varchar](50) COLLATE Latin1_General_CI_AS NOT NULL, +[friendID] [varchar](50) COLLATE Latin1_General_CI_AS NOT NULL, +[friendPerms] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, +[datetimestamp] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL +) ON [PRIMARY] + +SET ANSI_PADDING OFF diff --git a/trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-agents.sql b/trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-agents.sql new file mode 100644 index 0000000000..ad531735fc --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-agents.sql @@ -0,0 +1,37 @@ +SET ANSI_NULLS ON + +SET QUOTED_IDENTIFIER ON + +SET ANSI_PADDING ON + +CREATE TABLE [agents] ( + [UUID] [varchar](36) NOT NULL, + [sessionID] [varchar](36) NOT NULL, + [secureSessionID] [varchar](36) NOT NULL, + [agentIP] [varchar](16) NOT NULL, + [agentPort] [int] NOT NULL, + [agentOnline] [tinyint] NOT NULL, + [loginTime] [int] NOT NULL, + [logoutTime] [int] NOT NULL, + [currentRegion] [varchar](36) NOT NULL, + [currentHandle] [bigint] NOT NULL, + [currentPos] [varchar](64) NOT NULL, + PRIMARY KEY CLUSTERED +( + [UUID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] + + +CREATE NONCLUSTERED INDEX [session] ON [agents] +( + [sessionID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + +CREATE NONCLUSTERED INDEX [ssession] ON [agents] +( + [secureSessionID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + +SET ANSI_PADDING OFF + diff --git a/trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-logs.sql b/trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-logs.sql new file mode 100644 index 0000000000..3b747d8a0d --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-logs.sql @@ -0,0 +1,20 @@ +SET ANSI_NULLS ON + +SET QUOTED_IDENTIFIER ON + +SET ANSI_PADDING ON + +CREATE TABLE [logs] ( + [logID] [int] NOT NULL, + [target] [varchar](36) default NULL, + [server] [varchar](64) default NULL, + [method] [varchar](64) default NULL, + [arguments] [varchar](255) default NULL, + [priority] [int] default NULL, + [message] [ntext], + PRIMARY KEY CLUSTERED +( + [logID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] + diff --git a/trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-regions.sql b/trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-regions.sql new file mode 100644 index 0000000000..c5d8329cf4 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-regions.sql @@ -0,0 +1,40 @@ +SET ANSI_NULLS ON + +SET QUOTED_IDENTIFIER ON + +SET ANSI_PADDING ON + +CREATE TABLE [dbo].[regions]( + [regionHandle] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [regionName] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [uuid] [varchar](255) COLLATE Latin1_General_CI_AS NOT NULL, + [regionRecvKey] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [regionSecret] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [regionSendKey] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [regionDataURI] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [serverIP] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [serverPort] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [serverURI] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [locX] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [locY] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [locZ] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [eastOverrideHandle] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [westOverrideHandle] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [southOverrideHandle] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [northOverrideHandle] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [regionAssetURI] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [regionAssetRecvKey] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [regionAssetSendKey] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [regionUserURI] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [regionUserRecvKey] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [regionUserSendKey] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [regionMapTexture] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [serverHttpPort] [varchar](255) COLLATE Latin1_General_CI_AS NULL, + [serverRemotingPort] [varchar](255) COLLATE Latin1_General_CI_AS NULL, +PRIMARY KEY CLUSTERED +( + [uuid] ASC +)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY] +) ON [PRIMARY] + +SET ANSI_PADDING OFF diff --git a/trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-users.sql b/trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-users.sql new file mode 100644 index 0000000000..abcc091835 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MSSQL/Resources/Mssql-users.sql @@ -0,0 +1,42 @@ +SET ANSI_NULLS ON + +SET QUOTED_IDENTIFIER ON + +SET ANSI_PADDING ON + +CREATE TABLE [users] ( + [UUID] [varchar](36) NOT NULL default '', + [username] [varchar](32) NOT NULL, + [lastname] [varchar](32) NOT NULL, + [passwordHash] [varchar](32) NOT NULL, + [passwordSalt] [varchar](32) NOT NULL, + [homeRegion] [bigint] default NULL, + [homeLocationX] [float] default NULL, + [homeLocationY] [float] default NULL, + [homeLocationZ] [float] default NULL, + [homeLookAtX] [float] default NULL, + [homeLookAtY] [float] default NULL, + [homeLookAtZ] [float] default NULL, + [created] [int] NOT NULL, + [lastLogin] [int] NOT NULL, + [userInventoryURI] [varchar](255) default NULL, + [userAssetURI] [varchar](255) default NULL, + [profileCanDoMask] [int] default NULL, + [profileWantDoMask] [int] default NULL, + [profileAboutText] [ntext], + [profileFirstText] [ntext], + [profileImage] [varchar](36) default NULL, + [profileFirstImage] [varchar](36) default NULL, + [webLoginKey] [varchar](36) default NULL, + PRIMARY KEY CLUSTERED +( + [UUID] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] + + +CREATE NONCLUSTERED INDEX [usernames] ON [users] +( + [username] ASC, + [lastname] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] diff --git a/trunk/OpenSim/Framework/Data.MySQL/MySQLAssetData.cs b/trunk/OpenSim/Framework/Data.MySQL/MySQLAssetData.cs new file mode 100644 index 0000000000..0dfe6711cf --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/MySQLAssetData.cs @@ -0,0 +1,199 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using libsecondlife; +using MySql.Data.MySqlClient; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.MySQL +{ + internal class MySQLAssetData : IAssetProvider + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private MySQLManager _dbConnection; + + #region IAssetProvider Members + + private void UpgradeAssetsTable(string oldVersion) + { + // null as the version, indicates that the table didn't exist + if (oldVersion == null) + { + m_log.Info("[ASSETS]: Creating new database tables"); + _dbConnection.ExecuteResourceSql("CreateAssetsTable.sql"); + return; + } + } + + /// + /// Ensure that the assets related tables exists and are at the latest version + /// + private void TestTables() + { + Dictionary tableList = new Dictionary(); + + tableList["assets"] = null; + _dbConnection.GetTableVersion(tableList); + + UpgradeAssetsTable(tableList["assets"]); + } + + public AssetBase FetchAsset(LLUUID assetID) + { + AssetBase asset = null; + lock (_dbConnection) + { + MySqlCommand cmd = + new MySqlCommand( + "SELECT name, description, assetType, invType, local, temporary, data FROM assets WHERE id=?id", + _dbConnection.Connection); + MySqlParameter p = cmd.Parameters.Add("?id", MySqlDbType.Binary, 16); + p.Value = assetID.GetBytes(); + + try + { + using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) + { + if (dbReader.Read()) + { + asset = new AssetBase(); + asset.Data = (byte[]) dbReader["data"]; + asset.Description = (string) dbReader["description"]; + asset.FullID = assetID; + asset.InvType = (sbyte) dbReader["invType"]; + asset.Local = ((sbyte) dbReader["local"]) != 0 ? true : false; + asset.Name = (string) dbReader["name"]; + asset.Type = (sbyte) dbReader["assetType"]; + } + dbReader.Close(); + cmd.Dispose(); + } + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ASSETS]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString() + + Environment.NewLine + "Attempting reconnection", assetID); + _dbConnection.Reconnect(); + } + } + return asset; + } + + public void CreateAsset(AssetBase asset) + { + lock (_dbConnection) + { + MySqlCommand cmd = + new MySqlCommand( + "REPLACE INTO assets(id, name, description, assetType, invType, local, temporary, data)" + + "VALUES(?id, ?name, ?description, ?assetType, ?invType, ?local, ?temporary, ?data)", + _dbConnection.Connection); + + // need to ensure we dispose + try + { + using (cmd) + { + MySqlParameter p = cmd.Parameters.Add("?id", MySqlDbType.Binary, 16); + p.Value = asset.FullID.GetBytes(); + cmd.Parameters.AddWithValue("?name", asset.Name); + cmd.Parameters.AddWithValue("?description", asset.Description); + cmd.Parameters.AddWithValue("?assetType", asset.Type); + cmd.Parameters.AddWithValue("?invType", asset.InvType); + cmd.Parameters.AddWithValue("?local", asset.Local); + cmd.Parameters.AddWithValue("?temporary", asset.Temporary); + cmd.Parameters.AddWithValue("?data", asset.Data); + cmd.ExecuteNonQuery(); + cmd.Dispose(); + } + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ASSETS]: " + + "MySql failure creating asset {0} with name {1}" + Environment.NewLine + e.ToString() + + Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name); + _dbConnection.Reconnect(); + } + } + } + + public void UpdateAsset(AssetBase asset) + { + CreateAsset(asset); + } + + public bool ExistsAsset(LLUUID uuid) + { + throw new Exception("The method or operation is not implemented."); + } + + /// + /// All writes are immediately commited to the database, so this is a no-op + /// + public void CommitAssets() + { + } + + #endregion + + #region IPlugin Members + + public void Initialise() + { + IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini"); + string hostname = GridDataMySqlFile.ParseFileReadValue("hostname"); + string database = GridDataMySqlFile.ParseFileReadValue("database"); + string username = GridDataMySqlFile.ParseFileReadValue("username"); + string password = GridDataMySqlFile.ParseFileReadValue("password"); + string pooling = GridDataMySqlFile.ParseFileReadValue("pooling"); + string port = GridDataMySqlFile.ParseFileReadValue("port"); + + _dbConnection = new MySQLManager(hostname, database, username, password, pooling, port); + + TestTables(); + } + + public string Version + { + get { return _dbConnection.getVersion(); } + } + + public string Name + { + get { return "MySQL Asset storage engine"; } + } + + #endregion + } +} diff --git a/trunk/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs b/trunk/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs new file mode 100644 index 0000000000..9518724f25 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs @@ -0,0 +1,1692 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.IO; +using libsecondlife; +using MySql.Data.MySqlClient; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.LandManagement; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Framework.Data.MySQL +{ + public class MySQLDataStore : IRegionDataStore + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private const string m_primSelect = "select * from prims"; + private const string m_shapeSelect = "select * from primshapes"; + private const string m_itemsSelect = "select * from primitems"; + private const string m_terrainSelect = "select * from terrain limit 1"; + private const string m_landSelect = "select * from land"; + private const string m_landAccessListSelect = "select * from landaccesslist"; + + private DataSet m_dataSet; + private MySqlDataAdapter m_primDataAdapter; + private MySqlDataAdapter m_shapeDataAdapter; + private MySqlDataAdapter m_itemsDataAdapter; + private MySqlConnection m_connection; + private MySqlDataAdapter m_terrainDataAdapter; + private MySqlDataAdapter m_landDataAdapter; + private MySqlDataAdapter m_landAccessListDataAdapter; + + private DataTable m_primTable; + private DataTable m_shapeTable; + private DataTable m_itemsTable; + private DataTable m_terrainTable; + private DataTable m_landTable; + private DataTable m_landAccessListTable; + + // Temporary attribute while this is experimental + private bool persistPrimInventories; + + /*********************************************************************** + * + * Public Interface Functions + * + **********************************************************************/ + + // see IRegionDataStore + public void Initialise(string connectionstring, bool persistPrimInventories) + { + m_dataSet = new DataSet(); + this.persistPrimInventories = persistPrimInventories; + + m_log.Info("[DATASTORE]: MySql - connecting: " + connectionstring); + m_connection = new MySqlConnection(connectionstring); + + MySqlCommand primSelectCmd = new MySqlCommand(m_primSelect, m_connection); + m_primDataAdapter = new MySqlDataAdapter(primSelectCmd); + + MySqlCommand shapeSelectCmd = new MySqlCommand(m_shapeSelect, m_connection); + m_shapeDataAdapter = new MySqlDataAdapter(shapeSelectCmd); + + MySqlCommand itemsSelectCmd = new MySqlCommand(m_itemsSelect, m_connection); + m_itemsDataAdapter = new MySqlDataAdapter(itemsSelectCmd); + + MySqlCommand terrainSelectCmd = new MySqlCommand(m_terrainSelect, m_connection); + m_terrainDataAdapter = new MySqlDataAdapter(terrainSelectCmd); + + MySqlCommand landSelectCmd = new MySqlCommand(m_landSelect, m_connection); + m_landDataAdapter = new MySqlDataAdapter(landSelectCmd); + + MySqlCommand landAccessListSelectCmd = new MySqlCommand(m_landAccessListSelect, m_connection); + m_landAccessListDataAdapter = new MySqlDataAdapter(landAccessListSelectCmd); + + TestTables(m_connection); + + lock (m_dataSet) + { + m_primTable = createPrimTable(); + m_dataSet.Tables.Add(m_primTable); + SetupPrimCommands(m_primDataAdapter, m_connection); + m_primDataAdapter.Fill(m_primTable); + + m_shapeTable = createShapeTable(); + m_dataSet.Tables.Add(m_shapeTable); + SetupShapeCommands(m_shapeDataAdapter, m_connection); + m_shapeDataAdapter.Fill(m_shapeTable); + + if (persistPrimInventories) + { + m_itemsTable = createItemsTable(); + m_dataSet.Tables.Add(m_itemsTable); + SetupItemsCommands(m_itemsDataAdapter, m_connection); + m_itemsDataAdapter.Fill(m_itemsTable); + } + + m_terrainTable = createTerrainTable(); + m_dataSet.Tables.Add(m_terrainTable); + SetupTerrainCommands(m_terrainDataAdapter, m_connection); + m_terrainDataAdapter.Fill(m_terrainTable); + + m_landTable = createLandTable(); + m_dataSet.Tables.Add(m_landTable); + setupLandCommands(m_landDataAdapter, m_connection); + m_landDataAdapter.Fill(m_landTable); + + m_landAccessListTable = createLandAccessListTable(); + m_dataSet.Tables.Add(m_landAccessListTable); + setupLandAccessCommands(m_landAccessListDataAdapter, m_connection); + m_landAccessListDataAdapter.Fill(m_landAccessListTable); + } + } + + public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID) + { + lock (m_dataSet) + { + foreach (SceneObjectPart prim in obj.Children.Values) + { + if ((prim.ObjectFlags & (uint) LLObject.ObjectFlags.Physics) == 0) + { + m_log.Info("[DATASTORE]: Adding obj: " + obj.UUID + " to region: " + regionUUID); + addPrim(prim, obj.UUID, regionUUID); + } + else + { + // m_log.Info("[DATASTORE]: Ignoring Physical obj: " + obj.UUID + " in region: " + regionUUID); + } + } + } + + Commit(); + } + + public void RemoveObject(LLUUID obj, LLUUID regionUUID) + { + m_log.InfoFormat("[DATASTORE]: Removing obj: {0} from region: {1}", obj.UUID, regionUUID); + + DataTable prims = m_primTable; + DataTable shapes = m_shapeTable; + + string selectExp = "SceneGroupID = '" + Util.ToRawUuidString(obj) + "'"; + lock (m_dataSet) + { + DataRow[] primRows = prims.Select(selectExp); + foreach (DataRow row in primRows) + { + // Remove shapes row + LLUUID uuid = new LLUUID((string) row["UUID"]); + DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(uuid)); + if (shapeRow != null) + { + shapeRow.Delete(); + } + + if (persistPrimInventories) + { + RemoveItems(uuid); + } + + // Remove prim row + row.Delete(); + } + } + + Commit(); + } + + /// + /// Remove all persisted items of the given prim. + /// The caller must acquire the necessrary synchronization locks and commit or rollback changes. + /// + private void RemoveItems(LLUUID uuid) + { + String sql = String.Format("primID = '{0}'", uuid); + DataRow[] itemRows = m_itemsTable.Select(sql); + + foreach (DataRow itemRow in itemRows) + { + itemRow.Delete(); + } + } + + /// + /// Load persisted objects from region storage. + /// + public List LoadObjects(LLUUID regionUUID) + { + Dictionary createdObjects = new Dictionary(); + + List retvals = new List(); + + DataTable prims = m_primTable; + DataTable shapes = m_shapeTable; + + string byRegion = "RegionUUID = '" + Util.ToRawUuidString(regionUUID) + "'"; + string orderByParent = "ParentID ASC"; + + lock (m_dataSet) + { + DataRow[] primsForRegion = prims.Select(byRegion, orderByParent); + m_log.Info("[DATASTORE]: " + + "Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); + + foreach (DataRow primRow in primsForRegion) + { + try + { + string uuid = (string) primRow["UUID"]; + string objID = (string) primRow["SceneGroupID"]; + + SceneObjectPart prim = buildPrim(primRow); + + if (uuid == objID) //is new SceneObjectGroup ? + { + SceneObjectGroup group = new SceneObjectGroup(); + + DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID)); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Info( + "No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + group.AddPart(prim); + group.RootPart = prim; + + createdObjects.Add(group.UUID, group); + retvals.Add(group); + } + else + { + DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID)); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Info( + "No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + createdObjects[new LLUUID(objID)].AddPart(prim); + } + + if (persistPrimInventories) + { + LoadItems(prim); + } + } + catch (Exception e) + { + m_log.Error("[DATASTORE]: Failed create prim object, exception and data follows"); + m_log.Info("[DATASTORE]: " + e.ToString()); + foreach (DataColumn col in prims.Columns) + { + m_log.Info("[DATASTORE]: Col: " + col.ColumnName + " => " + primRow[col]); + } + } + } + } + return retvals; + } + + /// + /// Load in a prim's persisted inventory. + /// + /// + private void LoadItems(SceneObjectPart prim) + { + //m_log.InfoFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID); + + DataTable dbItems = m_itemsTable; + + String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); + DataRow[] dbItemRows = dbItems.Select(sql); + + IList inventory = new List(); + + foreach (DataRow row in dbItemRows) + { + TaskInventoryItem item = buildItem(row); + inventory.Add(item); + + m_log.InfoFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID); + } + + prim.RestoreInventoryItems(inventory); + + // XXX A nasty little hack to recover the folder id for the prim (which is currently stored in + // every item). This data should really be stored in the prim table itself. + if (dbItemRows.Length > 0) + { + prim.FolderID = inventory[0].ParentID; + } + } + + public void StoreTerrain(double[,] ter, LLUUID regionID) + { + int revision = Util.UnixTimeSinceEpoch(); + m_log.Info("[DATASTORE]: Storing terrain revision r" + revision.ToString()); + + DataTable terrain = m_dataSet.Tables["terrain"]; + lock (m_dataSet) + { + MySqlCommand cmd = new MySqlCommand("insert into terrain(RegionUUID, Revision, Heightfield)" + + " values(?RegionUUID, ?Revision, ?Heightfield)", m_connection); + using (cmd) + { + cmd.Parameters.Add(new MySqlParameter("?RegionUUID", Util.ToRawUuidString(regionID))); + cmd.Parameters.Add(new MySqlParameter("?Revision", revision)); + cmd.Parameters.Add(new MySqlParameter("?Heightfield", serializeTerrain(ter))); + cmd.ExecuteNonQuery(); + } + } + } + + public double[,] LoadTerrain(LLUUID regionID) + { + double[,] terret = new double[256,256]; + terret.Initialize(); + + MySqlCommand cmd = new MySqlCommand( + @"select RegionUUID, Revision, Heightfield from terrain + where RegionUUID=?RegionUUID order by Revision desc limit 1" + , m_connection); + + MySqlParameter param = new MySqlParameter(); + cmd.Parameters.Add(new MySqlParameter("?RegionUUID", Util.ToRawUuidString(regionID))); + + if (m_connection.State != ConnectionState.Open) + { + m_connection.Open(); + } + + using (MySqlDataReader row = cmd.ExecuteReader()) + { + int rev = 0; + if (row.Read()) + { + MemoryStream str = new MemoryStream((byte[]) row["Heightfield"]); + BinaryReader br = new BinaryReader(str); + for (int x = 0; x < 256; x++) + { + for (int y = 0; y < 256; y++) + { + terret[x, y] = br.ReadDouble(); + } + } + rev = (int) row["Revision"]; + } + else + { + m_log.Info("[DATASTORE]: No terrain found for region"); + return null; + } + + m_log.Info("[DATASTORE]: Loaded terrain revision r" + rev.ToString()); + } + + return terret; + } + + public void RemoveLandObject(LLUUID globalID) + { + lock (m_dataSet) + { + using (MySqlCommand cmd = new MySqlCommand("delete from land where UUID=?UUID", m_connection)) + { + cmd.Parameters.Add(new MySqlParameter("?UUID", Util.ToRawUuidString(globalID))); + cmd.ExecuteNonQuery(); + } + + using ( + MySqlCommand cmd = new MySqlCommand("delete from landaccesslist where LandUUID=?UUID", m_connection) + ) + { + cmd.Parameters.Add(new MySqlParameter("?UUID", Util.ToRawUuidString(globalID))); + cmd.ExecuteNonQuery(); + } + } + } + + static Random rnd = new Random(); + public void StoreLandObject(Land parcel, LLUUID regionUUID) + { + // Does the new locking fix it? + m_log.Info("[DATASTORE]: Tedds temp fix: Waiting 3 seconds for stuff to catch up. (Someone please fix! :))"); + System.Threading.Thread.Sleep(2500 + rnd.Next(300, 900)); + + lock (m_dataSet) + { + DataTable land = m_landTable; + DataTable landaccesslist = m_landAccessListTable; + + DataRow landRow = land.Rows.Find(Util.ToRawUuidString(parcel.landData.globalID)); + if (landRow == null) + { + landRow = land.NewRow(); + fillLandRow(landRow, parcel.landData, regionUUID); + land.Rows.Add(landRow); + } + else + { + fillLandRow(landRow, parcel.landData, regionUUID); + } + + using ( + MySqlCommand cmd = + new MySqlCommand("delete from landaccesslist where LandUUID=?LandUUID", m_connection)) + { + cmd.Parameters.Add(new MySqlParameter("?LandUUID", Util.ToRawUuidString(parcel.landData.globalID))); + cmd.ExecuteNonQuery(); + } + + foreach (ParcelManager.ParcelAccessEntry entry in parcel.landData.parcelAccessList) + { + DataRow newAccessRow = landaccesslist.NewRow(); + fillLandAccessRow(newAccessRow, entry, parcel.landData.globalID); + landaccesslist.Rows.Add(newAccessRow); + } + + } + Commit(); + } + + public List LoadLandObjects(LLUUID regionUUID) + { + List landDataForRegion = new List(); + lock (m_dataSet) + { + DataTable land = m_landTable; + DataTable landaccesslist = m_landAccessListTable; + string searchExp = "RegionUUID = '" + Util.ToRawUuidString(regionUUID) + "'"; + DataRow[] rawDataForRegion = land.Select(searchExp); + foreach (DataRow rawDataLand in rawDataForRegion) + { + LandData newLand = buildLandData(rawDataLand); + string accessListSearchExp = "LandUUID = '" + Util.ToRawUuidString(newLand.globalID) + "'"; + DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp); + foreach (DataRow rawDataLandAccess in rawDataForLandAccessList) + { + newLand.parcelAccessList.Add(buildLandAccessData(rawDataLandAccess)); + } + + landDataForRegion.Add(newLand); + } + } + return landDataForRegion; + } + + private void DisplayDataSet(DataSet ds, string title) + { + Debug.WriteLine(title); + //--- Loop through the DataTables + foreach (DataTable table in ds.Tables) + { + Debug.WriteLine("*** DataTable: " + table.TableName + "***"); + //--- Loop through each DataTable's DataRows + foreach (DataRow row in table.Rows) + { + //--- Display the original values, if there are any. + if (row.HasVersion(DataRowVersion.Original)) + { + Debug.Write("Original Row Values ===> "); + foreach (DataColumn column in table.Columns) + Debug.Write(column.ColumnName + " = " + + row[column, DataRowVersion.Original] + ", "); + Debug.WriteLine(String.Empty); + } + //--- Display the current values, if there are any. + if (row.HasVersion(DataRowVersion.Current)) + { + Debug.Write("Current Row Values ====> "); + foreach (DataColumn column in table.Columns) + Debug.Write(column.ColumnName + " = " + + row[column, DataRowVersion.Current] + ", "); + Debug.WriteLine(String.Empty); + } + Debug.WriteLine(String.Empty); + } + } + } + + public void Commit() + { + if (m_connection.State != ConnectionState.Open) + { + m_connection.Open(); + } + + lock (m_dataSet) + { + // DisplayDataSet(m_dataSet, "Region DataSet"); + + m_primDataAdapter.Update(m_primTable); + m_shapeDataAdapter.Update(m_shapeTable); + + if (persistPrimInventories) + { + m_itemsDataAdapter.Update(m_itemsTable); + } + + m_terrainDataAdapter.Update(m_terrainTable); + m_landDataAdapter.Update(m_landTable); + m_landAccessListDataAdapter.Update(m_landAccessListTable); + + m_dataSet.AcceptChanges(); + } + } + + + public void Shutdown() + { + Commit(); + } + + /*********************************************************************** + * + * Database Definition Functions + * + * This should be db agnostic as we define them in ADO.NET terms + * + **********************************************************************/ + + private DataColumn createCol(DataTable dt, string name, Type type) + { + DataColumn col = new DataColumn(name, type); + dt.Columns.Add(col); + return col; + } + + private DataTable createTerrainTable() + { + DataTable terrain = new DataTable("terrain"); + + createCol(terrain, "RegionUUID", typeof (String)); + createCol(terrain, "Revision", typeof (Int32)); + DataColumn heightField = createCol(terrain, "Heightfield", typeof (Byte[])); + return terrain; + } + + private DataTable createPrimTable() + { + DataTable prims = new DataTable("prims"); + + createCol(prims, "UUID", typeof (String)); + createCol(prims, "RegionUUID", typeof (String)); + createCol(prims, "ParentID", typeof (Int32)); + createCol(prims, "CreationDate", typeof (Int32)); + createCol(prims, "Name", typeof (String)); + createCol(prims, "SceneGroupID", typeof (String)); + // various text fields + createCol(prims, "Text", typeof (String)); + createCol(prims, "Description", typeof (String)); + createCol(prims, "SitName", typeof (String)); + createCol(prims, "TouchName", typeof (String)); + // permissions + createCol(prims, "ObjectFlags", typeof (Int32)); + createCol(prims, "CreatorID", typeof (String)); + createCol(prims, "OwnerID", typeof (String)); + createCol(prims, "GroupID", typeof (String)); + createCol(prims, "LastOwnerID", typeof (String)); + createCol(prims, "OwnerMask", typeof (Int32)); + createCol(prims, "NextOwnerMask", typeof (Int32)); + createCol(prims, "GroupMask", typeof (Int32)); + createCol(prims, "EveryoneMask", typeof (Int32)); + createCol(prims, "BaseMask", typeof (Int32)); + // vectors + createCol(prims, "PositionX", typeof (Double)); + createCol(prims, "PositionY", typeof (Double)); + createCol(prims, "PositionZ", typeof (Double)); + createCol(prims, "GroupPositionX", typeof (Double)); + createCol(prims, "GroupPositionY", typeof (Double)); + createCol(prims, "GroupPositionZ", typeof (Double)); + createCol(prims, "VelocityX", typeof (Double)); + createCol(prims, "VelocityY", typeof (Double)); + createCol(prims, "VelocityZ", typeof (Double)); + createCol(prims, "AngularVelocityX", typeof (Double)); + createCol(prims, "AngularVelocityY", typeof (Double)); + createCol(prims, "AngularVelocityZ", typeof (Double)); + createCol(prims, "AccelerationX", typeof (Double)); + createCol(prims, "AccelerationY", typeof (Double)); + createCol(prims, "AccelerationZ", typeof (Double)); + // quaternions + createCol(prims, "RotationX", typeof (Double)); + createCol(prims, "RotationY", typeof (Double)); + createCol(prims, "RotationZ", typeof (Double)); + createCol(prims, "RotationW", typeof (Double)); + // sit target + createCol(prims, "SitTargetOffsetX", typeof (Double)); + createCol(prims, "SitTargetOffsetY", typeof (Double)); + createCol(prims, "SitTargetOffsetZ", typeof (Double)); + + createCol(prims, "SitTargetOrientW", typeof (Double)); + createCol(prims, "SitTargetOrientX", typeof (Double)); + createCol(prims, "SitTargetOrientY", typeof (Double)); + createCol(prims, "SitTargetOrientZ", typeof (Double)); + + + // Add in contraints + prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]}; + + return prims; + } + + private DataTable createLandTable() + { + DataTable land = new DataTable("land"); + createCol(land, "UUID", typeof (String)); + createCol(land, "RegionUUID", typeof (String)); + createCol(land, "LocalLandID", typeof (Int32)); + + // Bitmap is a byte[512] + createCol(land, "Bitmap", typeof (Byte[])); + + createCol(land, "Name", typeof (String)); + createCol(land, "Description", typeof (String)); + createCol(land, "OwnerUUID", typeof (String)); + createCol(land, "IsGroupOwned", typeof (Int32)); + createCol(land, "Area", typeof (Int32)); + createCol(land, "AuctionID", typeof (Int32)); //Unemplemented + createCol(land, "Category", typeof (Int32)); //Enum libsecondlife.Parcel.ParcelCategory + createCol(land, "ClaimDate", typeof (Int32)); + createCol(land, "ClaimPrice", typeof (Int32)); + createCol(land, "GroupUUID", typeof (String)); + createCol(land, "SalePrice", typeof (Int32)); + createCol(land, "LandStatus", typeof (Int32)); //Enum. libsecondlife.Parcel.ParcelStatus + createCol(land, "LandFlags", typeof (Int32)); + createCol(land, "LandingType", typeof (Int32)); + createCol(land, "MediaAutoScale", typeof (Int32)); + createCol(land, "MediaTextureUUID", typeof (String)); + createCol(land, "MediaURL", typeof (String)); + createCol(land, "MusicURL", typeof (String)); + createCol(land, "PassHours", typeof (Double)); + createCol(land, "PassPrice", typeof (Int32)); + createCol(land, "SnapshotUUID", typeof (String)); + createCol(land, "UserLocationX", typeof (Double)); + createCol(land, "UserLocationY", typeof (Double)); + createCol(land, "UserLocationZ", typeof (Double)); + createCol(land, "UserLookAtX", typeof (Double)); + createCol(land, "UserLookAtY", typeof (Double)); + createCol(land, "UserLookAtZ", typeof (Double)); + + land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]}; + + return land; + } + + private DataTable createLandAccessListTable() + { + DataTable landaccess = new DataTable("landaccesslist"); + createCol(landaccess, "LandUUID", typeof (String)); + createCol(landaccess, "AccessUUID", typeof (String)); + createCol(landaccess, "Flags", typeof (Int32)); + + return landaccess; + } + + private DataTable createShapeTable() + { + DataTable shapes = new DataTable("primshapes"); + createCol(shapes, "UUID", typeof (String)); + // shape is an enum + createCol(shapes, "Shape", typeof (Int32)); + // vectors + createCol(shapes, "ScaleX", typeof (Double)); + createCol(shapes, "ScaleY", typeof (Double)); + createCol(shapes, "ScaleZ", typeof (Double)); + // paths + createCol(shapes, "PCode", typeof (Int32)); + createCol(shapes, "PathBegin", typeof (Int32)); + createCol(shapes, "PathEnd", typeof (Int32)); + createCol(shapes, "PathScaleX", typeof (Int32)); + createCol(shapes, "PathScaleY", typeof (Int32)); + createCol(shapes, "PathShearX", typeof (Int32)); + createCol(shapes, "PathShearY", typeof (Int32)); + createCol(shapes, "PathSkew", typeof (Int32)); + createCol(shapes, "PathCurve", typeof (Int32)); + createCol(shapes, "PathRadiusOffset", typeof (Int32)); + createCol(shapes, "PathRevolutions", typeof (Int32)); + createCol(shapes, "PathTaperX", typeof (Int32)); + createCol(shapes, "PathTaperY", typeof (Int32)); + createCol(shapes, "PathTwist", typeof (Int32)); + createCol(shapes, "PathTwistBegin", typeof (Int32)); + // profile + createCol(shapes, "ProfileBegin", typeof (Int32)); + createCol(shapes, "ProfileEnd", typeof (Int32)); + createCol(shapes, "ProfileCurve", typeof (Int32)); + createCol(shapes, "ProfileHollow", typeof (Int32)); + createCol(shapes, "Texture", typeof (Byte[])); + createCol(shapes, "ExtraParams", typeof (Byte[])); + + shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]}; + + return shapes; + } + + private DataTable createItemsTable() + { + DataTable items = new DataTable("primitems"); + + createCol(items, "itemID", typeof (String)); + createCol(items, "primID", typeof (String)); + createCol(items, "assetID", typeof (String)); + createCol(items, "parentFolderID", typeof (String)); + + createCol(items, "invType", typeof (Int32)); + createCol(items, "assetType", typeof (Int32)); + + createCol(items, "name", typeof (String)); + createCol(items, "description", typeof (String)); + + createCol(items, "creationDate", typeof (Int64)); + createCol(items, "creatorID", typeof (String)); + createCol(items, "ownerID", typeof (String)); + createCol(items, "lastOwnerID", typeof (String)); + createCol(items, "groupID", typeof (String)); + + createCol(items, "nextPermissions", typeof (Int32)); + createCol(items, "currentPermissions", typeof (Int32)); + createCol(items, "basePermissions", typeof (Int32)); + createCol(items, "everyonePermissions", typeof (Int32)); + createCol(items, "groupPermissions", typeof (Int32)); + + items.PrimaryKey = new DataColumn[] {items.Columns["itemID"]}; + + return items; + } + + /*********************************************************************** + * + * Convert between ADO.NET <=> OpenSim Objects + * + * These should be database independant + * + **********************************************************************/ + + private SceneObjectPart buildPrim(DataRow row) + { + SceneObjectPart prim = new SceneObjectPart(); + prim.UUID = new LLUUID((String) row["UUID"]); + // explicit conversion of integers is required, which sort + // of sucks. No idea if there is a shortcut here or not. + prim.ParentID = Convert.ToUInt32(row["ParentID"]); + prim.CreationDate = Convert.ToInt32(row["CreationDate"]); + prim.Name = (String) row["Name"]; + // various text fields + prim.Text = (String) row["Text"]; + prim.Description = (String) row["Description"]; + prim.SitName = (String) row["SitName"]; + prim.TouchName = (String) row["TouchName"]; + // permissions + prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]); + prim.CreatorID = new LLUUID((String) row["CreatorID"]); + prim.OwnerID = new LLUUID((String) row["OwnerID"]); + prim.GroupID = new LLUUID((String) row["GroupID"]); + prim.LastOwnerID = new LLUUID((String) row["LastOwnerID"]); + prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); + prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); + prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); + prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); + prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); + // vectors + prim.OffsetPosition = new LLVector3( + Convert.ToSingle(row["PositionX"]), + Convert.ToSingle(row["PositionY"]), + Convert.ToSingle(row["PositionZ"]) + ); + prim.GroupPosition = new LLVector3( + Convert.ToSingle(row["GroupPositionX"]), + Convert.ToSingle(row["GroupPositionY"]), + Convert.ToSingle(row["GroupPositionZ"]) + ); + prim.Velocity = new LLVector3( + Convert.ToSingle(row["VelocityX"]), + Convert.ToSingle(row["VelocityY"]), + Convert.ToSingle(row["VelocityZ"]) + ); + prim.AngularVelocity = new LLVector3( + Convert.ToSingle(row["AngularVelocityX"]), + Convert.ToSingle(row["AngularVelocityY"]), + Convert.ToSingle(row["AngularVelocityZ"]) + ); + prim.Acceleration = new LLVector3( + Convert.ToSingle(row["AccelerationX"]), + Convert.ToSingle(row["AccelerationY"]), + Convert.ToSingle(row["AccelerationZ"]) + ); + // quaternions + prim.RotationOffset = new LLQuaternion( + Convert.ToSingle(row["RotationX"]), + Convert.ToSingle(row["RotationY"]), + Convert.ToSingle(row["RotationZ"]), + Convert.ToSingle(row["RotationW"]) + ); + try + { + prim.SetSitTargetLL(new LLVector3( + Convert.ToSingle(row["SitTargetOffsetX"]), + Convert.ToSingle(row["SitTargetOffsetY"]), + Convert.ToSingle(row["SitTargetOffsetZ"])), new LLQuaternion( + Convert.ToSingle( + row["SitTargetOrientX"]), + Convert.ToSingle( + row["SitTargetOrientY"]), + Convert.ToSingle( + row["SitTargetOrientZ"]), + Convert.ToSingle( + row["SitTargetOrientW"]))); + } + catch (InvalidCastException) + { + // Database table was created before we got here and needs to be created! :P + + using ( + MySqlCommand cmd = + new MySqlCommand( + "ALTER TABLE `prims` ADD COLUMN `SitTargetOffsetX` float NOT NULL default 0, ADD COLUMN `SitTargetOffsetY` float NOT NULL default 0, ADD COLUMN `SitTargetOffsetZ` float NOT NULL default 0, ADD COLUMN `SitTargetOrientW` float NOT NULL default 0, ADD COLUMN `SitTargetOrientX` float NOT NULL default 0, ADD COLUMN `SitTargetOrientY` float NOT NULL default 0, ADD COLUMN `SitTargetOrientZ` float NOT NULL default 0;", + m_connection)) + { + cmd.ExecuteNonQuery(); + } + } + return prim; + } + + + /// + /// Build a prim inventory item from the persisted data. + /// + /// + /// + private TaskInventoryItem buildItem(DataRow row) + { + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ItemID = new LLUUID((String)row["itemID"]); + taskItem.ParentPartID = new LLUUID((String)row["primID"]); + taskItem.AssetID = new LLUUID((String)row["assetID"]); + taskItem.ParentID = new LLUUID((String)row["parentFolderID"]); + + taskItem.InvType = Convert.ToInt32(row["invType"]); + taskItem.Type = Convert.ToInt32(row["assetType"]); + + taskItem.Name = (String)row["name"]; + taskItem.Description = (String)row["description"]; + taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]); + taskItem.CreatorID = new LLUUID((String)row["creatorID"]); + taskItem.OwnerID = new LLUUID((String)row["ownerID"]); + taskItem.LastOwnerID = new LLUUID((String)row["lastOwnerID"]); + taskItem.GroupID = new LLUUID((String)row["groupID"]); + + taskItem.NextOwnerMask = Convert.ToUInt32(row["nextPermissions"]); + taskItem.OwnerMask = Convert.ToUInt32(row["currentPermissions"]); + taskItem.BaseMask = Convert.ToUInt32(row["basePermissions"]); + taskItem.EveryoneMask = Convert.ToUInt32(row["everyonePermissions"]); + taskItem.GroupMask = Convert.ToUInt32(row["groupPermissions"]); + + return taskItem; + } + + private LandData buildLandData(DataRow row) + { + LandData newData = new LandData(); + + newData.globalID = new LLUUID((String) row["UUID"]); + newData.localID = Convert.ToInt32(row["LocalLandID"]); + + // Bitmap is a byte[512] + newData.landBitmapByteArray = (Byte[]) row["Bitmap"]; + + newData.landName = (String) row["Name"]; + newData.landDesc = (String) row["Description"]; + newData.ownerID = (String) row["OwnerUUID"]; + newData.isGroupOwned = Convert.ToBoolean(row["IsGroupOwned"]); + newData.area = Convert.ToInt32(row["Area"]); + newData.auctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented + newData.category = (Parcel.ParcelCategory) Convert.ToInt32(row["Category"]); + //Enum libsecondlife.Parcel.ParcelCategory + newData.claimDate = Convert.ToInt32(row["ClaimDate"]); + newData.claimPrice = Convert.ToInt32(row["ClaimPrice"]); + newData.groupID = new LLUUID((String) row["GroupUUID"]); + newData.salePrice = Convert.ToInt32(row["SalePrice"]); + newData.landStatus = (Parcel.ParcelStatus) Convert.ToInt32(row["LandStatus"]); + //Enum. libsecondlife.Parcel.ParcelStatus + newData.landFlags = Convert.ToUInt32(row["LandFlags"]); + newData.landingType = Convert.ToByte(row["LandingType"]); + newData.mediaAutoScale = Convert.ToByte(row["MediaAutoScale"]); + newData.mediaID = new LLUUID((String) row["MediaTextureUUID"]); + newData.mediaURL = (String) row["MediaURL"]; + newData.musicURL = (String) row["MusicURL"]; + newData.passHours = Convert.ToSingle(row["PassHours"]); + newData.passPrice = Convert.ToInt32(row["PassPrice"]); + newData.snapshotID = (String) row["SnapshotUUID"]; + + newData.userLocation = + new LLVector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), + Convert.ToSingle(row["UserLocationZ"])); + newData.userLookAt = + new LLVector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), + Convert.ToSingle(row["UserLookAtZ"])); + newData.parcelAccessList = new List(); + + return newData; + } + + private ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = new LLUUID((string) row["AccessUUID"]); + entry.Flags = (ParcelManager.AccessList) Convert.ToInt32(row["Flags"]); + entry.Time = new DateTime(); + return entry; + } + + private Array serializeTerrain(double[,] val) + { + MemoryStream str = new MemoryStream(65536*sizeof (double)); + BinaryWriter bw = new BinaryWriter(str); + + // TODO: COMPATIBILITY - Add byte-order conversions + for (int x = 0; x < 256; x++) + for (int y = 0; y < 256; y++) + bw.Write(val[x, y]); + + return str.ToArray(); + } + + private void fillPrimRow(DataRow row, SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID) + { + row["UUID"] = Util.ToRawUuidString(prim.UUID); + row["RegionUUID"] = Util.ToRawUuidString(regionUUID); + row["ParentID"] = prim.ParentID; + row["CreationDate"] = prim.CreationDate; + row["Name"] = prim.Name; + row["SceneGroupID"] = Util.ToRawUuidString(sceneGroupID); + // the UUID of the root part for this SceneObjectGroup + // various text fields + row["Text"] = prim.Text; + row["Description"] = prim.Description; + row["SitName"] = prim.SitName; + row["TouchName"] = prim.TouchName; + // permissions + row["ObjectFlags"] = prim.ObjectFlags; + row["CreatorID"] = Util.ToRawUuidString(prim.CreatorID); + row["OwnerID"] = Util.ToRawUuidString(prim.OwnerID); + row["GroupID"] = Util.ToRawUuidString(prim.GroupID); + row["LastOwnerID"] = Util.ToRawUuidString(prim.LastOwnerID); + row["OwnerMask"] = prim.OwnerMask; + row["NextOwnerMask"] = prim.NextOwnerMask; + row["GroupMask"] = prim.GroupMask; + row["EveryoneMask"] = prim.EveryoneMask; + row["BaseMask"] = prim.BaseMask; + // vectors + row["PositionX"] = prim.OffsetPosition.X; + row["PositionY"] = prim.OffsetPosition.Y; + row["PositionZ"] = prim.OffsetPosition.Z; + row["GroupPositionX"] = prim.GroupPosition.X; + row["GroupPositionY"] = prim.GroupPosition.Y; + row["GroupPositionZ"] = prim.GroupPosition.Z; + row["VelocityX"] = prim.Velocity.X; + row["VelocityY"] = prim.Velocity.Y; + row["VelocityZ"] = prim.Velocity.Z; + row["AngularVelocityX"] = prim.AngularVelocity.X; + row["AngularVelocityY"] = prim.AngularVelocity.Y; + row["AngularVelocityZ"] = prim.AngularVelocity.Z; + row["AccelerationX"] = prim.Acceleration.X; + row["AccelerationY"] = prim.Acceleration.Y; + row["AccelerationZ"] = prim.Acceleration.Z; + // quaternions + row["RotationX"] = prim.RotationOffset.X; + row["RotationY"] = prim.RotationOffset.Y; + row["RotationZ"] = prim.RotationOffset.Z; + row["RotationW"] = prim.RotationOffset.W; + + try + { + // Sit target + LLVector3 sitTargetPos = prim.GetSitTargetPositionLL(); + row["SitTargetOffsetX"] = sitTargetPos.X; + row["SitTargetOffsetY"] = sitTargetPos.Y; + row["SitTargetOffsetZ"] = sitTargetPos.Z; + + LLQuaternion sitTargetOrient = prim.GetSitTargetOrientationLL(); + row["SitTargetOrientW"] = sitTargetOrient.W; + row["SitTargetOrientX"] = sitTargetOrient.X; + row["SitTargetOrientY"] = sitTargetOrient.Y; + row["SitTargetOrientZ"] = sitTargetOrient.Z; + } + catch (MySqlException) + { + // Database table was created before we got here and needs to be created! :P + + using ( + MySqlCommand cmd = + new MySqlCommand( + "ALTER TABLE `prims` ADD COLUMN `SitTargetOffsetX` float NOT NULL default 0, ADD COLUMN `SitTargetOffsetY` float NOT NULL default 0, ADD COLUMN `SitTargetOffsetZ` float NOT NULL default 0, ADD COLUMN `SitTargetOrientW` float NOT NULL default 0, ADD COLUMN `SitTargetOrientX` float NOT NULL default 0, ADD COLUMN `SitTargetOrientY` float NOT NULL default 0, ADD COLUMN `SitTargetOrientZ` float NOT NULL default 0;", + m_connection)) + { + cmd.ExecuteNonQuery(); + } + } + } + + private void fillItemRow(DataRow row, TaskInventoryItem taskItem) + { + row["itemID"] = taskItem.ItemID; + row["primID"] = taskItem.ParentPartID; + row["assetID"] = taskItem.AssetID; + row["parentFolderID"] = taskItem.ParentID; + + row["invType"] = taskItem.InvType; + row["assetType"] = taskItem.Type; + + row["name"] = taskItem.Name; + row["description"] = taskItem.Description; + row["creationDate"] = taskItem.CreationDate; + row["creatorID"] = taskItem.CreatorID; + row["ownerID"] = taskItem.OwnerID; + row["lastOwnerID"] = taskItem.LastOwnerID; + row["groupID"] = taskItem.GroupID; + row["nextPermissions"] = taskItem.NextOwnerMask; + row["currentPermissions"] = taskItem.OwnerMask; + row["basePermissions"] = taskItem.BaseMask; + row["everyonePermissions"] = taskItem.EveryoneMask; + row["groupPermissions"] = taskItem.GroupMask; + } + + private void fillLandRow(DataRow row, LandData land, LLUUID regionUUID) + { + row["UUID"] = Util.ToRawUuidString(land.globalID); + row["RegionUUID"] = Util.ToRawUuidString(regionUUID); + row["LocalLandID"] = land.localID; + + // Bitmap is a byte[512] + row["Bitmap"] = land.landBitmapByteArray; + + row["Name"] = land.landName; + row["Description"] = land.landDesc; + row["OwnerUUID"] = Util.ToRawUuidString(land.ownerID); + row["IsGroupOwned"] = land.isGroupOwned; + row["Area"] = land.area; + row["AuctionID"] = land.auctionID; //Unemplemented + row["Category"] = land.category; //Enum libsecondlife.Parcel.ParcelCategory + row["ClaimDate"] = land.claimDate; + row["ClaimPrice"] = land.claimPrice; + row["GroupUUID"] = Util.ToRawUuidString(land.groupID); + row["SalePrice"] = land.salePrice; + row["LandStatus"] = land.landStatus; //Enum. libsecondlife.Parcel.ParcelStatus + row["LandFlags"] = land.landFlags; + row["LandingType"] = land.landingType; + row["MediaAutoScale"] = land.mediaAutoScale; + row["MediaTextureUUID"] = Util.ToRawUuidString(land.mediaID); + row["MediaURL"] = land.mediaURL; + row["MusicURL"] = land.musicURL; + row["PassHours"] = land.passHours; + row["PassPrice"] = land.passPrice; + row["SnapshotUUID"] = Util.ToRawUuidString(land.snapshotID); + row["UserLocationX"] = land.userLocation.X; + row["UserLocationY"] = land.userLocation.Y; + row["UserLocationZ"] = land.userLocation.Z; + row["UserLookAtX"] = land.userLookAt.X; + row["UserLookAtY"] = land.userLookAt.Y; + row["UserLookAtZ"] = land.userLookAt.Z; + } + + private void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, LLUUID parcelID) + { + row["LandUUID"] = Util.ToRawUuidString(parcelID); + row["AccessUUID"] = Util.ToRawUuidString(entry.AgentID); + row["Flags"] = entry.Flags; + } + + private PrimitiveBaseShape buildShape(DataRow row) + { + PrimitiveBaseShape s = new PrimitiveBaseShape(); + s.Scale = new LLVector3( + Convert.ToSingle(row["ScaleX"]), + Convert.ToSingle(row["ScaleY"]), + Convert.ToSingle(row["ScaleZ"]) + ); + // paths + s.PCode = Convert.ToByte(row["PCode"]); + s.PathBegin = Convert.ToUInt16(row["PathBegin"]); + s.PathEnd = Convert.ToUInt16(row["PathEnd"]); + s.PathScaleX = Convert.ToByte(row["PathScaleX"]); + s.PathScaleY = Convert.ToByte(row["PathScaleY"]); + s.PathShearX = Convert.ToByte(row["PathShearX"]); + s.PathShearY = Convert.ToByte(row["PathShearY"]); + s.PathSkew = Convert.ToSByte(row["PathSkew"]); + s.PathCurve = Convert.ToByte(row["PathCurve"]); + s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]); + s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]); + s.PathTaperX = Convert.ToSByte(row["PathTaperX"]); + s.PathTaperY = Convert.ToSByte(row["PathTaperY"]); + s.PathTwist = Convert.ToSByte(row["PathTwist"]); + s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]); + // profile + s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]); + s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); + s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); + s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); + + byte[] textureEntry = (byte[]) row["Texture"]; + s.TextureEntry = textureEntry; + + s.ExtraParams = (byte[]) row["ExtraParams"]; + + return s; + } + + private void fillShapeRow(DataRow row, SceneObjectPart prim) + { + PrimitiveBaseShape s = prim.Shape; + row["UUID"] = Util.ToRawUuidString(prim.UUID); + // shape is an enum + row["Shape"] = 0; + // vectors + row["ScaleX"] = s.Scale.X; + row["ScaleY"] = s.Scale.Y; + row["ScaleZ"] = s.Scale.Z; + // paths + row["PCode"] = s.PCode; + row["PathBegin"] = s.PathBegin; + row["PathEnd"] = s.PathEnd; + row["PathScaleX"] = s.PathScaleX; + row["PathScaleY"] = s.PathScaleY; + row["PathShearX"] = s.PathShearX; + row["PathShearY"] = s.PathShearY; + row["PathSkew"] = s.PathSkew; + row["PathCurve"] = s.PathCurve; + row["PathRadiusOffset"] = s.PathRadiusOffset; + row["PathRevolutions"] = s.PathRevolutions; + row["PathTaperX"] = s.PathTaperX; + row["PathTaperY"] = s.PathTaperY; + row["PathTwist"] = s.PathTwist; + row["PathTwistBegin"] = s.PathTwistBegin; + // profile + row["ProfileBegin"] = s.ProfileBegin; + row["ProfileEnd"] = s.ProfileEnd; + row["ProfileCurve"] = s.ProfileCurve; + row["ProfileHollow"] = s.ProfileHollow; + row["Texture"] = s.TextureEntry; + row["ExtraParams"] = s.ExtraParams; + } + + private void addPrim(SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID) + { + DataTable prims = m_dataSet.Tables["prims"]; + DataTable shapes = m_dataSet.Tables["primshapes"]; + + DataRow primRow = prims.Rows.Find(Util.ToRawUuidString(prim.UUID)); + if (primRow == null) + { + primRow = prims.NewRow(); + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + prims.Rows.Add(primRow); + } + else + { + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + } + + DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID)); + if (shapeRow == null) + { + shapeRow = shapes.NewRow(); + fillShapeRow(shapeRow, prim); + shapes.Rows.Add(shapeRow); + } + else + { + fillShapeRow(shapeRow, prim); + } + } + + // see IRegionDatastore + public void StorePrimInventory(LLUUID primID, ICollection items) + { + if (!persistPrimInventories) + return; + + m_log.InfoFormat("[DATASTORE]: Persisting Prim Inventory with prim ID {0}", primID); + + // For now, we're just going to crudely remove all the previous inventory items + // no matter whether they have changed or not, and replace them with the current set. + lock (m_dataSet) + { + RemoveItems(primID); + + // repalce with current inventory details + foreach (TaskInventoryItem newItem in items) + { +// m_log.InfoFormat( +// "[DATASTORE]: " + +// "Adding item {0}, {1} to prim ID {2}", +// newItem.Name, newItem.ItemID, newItem.ParentPartID); + + DataRow newItemRow = m_itemsTable.NewRow(); + fillItemRow(newItemRow, newItem); + m_itemsTable.Rows.Add(newItemRow); + } + } + + Commit(); + } + + /*********************************************************************** + * + * SQL Statement Creation Functions + * + * These functions create SQL statements for update, insert, and create. + * They can probably be factored later to have a db independant + * portion and a db specific portion + * + **********************************************************************/ + + private MySqlCommand createInsertCommand(string table, DataTable dt) + { + /** + * This is subtle enough to deserve some commentary. + * Instead of doing *lots* and *lots of hardcoded strings + * for database definitions we'll use the fact that + * realistically all insert statements look like "insert + * into A(b, c) values(:b, :c) on the parameterized query + * front. If we just have a list of b, c, etc... we can + * generate these strings instead of typing them out. + */ + string[] cols = new string[dt.Columns.Count]; + for (int i = 0; i < dt.Columns.Count; i++) + { + DataColumn col = dt.Columns[i]; + cols[i] = col.ColumnName; + } + + string sql = "insert into " + table + "("; + sql += String.Join(", ", cols); + // important, the first ':' needs to be here, the rest get added in the join + sql += ") values (?"; + sql += String.Join(", ?", cols); + sql += ")"; + MySqlCommand cmd = new MySqlCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createMySqlParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + private MySqlCommand createUpdateCommand(string table, string pk, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "=?" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk; + MySqlCommand cmd = new MySqlCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createMySqlParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + private string defineTable(DataTable dt) + { + string sql = "create table " + dt.TableName + "("; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ",\n"; + } + subsql += col.ColumnName + " " + MySqlType(col.DataType); + if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0]) + { + subsql += " primary key"; + } + } + sql += subsql; + sql += ")"; + + //m_log.InfoFormat("[DATASTORE]: defineTable() sql {0}", sql); + + return sql; + } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + /// + /// This is a convenience function that collapses 5 repetitive + /// lines for defining MySqlParameters to 2 parameters: + /// column name and database type. + /// + /// It assumes certain conventions like ?param as the param + /// name to replace in parametrized queries, and that source + /// version is always current version, both of which are fine + /// for us. + /// + ///a built MySql parameter + private MySqlParameter createMySqlParameter(string name, Type type) + { + MySqlParameter param = new MySqlParameter(); + param.ParameterName = "?" + name; + param.DbType = dbtypeFromType(type); + param.SourceColumn = name; + param.SourceVersion = DataRowVersion.Current; + return param; + } + + private MySqlParameter createParamWithValue(string name, Type type, Object o) + { + MySqlParameter param = createMySqlParameter(name, type); + param.Value = o; + return param; + } + + private void SetupPrimCommands(MySqlDataAdapter da, MySqlConnection conn) + { + MySqlCommand insertCommand = createInsertCommand("prims", m_primTable); + insertCommand.Connection = conn; + da.InsertCommand = insertCommand; + + MySqlCommand updateCommand = createUpdateCommand("prims", "UUID=?UUID", m_primTable); + updateCommand.Connection = conn; + da.UpdateCommand = updateCommand; + + MySqlCommand delete = new MySqlCommand("delete from prims where UUID=?UUID"); + delete.Parameters.Add(createMySqlParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + private void SetupItemsCommands(MySqlDataAdapter da, MySqlConnection conn) + { + da.InsertCommand = createInsertCommand("primitems", m_itemsTable); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primitems", "itemID = ?itemID", m_itemsTable); + da.UpdateCommand.Connection = conn; + + MySqlCommand delete = new MySqlCommand("delete from primitems where itemID = ?itemID"); + delete.Parameters.Add(createMySqlParameter("itemID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + private void SetupTerrainCommands(MySqlDataAdapter da, MySqlConnection conn) + { + da.InsertCommand = createInsertCommand("terrain", m_dataSet.Tables["terrain"]); + da.InsertCommand.Connection = conn; + } + + private void setupLandCommands(MySqlDataAdapter da, MySqlConnection conn) + { + da.InsertCommand = createInsertCommand("land", m_dataSet.Tables["land"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("land", "UUID=?UUID", m_dataSet.Tables["land"]); + da.UpdateCommand.Connection = conn; + } + + private void setupLandAccessCommands(MySqlDataAdapter da, MySqlConnection conn) + { + da.InsertCommand = createInsertCommand("landaccesslist", m_dataSet.Tables["landaccesslist"]); + da.InsertCommand.Connection = conn; + } + + private void SetupShapeCommands(MySqlDataAdapter da, MySqlConnection conn) + { + da.InsertCommand = createInsertCommand("primshapes", m_dataSet.Tables["primshapes"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primshapes", "UUID=?UUID", m_dataSet.Tables["primshapes"]); + da.UpdateCommand.Connection = conn; + + MySqlCommand delete = new MySqlCommand("delete from primshapes where UUID = ?UUID"); + delete.Parameters.Add(createMySqlParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + private void InitDB(MySqlConnection conn) + { + string createPrims = defineTable(createPrimTable()); + string createShapes = defineTable(createShapeTable()); + string createItems = defineTable(createItemsTable()); + string createTerrain = defineTable(createTerrainTable()); + string createLand = defineTable(createLandTable()); + string createLandAccessList = defineTable(createLandAccessListTable()); + + MySqlCommand pcmd = new MySqlCommand(createPrims, conn); + MySqlCommand scmd = new MySqlCommand(createShapes, conn); + MySqlCommand icmd = new MySqlCommand(createItems, conn); + MySqlCommand tcmd = new MySqlCommand(createTerrain, conn); + MySqlCommand lcmd = new MySqlCommand(createLand, conn); + MySqlCommand lalcmd = new MySqlCommand(createLandAccessList, conn); + + if (conn.State != ConnectionState.Open) + { + try + { + conn.Open(); + } + catch (Exception ex) + { + m_log.Error("[MySql]: Error connecting to MySQL server: " + ex.Message); + m_log.Error("[MySql]: Application is terminating!"); + System.Threading.Thread.CurrentThread.Abort(); + } + } + + try + { + pcmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + m_log.WarnFormat("[MySql]: Primitives Table Already Exists: {0}", e); + } + + try + { + scmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + m_log.WarnFormat("[MySql]: Shapes Table Already Exists: {0}", e); + } + + try + { + icmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + m_log.WarnFormat("[MySql]: Items Table Already Exists: {0}", e); + } + + try + { + tcmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + m_log.WarnFormat("[MySql]: Terrain Table Already Exists: {0}", e); + } + + try + { + lcmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + m_log.WarnFormat("[MySql]: Land Table Already Exists: {0}", e); + } + + try + { + lalcmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + m_log.WarnFormat("[MySql]: LandAccessList Table Already Exists: {0}", e); + } + conn.Close(); + } + + private bool TestTables(MySqlConnection conn) + { + MySqlCommand primSelectCmd = new MySqlCommand(m_primSelect, conn); + MySqlDataAdapter pDa = new MySqlDataAdapter(primSelectCmd); + MySqlCommand shapeSelectCmd = new MySqlCommand(m_shapeSelect, conn); + MySqlDataAdapter sDa = new MySqlDataAdapter(shapeSelectCmd); + MySqlCommand itemsSelectCmd = new MySqlCommand(m_itemsSelect, conn); + MySqlDataAdapter iDa = new MySqlDataAdapter(itemsSelectCmd); + MySqlCommand terrainSelectCmd = new MySqlCommand(m_terrainSelect, conn); + MySqlDataAdapter tDa = new MySqlDataAdapter(terrainSelectCmd); + MySqlCommand landSelectCmd = new MySqlCommand(m_landSelect, conn); + MySqlDataAdapter lDa = new MySqlDataAdapter(landSelectCmd); + MySqlCommand landAccessListSelectCmd = new MySqlCommand(m_landAccessListSelect, conn); + MySqlDataAdapter lalDa = new MySqlDataAdapter(landAccessListSelectCmd); + + DataSet tmpDS = new DataSet(); + try + { + pDa.Fill(tmpDS, "prims"); + sDa.Fill(tmpDS, "primshapes"); + + if (persistPrimInventories) + iDa.Fill(tmpDS, "primitems"); + + tDa.Fill(tmpDS, "terrain"); + lDa.Fill(tmpDS, "land"); + lalDa.Fill(tmpDS, "landaccesslist"); + } + catch (MySqlException) + { + m_log.Info("[DATASTORE]: MySql Database doesn't exist... creating"); + InitDB(conn); + } + + pDa.Fill(tmpDS, "prims"); + sDa.Fill(tmpDS, "primshapes"); + + if (persistPrimInventories) + iDa.Fill(tmpDS, "primitems"); + + tDa.Fill(tmpDS, "terrain"); + lDa.Fill(tmpDS, "land"); + lalDa.Fill(tmpDS, "landaccesslist"); + + foreach (DataColumn col in createPrimTable().Columns) + { + if (!tmpDS.Tables["prims"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing required column:" + col.ColumnName); + return false; + } + } + + foreach (DataColumn col in createShapeTable().Columns) + { + if (!tmpDS.Tables["primshapes"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing required column:" + col.ColumnName); + return false; + } + } + + // XXX primitems should probably go here eventually + + foreach (DataColumn col in createTerrainTable().Columns) + { + if (!tmpDS.Tables["terrain"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing require column:" + col.ColumnName); + return false; + } + } + + foreach (DataColumn col in createLandTable().Columns) + { + if (!tmpDS.Tables["land"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing require column:" + col.ColumnName); + return false; + } + } + + foreach (DataColumn col in createLandAccessListTable().Columns) + { + if (!tmpDS.Tables["landaccesslist"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing require column:" + col.ColumnName); + return false; + } + } + + return true; + } + + /*********************************************************************** + * + * Type conversion functions + * + **********************************************************************/ + + private DbType dbtypeFromType(Type type) + { + if (type == typeof (String)) + { + return DbType.String; + } + else if (type == typeof (Int32)) + { + return DbType.Int32; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte)) + { + return DbType.Byte; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte[])) + { + return DbType.Binary; + } + else + { + return DbType.String; + } + } + + // this is something we'll need to implement for each db + // slightly differently. + private string MySqlType(Type type) + { + if (type == typeof (String)) + { + return "varchar(255)"; + } + else if (type == typeof (Int32)) + { + return "integer"; + } + else if (type == typeof (Int64)) + { + return "bigint"; + } + else if (type == typeof (Double)) + { + return "float"; + } + else if (type == typeof (Byte[])) + { + return "longblob"; + } + else + { + return "string"; + } + } + } +} diff --git a/trunk/OpenSim/Framework/Data.MySQL/MySQLDatabaseMapper.cs b/trunk/OpenSim/Framework/Data.MySQL/MySQLDatabaseMapper.cs new file mode 100644 index 0000000000..04b4b4d391 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/MySQLDatabaseMapper.cs @@ -0,0 +1,54 @@ +/* +* 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.Data.Common; +using MySql.Data.MySqlClient; + //using TribalMedia.Framework.Data; + +namespace OpenSim.Framework.Data.MySQL +{ + /* + public class MySQLDatabaseMapper : OpenSimDatabaseConnector + { + public MySQLDatabaseMapper(string connectionString) + : base(connectionString) + { + } + + public override DbConnection GetNewConnection() + { + MySqlConnection connection = new MySqlConnection(m_connectionString); + return connection; + } + + public override string CreateParamName(string fieldName) + { + return "?" + fieldName; + } + }*/ +} diff --git a/trunk/OpenSim/Framework/Data.MySQL/MySQLGridData.cs b/trunk/OpenSim/Framework/Data.MySQL/MySQLGridData.cs new file mode 100644 index 0000000000..3737e486ed --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/MySQLGridData.cs @@ -0,0 +1,331 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.MySQL +{ + /// + /// A MySQL Interface for the Grid Server + /// + public class MySQLGridData : IGridData + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// MySQL Database Manager + /// + private MySQLManager database; + + /// + /// Initialises the Grid Interface + /// + public void Initialise() + { + IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini"); + string settingHostname = GridDataMySqlFile.ParseFileReadValue("hostname"); + string settingDatabase = GridDataMySqlFile.ParseFileReadValue("database"); + string settingUsername = GridDataMySqlFile.ParseFileReadValue("username"); + string settingPassword = GridDataMySqlFile.ParseFileReadValue("password"); + string settingPooling = GridDataMySqlFile.ParseFileReadValue("pooling"); + string settingPort = GridDataMySqlFile.ParseFileReadValue("port"); + + database = + new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword, settingPooling, + settingPort); + + TestTables(); + } + + #region Test and initialization code + + /// + /// Ensure that the user related tables exists and are at the latest version + /// + private void TestTables() + { + Dictionary tableList = new Dictionary(); + + tableList["regions"] = null; + database.GetTableVersion(tableList); + + UpgradeRegionsTable(tableList["regions"]); + } + + /// + /// Create or upgrade the table if necessary + /// + /// A null indicates that the table does not + /// currently exist + private void UpgradeRegionsTable(string oldVersion) + { + // null as the version, indicates that the table didn't exist + if (oldVersion == null) + { + database.ExecuteResourceSql("CreateRegionsTable.sql"); + return; + } + } + + #endregion + + /// + /// Shuts down the grid interface + /// + public void Close() + { + database.Close(); + } + + /// + /// Returns the plugin name + /// + /// Plugin name + public string getName() + { + return "MySql OpenGridData"; + } + + /// + /// Returns the plugin version + /// + /// Plugin version + public string getVersion() + { + return "0.1"; + } + + /// + /// Returns all the specified region profiles within coordates -- coordinates are inclusive + /// + /// Minimum X coordinate + /// Minimum Y coordinate + /// Maximum X coordinate + /// Maximum Y coordinate + /// + public RegionProfileData[] GetProfilesInRange(uint xmin, uint ymin, uint xmax, uint ymax) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["?xmin"] = xmin.ToString(); + param["?ymin"] = ymin.ToString(); + param["?xmax"] = xmax.ToString(); + param["?ymax"] = ymax.ToString(); + + IDbCommand result = + database.Query( + "SELECT * FROM regions WHERE locX >= ?xmin AND locX <= ?xmax AND locY >= ?ymin AND locY <= ?ymax", + param); + IDataReader reader = result.ExecuteReader(); + + RegionProfileData row; + + List rows = new List(); + + while ((row = database.readSimRow(reader)) != null) + { + rows.Add(row); + } + reader.Close(); + result.Dispose(); + + return rows.ToArray(); + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Returns a sim profile from it's location + /// + /// Region location handle + /// Sim profile + public RegionProfileData GetProfileByHandle(ulong handle) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["?handle"] = handle.ToString(); + + IDbCommand result = database.Query("SELECT * FROM regions WHERE regionHandle = ?handle", param); + IDataReader reader = result.ExecuteReader(); + + RegionProfileData row = database.readSimRow(reader); + reader.Close(); + result.Dispose(); + + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Returns a sim profile from it's UUID + /// + /// The region UUID + /// The sim profile + public RegionProfileData GetProfileByLLUUID(LLUUID uuid) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["?uuid"] = uuid.ToString(); + + IDbCommand result = database.Query("SELECT * FROM regions WHERE uuid = ?uuid", param); + IDataReader reader = result.ExecuteReader(); + + RegionProfileData row = database.readSimRow(reader); + reader.Close(); + result.Dispose(); + + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Adds a new profile to the database + /// + /// The profile to add + /// Successful? + public DataResponse AddProfile(RegionProfileData profile) + { + lock (database) + { + if (database.insertRegion(profile)) + { + return DataResponse.RESPONSE_OK; + } + else + { + return DataResponse.RESPONSE_ERROR; + } + } + } + + /// + /// DEPRECIATED. Attempts to authenticate a region by comparing a shared secret. + /// + /// The UUID of the challenger + /// The attempted regionHandle of the challenger + /// The secret + /// Whether the secret and regionhandle match the database entry for UUID + public bool AuthenticateSim(LLUUID uuid, ulong handle, string authkey) + { + bool throwHissyFit = false; // Should be true by 1.0 + + if (throwHissyFit) + throw new Exception("CRYPTOWEAK AUTHENTICATE: Refusing to authenticate due to replay potential."); + + RegionProfileData data = GetProfileByLLUUID(uuid); + + return (handle == data.regionHandle && authkey == data.regionSecret); + } + + /// + /// NOT YET FUNCTIONAL. Provides a cryptographic authentication of a region + /// + /// This requires a security audit. + /// + /// + /// + /// + /// + public bool AuthenticateSim(LLUUID uuid, ulong handle, string authhash, string challenge) + { + SHA512Managed HashProvider = new SHA512Managed(); + ASCIIEncoding TextProvider = new ASCIIEncoding(); + + byte[] stream = TextProvider.GetBytes(uuid.ToString() + ":" + handle.ToString() + ":" + challenge); + byte[] hash = HashProvider.ComputeHash(stream); + + return false; + } + + public ReservationData GetReservationAtPoint(uint x, uint y) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["?x"] = x.ToString(); + param["?y"] = y.ToString(); + IDbCommand result = + database.Query( + "SELECT * FROM reservations WHERE resXMin <= ?x AND resXMax >= ?x AND resYMin <= ?y AND resYMax >= ?y", + param); + IDataReader reader = result.ExecuteReader(); + + ReservationData row = database.readReservationRow(reader); + reader.Close(); + result.Dispose(); + + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MySQL/MySQLInventoryData.cs b/trunk/OpenSim/Framework/Data.MySQL/MySQLInventoryData.cs new file mode 100644 index 0000000000..8257a23bf2 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/MySQLInventoryData.cs @@ -0,0 +1,653 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using MySql.Data.MySqlClient; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.MySQL +{ + /// + /// A MySQL interface for the inventory server + /// + public class MySQLInventoryData : IInventoryData + { + private static readonly log4net.ILog m_log + = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The database manager + /// + private MySQLManager database; + + /// + /// Loads and initialises this database plugin + /// + public void Initialise() + { + IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini"); + string settingHostname = GridDataMySqlFile.ParseFileReadValue("hostname"); + string settingDatabase = GridDataMySqlFile.ParseFileReadValue("database"); + string settingUsername = GridDataMySqlFile.ParseFileReadValue("username"); + string settingPassword = GridDataMySqlFile.ParseFileReadValue("password"); + string settingPooling = GridDataMySqlFile.ParseFileReadValue("pooling"); + string settingPort = GridDataMySqlFile.ParseFileReadValue("port"); + + database = + new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword, settingPooling, + settingPort); + TestTables(database.Connection); + } + + #region Test and initialization code + + private void UpgradeFoldersTable(string oldVersion) + { + // null as the version, indicates that the table didn't exist + if (oldVersion == null) + { + database.ExecuteResourceSql("CreateFoldersTable.sql"); + return; + } + + // if the table is already at the current version, then we can exit immediately +// if (oldVersion == "Rev. 2") +// return; + +// database.ExecuteResourceSql("UpgradeFoldersTableToVersion2.sql"); + } + + private void UpgradeItemsTable(string oldVersion) + { + // null as the version, indicates that the table didn't exist + if (oldVersion == null) + { + database.ExecuteResourceSql("CreateItemsTable.sql"); + return; + } + + // if the table is already at the current version, then we can exit immediately +// if (oldVersion == "Rev. 2") +// return; + +// database.ExecuteResourceSql("UpgradeItemsTableToVersion2.sql"); + } + + private void TestTables(MySqlConnection conn) + { + Dictionary tableList = new Dictionary(); + + tableList["inventoryfolders"] = null; + tableList["inventoryitems"] = null; + + database.GetTableVersion(tableList); + m_log.Info("[MYSQL]: Inventory Folder Version: " + tableList["inventoryfolders"]); + m_log.Info("[MYSQL]: Inventory Items Version: " + tableList["inventoryitems"]); + + UpgradeFoldersTable(tableList["inventoryfolders"]); + UpgradeItemsTable(tableList["inventoryitems"]); + } + + #endregion + + /// + /// The name of this DB provider + /// + /// Name of DB provider + public string getName() + { + return "MySQL Inventory Data Interface"; + } + + /// + /// Closes this DB provider + /// + public void Close() + { + // Do nothing. + } + + /// + /// Returns the version of this DB provider + /// + /// A string containing the DB provider + public string getVersion() + { + return database.getVersion(); + } + + /// + /// Returns a list of items in a specified folder + /// + /// The folder to search + /// A list containing inventory items + public List getInventoryInFolder(LLUUID folderID) + { + try + { + lock (database) + { + List items = new List(); + + MySqlCommand result = + new MySqlCommand("SELECT * FROM inventoryitems WHERE parentFolderID = ?uuid", + database.Connection); + result.Parameters.AddWithValue("?uuid", folderID.ToString()); + MySqlDataReader reader = result.ExecuteReader(); + + while (reader.Read()) + items.Add(readInventoryItem(reader)); + + reader.Close(); + result.Dispose(); + + return items; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Returns a list of the root folders within a users inventory + /// + /// The user whos inventory is to be searched + /// A list of folder objects + public List getUserRootFolders(LLUUID user) + { + try + { + lock (database) + { + MySqlCommand result = + new MySqlCommand( + "SELECT * FROM inventoryfolders WHERE parentFolderID = ?zero AND agentID = ?uuid", + database.Connection); + result.Parameters.AddWithValue("?uuid", user.ToString()); + result.Parameters.AddWithValue("?zero", LLUUID.Zero.ToString()); + MySqlDataReader reader = result.ExecuteReader(); + + List items = new List(); + while (reader.Read()) + items.Add(readInventoryFolder(reader)); + + + reader.Close(); + result.Dispose(); + + return items; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + // see InventoryItemBase.getUserRootFolder + public InventoryFolderBase getUserRootFolder(LLUUID user) + { + try + { + lock (database) + { + MySqlCommand result = + new MySqlCommand( + "SELECT * FROM inventoryfolders WHERE parentFolderID = ?zero AND agentID = ?uuid", + database.Connection); + result.Parameters.AddWithValue("?uuid", user.ToString()); + result.Parameters.AddWithValue("?zero", LLUUID.Zero.ToString()); + + MySqlDataReader reader = result.ExecuteReader(); + + List items = new List(); + while (reader.Read()) + items.Add(readInventoryFolder(reader)); + + InventoryFolderBase rootFolder = null; + + // There should only ever be one root folder for a user. However, if there's more + // than one we'll simply use the first one rather than failing. It would be even + // nicer to print some message to this effect, but this feels like it's too low a + // to put such a message out, and it's too minor right now to spare the time to + // suitably refactor. + if (items.Count > 0) + { + rootFolder = items[0]; + } + + reader.Close(); + result.Dispose(); + + return rootFolder; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Return a list of folders in a users inventory contained within the specified folder. + /// This method is only used in tests - in normal operation the user always have one, + /// and only one, root folder. + /// + /// The folder to search + /// A list of inventory folders + public List getInventoryFolders(LLUUID parentID) + { + try + { + lock (database) + { + MySqlCommand result = + new MySqlCommand("SELECT * FROM inventoryfolders WHERE parentFolderID = ?uuid", + database.Connection); + result.Parameters.AddWithValue("?uuid", parentID.ToString()); + MySqlDataReader reader = result.ExecuteReader(); + + List items = new List(); + + while (reader.Read()) + items.Add(readInventoryFolder(reader)); + + reader.Close(); + result.Dispose(); + + return items; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Reads a one item from an SQL result + /// + /// The SQL Result + /// the item read + private InventoryItemBase readInventoryItem(MySqlDataReader reader) + { + try + { + InventoryItemBase item = new InventoryItemBase(); + + item.inventoryID = new LLUUID((string) reader["inventoryID"]); + item.assetID = new LLUUID((string) reader["assetID"]); + item.assetType = (int) reader["assetType"]; + item.parentFolderID = new LLUUID((string) reader["parentFolderID"]); + item.avatarID = new LLUUID((string) reader["avatarID"]); + item.inventoryName = (string) reader["inventoryName"]; + item.inventoryDescription = (string) reader["inventoryDescription"]; + item.inventoryNextPermissions = (uint) reader["inventoryNextPermissions"]; + item.inventoryCurrentPermissions = (uint) reader["inventoryCurrentPermissions"]; + item.invType = (int) reader["invType"]; + item.creatorsID = new LLUUID((string) reader["creatorID"]); + item.inventoryBasePermissions = (uint) reader["inventoryBasePermissions"]; + item.inventoryEveryOnePermissions = (uint) reader["inventoryEveryOnePermissions"]; + return item; + } + catch (MySqlException e) + { + m_log.Error(e.ToString()); + } + + return null; + } + + /// + /// Returns a specified inventory item + /// + /// The item to return + /// An inventory item + public InventoryItemBase getInventoryItem(LLUUID itemID) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + + MySqlCommand result = + new MySqlCommand("SELECT * FROM inventoryitems WHERE inventoryID = ?uuid", database.Connection); + result.Parameters.AddWithValue("?uuid", itemID.ToString()); + MySqlDataReader reader = result.ExecuteReader(); + + InventoryItemBase item = null; + if (reader.Read()) + item = readInventoryItem(reader); + + reader.Close(); + result.Dispose(); + + return item; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + } + return null; + } + + /// + /// Reads a list of inventory folders returned by a query. + /// + /// A MySQL Data Reader + /// A List containing inventory folders + protected InventoryFolderBase readInventoryFolder(MySqlDataReader reader) + { + try + { + InventoryFolderBase folder = new InventoryFolderBase(); + folder.agentID = new LLUUID((string) reader["agentID"]); + folder.parentID = new LLUUID((string) reader["parentFolderID"]); + folder.folderID = new LLUUID((string) reader["folderID"]); + folder.name = (string) reader["folderName"]; + folder.type = (short) reader["type"]; + folder.version = (ushort) ((int) reader["version"]); + return folder; + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + + return null; + } + + + /// + /// Returns a specified inventory folder + /// + /// The folder to return + /// A folder class + public InventoryFolderBase getInventoryFolder(LLUUID folderID) + { + try + { + lock (database) + { + MySqlCommand result = + new MySqlCommand("SELECT * FROM inventoryfolders WHERE folderID = ?uuid", database.Connection); + result.Parameters.AddWithValue("?uuid", folderID.ToString()); + MySqlDataReader reader = result.ExecuteReader(); + + reader.Read(); + InventoryFolderBase folder = readInventoryFolder(reader); + reader.Close(); + result.Dispose(); + + return folder; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Adds a specified item to the database + /// + /// The inventory item + public void addInventoryItem(InventoryItemBase item) + { + string sql = + "REPLACE INTO inventoryitems (inventoryID, assetID, assetType, parentFolderID, avatarID, inventoryName, inventoryDescription, inventoryNextPermissions, inventoryCurrentPermissions, invType, creatorID, inventoryBasePermissions, inventoryEveryOnePermissions) VALUES "; + sql += + "(?inventoryID, ?assetID, ?assetType, ?parentFolderID, ?avatarID, ?inventoryName, ?inventoryDescription, ?inventoryNextPermissions, ?inventoryCurrentPermissions, ?invType, ?creatorID, ?inventoryBasePermissions, ?inventoryEveryOnePermissions)"; + + try + { + MySqlCommand result = new MySqlCommand(sql, database.Connection); + result.Parameters.AddWithValue("?inventoryID", item.inventoryID.ToString()); + result.Parameters.AddWithValue("?assetID", item.assetID.ToString()); + result.Parameters.AddWithValue("?assetType", item.assetType.ToString()); + result.Parameters.AddWithValue("?parentFolderID", item.parentFolderID.ToString()); + result.Parameters.AddWithValue("?avatarID", item.avatarID.ToString()); + result.Parameters.AddWithValue("?inventoryName", item.inventoryName); + result.Parameters.AddWithValue("?inventoryDescription", item.inventoryDescription); + result.Parameters.AddWithValue("?inventoryNextPermissions", item.inventoryNextPermissions.ToString()); + result.Parameters.AddWithValue("?inventoryCurrentPermissions", + item.inventoryCurrentPermissions.ToString()); + result.Parameters.AddWithValue("?invType", item.invType); + result.Parameters.AddWithValue("?creatorID", item.creatorsID.ToString()); + result.Parameters.AddWithValue("?inventoryBasePermissions", item.inventoryBasePermissions); + result.Parameters.AddWithValue("?inventoryEveryOnePermissions", item.inventoryEveryOnePermissions); + result.ExecuteNonQuery(); + result.Dispose(); + } + catch (MySqlException e) + { + m_log.Error(e.ToString()); + } + } + + /// + /// Updates the specified inventory item + /// + /// Inventory item to update + public void updateInventoryItem(InventoryItemBase item) + { + addInventoryItem(item); + } + + /// + /// + /// + /// + public void deleteInventoryItem(LLUUID itemID) + { + try + { + MySqlCommand cmd = + new MySqlCommand("DELETE FROM inventoryitems WHERE inventoryID=?uuid", database.Connection); + cmd.Parameters.AddWithValue("?uuid", itemID.ToString()); + cmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + } + } + + /// + /// Creates a new inventory folder + /// + /// Folder to create + public void addInventoryFolder(InventoryFolderBase folder) + { + string sql = + "REPLACE INTO inventoryfolders (folderID, agentID, parentFolderID, folderName, type, version) VALUES "; + sql += "(?folderID, ?agentID, ?parentFolderID, ?folderName, ?type, ?version)"; + + MySqlCommand cmd = new MySqlCommand(sql, database.Connection); + cmd.Parameters.AddWithValue("?folderID", folder.folderID.ToString()); + cmd.Parameters.AddWithValue("?agentID", folder.agentID.ToString()); + cmd.Parameters.AddWithValue("?parentFolderID", folder.parentID.ToString()); + cmd.Parameters.AddWithValue("?folderName", folder.name); + cmd.Parameters.AddWithValue("?type", (short) folder.type); + cmd.Parameters.AddWithValue("?version", folder.version); + + try + { + lock (database) + { + cmd.ExecuteNonQuery(); + } + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + } + + /// + /// Updates an inventory folder + /// + /// Folder to update + public void updateInventoryFolder(InventoryFolderBase folder) + { + addInventoryFolder(folder); + } + + /// Creates a new inventory folder + /// + /// Folder to create + public void moveInventoryFolder(InventoryFolderBase folder) + { + string sql = + "UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID"; + + MySqlCommand cmd = new MySqlCommand(sql, database.Connection); + cmd.Parameters.AddWithValue("?folderID", folder.folderID.ToString()); + cmd.Parameters.AddWithValue("?parentFolderID", folder.parentID.ToString()); + + try + { + lock (database) + { + cmd.ExecuteNonQuery(); + } + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + } + + /// + /// Append a list of all the child folders of a parent folder + /// + /// list where folders will be appended + /// ID of parent + protected void getInventoryFolders(ref List folders, LLUUID parentID) + { + List subfolderList = getInventoryFolders(parentID); + + foreach (InventoryFolderBase f in subfolderList) + folders.Add(f); + } + + /// + /// Returns all child folders in the hierarchy from the parent folder and down + /// + /// The folder to get subfolders for + /// A list of inventory folders + protected List getFolderHierarchy(LLUUID parentID) + { + List folders = new List(); + getInventoryFolders(ref folders, parentID); + + for (int i = 0; i < folders.Count; i++) + getInventoryFolders(ref folders, folders[i].folderID); + + return folders; + } + + protected void deleteOneFolder(LLUUID folderID) + { + try + { + MySqlCommand cmd = + new MySqlCommand("DELETE FROM inventoryfolders WHERE folderID=?uuid", database.Connection); + cmd.Parameters.AddWithValue("?uuid", folderID.ToString()); + + lock (database) + { + cmd.ExecuteNonQuery(); + } + } + catch (MySqlException e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + } + } + + protected void deleteItemsInFolder(LLUUID folderID) + { + try + { + MySqlCommand cmd = + new MySqlCommand("DELETE FROM inventoryitems WHERE parentFolderID=?uuid", database.Connection); + cmd.Parameters.AddWithValue("?uuid", folderID.ToString()); + + lock (database) + { + cmd.ExecuteNonQuery(); + } + } + catch (MySqlException e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + } + } + + + /// + /// Delete an inventory folder + /// + /// Id of folder to delete + public void deleteInventoryFolder(LLUUID folderID) + { + List subFolders = getFolderHierarchy(folderID); + + //Delete all sub-folders + foreach (InventoryFolderBase f in subFolders) + { + deleteOneFolder(f.folderID); + deleteItemsInFolder(f.folderID); + } + + //Delete the actual row + deleteOneFolder(folderID); + deleteItemsInFolder(folderID); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MySQL/MySQLLogData.cs b/trunk/OpenSim/Framework/Data.MySQL/MySQLLogData.cs new file mode 100644 index 0000000000..d2605fa14c --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/MySQLLogData.cs @@ -0,0 +1,106 @@ +/* +* 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. +* +*/ +namespace OpenSim.Framework.Data.MySQL +{ + /// + /// An interface to the log database for MySQL + /// + internal class MySQLLogData : ILogData + { + /// + /// The database manager + /// + public MySQLManager database; + + /// + /// Artificial constructor called when the plugin is loaded + /// + public void Initialise() + { + IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini"); + string settingHostname = GridDataMySqlFile.ParseFileReadValue("hostname"); + string settingDatabase = GridDataMySqlFile.ParseFileReadValue("database"); + string settingUsername = GridDataMySqlFile.ParseFileReadValue("username"); + string settingPassword = GridDataMySqlFile.ParseFileReadValue("password"); + string settingPooling = GridDataMySqlFile.ParseFileReadValue("pooling"); + string settingPort = GridDataMySqlFile.ParseFileReadValue("port"); + + database = + new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword, settingPooling, + settingPort); + } + + /// + /// Saves a log item to the database + /// + /// The daemon triggering the event + /// The target of the action (region / agent UUID, etc) + /// The method call where the problem occured + /// The arguments passed to the method + /// How critical is this? + /// The message to log + public void saveLog(string serverDaemon, string target, string methodCall, string arguments, int priority, + string logMessage) + { + try + { + database.insertLogRow(serverDaemon, target, methodCall, arguments, priority, logMessage); + } + catch + { + database.Reconnect(); + } + } + + /// + /// Returns the name of this DB provider + /// + /// A string containing the DB provider name + public string getName() + { + return "MySQL Logdata Interface"; + } + + /// + /// Closes the database provider + /// + public void Close() + { + // Do nothing. + } + + /// + /// Returns the version of this DB provider + /// + /// A string containing the provider version + public string getVersion() + { + return "0.1"; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MySQL/MySQLManager.cs b/trunk/OpenSim/Framework/Data.MySQL/MySQLManager.cs new file mode 100644 index 0000000000..0ec976cee7 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/MySQLManager.cs @@ -0,0 +1,748 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.IO; +using System.Reflection; +using libsecondlife; +using MySql.Data.MySqlClient; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.MySQL +{ + /// + /// A MySQL Database manager + /// + internal class MySQLManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The database connection object + /// + private MySqlConnection dbcon; + + /// + /// Connection string for ADO.net + /// + private string connectionString; + + /// + /// Initialises and creates a new MySQL connection and maintains it. + /// + /// The MySQL server being connected to + /// The name of the MySQL database being used + /// The username logging into the database + /// The password for the user logging in + /// Whether to use connection pooling or not, can be one of the following: 'yes', 'true', 'no' or 'false', if unsure use 'false'. + public MySQLManager(string hostname, string database, string username, string password, string cpooling, + string port) + { + try + { + connectionString = "Server=" + hostname + ";Port=" + port + ";Database=" + database + ";User ID=" + + username + ";Password=" + password + ";Pooling=" + cpooling + ";"; + dbcon = new MySqlConnection(connectionString); + + try + { + dbcon.Open(); + } + catch(Exception e) + { + throw new Exception( "Connection error while using connection string ["+connectionString+"]", e ); + } + + m_log.Info("[MYSQL]: Connection established"); + } + catch (Exception e) + { + throw new Exception("Error initialising MySql Database: " + e.ToString()); + } + } + + /// + /// Get the connection being used + /// + public MySqlConnection Connection + { + get { return dbcon; } + } + + /// + /// Shuts down the database connection + /// + public void Close() + { + dbcon.Close(); + dbcon = null; + } + + /// + /// Reconnects to the database + /// + public void Reconnect() + { + lock (dbcon) + { + try + { + // Close the DB connection + dbcon.Close(); + // Try reopen it + dbcon = new MySqlConnection(connectionString); + dbcon.Open(); + } + catch (Exception e) + { + m_log.Error("Unable to reconnect to database " + e.ToString()); + } + } + } + + /// + /// Returns the version of this DB provider + /// + /// A string containing the DB provider + public string getVersion() + { + Module module = GetType().Module; + string dllName = module.Assembly.ManifestModule.Name; + Version dllVersion = module.Assembly.GetName().Version; + + + return + string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build, + dllVersion.Revision); + } + + + /// + /// Extract a named string resource from the embedded resources + /// + /// name of embedded resource + /// string contained within the embedded resource + private string getResourceString(string name) + { + Assembly assem = GetType().Assembly; + string[] names = assem.GetManifestResourceNames(); + + foreach (string s in names) + if (s.EndsWith(name)) + using (Stream resource = assem.GetManifestResourceStream(s)) + { + using (StreamReader resourceReader = new StreamReader(resource)) + { + string resourceString = resourceReader.ReadToEnd(); + return resourceString; + } + } + throw new Exception(string.Format("Resource '{0}' was not found", name)); + } + + /// + /// Execute a SQL statement stored in a resource, as a string + /// + /// + public void ExecuteResourceSql(string name) + { + MySqlCommand cmd = new MySqlCommand(getResourceString(name), dbcon); + cmd.ExecuteNonQuery(); + } + + /// + /// Given a list of tables, return the version of the tables, as seen in the database + /// + /// + public void GetTableVersion(Dictionary tableList) + { + lock (dbcon) + { + MySqlCommand tablesCmd = + new MySqlCommand( + "SELECT TABLE_NAME, TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=?dbname", + dbcon); + tablesCmd.Parameters.AddWithValue("?dbname", dbcon.Database); + using (MySqlDataReader tables = tablesCmd.ExecuteReader()) + { + while (tables.Read()) + { + try + { + string tableName = (string) tables["TABLE_NAME"]; + string comment = (string) tables["TABLE_COMMENT"]; + if (tableList.ContainsKey(tableName)) + { + tableList[tableName] = comment; + } + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + } + tables.Close(); + } + } + } + + + // at some time this code should be cleaned up + + /// + /// Runs a query with protection against SQL Injection by using parameterised input. + /// + /// The SQL string - replace any variables such as WHERE x = "y" with WHERE x = @y + /// The parameters - index so that @y is indexed as 'y' + /// A MySQL DB Command + public IDbCommand Query(string sql, Dictionary parameters) + { + try + { + MySqlCommand dbcommand = (MySqlCommand) dbcon.CreateCommand(); + dbcommand.CommandText = sql; + foreach (KeyValuePair param in parameters) + { + dbcommand.Parameters.AddWithValue(param.Key, param.Value); + } + + return (IDbCommand) dbcommand; + } + catch + { + lock (dbcon) + { + // Close the DB connection + try + { + dbcon.Close(); + } + catch + { + } + + // Try reopen it + try + { + dbcon = new MySqlConnection(connectionString); + dbcon.Open(); + } + catch (Exception e) + { + m_log.Error("Unable to reconnect to database " + e.ToString()); + } + + // Run the query again + try + { + MySqlCommand dbcommand = (MySqlCommand) dbcon.CreateCommand(); + dbcommand.CommandText = sql; + foreach (KeyValuePair param in parameters) + { + dbcommand.Parameters.AddWithValue(param.Key, param.Value); + } + + return (IDbCommand) dbcommand; + } + catch (Exception e) + { + // Return null if it fails. + m_log.Error("Failed during Query generation: " + e.ToString()); + return null; + } + } + } + } + + /// + /// Reads a region row from a database reader + /// + /// An active database reader + /// A region profile + public RegionProfileData readSimRow(IDataReader reader) + { + RegionProfileData retval = new RegionProfileData(); + + if (reader.Read()) + { + // Region Main + retval.regionHandle = Convert.ToUInt64(reader["regionHandle"].ToString()); + retval.regionName = (string) reader["regionName"]; + retval.UUID = new LLUUID((string) reader["uuid"]); + + // Secrets + retval.regionRecvKey = (string) reader["regionRecvKey"]; + retval.regionSecret = (string) reader["regionSecret"]; + retval.regionSendKey = (string) reader["regionSendKey"]; + + // Region Server + retval.regionDataURI = (string) reader["regionDataURI"]; + retval.regionOnline = false; // Needs to be pinged before this can be set. + retval.serverIP = (string) reader["serverIP"]; + retval.serverPort = (uint) reader["serverPort"]; + retval.serverURI = (string) reader["serverURI"]; + retval.httpPort = Convert.ToUInt32(reader["serverHttpPort"].ToString()); + retval.remotingPort = Convert.ToUInt32(reader["serverRemotingPort"].ToString()); + + // Location + retval.regionLocX = Convert.ToUInt32(reader["locX"].ToString()); + retval.regionLocY = Convert.ToUInt32(reader["locY"].ToString()); + retval.regionLocZ = Convert.ToUInt32(reader["locZ"].ToString()); + + // Neighbours - 0 = No Override + retval.regionEastOverrideHandle = Convert.ToUInt64(reader["eastOverrideHandle"].ToString()); + retval.regionWestOverrideHandle = Convert.ToUInt64(reader["westOverrideHandle"].ToString()); + retval.regionSouthOverrideHandle = Convert.ToUInt64(reader["southOverrideHandle"].ToString()); + retval.regionNorthOverrideHandle = Convert.ToUInt64(reader["northOverrideHandle"].ToString()); + + // Assets + retval.regionAssetURI = (string) reader["regionAssetURI"]; + retval.regionAssetRecvKey = (string) reader["regionAssetRecvKey"]; + retval.regionAssetSendKey = (string) reader["regionAssetSendKey"]; + + // Userserver + retval.regionUserURI = (string) reader["regionUserURI"]; + retval.regionUserRecvKey = (string) reader["regionUserRecvKey"]; + retval.regionUserSendKey = (string) reader["regionUserSendKey"]; + + // World Map Addition + string tempRegionMap = reader["regionMapTexture"].ToString(); + if (tempRegionMap != String.Empty) + { + retval.regionMapTextureID = new LLUUID(tempRegionMap); + } + else + { + retval.regionMapTextureID = LLUUID.Zero; + } + + // Added by daTwitch + // part of an initial brutish effort to provide accurate information (as per the xml region spec) + // wrt the ownership of a given region + // the (very bad) assumption is that this value is being read and handled inconsistently or + // not at all. Current strategy is to put the code in place to support the validity of this information + // and to roll forward debugging any issues from that point + // + // this particular section of the mod attempts to supply a value from the region table to the caller of 'readSimRow()' + // for the UUID of the region's owner (master avatar) + // + //retval.owner_uuid = (string) reader["owner_uuid"]; + try + { + retval.owner_uuid = new LLUUID((string)reader["owner_uuid"]); + } + catch + { + retval.owner_uuid = LLUUID.Zero; + } + // + // end of daTwitch's mods to this file + } + else + { + return null; + } + return retval; + } + + /// + /// Reads a reservation row from a database reader + /// + /// An active database reader + /// A reservation data object + public ReservationData readReservationRow(IDataReader reader) + { + ReservationData retval = new ReservationData(); + if (reader.Read()) + { + retval.gridRecvKey = (string) reader["gridRecvKey"]; + retval.gridSendKey = (string) reader["gridSendKey"]; + retval.reservationCompany = (string) reader["resCompany"]; + retval.reservationMaxX = Convert.ToInt32(reader["resXMax"].ToString()); + retval.reservationMaxY = Convert.ToInt32(reader["resYMax"].ToString()); + retval.reservationMinX = Convert.ToInt32(reader["resXMin"].ToString()); + retval.reservationMinY = Convert.ToInt32(reader["resYMin"].ToString()); + retval.reservationName = (string) reader["resName"]; + retval.status = Convert.ToInt32(reader["status"].ToString()) == 1; + retval.userUUID = new LLUUID((string) reader["userUUID"]); + } + else + { + return null; + } + return retval; + } + + /// + /// Reads an agent row from a database reader + /// + /// An active database reader + /// A user session agent + public UserAgentData readAgentRow(IDataReader reader) + { + UserAgentData retval = new UserAgentData(); + + if (reader.Read()) + { + // Agent IDs + retval.UUID = new LLUUID((string) reader["UUID"]); + retval.sessionID = new LLUUID((string) reader["sessionID"]); + retval.secureSessionID = new LLUUID((string) reader["secureSessionID"]); + + // Agent Who? + retval.agentIP = (string) reader["agentIP"]; + retval.agentPort = Convert.ToUInt32(reader["agentPort"].ToString()); + retval.agentOnline = Convert.ToBoolean(reader["agentOnline"].ToString()); + + // Login/Logout times (UNIX Epoch) + retval.loginTime = Convert.ToInt32(reader["loginTime"].ToString()); + retval.logoutTime = Convert.ToInt32(reader["logoutTime"].ToString()); + + // Current position + retval.currentRegion = (string) reader["currentRegion"]; + retval.currentHandle = Convert.ToUInt64(reader["currentHandle"].ToString()); + LLVector3.TryParse((string) reader["currentPos"], out retval.currentPos); + } + else + { + return null; + } + return retval; + } + + /// + /// Reads a user profile from an active data reader + /// + /// An active database reader + /// A user profile + public UserProfileData readUserRow(IDataReader reader) + { + UserProfileData retval = new UserProfileData(); + + if (reader.Read()) + { + retval.UUID = new LLUUID((string) reader["UUID"]); + retval.username = (string) reader["username"]; + retval.surname = (string) reader["lastname"]; + + retval.passwordHash = (string) reader["passwordHash"]; + retval.passwordSalt = (string) reader["passwordSalt"]; + + retval.homeRegion = Convert.ToUInt64(reader["homeRegion"].ToString()); + retval.homeLocation = new LLVector3( + Convert.ToSingle(reader["homeLocationX"].ToString()), + Convert.ToSingle(reader["homeLocationY"].ToString()), + Convert.ToSingle(reader["homeLocationZ"].ToString())); + retval.homeLookAt = new LLVector3( + Convert.ToSingle(reader["homeLookAtX"].ToString()), + Convert.ToSingle(reader["homeLookAtY"].ToString()), + Convert.ToSingle(reader["homeLookAtZ"].ToString())); + + retval.created = Convert.ToInt32(reader["created"].ToString()); + retval.lastLogin = Convert.ToInt32(reader["lastLogin"].ToString()); + + retval.userInventoryURI = (string) reader["userInventoryURI"]; + retval.userAssetURI = (string) reader["userAssetURI"]; + + retval.profileCanDoMask = Convert.ToUInt32(reader["profileCanDoMask"].ToString()); + retval.profileWantDoMask = Convert.ToUInt32(reader["profileWantDoMask"].ToString()); + + retval.profileAboutText = (string) reader["profileAboutText"]; + retval.profileFirstText = (string) reader["profileFirstText"]; + + retval.profileImage = new LLUUID((string) reader["profileImage"]); + retval.profileFirstImage = new LLUUID((string) reader["profileFirstImage"]); + + if( reader.IsDBNull( reader.GetOrdinal( "webLoginKey" ) ) ) + { + retval.webLoginKey = LLUUID.Zero; + } + else + { + retval.webLoginKey = new LLUUID((string)reader["webLoginKey"]); + } + } + else + { + return null; + } + return retval; + } + + + /// + /// Inserts a new row into the log database + /// + /// The daemon which triggered this event + /// Who were we operating on when this occured (region UUID, user UUID, etc) + /// The method call where the problem occured + /// The arguments passed to the method + /// How critical is this? + /// Extra message info + /// Saved successfully? + public bool insertLogRow(string serverDaemon, string target, string methodCall, string arguments, int priority, + string logMessage) + { + string sql = "INSERT INTO logs (`target`, `server`, `method`, `arguments`, `priority`, `message`) VALUES "; + sql += "(?target, ?server, ?method, ?arguments, ?priority, ?message)"; + + Dictionary parameters = new Dictionary(); + parameters["?server"] = serverDaemon; + parameters["?target"] = target; + parameters["?method"] = methodCall; + parameters["?arguments"] = arguments; + parameters["?priority"] = priority.ToString(); + parameters["?message"] = logMessage; + + bool returnval = false; + + try + { + IDbCommand result = Query(sql, parameters); + + if (result.ExecuteNonQuery() == 1) + returnval = true; + + result.Dispose(); + } + catch (Exception e) + { + m_log.Error(e.ToString()); + return false; + } + + return returnval; + } + + + /// + /// Creates a new user and inserts it into the database + /// + /// User ID + /// First part of the login + /// Second part of the login + /// A salted hash of the users password + /// The salt used for the password hash + /// A regionHandle of the users home region + /// Home region position vector + /// Home region position vector + /// Home region position vector + /// Home region 'look at' vector + /// Home region 'look at' vector + /// Home region 'look at' vector + /// Account created (unix timestamp) + /// Last login (unix timestamp) + /// Users inventory URI + /// Users asset URI + /// I can do mask + /// I want to do mask + /// Profile text + /// Firstlife text + /// UUID for profile image + /// UUID for firstlife image + /// Success? + public bool insertUserRow(LLUUID uuid, string username, string lastname, string passwordHash, + string passwordSalt, UInt64 homeRegion, float homeLocX, float homeLocY, float homeLocZ, + float homeLookAtX, float homeLookAtY, float homeLookAtZ, int created, int lastlogin, + string inventoryURI, string assetURI, uint canDoMask, uint wantDoMask, + string aboutText, string firstText, + LLUUID profileImage, LLUUID firstImage, LLUUID webLoginKey) + { + string sql = + "INSERT INTO users (`UUID`, `username`, `lastname`, `passwordHash`, `passwordSalt`, `homeRegion`, "; + sql += + "`homeLocationX`, `homeLocationY`, `homeLocationZ`, `homeLookAtX`, `homeLookAtY`, `homeLookAtZ`, `created`, "; + sql += + "`lastLogin`, `userInventoryURI`, `userAssetURI`, `profileCanDoMask`, `profileWantDoMask`, `profileAboutText`, "; + sql += "`profileFirstText`, `profileImage`, `profileFirstImage`, `webLoginKey`) VALUES "; + + sql += "(?UUID, ?username, ?lastname, ?passwordHash, ?passwordSalt, ?homeRegion, "; + sql += + "?homeLocationX, ?homeLocationY, ?homeLocationZ, ?homeLookAtX, ?homeLookAtY, ?homeLookAtZ, ?created, "; + sql += + "?lastLogin, ?userInventoryURI, ?userAssetURI, ?profileCanDoMask, ?profileWantDoMask, ?profileAboutText, "; + sql += "?profileFirstText, ?profileImage, ?profileFirstImage, ?webLoginKey)"; + + Dictionary parameters = new Dictionary(); + parameters["?UUID"] = uuid.ToString(); + parameters["?username"] = username.ToString(); + parameters["?lastname"] = lastname.ToString(); + parameters["?passwordHash"] = passwordHash.ToString(); + parameters["?passwordSalt"] = passwordSalt.ToString(); + parameters["?homeRegion"] = homeRegion.ToString(); + parameters["?homeLocationX"] = homeLocX.ToString(); + parameters["?homeLocationY"] = homeLocY.ToString(); + parameters["?homeLocationZ"] = homeLocZ.ToString(); + parameters["?homeLookAtX"] = homeLookAtX.ToString(); + parameters["?homeLookAtY"] = homeLookAtY.ToString(); + parameters["?homeLookAtZ"] = homeLookAtZ.ToString(); + parameters["?created"] = created.ToString(); + parameters["?lastLogin"] = lastlogin.ToString(); + parameters["?userInventoryURI"] = String.Empty; + parameters["?userAssetURI"] = String.Empty; + parameters["?profileCanDoMask"] = "0"; + parameters["?profileWantDoMask"] = "0"; + parameters["?profileAboutText"] = String.Empty; + parameters["?profileFirstText"] = String.Empty; + parameters["?profileImage"] = LLUUID.Zero.ToString(); + parameters["?profileFirstImage"] = LLUUID.Zero.ToString(); + parameters["?webLoginKey"] = LLUUID.Random().ToString(); + + bool returnval = false; + + try + { + IDbCommand result = Query(sql, parameters); + + if (result.ExecuteNonQuery() == 1) + returnval = true; + + result.Dispose(); + } + catch (Exception e) + { + m_log.Error(e.ToString()); + return false; + } + + return returnval; + } + + + /// + /// Inserts a new region into the database + /// + /// The region to insert + /// Success? + public bool insertRegion(RegionProfileData regiondata) + { + bool GRID_ONLY_UPDATE_NECESSARY_DATA = false; + + string sql = String.Empty; + if (GRID_ONLY_UPDATE_NECESSARY_DATA) + { + sql += "INSERT INTO "; + } + else + { + sql += "REPLACE INTO "; + } + + sql += "regions (regionHandle, regionName, uuid, regionRecvKey, regionSecret, regionSendKey, regionDataURI, "; + sql += + "serverIP, serverPort, serverURI, locX, locY, locZ, eastOverrideHandle, westOverrideHandle, southOverrideHandle, northOverrideHandle, regionAssetURI, regionAssetRecvKey, "; + + // Added by daTwitch + // part of an initial brutish effort to provide accurate information (as per the xml region spec) + // wrt the ownership of a given region + // the (very bad) assumption is that this value is being read and handled inconsistently or + // not at all. Current strategy is to put the code in place to support the validity of this information + // and to roll forward debugging any issues from that point + // + // this particular section of the mod attempts to implement the commit of a supplied value + // server for the UUID of the region's owner (master avatar). It consists of the addition of the column and value to the relevant sql, + // as well as the related parameterization + sql += + "regionAssetSendKey, regionUserURI, regionUserRecvKey, regionUserSendKey, regionMapTexture, serverHttpPort, serverRemotingPort, owner_uuid) VALUES "; + // daTwitch + + + sql += "(?regionHandle, ?regionName, ?uuid, ?regionRecvKey, ?regionSecret, ?regionSendKey, ?regionDataURI, "; + sql += + "?serverIP, ?serverPort, ?serverURI, ?locX, ?locY, ?locZ, ?eastOverrideHandle, ?westOverrideHandle, ?southOverrideHandle, ?northOverrideHandle, ?regionAssetURI, ?regionAssetRecvKey, "; + sql += + "?regionAssetSendKey, ?regionUserURI, ?regionUserRecvKey, ?regionUserSendKey, ?regionMapTexture, ?serverHttpPort, ?serverRemotingPort, ?owner_uuid)"; + // daTwitch + if (GRID_ONLY_UPDATE_NECESSARY_DATA) + { + sql += "ON DUPLICATE KEY UPDATE serverIP = ?serverIP, serverPort = ?serverPort, serverURI = ?serverURI, owner_uuid - ?owner_uuid;"; + // daTwitch + } + else + { + sql += ";"; + } + + Dictionary parameters = new Dictionary(); + + parameters["?regionHandle"] = regiondata.regionHandle.ToString(); + parameters["?regionName"] = regiondata.regionName.ToString(); + parameters["?uuid"] = regiondata.UUID.ToString(); + parameters["?regionRecvKey"] = regiondata.regionRecvKey.ToString(); + parameters["?regionSecret"] = regiondata.regionSecret.ToString(); + parameters["?regionSendKey"] = regiondata.regionSendKey.ToString(); + parameters["?regionDataURI"] = regiondata.regionDataURI.ToString(); + parameters["?serverIP"] = regiondata.serverIP.ToString(); + parameters["?serverPort"] = regiondata.serverPort.ToString(); + parameters["?serverURI"] = regiondata.serverURI.ToString(); + parameters["?locX"] = regiondata.regionLocX.ToString(); + parameters["?locY"] = regiondata.regionLocY.ToString(); + parameters["?locZ"] = regiondata.regionLocZ.ToString(); + parameters["?eastOverrideHandle"] = regiondata.regionEastOverrideHandle.ToString(); + parameters["?westOverrideHandle"] = regiondata.regionWestOverrideHandle.ToString(); + parameters["?northOverrideHandle"] = regiondata.regionNorthOverrideHandle.ToString(); + parameters["?southOverrideHandle"] = regiondata.regionSouthOverrideHandle.ToString(); + parameters["?regionAssetURI"] = regiondata.regionAssetURI.ToString(); + parameters["?regionAssetRecvKey"] = regiondata.regionAssetRecvKey.ToString(); + parameters["?regionAssetSendKey"] = regiondata.regionAssetSendKey.ToString(); + parameters["?regionUserURI"] = regiondata.regionUserURI.ToString(); + parameters["?regionUserRecvKey"] = regiondata.regionUserRecvKey.ToString(); + parameters["?regionUserSendKey"] = regiondata.regionUserSendKey.ToString(); + parameters["?regionMapTexture"] = regiondata.regionMapTextureID.ToString(); + parameters["?serverHttpPort"] = regiondata.httpPort.ToString(); + parameters["?serverRemotingPort"] = regiondata.remotingPort.ToString(); + parameters["?owner_uuid"] = regiondata.owner_uuid.ToString(); + // daTwitch + + bool returnval = false; + + try + { + IDbCommand result = Query(sql, parameters); + + //Console.WriteLine(result.CommandText); + int x; + if ((x = result.ExecuteNonQuery()) > 0) + { + returnval = true; + } + result.Dispose(); + } + catch (Exception e) + { + m_log.Error(e.ToString()); + return false; + } + + return returnval; + } + } +} diff --git a/trunk/OpenSim/Framework/Data.MySQL/MySQLUserData.cs b/trunk/OpenSim/Framework/Data.MySQL/MySQLUserData.cs new file mode 100644 index 0000000000..bc183767f6 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/MySQLUserData.cs @@ -0,0 +1,644 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Text.RegularExpressions; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.MySQL +{ + /// + /// A database interface class to a user profile storage system + /// + internal class MySQLUserData : IUserData + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Database manager for MySQL + /// + public MySQLManager database; + + private string m_agentsTableName; + private string m_usersTableName; + private string m_userFriendsTableName; + + /// + /// Loads and initialises the MySQL storage plugin + /// + public void Initialise() + { + // Load from an INI file connection details + // TODO: move this to XML? Yes, PLEASE! + + IniFile iniFile = new IniFile("mysql_connection.ini"); + string settingHostname = iniFile.ParseFileReadValue("hostname"); + string settingDatabase = iniFile.ParseFileReadValue("database"); + string settingUsername = iniFile.ParseFileReadValue("username"); + string settingPassword = iniFile.ParseFileReadValue("password"); + string settingPooling = iniFile.ParseFileReadValue("pooling"); + string settingPort = iniFile.ParseFileReadValue("port"); + + m_usersTableName = iniFile.ParseFileReadValue("userstablename"); + if( m_usersTableName == null ) + { + m_usersTableName = "users"; + } + + m_userFriendsTableName = iniFile.ParseFileReadValue("userfriendstablename"); + if (m_userFriendsTableName == null) + { + m_userFriendsTableName = "userfriends"; + } + + m_agentsTableName = iniFile.ParseFileReadValue("agentstablename"); + if (m_agentsTableName == null) + { + m_agentsTableName = "agents"; + } + + database = + new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword, settingPooling, + settingPort); + + TestTables(); + } + + #region Test and initialization code + + /// + /// Ensure that the user related tables exists and are at the latest version + /// + private void TestTables() + { + Dictionary tableList = new Dictionary(); + + tableList[m_agentsTableName] = null; + tableList[m_usersTableName] = null; + tableList[m_userFriendsTableName] = null; + database.GetTableVersion(tableList); + + UpgradeAgentsTable(tableList[m_agentsTableName]); + UpgradeUsersTable(tableList[m_usersTableName]); + UpgradeFriendsTable(tableList[m_userFriendsTableName]); + + } + + /// + /// Create or upgrade the table if necessary + /// + /// A null indicates that the table does not + /// currently exist + private void UpgradeAgentsTable(string oldVersion) + { + // null as the version, indicates that the table didn't exist + if (oldVersion == null) + { + database.ExecuteResourceSql("CreateAgentsTable.sql"); + return; + } + } + + /// + /// Create or upgrade the table if necessary + /// + /// A null indicates that the table does not + /// currently exist + private void UpgradeUsersTable(string oldVersion) + { + // null as the version, indicates that the table didn't exist + if (oldVersion == null) + { + database.ExecuteResourceSql("CreateUsersTable.sql"); + return; + } + else if (oldVersion.Contains("Rev. 1")) + { + database.ExecuteResourceSql("UpgradeUsersTableToVersion2.sql"); + return; + } + //m_log.Info("[DB]: DBVers:" + oldVersion); + } + + /// + /// Create or upgrade the table if necessary + /// + /// A null indicates that the table does not + /// currently exist + private void UpgradeFriendsTable(string oldVersion) + { + // null as the version, indicates that the table didn't exist + if (oldVersion == null) + { + database.ExecuteResourceSql("CreateUserFriendsTable.sql"); + return; + } + } + + #endregion + + // see IUserData + public UserProfileData GetUserByName(string user, string last) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["?first"] = user; + param["?second"] = last; + + IDbCommand result = + database.Query("SELECT * FROM " + m_usersTableName + " WHERE username = ?first AND lastname = ?second", param); + IDataReader reader = result.ExecuteReader(); + + UserProfileData row = database.readUserRow(reader); + + reader.Close(); + result.Dispose(); + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + #region User Friends List Data + + public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms) + { + int dtvalue = Util.UnixTimeSinceEpoch(); + + Dictionary param = new Dictionary(); + param["?ownerID"] = friendlistowner.UUID.ToString(); + param["?friendID"] = friend.UUID.ToString(); + param["?friendPerms"] = perms.ToString(); + param["?datetimestamp"] = dtvalue.ToString(); + + try + { + lock (database) + { + IDbCommand adder = + database.Query( + "INSERT INTO `" + m_userFriendsTableName + "` " + + "(`ownerID`,`friendID`,`friendPerms`,`datetimestamp`) " + + "VALUES " + + "(?ownerID,?friendID,?friendPerms,?datetimestamp)", + param); + adder.ExecuteNonQuery(); + + adder = + database.Query( + "INSERT INTO `" + m_userFriendsTableName + "` " + + "(`ownerID`,`friendID`,`friendPerms`,`datetimestamp`) " + + "VALUES " + + "(?friendID,?ownerID,?friendPerms,?datetimestamp)", + param); + adder.ExecuteNonQuery(); + + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return; + } + } + + public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend) + { + Dictionary param = new Dictionary(); + param["?ownerID"] = friendlistowner.UUID.ToString(); + param["?friendID"] = friend.UUID.ToString(); + + + try + { + lock (database) + { + IDbCommand updater = + database.Query( + "delete from " + m_userFriendsTableName + " where ownerID = ?ownerID and friendID = ?friendID", + param); + updater.ExecuteNonQuery(); + + updater = + database.Query( + "delete from " + m_userFriendsTableName + " where ownerID = ?friendID and friendID = ?ownerID", + param); + updater.ExecuteNonQuery(); + + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return; + } + } + public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms) + { + Dictionary param = new Dictionary(); + param["?ownerID"] = friendlistowner.UUID.ToString(); + param["?friendID"] = friend.UUID.ToString(); + param["?friendPerms"] = perms.ToString(); + + + try + { + lock (database) + { + IDbCommand updater = + database.Query( + "update " + m_userFriendsTableName + + " SET friendPerms = ?friendPerms " + + "where ownerID = ?ownerID and friendID = ?friendID", + param); + updater.ExecuteNonQuery(); + + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return; + } + } + + + public List GetUserFriendList(LLUUID friendlistowner) + { + List Lfli = new List(); + + Dictionary param = new Dictionary(); + param["?ownerID"] = friendlistowner.UUID.ToString(); + + try + { + lock (database) + { + //Left Join userfriends to itself + IDbCommand result = + database.Query( + "select a.ownerID,a.friendID,a.friendPerms,b.friendPerms as ownerperms from " + m_userFriendsTableName + " as a, " + m_userFriendsTableName + " as b" + + " where a.ownerID = ?ownerID and b.ownerID = a.friendID and b.friendID = a.ownerID", + param); + IDataReader reader = result.ExecuteReader(); + + + while (reader.Read()) + { + FriendListItem fli = new FriendListItem(); + fli.FriendListOwner = new LLUUID((string)reader["ownerID"]); + fli.Friend = new LLUUID((string)reader["friendID"]); + fli.FriendPerms = (uint)Convert.ToInt32(reader["friendPerms"]); + + // This is not a real column in the database table, it's a joined column from the opposite record + fli.FriendListOwnerPerms = (uint)Convert.ToInt32(reader["ownerperms"]); + + Lfli.Add(fli); + } + reader.Close(); + result.Dispose(); + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return Lfli; + } + + return Lfli; + } + + #endregion + + public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid) + { + m_log.Info("[USER]: Stub UpdateUserCUrrentRegion called"); + } + + + public List GeneratePickerResults(LLUUID queryID, string query) + { + List returnlist = new List(); + + Regex objAlphaNumericPattern = new Regex("[^a-zA-Z0-9]"); + + string[] querysplit; + querysplit = query.Split(' '); + if (querysplit.Length == 2) + { + Dictionary param = new Dictionary(); + param["?first"] = objAlphaNumericPattern.Replace(querysplit[0], String.Empty) + "%"; + param["?second"] = objAlphaNumericPattern.Replace(querysplit[1], String.Empty) + "%"; + try + { + lock (database) + { + IDbCommand result = + database.Query( + "SELECT UUID,username,lastname FROM " + m_usersTableName + " WHERE username like ?first AND lastname like ?second LIMIT 100", + param); + IDataReader reader = result.ExecuteReader(); + + + while (reader.Read()) + { + Framework.AvatarPickerAvatar user = new Framework.AvatarPickerAvatar(); + user.AvatarID = new LLUUID((string) reader["UUID"]); + user.firstName = (string) reader["username"]; + user.lastName = (string) reader["lastname"]; + returnlist.Add(user); + } + reader.Close(); + result.Dispose(); + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return returnlist; + } + } + else if (querysplit.Length == 1) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["?first"] = objAlphaNumericPattern.Replace(querysplit[0], String.Empty) + "%"; + + IDbCommand result = + database.Query( + "SELECT UUID,username,lastname FROM " + m_usersTableName + " WHERE username like ?first OR lastname like ?first LIMIT 100", + param); + IDataReader reader = result.ExecuteReader(); + + + while (reader.Read()) + { + Framework.AvatarPickerAvatar user = new Framework.AvatarPickerAvatar(); + user.AvatarID = new LLUUID((string) reader["UUID"]); + user.firstName = (string) reader["username"]; + user.lastName = (string) reader["lastname"]; + returnlist.Add(user); + } + reader.Close(); + result.Dispose(); + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return returnlist; + } + } + return returnlist; + } + + // see IUserData + public UserProfileData GetUserByUUID(LLUUID uuid) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["?uuid"] = uuid.ToString(); + + IDbCommand result = database.Query("SELECT * FROM " + m_usersTableName + " WHERE UUID = ?uuid", param); + IDataReader reader = result.ExecuteReader(); + + UserProfileData row = database.readUserRow(reader); + + reader.Close(); + result.Dispose(); + + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Returns a user session searching by name + /// + /// The account name + /// The users session + public UserAgentData GetAgentByName(string name) + { + return GetAgentByName(name.Split(' ')[0], name.Split(' ')[1]); + } + + /// + /// Returns a user session by account name + /// + /// First part of the users account name + /// Second part of the users account name + /// The users session + public UserAgentData GetAgentByName(string user, string last) + { + UserProfileData profile = GetUserByName(user, last); + return GetAgentByUUID(profile.UUID); + } + + public void StoreWebLoginKey(LLUUID AgentID, LLUUID WebLoginKey) + { + + Dictionary param = new Dictionary(); + param["?UUID"] = AgentID.UUID.ToString(); + param["?webLoginKey"] = WebLoginKey.UUID.ToString(); + + try + { + lock (database) + { + IDbCommand updater = + database.Query( + "update " + m_usersTableName + " SET webLoginKey = ?webLoginKey " + + "where UUID = ?UUID", + param); + updater.ExecuteNonQuery(); + + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return; + } + + + + + } + + /// + /// Returns an agent session by account UUID + /// + /// The accounts UUID + /// The users session + public UserAgentData GetAgentByUUID(LLUUID uuid) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["?uuid"] = uuid.ToString(); + + IDbCommand result = database.Query("SELECT * FROM " + m_agentsTableName + " WHERE UUID = ?uuid", param); + IDataReader reader = result.ExecuteReader(); + + UserAgentData row = database.readAgentRow(reader); + + reader.Close(); + result.Dispose(); + + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Creates a new users profile + /// + /// The user profile to create + public void AddNewUserProfile(UserProfileData user) + { + try + { + lock (database) + { + database.insertUserRow(user.UUID, user.username, user.surname, user.passwordHash, user.passwordSalt, + user.homeRegion, user.homeLocation.X, user.homeLocation.Y, + user.homeLocation.Z, + user.homeLookAt.X, user.homeLookAt.Y, user.homeLookAt.Z, user.created, + user.lastLogin, user.userInventoryURI, user.userAssetURI, + user.profileCanDoMask, user.profileWantDoMask, + user.profileAboutText, user.profileFirstText, user.profileImage, + user.profileFirstImage, user.webLoginKey); + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + } + } + + /// + /// Creates a new agent + /// + /// The agent to create + public void AddNewUserAgent(UserAgentData agent) + { + // Do nothing. + } + + /// + /// Updates a user profile stored in the DB + /// + /// The profile data to use to update the DB + public bool UpdateUserProfile(UserProfileData user) + { + // TODO: implement + return true; + } + + /// + /// Performs a money transfer request between two accounts + /// + /// The senders account ID + /// The receivers account ID + /// The amount to transfer + /// Success? + public bool MoneyTransferRequest(LLUUID from, LLUUID to, uint amount) + { + return false; + } + + /// + /// Performs an inventory transfer request between two accounts + /// + /// TODO: Move to inventory server + /// The senders account ID + /// The receivers account ID + /// The item to transfer + /// Success? + public bool InventoryTransferRequest(LLUUID from, LLUUID to, LLUUID item) + { + return false; + } + + /// + /// Database provider name + /// + /// Provider name + public string getName() + { + return "MySQL Userdata Interface"; + } + + /// + /// Database provider version + /// + /// provider version + public string GetVersion() + { + return "0.1"; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MySQL/Properties/AssemblyInfo.cs b/trunk/OpenSim/Framework/Data.MySQL/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..b33d319531 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* 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.Framework.Data.MySQL")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Framework.Data.MySQL")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("e49826b2-dcef-41be-a5bd-596733fa3304")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MySQL/Resources/AvatarAppearance.sql b/trunk/OpenSim/Framework/Data.MySQL/Resources/AvatarAppearance.sql new file mode 100644 index 0000000000..b638ee2d7d --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Resources/AvatarAppearance.sql @@ -0,0 +1,42 @@ +-- +-- Create schema avatar_appearance +-- + +CREATE DATABASE IF NOT EXISTS avatar_appearance; +USE avatar_appearance; + +DROP TABLE IF EXISTS `avatarappearance`; +CREATE TABLE `avatarappearance` ( + `UUID` char(36) NOT NULL, + `Serial` int(10) unsigned NOT NULL, + `WearableItem0` char(36) NOT NULL, + `WearableAsset0` char(36) NOT NULL, + `WearableItem1` char(36) NOT NULL, + `WearableAsset1` char(36) NOT NULL, + `WearableItem2` char(36) NOT NULL, + `WearableAsset2` char(36) NOT NULL, + `WearableItem3` char(36) NOT NULL, + `WearableAsset3` char(36) NOT NULL, + `WearableItem4` char(36) NOT NULL, + `WearableAsset4` char(36) NOT NULL, + `WearableItem5` char(36) NOT NULL, + `WearableAsset5` char(36) NOT NULL, + `WearableItem6` char(36) NOT NULL, + `WearableAsset6` char(36) NOT NULL, + `WearableItem7` char(36) NOT NULL, + `WearableAsset7` char(36) NOT NULL, + `WearableItem8` char(36) NOT NULL, + `WearableAsset8` char(36) NOT NULL, + `WearableItem9` char(36) NOT NULL, + `WearableAsset9` char(36) NOT NULL, + `WearableItem10` char(36) NOT NULL, + `WearableAsset10` char(36) NOT NULL, + `WearableItem11` char(36) NOT NULL, + `WearableAsset11` char(36) NOT NULL, + `WearableItem12` char(36) NOT NULL, + `WearableAsset12` char(36) NOT NULL, + + + PRIMARY KEY (`UUID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + diff --git a/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateAgentsTable.sql b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateAgentsTable.sql new file mode 100644 index 0000000000..3ef7bc9dc3 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateAgentsTable.sql @@ -0,0 +1,24 @@ +SET FOREIGN_KEY_CHECKS=0; +-- ---------------------------- +-- Table structure for agents +-- ---------------------------- +CREATE TABLE `agents` ( + `UUID` varchar(36) NOT NULL, + `sessionID` varchar(36) NOT NULL, + `secureSessionID` varchar(36) NOT NULL, + `agentIP` varchar(16) NOT NULL, + `agentPort` int(11) NOT NULL, + `agentOnline` tinyint(4) NOT NULL, + `loginTime` int(11) NOT NULL, + `logoutTime` int(11) NOT NULL, + `currentRegion` varchar(36) NOT NULL, + `currentHandle` bigint(20) unsigned NOT NULL, + `currentPos` varchar(64) NOT NULL, + PRIMARY KEY (`UUID`), + UNIQUE KEY `session` (`sessionID`), + UNIQUE KEY `ssession` (`secureSessionID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Rev. 1'; + +-- ---------------------------- +-- Records +-- ---------------------------- diff --git a/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateAssetsTable.sql b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateAssetsTable.sql new file mode 100644 index 0000000000..2c750fe283 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateAssetsTable.sql @@ -0,0 +1,11 @@ +CREATE TABLE `assets` ( + `id` binary(16) NOT NULL, + `name` varchar(64) NOT NULL, + `description` varchar(64) NOT NULL, + `assetType` tinyint(4) NOT NULL, + `invType` tinyint(4) NOT NULL, + `local` tinyint(1) NOT NULL, + `temporary` tinyint(1) NOT NULL, + `data` longblob NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Rev. 1'; \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateFoldersTable.sql b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateFoldersTable.sql new file mode 100644 index 0000000000..b5bddde67a --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateFoldersTable.sql @@ -0,0 +1,11 @@ +CREATE TABLE `inventoryfolders` ( + `folderID` varchar(36) NOT NULL default '', + `agentID` varchar(36) default NULL, + `parentFolderID` varchar(36) default NULL, + `folderName` varchar(64) default NULL, + `type` smallint NOT NULL default 0, + `version` int NOT NULL default 0, + PRIMARY KEY (`folderID`), + KEY `owner` (`agentID`), + KEY `parent` (`parentFolderID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Rev. 2'; diff --git a/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateItemsTable.sql b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateItemsTable.sql new file mode 100644 index 0000000000..53d2db0607 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateItemsTable.sql @@ -0,0 +1,18 @@ +CREATE TABLE `inventoryitems` ( + `inventoryID` varchar(36) NOT NULL default '', + `assetID` varchar(36) default NULL, + `assetType` int(11) default NULL, + `parentFolderID` varchar(36) default NULL, + `avatarID` varchar(36) default NULL, + `inventoryName` varchar(64) default NULL, + `inventoryDescription` varchar(64) default NULL, + `inventoryNextPermissions` int(10) unsigned default NULL, + `inventoryCurrentPermissions` int(10) unsigned default NULL, + `invType` int(11) default NULL, + `creatorID` varchar(36) default NULL, + `inventoryBasePermissions` int(10) unsigned NOT NULL default 0, + `inventoryEveryOnePermissions` int(10) unsigned NOT NULL default 0, + PRIMARY KEY (`inventoryID`), + KEY `owner` (`avatarID`), + KEY `folder` (`parentFolderID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Rev. 2'; diff --git a/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateLogsTable.sql b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateLogsTable.sql new file mode 100644 index 0000000000..64b3a8029a --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateLogsTable.sql @@ -0,0 +1,10 @@ +CREATE TABLE `logs` ( + `logID` int(10) unsigned NOT NULL auto_increment, + `target` varchar(36) default NULL, + `server` varchar(64) default NULL, + `method` varchar(64) default NULL, + `arguments` varchar(255) default NULL, + `priority` int(11) default NULL, + `message` text, + PRIMARY KEY (`logID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Rev. 1'; diff --git a/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateRegionsTable.sql b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateRegionsTable.sql new file mode 100644 index 0000000000..07b0d9b1a1 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateRegionsTable.sql @@ -0,0 +1,30 @@ +CREATE TABLE `regions` ( + `uuid` varchar(36) NOT NULL, + `regionHandle` bigint(20) unsigned NOT NULL, + `regionName` varchar(32) default NULL, + `regionRecvKey` varchar(128) default NULL, + `regionSendKey` varchar(128) default NULL, + `regionSecret` varchar(128) default NULL, + `regionDataURI` varchar(255) default NULL, + `serverIP` varchar(64) default NULL, + `serverPort` int(10) unsigned default NULL, + `serverURI` varchar(255) default NULL, + `locX` int(10) unsigned default NULL, + `locY` int(10) unsigned default NULL, + `locZ` int(10) unsigned default NULL, + `eastOverrideHandle` bigint(20) unsigned default NULL, + `westOverrideHandle` bigint(20) unsigned default NULL, + `southOverrideHandle` bigint(20) unsigned default NULL, + `northOverrideHandle` bigint(20) unsigned default NULL, + `regionAssetURI` varchar(255) default NULL, + `regionAssetRecvKey` varchar(128) default NULL, + `regionAssetSendKey` varchar(128) default NULL, + `regionUserURI` varchar(255) default NULL, + `regionUserRecvKey` varchar(128) default NULL, + `regionUserSendKey` varchar(128) default NULL, `regionMapTexture` varchar(36) default NULL, + `serverHttpPort` int(10) default NULL, `serverRemotingPort` int(10) default NULL, + PRIMARY KEY (`uuid`), + KEY `regionName` (`regionName`), + KEY `regionHandle` (`regionHandle`), + KEY `overrideHandles` (`eastOverrideHandle`,`westOverrideHandle`,`southOverrideHandle`,`northOverrideHandle`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Rev. 1'; diff --git a/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateUserFriendsTable.sql b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateUserFriendsTable.sql new file mode 100644 index 0000000000..8480d48884 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateUserFriendsTable.sql @@ -0,0 +1,11 @@ +SET FOREIGN_KEY_CHECKS=0; +-- ---------------------------- +-- Table structure for users +-- ---------------------------- +CREATE TABLE `userfriends` ( + `ownerID` VARCHAR(37) NOT NULL, + `friendID` VARCHAR(37) NOT NULL, + `friendPerms` INT NOT NULL, + `datetimestamp` INT NOT NULL, + UNIQUE KEY (`ownerID`, `friendID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Rev.1'; \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateUsersTable.sql b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateUsersTable.sql new file mode 100644 index 0000000000..d9e8ae202b --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Resources/CreateUsersTable.sql @@ -0,0 +1,35 @@ +SET FOREIGN_KEY_CHECKS=0; +-- ---------------------------- +-- Table structure for users +-- ---------------------------- +CREATE TABLE `users` ( + `UUID` varchar(36) NOT NULL default '', + `username` varchar(32) NOT NULL, + `lastname` varchar(32) NOT NULL, + `passwordHash` varchar(32) NOT NULL, + `passwordSalt` varchar(32) NOT NULL, + `homeRegion` bigint(20) unsigned default NULL, + `homeLocationX` float default NULL, + `homeLocationY` float default NULL, + `homeLocationZ` float default NULL, + `homeLookAtX` float default NULL, + `homeLookAtY` float default NULL, + `homeLookAtZ` float default NULL, + `created` int(11) NOT NULL, + `lastLogin` int(11) NOT NULL, + `userInventoryURI` varchar(255) default NULL, + `userAssetURI` varchar(255) default NULL, + `profileCanDoMask` int(10) unsigned default NULL, + `profileWantDoMask` int(10) unsigned default NULL, + `profileAboutText` text, + `profileFirstText` text, + `profileImage` varchar(36) default NULL, + `profileFirstImage` varchar(36) default NULL, + `webLoginKey` varchar(36) default NULL, + PRIMARY KEY (`UUID`), + UNIQUE KEY `usernames` (`username`,`lastname`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Rev. 2'; + +-- ---------------------------- +-- Records +-- ---------------------------- diff --git a/trunk/OpenSim/Framework/Data.MySQL/Resources/UpgradeFoldersTableToVersion2.sql b/trunk/OpenSim/Framework/Data.MySQL/Resources/UpgradeFoldersTableToVersion2.sql new file mode 100644 index 0000000000..b5a796490e --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Resources/UpgradeFoldersTableToVersion2.sql @@ -0,0 +1,4 @@ +ALTER TABLE `inventoryfolders` + ADD COLUMN `type` smallint NOT NULL default 0, + ADD COLUMN `version` int NOT NULL default 0, +COMMENT='Rev. 2'; diff --git a/trunk/OpenSim/Framework/Data.MySQL/Resources/UpgradeItemsTableToVersion2.sql b/trunk/OpenSim/Framework/Data.MySQL/Resources/UpgradeItemsTableToVersion2.sql new file mode 100644 index 0000000000..d1ef504b50 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Resources/UpgradeItemsTableToVersion2.sql @@ -0,0 +1,9 @@ +ALTER TABLE `inventoryitems` + CHANGE COLUMN `type` `assetType` int(11) default NULL, + ADD COLUMN `invType` int(11) default NULL, + ADD COLUMN `creatorID` varchar(36) default NULL, + ADD COLUMN `inventoryBasePermissions` int(10) unsigned NOT NULL default 0, + ADD COLUMN `inventoryEveryOnePermissions` int(10) unsigned NOT NULL default 0, +COMMENT='Rev. 2'; + +UPDATE `inventoryitems` SET invType=assetType; diff --git a/trunk/OpenSim/Framework/Data.MySQL/Resources/UpgradeUsersTableToVersion2.sql b/trunk/OpenSim/Framework/Data.MySQL/Resources/UpgradeUsersTableToVersion2.sql new file mode 100644 index 0000000000..dd21a66660 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.MySQL/Resources/UpgradeUsersTableToVersion2.sql @@ -0,0 +1,3 @@ +ALTER TABLE `users` + ADD COLUMN `webLoginKey` varchar(36) default '00000000-0000-0000-0000-000000000000' NOT NULL, +COMMENT='Rev. 2'; \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.SQLite/Properties/AssemblyInfo.cs b/trunk/OpenSim/Framework/Data.SQLite/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..5493cf5456 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.SQLite/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* 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.Framework.Data.SQLite")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Framework.Data.SQLite")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("6113d5ce-4547-49f4-9236-0dcc503457b1")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.SQLite/Resources/001_AssetStore.sql b/trunk/OpenSim/Framework/Data.SQLite/Resources/001_AssetStore.sql new file mode 100644 index 0000000000..1dc05d8cd7 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.SQLite/Resources/001_AssetStore.sql @@ -0,0 +1,13 @@ +BEGIN TRANSACTION; + +CREATE TABLE assets( + UUID varchar(255) primary key, + Name varchar(255), + Description varchar(255), + Type integer, + InvType integer, + Local integer, + Temporary integer, + Data blob); + +COMMIT; diff --git a/trunk/OpenSim/Framework/Data.SQLite/Resources/001_InventoryStore.sql b/trunk/OpenSim/Framework/Data.SQLite/Resources/001_InventoryStore.sql new file mode 100644 index 0000000000..e4951b060c --- /dev/null +++ b/trunk/OpenSim/Framework/Data.SQLite/Resources/001_InventoryStore.sql @@ -0,0 +1,26 @@ +BEGIN TRANSACTION; + +CREATE TABLE inventoryitems( + UUID varchar(255) primary key, + assetID varchar(255), + assetType integer, + invType integer, + parentFolderID varchar(255), + avatarID varchar(255), + creatorsID varchar(255), + inventoryName varchar(255), + inventoryDescription varchar(255), + inventoryNextPermissions integer, + inventoryCurrentPermissions integer, + inventoryBasePermissions integer, + inventoryEveryOnePermissions integer); + +CREATE TABLE inventoryfolders( + UUID varchar(255) primary key, + name varchar(255), + agentID varchar(255), + parentID varchar(255), + type integer, + version integer); + +COMMIT; diff --git a/trunk/OpenSim/Framework/Data.SQLite/Resources/001_RegionStore.sql b/trunk/OpenSim/Framework/Data.SQLite/Resources/001_RegionStore.sql new file mode 100644 index 0000000000..45a36facc6 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.SQLite/Resources/001_RegionStore.sql @@ -0,0 +1,121 @@ +BEGIN TRANSACTION; + +CREATE TABLE prims( + UUID varchar(255) primary key, + RegionUUID varchar(255), + ParentID integer, + CreationDate integer, + Name varchar(255), + SceneGroupID varchar(255), + Text varchar(255), + Description varchar(255), + SitName varchar(255), + TouchName varchar(255), + CreatorID varchar(255), + OwnerID varchar(255), + GroupID varchar(255), + LastOwnerID varchar(255), + OwnerMask integer, + NextOwnerMask integer, + GroupMask integer, + EveryoneMask integer, + BaseMask integer, + PositionX float, + PositionY float, + PositionZ float, + GroupPositionX float, + GroupPositionY float, + GroupPositionZ float, + VelocityX float, + VelocityY float, + VelocityZ float, + AngularVelocityX float, + AngularVelocityY float, + AngularVelocityZ float, + AccelerationX float, + AccelerationY float, + AccelerationZ float, + RotationX float, + RotationY float, + RotationZ float, + RotationW float, + ObjectFlags integer, + SitTargetOffsetX float NOT NULL default 0, + SitTargetOffsetY float NOT NULL default 0, + SitTargetOffsetZ float NOT NULL default 0, + SitTargetOrientW float NOT NULL default 0, + SitTargetOrientX float NOT NULL default 0, + SitTargetOrientY float NOT NULL default 0, + SitTargetOrientZ float NOT NULL default 0); + +CREATE TABLE primshapes(UUID varchar(255) primary key, + Shape integer, + ScaleX float, + ScaleY float, + ScaleZ float, + PCode integer, + PathBegin integer, + PathEnd integer, + PathScaleX integer, + PathScaleY integer, + PathShearX integer, + PathShearY integer, + PathSkew integer, + PathCurve integer, + PathRadiusOffset integer, + PathRevolutions integer, + PathTaperX integer, + PathTaperY integer, + PathTwist integer, + PathTwistBegin integer, + ProfileBegin integer, + ProfileEnd integer, + ProfileCurve integer, + ProfileHollow integer, + Texture blob, + ExtraParams blob); + +CREATE TABLE terrain( + RegionUUID varchar(255), + Revision integer, + Heightfield blob); + +CREATE TABLE land( + UUID varchar(255) primary key, + RegionUUID varchar(255), + LocalLandID string, + Bitmap blob, + Name varchar(255), + Desc varchar(255), + OwnerUUID varchar(36), + IsGroupOwned string, + Area integer, + AuctionID integer, + Category integer, + ClaimDate integer, + ClaimPrice integer, + GroupUUID varchar(255), + SalePrice integer, + LandStatus integer, + LandFlags string, + LandingType string, + MediaAutoScale string, + MediaTextureUUID varchar(255), + MediaURL varchar(255), + MusicURL varchar(255), + PassHours float, + PassPrice string, + SnapshotUUID varchar(255), + UserLocationX float, + UserLocationY float, + UserLocationZ float, + UserLookAtX float, + UserLookAtY float, + UserLookAtZ float); + +CREATE TABLE landaccesslist( + LandUUID varchar(255), + AccessUUID varchar(255), + Flags string); + +COMMIT; diff --git a/trunk/OpenSim/Framework/Data.SQLite/Resources/001_UserStore.sql b/trunk/OpenSim/Framework/Data.SQLite/Resources/001_UserStore.sql new file mode 100644 index 0000000000..070e340155 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.SQLite/Resources/001_UserStore.sql @@ -0,0 +1,37 @@ +BEGIN TRANSACTION; + +CREATE TABLE users( + UUID varchar(255) primary key, + username varchar(255), + surname varchar(255), + passwordHash varchar(255), + passwordSalt varchar(255), + homeRegionX integer, + homeRegionY integer, + homeLocationX float, + homeLocationY float, + homeLocationZ float, + homeLookAtX float, + homeLookAtY float, + homeLookAtZ float, + created integer, + lastLogin integer, + rootInventoryFolderID varchar(255), + userInventoryURI varchar(255), + userAssetURI varchar(255), + profileCanDoMask integer, + profileWantDoMask integer, + profileAboutText varchar(255), + profileFirstText varchar(255), + profileImage varchar(255), + profileFirstImage varchar(255), + webLoginKey text default '00000000-0000-0000-0000-000000000000'); + +CREATE TABLE userfriends( + ownerID varchar(255), + friendID varchar(255), + friendPerms integer, + ownerPerms integer, + datetimestamp integer); + +COMMIT; diff --git a/trunk/OpenSim/Framework/Data.SQLite/SQLiteAssetData.cs b/trunk/OpenSim/Framework/Data.SQLite/SQLiteAssetData.cs new file mode 100644 index 0000000000..d08ef8bc11 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.SQLite/SQLiteAssetData.cs @@ -0,0 +1,300 @@ +/* +* 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; +using System.Data; +using System.Reflection; +using libsecondlife; +using Mono.Data.SqliteClient; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.SQLite +{ + /// + /// A User storage interface for the DB4o database system + /// + public class SQLiteAssetData : SQLiteBase, IAssetProvider + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The database manager + /// + /// + /// Artificial constructor called upon plugin load + /// + private const string SelectAssetSQL = "select * from assets where UUID=:UUID"; + private const string DeleteAssetSQL = "delete from assets where UUID=:UUID"; + private const string InsertAssetSQL = "insert into assets(UUID, Name, Description, Type, InvType, Local, Temporary, Data) values(:UUID, :Name, :Description, :Type, :InvType, :Local, :Temporary, :Data)"; + private const string UpdateAssetSQL = "update assets set Name=:Name, Description=:Description, Type=:Type, InvType=:InvType, Local=:Local, Temporary=:Temporary, Data=:Data where UUID=:UUID"; + private const string assetSelect = "select * from assets"; + + private SqliteConnection m_conn; + + public void Initialise(string dbfile, string dbname) + { + m_conn = new SqliteConnection("URI=file:" + dbfile + ",version=3"); + m_conn.Open(); + TestTables(m_conn); + return; + } + + public AssetBase FetchAsset(LLUUID uuid) + { + + using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", Util.ToRawUuidString(uuid))); + using (IDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + AssetBase asset = buildAsset(reader); + reader.Close(); + return asset; + } + else + { + reader.Close(); + return null; + } + } + } + } + + public void CreateAsset(AssetBase asset) + { + m_log.Info("[SQLITE]: Creating Asset " + Util.ToRawUuidString(asset.FullID)); + if (ExistsAsset(asset.FullID)) + { + m_log.Info("[SQLITE]: Asset exists, updating instead. You should fix the caller for this!"); + UpdateAsset(asset); + } + else + { + using (SqliteCommand cmd = new SqliteCommand(InsertAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", Util.ToRawUuidString(asset.FullID))); + cmd.Parameters.Add(new SqliteParameter(":Name", asset.Name)); + cmd.Parameters.Add(new SqliteParameter(":Description", asset.Description)); + cmd.Parameters.Add(new SqliteParameter(":Type", asset.Type)); + cmd.Parameters.Add(new SqliteParameter(":InvType", asset.InvType)); + cmd.Parameters.Add(new SqliteParameter(":Local", asset.Local)); + cmd.Parameters.Add(new SqliteParameter(":Temporary", asset.Temporary)); + cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); + + cmd.ExecuteNonQuery(); + } + } + } + + public void UpdateAsset(AssetBase asset) + { + LogAssetLoad(asset); + + using (SqliteCommand cmd = new SqliteCommand(UpdateAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", Util.ToRawUuidString(asset.FullID))); + cmd.Parameters.Add(new SqliteParameter(":Name", asset.Name)); + cmd.Parameters.Add(new SqliteParameter(":Description", asset.Description)); + cmd.Parameters.Add(new SqliteParameter(":Type", asset.Type)); + cmd.Parameters.Add(new SqliteParameter(":InvType", asset.InvType)); + cmd.Parameters.Add(new SqliteParameter(":Local", asset.Local)); + cmd.Parameters.Add(new SqliteParameter(":Temporary", asset.Temporary)); + cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); + + cmd.ExecuteNonQuery(); + } + + } + + private void LogAssetLoad(AssetBase asset) + { + string temporary = asset.Temporary ? "Temporary" : "Stored"; + string local = asset.Local ? "Local" : "Remote"; + + m_log.Info("[SQLITE]: " + + string.Format("Loaded {6} {5} Asset: [{0}][{3}/{4}] \"{1}\":{2} ({7} bytes)", + asset.FullID, asset.Name, asset.Description, asset.Type, + asset.InvType, temporary, local, asset.Data.Length)); + } + + public bool ExistsAsset(LLUUID uuid) + { + using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", Util.ToRawUuidString(uuid))); + using (IDataReader reader = cmd.ExecuteReader()) + { + if(reader.Read()) + { + reader.Close(); + return true; + } + else + { + reader.Close(); + return false; + } + } + } + } + + public void DeleteAsset(LLUUID uuid) + { + using (SqliteCommand cmd = new SqliteCommand(DeleteAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", Util.ToRawUuidString(uuid))); + + cmd.ExecuteNonQuery(); + } + } + + public void CommitAssets() // force a sync to the database + { + m_log.Info("[SQLITE]: Attempting commit"); + // lock (ds) + // { + // da.Update(ds, "assets"); + // ds.AcceptChanges(); + // } + } + + /*********************************************************************** + * + * Database Definition Functions + * + * This should be db agnostic as we define them in ADO.NET terms + * + **********************************************************************/ + + private DataTable createAssetsTable() + { + DataTable assets = new DataTable("assets"); + + createCol(assets, "UUID", typeof (String)); + createCol(assets, "Name", typeof (String)); + createCol(assets, "Description", typeof (String)); + createCol(assets, "Type", typeof (Int32)); + createCol(assets, "InvType", typeof (Int32)); + createCol(assets, "Local", typeof (Boolean)); + createCol(assets, "Temporary", typeof (Boolean)); + createCol(assets, "Data", typeof (Byte[])); + // Add in contraints + assets.PrimaryKey = new DataColumn[] {assets.Columns["UUID"]}; + return assets; + } + + /*********************************************************************** + * + * Convert between ADO.NET <=> OpenSim Objects + * + * These should be database independant + * + **********************************************************************/ + + private AssetBase buildAsset(IDataReader row) + { + // TODO: this doesn't work yet because something more + // interesting has to be done to actually get these values + // back out. Not enough time to figure it out yet. + AssetBase asset = new AssetBase(); + + asset.FullID = new LLUUID((String) row["UUID"]); + asset.Name = (String) row["Name"]; + asset.Description = (String) row["Description"]; + asset.Type = Convert.ToSByte(row["Type"]); + asset.InvType = Convert.ToSByte(row["InvType"]); + asset.Local = Convert.ToBoolean(row["Local"]); + asset.Temporary = Convert.ToBoolean(row["Temporary"]); + asset.Data = (byte[]) row["Data"]; + return asset; + } + + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + private void InitDB(SqliteConnection conn) + { + string createAssets = defineTable(createAssetsTable()); + SqliteCommand pcmd = new SqliteCommand(createAssets, conn); + pcmd.ExecuteNonQuery(); + } + + private bool TestTables(SqliteConnection conn) + { + SqliteCommand cmd = new SqliteCommand(assetSelect, conn); + SqliteDataAdapter pDa = new SqliteDataAdapter(cmd); + DataSet tmpDS = new DataSet(); + try + { + pDa.Fill(tmpDS, "assets"); + } + catch (SqliteSyntaxException) + { + m_log.Info("[SQLITE]: SQLite Database doesn't exist... creating"); + InitDB(conn); + } + return true; + } + + #region IPlugin interface + + public string Version + { + get + { + Module module = GetType().Module; + string dllName = module.Assembly.ManifestModule.Name; + Version dllVersion = module.Assembly.GetName().Version; + + return + string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build, + dllVersion.Revision); + } + } + + public void Initialise() + { + Initialise("AssetStorage.db", ""); + } + + public string Name + { + get { return "SQLite Asset storage engine"; } + } + + #endregion + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.SQLite/SQLiteBase.cs b/trunk/OpenSim/Framework/Data.SQLite/SQLiteBase.cs new file mode 100644 index 0000000000..87d63a5b72 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.SQLite/SQLiteBase.cs @@ -0,0 +1,269 @@ +/* +* 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; +using System.Data; +using Mono.Data.SqliteClient; + +namespace OpenSim.Framework.Data.SQLite +{ + /// + /// A base class for methods needed by all SQLite database classes + /// + public class SQLiteBase + { + /*********************************************************************** + * + * Database Definition Functions + * + * This should be db agnostic as we define them in ADO.NET terms + * + **********************************************************************/ + + protected static void createCol(DataTable dt, string name, Type type) + { + DataColumn col = new DataColumn(name, type); + dt.Columns.Add(col); + } + + /*********************************************************************** + * + * SQL Statement Creation Functions + * + * These functions create SQL statements for update, insert, and create. + * They can probably be factored later to have a db independant + * portion and a db specific portion + * + **********************************************************************/ + + protected static SqliteCommand createInsertCommand(string table, DataTable dt) + { + /** + * This is subtle enough to deserve some commentary. + * Instead of doing *lots* and *lots of hardcoded strings + * for database definitions we'll use the fact that + * realistically all insert statements look like "insert + * into A(b, c) values(:b, :c) on the parameterized query + * front. If we just have a list of b, c, etc... we can + * generate these strings instead of typing them out. + */ + string[] cols = new string[dt.Columns.Count]; + for (int i = 0; i < dt.Columns.Count; i++) + { + DataColumn col = dt.Columns[i]; + cols[i] = col.ColumnName; + } + + string sql = "insert into " + table + "("; + sql += String.Join(", ", cols); + // important, the first ':' needs to be here, the rest get added in the join + sql += ") values (:"; + sql += String.Join(", :", cols); + sql += ")"; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + protected static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= :" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + + protected static string defineTable(DataTable dt) + { + string sql = "create table " + dt.TableName + "("; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ",\n"; + } + subsql += col.ColumnName + " " + sqliteType(col.DataType); + if (dt.PrimaryKey.Length > 0) + { + if (col == dt.PrimaryKey[0]) + { + subsql += " primary key"; + } + } + } + sql += subsql; + sql += ")"; + return sql; + } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + /// + /// This is a convenience function that collapses 5 repetitive + /// lines for defining SqliteParameters to 2 parameters: + /// column name and database type. + /// + /// It assumes certain conventions like :param as the param + /// name to replace in parametrized queries, and that source + /// version is always current version, both of which are fine + /// for us. + /// + ///a built sqlite parameter + protected static SqliteParameter createSqliteParameter(string name, Type type) + { + SqliteParameter param = new SqliteParameter(); + param.ParameterName = ":" + name; + param.DbType = dbtypeFromType(type); + param.SourceColumn = name; + param.SourceVersion = DataRowVersion.Current; + return param; + } + + /*********************************************************************** + * + * Type conversion functions + * + **********************************************************************/ + + protected static DbType dbtypeFromType(Type type) + { + if (type == typeof (String)) + { + return DbType.String; + } + else if (type == typeof (Int32)) + { + return DbType.Int32; + } + else if (type == typeof (UInt32)) + { + return DbType.UInt32; + } + else if (type == typeof (Int64)) + { + return DbType.Int64; + } + else if (type == typeof (UInt64)) + { + return DbType.UInt64; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Boolean)) + { + return DbType.Boolean; + } + else if (type == typeof (Byte[])) + { + return DbType.Binary; + } + else + { + return DbType.String; + } + } + + // this is something we'll need to implement for each db + // slightly differently. + protected static string sqliteType(Type type) + { + if (type == typeof (String)) + { + return "varchar(255)"; + } + else if (type == typeof (Int32)) + { + return "integer"; + } + else if (type == typeof (UInt32)) + { + return "integer"; + } + else if (type == typeof (Int64)) + { + return "varchar(255)"; + } + else if (type == typeof (UInt64)) + { + return "varchar(255)"; + } + else if (type == typeof (Double)) + { + return "float"; + } + else if (type == typeof (Boolean)) + { + return "integer"; + } + else if (type == typeof (Byte[])) + { + return "blob"; + } + else + { + return "string"; + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.SQLite/SQLiteGridData.cs b/trunk/OpenSim/Framework/Data.SQLite/SQLiteGridData.cs new file mode 100644 index 0000000000..4b790c387b --- /dev/null +++ b/trunk/OpenSim/Framework/Data.SQLite/SQLiteGridData.cs @@ -0,0 +1,205 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Security.Cryptography; +using System.Text; +using libsecondlife; + +namespace OpenSim.Framework.Data.SQLite +{ + /// + /// A Grid Interface to the SQLite database + /// + public class SQLiteGridData : IGridData + { + /// + /// A database manager + /// + private SQLiteManager database; + + /// + /// Initialises the Grid Interface + /// + public void Initialise() + { + database = new SQLiteManager("localhost", "db", "user", "password", "false"); + } + + /// + /// Shuts down the grid interface + /// + public void Close() + { + database.Close(); + } + + /// + /// Returns the name of this grid interface + /// + /// A string containing the grid interface + public string getName() + { + return "SQLite OpenGridData"; + } + + /// + /// Returns the version of this grid interface + /// + /// A string containing the version + public string getVersion() + { + return "0.1"; + } + + /// + /// Returns a list of regions within the specified ranges + /// + /// minimum X coordinate + /// minimum Y coordinate + /// maximum X coordinate + /// maximum Y coordinate + /// An array of region profiles + public RegionProfileData[] GetProfilesInRange(uint a, uint b, uint c, uint d) + { + return null; + } + + /// + /// Returns a sim profile from it's location + /// + /// Region location handle + /// Sim profile + public RegionProfileData GetProfileByHandle(ulong handle) + { + Dictionary param = new Dictionary(); + param["handle"] = handle.ToString(); + + IDbCommand result = database.Query("SELECT * FROM regions WHERE handle = @handle", param); + IDataReader reader = result.ExecuteReader(); + + RegionProfileData row = database.getRow(reader); + reader.Close(); + result.Dispose(); + + return row; + } + + /// + /// Returns a sim profile from it's UUID + /// + /// The region UUID + /// The sim profile + public RegionProfileData GetProfileByLLUUID(LLUUID uuid) + { + Dictionary param = new Dictionary(); + param["uuid"] = uuid.ToString(); + + IDbCommand result = database.Query("SELECT * FROM regions WHERE uuid = @uuid", param); + IDataReader reader = result.ExecuteReader(); + + RegionProfileData row = database.getRow(reader); + reader.Close(); + result.Dispose(); + + return row; + } + + /// + /// // Returns a list of avatar and UUIDs that match the query + /// + public List GeneratePickerResults(LLUUID queryID, string query) + { + //Do nothing yet + List returnlist = new List(); + return returnlist; + } + + /// + /// Adds a new specified region to the database + /// + /// The profile to add + /// A dataresponse enum indicating success + public DataResponse AddProfile(RegionProfileData profile) + { + if (database.insertRow(profile)) + { + return DataResponse.RESPONSE_OK; + } + else + { + return DataResponse.RESPONSE_ERROR; + } + } + + /// + /// DEPRECIATED. Attempts to authenticate a region by comparing a shared secret. + /// + /// The UUID of the challenger + /// The attempted regionHandle of the challenger + /// The secret + /// Whether the secret and regionhandle match the database entry for UUID + public bool AuthenticateSim(LLUUID uuid, ulong handle, string authkey) + { + bool throwHissyFit = false; // Should be true by 1.0 + + if (throwHissyFit) + throw new Exception("CRYPTOWEAK AUTHENTICATE: Refusing to authenticate due to replay potential."); + + RegionProfileData data = GetProfileByLLUUID(uuid); + + return (handle == data.regionHandle && authkey == data.regionSecret); + } + + /// + /// NOT YET FUNCTIONAL. Provides a cryptographic authentication of a region + /// + /// This requires a security audit. + /// + /// + /// + /// + /// + public bool AuthenticateSim(LLUUID uuid, ulong handle, string authhash, string challenge) + { + SHA512Managed HashProvider = new SHA512Managed(); + ASCIIEncoding TextProvider = new ASCIIEncoding(); + + byte[] stream = TextProvider.GetBytes(uuid.ToString() + ":" + handle.ToString() + ":" + challenge); + byte[] hash = HashProvider.ComputeHash(stream); + + return false; + } + + public ReservationData GetReservationAtPoint(uint x, uint y) + { + return null; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.SQLite/SQLiteInventoryStore.cs b/trunk/OpenSim/Framework/Data.SQLite/SQLiteInventoryStore.cs new file mode 100644 index 0000000000..5e5d1e480f --- /dev/null +++ b/trunk/OpenSim/Framework/Data.SQLite/SQLiteInventoryStore.cs @@ -0,0 +1,634 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using libsecondlife; +using Mono.Data.SqliteClient; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.SQLite +{ + public class SQLiteInventoryStore : SQLiteBase, IInventoryData + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private const string invItemsSelect = "select * from inventoryitems"; + private const string invFoldersSelect = "select * from inventoryfolders"; + + private DataSet ds; + private SqliteDataAdapter invItemsDa; + private SqliteDataAdapter invFoldersDa; + + /// + /// Initialises the interface + /// + public void Initialise() + { + Initialise("inventoryStore.db", "inventoryDatabase"); + } + + public void Initialise(string dbfile, string dbname) + { + string connectionString = "URI=file:" + dbfile + ",version=3"; + + m_log.Info("[Inventory]: Sqlite - connecting: " + dbfile); + SqliteConnection conn = new SqliteConnection(connectionString); + + TestTables(conn); + + SqliteCommand itemsSelectCmd = new SqliteCommand(invItemsSelect, conn); + invItemsDa = new SqliteDataAdapter(itemsSelectCmd); + // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); + + SqliteCommand foldersSelectCmd = new SqliteCommand(invFoldersSelect, conn); + invFoldersDa = new SqliteDataAdapter(foldersSelectCmd); + + ds = new DataSet(); + + ds.Tables.Add(createInventoryFoldersTable()); + invFoldersDa.Fill(ds.Tables["inventoryfolders"]); + setupFoldersCommands(invFoldersDa, conn); + m_log.Info("[DATASTORE]: Populated Intentory Folders Definitions"); + + ds.Tables.Add(createInventoryItemsTable()); + invItemsDa.Fill(ds.Tables["inventoryitems"]); + setupItemsCommands(invItemsDa, conn); + m_log.Info("[DATASTORE]: Populated Intentory Items Definitions"); + + ds.AcceptChanges(); + } + + public InventoryItemBase buildItem(DataRow row) + { + InventoryItemBase item = new InventoryItemBase(); + item.inventoryID = new LLUUID((string) row["UUID"]); + item.assetID = new LLUUID((string) row["assetID"]); + item.assetType = Convert.ToInt32(row["assetType"]); + item.invType = Convert.ToInt32(row["invType"]); + item.parentFolderID = new LLUUID((string) row["parentFolderID"]); + item.avatarID = new LLUUID((string) row["avatarID"]); + item.creatorsID = new LLUUID((string) row["creatorsID"]); + item.inventoryName = (string) row["inventoryName"]; + item.inventoryDescription = (string) row["inventoryDescription"]; + + item.inventoryNextPermissions = Convert.ToUInt32(row["inventoryNextPermissions"]); + item.inventoryCurrentPermissions = Convert.ToUInt32(row["inventoryCurrentPermissions"]); + item.inventoryBasePermissions = Convert.ToUInt32(row["inventoryBasePermissions"]); + item.inventoryEveryOnePermissions = Convert.ToUInt32(row["inventoryEveryOnePermissions"]); + return item; + } + + private void fillItemRow(DataRow row, InventoryItemBase item) + { + row["UUID"] = Util.ToRawUuidString(item.inventoryID); + row["assetID"] = Util.ToRawUuidString(item.assetID); + row["assetType"] = item.assetType; + row["invType"] = item.invType; + row["parentFolderID"] = Util.ToRawUuidString(item.parentFolderID); + row["avatarID"] = Util.ToRawUuidString(item.avatarID); + row["creatorsID"] = Util.ToRawUuidString(item.creatorsID); + row["inventoryName"] = item.inventoryName; + row["inventoryDescription"] = item.inventoryDescription; + + row["inventoryNextPermissions"] = item.inventoryNextPermissions; + row["inventoryCurrentPermissions"] = item.inventoryCurrentPermissions; + row["inventoryBasePermissions"] = item.inventoryBasePermissions; + row["inventoryEveryOnePermissions"] = item.inventoryEveryOnePermissions; + } + + private void addFolder(InventoryFolderBase folder) + { + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + + DataRow inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(folder.folderID)); + if (inventoryRow == null) + { + inventoryRow = inventoryFolderTable.NewRow(); + fillFolderRow(inventoryRow, folder); + inventoryFolderTable.Rows.Add(inventoryRow); + } + else + { + fillFolderRow(inventoryRow, folder); + } + + invFoldersDa.Update(ds, "inventoryfolders"); + } + + private void moveFolder(InventoryFolderBase folder) + { + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + + DataRow inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(folder.folderID)); + if (inventoryRow == null) + { + inventoryRow = inventoryFolderTable.NewRow(); + fillFolderRow(inventoryRow, folder); + inventoryFolderTable.Rows.Add(inventoryRow); + } + else + { + moveFolderRow(inventoryRow, folder); + } + + invFoldersDa.Update(ds, "inventoryfolders"); + } + + private void addItem(InventoryItemBase item) + { + DataTable inventoryItemTable = ds.Tables["inventoryitems"]; + + DataRow inventoryRow = inventoryItemTable.Rows.Find(Util.ToRawUuidString(item.inventoryID)); + if (inventoryRow == null) + { + inventoryRow = inventoryItemTable.NewRow(); + fillItemRow(inventoryRow, item); + inventoryItemTable.Rows.Add(inventoryRow); + } + else + { + fillItemRow(inventoryRow, item); + } + invItemsDa.Update(ds, "inventoryitems"); + } + + public void Shutdown() + { + // TODO: DataSet commit + } + + /// + /// Closes the interface + /// + public void Close() + { + } + + /// + /// The plugin being loaded + /// + /// A string containing the plugin name + public string getName() + { + return "SQLite Inventory Data Interface"; + } + + /// + /// The plugins version + /// + /// A string containing the plugin version + public string getVersion() + { + Module module = GetType().Module; + string dllName = module.Assembly.ManifestModule.Name; + Version dllVersion = module.Assembly.GetName().Version; + + + return + string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build, + dllVersion.Revision); + } + + /// + /// Returns a list of inventory items contained within the specified folder + /// + /// The UUID of the target folder + /// A List of InventoryItemBase items + public List getInventoryInFolder(LLUUID folderID) + { + List retval = new List(); + DataTable inventoryItemTable = ds.Tables["inventoryitems"]; + string selectExp = "parentFolderID = '" + Util.ToRawUuidString(folderID) + "'"; + DataRow[] rows = inventoryItemTable.Select(selectExp); + foreach (DataRow row in rows) + { + retval.Add(buildItem(row)); + } + + return retval; + } + + /// + /// Returns a list of the root folders within a users inventory + /// + /// The user whos inventory is to be searched + /// A list of folder objects + public List getUserRootFolders(LLUUID user) + { + return new List(); + } + + // see InventoryItemBase.getUserRootFolder + public InventoryFolderBase getUserRootFolder(LLUUID user) + { + List folders = new List(); + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + string selectExp = "agentID = '" + Util.ToRawUuidString(user) + "' AND parentID = '" + + Util.ToRawUuidString(LLUUID.Zero) + "'"; + DataRow[] rows = inventoryFolderTable.Select(selectExp); + foreach (DataRow row in rows) + { + folders.Add(buildFolder(row)); + } + + // There should only ever be one root folder for a user. However, if there's more + // than one we'll simply use the first one rather than failing. It would be even + // nicer to print some message to this effect, but this feels like it's too low a + // to put such a message out, and it's too minor right now to spare the time to + // suitably refactor. + if (folders.Count > 0) + { + return folders[0]; + } + + return null; + } + + /// + /// Append a list of all the child folders of a parent folder + /// + /// list where folders will be appended + /// ID of parent + protected void getInventoryFolders(ref List folders, LLUUID parentID) + { + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + string selectExp = "parentID = '" + Util.ToRawUuidString(parentID) + "'"; + DataRow[] rows = inventoryFolderTable.Select(selectExp); + foreach (DataRow row in rows) + { + folders.Add(buildFolder(row)); + } + } + + /// + /// Returns a list of inventory folders contained in the folder 'parentID' + /// + /// The folder to get subfolders for + /// A list of inventory folders + public List getInventoryFolders(LLUUID parentID) + { + List folders = new List(); + getInventoryFolders(ref folders, Util.ToRawUuidString(parentID)); + return folders; + } + + /// + /// Returns all child folders in the hierarchy from the parent folder and down + /// + /// The folder to get subfolders for + /// A list of inventory folders + protected List getFolderHierarchy(LLUUID parentID) + { + List folders = new List(); + getInventoryFolders(ref folders, Util.ToRawUuidString(parentID)); + + for (int i = 0; i < folders.Count; i++) + getInventoryFolders(ref folders, Util.ToRawUuidString(folders[i].folderID)); + + return folders; + } + + /// + /// Returns an inventory item by its UUID + /// + /// The UUID of the item to be returned + /// A class containing item information + public InventoryItemBase getInventoryItem(LLUUID item) + { + DataRow row = ds.Tables["inventoryitems"].Rows.Find(Util.ToRawUuidString(item)); + if (row != null) + { + return buildItem(row); + } + else + { + return null; + } + } + + /// + /// Returns a specified inventory folder by its UUID + /// + /// The UUID of the folder to be returned + /// A class containing folder information + public InventoryFolderBase getInventoryFolder(LLUUID folder) + { + // TODO: Deep voodoo here. If you enable this code then + // multi region breaks. No idea why, but I figured it was + // better to leave multi region at this point. It does mean + // that you don't get to see system textures why creating + // clothes and the like. :( + + DataRow row = ds.Tables["inventoryfolders"].Rows.Find(Util.ToRawUuidString(folder)); + if (row != null) + { + return buildFolder(row); + } + else + { + return null; + } + } + + /// + /// Creates a new inventory item based on item + /// + /// The item to be created + public void addInventoryItem(InventoryItemBase item) + { + addItem(item); + } + + /// + /// Updates an inventory item with item (updates based on ID) + /// + /// The updated item + public void updateInventoryItem(InventoryItemBase item) + { + addItem(item); + } + + /// + /// + /// + /// + public void deleteInventoryItem(LLUUID itemID) + { + DataTable inventoryItemTable = ds.Tables["inventoryitems"]; + + DataRow inventoryRow = inventoryItemTable.Rows.Find(Util.ToRawUuidString(itemID)); + if (inventoryRow != null) + { + inventoryRow.Delete(); + } + + invItemsDa.Update(ds, "inventoryitems"); + } + + + /// + /// Delete all items in the specified folder + /// + /// id of the folder, whose item content should be deleted + //!TODO, this is horribly inefficient, but I don't want to ruin the overall structure of this implementation + private void deleteItemsInFolder(LLUUID folderId) + { + List items = getInventoryInFolder(Util.ToRawUuidString(folderId)); + + foreach (InventoryItemBase i in items) + deleteInventoryItem(Util.ToRawUuidString(i.inventoryID)); + } + + /// + /// Adds a new folder specified by folder + /// + /// The inventory folder + public void addInventoryFolder(InventoryFolderBase folder) + { + addFolder(folder); + } + + /// + /// Updates a folder based on its ID with folder + /// + /// The inventory folder + public void updateInventoryFolder(InventoryFolderBase folder) + { + addFolder(folder); + } + + /// + /// Moves a folder based on its ID with folder + /// + /// The inventory folder + public void moveInventoryFolder(InventoryFolderBase folder) + { + moveFolder(folder); + } + + /// + /// Delete a folder + /// + /// + /// This will clean-up any child folders and child items as well + /// + /// + public void deleteInventoryFolder(LLUUID folderID) + { + List subFolders = getFolderHierarchy(Util.ToRawUuidString(folderID)); + + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + DataRow inventoryRow; + + //Delete all sub-folders + foreach (InventoryFolderBase f in subFolders) + { + inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(f.folderID)); + if (inventoryRow != null) + { + deleteItemsInFolder(Util.ToRawUuidString(f.folderID)); + inventoryRow.Delete(); + } + } + + //Delete the actual row + inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(folderID)); + if (inventoryRow != null) + { + deleteItemsInFolder(Util.ToRawUuidString(folderID)); + inventoryRow.Delete(); + } + + invFoldersDa.Update(ds, "inventoryfolders"); + } + + /*********************************************************************** + * + * Data Table definitions + * + **********************************************************************/ + + private static DataTable createInventoryItemsTable() + { + DataTable inv = new DataTable("inventoryitems"); + + createCol(inv, "UUID", typeof (String)); //inventoryID + createCol(inv, "assetID", typeof (String)); + createCol(inv, "assetType", typeof (Int32)); + createCol(inv, "invType", typeof (Int32)); + createCol(inv, "parentFolderID", typeof (String)); + createCol(inv, "avatarID", typeof (String)); + createCol(inv, "creatorsID", typeof (String)); + + createCol(inv, "inventoryName", typeof (String)); + createCol(inv, "inventoryDescription", typeof (String)); + // permissions + createCol(inv, "inventoryNextPermissions", typeof (Int32)); + createCol(inv, "inventoryCurrentPermissions", typeof (Int32)); + createCol(inv, "inventoryBasePermissions", typeof (Int32)); + createCol(inv, "inventoryEveryOnePermissions", typeof (Int32)); + + inv.PrimaryKey = new DataColumn[] {inv.Columns["UUID"]}; + return inv; + } + + private DataTable createInventoryFoldersTable() + { + DataTable fol = new DataTable("inventoryfolders"); + + createCol(fol, "UUID", typeof (String)); //folderID + createCol(fol, "name", typeof (String)); + createCol(fol, "agentID", typeof (String)); + createCol(fol, "parentID", typeof (String)); + createCol(fol, "type", typeof (Int32)); + createCol(fol, "version", typeof (Int32)); + + fol.PrimaryKey = new DataColumn[] {fol.Columns["UUID"]}; + return fol; + } + + private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("inventoryitems", ds.Tables["inventoryitems"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("inventoryitems", "UUID=:UUID", ds.Tables["inventoryitems"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from inventoryitems where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + private void setupFoldersCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("inventoryfolders", ds.Tables["inventoryfolders"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("inventoryfolders", "UUID=:UUID", ds.Tables["inventoryfolders"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from inventoryfolders where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + private InventoryFolderBase buildFolder(DataRow row) + { + InventoryFolderBase folder = new InventoryFolderBase(); + folder.folderID = new LLUUID((string) row["UUID"]); + folder.name = (string) row["name"]; + folder.agentID = new LLUUID((string) row["agentID"]); + folder.parentID = new LLUUID((string) row["parentID"]); + folder.type = Convert.ToInt16(row["type"]); + folder.version = Convert.ToUInt16(row["version"]); + return folder; + } + + private void fillFolderRow(DataRow row, InventoryFolderBase folder) + { + row["UUID"] = Util.ToRawUuidString(folder.folderID); + row["name"] = folder.name; + row["agentID"] = Util.ToRawUuidString(folder.agentID); + row["parentID"] = Util.ToRawUuidString(folder.parentID); + row["type"] = folder.type; + row["version"] = folder.version; + } + + private void moveFolderRow(DataRow row, InventoryFolderBase folder) + { + row["UUID"] = Util.ToRawUuidString(folder.folderID); + row["parentID"] = Util.ToRawUuidString(folder.parentID); + } + + /*********************************************************************** + * + * Test and Initialization code + * + **********************************************************************/ + + private void InitDB(SqliteConnection conn) + { + string createInventoryItems = defineTable(createInventoryItemsTable()); + string createInventoryFolders = defineTable(createInventoryFoldersTable()); + + SqliteCommand pcmd = new SqliteCommand(createInventoryItems, conn); + SqliteCommand scmd = new SqliteCommand(createInventoryFolders, conn); + conn.Open(); + pcmd.ExecuteNonQuery(); + scmd.ExecuteNonQuery(); + conn.Close(); + } + + private bool TestTables(SqliteConnection conn) + { + SqliteCommand invItemsSelectCmd = new SqliteCommand(invItemsSelect, conn); + SqliteDataAdapter pDa = new SqliteDataAdapter(invItemsSelectCmd); + SqliteCommand invFoldersSelectCmd = new SqliteCommand(invFoldersSelect, conn); + SqliteDataAdapter sDa = new SqliteDataAdapter(invFoldersSelectCmd); + + DataSet tmpDS = new DataSet(); + try + { + pDa.Fill(tmpDS, "inventoryitems"); + sDa.Fill(tmpDS, "inventoryfolders"); + } + catch (SqliteSyntaxException) + { + m_log.Info("[DATASTORE]: SQLite Database doesn't exist... creating"); + InitDB(conn); + } + + pDa.Fill(tmpDS, "inventoryitems"); + sDa.Fill(tmpDS, "inventoryfolders"); + + foreach (DataColumn col in createInventoryItemsTable().Columns) + { + if (! tmpDS.Tables["inventoryitems"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing required column:" + col.ColumnName); + return false; + } + } + foreach (DataColumn col in createInventoryFoldersTable().Columns) + { + if (! tmpDS.Tables["inventoryfolders"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing required column:" + col.ColumnName); + return false; + } + } + return true; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.SQLite/SQLiteManager.cs b/trunk/OpenSim/Framework/Data.SQLite/SQLiteManager.cs new file mode 100644 index 0000000000..c77a8f601b --- /dev/null +++ b/trunk/OpenSim/Framework/Data.SQLite/SQLiteManager.cs @@ -0,0 +1,280 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Data.SQLite; +using libsecondlife; +using Mono.Data.SqliteClient; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.SQLite +{ + internal class SQLiteManager : SQLiteBase + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private IDbConnection dbcon; + + /// + /// Initialises and creates a new SQLite connection and maintains it. + /// + /// The SQLite server being connected to + /// The name of the SQLite database being used + /// The username logging into the database + /// The password for the user logging in + /// Whether to use connection pooling or not, can be one of the following: 'yes', 'true', 'no' or 'false', if unsure use 'false'. + public SQLiteManager(string hostname, string database, string username, string password, string cpooling) + { + try + { + string connectionString = "URI=file:GridServerSqlite.db;"; + dbcon = new SQLiteConnection(connectionString); + + dbcon.Open(); + } + catch (Exception e) + { + throw new Exception("Error initialising SQLite Database: " + e.ToString()); + } + } + + /// + /// Shuts down the database connection + /// + public void Close() + { + dbcon.Close(); + dbcon = null; + } + + /// + /// Runs a query with protection against SQL Injection by using parameterised input. + /// + /// The SQL string - replace any variables such as WHERE x = "y" with WHERE x = @y + /// The parameters - index so that @y is indexed as 'y' + /// A SQLite DB Command + public IDbCommand Query(string sql, Dictionary parameters) + { + SQLiteCommand dbcommand = (SQLiteCommand) dbcon.CreateCommand(); + dbcommand.CommandText = sql; + foreach (KeyValuePair param in parameters) + { + SQLiteParameter paramx = new SQLiteParameter(param.Key, param.Value); + dbcommand.Parameters.Add(paramx); + } + + return (IDbCommand) dbcommand; + } + + private bool TestTables(SQLiteConnection conn) + { + SQLiteCommand cmd = new SQLiteCommand("SELECT * FROM regions", conn); + SQLiteDataAdapter pDa = new SQLiteDataAdapter(cmd); + DataSet tmpDS = new DataSet(); + try + { + pDa.Fill(tmpDS, "regions"); + } + catch (SqliteSyntaxException) + { + m_log.Info("[DATASTORE]: SQLite Database doesn't exist... creating"); + InitDB(conn); + } + return true; + } + + private DataTable createRegionsTable() + { + DataTable regions = new DataTable("regions"); + + createCol(regions, "regionHandle", typeof (ulong)); + createCol(regions, "regionName", typeof (String)); + createCol(regions, "uuid", typeof (String)); + + createCol(regions, "regionRecvKey", typeof (String)); + createCol(regions, "regionSecret", typeof (String)); + createCol(regions, "regionSendKey", typeof (String)); + + createCol(regions, "regionDataURI", typeof (String)); + createCol(regions, "serverIP", typeof (String)); + createCol(regions, "serverPort", typeof (String)); + createCol(regions, "serverURI", typeof (String)); + + + createCol(regions, "locX", typeof (uint)); + createCol(regions, "locY", typeof (uint)); + createCol(regions, "locZ", typeof (uint)); + + createCol(regions, "eastOverrideHandle", typeof (ulong)); + createCol(regions, "westOverrideHandle", typeof (ulong)); + createCol(regions, "southOverrideHandle", typeof (ulong)); + createCol(regions, "northOverrideHandle", typeof (ulong)); + + createCol(regions, "regionAssetURI", typeof (String)); + createCol(regions, "regionAssetRecvKey", typeof (String)); + createCol(regions, "regionAssetSendKey", typeof (String)); + + createCol(regions, "regionUserURI", typeof (String)); + createCol(regions, "regionUserRecvKey", typeof (String)); + createCol(regions, "regionUserSendKey", typeof (String)); + + // Add in contraints + regions.PrimaryKey = new DataColumn[] {regions.Columns["UUID"]}; + return regions; + } + + private void InitDB(SQLiteConnection conn) + { + string createUsers = defineTable(createRegionsTable()); + SQLiteCommand pcmd = new SQLiteCommand(createUsers, conn); + conn.Open(); + pcmd.ExecuteNonQuery(); + conn.Close(); + } + + + /// + /// Reads a region row from a database reader + /// + /// An active database reader + /// A region profile + public RegionProfileData getRow(IDataReader reader) + { + RegionProfileData retval = new RegionProfileData(); + + if (reader.Read()) + { + // Region Main + retval.regionHandle = (ulong) reader["regionHandle"]; + retval.regionName = (string) reader["regionName"]; + retval.UUID = new LLUUID((string) reader["uuid"]); + + // Secrets + retval.regionRecvKey = (string) reader["regionRecvKey"]; + retval.regionSecret = (string) reader["regionSecret"]; + retval.regionSendKey = (string) reader["regionSendKey"]; + + // Region Server + retval.regionDataURI = (string) reader["regionDataURI"]; + retval.regionOnline = false; // Needs to be pinged before this can be set. + retval.serverIP = (string) reader["serverIP"]; + retval.serverPort = (uint) reader["serverPort"]; + retval.serverURI = (string) reader["serverURI"]; + + // Location + retval.regionLocX = (uint) ((int) reader["locX"]); + retval.regionLocY = (uint) ((int) reader["locY"]); + retval.regionLocZ = (uint) ((int) reader["locZ"]); + + // Neighbours - 0 = No Override + retval.regionEastOverrideHandle = (ulong) reader["eastOverrideHandle"]; + retval.regionWestOverrideHandle = (ulong) reader["westOverrideHandle"]; + retval.regionSouthOverrideHandle = (ulong) reader["southOverrideHandle"]; + retval.regionNorthOverrideHandle = (ulong) reader["northOverrideHandle"]; + + // Assets + retval.regionAssetURI = (string) reader["regionAssetURI"]; + retval.regionAssetRecvKey = (string) reader["regionAssetRecvKey"]; + retval.regionAssetSendKey = (string) reader["regionAssetSendKey"]; + + // Userserver + retval.regionUserURI = (string) reader["regionUserURI"]; + retval.regionUserRecvKey = (string) reader["regionUserRecvKey"]; + retval.regionUserSendKey = (string) reader["regionUserSendKey"]; + } + else + { + throw new Exception("No rows to return"); + } + return retval; + } + + /// + /// Inserts a new region into the database + /// + /// The region to insert + /// Success? + public bool insertRow(RegionProfileData profile) + { + string sql = + "REPLACE INTO regions VALUES (regionHandle, regionName, uuid, regionRecvKey, regionSecret, regionSendKey, regionDataURI, "; + sql += + "serverIP, serverPort, serverURI, locX, locY, locZ, eastOverrideHandle, westOverrideHandle, southOverrideHandle, northOverrideHandle, regionAssetURI, regionAssetRecvKey, "; + sql += "regionAssetSendKey, regionUserURI, regionUserRecvKey, regionUserSendKey) VALUES "; + + sql += "(@regionHandle, @regionName, @uuid, @regionRecvKey, @regionSecret, @regionSendKey, @regionDataURI, "; + sql += + "@serverIP, @serverPort, @serverURI, @locX, @locY, @locZ, @eastOverrideHandle, @westOverrideHandle, @southOverrideHandle, @northOverrideHandle, @regionAssetURI, @regionAssetRecvKey, "; + sql += "@regionAssetSendKey, @regionUserURI, @regionUserRecvKey, @regionUserSendKey);"; + + Dictionary parameters = new Dictionary(); + + parameters["regionHandle"] = profile.regionHandle.ToString(); + parameters["regionName"] = profile.regionName; + parameters["uuid"] = profile.UUID.ToString(); + parameters["regionRecvKey"] = profile.regionRecvKey; + parameters["regionSendKey"] = profile.regionSendKey; + parameters["regionDataURI"] = profile.regionDataURI; + parameters["serverIP"] = profile.serverIP; + parameters["serverPort"] = profile.serverPort.ToString(); + parameters["serverURI"] = profile.serverURI; + parameters["locX"] = profile.regionLocX.ToString(); + parameters["locY"] = profile.regionLocY.ToString(); + parameters["locZ"] = profile.regionLocZ.ToString(); + parameters["eastOverrideHandle"] = profile.regionEastOverrideHandle.ToString(); + parameters["westOverrideHandle"] = profile.regionWestOverrideHandle.ToString(); + parameters["northOverrideHandle"] = profile.regionNorthOverrideHandle.ToString(); + parameters["southOverrideHandle"] = profile.regionSouthOverrideHandle.ToString(); + parameters["regionAssetURI"] = profile.regionAssetURI; + parameters["regionAssetRecvKey"] = profile.regionAssetRecvKey; + parameters["regionAssetSendKey"] = profile.regionAssetSendKey; + parameters["regionUserURI"] = profile.regionUserURI; + parameters["regionUserRecvKey"] = profile.regionUserRecvKey; + parameters["regionUserSendKey"] = profile.regionUserSendKey; + + bool returnval = false; + + try + { + IDbCommand result = Query(sql, parameters); + + if (result.ExecuteNonQuery() == 1) + returnval = true; + + result.Dispose(); + } + catch (Exception) + { + return false; + } + + return returnval; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data.SQLite/SQLiteRegionData.cs b/trunk/OpenSim/Framework/Data.SQLite/SQLiteRegionData.cs new file mode 100644 index 0000000000..5d9580e5e0 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.SQLite/SQLiteRegionData.cs @@ -0,0 +1,1733 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.IO; +using libsecondlife; +using Mono.Data.SqliteClient; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.LandManagement; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Framework.Data.SQLite +{ + public class SQLiteRegionData : IRegionDataStore + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private const string primSelect = "select * from prims"; + private const string shapeSelect = "select * from primshapes"; + private const string itemsSelect = "select * from primitems"; + private const string terrainSelect = "select * from terrain limit 1"; + private const string landSelect = "select * from land"; + private const string landAccessListSelect = "select * from landaccesslist"; + + private DataSet ds; + private SqliteDataAdapter primDa; + private SqliteDataAdapter shapeDa; + private SqliteDataAdapter itemsDa; + private SqliteDataAdapter terrainDa; + private SqliteDataAdapter landDa; + private SqliteDataAdapter landAccessListDa; + + private SqliteConnection m_conn; + + private String m_connectionString; + + // Temporary attribute while this is experimental + private bool persistPrimInventories; + + /*********************************************************************** + * + * Public Interface Functions + * + **********************************************************************/ + + // see IRegionDataStore + public void Initialise(string connectionString, bool persistPrimInventories) + { + m_connectionString = connectionString; + this.persistPrimInventories = persistPrimInventories; + + ds = new DataSet(); + + m_log.Info("[DATASTORE]: Sqlite - connecting: " + connectionString); + m_conn = new SqliteConnection(m_connectionString); + m_conn.Open(); + + SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); + primDa = new SqliteDataAdapter(primSelectCmd); + // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); + + SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); + shapeDa = new SqliteDataAdapter(shapeSelectCmd); + // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); + + SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn); + itemsDa = new SqliteDataAdapter(itemsSelectCmd); + + SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn); + terrainDa = new SqliteDataAdapter(terrainSelectCmd); + + SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn); + landDa = new SqliteDataAdapter(landSelectCmd); + + SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn); + landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd); + + // We fill the data set, now we've got copies in memory for the information + // TODO: see if the linkage actually holds. + // primDa.FillSchema(ds, SchemaType.Source, "PrimSchema"); + TestTables(m_conn); + + lock (ds) + { + ds.Tables.Add(createPrimTable()); + setupPrimCommands(primDa, m_conn); + primDa.Fill(ds.Tables["prims"]); + + ds.Tables.Add(createShapeTable()); + setupShapeCommands(shapeDa, m_conn); + + if (persistPrimInventories) + { + ds.Tables.Add(createItemsTable()); + setupItemsCommands(itemsDa, m_conn); + itemsDa.Fill(ds.Tables["primitems"]); + } + + ds.Tables.Add(createTerrainTable()); + setupTerrainCommands(terrainDa, m_conn); + + ds.Tables.Add(createLandTable()); + setupLandCommands(landDa, m_conn); + + ds.Tables.Add(createLandAccessListTable()); + setupLandAccessCommands(landAccessListDa, m_conn); + + // WORKAROUND: This is a work around for sqlite on + // windows, which gets really unhappy with blob columns + // that have no sample data in them. At some point we + // need to actually find a proper way to handle this. + try + { + shapeDa.Fill(ds.Tables["primshapes"]); + } + catch (Exception) + { + m_log.Info("[DATASTORE]: Caught fill error on primshapes table"); + } + + try + { + terrainDa.Fill(ds.Tables["terrain"]); + } + catch (Exception) + { + m_log.Info("[DATASTORE]: Caught fill error on terrain table"); + } + + try + { + landDa.Fill(ds.Tables["land"]); + } + catch (Exception) + { + m_log.Info("[DATASTORE]: Caught fill error on land table"); + } + + try + { + landAccessListDa.Fill(ds.Tables["landaccesslist"]); + } + catch (Exception) + { + m_log.Info("[DATASTORE]: Caught fill error on landaccesslist table"); + } + return; + } + } + + public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID) + { + lock (ds) + { + foreach (SceneObjectPart prim in obj.Children.Values) + { + if ((prim.ObjectFlags & (uint) LLObject.ObjectFlags.Physics) == 0) + { + m_log.Info("[DATASTORE]: Adding obj: " + obj.UUID + " to region: " + regionUUID); + addPrim(prim, Util.ToRawUuidString(obj.UUID), Util.ToRawUuidString(regionUUID)); + } + else if (prim.Stopped) + { + //m_log.Info("[DATASTORE]: " + + //"Adding stopped obj: " + obj.UUID + " to region: " + regionUUID); + //addPrim(prim, Util.ToRawUuidString(obj.UUID), Util.ToRawUuidString(regionUUID)); + } + else + { + // m_log.Info("[DATASTORE]: Ignoring Physical obj: " + obj.UUID + " in region: " + regionUUID); + } + } + } + + Commit(); + // m_log.Info("[Dump of prims]: " + ds.GetXml()); + } + + public void RemoveObject(LLUUID obj, LLUUID regionUUID) + { + m_log.InfoFormat("[DATASTORE]: Removing obj: {0} from region: {1}", obj.UUID, regionUUID); + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + string selectExp = "SceneGroupID = '" + Util.ToRawUuidString(obj) + "'"; + lock (ds) + { + DataRow[] primRows = prims.Select(selectExp); + foreach (DataRow row in primRows) + { + // Remove shape rows + LLUUID uuid = new LLUUID((string) row["UUID"]); + DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(uuid)); + if (shapeRow != null) + { + shapeRow.Delete(); + } + + if (persistPrimInventories) + { + RemoveItems(uuid); + } + + // Remove prim row + row.Delete(); + } + } + + Commit(); + } + + /// + /// Remove all persisted items of the given prim. + /// The caller must acquire the necessrary synchronization locks and commit or rollback changes. + /// + private void RemoveItems(LLUUID uuid) + { + DataTable items = ds.Tables["primitems"]; + + String sql = String.Format("primID = '{0}'", uuid); + DataRow[] itemRows = items.Select(sql); + + foreach (DataRow itemRow in itemRows) + { + itemRow.Delete(); + } + } + + /// + /// Load persisted objects from region storage. + /// + /// + /// List of loaded groups + public List LoadObjects(LLUUID regionUUID) + { + Dictionary createdObjects = new Dictionary(); + + List retvals = new List(); + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + string byRegion = "RegionUUID = '" + Util.ToRawUuidString(regionUUID) + "'"; + string orderByParent = "ParentID ASC"; + + lock (ds) + { + DataRow[] primsForRegion = prims.Select(byRegion, orderByParent); + m_log.Info("[DATASTORE]: " + + "Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); + + foreach (DataRow primRow in primsForRegion) + { + try + { + SceneObjectPart prim = null; + + string uuid = (string) primRow["UUID"]; + string objID = (string) primRow["SceneGroupID"]; + if (uuid == objID) //is new SceneObjectGroup ? + { + SceneObjectGroup group = new SceneObjectGroup(); + prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID)); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Info( + "No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + group.AddPart(prim); + group.RootPart = prim; + + createdObjects.Add(Util.ToRawUuidString(group.UUID), group); + retvals.Add(group); + } + else + { + prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID)); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Info( + "No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + createdObjects[new LLUUID(objID)].AddPart(prim); + } + + if (persistPrimInventories) + { + LoadItems(prim); + } + } + catch (Exception e) + { + m_log.Error("[DATASTORE]: Failed create prim object, exception and data follows"); + m_log.Info("[DATASTORE]: " + e.ToString()); + foreach (DataColumn col in prims.Columns) + { + m_log.Info("[DATASTORE]: Col: " + col.ColumnName + " => " + primRow[col]); + } + } + } + } + return retvals; + } + + /// + /// Load in a prim's persisted inventory. + /// + /// + private void LoadItems(SceneObjectPart prim) + { + m_log.InfoFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID); + + DataTable dbItems = ds.Tables["primitems"]; + + String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); + DataRow[] dbItemRows = dbItems.Select(sql); + + IList inventory = new List(); + + foreach (DataRow row in dbItemRows) + { + TaskInventoryItem item = buildItem(row); + inventory.Add(item); + + m_log.InfoFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID); + } + + prim.RestoreInventoryItems(inventory); + + // XXX A nasty little hack to recover the folder id for the prim (which is currently stored in + // every item). This data should really be stored in the prim table itself. + if (dbItemRows.Length > 0) + { + prim.FolderID = inventory[0].ParentID; + } + } + + public void StoreTerrain(double[,] ter, LLUUID regionID) + { + lock (ds) + { + int revision = Util.UnixTimeSinceEpoch(); + + // the following is an work around for .NET. The perf + // issues associated with it aren't as bad as you think. + m_log.Info("[DATASTORE]: Storing terrain revision r" + revision.ToString()); + String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" + + " values(:RegionUUID, :Revision, :Heightfield)"; + + using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", Util.ToRawUuidString(regionID))); + cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); + cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter))); + cmd.ExecuteNonQuery(); + } + + // This is added to get rid of the infinitely growing + // terrain databases which negatively impact on SQLite + // over time. Before reenabling this feature there + // needs to be a limitter put on the number of + // revisions in the database, as this old + // implementation is a DOS attack waiting to happen. + + using ( + SqliteCommand cmd = + new SqliteCommand("delete from terrain where RegionUUID=:RegionUUID and Revision < :Revision", + m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", Util.ToRawUuidString(regionID))); + cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); + cmd.ExecuteNonQuery(); + } + } + } + + public double[,] LoadTerrain(LLUUID regionID) + { + lock (ds) + { + double[,] terret = new double[256,256]; + terret.Initialize(); + + String sql = "select RegionUUID, Revision, Heightfield from terrain" + + " where RegionUUID=:RegionUUID order by Revision desc"; + + using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", Util.ToRawUuidString(regionID))); + + using (IDataReader row = cmd.ExecuteReader()) + { + int rev = 0; + if (row.Read()) + { + // TODO: put this into a function + MemoryStream str = new MemoryStream((byte[]) row["Heightfield"]); + BinaryReader br = new BinaryReader(str); + for (int x = 0; x < 256; x++) + { + for (int y = 0; y < 256; y++) + { + terret[x, y] = br.ReadDouble(); + } + } + rev = (int) row["Revision"]; + } + else + { + m_log.Info("[DATASTORE]: No terrain found for region"); + return null; + } + + m_log.Info("[DATASTORE]: Loaded terrain revision r" + rev.ToString()); + } + } + return terret; + } + } + + public void RemoveLandObject(LLUUID globalID) + { + lock (ds) + { + using (SqliteCommand cmd = new SqliteCommand("delete from land where UUID=:UUID", m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", Util.ToRawUuidString(globalID))); + cmd.ExecuteNonQuery(); + } + + using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:UUID", m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", Util.ToRawUuidString(globalID))); + cmd.ExecuteNonQuery(); + } + } + } + + public void StoreLandObject(Land parcel, LLUUID regionUUID) + { + lock (ds) + { + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + + DataRow landRow = land.Rows.Find(Util.ToRawUuidString(parcel.landData.globalID)); + if (landRow == null) + { + landRow = land.NewRow(); + fillLandRow(landRow, parcel.landData, regionUUID); + land.Rows.Add(landRow); + } + else + { + fillLandRow(landRow, parcel.landData, regionUUID); + } + + using ( + SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:LandUUID", m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":LandUUID", Util.ToRawUuidString(parcel.landData.globalID))); + cmd.ExecuteNonQuery(); + } + + foreach (ParcelManager.ParcelAccessEntry entry in parcel.landData.parcelAccessList) + { + DataRow newAccessRow = landaccesslist.NewRow(); + fillLandAccessRow(newAccessRow, entry, parcel.landData.globalID); + landaccesslist.Rows.Add(newAccessRow); + } + } + + Commit(); + } + + public List LoadLandObjects(LLUUID regionUUID) + { + List landDataForRegion = new List(); + lock (ds) + { + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + string searchExp = "RegionUUID = '" + Util.ToRawUuidString(regionUUID) + "'"; + DataRow[] rawDataForRegion = land.Select(searchExp); + foreach (DataRow rawDataLand in rawDataForRegion) + { + LandData newLand = buildLandData(rawDataLand); + string accessListSearchExp = "LandUUID = '" + Util.ToRawUuidString(newLand.globalID) + "'"; + DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp); + foreach (DataRow rawDataLandAccess in rawDataForLandAccessList) + { + newLand.parcelAccessList.Add(buildLandAccessData(rawDataLandAccess)); + } + + landDataForRegion.Add(newLand); + } + } + return landDataForRegion; + } + + public void Commit() + { + lock (ds) + { + primDa.Update(ds, "prims"); + shapeDa.Update(ds, "primshapes"); + + if (persistPrimInventories) + { + itemsDa.Update(ds, "primitems"); + } + + terrainDa.Update(ds, "terrain"); + landDa.Update(ds, "land"); + landAccessListDa.Update(ds, "landaccesslist"); + ds.AcceptChanges(); + } + } + + public void Shutdown() + { + Commit(); + } + + /*********************************************************************** + * + * Database Definition Functions + * + * This should be db agnostic as we define them in ADO.NET terms + * + **********************************************************************/ + + private void createCol(DataTable dt, string name, Type type) + { + DataColumn col = new DataColumn(name, type); + dt.Columns.Add(col); + } + + private DataTable createTerrainTable() + { + DataTable terrain = new DataTable("terrain"); + + createCol(terrain, "RegionUUID", typeof (String)); + createCol(terrain, "Revision", typeof (Int32)); + createCol(terrain, "Heightfield", typeof (Byte[])); + + return terrain; + } + + private DataTable createPrimTable() + { + DataTable prims = new DataTable("prims"); + + createCol(prims, "UUID", typeof (String)); + createCol(prims, "RegionUUID", typeof (String)); + createCol(prims, "ParentID", typeof (Int32)); + createCol(prims, "CreationDate", typeof (Int32)); + createCol(prims, "Name", typeof (String)); + createCol(prims, "SceneGroupID", typeof (String)); + // various text fields + createCol(prims, "Text", typeof (String)); + createCol(prims, "Description", typeof (String)); + createCol(prims, "SitName", typeof (String)); + createCol(prims, "TouchName", typeof (String)); + // permissions + createCol(prims, "ObjectFlags", typeof (Int32)); + createCol(prims, "CreatorID", typeof (String)); + createCol(prims, "OwnerID", typeof (String)); + createCol(prims, "GroupID", typeof (String)); + createCol(prims, "LastOwnerID", typeof (String)); + createCol(prims, "OwnerMask", typeof (Int32)); + createCol(prims, "NextOwnerMask", typeof (Int32)); + createCol(prims, "GroupMask", typeof (Int32)); + createCol(prims, "EveryoneMask", typeof (Int32)); + createCol(prims, "BaseMask", typeof (Int32)); + // vectors + createCol(prims, "PositionX", typeof (Double)); + createCol(prims, "PositionY", typeof (Double)); + createCol(prims, "PositionZ", typeof (Double)); + createCol(prims, "GroupPositionX", typeof (Double)); + createCol(prims, "GroupPositionY", typeof (Double)); + createCol(prims, "GroupPositionZ", typeof (Double)); + createCol(prims, "VelocityX", typeof (Double)); + createCol(prims, "VelocityY", typeof (Double)); + createCol(prims, "VelocityZ", typeof (Double)); + createCol(prims, "AngularVelocityX", typeof (Double)); + createCol(prims, "AngularVelocityY", typeof (Double)); + createCol(prims, "AngularVelocityZ", typeof (Double)); + createCol(prims, "AccelerationX", typeof (Double)); + createCol(prims, "AccelerationY", typeof (Double)); + createCol(prims, "AccelerationZ", typeof (Double)); + // quaternions + createCol(prims, "RotationX", typeof (Double)); + createCol(prims, "RotationY", typeof (Double)); + createCol(prims, "RotationZ", typeof (Double)); + createCol(prims, "RotationW", typeof (Double)); + + // sit target + createCol(prims, "SitTargetOffsetX", typeof (Double)); + createCol(prims, "SitTargetOffsetY", typeof (Double)); + createCol(prims, "SitTargetOffsetZ", typeof (Double)); + + createCol(prims, "SitTargetOrientW", typeof (Double)); + createCol(prims, "SitTargetOrientX", typeof (Double)); + createCol(prims, "SitTargetOrientY", typeof (Double)); + createCol(prims, "SitTargetOrientZ", typeof (Double)); + + // Add in contraints + prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]}; + + return prims; + } + + private DataTable createShapeTable() + { + DataTable shapes = new DataTable("primshapes"); + createCol(shapes, "UUID", typeof (String)); + // shape is an enum + createCol(shapes, "Shape", typeof (Int32)); + // vectors + createCol(shapes, "ScaleX", typeof (Double)); + createCol(shapes, "ScaleY", typeof (Double)); + createCol(shapes, "ScaleZ", typeof (Double)); + // paths + createCol(shapes, "PCode", typeof (Int32)); + createCol(shapes, "PathBegin", typeof (Int32)); + createCol(shapes, "PathEnd", typeof (Int32)); + createCol(shapes, "PathScaleX", typeof (Int32)); + createCol(shapes, "PathScaleY", typeof (Int32)); + createCol(shapes, "PathShearX", typeof (Int32)); + createCol(shapes, "PathShearY", typeof (Int32)); + createCol(shapes, "PathSkew", typeof (Int32)); + createCol(shapes, "PathCurve", typeof (Int32)); + createCol(shapes, "PathRadiusOffset", typeof (Int32)); + createCol(shapes, "PathRevolutions", typeof (Int32)); + createCol(shapes, "PathTaperX", typeof (Int32)); + createCol(shapes, "PathTaperY", typeof (Int32)); + createCol(shapes, "PathTwist", typeof (Int32)); + createCol(shapes, "PathTwistBegin", typeof (Int32)); + // profile + createCol(shapes, "ProfileBegin", typeof (Int32)); + createCol(shapes, "ProfileEnd", typeof (Int32)); + createCol(shapes, "ProfileCurve", typeof (Int32)); + createCol(shapes, "ProfileHollow", typeof (Int32)); + // text TODO: this isn't right, but I'm not sure the right + // way to specify this as a blob atm + createCol(shapes, "Texture", typeof (Byte[])); + createCol(shapes, "ExtraParams", typeof (Byte[])); + + shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]}; + + return shapes; + } + + private DataTable createItemsTable() + { + DataTable items = new DataTable("primitems"); + + createCol(items, "itemID", typeof (String)); + createCol(items, "primID", typeof (String)); + createCol(items, "assetID", typeof (String)); + createCol(items, "parentFolderID", typeof (String)); + + createCol(items, "invType", typeof (Int32)); + createCol(items, "assetType", typeof (Int32)); + + createCol(items, "name", typeof (String)); + createCol(items, "description", typeof (String)); + + createCol(items, "creationDate", typeof (Int64)); + createCol(items, "creatorID", typeof (String)); + createCol(items, "ownerID", typeof (String)); + createCol(items, "lastOwnerID", typeof (String)); + createCol(items, "groupID", typeof (String)); + + createCol(items, "nextPermissions", typeof (UInt32)); + createCol(items, "currentPermissions", typeof (UInt32)); + createCol(items, "basePermissions", typeof (UInt32)); + createCol(items, "everyonePermissions", typeof (UInt32)); + createCol(items, "groupPermissions", typeof (UInt32)); + + items.PrimaryKey = new DataColumn[] {items.Columns["itemID"]}; + + return items; + } + + private DataTable createLandTable() + { + DataTable land = new DataTable("land"); + createCol(land, "UUID", typeof (String)); + createCol(land, "RegionUUID", typeof (String)); + createCol(land, "LocalLandID", typeof (UInt32)); + + // Bitmap is a byte[512] + createCol(land, "Bitmap", typeof (Byte[])); + + createCol(land, "Name", typeof (String)); + createCol(land, "Desc", typeof (String)); + createCol(land, "OwnerUUID", typeof (String)); + createCol(land, "IsGroupOwned", typeof (Boolean)); + createCol(land, "Area", typeof (Int32)); + createCol(land, "AuctionID", typeof (Int32)); //Unemplemented + createCol(land, "Category", typeof (Int32)); //Enum libsecondlife.Parcel.ParcelCategory + createCol(land, "ClaimDate", typeof (Int32)); + createCol(land, "ClaimPrice", typeof (Int32)); + createCol(land, "GroupUUID", typeof (string)); + createCol(land, "SalePrice", typeof (Int32)); + createCol(land, "LandStatus", typeof (Int32)); //Enum. libsecondlife.Parcel.ParcelStatus + createCol(land, "LandFlags", typeof (UInt32)); + createCol(land, "LandingType", typeof (Byte)); + createCol(land, "MediaAutoScale", typeof (Byte)); + createCol(land, "MediaTextureUUID", typeof (String)); + createCol(land, "MediaURL", typeof (String)); + createCol(land, "MusicURL", typeof (String)); + createCol(land, "PassHours", typeof (Double)); + createCol(land, "PassPrice", typeof (UInt32)); + createCol(land, "SnapshotUUID", typeof (String)); + createCol(land, "UserLocationX", typeof (Double)); + createCol(land, "UserLocationY", typeof (Double)); + createCol(land, "UserLocationZ", typeof (Double)); + createCol(land, "UserLookAtX", typeof (Double)); + createCol(land, "UserLookAtY", typeof (Double)); + createCol(land, "UserLookAtZ", typeof (Double)); + + land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]}; + + return land; + } + + private DataTable createLandAccessListTable() + { + DataTable landaccess = new DataTable("landaccesslist"); + createCol(landaccess, "LandUUID", typeof (String)); + createCol(landaccess, "AccessUUID", typeof (String)); + createCol(landaccess, "Flags", typeof (UInt32)); + + return landaccess; + } + + /*********************************************************************** + * + * Convert between ADO.NET <=> OpenSim Objects + * + * These should be database independant + * + **********************************************************************/ + + private SceneObjectPart buildPrim(DataRow row) + { + // TODO: this doesn't work yet because something more + // interesting has to be done to actually get these values + // back out. Not enough time to figure it out yet. + SceneObjectPart prim = new SceneObjectPart(); + prim.UUID = new LLUUID((String) row["UUID"]); + // explicit conversion of integers is required, which sort + // of sucks. No idea if there is a shortcut here or not. + prim.ParentID = Convert.ToUInt32(row["ParentID"]); + prim.CreationDate = Convert.ToInt32(row["CreationDate"]); + prim.Name = (String) row["Name"]; + // various text fields + prim.Text = (String) row["Text"]; + prim.Description = (String) row["Description"]; + prim.SitName = (String) row["SitName"]; + prim.TouchName = (String) row["TouchName"]; + // permissions + prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]); + prim.CreatorID = new LLUUID((String) row["CreatorID"]); + prim.OwnerID = new LLUUID((String) row["OwnerID"]); + prim.GroupID = new LLUUID((String) row["GroupID"]); + prim.LastOwnerID = new LLUUID((String) row["LastOwnerID"]); + prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); + prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); + prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); + prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); + prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); + // vectors + prim.OffsetPosition = new LLVector3( + Convert.ToSingle(row["PositionX"]), + Convert.ToSingle(row["PositionY"]), + Convert.ToSingle(row["PositionZ"]) + ); + prim.GroupPosition = new LLVector3( + Convert.ToSingle(row["GroupPositionX"]), + Convert.ToSingle(row["GroupPositionY"]), + Convert.ToSingle(row["GroupPositionZ"]) + ); + prim.Velocity = new LLVector3( + Convert.ToSingle(row["VelocityX"]), + Convert.ToSingle(row["VelocityY"]), + Convert.ToSingle(row["VelocityZ"]) + ); + prim.AngularVelocity = new LLVector3( + Convert.ToSingle(row["AngularVelocityX"]), + Convert.ToSingle(row["AngularVelocityY"]), + Convert.ToSingle(row["AngularVelocityZ"]) + ); + prim.Acceleration = new LLVector3( + Convert.ToSingle(row["AccelerationX"]), + Convert.ToSingle(row["AccelerationY"]), + Convert.ToSingle(row["AccelerationZ"]) + ); + // quaternions + prim.RotationOffset = new LLQuaternion( + Convert.ToSingle(row["RotationX"]), + Convert.ToSingle(row["RotationY"]), + Convert.ToSingle(row["RotationZ"]), + Convert.ToSingle(row["RotationW"]) + ); + + try + { + prim.SetSitTargetLL(new LLVector3( + Convert.ToSingle(row["SitTargetOffsetX"]), + Convert.ToSingle(row["SitTargetOffsetY"]), + Convert.ToSingle(row["SitTargetOffsetZ"])), new LLQuaternion( + Convert.ToSingle( + row["SitTargetOrientX"]), + Convert.ToSingle( + row["SitTargetOrientY"]), + Convert.ToSingle( + row["SitTargetOrientZ"]), + Convert.ToSingle( + row["SitTargetOrientW"]))); + } + catch (InvalidCastException) + { + // Database table was created before we got here and now has null values :P + m_conn.Open(); + SqliteCommand cmd = + new SqliteCommand("ALTER TABLE prims ADD COLUMN SitTargetOffsetX float NOT NULL default 0;", m_conn); + cmd.ExecuteNonQuery(); + cmd = + new SqliteCommand("ALTER TABLE prims ADD COLUMN SitTargetOffsetY float NOT NULL default 0;", m_conn); + cmd.ExecuteNonQuery(); + cmd = + new SqliteCommand("ALTER TABLE prims ADD COLUMN SitTargetOffsetZ float NOT NULL default 0;", m_conn); + cmd.ExecuteNonQuery(); + cmd = + new SqliteCommand("ALTER TABLE prims ADD COLUMN SitTargetOrientW float NOT NULL default 0;", m_conn); + cmd.ExecuteNonQuery(); + cmd = + new SqliteCommand("ALTER TABLE prims ADD COLUMN SitTargetOrientX float NOT NULL default 0;", m_conn); + cmd.ExecuteNonQuery(); + cmd = + new SqliteCommand("ALTER TABLE prims ADD COLUMN SitTargetOrientY float NOT NULL default 0;", m_conn); + cmd.ExecuteNonQuery(); + cmd = + new SqliteCommand("ALTER TABLE prims ADD COLUMN SitTargetOrientZ float NOT NULL default 0;", m_conn); + cmd.ExecuteNonQuery(); + } + + return prim; + } + + /// + /// Build a prim inventory item from the persisted data. + /// + /// + /// + private TaskInventoryItem buildItem(DataRow row) + { + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ItemID = new LLUUID((String)row["itemID"]); + taskItem.ParentPartID = new LLUUID((String)row["primID"]); + taskItem.AssetID = new LLUUID((String)row["assetID"]); + taskItem.ParentID = new LLUUID((String)row["parentFolderID"]); + + taskItem.InvType = Convert.ToInt32(row["invType"]); + taskItem.Type = Convert.ToInt32(row["assetType"]); + + taskItem.Name = (String)row["name"]; + taskItem.Description = (String)row["description"]; + taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]); + taskItem.CreatorID = new LLUUID((String)row["creatorID"]); + taskItem.OwnerID = new LLUUID((String)row["ownerID"]); + taskItem.LastOwnerID = new LLUUID((String)row["lastOwnerID"]); + taskItem.GroupID = new LLUUID((String)row["groupID"]); + + taskItem.NextOwnerMask = Convert.ToUInt32(row["nextPermissions"]); + taskItem.OwnerMask = Convert.ToUInt32(row["currentPermissions"]); + taskItem.BaseMask = Convert.ToUInt32(row["basePermissions"]); + taskItem.EveryoneMask = Convert.ToUInt32(row["everyonePermissions"]); + taskItem.GroupMask = Convert.ToUInt32(row["groupPermissions"]); + + return taskItem; + } + + private LandData buildLandData(DataRow row) + { + LandData newData = new LandData(); + + newData.globalID = new LLUUID((String) row["UUID"]); + newData.localID = Convert.ToInt32(row["LocalLandID"]); + + // Bitmap is a byte[512] + newData.landBitmapByteArray = (Byte[]) row["Bitmap"]; + + newData.landName = (String) row["Name"]; + newData.landDesc = (String) row["Desc"]; + newData.ownerID = (String) row["OwnerUUID"]; + newData.isGroupOwned = (Boolean) row["IsGroupOwned"]; + newData.area = Convert.ToInt32(row["Area"]); + newData.auctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented + newData.category = (Parcel.ParcelCategory) Convert.ToInt32(row["Category"]); + //Enum libsecondlife.Parcel.ParcelCategory + newData.claimDate = Convert.ToInt32(row["ClaimDate"]); + newData.claimPrice = Convert.ToInt32(row["ClaimPrice"]); + newData.groupID = new LLUUID((String) row["GroupUUID"]); + newData.salePrice = Convert.ToInt32(row["SalePrice"]); + newData.landStatus = (Parcel.ParcelStatus) Convert.ToInt32(row["LandStatus"]); + //Enum. libsecondlife.Parcel.ParcelStatus + newData.landFlags = Convert.ToUInt32(row["LandFlags"]); + newData.landingType = (Byte) row["LandingType"]; + newData.mediaAutoScale = (Byte) row["MediaAutoScale"]; + newData.mediaID = new LLUUID((String) row["MediaTextureUUID"]); + newData.mediaURL = (String) row["MediaURL"]; + newData.musicURL = (String) row["MusicURL"]; + newData.passHours = Convert.ToSingle(row["PassHours"]); + newData.passPrice = Convert.ToInt32(row["PassPrice"]); + newData.snapshotID = (String) row["SnapshotUUID"]; + + newData.userLocation = + new LLVector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), + Convert.ToSingle(row["UserLocationZ"])); + newData.userLookAt = + new LLVector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), + Convert.ToSingle(row["UserLookAtZ"])); + newData.parcelAccessList = new List(); + + return newData; + } + + private ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = new LLUUID((string) row["AccessUUID"]); + entry.Flags = (ParcelManager.AccessList) row["Flags"]; + entry.Time = new DateTime(); + return entry; + } + + private Array serializeTerrain(double[,] val) + { + MemoryStream str = new MemoryStream(65536*sizeof (double)); + BinaryWriter bw = new BinaryWriter(str); + + // TODO: COMPATIBILITY - Add byte-order conversions + for (int x = 0; x < 256; x++) + for (int y = 0; y < 256; y++) + bw.Write(val[x, y]); + + return str.ToArray(); + } + +// private void fillTerrainRow(DataRow row, LLUUID regionUUID, int rev, double[,] val) +// { +// row["RegionUUID"] = regionUUID; +// row["Revision"] = rev; + +// MemoryStream str = new MemoryStream(65536*sizeof (double)); +// BinaryWriter bw = new BinaryWriter(str); + +// // TODO: COMPATIBILITY - Add byte-order conversions +// for (int x = 0; x < 256; x++) +// for (int y = 0; y < 256; y++) +// bw.Write(val[x, y]); + +// row["Heightfield"] = str.ToArray(); +// } + + private void fillPrimRow(DataRow row, SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID) + { + row["UUID"] = Util.ToRawUuidString(prim.UUID); + row["RegionUUID"] = Util.ToRawUuidString(regionUUID); + row["ParentID"] = prim.ParentID; + row["CreationDate"] = prim.CreationDate; + row["Name"] = prim.Name; + row["SceneGroupID"] = Util.ToRawUuidString(sceneGroupID); + // the UUID of the root part for this SceneObjectGroup + // various text fields + row["Text"] = prim.Text; + row["Description"] = prim.Description; + row["SitName"] = prim.SitName; + row["TouchName"] = prim.TouchName; + // permissions + row["ObjectFlags"] = prim.ObjectFlags; + row["CreatorID"] = Util.ToRawUuidString(prim.CreatorID); + row["OwnerID"] = Util.ToRawUuidString(prim.OwnerID); + row["GroupID"] = Util.ToRawUuidString(prim.GroupID); + row["LastOwnerID"] = Util.ToRawUuidString(prim.LastOwnerID); + row["OwnerMask"] = prim.OwnerMask; + row["NextOwnerMask"] = prim.NextOwnerMask; + row["GroupMask"] = prim.GroupMask; + row["EveryoneMask"] = prim.EveryoneMask; + row["BaseMask"] = prim.BaseMask; + // vectors + row["PositionX"] = prim.OffsetPosition.X; + row["PositionY"] = prim.OffsetPosition.Y; + row["PositionZ"] = prim.OffsetPosition.Z; + row["GroupPositionX"] = prim.GroupPosition.X; + row["GroupPositionY"] = prim.GroupPosition.Y; + row["GroupPositionZ"] = prim.GroupPosition.Z; + row["VelocityX"] = prim.Velocity.X; + row["VelocityY"] = prim.Velocity.Y; + row["VelocityZ"] = prim.Velocity.Z; + row["AngularVelocityX"] = prim.AngularVelocity.X; + row["AngularVelocityY"] = prim.AngularVelocity.Y; + row["AngularVelocityZ"] = prim.AngularVelocity.Z; + row["AccelerationX"] = prim.Acceleration.X; + row["AccelerationY"] = prim.Acceleration.Y; + row["AccelerationZ"] = prim.Acceleration.Z; + // quaternions + row["RotationX"] = prim.RotationOffset.X; + row["RotationY"] = prim.RotationOffset.Y; + row["RotationZ"] = prim.RotationOffset.Z; + row["RotationW"] = prim.RotationOffset.W; + + // Sit target + LLVector3 sitTargetPos = prim.GetSitTargetPositionLL(); + row["SitTargetOffsetX"] = sitTargetPos.X; + row["SitTargetOffsetY"] = sitTargetPos.Y; + row["SitTargetOffsetZ"] = sitTargetPos.Z; + + LLQuaternion sitTargetOrient = prim.GetSitTargetOrientationLL(); + row["SitTargetOrientW"] = sitTargetOrient.W; + row["SitTargetOrientX"] = sitTargetOrient.X; + row["SitTargetOrientY"] = sitTargetOrient.Y; + row["SitTargetOrientZ"] = sitTargetOrient.Z; + } + + private void fillItemRow(DataRow row, TaskInventoryItem taskItem) + { + row["itemID"] = taskItem.ItemID; + row["primID"] = taskItem.ParentPartID; + row["assetID"] = taskItem.AssetID; + row["parentFolderID"] = taskItem.ParentID; + + row["invType"] = taskItem.InvType; + row["assetType"] = taskItem.Type; + + row["name"] = taskItem.Name; + row["description"] = taskItem.Description; + row["creationDate"] = taskItem.CreationDate; + row["creatorID"] = taskItem.CreatorID; + row["ownerID"] = taskItem.OwnerID; + row["lastOwnerID"] = taskItem.LastOwnerID; + row["groupID"] = taskItem.GroupID; + row["nextPermissions"] = taskItem.NextOwnerMask; + row["currentPermissions"] = taskItem.OwnerMask; + row["basePermissions"] = taskItem.BaseMask; + row["everyonePermissions"] = taskItem.EveryoneMask; + row["groupPermissions"] = taskItem.GroupMask; + } + + private void fillLandRow(DataRow row, LandData land, LLUUID regionUUID) + { + row["UUID"] = Util.ToRawUuidString(land.globalID); + row["RegionUUID"] = Util.ToRawUuidString(regionUUID); + row["LocalLandID"] = land.localID; + + // Bitmap is a byte[512] + row["Bitmap"] = land.landBitmapByteArray; + + row["Name"] = land.landName; + row["Desc"] = land.landDesc; + row["OwnerUUID"] = Util.ToRawUuidString(land.ownerID); + row["IsGroupOwned"] = land.isGroupOwned; + row["Area"] = land.area; + row["AuctionID"] = land.auctionID; //Unemplemented + row["Category"] = land.category; //Enum libsecondlife.Parcel.ParcelCategory + row["ClaimDate"] = land.claimDate; + row["ClaimPrice"] = land.claimPrice; + row["GroupUUID"] = Util.ToRawUuidString(land.groupID); + row["SalePrice"] = land.salePrice; + row["LandStatus"] = land.landStatus; //Enum. libsecondlife.Parcel.ParcelStatus + row["LandFlags"] = land.landFlags; + row["LandingType"] = land.landingType; + row["MediaAutoScale"] = land.mediaAutoScale; + row["MediaTextureUUID"] = Util.ToRawUuidString(land.mediaID); + row["MediaURL"] = land.mediaURL; + row["MusicURL"] = land.musicURL; + row["PassHours"] = land.passHours; + row["PassPrice"] = land.passPrice; + row["SnapshotUUID"] = Util.ToRawUuidString(land.snapshotID); + row["UserLocationX"] = land.userLocation.X; + row["UserLocationY"] = land.userLocation.Y; + row["UserLocationZ"] = land.userLocation.Z; + row["UserLookAtX"] = land.userLookAt.X; + row["UserLookAtY"] = land.userLookAt.Y; + row["UserLookAtZ"] = land.userLookAt.Z; + } + + private void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, LLUUID parcelID) + { + row["LandUUID"] = Util.ToRawUuidString(parcelID); + row["AccessUUID"] = Util.ToRawUuidString(entry.AgentID); + row["Flags"] = entry.Flags; + } + + private PrimitiveBaseShape buildShape(DataRow row) + { + PrimitiveBaseShape s = new PrimitiveBaseShape(); + s.Scale = new LLVector3( + Convert.ToSingle(row["ScaleX"]), + Convert.ToSingle(row["ScaleY"]), + Convert.ToSingle(row["ScaleZ"]) + ); + // paths + s.PCode = Convert.ToByte(row["PCode"]); + s.PathBegin = Convert.ToUInt16(row["PathBegin"]); + s.PathEnd = Convert.ToUInt16(row["PathEnd"]); + s.PathScaleX = Convert.ToByte(row["PathScaleX"]); + s.PathScaleY = Convert.ToByte(row["PathScaleY"]); + s.PathShearX = Convert.ToByte(row["PathShearX"]); + s.PathShearY = Convert.ToByte(row["PathShearY"]); + s.PathSkew = Convert.ToSByte(row["PathSkew"]); + s.PathCurve = Convert.ToByte(row["PathCurve"]); + s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]); + s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]); + s.PathTaperX = Convert.ToSByte(row["PathTaperX"]); + s.PathTaperY = Convert.ToSByte(row["PathTaperY"]); + s.PathTwist = Convert.ToSByte(row["PathTwist"]); + s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]); + // profile + s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]); + s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); + s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); + s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); + // text TODO: this isn't right] = but I'm not sure the right + // way to specify this as a blob atm + + byte[] textureEntry = (byte[]) row["Texture"]; + s.TextureEntry = textureEntry; + + s.ExtraParams = (byte[]) row["ExtraParams"]; + // System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); + // string texture = encoding.GetString((Byte[])row["Texture"]); + // if (!texture.StartsWith("<")) + // { + // //here so that we can still work with old format database files (ie from before I added xml serialization) + // LLObject.TextureEntry textureEntry = null; + // textureEntry = new LLObject.TextureEntry(new LLUUID(texture)); + // s.TextureEntry = textureEntry.ToBytes(); + // } + // else + // { + // TextureBlock textureEntry = TextureBlock.FromXmlString(texture); + // s.TextureEntry = textureEntry.TextureData; + // s.ExtraParams = textureEntry.ExtraParams; + // } + + return s; + } + + private void fillShapeRow(DataRow row, SceneObjectPart prim) + { + PrimitiveBaseShape s = prim.Shape; + row["UUID"] = Util.ToRawUuidString(prim.UUID); + // shape is an enum + row["Shape"] = 0; + // vectors + row["ScaleX"] = s.Scale.X; + row["ScaleY"] = s.Scale.Y; + row["ScaleZ"] = s.Scale.Z; + // paths + row["PCode"] = s.PCode; + row["PathBegin"] = s.PathBegin; + row["PathEnd"] = s.PathEnd; + row["PathScaleX"] = s.PathScaleX; + row["PathScaleY"] = s.PathScaleY; + row["PathShearX"] = s.PathShearX; + row["PathShearY"] = s.PathShearY; + row["PathSkew"] = s.PathSkew; + row["PathCurve"] = s.PathCurve; + row["PathRadiusOffset"] = s.PathRadiusOffset; + row["PathRevolutions"] = s.PathRevolutions; + row["PathTaperX"] = s.PathTaperX; + row["PathTaperY"] = s.PathTaperY; + row["PathTwist"] = s.PathTwist; + row["PathTwistBegin"] = s.PathTwistBegin; + // profile + row["ProfileBegin"] = s.ProfileBegin; + row["ProfileEnd"] = s.ProfileEnd; + row["ProfileCurve"] = s.ProfileCurve; + row["ProfileHollow"] = s.ProfileHollow; + + row["Texture"] = s.TextureEntry; + row["ExtraParams"] = s.ExtraParams; + } + + private void addPrim(SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID) + { + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + DataRow primRow = prims.Rows.Find(Util.ToRawUuidString(prim.UUID)); + if (primRow == null) + { + primRow = prims.NewRow(); + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + prims.Rows.Add(primRow); + } + else + { + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + } + + DataRow shapeRow = shapes.Rows.Find(Util.ToRawUuidString(prim.UUID)); + if (shapeRow == null) + { + shapeRow = shapes.NewRow(); + fillShapeRow(shapeRow, prim); + shapes.Rows.Add(shapeRow); + } + else + { + fillShapeRow(shapeRow, prim); + } + } + + // see IRegionDatastore + public void StorePrimInventory(LLUUID primID, ICollection items) + { + if (!persistPrimInventories) + return; + + m_log.InfoFormat("[DATASTORE]: Entered StorePrimInventory with prim ID {0}", primID); + + DataTable dbItems = ds.Tables["primitems"]; + + // For now, we're just going to crudely remove all the previous inventory items + // no matter whether they have changed or not, and replace them with the current set. + lock (ds) + { + RemoveItems(primID); + + // repalce with current inventory details + foreach (TaskInventoryItem newItem in items) + { +// m_log.InfoFormat( +// "[DATASTORE]: ", +// "Adding item {0}, {1} to prim ID {2}", +// newItem.Name, newItem.ItemID, newItem.ParentPartID); + + DataRow newItemRow = dbItems.NewRow(); + fillItemRow(newItemRow, newItem); + dbItems.Rows.Add(newItemRow); + } + } + + Commit(); + } + + /*********************************************************************** + * + * SQL Statement Creation Functions + * + * These functions create SQL statements for update, insert, and create. + * They can probably be factored later to have a db independant + * portion and a db specific portion + * + **********************************************************************/ + + private SqliteCommand createInsertCommand(string table, DataTable dt) + { + /** + * This is subtle enough to deserve some commentary. + * Instead of doing *lots* and *lots of hardcoded strings + * for database definitions we'll use the fact that + * realistically all insert statements look like "insert + * into A(b, c) values(:b, :c) on the parameterized query + * front. If we just have a list of b, c, etc... we can + * generate these strings instead of typing them out. + */ + string[] cols = new string[dt.Columns.Count]; + for (int i = 0; i < dt.Columns.Count; i++) + { + DataColumn col = dt.Columns[i]; + cols[i] = col.ColumnName; + } + + string sql = "insert into " + table + "("; + sql += String.Join(", ", cols); + // important, the first ':' needs to be here, the rest get added in the join + sql += ") values (:"; + sql += String.Join(", :", cols); + sql += ")"; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + private SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= :" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + + private string defineTable(DataTable dt) + { + string sql = "create table " + dt.TableName + "("; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ",\n"; + } + subsql += col.ColumnName + " " + sqliteType(col.DataType); + if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0]) + { + subsql += " primary key"; + } + } + sql += subsql; + sql += ")"; + return sql; + } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + /// + /// This is a convenience function that collapses 5 repetitive + /// lines for defining SqliteParameters to 2 parameters: + /// column name and database type. + /// + /// It assumes certain conventions like :param as the param + /// name to replace in parametrized queries, and that source + /// version is always current version, both of which are fine + /// for us. + /// + ///a built sqlite parameter + private SqliteParameter createSqliteParameter(string name, Type type) + { + SqliteParameter param = new SqliteParameter(); + param.ParameterName = ":" + name; + param.DbType = dbtypeFromType(type); + param.SourceColumn = name; + param.SourceVersion = DataRowVersion.Current; + return param; + } + + private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("primitems", ds.Tables["primitems"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primitems", "itemID = :itemID", ds.Tables["primitems"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from primitems where itemID = :itemID"); + delete.Parameters.Add(createSqliteParameter("itemID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]); + da.InsertCommand.Connection = conn; + } + + private void setupLandCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("land", ds.Tables["land"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("land", "UUID=:UUID", ds.Tables["land"]); + da.UpdateCommand.Connection = conn; + } + + private void setupLandAccessCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("landaccesslist", ds.Tables["landaccesslist"]); + da.InsertCommand.Connection = conn; + } + + private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /// + /// Create the necessary database tables. + /// + /// + private void InitDB(SqliteConnection conn) + { + string createPrims = defineTable(createPrimTable()); + string createShapes = defineTable(createShapeTable()); + string createItems = defineTable(createItemsTable()); + string createTerrain = defineTable(createTerrainTable()); + string createLand = defineTable(createLandTable()); + string createLandAccessList = defineTable(createLandAccessListTable()); + + SqliteCommand pcmd = new SqliteCommand(createPrims, conn); + SqliteCommand scmd = new SqliteCommand(createShapes, conn); + SqliteCommand icmd = new SqliteCommand(createItems, conn); + SqliteCommand tcmd = new SqliteCommand(createTerrain, conn); + SqliteCommand lcmd = new SqliteCommand(createLand, conn); + SqliteCommand lalcmd = new SqliteCommand(createLandAccessList, conn); + + conn.Open(); + + try + { + pcmd.ExecuteNonQuery(); + } + catch (SqliteSyntaxException) + { + m_log.Warn("[SQLITE]: Primitives Table Already Exists"); + } + + try + { + scmd.ExecuteNonQuery(); + } + catch (SqliteSyntaxException) + { + m_log.Warn("[SQLITE]: Shapes Table Already Exists"); + } + + if (persistPrimInventories) + { + try + { + icmd.ExecuteNonQuery(); + } + catch (SqliteSyntaxException) + { + m_log.Warn("[SQLITE]: Primitives Inventory Table Already Exists"); + } + } + + try + { + tcmd.ExecuteNonQuery(); + } + catch (SqliteSyntaxException) + { + m_log.Warn("[SQLITE]: Terrain Table Already Exists"); + } + + try + { + lcmd.ExecuteNonQuery(); + } + catch (SqliteSyntaxException) + { + m_log.Warn("[SQLITE]: Land Table Already Exists"); + } + + try + { + lalcmd.ExecuteNonQuery(); + } + catch (SqliteSyntaxException) + { + m_log.Warn("[SQLITE]: LandAccessList Table Already Exists"); + } + conn.Close(); + } + + private bool TestTables(SqliteConnection conn) + { + SqliteCommand primSelectCmd = new SqliteCommand(primSelect, conn); + SqliteDataAdapter pDa = new SqliteDataAdapter(primSelectCmd); + + SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, conn); + SqliteDataAdapter sDa = new SqliteDataAdapter(shapeSelectCmd); + + SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, conn); + SqliteDataAdapter iDa = new SqliteDataAdapter(itemsSelectCmd); + + SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, conn); + SqliteDataAdapter tDa = new SqliteDataAdapter(terrainSelectCmd); + + SqliteCommand landSelectCmd = new SqliteCommand(landSelect, conn); + SqliteDataAdapter lDa = new SqliteDataAdapter(landSelectCmd); + + SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, conn); + SqliteDataAdapter lalDa = new SqliteDataAdapter(landAccessListSelectCmd); + + DataSet tmpDS = new DataSet(); + try + { + pDa.Fill(tmpDS, "prims"); + sDa.Fill(tmpDS, "primshapes"); + + if (persistPrimInventories) + iDa.Fill(tmpDS, "primitems"); + + tDa.Fill(tmpDS, "terrain"); + lDa.Fill(tmpDS, "land"); + lalDa.Fill(tmpDS, "landaccesslist"); + } + catch (SqliteSyntaxException) + { + m_log.Info("[DATASTORE]: SQLite Database doesn't exist... creating"); + InitDB(conn); + } + + pDa.Fill(tmpDS, "prims"); + sDa.Fill(tmpDS, "primshapes"); + + if (persistPrimInventories) + iDa.Fill(tmpDS, "primitems"); + + tDa.Fill(tmpDS, "terrain"); + lDa.Fill(tmpDS, "land"); + lalDa.Fill(tmpDS, "landaccesslist"); + + foreach (DataColumn col in createPrimTable().Columns) + { + if (!tmpDS.Tables["prims"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing required column:" + col.ColumnName); + return false; + } + } + + foreach (DataColumn col in createShapeTable().Columns) + { + if (!tmpDS.Tables["primshapes"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing required column:" + col.ColumnName); + return false; + } + } + + // XXX primitems should probably go here eventually + + foreach (DataColumn col in createTerrainTable().Columns) + { + if (!tmpDS.Tables["terrain"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing require column:" + col.ColumnName); + return false; + } + } + + foreach (DataColumn col in createLandTable().Columns) + { + if (!tmpDS.Tables["land"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing require column:" + col.ColumnName); + return false; + } + } + + foreach (DataColumn col in createLandAccessListTable().Columns) + { + if (!tmpDS.Tables["landaccesslist"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing require column:" + col.ColumnName); + return false; + } + } + + return true; + } + + /*********************************************************************** + * + * Type conversion functions + * + **********************************************************************/ + + private DbType dbtypeFromType(Type type) + { + if (type == typeof (String)) + { + return DbType.String; + } + else if (type == typeof (Int32)) + { + return DbType.Int32; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte)) + { + return DbType.Byte; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte[])) + { + return DbType.Binary; + } + else + { + return DbType.String; + } + } + + // this is something we'll need to implement for each db + // slightly differently. + private string sqliteType(Type type) + { + if (type == typeof (String)) + { + return "varchar(255)"; + } + else if (type == typeof (Int32)) + { + return "integer"; + } + else if (type == typeof (Int64)) + { + return "integer"; + } + else if (type == typeof (Double)) + { + return "float"; + } + else if (type == typeof (Byte[])) + { + return "blob"; + } + else + { + return "string"; + } + } + } +} diff --git a/trunk/OpenSim/Framework/Data.SQLite/SQLiteUserData.cs b/trunk/OpenSim/Framework/Data.SQLite/SQLiteUserData.cs new file mode 100644 index 0000000000..2316de8400 --- /dev/null +++ b/trunk/OpenSim/Framework/Data.SQLite/SQLiteUserData.cs @@ -0,0 +1,835 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using libsecondlife; +using Mono.Data.SqliteClient; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.SQLite +{ + /// + /// A User storage interface for the SQLite database system + /// + public class SQLiteUserData : SQLiteBase, IUserData + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The database manager + /// + /// + /// Artificial constructor called upon plugin load + /// + private const string SelectUserByUUID = "select * from users where UUID=:UUID"; + private const string SelectUserByName = "select * from users where username=:username and surname=:surname"; + private const string SelectFriendsByUUID = "select a.friendID, a.friendPerms, b.friendPerms from userfriends as a, userfriends as b where a.ownerID=:ownerID and b.ownerID=a.friendID and b.friendID=a.ownerID"; + + private const string userSelect = "select * from users"; + private const string userFriendsSelect = "select a.ownerID as ownerID,a.friendID as friendID,a.friendPerms as friendPerms,b.friendPerms as ownerperms, b.ownerID as fownerID, b.friendID as ffriendID from userfriends as a, userfriends as b"; + + private const string AvatarPickerAndSQL = "select * from users where username like :username and surname like :surname"; + private const string AvatarPickerOrSQL = "select * from users where username like :username or surname like :surname"; + + private DataSet ds; + private SqliteDataAdapter da; + private SqliteDataAdapter daf; + SqliteConnection g_conn; + + public void Initialise() + { + SqliteConnection conn = new SqliteConnection("URI=file:userprofiles.db,version=3"); + TestTables(conn); + + // This sucks, but It doesn't seem to work with the dataset Syncing :P + g_conn = conn; + g_conn.Open(); + + ds = new DataSet(); + da = new SqliteDataAdapter(new SqliteCommand(userSelect, conn)); + daf = new SqliteDataAdapter(new SqliteCommand(userFriendsSelect, conn)); + + lock (ds) + { + ds.Tables.Add(createUsersTable()); + ds.Tables.Add(createUserAgentsTable()); + ds.Tables.Add(createUserFriendsTable()); + + setupUserCommands(da, conn); + da.Fill(ds.Tables["users"]); + + setupUserFriendsCommands(daf, conn); + try + { + daf.Fill(ds.Tables["userfriends"]); + } + catch (SqliteSyntaxException) + { + m_log.Info("[SQLITE]: userfriends table not found, creating.... "); + InitDB(conn); + daf.Fill(ds.Tables["userfriends"]); + } + + } + + return; + } + + // see IUserData + public UserProfileData GetUserByUUID(LLUUID uuid) + { + lock (ds) + { + DataRow row = ds.Tables["users"].Rows.Find(Util.ToRawUuidString(uuid)); + if (row != null) + { + UserProfileData user = buildUserProfile(row); + row = ds.Tables["useragents"].Rows.Find(Util.ToRawUuidString(uuid)); + if (row != null) + { + user.currentAgent = buildUserAgent(row); + } + return user; + } + else + { + return null; + } + } + } + + // see IUserData + public UserProfileData GetUserByName(string fname, string lname) + { + string select = "surname = '" + lname + "' and username = '" + fname + "'"; + lock (ds) + { + DataRow[] rows = ds.Tables["users"].Select(select); + if (rows.Length > 0) + { + UserProfileData user = buildUserProfile(rows[0]); + DataRow row = ds.Tables["useragents"].Rows.Find(Util.ToRawUuidString(user.UUID)); + if (row != null) + { + user.currentAgent = buildUserAgent(row); + } + return user; + } + else + { + return null; + } + } + } + + #region User Friends List Data + + public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms) + { + string InsertFriends = "insert into userfriends(ownerID, friendID, friendPerms) values(:ownerID, :friendID, :perms)"; + + using (SqliteCommand cmd = new SqliteCommand(InsertFriends, g_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":ownerID", friendlistowner.UUID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":friendID", friend.UUID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":perms", perms)); + cmd.ExecuteNonQuery(); + } + using (SqliteCommand cmd = new SqliteCommand(InsertFriends, g_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":ownerID", friend.UUID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":friendID", friendlistowner.UUID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":perms", perms)); + cmd.ExecuteNonQuery(); + } + } + + public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend) + { + string DeletePerms = "delete from friendlist where (ownerID=:ownerID and friendID=:friendID) or (ownerID=:friendID and friendID=:ownerID)"; + using (SqliteCommand cmd = new SqliteCommand(DeletePerms, g_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":ownerID", friendlistowner.UUID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":friendID", friend.UUID.ToString())); + cmd.ExecuteNonQuery(); + } + } + + public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms) + { + string UpdatePerms = "update friendlist set perms=:perms where ownerID=:ownerID and friendID=:friendID"; + using (SqliteCommand cmd = new SqliteCommand(UpdatePerms, g_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":perms", perms)); + cmd.Parameters.Add(new SqliteParameter(":ownerID", friendlistowner.UUID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":friendID", friend.UUID.ToString())); + cmd.ExecuteNonQuery(); + } + } + + public List GetUserFriendList(LLUUID friendlistowner) + { + List returnlist = new List(); + + using (SqliteCommand cmd = new SqliteCommand(SelectFriendsByUUID, g_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":ownerID", friendlistowner.UUID.ToString())); + + try + { + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + FriendListItem user = new FriendListItem(); + user.FriendListOwner = friendlistowner; + user.Friend = new LLUUID((string)reader[0]); + user.FriendPerms = Convert.ToUInt32(reader[1]); + user.FriendListOwnerPerms = Convert.ToUInt32(reader[2]); + returnlist.Add(user); + } + reader.Close(); + } + } + catch (Exception ex) + { + m_log.Error("[USER]: Exception getting friends list for user: " + ex.ToString()); + } + } + + return returnlist; + } + + + + + #endregion + + public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid) + { + m_log.Info("[USER]: Stub UpdateUserCUrrentRegion called"); + } + + + public List GeneratePickerResults(LLUUID queryID, string query) + { + List returnlist = new List(); + string[] querysplit; + querysplit = query.Split(' '); + if (querysplit.Length == 2) + { + using (SqliteCommand cmd = new SqliteCommand(AvatarPickerAndSQL, g_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":username", querysplit[0] + "%")); + cmd.Parameters.Add(new SqliteParameter(":surname", querysplit[1] + "%")); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + Framework.AvatarPickerAvatar user = new Framework.AvatarPickerAvatar(); + user.AvatarID = new LLUUID((string) reader["UUID"]); + user.firstName = (string) reader["username"]; + user.lastName = (string) reader["surname"]; + returnlist.Add(user); + } + reader.Close(); + } + } + } + else if (querysplit.Length == 1) + { + using (SqliteCommand cmd = new SqliteCommand(AvatarPickerOrSQL, g_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":username", querysplit[0] + "%")); + cmd.Parameters.Add(new SqliteParameter(":surname", querysplit[0] + "%")); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + Framework.AvatarPickerAvatar user = new Framework.AvatarPickerAvatar(); + user.AvatarID = new LLUUID((string) reader["UUID"]); + user.firstName = (string) reader["username"]; + user.lastName = (string) reader["surname"]; + returnlist.Add(user); + } + reader.Close(); + } + } + } + return returnlist; + } + + /// + /// Returns a user by UUID direct + /// + /// The user's account ID + /// A matching user profile + public UserAgentData GetAgentByUUID(LLUUID uuid) + { + try + { + return GetUserByUUID(uuid).currentAgent; + } + catch (Exception) + { + return null; + } + } + + /// + /// Returns a session by account name + /// + /// The account name + /// The user's session agent + public UserAgentData GetAgentByName(string name) + { + return GetAgentByName(name.Split(' ')[0], name.Split(' ')[1]); + } + + /// + /// Returns a session by account name + /// + /// The first part of the user's account name + /// The second part of the user's account name + /// A user agent + public UserAgentData GetAgentByName(string fname, string lname) + { + try + { + return GetUserByName(fname, lname).currentAgent; + } + catch (Exception) + { + return null; + } + } + + + public void StoreWebLoginKey(LLUUID AgentID, LLUUID WebLoginKey) + { + DataTable users = ds.Tables["users"]; + lock (ds) + { + DataRow row = users.Rows.Find(Util.ToRawUuidString(AgentID)); + if (row == null) + { + m_log.Warn("[WEBLOGIN]: Unable to store new web login key for non-existant user"); + } + else + { + UserProfileData user = GetUserByUUID(AgentID); + user.webLoginKey = WebLoginKey; + fillUserRow(row, user); + da.Update(ds, "users"); + + } + } + + } + + /// + /// Creates a new user profile + /// + /// The profile to add to the database + public void AddNewUserProfile(UserProfileData user) + { + DataTable users = ds.Tables["users"]; + lock (ds) + { + DataRow row = users.Rows.Find(Util.ToRawUuidString(user.UUID)); + if (row == null) + { + row = users.NewRow(); + fillUserRow(row, user); + users.Rows.Add(row); + } + else + { + fillUserRow(row, user); + + } + // This is why we're getting the 'logins never log-off'.. because It isn't clearing the + // useragents table once the useragent is null + // + // A database guy should look at this and figure out the best way to clear the useragents table. + if (user.currentAgent != null) + { + DataTable ua = ds.Tables["useragents"]; + row = ua.Rows.Find(Util.ToRawUuidString(user.UUID)); + if (row == null) + { + row = ua.NewRow(); + fillUserAgentRow(row, user.currentAgent); + ua.Rows.Add(row); + } + else + { + fillUserAgentRow(row, user.currentAgent); + } + } + else + { + // I just added this to help the standalone login situation. + //It still needs to be looked at by a Database guy + DataTable ua = ds.Tables["useragents"]; + row = ua.Rows.Find(Util.ToRawUuidString(user.UUID)); + + if (row == null) + { + // do nothing + } + else + { + row.Delete(); + ua.AcceptChanges(); + } + } + + m_log.Info("[SQLITE]: " + + "Syncing user database: " + ds.Tables["users"].Rows.Count + " users stored"); + // save changes off to disk + da.Update(ds, "users"); + } + } + + /// + /// Creates a new user profile + /// + /// The profile to add to the database + /// True on success, false on error + public bool UpdateUserProfile(UserProfileData user) + { + try + { + AddNewUserProfile(user); + return true; + } + catch (Exception) + { + return false; + } + } + + /// + /// Creates a new user agent + /// + /// The agent to add to the database + public void AddNewUserAgent(UserAgentData agent) + { + // Do nothing. yet. + } + + /// + /// Transfers money between two user accounts + /// + /// Starting account + /// End account + /// The amount to move + /// Success? + public bool MoneyTransferRequest(LLUUID from, LLUUID to, uint amount) + { + return true; + } + + /// + /// Transfers inventory between two accounts + /// + /// Move to inventory server + /// Senders account + /// Receivers account + /// Inventory item + /// Success? + public bool InventoryTransferRequest(LLUUID from, LLUUID to, LLUUID item) + { + return true; + } + + /// + /// Returns the name of the storage provider + /// + /// Storage provider name + public string getName() + { + return "Sqlite Userdata"; + } + + /// + /// Returns the version of the storage provider + /// + /// Storage provider version + public string GetVersion() + { + return "0.1"; + } + + /*********************************************************************** + * + * DataTable creation + * + **********************************************************************/ + /*********************************************************************** + * + * Database Definition Functions + * + * This should be db agnostic as we define them in ADO.NET terms + * + **********************************************************************/ + + private DataTable createUsersTable() + { + DataTable users = new DataTable("users"); + + createCol(users, "UUID", typeof (String)); + createCol(users, "username", typeof (String)); + createCol(users, "surname", typeof (String)); + createCol(users, "passwordHash", typeof (String)); + createCol(users, "passwordSalt", typeof (String)); + + createCol(users, "homeRegionX", typeof (Int32)); + createCol(users, "homeRegionY", typeof (Int32)); + createCol(users, "homeLocationX", typeof (Double)); + createCol(users, "homeLocationY", typeof (Double)); + createCol(users, "homeLocationZ", typeof (Double)); + createCol(users, "homeLookAtX", typeof (Double)); + createCol(users, "homeLookAtY", typeof (Double)); + createCol(users, "homeLookAtZ", typeof (Double)); + createCol(users, "created", typeof (Int32)); + createCol(users, "lastLogin", typeof (Int32)); + createCol(users, "rootInventoryFolderID", typeof (String)); + createCol(users, "userInventoryURI", typeof (String)); + createCol(users, "userAssetURI", typeof (String)); + createCol(users, "profileCanDoMask", typeof (Int32)); + createCol(users, "profileWantDoMask", typeof (Int32)); + createCol(users, "profileAboutText", typeof (String)); + createCol(users, "profileFirstText", typeof (String)); + createCol(users, "profileImage", typeof (String)); + createCol(users, "profileFirstImage", typeof (String)); + createCol(users, "webLoginKey", typeof(String)); + // Add in contraints + users.PrimaryKey = new DataColumn[] {users.Columns["UUID"]}; + return users; + } + + private DataTable createUserAgentsTable() + { + DataTable ua = new DataTable("useragents"); + // this is the UUID of the user + createCol(ua, "UUID", typeof (String)); + createCol(ua, "agentIP", typeof (String)); + createCol(ua, "agentPort", typeof (Int32)); + createCol(ua, "agentOnline", typeof (Boolean)); + createCol(ua, "sessionID", typeof (String)); + createCol(ua, "secureSessionID", typeof (String)); + createCol(ua, "regionID", typeof (String)); + createCol(ua, "loginTime", typeof (Int32)); + createCol(ua, "logoutTime", typeof (Int32)); + createCol(ua, "currentRegion", typeof (String)); + createCol(ua, "currentHandle", typeof (String)); + // vectors + createCol(ua, "currentPosX", typeof (Double)); + createCol(ua, "currentPosY", typeof (Double)); + createCol(ua, "currentPosZ", typeof (Double)); + // constraints + ua.PrimaryKey = new DataColumn[] {ua.Columns["UUID"]}; + + return ua; + } + + private DataTable createUserFriendsTable() + { + DataTable ua = new DataTable("userfriends"); + // table contains user <----> user relationship with perms + createCol(ua, "ownerID", typeof(String)); + createCol(ua, "friendID", typeof(String)); + createCol(ua, "friendPerms", typeof(Int32)); + createCol(ua, "ownerPerms", typeof(Int32)); + createCol(ua, "datetimestamp", typeof(Int32)); + + return ua; + } + + /*********************************************************************** + * + * Convert between ADO.NET <=> OpenSim Objects + * + * These should be database independant + * + **********************************************************************/ + + private UserProfileData buildUserProfile(DataRow row) + { + // TODO: this doesn't work yet because something more + // interesting has to be done to actually get these values + // back out. Not enough time to figure it out yet. + UserProfileData user = new UserProfileData(); + user.UUID = new LLUUID((String) row["UUID"]); + user.username = (String) row["username"]; + user.surname = (String) row["surname"]; + user.passwordHash = (String) row["passwordHash"]; + user.passwordSalt = (String) row["passwordSalt"]; + + user.homeRegionX = Convert.ToUInt32(row["homeRegionX"]); + user.homeRegionY = Convert.ToUInt32(row["homeRegionY"]); + user.homeLocation = new LLVector3( + Convert.ToSingle(row["homeLocationX"]), + Convert.ToSingle(row["homeLocationY"]), + Convert.ToSingle(row["homeLocationZ"]) + ); + user.homeLookAt = new LLVector3( + Convert.ToSingle(row["homeLookAtX"]), + Convert.ToSingle(row["homeLookAtY"]), + Convert.ToSingle(row["homeLookAtZ"]) + ); + user.created = Convert.ToInt32(row["created"]); + user.lastLogin = Convert.ToInt32(row["lastLogin"]); + user.rootInventoryFolderID = new LLUUID((String) row["rootInventoryFolderID"]); + user.userInventoryURI = (String) row["userInventoryURI"]; + user.userAssetURI = (String) row["userAssetURI"]; + user.profileCanDoMask = Convert.ToUInt32(row["profileCanDoMask"]); + user.profileWantDoMask = Convert.ToUInt32(row["profileWantDoMask"]); + user.profileAboutText = (String) row["profileAboutText"]; + user.profileFirstText = (String) row["profileFirstText"]; + user.profileImage = new LLUUID((String) row["profileImage"]); + user.profileFirstImage = new LLUUID((String) row["profileFirstImage"]); + user.webLoginKey = new LLUUID((String) row["webLoginKey"]); + + return user; + } + + private void fillFriendRow(DataRow row, LLUUID ownerID, LLUUID friendID, uint perms) + { + row["ownerID"] = ownerID.UUID.ToString(); + row["friendID"] = friendID.UUID.ToString(); + row["friendPerms"] = perms; + foreach (DataColumn col in ds.Tables["userfriends"].Columns) + { + if (row[col] == null) + { + row[col] = String.Empty; + } + } + } + + private void fillUserRow(DataRow row, UserProfileData user) + { + row["UUID"] = Util.ToRawUuidString(user.UUID); + row["username"] = user.username; + row["surname"] = user.surname; + row["passwordHash"] = user.passwordHash; + row["passwordSalt"] = user.passwordSalt; + + + row["homeRegionX"] = user.homeRegionX; + row["homeRegionY"] = user.homeRegionY; + row["homeLocationX"] = user.homeLocation.X; + row["homeLocationY"] = user.homeLocation.Y; + row["homeLocationZ"] = user.homeLocation.Z; + row["homeLookAtX"] = user.homeLookAt.X; + row["homeLookAtY"] = user.homeLookAt.Y; + row["homeLookAtZ"] = user.homeLookAt.Z; + + row["created"] = user.created; + row["lastLogin"] = user.lastLogin; + row["rootInventoryFolderID"] = user.rootInventoryFolderID; + row["userInventoryURI"] = user.userInventoryURI; + row["userAssetURI"] = user.userAssetURI; + row["profileCanDoMask"] = user.profileCanDoMask; + row["profileWantDoMask"] = user.profileWantDoMask; + row["profileAboutText"] = user.profileAboutText; + row["profileFirstText"] = user.profileFirstText; + row["profileImage"] = user.profileImage; + row["profileFirstImage"] = user.profileFirstImage; + row["webLoginKey"] = user.webLoginKey; + + // ADO.NET doesn't handle NULL very well + foreach (DataColumn col in ds.Tables["users"].Columns) + { + if (row[col] == null) + { + row[col] = String.Empty; + } + } + } + + private UserAgentData buildUserAgent(DataRow row) + { + UserAgentData ua = new UserAgentData(); + + ua.UUID = new LLUUID((String) row["UUID"]); + ua.agentIP = (String) row["agentIP"]; + ua.agentPort = Convert.ToUInt32(row["agentPort"]); + ua.agentOnline = Convert.ToBoolean(row["agentOnline"]); + ua.sessionID = new LLUUID((String) row["sessionID"]); + ua.secureSessionID = new LLUUID((String) row["secureSessionID"]); + ua.regionID = new LLUUID((String) row["regionID"]); + ua.loginTime = Convert.ToInt32(row["loginTime"]); + ua.logoutTime = Convert.ToInt32(row["logoutTime"]); + ua.currentRegion = new LLUUID((String) row["currentRegion"]); + ua.currentHandle = Convert.ToUInt64(row["currentHandle"]); + ua.currentPos = new LLVector3( + Convert.ToSingle(row["currentPosX"]), + Convert.ToSingle(row["currentPosY"]), + Convert.ToSingle(row["currentPosZ"]) + ); + return ua; + } + + private void fillUserAgentRow(DataRow row, UserAgentData ua) + { + row["UUID"] = ua.UUID; + row["agentIP"] = ua.agentIP; + row["agentPort"] = ua.agentPort; + row["agentOnline"] = ua.agentOnline; + row["sessionID"] = ua.sessionID; + row["secureSessionID"] = ua.secureSessionID; + row["regionID"] = ua.regionID; + row["loginTime"] = ua.loginTime; + row["logoutTime"] = ua.logoutTime; + row["currentRegion"] = ua.currentRegion; + row["currentHandle"] = ua.currentHandle.ToString(); + // vectors + row["currentPosX"] = ua.currentPos.X; + row["currentPosY"] = ua.currentPos.Y; + row["currentPosZ"] = ua.currentPos.Z; + } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + private void setupUserCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("users", ds.Tables["users"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("users", "UUID=:UUID", ds.Tables["users"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from users where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + private void setupUserFriendsCommands(SqliteDataAdapter daf, SqliteConnection conn) + { + daf.InsertCommand = createInsertCommand("userfriends", ds.Tables["userfriends"]); + daf.InsertCommand.Connection = conn; + + daf.UpdateCommand = createUpdateCommand("userfriends", "ownerID=:ownerID and friendID=:friendID", ds.Tables["userfriends"]); + daf.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from userfriends where ownerID=:ownerID and friendID=:friendID"); + delete.Parameters.Add(createSqliteParameter("ownerID", typeof(String))); + delete.Parameters.Add(createSqliteParameter("friendID", typeof(String))); + delete.Connection = conn; + daf.DeleteCommand = delete; + + } + + private void InitDB(SqliteConnection conn) + { + string createUsers = defineTable(createUsersTable()); + string createFriends = defineTable(createUserFriendsTable()); + + SqliteCommand pcmd = new SqliteCommand(createUsers, conn); + SqliteCommand fcmd = new SqliteCommand(createFriends, conn); + + conn.Open(); + + try + { + + pcmd.ExecuteNonQuery(); + } + catch (System.Exception) + { + m_log.Info("[USERS]: users table already exists"); + } + + try + { + fcmd.ExecuteNonQuery(); + } + catch (System.Exception) + { + m_log.Info("[USERS]: userfriends table already exists"); + } + + conn.Close(); + } + + private bool TestTables(SqliteConnection conn) + { + SqliteCommand cmd = new SqliteCommand(userSelect, conn); + SqliteCommand fcmd = new SqliteCommand(userFriendsSelect, conn); + SqliteDataAdapter pDa = new SqliteDataAdapter(cmd); + SqliteDataAdapter fDa = new SqliteDataAdapter(cmd); + + DataSet tmpDS = new DataSet(); + DataSet tmpDS2 = new DataSet(); + + try + { + pDa.Fill(tmpDS, "users"); + fDa.Fill(tmpDS2, "userfriends"); + } + catch (SqliteSyntaxException) + { + m_log.Info("[DATASTORE]: SQLite Database doesn't exist... creating"); + InitDB(conn); + } + conn.Open(); + try + { + cmd = new SqliteCommand("select webLoginKey from users limit 1;", conn); + cmd.ExecuteNonQuery(); + } + catch (SqliteSyntaxException) + { + cmd = new SqliteCommand("alter table users add column webLoginKey text default '00000000-0000-0000-0000-000000000000';", conn); + cmd.ExecuteNonQuery(); + pDa.Fill(tmpDS, "users"); + } + finally + { + conn.Close(); + } + + return true; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data/GridData.cs b/trunk/OpenSim/Framework/Data/GridData.cs new file mode 100644 index 0000000000..ee6f18ac61 --- /dev/null +++ b/trunk/OpenSim/Framework/Data/GridData.cs @@ -0,0 +1,122 @@ +/* +* 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.Collections.Generic; +using libsecondlife; + +namespace OpenSim.Framework.Data +{ + public class AvatarPickerAvatar + { + public LLUUID AvatarID; + public string firstName; + public string lastName; + + public AvatarPickerAvatar() + { + } + } + + public enum DataResponse + { + RESPONSE_OK, + RESPONSE_AUTHREQUIRED, + RESPONSE_INVALIDCREDENTIALS, + RESPONSE_ERROR + } + + /// + /// A standard grid interface + /// + public interface IGridData + { + /// + /// Returns a sim profile from a regionHandle + /// + /// A 64bit Region Handle + /// A simprofile + RegionProfileData GetProfileByHandle(ulong regionHandle); + + /// + /// Returns a sim profile from a UUID + /// + /// A 128bit UUID + /// A sim profile + RegionProfileData GetProfileByLLUUID(LLUUID UUID); + + /// + /// Returns all profiles within the specified range + /// + /// Minimum sim coordinate (X) + /// Minimum sim coordinate (Y) + /// Maximum sim coordinate (X) + /// Maximum sim coordinate (Y) + /// An array containing all the sim profiles in the specified range + RegionProfileData[] GetProfilesInRange(uint Xmin, uint Ymin, uint Xmax, uint Ymax); + + /// + /// Authenticates a sim by use of its recv key. + /// WARNING: Insecure + /// + /// The UUID sent by the sim + /// The regionhandle sent by the sim + /// The receiving key sent by the sim + /// Whether the sim has been authenticated + bool AuthenticateSim(LLUUID UUID, ulong regionHandle, string simrecvkey); + + /// + /// Initialises the interface + /// + void Initialise(); + + /// + /// Closes the interface + /// + void Close(); + + /// + /// The plugin being loaded + /// + /// A string containing the plugin name + string getName(); + + /// + /// The plugins version + /// + /// A string containing the plugin version + string getVersion(); + + /// + /// Adds a new profile to the database + /// + /// The profile to add + /// RESPONSE_OK if successful, error if not. + DataResponse AddProfile(RegionProfileData profile); + + ReservationData GetReservationAtPoint(uint x, uint y); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data/ILogData.cs b/trunk/OpenSim/Framework/Data/ILogData.cs new file mode 100644 index 0000000000..8765b5c795 --- /dev/null +++ b/trunk/OpenSim/Framework/Data/ILogData.cs @@ -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. +* +*/ +namespace OpenSim.Framework.Data +{ + /// + /// The severity of an individual log message + /// + public enum LogSeverity : int + { + /// + /// Critical: systems failure + /// + CRITICAL = 1, + /// + /// Major: warning prior to systems failure + /// + MAJOR = 2, + /// + /// Medium: an individual non-critical task failed + /// + MEDIUM = 3, + /// + /// Low: Informational warning + /// + LOW = 4, + /// + /// Info: Information + /// + INFO = 5, + /// + /// Verbose: Debug Information + /// + VERBOSE = 6 + } + + /// + /// An interface to a LogData storage system + /// + public interface ILogData + { + void saveLog(string serverDaemon, string target, string methodCall, string arguments, int priority, + string logMessage); + + /// + /// Initialises the interface + /// + void Initialise(); + + /// + /// Closes the interface + /// + void Close(); + + /// + /// The plugin being loaded + /// + /// A string containing the plugin name + string getName(); + + /// + /// The plugins version + /// + /// A string containing the plugin version + string getVersion(); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data/IniConfig.cs b/trunk/OpenSim/Framework/Data/IniConfig.cs new file mode 100644 index 0000000000..6af97701e2 --- /dev/null +++ b/trunk/OpenSim/Framework/Data/IniConfig.cs @@ -0,0 +1,98 @@ +/* +* 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.IO; +using System.Text.RegularExpressions; + +/* + Taken from public code listing at by Alex Pinsker + http://alexpinsker.blogspot.com/2005/12/reading-ini-file-from-c_113432097333021549.html + */ + +namespace OpenSim.Framework.Data +{ + /// + /// Parse settings from ini-like files + /// + public class IniFile + { + static IniFile() + { + _iniKeyValuePatternRegex = new Regex( + @"((\s)*(?([^\=^\s^\n]+))[\s^\n]* + # key part (surrounding whitespace stripped) + \= + (\s)*(?([^\n^\s]+(\n){0,1}))) + # value part (surrounding whitespace stripped) + ", + RegexOptions.IgnorePatternWhitespace | + RegexOptions.Compiled | + RegexOptions.CultureInvariant); + } + + private static Regex _iniKeyValuePatternRegex; + + public IniFile(string iniFileName) + { + _iniFileName = iniFileName; + } + + public string ParseFileReadValue(string key) + { + using (StreamReader reader = + new StreamReader(_iniFileName)) + { + do + { + string line = reader.ReadLine(); + Match match = + _iniKeyValuePatternRegex.Match(line); + if (match.Success) + { + string currentKey = + match.Groups["Key"].Value as string; + if (currentKey != null && + currentKey.Trim().CompareTo(key) == 0) + { + string value = + match.Groups["Value"].Value as string; + return value; + } + } + } while (reader.Peek() != -1); + } + return null; + } + + public string IniFileName + { + get { return _iniFileName; } + } + + private string _iniFileName; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Data/OpenSimDataReader.cs b/trunk/OpenSim/Framework/Data/OpenSimDataReader.cs new file mode 100644 index 0000000000..716a74ecb9 --- /dev/null +++ b/trunk/OpenSim/Framework/Data/OpenSimDataReader.cs @@ -0,0 +1,68 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Text; +using libsecondlife; + +using TribalMedia.Framework.Data; + +namespace OpenSim.Framework.Data +{ + public class OpenSimDataReader : BaseDataReader + { + public OpenSimDataReader(IDataReader source) : base(source) + { + } + + public LLVector3 GetVector(string s) + { + float x = GetFloat(s + "X"); + float y = GetFloat(s + "Y"); + float z = GetFloat(s + "Z"); + + LLVector3 vector = new LLVector3(x, y, z); + + return vector; + } + + public LLQuaternion GetQuaternion(string s) + { + float x = GetFloat(s + "X"); + float y = GetFloat(s + "Y"); + float z = GetFloat(s + "Z"); + float w = GetFloat(s + "W"); + + LLQuaternion quaternion = new LLQuaternion(x, y, z, w); + + return quaternion; + } + } +} diff --git a/trunk/OpenSim/Framework/Data/OpenSimDatabaseConnector.cs b/trunk/OpenSim/Framework/Data/OpenSimDatabaseConnector.cs new file mode 100644 index 0000000000..5f8a261900 --- /dev/null +++ b/trunk/OpenSim/Framework/Data/OpenSimDatabaseConnector.cs @@ -0,0 +1,78 @@ +/* +* 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.Data; +using System.Data.Common; +using libsecondlife; +using MySql.Data.MySqlClient; + +using TribalMedia.Framework.Data; + +namespace OpenSim.Framework.Data +{ + public abstract class OpenSimDatabaseConnector : BaseDatabaseConnector + { + public OpenSimDatabaseConnector(string connectionString) : base(connectionString) + { + } + + public override object ConvertToDbType(object value) + { + if (value is LLUUID) + { + return ((LLUUID) value).UUID.ToString(); + } + + return base.ConvertToDbType(value); + } + + public override BaseDataReader CreateReader(IDataReader reader) + { + return new OpenSimDataReader(reader); + } + } + + public class MySQLDatabaseMapper : OpenSimDatabaseConnector + { + public MySQLDatabaseMapper(string connectionString) + : base(connectionString) + { + } + + public override DbConnection GetNewConnection() + { + MySqlConnection connection = new MySqlConnection(m_connectionString); + return connection; + } + + public override string CreateParamName(string fieldName) + { + return "?" + fieldName; + } + } +} diff --git a/trunk/OpenSim/Framework/Data/OpenSimObjectFieldMapper.cs b/trunk/OpenSim/Framework/Data/OpenSimObjectFieldMapper.cs new file mode 100644 index 0000000000..67d9d43fb0 --- /dev/null +++ b/trunk/OpenSim/Framework/Data/OpenSimObjectFieldMapper.cs @@ -0,0 +1,103 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data.Common; +using System.Text; +using libsecondlife; + +using TribalMedia.Framework.Data; + +namespace OpenSim.Framework.Data +{ + public class OpenSimObjectFieldMapper : ObjectField + { + public OpenSimObjectFieldMapper(BaseTableMapper tableMapper, string fieldName, + ObjectGetAccessor rowMapperGetAccessor, + ObjectSetAccessor rowMapperSetAccessor) + : base(tableMapper, fieldName, rowMapperGetAccessor, rowMapperSetAccessor) + { + } + + public override void ExpandField(TObj obj, DbCommand command, List fieldNames) + { + string fieldName = FieldName; + object value = GetParamValue(obj); + + if (ValueType == typeof(LLVector3)) + { + LLVector3 vector = (LLVector3)value; + + RawAddParam(command, fieldNames, fieldName + "X", vector.X); + RawAddParam(command, fieldNames, fieldName + "Y", vector.Y); + RawAddParam(command, fieldNames, fieldName + "Z", vector.Z); + } + else if (ValueType == typeof(LLQuaternion)) + { + LLQuaternion quaternion = (LLQuaternion)value; + + RawAddParam(command, fieldNames, fieldName + "X", quaternion.X); + RawAddParam(command, fieldNames, fieldName + "Y", quaternion.Y); + RawAddParam(command, fieldNames, fieldName + "Z", quaternion.Z); + RawAddParam(command, fieldNames, fieldName + "W", quaternion.W); + } + else + { + base.ExpandField(obj, command, fieldNames); + } + } + + protected override object GetValue(BaseDataReader reader) + { + object value; + + OpenSimDataReader osreader = (OpenSimDataReader) reader; + + if (ValueType == typeof(LLVector3)) + { + value = osreader.GetVector(FieldName); + } + else if (ValueType == typeof(LLQuaternion)) + { + value = osreader.GetQuaternion(FieldName); + } + else if (ValueType == typeof(LLUUID)) + { + Guid guid = reader.GetGuid(FieldName); + value = new LLUUID(guid); + } + else + { + value = base.GetValue(reader); + } + + return value; + } + } +} diff --git a/trunk/OpenSim/Framework/Data/OpenSimTableMapper.cs b/trunk/OpenSim/Framework/Data/OpenSimTableMapper.cs new file mode 100644 index 0000000000..e7b2ba67da --- /dev/null +++ b/trunk/OpenSim/Framework/Data/OpenSimTableMapper.cs @@ -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. +* +*/ + +using System.Data; + +using TribalMedia.Framework.Data; + +namespace OpenSim.Framework.Data +{ + public abstract class OpenSimTableMapper : BaseTableMapper + { + public OpenSimTableMapper(BaseDatabaseConnector database, string tableName) : base(database, tableName) + { + } + } +} diff --git a/trunk/OpenSim/Framework/Data/PrimitiveBaseShapeTableMapper.cs b/trunk/OpenSim/Framework/Data/PrimitiveBaseShapeTableMapper.cs new file mode 100644 index 0000000000..9eb43320dd --- /dev/null +++ b/trunk/OpenSim/Framework/Data/PrimitiveBaseShapeTableMapper.cs @@ -0,0 +1,171 @@ +/* +* 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; +using OpenSim.Framework; +using TribalMedia.Framework.Data; +using libsecondlife; + +namespace OpenSim.Framework.Data +{ + public class PrimitiveBaseShapeRowMapper : BaseRowMapper + { + public Guid SceneObjectPartId; + + public PrimitiveBaseShapeRowMapper(BaseSchema schema, PrimitiveBaseShape obj) : base(schema, obj) + { + } + } + + public class PrimitiveBaseShapeTableMapper : OpenSimTableMapper + { + public PrimitiveBaseShapeTableMapper(BaseDatabaseConnector connection, string tableName) + : base(connection, tableName) + { + BaseSchema rowMapperSchema = new BaseSchema(this); + m_schema = rowMapperSchema; + + m_keyFieldMapper = rowMapperSchema.AddMapping("SceneObjectPartId", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.SceneObjectPartId; }, + delegate(PrimitiveBaseShapeRowMapper shape, Guid value) { shape.SceneObjectPartId = value; }); + + rowMapperSchema.AddMapping("PCode", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PCode; }, + delegate(PrimitiveBaseShapeRowMapper shape, byte value) { shape.Object.PCode = value; }); + + rowMapperSchema.AddMapping("PathBegin", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathBegin; }, + delegate(PrimitiveBaseShapeRowMapper shape, ushort value) { shape.Object.PathBegin = value; }); + + rowMapperSchema.AddMapping("PathEnd", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathEnd; }, + delegate(PrimitiveBaseShapeRowMapper shape, ushort value) { shape.Object.PathEnd = value; }); + + rowMapperSchema.AddMapping("PathScaleX", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathScaleX; }, + delegate(PrimitiveBaseShapeRowMapper shape, byte value) { shape.Object.PathScaleX = value; }); + + rowMapperSchema.AddMapping("PathScaleY", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathScaleY; }, + delegate(PrimitiveBaseShapeRowMapper shape, byte value) { shape.Object.PathScaleY = value; }); + + rowMapperSchema.AddMapping("PathShearX", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathShearX; }, + delegate(PrimitiveBaseShapeRowMapper shape, byte value) { shape.Object.PathShearX = value; }); + + rowMapperSchema.AddMapping("PathShearY", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathShearY; }, + delegate(PrimitiveBaseShapeRowMapper shape, byte value) { shape.Object.PathShearY = value; }); + + rowMapperSchema.AddMapping("ProfileBegin", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.ProfileBegin; }, + delegate(PrimitiveBaseShapeRowMapper shape, ushort value) { shape.Object.ProfileBegin = value; }); + + rowMapperSchema.AddMapping("ProfileEnd", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.ProfileEnd; }, + delegate(PrimitiveBaseShapeRowMapper shape, ushort value) { shape.Object.ProfileEnd = value; }); + + rowMapperSchema.AddMapping("Scale", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.Scale; }, + delegate(PrimitiveBaseShapeRowMapper shape, LLVector3 value) { shape.Object.Scale = value; }); + + rowMapperSchema.AddMapping("PathTaperX", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathTaperX; }, + delegate(PrimitiveBaseShapeRowMapper shape, sbyte value) { shape.Object.PathTaperX = value; }); + + rowMapperSchema.AddMapping("PathTaperY", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathTaperY; }, + delegate(PrimitiveBaseShapeRowMapper shape, sbyte value) { shape.Object.PathTaperY = value; }); + + rowMapperSchema.AddMapping("PathTwist", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathTwist; }, + delegate(PrimitiveBaseShapeRowMapper shape, sbyte value) { shape.Object.PathTwist = value; }); + + rowMapperSchema.AddMapping("PathRadiusOffset", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathRadiusOffset; }, + delegate(PrimitiveBaseShapeRowMapper shape, sbyte value) { shape.Object.PathRadiusOffset = value; }); + + rowMapperSchema.AddMapping("PathRevolutions", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathRevolutions; }, + delegate(PrimitiveBaseShapeRowMapper shape, byte value) { shape.Object.PathRevolutions = value; }); + + rowMapperSchema.AddMapping("PathTwistBegin", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathTwistBegin; }, + delegate(PrimitiveBaseShapeRowMapper shape, sbyte value) { shape.Object.PathTwistBegin = value; }); + + rowMapperSchema.AddMapping("PathCurve", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.PathCurve; }, + delegate(PrimitiveBaseShapeRowMapper shape, byte value) { shape.Object.PathCurve = value; }); + + rowMapperSchema.AddMapping("ProfileCurve", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.ProfileCurve; }, + delegate(PrimitiveBaseShapeRowMapper shape, byte value) { shape.Object.ProfileCurve = value; }); + + rowMapperSchema.AddMapping("ProfileHollow", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.ProfileHollow; }, + delegate(PrimitiveBaseShapeRowMapper shape, ushort value) { shape.Object.ProfileHollow = value; }); + + rowMapperSchema.AddMapping("TextureEntry", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.TextureEntry; }, + delegate(PrimitiveBaseShapeRowMapper shape, byte[] value) { shape.Object.TextureEntry = value; }); + + rowMapperSchema.AddMapping("ExtraParams", + delegate(PrimitiveBaseShapeRowMapper shape) { return shape.Object.ExtraParams; }, + delegate(PrimitiveBaseShapeRowMapper shape, byte[] value) { shape.Object.ExtraParams = value; }); + } + + public override PrimitiveBaseShapeRowMapper FromReader(BaseDataReader reader) + { + PrimitiveBaseShape shape = new PrimitiveBaseShape(); + + PrimitiveBaseShapeRowMapper mapper = new PrimitiveBaseShapeRowMapper(m_schema, shape); + mapper.FillObject( reader ); + + return mapper; + } + + public bool Update(Guid sceneObjectPartId, PrimitiveBaseShape primitiveBaseShape) + { + PrimitiveBaseShapeRowMapper mapper = CreateRowMapper(sceneObjectPartId, primitiveBaseShape); + return Update(sceneObjectPartId, mapper); + } + + public bool Add(Guid sceneObjectPartId, PrimitiveBaseShape primitiveBaseShape) + { + PrimitiveBaseShapeRowMapper mapper = CreateRowMapper(sceneObjectPartId, primitiveBaseShape); + return Add(mapper); + } + + private PrimitiveBaseShapeRowMapper CreateRowMapper(Guid sceneObjectPartId, PrimitiveBaseShape primitiveBaseShape) + { + PrimitiveBaseShapeRowMapper mapper = new PrimitiveBaseShapeRowMapper( m_schema, primitiveBaseShape ); + mapper.SceneObjectPartId = sceneObjectPartId; + return mapper; + } + } +} diff --git a/trunk/OpenSim/Framework/Data/Properties/AssemblyInfo.cs b/trunk/OpenSim/Framework/Data/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..4ef500ccea --- /dev/null +++ b/trunk/OpenSim/Framework/Data/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* 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.Framework.Data")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Framework.Data")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("3a711c34-b0c0-4264-b0fe-f366eabf9d7b")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] diff --git a/trunk/OpenSim/Framework/Data/RegionProfileData.cs b/trunk/OpenSim/Framework/Data/RegionProfileData.cs new file mode 100644 index 0000000000..8119d018fc --- /dev/null +++ b/trunk/OpenSim/Framework/Data/RegionProfileData.cs @@ -0,0 +1,219 @@ +/* +* 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; +using System.Collections; +using libsecondlife; +using Nwc.XmlRpc; + +namespace OpenSim.Framework.Data +{ + /// + /// A class which contains information known to the grid server about a region + /// + public class RegionProfileData + { + /// + /// The name of the region + /// + public string regionName = String.Empty; + + /// + /// A 64-bit number combining map position into a (mostly) unique ID + /// + public ulong regionHandle; + + /// + /// OGS/OpenSim Specific ID for a region + /// + public LLUUID UUID; + + /// + /// Coordinates of the region + /// + public uint regionLocX; + + public uint regionLocY; + public uint regionLocZ; // Reserved (round-robin, layers, etc) + + /// + /// Authentication secrets + /// + /// Not very secure, needs improvement. + public string regionSendKey = String.Empty; + + public string regionRecvKey = String.Empty; + public string regionSecret = String.Empty; + + /// + /// Whether the region is online + /// + public bool regionOnline; + + /// + /// Information about the server that the region is currently hosted on + /// + public string serverIP = String.Empty; + + public uint serverPort; + public string serverURI = String.Empty; + + public uint httpPort; + public uint remotingPort; + public string httpServerURI = String.Empty; + + /// + /// Set of optional overrides. Can be used to create non-eulicidean spaces. + /// + public ulong regionNorthOverrideHandle; + + public ulong regionSouthOverrideHandle; + public ulong regionEastOverrideHandle; + public ulong regionWestOverrideHandle; + + /// + /// Optional: URI Location of the region database + /// + /// Used for floating sim pools where the region data is not nessecarily coupled to a specific server + public string regionDataURI = String.Empty; + + /// + /// Region Asset Details + /// + public string regionAssetURI = String.Empty; + + public string regionAssetSendKey = String.Empty; + public string regionAssetRecvKey = String.Empty; + + /// + /// Region Userserver Details + /// + public string regionUserURI = String.Empty; + + public string regionUserSendKey = String.Empty; + public string regionUserRecvKey = String.Empty; + + /// + /// Region Map Texture Asset + /// + public LLUUID regionMapTextureID = new LLUUID("00000000-0000-0000-9999-000000000006"); + + // added by daTwitch + // part of an initial brutish effort to provide accurate information (as per the xml region spec) + // wrt the ownership of a given region + // the (very bad) assumption is that this value is being read and handled inconsistently or + // not at all. Current strategy is to put the code in place to support the validity of this information + // and to roll forward debugging any issues from that point + // + // this particular mod to the file provides support within the spec for RegionProfileData for the + // owner_uuid for the region + // + /// + /// this particular mod to the file provides support within the spec for RegionProfileData for the + /// owner_uuid for the region + /// + public LLUUID owner_uuid; + // + // end of daTwitch mod to this file + + /// + /// Get Sim profile data from grid server when in grid mode + /// + /// + /// + /// + /// + public RegionProfileData RequestSimProfileData(LLUUID region_uuid, string gridserver_url, + string gridserver_sendkey, string gridserver_recvkey) + { + Hashtable requestData = new Hashtable(); + requestData["region_uuid"] = region_uuid.UUID.ToString(); + requestData["authkey"] = gridserver_sendkey; + ArrayList SendParams = new ArrayList(); + SendParams.Add(requestData); + XmlRpcRequest GridReq = new XmlRpcRequest("simulator_data_request", SendParams); + XmlRpcResponse GridResp = GridReq.Send(gridserver_url, 3000); + + Hashtable responseData = (Hashtable) GridResp.Value; + + if (responseData.ContainsKey("error")) + { + return null; + } + + RegionProfileData simData = new RegionProfileData(); + simData.regionLocX = Convert.ToUInt32((string) responseData["region_locx"]); + simData.regionLocY = Convert.ToUInt32((string) responseData["region_locy"]); + simData.regionHandle = Helpers.UIntsToLong((simData.regionLocX * Constants.RegionSize), (simData.regionLocY * Constants.RegionSize)); + simData.serverIP = (string) responseData["sim_ip"]; + simData.serverPort = Convert.ToUInt32((string) responseData["sim_port"]); + simData.httpPort = Convert.ToUInt32((string) responseData["http_port"]); + simData.remotingPort = Convert.ToUInt32((string) responseData["remoting_port"]); + simData.serverURI = "http://" + simData.serverIP + ":" + simData.serverPort.ToString() + "/"; + simData.httpServerURI = "http://" + simData.serverIP + ":" + simData.httpPort.ToString() + "/"; + simData.UUID = new LLUUID((string) responseData["region_UUID"]); + simData.regionName = (string) responseData["region_name"]; + + return simData; + } + + public RegionProfileData RequestSimProfileData(ulong region_handle, string gridserver_url, + string gridserver_sendkey, string gridserver_recvkey) + { + Hashtable requestData = new Hashtable(); + requestData["region_handle"] = region_handle.ToString(); + requestData["authkey"] = gridserver_sendkey; + ArrayList SendParams = new ArrayList(); + SendParams.Add(requestData); + XmlRpcRequest GridReq = new XmlRpcRequest("simulator_data_request", SendParams); + XmlRpcResponse GridResp = GridReq.Send(gridserver_url, 3000); + + Hashtable responseData = (Hashtable) GridResp.Value; + + if (responseData.ContainsKey("error")) + { + return null; + } + + RegionProfileData simData = new RegionProfileData(); + simData.regionLocX = Convert.ToUInt32((string) responseData["region_locx"]); + simData.regionLocY = Convert.ToUInt32((string) responseData["region_locy"]); + simData.regionHandle = Helpers.UIntsToLong((simData.regionLocX * Constants.RegionSize), (simData.regionLocY * Constants.RegionSize)); + simData.serverIP = (string) responseData["sim_ip"]; + simData.serverPort = Convert.ToUInt32((string) responseData["sim_port"]); + simData.httpPort = Convert.ToUInt32((string) responseData["http_port"]); + simData.remotingPort = Convert.ToUInt32((string) responseData["remoting_port"]); + simData.httpServerURI = "http://" + simData.serverIP + ":" + simData.httpPort.ToString() + "/"; + simData.serverURI = "http://" + simData.serverIP + ":" + simData.serverPort.ToString() + "/"; + simData.UUID = new LLUUID((string) responseData["region_UUID"]); + simData.regionName = (string) responseData["region_name"]; + + return simData; + } + } +} diff --git a/trunk/OpenSim/Framework/Data/ReservationData.cs b/trunk/OpenSim/Framework/Data/ReservationData.cs new file mode 100644 index 0000000000..187ff321bb --- /dev/null +++ b/trunk/OpenSim/Framework/Data/ReservationData.cs @@ -0,0 +1,47 @@ +/* +* 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 libsecondlife; + +namespace OpenSim.Framework.Data +{ + public class ReservationData + { + public LLUUID userUUID = LLUUID.Zero; + public int reservationMinX = 0; + public int reservationMinY = 0; + public int reservationMaxX = 65536; + public int reservationMaxY = 65536; + + public string reservationName = System.String.Empty; + public string reservationCompany = System.String.Empty; + public bool status = true; + + public string gridSendKey = System.String.Empty; + public string gridRecvKey = System.String.Empty; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/EstateSettings.cs b/trunk/OpenSim/Framework/EstateSettings.cs new file mode 100644 index 0000000000..26924ebb2e --- /dev/null +++ b/trunk/OpenSim/Framework/EstateSettings.cs @@ -0,0 +1,1021 @@ +/* +* 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; +using System.IO; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework +{ + public class EstateSettings + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + //Settings to this island + private float m_billableFactor; + + public float billableFactor + { + get { return m_billableFactor; } + set + { + m_billableFactor = value; + configMember.forceSetConfigurationOption("billable_factor", m_billableFactor.ToString()); + } + } + + + private uint m_estateID; + + public uint estateID + { + get { return m_estateID; } + set + { + m_estateID = value; + configMember.forceSetConfigurationOption("estate_id", m_estateID.ToString()); + } + } + + + private uint m_parentEstateID; + + public uint parentEstateID + { + get { return m_parentEstateID; } + set + { + m_parentEstateID = value; + configMember.forceSetConfigurationOption("parent_estate_id", m_parentEstateID.ToString()); + } + } + + private byte m_maxAgents; + + public byte maxAgents + { + get { return m_maxAgents; } + set + { + m_maxAgents = value; + configMember.forceSetConfigurationOption("max_agents", m_maxAgents.ToString()); + } + } + + private float m_objectBonusFactor; + + public float objectBonusFactor + { + get { return m_objectBonusFactor; } + set + { + m_objectBonusFactor = value; + configMember.forceSetConfigurationOption("object_bonus_factor", m_objectBonusFactor.ToString()); + } + } + + private int m_redirectGridX; + + public int redirectGridX + { + get { return m_redirectGridX; } + set + { + m_redirectGridX = value; + configMember.forceSetConfigurationOption("redirect_grid_x", m_redirectGridX.ToString()); + } + } + + private int m_redirectGridY; + + public int redirectGridY + { + get { return m_redirectGridY; } + set + { + m_redirectGridY = value; + configMember.forceSetConfigurationOption("redirect_grid_y", m_redirectGridY.ToString()); + } + } + + private Simulator.RegionFlags m_regionFlags; + + public Simulator.RegionFlags regionFlags + { + get { return m_regionFlags; } + set + { + m_regionFlags = value; + configMember.forceSetConfigurationOption("region_flags", ((uint)m_regionFlags).ToString()); + } + } + + + private Simulator.SimAccess m_simAccess; + + public Simulator.SimAccess simAccess + { + get { return m_simAccess; } + set + { + m_simAccess = value; + configMember.forceSetConfigurationOption("sim_access", ((byte)m_simAccess).ToString()); + } + } + + private float m_sunHour; + + public float sunHour + { + get { return m_sunHour; } + set + { + m_sunHour = value; + configMember.forceSetConfigurationOption("sun_hour", m_sunHour.ToString()); + } + } + + private float m_terrainRaiseLimit; + + public float terrainRaiseLimit + { + get { return m_terrainRaiseLimit; } + set + { + m_terrainRaiseLimit = value; + configMember.forceSetConfigurationOption("terrain_raise_limit", m_terrainRaiseLimit.ToString()); + } + } + + private float m_terrainLowerLimit; + + public float terrainLowerLimit + { + get { return m_terrainLowerLimit; } + set + { + m_terrainLowerLimit = value; + configMember.forceSetConfigurationOption("terrain_lower_limit", m_terrainLowerLimit.ToString()); + } + } + + private bool m_useFixedSun; + + public bool useFixedSun + { + get { return m_useFixedSun; } + set + { + m_useFixedSun = value; + configMember.forceSetConfigurationOption("use_fixed_sun", m_useFixedSun.ToString()); + } + } + + + private int m_pricePerMeter; + + public int pricePerMeter + { + get { return m_pricePerMeter; } + set + { + m_pricePerMeter = value; + configMember.forceSetConfigurationOption("price_per_meter", m_pricePerMeter.ToString()); + } + } + + + private ushort m_regionWaterHeight; + + public ushort regionWaterHeight + { + get { return m_regionWaterHeight; } + set + { + m_regionWaterHeight = value; + configMember.forceSetConfigurationOption("region_water_height", m_regionWaterHeight.ToString()); + } + } + + + private bool m_regionAllowTerraform; + + public bool regionAllowTerraform + { + get { return m_regionAllowTerraform; } + set + { + m_regionAllowTerraform = value; + configMember.forceSetConfigurationOption("region_allow_terraform", m_regionAllowTerraform.ToString()); + } + } + + + // Region Information + // Low resolution 'base' textures. No longer used. + private LLUUID m_terrainBase0; + + public LLUUID terrainBase0 + { + get { return m_terrainBase0; } + set + { + m_terrainBase0 = value; + configMember.forceSetConfigurationOption("terrain_base_0", m_terrainBase0.ToString()); + } + } + + private LLUUID m_terrainBase1; + + public LLUUID terrainBase1 + { + get { return m_terrainBase1; } + set + { + m_terrainBase1 = value; + configMember.forceSetConfigurationOption("terrain_base_1", m_terrainBase1.ToString()); + } + } + + private LLUUID m_terrainBase2; + + public LLUUID terrainBase2 + { + get { return m_terrainBase2; } + set + { + m_terrainBase2 = value; + configMember.forceSetConfigurationOption("terrain_base_2", m_terrainBase2.ToString()); + } + } + + private LLUUID m_terrainBase3; + + public LLUUID terrainBase3 + { + get { return m_terrainBase3; } + set + { + m_terrainBase3 = value; + configMember.forceSetConfigurationOption("terrain_base_3", m_terrainBase3.ToString()); + } + } + + + // Higher resolution terrain textures + private LLUUID m_terrainDetail0; + + public LLUUID terrainDetail0 + { + get { return m_terrainDetail0; } + set + { + m_terrainDetail0 = value; + configMember.forceSetConfigurationOption("terrain_detail_0", m_terrainDetail0.ToString()); + } + } + + private LLUUID m_terrainDetail1; + + public LLUUID terrainDetail1 + { + get { return m_terrainDetail1; } + set + { + m_terrainDetail1 = value; + configMember.forceSetConfigurationOption("terrain_detail_1", m_terrainDetail1.ToString()); + } + } + + private LLUUID m_terrainDetail2; + + public LLUUID terrainDetail2 + { + get { return m_terrainDetail2; } + set + { + m_terrainDetail2 = value; + configMember.forceSetConfigurationOption("terrain_detail_2", m_terrainDetail2.ToString()); + } + } + + private LLUUID m_terrainDetail3; + + public LLUUID terrainDetail3 + { + get { return m_terrainDetail3; } + set + { + m_terrainDetail3 = value; + configMember.forceSetConfigurationOption("terrain_detail_3", m_terrainDetail3.ToString()); + } + } + + // First quad - each point is bilinearly interpolated at each meter of terrain + private float m_terrainStartHeight0; + + public float terrainStartHeight0 + { + get { return m_terrainStartHeight0; } + set + { + m_terrainStartHeight0 = value; + configMember.forceSetConfigurationOption("terrain_start_height_0", m_terrainStartHeight0.ToString()); + } + } + + + private float m_terrainStartHeight1; + + public float terrainStartHeight1 + { + get { return m_terrainStartHeight1; } + set + { + m_terrainStartHeight1 = value; + configMember.forceSetConfigurationOption("terrain_start_height_1", m_terrainStartHeight1.ToString()); + } + } + + private float m_terrainStartHeight2; + + public float terrainStartHeight2 + { + get { return m_terrainStartHeight2; } + set + { + m_terrainStartHeight2 = value; + configMember.forceSetConfigurationOption("terrain_start_height_2", m_terrainStartHeight2.ToString()); + } + } + + private float m_terrainStartHeight3; + + public float terrainStartHeight3 + { + get { return m_terrainStartHeight3; } + set + { + m_terrainStartHeight3 = value; + configMember.forceSetConfigurationOption("terrain_start_height_3", m_terrainStartHeight3.ToString()); + } + } + + // Second quad - also bilinearly interpolated. + // Terrain texturing is done that: + // 0..3 (0 = base0, 3 = base3) = (terrain[x,y] - start[x,y]) / range[x,y] + private float m_terrainHeightRange0; + + public float terrainHeightRange0 + { + get { return m_terrainHeightRange0; } + set + { + m_terrainHeightRange0 = value; + configMember.forceSetConfigurationOption("terrain_height_range_0", m_terrainHeightRange0.ToString()); + } + } + + private float m_terrainHeightRange1; + + public float terrainHeightRange1 + { + get { return m_terrainHeightRange1; } + set + { + m_terrainHeightRange1 = value; + configMember.forceSetConfigurationOption("terrain_height_range_1", m_terrainHeightRange1.ToString()); + } + } + + private float m_terrainHeightRange2; + + public float terrainHeightRange2 + { + get { return m_terrainHeightRange2; } + set + { + m_terrainHeightRange2 = value; + configMember.forceSetConfigurationOption("terrain_height_range_2", m_terrainHeightRange2.ToString()); + } + } + + private float m_terrainHeightRange3; + + public float terrainHeightRange3 + { + get { return m_terrainHeightRange3; } + set + { + m_terrainHeightRange3 = value; + configMember.forceSetConfigurationOption("terrain_height_range_3", m_terrainHeightRange3.ToString()); + } + } + + // Terrain Default (Must be in F32 Format!) + private string m_terrainFile; + + public string terrainFile + { + get { return m_terrainFile; } + set + { + m_terrainFile = value; + configMember.forceSetConfigurationOption("terrain_file", m_terrainFile.ToString()); + } + } + + private double m_terrainMultiplier; + + public double terrainMultiplier + { + get { return m_terrainMultiplier; } + set + { + m_terrainMultiplier = value; + configMember.forceSetConfigurationOption("terrain_multiplier", m_terrainMultiplier.ToString()); + } + } + + private float m_waterHeight; + + public float waterHeight + { + get { return m_waterHeight; } + set + { + m_waterHeight = value; + configMember.forceSetConfigurationOption("water_height", m_waterHeight.ToString()); + } + } + + private LLUUID m_terrainImageID; + + public LLUUID terrainImageID + { + get { return m_terrainImageID; } + set + { + m_terrainImageID = value; + // I don't think there is a reason that this actually + // needs to be written back to the estate settings + // file. + + // configMember.forceSetConfigurationOption("terrain_image_id", m_terrainImageID.ToString()); + } + } + + private LLUUID m_estateManager0; + private LLUUID m_estateManager1; + private LLUUID m_estateManager2; + private LLUUID m_estateManager3; + private LLUUID m_estateManager4; + private LLUUID m_estateManager5; + private LLUUID m_estateManager6; + private LLUUID m_estateManager7; + private LLUUID m_estateManager8; + private LLUUID m_estateManager9; + + public LLUUID[] estateManagers + { + get { + // returns a condensed array of LLUUIDs + return GetEstateManagers(); + + } + set + { + // Sets a Condensed array of LLUUIDS + int i = 0; + for (i = 0; i < value.Length; i++) + { + switch (i) + { + case 0: + m_estateManager0 = value[i]; + break; + case 1: + m_estateManager1 = value[i]; + break; + case 2: + m_estateManager2 = value[i]; + break; + case 3: + m_estateManager3 = value[i]; + break; + case 4: + m_estateManager4 = value[i]; + break; + case 5: + m_estateManager5 = value[i]; + break; + case 6: + m_estateManager6 = value[i]; + break; + case 7: + m_estateManager7 = value[i]; + break; + case 8: + m_estateManager8 = value[i]; + break; + case 9: + m_estateManager9 = value[i]; + break; + } + + } + // Clear the rest of them.. as they're no longer valid + for (int j = i; j < 10; j++) + { + switch (i) + { + case 0: + m_estateManager0 = LLUUID.Zero; + break; + case 1: + m_estateManager1 = LLUUID.Zero; + break; + case 2: + m_estateManager2 = LLUUID.Zero; + break; + case 3: + m_estateManager3 = LLUUID.Zero; + break; + case 4: + m_estateManager4 = LLUUID.Zero; + break; + case 5: + m_estateManager5 = LLUUID.Zero; + break; + case 6: + m_estateManager6 = LLUUID.Zero; + break; + case 7: + m_estateManager7 = LLUUID.Zero; + break; + case 8: + m_estateManager8 = LLUUID.Zero; + break; + case 9: + m_estateManager9 = LLUUID.Zero; + break; + } + } + for (i = 0; i < 10; i++) + { + // Writes out the Estate managers to the XML file. + configMember.forceSetConfigurationOption("estate_manager_" + i, (GetEstateManagerAtPos(i)).ToString()); + + } + } + } + + + + #region EstateManager Get Methods to sort out skipped spots in the XML (suser error) + + private LLUUID GetEstateManagerAtPos(int pos) + { + // This is a helper for writing them out to the xml file + switch (pos) + { + case 0: + return m_estateManager0; + + case 1: + return m_estateManager1; + + case 2: + return m_estateManager2; + + case 3: + return m_estateManager3; + + case 4: + return m_estateManager4; + + case 5: + return m_estateManager5; + + case 6: + return m_estateManager6; + + case 7: + return m_estateManager7; + + case 8: + return m_estateManager8; + + case 9: + return m_estateManager9; + + default: + return LLUUID.Zero; + + } + } + private LLUUID[] GetEstateManagers() + { + int numEstateManagers = GetNumberOfEstateManagers(); + LLUUID[] rEstateManagers = new LLUUID[numEstateManagers]; + + int pos = 0; + + for (int i = 0; i < numEstateManagers; i++) + { + pos = GetNextEstateManager(pos); + + rEstateManagers[i] = GetEstateManagerAtPos(pos); pos++; + + } + return rEstateManagers; + } + + private int GetNextEstateManager(int startpos) + { + // This is a utility function that skips over estate managers set to LLUUID.Zero + int i = startpos; + for (i=startpos;i<10;i++) + { + if (GetEstateManagerAtPos(i) != LLUUID.Zero) return i; + } + return i; + + } + private int GetNumberOfEstateManagers() + { + // This function returns the number of estate managers set + // Regardless of whether there is a skipped spot + int numEstateManagers = 0; + if (m_estateManager0 != LLUUID.Zero) numEstateManagers++; + if (m_estateManager1 != LLUUID.Zero) numEstateManagers++; + if (m_estateManager2 != LLUUID.Zero) numEstateManagers++; + if (m_estateManager3 != LLUUID.Zero) numEstateManagers++; + if (m_estateManager4 != LLUUID.Zero) numEstateManagers++; + if (m_estateManager5 != LLUUID.Zero) numEstateManagers++; + if (m_estateManager6 != LLUUID.Zero) numEstateManagers++; + if (m_estateManager7 != LLUUID.Zero) numEstateManagers++; + if (m_estateManager8 != LLUUID.Zero) numEstateManagers++; + if (m_estateManager9 != LLUUID.Zero) numEstateManagers++; + + return numEstateManagers; + } + + public void AddEstateManager(LLUUID avatarID) + { + LLUUID[] testateManagers = GetEstateManagers(); + LLUUID[] nestateManagers = new LLUUID[testateManagers.Length + 1]; + + int i = 0; + for (i = 0; i < testateManagers.Length; i++) + { + nestateManagers[i] = testateManagers[i]; + } + + nestateManagers[i] = avatarID; + + //Saves it to the estate settings file + estateManagers = nestateManagers; + + } + public void RemoveEstateManager(LLUUID avatarID) + { + int notfoundparam = 11; // starting high so the condense routine (max ten) doesn't run if we don't find it. + LLUUID[] testateManagers = GetEstateManagers(); // temporary estate managers list + + + int i = 0; + int foundpos = notfoundparam; + + // search for estate manager. + for (i = 0; i < testateManagers.Length; i++) + { + if (testateManagers[i] == avatarID) + { + foundpos = i; + break; + } + } + if (foundpos < notfoundparam) + { + LLUUID[] restateManagers = new LLUUID[testateManagers.Length - 1]; + + // fill new estate managers array up to the found spot + for (int j = 0; j < foundpos; j++) + restateManagers[j] = testateManagers[j]; + + // skip over the estate manager we're removing and compress + for (int j = foundpos + 1; j < testateManagers.Length; j++) + restateManagers[j - 1] = testateManagers[j]; + + estateManagers = restateManagers; + } + else + { + m_log.Error("[ESTATESETTINGS]: Unable to locate estate manager : " + avatarID.ToString() + " for removal"); + } + } + + #endregion + + private ConfigurationMember configMember; + + public EstateSettings() + { + // Temporary hack to prevent multiple loadings. + if (configMember == null) + { + configMember = + new ConfigurationMember(Path.Combine(Util.configDir(), "estate_settings.xml"), "ESTATE SETTINGS", + loadConfigurationOptions, handleIncomingConfiguration, true); + configMember.performConfigurationRetrieve(); + } + } + + public void loadConfigurationOptions() + { + configMember.addConfigurationOption("billable_factor", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, String.Empty, + "0.0", true); + configMember.addConfigurationOption("estate_id", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, String.Empty, "0", + true); + configMember.addConfigurationOption("parent_estate_id", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + String.Empty, "0", true); + configMember.addConfigurationOption("max_agents", ConfigurationOption.ConfigurationTypes.TYPE_BYTE, String.Empty, "40", + true); + + configMember.addConfigurationOption("object_bonus_factor", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, + String.Empty, "1.0", true); + configMember.addConfigurationOption("redirect_grid_x", ConfigurationOption.ConfigurationTypes.TYPE_INT32, String.Empty, + "0", true); + configMember.addConfigurationOption("redirect_grid_y", ConfigurationOption.ConfigurationTypes.TYPE_INT32, String.Empty, + "0", true); + configMember.addConfigurationOption("region_flags", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, String.Empty, + "0", true); + configMember.addConfigurationOption("sim_access", ConfigurationOption.ConfigurationTypes.TYPE_BYTE, String.Empty, "21", + true); + configMember.addConfigurationOption("sun_hour", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, String.Empty, "0", + true); + configMember.addConfigurationOption("terrain_raise_limit", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, + String.Empty, "0", true); + configMember.addConfigurationOption("terrain_lower_limit", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, + String.Empty, "0", true); + configMember.addConfigurationOption("use_fixed_sun", ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN, String.Empty, + "false", true); + configMember.addConfigurationOption("price_per_meter", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + String.Empty, "1", true); + configMember.addConfigurationOption("region_water_height", + ConfigurationOption.ConfigurationTypes.TYPE_UINT16, String.Empty, "20", true); + configMember.addConfigurationOption("region_allow_terraform", + ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN, String.Empty, "true", true); + + configMember.addConfigurationOption("terrain_base_0", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, String.Empty, + "b8d3965a-ad78-bf43-699b-bff8eca6c975", true); + configMember.addConfigurationOption("terrain_base_1", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, String.Empty, + "abb783e6-3e93-26c0-248a-247666855da3", true); + configMember.addConfigurationOption("terrain_base_2", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, String.Empty, + "179cdabd-398a-9b6b-1391-4dc333ba321f", true); + configMember.addConfigurationOption("terrain_base_3", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, String.Empty, + "beb169c7-11ea-fff2-efe5-0f24dc881df2", true); + + configMember.addConfigurationOption("terrain_detail_0", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + configMember.addConfigurationOption("terrain_detail_1", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + configMember.addConfigurationOption("terrain_detail_2", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + configMember.addConfigurationOption("terrain_detail_3", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + + configMember.addConfigurationOption("terrain_start_height_0", + ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, String.Empty, "10.0", true); + configMember.addConfigurationOption("terrain_start_height_1", + ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, String.Empty, "10.0", true); + configMember.addConfigurationOption("terrain_start_height_2", + ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, String.Empty, "10.0", true); + configMember.addConfigurationOption("terrain_start_height_3", + ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, String.Empty, "10.0", true); + + configMember.addConfigurationOption("terrain_height_range_0", + ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, String.Empty, "60.0", true); + configMember.addConfigurationOption("terrain_height_range_1", + ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, String.Empty, "60.0", true); + configMember.addConfigurationOption("terrain_height_range_2", + ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, String.Empty, "60.0", true); + configMember.addConfigurationOption("terrain_height_range_3", + ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, String.Empty, "60.0", true); + + configMember.addConfigurationOption("terrain_file", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, String.Empty, + "default.r32", true); + configMember.addConfigurationOption("terrain_multiplier", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, + String.Empty, "60.0", true); + configMember.addConfigurationOption("water_height", ConfigurationOption.ConfigurationTypes.TYPE_DOUBLE, String.Empty, + "20.0", true); + configMember.addConfigurationOption("terrain_image_id", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + + configMember.addConfigurationOption("estate_manager_0", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + configMember.addConfigurationOption("estate_manager_1", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + configMember.addConfigurationOption("estate_manager_2", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + configMember.addConfigurationOption("estate_manager_3", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + configMember.addConfigurationOption("estate_manager_4", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + configMember.addConfigurationOption("estate_manager_5", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + configMember.addConfigurationOption("estate_manager_6", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + configMember.addConfigurationOption("estate_manager_7", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + configMember.addConfigurationOption("estate_manager_8", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + configMember.addConfigurationOption("estate_manager_9", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + String.Empty, "00000000-0000-0000-0000-000000000000", true); + + } + + public bool handleIncomingConfiguration(string configuration_key, object configuration_result) + { + switch (configuration_key) + { + case "billable_factor": + m_billableFactor = (float) configuration_result; + break; + case "estate_id": + m_estateID = (uint) configuration_result; + break; + case "parent_estate_id": + m_parentEstateID = (uint) configuration_result; + break; + case "max_agents": + m_maxAgents = (byte) configuration_result; + break; + + case "object_bonus_factor": + m_objectBonusFactor = (float) configuration_result; + break; + case "redirect_grid_x": + m_redirectGridX = (int) configuration_result; + break; + case "redirect_grid_y": + m_redirectGridY = (int) configuration_result; + break; + case "region_flags": + m_regionFlags = (Simulator.RegionFlags) ((uint) configuration_result); + break; + case "sim_access": + m_simAccess = (Simulator.SimAccess) ((byte) configuration_result); + break; + case "sun_hour": + m_sunHour = (float) configuration_result; + break; + case "terrain_raise_limit": + m_terrainRaiseLimit = (float) configuration_result; + break; + case "terrain_lower_limit": + m_terrainLowerLimit = (float) configuration_result; + break; + case "use_fixed_sun": + m_useFixedSun = (bool) configuration_result; + break; + case "price_per_meter": + m_pricePerMeter = Convert.ToInt32(configuration_result); + break; + case "region_water_height": + m_regionWaterHeight = (ushort) configuration_result; + break; + case "region_allow_terraform": + m_regionAllowTerraform = (bool) configuration_result; + break; + + case "terrain_base_0": + m_terrainBase0 = (LLUUID) configuration_result; + break; + case "terrain_base_1": + m_terrainBase1 = (LLUUID) configuration_result; + break; + case "terrain_base_2": + m_terrainBase2 = (LLUUID) configuration_result; + break; + case "terrain_base_3": + m_terrainBase3 = (LLUUID) configuration_result; + break; + + case "terrain_detail_0": + m_terrainDetail0 = (LLUUID) configuration_result; + break; + case "terrain_detail_1": + m_terrainDetail1 = (LLUUID) configuration_result; + break; + case "terrain_detail_2": + m_terrainDetail2 = (LLUUID) configuration_result; + break; + case "terrain_detail_3": + m_terrainDetail3 = (LLUUID) configuration_result; + break; + + case "terrain_start_height_0": + m_terrainStartHeight0 = (float) configuration_result; + break; + case "terrain_start_height_1": + m_terrainStartHeight1 = (float) configuration_result; + break; + case "terrain_start_height_2": + m_terrainStartHeight2 = (float) configuration_result; + break; + case "terrain_start_height_3": + m_terrainStartHeight3 = (float) configuration_result; + break; + + case "terrain_height_range_0": + m_terrainHeightRange0 = (float) configuration_result; + break; + case "terrain_height_range_1": + m_terrainHeightRange1 = (float) configuration_result; + break; + case "terrain_height_range_2": + m_terrainHeightRange2 = (float) configuration_result; + break; + case "terrain_height_range_3": + m_terrainHeightRange3 = (float) configuration_result; + break; + + case "terrain_file": + m_terrainFile = (string) configuration_result; + break; + case "terrain_multiplier": + m_terrainMultiplier = Convert.ToDouble(configuration_result); + break; + case "water_height": + double tmpVal = (double) configuration_result; + m_waterHeight = (float) tmpVal; + break; + case "terrain_image_id": + m_terrainImageID = (LLUUID) configuration_result; + break; + + case "estate_manager_0": + m_estateManager0 = (LLUUID)configuration_result; + break; + case "estate_manager_1": + m_estateManager1 = (LLUUID)configuration_result; + break; + case "estate_manager_2": + m_estateManager2 = (LLUUID)configuration_result; + break; + case "estate_manager_3": + m_estateManager3 = (LLUUID)configuration_result; + break; + case "estate_manager_4": + m_estateManager4 = (LLUUID)configuration_result; + break; + case "estate_manager_5": + m_estateManager5 = (LLUUID)configuration_result; + break; + case "estate_manager_6": + m_estateManager6 = (LLUUID)configuration_result; + break; + case "estate_manager_7": + m_estateManager7 = (LLUUID)configuration_result; + break; + case "estate_manager_8": + m_estateManager8 = (LLUUID)configuration_result; + break; + case "estate_manager_9": + m_estateManager9 = (LLUUID)configuration_result; + break; + + } + + return true; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/FriendListItem.cs b/trunk/OpenSim/Framework/FriendListItem.cs new file mode 100644 index 0000000000..f090ab1c4b --- /dev/null +++ b/trunk/OpenSim/Framework/FriendListItem.cs @@ -0,0 +1,51 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; + +namespace OpenSim.Framework +{ + public class FriendListItem + { + + public LLUUID FriendListOwner; + public LLUUID Friend; + + // These are what the list owner gives the friend permission to do + public uint FriendPerms; + + // These are what the friend gives the listowner permission to do + public uint FriendListOwnerPerms; + + public bool onlinestatus = false; + + + } +} diff --git a/trunk/OpenSim/Framework/GridConfig.cs b/trunk/OpenSim/Framework/GridConfig.cs new file mode 100644 index 0000000000..0723756d87 --- /dev/null +++ b/trunk/OpenSim/Framework/GridConfig.cs @@ -0,0 +1,149 @@ +/* +* 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; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework +{ + public class GridConfig + { + public string GridOwner = String.Empty; + public string DefaultAssetServer = String.Empty; + public string AssetSendKey = String.Empty; + public string AssetRecvKey = String.Empty; + + public string DefaultUserServer = String.Empty; + public string UserSendKey = String.Empty; + public string UserRecvKey = String.Empty; + + public string SimSendKey = String.Empty; + public string SimRecvKey = String.Empty; + + public string DatabaseProvider = String.Empty; + + + public static uint DefaultHttpPort = 8001; + public uint HttpPort = DefaultHttpPort; + + public string AllowForcefulBanlines = "TRUE"; + + private ConfigurationMember configMember; + + public GridConfig(string description, string filename) + { + configMember = + new ConfigurationMember(filename, description, loadConfigurationOptions, handleIncomingConfiguration, true); + configMember.performConfigurationRetrieve(); + } + + public void loadConfigurationOptions() + { + configMember.addConfigurationOption("grid_owner", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "OGS Grid Owner", "OGS development team", false); + configMember.addConfigurationOption("default_asset_server", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "Default Asset Server URI", + "http://127.0.0.1:" + AssetConfig.DefaultHttpPort.ToString() + "/", + false); + configMember.addConfigurationOption("asset_send_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to send to asset server", "null", false); + configMember.addConfigurationOption("asset_recv_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to expect from asset server", "null", false); + + configMember.addConfigurationOption("default_user_server", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "Default User Server URI", + "http://127.0.0.1:" + UserConfig.DefaultHttpPort.ToString() + "/", false); + configMember.addConfigurationOption("user_send_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to send to user server", "null", false); + configMember.addConfigurationOption("user_recv_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to expect from user server", "null", false); + + configMember.addConfigurationOption("sim_send_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to send to a simulator", "null", false); + configMember.addConfigurationOption("sim_recv_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to expect from a simulator", "null", false); + configMember.addConfigurationOption("database_provider", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "DLL for database provider", "OpenSim.Framework.Data.MySQL.dll", false); + + configMember.addConfigurationOption("http_port", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Http Listener port", DefaultHttpPort.ToString(), false); + + configMember.addConfigurationOption("allow_forceful_banlines", + ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Allow Forceful Banlines", "TRUE", true); + } + + public bool handleIncomingConfiguration(string configuration_key, object configuration_result) + { + switch (configuration_key) + { + case "grid_owner": + GridOwner = (string) configuration_result; + break; + case "default_asset_server": + DefaultAssetServer = (string) configuration_result; + break; + case "asset_send_key": + AssetSendKey = (string) configuration_result; + break; + case "asset_recv_key": + AssetRecvKey = (string) configuration_result; + break; + case "default_user_server": + DefaultUserServer = (string) configuration_result; + break; + case "user_send_key": + UserSendKey = (string) configuration_result; + break; + case "user_recv_key": + UserRecvKey = (string) configuration_result; + break; + case "sim_send_key": + SimSendKey = (string) configuration_result; + break; + case "sim_recv_key": + SimRecvKey = (string) configuration_result; + break; + case "database_provider": + DatabaseProvider = (string) configuration_result; + break; + case "http_port": + HttpPort = (uint) configuration_result; + break; + case "allow_forceful_banlines": + AllowForcefulBanlines = (string) configuration_result; + break; + } + + return true; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/GridInstantMessage.cs b/trunk/OpenSim/Framework/GridInstantMessage.cs new file mode 100644 index 0000000000..6ae34241db --- /dev/null +++ b/trunk/OpenSim/Framework/GridInstantMessage.cs @@ -0,0 +1,64 @@ +/* +* 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; +using OpenSim.Framework; + + +namespace OpenSim.Framework +{ + + [Serializable] + public class GridInstantMessage + { + public Guid fromAgentID; + public Guid fromAgentSession; + public Guid toAgentID; + public Guid imSessionID; + public uint timestamp; + public string fromAgentName; + + public string message; + public byte dialog; + public bool fromGroup; + public byte offline; + + public uint ParentEstateID; + + public sLLVector3 Position; + + public Guid RegionID; + + public byte[] binaryBucket; + + public GridInstantMessage() + { + + } + } +} diff --git a/trunk/OpenSim/Framework/IAssetLoader.cs b/trunk/OpenSim/Framework/IAssetLoader.cs new file mode 100644 index 0000000000..df0b81b7f7 --- /dev/null +++ b/trunk/OpenSim/Framework/IAssetLoader.cs @@ -0,0 +1,38 @@ +/* +* 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; + +namespace OpenSim.Framework +{ + public interface IAssetLoader + { + void ForEachDefaultXmlAsset(Action action); + void ForEachDefaultXmlAsset(string assetSetFilename, Action action); + } +} diff --git a/trunk/OpenSim/Framework/IAssetProvider.cs b/trunk/OpenSim/Framework/IAssetProvider.cs new file mode 100644 index 0000000000..ad1cf6654c --- /dev/null +++ b/trunk/OpenSim/Framework/IAssetProvider.cs @@ -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. +* +*/ + +using libsecondlife; + +namespace OpenSim.Framework +{ + public interface IAssetProvider : IPlugin + { + AssetBase FetchAsset(LLUUID uuid); + void CreateAsset(AssetBase asset); + void UpdateAsset(AssetBase asset); + bool ExistsAsset(LLUUID uuid); + void CommitAssets(); // force a sync to the database + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/IAssetServer.cs b/trunk/OpenSim/Framework/IAssetServer.cs new file mode 100644 index 0000000000..df36623785 --- /dev/null +++ b/trunk/OpenSim/Framework/IAssetServer.cs @@ -0,0 +1,57 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; + +namespace OpenSim.Framework +{ + /// + /// Description of IAssetServer. + /// + public interface IAssetServer + { + void SetReceiver(IAssetReceiver receiver); + void RequestAsset(LLUUID assetID, bool isTexture); + void UpdateAsset(AssetBase asset); + void StoreAndCommitAsset(AssetBase asset); + void Close(); + } + + // could change to delegate? + public interface IAssetReceiver + { + void AssetReceived(AssetBase asset, bool IsTexture); + void AssetNotFound(LLUUID assetID); + } + + public interface IAssetPlugin + { + IAssetServer GetAssetServer(); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/IClientAPI.cs b/trunk/OpenSim/Framework/IClientAPI.cs new file mode 100644 index 0000000000..bdddc33b7e --- /dev/null +++ b/trunk/OpenSim/Framework/IClientAPI.cs @@ -0,0 +1,657 @@ +/* +* 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; +using System.Collections.Generic; +using System.Net; +using libsecondlife; +using libsecondlife.Packets; + +namespace OpenSim.Framework +{ + // Base Args Interface + public interface IEventArgs + { + IScene Scene { get; set; } + + IClientAPI Sender { get; set; } + } + + public delegate void ViewerEffectEventHandler(IClientAPI sender, ViewerEffectPacket.EffectBlock[] effectBlock); + + public delegate void ChatFromViewer(Object sender, ChatFromViewerArgs e); + + public enum ChatTypeEnum + { + Whisper = 0, + Say = 1, + Shout = 2, + // 3 is an obsolete version of Say + StartTyping = 4, + StopTyping = 5, + Broadcast = 0xFF + } + + public enum ThrottleOutPacketType : int + { + Resend = 0, + Land = 1, + Wind = 2, + Cloud = 3, + Task = 4, + Texture = 5, + Asset = 6, + Unknown = 7, + Back = 8 + } + + /// + /// ChatFromViewer Arguments + /// + public class ChatFromViewerArgs : EventArgs, IEventArgs + { + protected string m_message; + protected ChatTypeEnum m_type; + protected int m_channel; + protected LLVector3 m_position; + protected string m_from; + + protected IClientAPI m_sender; + protected IScene m_scene; + + /// + /// The message sent by the user + /// + public string Message + { + get { return m_message; } + set { m_message = value; } + } + + /// + /// The type of message, eg say, shout, broadcast. + /// + public ChatTypeEnum Type + { + get { return m_type; } + set { m_type = value; } + } + + /// + /// Which channel was this message sent on? Different channels may have different listeners. Public chat is on channel zero. + /// + public int Channel + { + get { return m_channel; } + set { m_channel = value; } + } + + /// + /// The position of the sender at the time of the message broadcast. + /// + public LLVector3 Position + { + get { return m_position; } + set { m_position = value; } + } + + /// + /// The name of the sender (needed for scripts) + /// + public string From + { + get { return m_from; } + set { m_from = value; } + } + + /// + /// The client responsible for sending the message, or null. + /// + public IClientAPI Sender + { + get { return m_sender; } + set { m_sender = value; } + } + + /// + /// + /// + public IScene Scene + { + get { return m_scene; } + set { m_scene = value; } + } + + public ChatFromViewerArgs() + { + m_position = new LLVector3(); + } + } + + public class TextureRequestArgs : EventArgs + { + protected LLUUID m_requestedAssetID; + private sbyte m_discardLevel; + private uint m_packetNumber; + private float m_priority; + + public float Priority + { + get { return m_priority; } + set { m_priority = value; } + } + + /// + /// + /// + public uint PacketNumber + { + get { return m_packetNumber; } + set { m_packetNumber = value; } + } + + /// + /// + /// + public sbyte DiscardLevel + { + get { return m_discardLevel; } + set { m_discardLevel = value; } + } + + /// + /// + /// + public LLUUID RequestedAssetID + { + get { return m_requestedAssetID; } + set { m_requestedAssetID = value; } + } + } + + public class AvatarWearingArgs : EventArgs + { + private List m_nowWearing = new List(); + + /// + /// + /// + public List NowWearing + { + get { return m_nowWearing; } + set { m_nowWearing = value; } + } + + public class Wearable + { + public LLUUID ItemID = new LLUUID("00000000-0000-0000-0000-000000000000"); + public byte Type = 0; + + public Wearable(LLUUID itemId, byte type) + { + ItemID = itemId; + Type = type; + } + } + } + + public delegate void TextureRequest(Object sender, TextureRequestArgs e); + + public delegate void AvatarNowWearing(Object sender, AvatarWearingArgs e); + + public delegate void ImprovedInstantMessage(IClientAPI remoteclient, + LLUUID fromAgentID, LLUUID fromAgentSession, LLUUID toAgentID, LLUUID imSessionID, uint timestamp, + string fromAgentName, string message, byte dialog, bool fromGroup, byte offline, uint ParentEstateID, + LLVector3 Position, LLUUID RegionID, byte[] binaryBucket); // This shouldn't be cut down... + // especially if we're ever going to implement groups, presence, estate message dialogs... + + public delegate void RezObject(IClientAPI remoteClient, LLUUID itemID, LLVector3 RayEnd, LLVector3 RayStart, + LLUUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, + uint EveryoneMask, uint GroupMask, uint NextOwnerMask, uint ItemFlags, + bool RezSelected, bool RemoveItem, LLUUID fromTaskID ); + + public delegate void RezSingleAttachmentFromInv(IClientAPI remoteClient, LLUUID itemID, uint AttachmentPt, + uint ItemFlags, uint NextOwnerMask); + + public delegate void ObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, LLQuaternion rot); + + public delegate void ModifyTerrain( + float height, float seconds, byte size, byte action, float north, float west, float south, float east, + IClientAPI remoteClient); + + public delegate void SetAppearance(byte[] texture, AgentSetAppearancePacket.VisualParamBlock[] visualParam); + + public delegate void StartAnim(IClientAPI remoteClient, LLUUID animID, int seq); + + public delegate void StopAnim(IClientAPI remoteClient, LLUUID animID); + + public delegate void LinkObjects(uint parent, List children); + + public delegate void DelinkObjects(List primIds); + + public delegate void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY); + + public delegate void RequestMapName(IClientAPI remoteClient, string mapName); + + public delegate void TeleportLocationRequest( + IClientAPI remoteClient, ulong regionHandle, LLVector3 position, LLVector3 lookAt, uint flags); + + public delegate void DisconnectUser(); + + public delegate void RequestAvatarProperties(IClientAPI remoteClient, LLUUID avatarID); + + public delegate void SetAlwaysRun(IClientAPI remoteClient, bool SetAlwaysRun); + + public delegate void GenericCall2(); + + // really don't want to be passing packets in these events, so this is very temporary. + public delegate void GenericCall4(Packet packet, IClientAPI remoteClient); + + public delegate void GenericCall5(IClientAPI remoteClient, bool status); + + public delegate void GenericCall7(IClientAPI remoteClient, uint localID, string message); + + public delegate void UpdateShape(LLUUID agentID, uint localID, ObjectShapePacket.ObjectDataBlock shapeBlock); + + public delegate void ObjectExtraParams(LLUUID agentID, uint localID, ushort type, bool inUse, byte[] data); + + public delegate void ObjectSelect(uint localID, IClientAPI remoteClient); + + public delegate void RequestObjectPropertiesFamily( + IClientAPI remoteClient, LLUUID AgentID, uint RequestFlags, LLUUID TaskID); + + public delegate void ObjectDeselect(uint localID, IClientAPI remoteClient); + + public delegate void UpdatePrimFlags(uint localID, Packet packet, IClientAPI remoteClient); + + public delegate void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient); + + public delegate void UpdateVector(uint localID, LLVector3 pos, IClientAPI remoteClient); + + public delegate void UpdatePrimRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient); + + public delegate void UpdatePrimSingleRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient); + + public delegate void UpdatePrimGroupRotation(uint localID, LLVector3 pos, LLQuaternion rot, IClientAPI remoteClient); + + public delegate void ObjectDuplicate(uint localID, LLVector3 offset, uint dupeFlags, LLUUID AgentID, LLUUID GroupID); + + public delegate void StatusChange(bool status); + + public delegate void NewAvatar(IClientAPI remoteClient, LLUUID agentID, bool status); + + public delegate void UpdateAgent(IClientAPI remoteClient, AgentUpdatePacket agentData); + + public delegate void AgentRequestSit(IClientAPI remoteClient, LLUUID agentID, LLUUID targetID, LLVector3 offset); + + public delegate void AgentSit(IClientAPI remoteClient, LLUUID agentID); + + public delegate void AvatarPickerRequest(IClientAPI remoteClient, LLUUID agentdata, LLUUID queryID, string UserQuery + ); + + public delegate void MoveObject(LLUUID objectID, LLVector3 offset, LLVector3 grapPos, IClientAPI remoteClient); + + public delegate void ParcelAccessListRequest( + LLUUID agentID, LLUUID sessionID, uint flags, int sequenceID, int landLocalID, IClientAPI remote_client); + + public delegate void ParcelAccessListUpdateRequest( + LLUUID agentID, LLUUID sessionID, uint flags, int landLocalID, List entries, + IClientAPI remote_client); + + public delegate void ParcelPropertiesRequest( + int start_x, int start_y, int end_x, int end_y, int sequence_id, bool snap_selection, IClientAPI remote_client); + + public delegate void ParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client); + + public delegate void ParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client); + + public delegate void ParcelPropertiesUpdateRequest(ParcelPropertiesUpdatePacket packet, IClientAPI remote_client); + + public delegate void ParcelSelectObjects(int land_local_id, int request_type, IClientAPI remote_client); + + public delegate void ParcelObjectOwnerRequest(int local_id, IClientAPI remote_client); + + public delegate void EstateOwnerMessageRequest(EstateOwnerMessagePacket packet, IClientAPI remote_client); + + public delegate void RegionInfoRequest(IClientAPI remote_client, LLUUID sessionID); + + public delegate void EstateCovenantRequest(IClientAPI remote_client, LLUUID sessionID); + + public delegate void UUIDNameRequest(LLUUID id, IClientAPI remote_client); + + public delegate void AddNewPrim(LLUUID ownerID, LLVector3 RayEnd, LLQuaternion rot, PrimitiveBaseShape shape, byte bypassRaycast, LLVector3 RayStart, LLUUID RayTargetID, byte RayEndIsIntersection); + + public delegate void RequestGodlikePowers(LLUUID AgentID, LLUUID SessionID, LLUUID token, IClientAPI remote_client); + + public delegate void GodKickUser( + LLUUID GodAgentID, LLUUID GodSessionID, LLUUID AgentID, uint kickflags, byte[] reason); + + public delegate void CreateInventoryFolder( + IClientAPI remoteClient, LLUUID folderID, ushort folderType, string folderName, LLUUID parentID); + + public delegate void UpdateInventoryFolder( + IClientAPI remoteClient, LLUUID folderID, ushort type, string name, LLUUID parentID); + + public delegate void MoveInventoryFolder( + IClientAPI remoteClient, LLUUID folderID, LLUUID parentID); + + public delegate void CreateNewInventoryItem( + IClientAPI remoteClient, LLUUID transActionID, LLUUID folderID, uint callbackID, string description, string name, + sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask); + + public delegate void FetchInventoryDescendents( + IClientAPI remoteClient, LLUUID folderID, LLUUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder); + + public delegate void PurgeInventoryDescendents( + IClientAPI remoteClient, LLUUID folderID); + + public delegate void FetchInventory(IClientAPI remoteClient, LLUUID itemID, LLUUID ownerID); + + public delegate void RequestTaskInventory(IClientAPI remoteClient, uint localID); + + public delegate void UpdateInventoryItem( + IClientAPI remoteClient, LLUUID transactionID, LLUUID itemID, string name, string description, + uint nextOwnerMask); + + public delegate void CopyInventoryItem( + IClientAPI remoteClient, uint callbackID, LLUUID oldAgentID, LLUUID oldItemID, LLUUID newFolderID, + string newName); + + public delegate void MoveInventoryItem( + IClientAPI remoteClient, LLUUID folderID, LLUUID itemID, int length, string newName); + + public delegate void RemoveInventoryItem( + IClientAPI remoteClient, LLUUID itemID); + + public delegate void RemoveInventoryFolder( + IClientAPI remoteClient, LLUUID folderID); + + public delegate void RezScript(IClientAPI remoteClient, LLUUID itemID, uint localID); + + public delegate void UpdateTaskInventory(IClientAPI remoteClient, LLUUID itemID, LLUUID folderID, uint localID); + + public delegate void RemoveTaskInventory(IClientAPI remoteClient, LLUUID itemID, uint localID); + + public delegate void UDPAssetUploadRequest( + IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data, bool storeLocal, + bool tempFile); + + public delegate void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data); + + public delegate void RequestXfer(IClientAPI remoteClient, ulong xferID, string fileName); + + public delegate void ConfirmXfer(IClientAPI remoteClient, ulong xferID, uint packetID); + + public delegate void FriendActionDelegate(IClientAPI remoteClient,LLUUID agentID,LLUUID transactionID,List callingCardFolders); + + public delegate void FriendshipTermination(IClientAPI remoteClient,LLUUID agentID, LLUUID ExID); + + public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes); + + public delegate void MoneyTransferRequest(LLUUID sourceID, LLUUID destID, int amount, int transactionType, string description); + + // We keep all this information for fraud purposes in the future. + public delegate void MoneyBalanceRequest(IClientAPI remoteClient, LLUUID agentID, LLUUID sessionID, LLUUID TransactionID); + + public delegate void ObjectPermissions(IClientAPI controller, LLUUID agentID, LLUUID sessionID, byte field, uint localId, uint mask, byte set); + + public interface IClientAPI + { + event ImprovedInstantMessage OnInstantMessage; + event ChatFromViewer OnChatFromViewer; + event TextureRequest OnRequestTexture; + event RezObject OnRezObject; + event ModifyTerrain OnModifyTerrain; + event SetAppearance OnSetAppearance; + event AvatarNowWearing OnAvatarNowWearing; + event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; + event ObjectAttach OnObjectAttach; + event StartAnim OnStartAnim; + event StopAnim OnStopAnim; + event LinkObjects OnLinkObjects; + event DelinkObjects OnDelinkObjects; + event RequestMapBlocks OnRequestMapBlocks; + event RequestMapName OnMapNameRequest; + event TeleportLocationRequest OnTeleportLocationRequest; + event DisconnectUser OnDisconnectUser; + event RequestAvatarProperties OnRequestAvatarProperties; + event SetAlwaysRun OnSetAlwaysRun; + event GenericCall4 OnDeRezObject; + event Action OnRegionHandShakeReply; + event GenericCall2 OnRequestWearables; + event GenericCall2 OnCompleteMovementToRegion; + event UpdateAgent OnAgentUpdate; + event AgentRequestSit OnAgentRequestSit; + event AgentSit OnAgentSit; + event AvatarPickerRequest OnAvatarPickerRequest; + event Action OnRequestAvatarsData; + event AddNewPrim OnAddPrim; + + event RequestGodlikePowers OnRequestGodlikePowers; + event GodKickUser OnGodKickUser; + + event ObjectDuplicate OnObjectDuplicate; + event UpdateVector OnGrabObject; + event ObjectSelect OnDeGrabObject; + event MoveObject OnGrabUpdate; + + event UpdateShape OnUpdatePrimShape; + event ObjectExtraParams OnUpdateExtraParams; + event ObjectSelect OnObjectSelect; + event ObjectDeselect OnObjectDeselect; + event GenericCall7 OnObjectDescription; + event GenericCall7 OnObjectName; + event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; + event UpdatePrimFlags OnUpdatePrimFlags; + event UpdatePrimTexture OnUpdatePrimTexture; + event UpdateVector OnUpdatePrimGroupPosition; + event UpdateVector OnUpdatePrimSinglePosition; + event UpdatePrimRotation OnUpdatePrimGroupRotation; + event UpdatePrimSingleRotation OnUpdatePrimSingleRotation; + event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; + event UpdateVector OnUpdatePrimScale; + event StatusChange OnChildAgentStatus; + event GenericCall2 OnStopMovement; + event Action OnRemoveAvatar; + event ObjectPermissions OnObjectPermissions; + + event CreateNewInventoryItem OnCreateNewInventoryItem; + event CreateInventoryFolder OnCreateNewInventoryFolder; + event UpdateInventoryFolder OnUpdateInventoryFolder; + event MoveInventoryFolder OnMoveInventoryFolder; + event FetchInventoryDescendents OnFetchInventoryDescendents; + event PurgeInventoryDescendents OnPurgeInventoryDescendents; + event FetchInventory OnFetchInventory; + event RequestTaskInventory OnRequestTaskInventory; + event UpdateInventoryItem OnUpdateInventoryItem; + event CopyInventoryItem OnCopyInventoryItem; + event MoveInventoryItem OnMoveInventoryItem; + event RemoveInventoryFolder OnRemoveInventoryFolder; + event RemoveInventoryItem OnRemoveInventoryItem; + event UDPAssetUploadRequest OnAssetUploadRequest; + event XferReceive OnXferReceive; + event RequestXfer OnRequestXfer; + event ConfirmXfer OnConfirmXfer; + event RezScript OnRezScript; + event UpdateTaskInventory OnUpdateTaskInventory; + event RemoveTaskInventory OnRemoveTaskItem; + + event UUIDNameRequest OnNameFromUUIDRequest; + + event ParcelAccessListRequest OnParcelAccessListRequest; + event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest; + event ParcelPropertiesRequest OnParcelPropertiesRequest; + event ParcelDivideRequest OnParcelDivideRequest; + event ParcelJoinRequest OnParcelJoinRequest; + event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; + event ParcelSelectObjects OnParcelSelectObjects; + event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest; + event EstateOwnerMessageRequest OnEstateOwnerMessage; + event RegionInfoRequest OnRegionInfoRequest; + event EstateCovenantRequest OnEstateCovenantRequest; + + event FriendActionDelegate OnApproveFriendRequest; + event FriendActionDelegate OnDenyFriendRequest; + event FriendshipTermination OnTerminateFriendship; + event PacketStats OnPacketStats; + + // Financial packets + event MoneyTransferRequest OnMoneyTransferRequest; + + event MoneyBalanceRequest OnMoneyBalanceRequest; + + + LLVector3 StartPos { get; set; } + + LLUUID AgentId { get; } + + LLUUID SessionId { get; } + + LLUUID SecureSessionId { get; } + + string FirstName { get; } + + string LastName { get; } + + /// + /// Returns the full name of the agent/avatar represented by this client + /// + /// + /// + string Name { get; } + + uint CircuitCode { get; } + + void OutPacket(Packet newPack, ThrottleOutPacketType packType); + void SendWearables(AvatarWearable[] wearables, int serial); + void SendAppearance(LLUUID agentID, byte[] visualParams, byte[] textureEntry); + void SendStartPingCheck(byte seq); + void SendKillObject(ulong regionHandle, uint localID); + void SendAnimations(LLUUID[] animID, int[] seqs, LLUUID sourceAgentId); + void SendRegionHandshake(RegionInfo regionInfo); + void SendChatMessage(string message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID); + void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID); + + void SendInstantMessage(LLUUID fromAgent, LLUUID fromAgentSession, string message, LLUUID toAgent, + LLUUID imSessionID, string fromName, byte dialog, uint timeStamp); + + void SendLayerData(float[] map); + void SendLayerData(int px, int py, float[] map); + void MoveAgentIntoRegion(RegionInfo regInfo, LLVector3 pos, LLVector3 look); + void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourExternalEndPoint); + AgentCircuitData RequestClientInfo(); + + void CrossRegion(ulong newRegionHandle, LLVector3 pos, LLVector3 lookAt, IPEndPoint newRegionExternalEndPoint, + string capsURL); + + void SendMapBlock(List mapBlocks); + void SendLocalTeleport(LLVector3 position, LLVector3 lookAt, uint flags); + + void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, uint locationID, + uint flags, string capsURL); + + void SendTeleportFailed(string reason); + void SendTeleportLocationStart(); + void SendMoneyBalance(LLUUID transaction, bool success, byte[] description, int balance); + + void SendAvatarData(ulong regionHandle, string firstName, string lastName, LLUUID avatarID, uint avatarLocalID, + LLVector3 Pos, byte[] textureEntry, uint parentID); + + void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, + LLVector3 velocity, LLQuaternion rotation); + + void SendCoarseLocationUpdate(List CoarseLocations); + + void AttachObject(uint localID, LLQuaternion rotation, byte attachPoint); + void SetChildAgentThrottle(byte[] throttle); + + void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, + LLVector3 pos, uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color, + uint parentID, byte[] particleSystem, LLQuaternion rotation, byte clickAction, byte[] textureanimation); + + void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, + LLVector3 pos, uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color, + uint parentID, byte[] particleSystem, LLQuaternion rotation, byte clickAction); + + void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, + LLQuaternion rotation); + + void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, + LLQuaternion rotation, LLVector3 velocity, LLVector3 rotationalvelocity); + + void SendInventoryFolderDetails(LLUUID ownerID, LLUUID folderID, List items, + List folders, bool fetchFolders, + bool fetchItems); + + void SendInventoryItemDetails(LLUUID ownerID, InventoryItemBase item); + + /// + /// Tell the client that we have created the item it requested. + /// + /// + void SendInventoryItemCreateUpdate(InventoryItemBase Item); + + void SendRemoveInventoryItem(LLUUID itemID); + void SendTaskInventory(LLUUID taskID, short serial, byte[] fileName); + void SendXferPacket(ulong xferID, uint packet, byte[] data); + void SendAvatarPickerReply(AvatarPickerReplyPacket Pack); + + void SendPreLoadSound(LLUUID objectID, LLUUID ownerID, LLUUID soundID); + void SendPlayAttachedSound(LLUUID soundID, LLUUID objectID, LLUUID ownerID, float gain, byte flags); + void SendTriggeredSound(LLUUID soundID, LLUUID ownerID, LLUUID objectID, LLUUID parentID, ulong handle, LLVector3 position, float gain); + + void SendNameReply(LLUUID profileId, string firstname, string lastname); + void SendAlertMessage(string message); + + void SendAgentAlertMessage(string message, bool modal); + void SendLoadURL(string objectname, LLUUID objectID, LLUUID ownerID, bool groupOwned, string message, string url); + void SendDialog(string objectname, LLUUID objectID, LLUUID ownerID, string msg, LLUUID textureID, int ch, string[] buttonlabels); + bool AddMoney(int debit); + + void SendSunPos(LLVector3 sunPos, LLVector3 sunVel); + void SendViewerTime(int phase); + + void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember, string flAbout, + uint flags, LLUUID flImageID, LLUUID imageID, string profileURL, LLUUID partnerID); + + byte[] GetThrottlesPacked(float multiplier); + + + void SetDebug(int newDebug); + void InPacket(Packet NewPack); + void Close(bool ShutdownCircuit); + void Kick(string message); + void Stop(); + event ViewerEffectEventHandler OnViewerEffect; + event Action OnLogout; + event Action OnConnectionClosed; + + void SendBlueBoxMessage(LLUUID FromAvatarID, LLUUID fromSessionID, String FromAvatarName, String Message); + + void SendLogoutPacket(); + } +} diff --git a/trunk/OpenSim/Framework/IGenericConfig.cs b/trunk/OpenSim/Framework/IGenericConfig.cs new file mode 100644 index 0000000000..0c9689c358 --- /dev/null +++ b/trunk/OpenSim/Framework/IGenericConfig.cs @@ -0,0 +1,40 @@ +/* +* 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. +* +*/ +namespace OpenSim.Framework +{ + public interface IGenericConfig + { + void SetFileName(string fileName); + void LoadData(); + void LoadDataFromString(string data); + string GetAttribute(string attributeName); + bool SetAttribute(string attributeName, string attributeValue); + void Commit(); + void Close(); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/IPlugin.cs b/trunk/OpenSim/Framework/IPlugin.cs new file mode 100644 index 0000000000..e649274b0c --- /dev/null +++ b/trunk/OpenSim/Framework/IPlugin.cs @@ -0,0 +1,53 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Framework +{ + /// + /// This interface, describes a generic plugin + /// + public interface IPlugin + { + /// + /// Returns the plugin version + /// + /// Plugin version in MAJOR.MINOR.REVISION.BUILD format + string Version { get; } + + /// + /// Returns the plugin name + /// + /// Plugin name, eg MySQL User Provider + string Name { get; } + + /// + /// Initialises the plugin (artificial constructor) + /// + void Initialise(); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/IRegionCommsListener.cs b/trunk/OpenSim/Framework/IRegionCommsListener.cs new file mode 100644 index 0000000000..c8fc9c555f --- /dev/null +++ b/trunk/OpenSim/Framework/IRegionCommsListener.cs @@ -0,0 +1,71 @@ +/* +* 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.Collections.Generic; +using libsecondlife; + +namespace OpenSim.Framework +{ + public delegate void ExpectUserDelegate(ulong regionHandle, AgentCircuitData agent); + + public delegate void ExpectPrimDelegate(ulong regionHandle, LLUUID primID, string objData); + + public delegate void UpdateNeighbours(List neighbours); + + public delegate void AgentCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying); + + public delegate void PrimCrossing(ulong regionHandle, LLUUID primID, LLVector3 position, bool isPhysical); + + public delegate void AcknowledgeAgentCross(ulong regionHandle, LLUUID agentID); + + public delegate void AcknowledgePrimCross(ulong regionHandle, LLUUID PrimID); + + public delegate bool CloseAgentConnection(ulong regionHandle, LLUUID agentID); + + public delegate bool RegionUp(RegionInfo region); + + public delegate bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData); + + + + + public interface IRegionCommsListener + { + event ExpectUserDelegate OnExpectUser; + event ExpectPrimDelegate OnExpectPrim; + event GenericCall2 OnExpectChildAgent; + event AgentCrossing OnAvatarCrossingIntoRegion; + event PrimCrossing OnPrimCrossingIntoRegion; + event AcknowledgeAgentCross OnAcknowledgeAgentCrossed; + event AcknowledgePrimCross OnAcknowledgePrimCrossed; + event UpdateNeighbours OnNeighboursUpdate; + event CloseAgentConnection OnCloseAgentConnection; + event RegionUp OnRegionUp; + event ChildAgentUpdate OnChildAgentUpdate; + + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/IRegionLoader.cs b/trunk/OpenSim/Framework/IRegionLoader.cs new file mode 100644 index 0000000000..f3e0a231a2 --- /dev/null +++ b/trunk/OpenSim/Framework/IRegionLoader.cs @@ -0,0 +1,38 @@ +/* +* 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 Nini.Config; + +namespace OpenSim.Framework +{ + public interface IRegionLoader + { + void SetIniConfigSource(IniConfigSource configSource); + RegionInfo[] LoadRegions(); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/IScene.cs b/trunk/OpenSim/Framework/IScene.cs new file mode 100644 index 0000000000..3445050ee5 --- /dev/null +++ b/trunk/OpenSim/Framework/IScene.cs @@ -0,0 +1,66 @@ +/* +* 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 libsecondlife; + +namespace OpenSim.Framework +{ + public delegate void restart(RegionInfo thisRegion); + + //public delegate void regionup ( RegionInfo thisRegion ); + + public enum RegionStatus : int + { + Down = 0, + Up = 1, + Crashed = 2, + Starting = 3 + } ; + + public interface IScene + { + event restart OnRestart; + + void AddNewClient(IClientAPI client, bool child); + void RemoveClient(LLUUID agentID); + void CloseAllAgents(uint circuitcode); + + void Restart(int seconds); + bool OtherRegionUp(RegionInfo thisRegion); + + string GetSimulatorVersion(); + + RegionInfo RegionInfo { get; } + uint NextLocalId { get; } + + bool PresenceChildStatus(LLUUID avatarID); + + RegionStatus Region_Status { get; set; } + + ClientManager ClientManager { get; } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/IUserData.cs b/trunk/OpenSim/Framework/IUserData.cs new file mode 100644 index 0000000000..45ba7fa117 --- /dev/null +++ b/trunk/OpenSim/Framework/IUserData.cs @@ -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 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.Collections.Generic; +using libsecondlife; + +namespace OpenSim.Framework +{ + /// + /// An interface for connecting to user storage servers. + /// + public interface IUserData + { + /// + /// Returns a user profile from a database via their UUID + /// + /// The user's UUID + /// The user data profile. Returns null if no user is found + UserProfileData GetUserByUUID(LLUUID user); + + /// + /// Returns a users profile by searching their username parts + /// + /// Account firstname + /// Account lastname + /// The user data profile + UserProfileData GetUserByName(string fname, string lname); + + /// + /// Returns a list of UUIDs firstnames and lastnames that match string query entered into the avatar picker. + /// + /// ID associated with the user's query. This must match what the client sent + /// The filtered contents of the search box when the user hit search. + /// The user data profile + List GeneratePickerResults(LLUUID queryID, string query); + + /// + /// Returns the current agent for a user searching by it's UUID + /// + /// The users UUID + /// The current agent session + UserAgentData GetAgentByUUID(LLUUID user); + + /// + /// Returns the current session agent for a user searching by username + /// + /// The users account name + /// The current agent session + UserAgentData GetAgentByName(string name); + + /// + /// Returns the current session agent for a user searching by username parts + /// + /// The users first account name + /// The users account surname + /// The current agent session + UserAgentData GetAgentByName(string fname, string lname); + + /// + /// Stores new web-login key for user during web page login + /// + /// + void StoreWebLoginKey(LLUUID agentID, LLUUID webLoginKey); + + /// + /// Adds a new User profile to the database + /// + /// UserProfile to add + void AddNewUserProfile(UserProfileData user); + + /// + /// Updates an existing user profile + /// + /// UserProfile to update + bool UpdateUserProfile(UserProfileData user); + + /// + /// Updates the current region the User is in + /// + /// User Region the Avatar is IN + /// User Region the Avatar is IN + void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid); + + /// + /// Adds a new agent to the database + /// + /// The agent to add + void AddNewUserAgent(UserAgentData agent); + + /// + /// Adds a new friend to the database for XUser + /// + /// The agent that who's friends list is being added to + /// The agent that being added to the friends list of the friends list owner + /// A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects + void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms); + + /// + /// Delete friend on friendlistowner's friendlist. + /// + /// The agent that who's friends list is being updated + /// The Ex-friend agent + void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend); + + /// + /// Update permissions for friend on friendlistowner's friendlist. + /// + /// The agent that who's friends list is being updated + /// The agent that is getting or loosing permissions + /// A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects + void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms); + + /// + /// Returns a list of FriendsListItems that describe the friends and permissions in the friend relationship for LLUUID friendslistowner + /// + /// The agent that we're retreiving the friends Data. + List GetUserFriendList(LLUUID friendlistowner); + /// + /// Attempts to move currency units between accounts (NOT RELIABLE / TRUSTWORTHY. DONT TRY RUN YOUR OWN CURRENCY EXCHANGE WITH REAL VALUES) + /// + /// The account to transfer from + /// The account to transfer to + /// The amount to transfer + /// Successful? + bool MoneyTransferRequest(LLUUID from, LLUUID to, uint amount); + + /// + /// Attempts to move inventory between accounts, if inventory is copyable it will be copied into the target account. + /// + /// User to transfer from + /// User to transfer to + /// Specified inventory item + /// Successful? + bool InventoryTransferRequest(LLUUID from, LLUUID to, LLUUID inventory); + + /// + /// Returns the plugin version + /// + /// Plugin version in MAJOR.MINOR.REVISION.BUILD format + string GetVersion(); + + /// + /// Returns the plugin name + /// + /// Plugin name, eg MySQL User Provider + string getName(); + + /// + /// Initialises the plugin (artificial constructor) + /// + void Initialise(); + } + + public class AvatarPickerAvatar + { + public LLUUID AvatarID; + public string firstName; + public string lastName; + + public AvatarPickerAvatar() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/IUserService.cs b/trunk/OpenSim/Framework/IUserService.cs new file mode 100644 index 0000000000..f1f3c81438 --- /dev/null +++ b/trunk/OpenSim/Framework/IUserService.cs @@ -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. +* +*/ +using System.Collections.Generic; +using libsecondlife; + +namespace OpenSim.Framework +{ + public interface IUserService + { + UserProfileData GetUserProfile(string firstName, string lastName); + //UserProfileData GetUserProfile(string name); + UserProfileData GetUserProfile(LLUUID userId); + void clearUserAgent(LLUUID avatarID); + List GenerateAgentPickerRequestResponse(LLUUID QueryID, string Query); + + UserProfileData SetupMasterUser(string firstName, string lastName); + UserProfileData SetupMasterUser(string firstName, string lastName, string password); + UserProfileData SetupMasterUser(LLUUID userId); + + /// + /// + /// + /// + LLUUID AddUserProfile(string firstName, string lastName, string pass, uint regX, uint regY); + + + /// + /// Adds a new friend to the database for XUser + /// + /// The agent that who's friends list is being added to + /// The agent that being added to the friends list of the friends list owner + /// A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects + void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms); + + /// + /// Delete friend on friendlistowner's friendlist. + /// + /// The agent that who's friends list is being updated + /// The Ex-friend agent + void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend); + + /// + /// Update permissions for friend on friendlistowner's friendlist. + /// + /// The agent that who's friends list is being updated + /// The agent that is getting or loosing permissions + /// A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects + void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms); + + /// + /// Logs off a user on the user server + /// + /// UUID of the user + /// UUID of the Region + /// final position x + /// final position y + /// final position z + void LogOffUser(LLUUID userid, LLUUID regionid, ulong regionhandle, float posx, float posy, float posz); + + /// + /// Returns a list of FriendsListItems that describe the friends and permissions in the friend relationship for LLUUID friendslistowner + /// + /// The agent that we're retreiving the friends Data. + List GetUserFriendList(LLUUID friendlistowner); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/InventoryConfig.cs b/trunk/OpenSim/Framework/InventoryConfig.cs new file mode 100644 index 0000000000..0c13df5498 --- /dev/null +++ b/trunk/OpenSim/Framework/InventoryConfig.cs @@ -0,0 +1,103 @@ +/* +* 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 OpenSim.Framework.Console; + +namespace OpenSim.Framework +{ + /// + /// UserConfig -- For User Server Configuration + /// + public class InventoryConfig + { + public string DefaultStartupMsg = System.String.Empty; + public string UserServerURL = System.String.Empty; + public string UserSendKey = System.String.Empty; + public string UserRecvKey = System.String.Empty; + + public string DatabaseProvider = System.String.Empty; + public static uint DefaultHttpPort = 8004; + + public uint HttpPort = DefaultHttpPort; + + private ConfigurationMember configMember; + + public InventoryConfig(string description, string filename) + { + configMember = + new ConfigurationMember(filename, description, loadConfigurationOptions, handleIncomingConfiguration, true); + configMember.performConfigurationRetrieve(); + } + + public void loadConfigurationOptions() + { + configMember.addConfigurationOption("default_startup_message", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "Default Startup Message", "Welcome to OGS", false); + configMember.addConfigurationOption("default_user_server", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "Default User Server URI", + "http://127.0.0.1:" + UserConfig.DefaultHttpPort.ToString(), false); + configMember.addConfigurationOption("user_send_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to send to user server", "null", false); + configMember.addConfigurationOption("user_recv_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to expect from user server", "null", false); + configMember.addConfigurationOption("database_provider", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "DLL for database provider", "OpenSim.Framework.Data.SQLite.dll", false); + configMember.addConfigurationOption("http_port", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Http Listener port", DefaultHttpPort.ToString(), false); + } + + public bool handleIncomingConfiguration(string configuration_key, object configuration_result) + { + switch (configuration_key) + { + case "default_startup_message": + DefaultStartupMsg = (string) configuration_result; + break; + case "default_user_server": + UserServerURL = (string) configuration_result; + break; + case "user_send_key": + UserSendKey = (string) configuration_result; + break; + case "user_recv_key": + UserRecvKey = (string) configuration_result; + break; + case "database_provider": + DatabaseProvider = (string) configuration_result; + break; + case "http_port": + HttpPort = (uint) configuration_result; + break; + } + + return true; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/InventoryItemBase.cs b/trunk/OpenSim/Framework/InventoryItemBase.cs new file mode 100644 index 0000000000..f9903d4540 --- /dev/null +++ b/trunk/OpenSim/Framework/InventoryItemBase.cs @@ -0,0 +1,294 @@ +/* +* 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.Collections; +using System.Collections.Generic; +using System.Xml.Serialization; +using libsecondlife; + +namespace OpenSim.Framework +{ + /// + /// Inventory Item - contains all the properties associated with an individual inventory piece. + /// + public class InventoryItemBase + { + /// + /// A UUID containing the ID for the inventory item itself + /// + public LLUUID inventoryID; + + /// + /// The UUID of the associated asset on the asset server + /// + public LLUUID assetID; + + /// + /// This is an enumerated value determining the type of asset (eg Notecard, Sound, Object, etc) + /// + public int assetType; + + /// + /// The type of inventory item. (Can be slightly different to the asset type + /// + public int invType; + + /// + /// The folder this item is contained in + /// + public LLUUID parentFolderID; + + /// + /// The owner of this inventory item + /// + public LLUUID avatarID; + + /// + /// The creator of this item + /// + public LLUUID creatorsID; + + /// + /// The name of the inventory item (must be less than 64 characters) + /// + public string inventoryName; + + /// + /// The description of the inventory item (must be less than 64 characters) + /// + public string inventoryDescription; + + /// + /// A mask containing the permissions for the next owner (cannot be enforced) + /// + public uint inventoryNextPermissions; + + /// + /// A mask containing permissions for the current owner (cannot be enforced) + /// + public uint inventoryCurrentPermissions; + + /// + /// + /// + public uint inventoryBasePermissions; + + /// + /// + /// + public uint inventoryEveryOnePermissions; + } + + /// + /// A Class for folders which contain users inventory + /// + public class InventoryFolderBase + { + /// + /// The name of the folder (64 characters or less) + /// + public string name; + + /// + /// The agent who's inventory this is contained by + /// + public LLUUID agentID; + + /// + /// The folder this folder is contained in + /// + public LLUUID parentID; + + /// + /// The UUID for this folder + /// + public LLUUID folderID; + + /// + /// Type of items normally stored in this folder + /// + public short type; + + /// + /// + /// + public ushort version; + } + + /// + /// An interface for accessing inventory data from a storage server + /// + public interface IInventoryData + { + /// + /// Initialises the interface + /// + void Initialise(); + + /// + /// Closes the interface + /// + void Close(); + + /// + /// The plugin being loaded + /// + /// A string containing the plugin name + string getName(); + + /// + /// The plugins version + /// + /// A string containing the plugin version + string getVersion(); + + /// + /// Returns a list of inventory items contained within the specified folder + /// + /// The UUID of the target folder + /// A List of InventoryItemBase items + List getInventoryInFolder(LLUUID folderID); + + /// + /// Returns a list of the root folders within a users inventory + /// + /// The user whos inventory is to be searched + /// A list of folder objects + List getUserRootFolders(LLUUID user); + + /// + /// Returns the users inventory root folder. + /// + /// The UUID of the user who is having inventory being returned + /// Root inventory folder, null if no root inventory folder was found + InventoryFolderBase getUserRootFolder(LLUUID user); + + /// + /// Returns a list of inventory folders contained in the folder 'parentID' + /// + /// The folder to get subfolders for + /// A list of inventory folders + List getInventoryFolders(LLUUID parentID); + + /// + /// Returns an inventory item by its UUID + /// + /// The UUID of the item to be returned + /// A class containing item information + InventoryItemBase getInventoryItem(LLUUID item); + + /// + /// Returns a specified inventory folder by its UUID + /// + /// The UUID of the folder to be returned + /// A class containing folder information + InventoryFolderBase getInventoryFolder(LLUUID folder); + + /// + /// Creates a new inventory item based on item + /// + /// The item to be created + void addInventoryItem(InventoryItemBase item); + + /// + /// Updates an inventory item with item (updates based on ID) + /// + /// The updated item + void updateInventoryItem(InventoryItemBase item); + + /// + /// + /// + /// + void deleteInventoryItem(LLUUID item); + + /// + /// Adds a new folder specified by folder + /// + /// The inventory folder + void addInventoryFolder(InventoryFolderBase folder); + + /// + /// Updates a folder based on its ID with folder + /// + /// The inventory folder + void updateInventoryFolder(InventoryFolderBase folder); + + /// + /// Updates a folder based on its ID with folder + /// + /// The inventory folder + void moveInventoryFolder(InventoryFolderBase folder); + + /// + /// Deletes a folder based on its ID with folder + /// + /// The id of the folder + void deleteInventoryFolder(LLUUID folder); + } + + public class InventoryCollection + { + public List Folders; + public List AllItems; + public LLUUID UserID; + + public InventoryCollection() + { + Folders = new List(); + AllItems = new List(); + } + + public InventoryCollection(List folders, List allItems) + { + Folders = folders; + AllItems = allItems; + } + } + + /* + * .Net has some issues, serializing a dictionary, so we cannot reuse the InventoryFolder + * class defined in Communications.Framework.Communications.Caches. So we serialize/deserialize + * into this simpler class, and then use that. + */ + + [XmlRoot(ElementName = "inventory", IsNullable = true)] + public class SerializableInventory + { + [XmlRoot(ElementName = "folder", IsNullable = true)] + public class SerializableFolder : InventoryFolderBase + { + [XmlArray(ElementName = "folders", IsNullable = true)] [XmlArrayItem(ElementName = "folder", IsNullable = true, Type = typeof (SerializableFolder))] public + ArrayList SubFolders; + + [XmlArray(ElementName = "items", IsNullable = true)] [XmlArrayItem(ElementName = "item", IsNullable = true, Type = typeof (InventoryItemBase))] public ArrayList + Items; + } + + [XmlElement(ElementName = "folder", IsNullable = true)] public SerializableFolder root; + } +} diff --git a/trunk/OpenSim/Framework/LandData.cs b/trunk/OpenSim/Framework/LandData.cs new file mode 100644 index 0000000000..bb99b27599 --- /dev/null +++ b/trunk/OpenSim/Framework/LandData.cs @@ -0,0 +1,138 @@ +/* +* 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.Collections.Generic; +using System; +using libsecondlife; + +namespace OpenSim.Framework +{ + public class LandData + { + public byte[] landBitmapByteArray = new byte[512]; + public string landName = "Your Parcel"; + public string landDesc = String.Empty; + public LLUUID ownerID = LLUUID.Zero; + public bool isGroupOwned = false; + public LLVector3 AABBMin = new LLVector3(); + public LLVector3 AABBMax = new LLVector3(); + public int area = 0; + public uint auctionID = 0; //Unemplemented. If set to 0, not being auctioned + public LLUUID authBuyerID = LLUUID.Zero; //Unemplemented. Authorized Buyer's UUID + public Parcel.ParcelCategory category = new Parcel.ParcelCategory(); //Unemplemented. Parcel's chosen category + public int claimDate = 0; //Unemplemented + public int claimPrice = 0; //Unemplemented + public LLUUID groupID = LLUUID.Zero; //Unemplemented + public int groupPrims = 0; + public int otherPrims = 0; + public int ownerPrims = 0; + public int selectedPrims = 0; + public int simwidePrims = 0; + public int simwideArea = 0; + public int salePrice = 0; //Unemeplemented. Parcels price. + public Parcel.ParcelStatus landStatus = Parcel.ParcelStatus.Leased; + + public uint landFlags = (uint) Parcel.ParcelFlags.AllowFly | (uint) Parcel.ParcelFlags.AllowLandmark | + (uint) Parcel.ParcelFlags.AllowAllObjectEntry | + (uint) Parcel.ParcelFlags.AllowDeedToGroup | (uint) Parcel.ParcelFlags.AllowTerraform | + (uint) Parcel.ParcelFlags.CreateObjects | (uint) Parcel.ParcelFlags.AllowOtherScripts | + (uint) Parcel.ParcelFlags.SoundLocal; + + public byte landingType = 0; + public byte mediaAutoScale = 0; + public LLUUID mediaID = LLUUID.Zero; + public int localID = 0; + public LLUUID globalID = LLUUID.Zero; + + public string mediaURL = String.Empty; + public string musicURL = String.Empty; + public float passHours = 0; + public int passPrice = 0; + public LLUUID snapshotID = LLUUID.Zero; + public LLVector3 userLocation = new LLVector3(); + public LLVector3 userLookAt = new LLVector3(); + + public List parcelAccessList = new List(); + + public LandData() + { + globalID = LLUUID.Random(); + } + + public LandData Copy() + { + LandData landData = new LandData(); + + landData.AABBMax = AABBMax; + landData.AABBMin = AABBMin; + landData.area = area; + landData.auctionID = auctionID; + landData.authBuyerID = authBuyerID; + landData.category = category; + landData.claimDate = claimDate; + landData.claimPrice = claimPrice; + landData.globalID = globalID; + landData.groupID = groupID; + landData.groupPrims = groupPrims; + landData.otherPrims = otherPrims; + landData.ownerPrims = ownerPrims; + landData.selectedPrims = selectedPrims; + landData.isGroupOwned = isGroupOwned; + landData.localID = localID; + landData.landingType = landingType; + landData.mediaAutoScale = mediaAutoScale; + landData.mediaID = mediaID; + landData.mediaURL = mediaURL; + landData.musicURL = musicURL; + landData.ownerID = ownerID; + landData.landBitmapByteArray = (byte[]) landBitmapByteArray.Clone(); + landData.landDesc = landDesc; + landData.landFlags = landFlags; + landData.landName = landName; + landData.landStatus = landStatus; + landData.passHours = passHours; + landData.passPrice = passPrice; + landData.salePrice = salePrice; + landData.snapshotID = snapshotID; + landData.userLocation = userLocation; + landData.userLookAt = userLookAt; + + landData.parcelAccessList.Clear(); + foreach (ParcelManager.ParcelAccessEntry entry in parcelAccessList) + { + ParcelManager.ParcelAccessEntry newEntry = new ParcelManager.ParcelAccessEntry(); + newEntry.AgentID = entry.AgentID; + newEntry.Flags = entry.Flags; + newEntry.Time = entry.Time; + + landData.parcelAccessList.Add(newEntry); + } + + return landData; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Login.cs b/trunk/OpenSim/Framework/Login.cs new file mode 100644 index 0000000000..7021194ce2 --- /dev/null +++ b/trunk/OpenSim/Framework/Login.cs @@ -0,0 +1,50 @@ +/* +* 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 libsecondlife; + +namespace OpenSim.Framework +{ + public class Login + { + public string First = "Test"; + public string Last = "User"; + public LLUUID Agent; + public LLUUID Session; + public LLUUID SecureSession = LLUUID.Zero; + public LLUUID InventoryFolder; + public LLUUID BaseFolder; + public uint CircuitCode; + public string CapsPath = System.String.Empty; + public LLVector3 StartPos; + + public Login() + { + StartPos = new LLVector3(128, 128, 70); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/MapBlockData.cs b/trunk/OpenSim/Framework/MapBlockData.cs new file mode 100644 index 0000000000..8609533197 --- /dev/null +++ b/trunk/OpenSim/Framework/MapBlockData.cs @@ -0,0 +1,50 @@ +/* +* 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; +using libsecondlife; + +namespace OpenSim.Framework +{ + public class MapBlockData + { + public uint Flags; + public ushort X; + public ushort Y; + public byte Agents; + public byte Access; + public byte WaterHeight; + public LLUUID MapImageId; + public String Name; + public uint RegionFlags; + + public MapBlockData() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/MessageServerConfig.cs b/trunk/OpenSim/Framework/MessageServerConfig.cs new file mode 100644 index 0000000000..c7fee8528e --- /dev/null +++ b/trunk/OpenSim/Framework/MessageServerConfig.cs @@ -0,0 +1,138 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework +{ + /// + /// Message Server Config - Configuration of the Message Server + /// + public class MessageServerConfig + { + public string DefaultStartupMsg = String.Empty; + public string UserServerURL = String.Empty; + public string UserSendKey = String.Empty; + public string UserRecvKey = String.Empty; + + public string GridServerURL = String.Empty; + public string GridSendKey = String.Empty; + public string GridRecvKey = String.Empty; + + public string DatabaseProvider = String.Empty; + public string GridCommsProvider = String.Empty; + + public static uint DefaultHttpPort = 8006; + public static bool DefaultHttpSSL = false; + public uint HttpPort = DefaultHttpPort; + public bool HttpSSL = DefaultHttpSSL; + + private ConfigurationMember configMember; + + public MessageServerConfig(string description, string filename) + { + configMember = + new ConfigurationMember(filename, description, loadConfigurationOptions, handleIncomingConfiguration, true); + configMember.performConfigurationRetrieve(); + } + public void loadConfigurationOptions() + { + + configMember.addConfigurationOption("default_user_server", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "Default User Server URI", + "http://127.0.0.1:" + MessageServerConfig.DefaultHttpPort.ToString() + "/", false); + configMember.addConfigurationOption("user_send_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to send to user server", "null", false); + configMember.addConfigurationOption("user_recv_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to expect from user server", "null", false); + configMember.addConfigurationOption("default_grid_server", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "Default Grid Server URI", + "http://127.0.0.1:8002/", false); + configMember.addConfigurationOption("grid_send_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to send to grid server", "null", false); + configMember.addConfigurationOption("grid_recv_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to expect from user server", "null", false); + + configMember.addConfigurationOption("database_provider", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "DLL for database provider", "OpenSim.Framework.Data.MySQL.dll", false); + + configMember.addConfigurationOption("region_comms_provider", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "DLL for comms provider", "OpenSim.Region.Communications.OGS1.dll", false); + + configMember.addConfigurationOption("http_port", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Http Listener port", DefaultHttpPort.ToString(), false); + configMember.addConfigurationOption("http_ssl", ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN, + "Use SSL? true/false", DefaultHttpSSL.ToString(), false); + + } + + public bool handleIncomingConfiguration(string configuration_key, object configuration_result) + { + switch (configuration_key) + { + + case "default_user_server": + UserServerURL = (string)configuration_result; + break; + case "user_send_key": + UserSendKey = (string)configuration_result; + break; + case "user_recv_key": + UserRecvKey = (string)configuration_result; + break; + case "default_grid_server": + GridServerURL = (string)configuration_result; + break; + case "grid_send_key": + GridSendKey = (string)configuration_result; + break; + case "grid_recv_key": + GridRecvKey = (string)configuration_result; + break; + case "database_provider": + DatabaseProvider = (string)configuration_result; + break; + case "http_port": + HttpPort = (uint)configuration_result; + break; + case "http_ssl": + HttpSSL = (bool)configuration_result; + break; + case "region_comms_provider": + GridCommsProvider = (string)configuration_result; + break; + } + + return true; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/NeighbourInfo.cs b/trunk/OpenSim/Framework/NeighbourInfo.cs new file mode 100644 index 0000000000..ddf9df6a89 --- /dev/null +++ b/trunk/OpenSim/Framework/NeighbourInfo.cs @@ -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. +* +*/ +namespace OpenSim.Framework +{ + public class NeighbourInfo + { + public NeighbourInfo() + { + } + + public ulong regionhandle; + public uint RegionLocX; + public uint RegionLocY; + public string sim_ip; + public uint sim_port; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/NetworkServersInfo.cs b/trunk/OpenSim/Framework/NetworkServersInfo.cs new file mode 100644 index 0000000000..c67a6bf67a --- /dev/null +++ b/trunk/OpenSim/Framework/NetworkServersInfo.cs @@ -0,0 +1,104 @@ +/* +* 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 Nini.Config; +using System; + +namespace OpenSim.Framework +{ + public class NetworkServersInfo + { + public string AssetURL = "http://127.0.0.1:" + AssetConfig.DefaultHttpPort.ToString() + "/"; + public string AssetSendKey = String.Empty; + + public string GridURL = String.Empty; + public string GridSendKey = String.Empty; + public string GridRecvKey = String.Empty; + public string UserURL = String.Empty; + public string UserSendKey = String.Empty; + public string UserRecvKey = String.Empty; + public bool isSandbox; + + public string InventoryURL = String.Empty; + + public static uint DefaultHttpListenerPort = 9000; + public uint HttpListenerPort = DefaultHttpListenerPort; + + public static uint RemotingListenerPort = 8895; + + + public NetworkServersInfo() + { + } + + public NetworkServersInfo(uint defaultHomeLocX, uint defaultHomeLocY) + { + m_defaultHomeLocX = defaultHomeLocX; + m_defaultHomeLocY = defaultHomeLocY; + } + + private uint? m_defaultHomeLocX; + + public uint DefaultHomeLocX + { + get { return m_defaultHomeLocX.Value; } + } + + private uint? m_defaultHomeLocY; + + public uint DefaultHomeLocY + { + get { return m_defaultHomeLocY.Value; } + } + + public void loadFromConfiguration(IConfigSource config) + { + m_defaultHomeLocX = (uint) config.Configs["StandAlone"].GetInt("default_location_x", 1000); + m_defaultHomeLocY = (uint) config.Configs["StandAlone"].GetInt("default_location_y", 1000); + + HttpListenerPort = + (uint) config.Configs["Network"].GetInt("http_listener_port", (int) DefaultHttpListenerPort); + RemotingListenerPort = + (uint) config.Configs["Network"].GetInt("remoting_listener_port", (int) RemotingListenerPort); + GridURL = + config.Configs["Network"].GetString("grid_server_url", + "http://127.0.0.1:" + GridConfig.DefaultHttpPort.ToString()); + GridSendKey = config.Configs["Network"].GetString("grid_send_key", "null"); + GridRecvKey = config.Configs["Network"].GetString("grid_recv_key", "null"); + UserURL = + config.Configs["Network"].GetString("user_server_url", + "http://127.0.0.1:" + UserConfig.DefaultHttpPort.ToString()); + UserSendKey = config.Configs["Network"].GetString("user_send_key", "null"); + UserRecvKey = config.Configs["Network"].GetString("user_recv_key", "null"); + AssetURL = config.Configs["Network"].GetString("asset_server_url", AssetURL); + InventoryURL = config.Configs["Network"].GetString("inventory_server_url", + "http://127.0.0.1:" + + InventoryConfig.DefaultHttpPort.ToString()); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/PacketPool.cs b/trunk/OpenSim/Framework/PacketPool.cs new file mode 100644 index 0000000000..30b6d6a5e7 --- /dev/null +++ b/trunk/OpenSim/Framework/PacketPool.cs @@ -0,0 +1,158 @@ +/* +* 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; +using System.Collections; +using libsecondlife.Packets; + +namespace OpenSim.Framework +{ + public sealed class PacketPool + { + // Set up a thread-safe singleton pattern + static PacketPool() + { + } + + private static readonly PacketPool instance = new PacketPool(); + + public static PacketPool Instance + { + get { return instance; } + } + + private Hashtable pool = new Hashtable(); + + public Packet GetPacket(PacketType type) + { + return Packet.BuildPacket(type); +/* Skip until PacketPool performance problems have been resolved (mantis 281) + Packet packet = null; + + lock (pool) + { + if (pool[type] == null || ((Stack) pool[type]).Count == 0) + { + // Creating a new packet if we cannot reuse an old package + packet = Packet.BuildPacket(type); + } + else + { + // Recycle old packages + packet = (Packet) ((Stack) pool[type]).Pop(); + } + } + + return packet; +*/ + } + + // Copied from LibSL, and added a check to avoid overwriting the + // buffer + private void ZeroDecodeCommand(byte[] src, byte[] dest) + { + for (int srcPos = 6, destPos = 6; destPos < 10; ++srcPos) + { + if (src[srcPos] == 0x00) + { + for (byte j = 0; j < src[srcPos + 1] && destPos < 10; ++j) + { + dest[destPos++] = 0x00; + } + ++srcPos; + } + else + { + dest[destPos++] = src[srcPos]; + } + } + } + + private PacketType GetType(byte[] bytes) + { + byte[] decoded_header = new byte[10]; + + ushort id; + libsecondlife.PacketFrequency freq; + + Buffer.BlockCopy(bytes, 0, decoded_header, 0, 10); + + if((bytes[0] & libsecondlife.Helpers.MSG_ZEROCODED)!=0) + { + ZeroDecodeCommand(bytes, decoded_header); + } + + if (decoded_header[6] == 0xFF) + { + if (decoded_header[7] == 0xFF) + { + id = (ushort)((decoded_header[8] << 8) + decoded_header[9]); + freq = libsecondlife.PacketFrequency.Low; + } + else + { + id = (ushort)decoded_header[7]; + freq = libsecondlife.PacketFrequency.Medium; + } + } + else + { + id = (ushort)decoded_header[6]; + freq = libsecondlife.PacketFrequency.High; + } + + return Packet.GetType(id, freq); + } + + public Packet GetPacket(byte[] bytes, ref int packetEnd, byte[] zeroBuffer) + { + PacketType type = GetType(bytes); + + int i = 0; + Packet packet = GetPacket(type); + packet.FromBytes(bytes, ref i, ref packetEnd, zeroBuffer); + return packet; + } + + public void ReturnPacket(Packet packet) + { +/* Skip until PacketPool performance problems have been resolved (mantis 281) + lock (pool) + { + PacketType type = packet.Type; + + if (pool[type] == null) + { + pool[type] = new Stack(); + } + + ((Stack) pool[type]).Push(packet); + } +*/ + } + } +} diff --git a/trunk/OpenSim/Framework/PrimitiveBaseShape.cs b/trunk/OpenSim/Framework/PrimitiveBaseShape.cs new file mode 100644 index 0000000000..50959f6db4 --- /dev/null +++ b/trunk/OpenSim/Framework/PrimitiveBaseShape.cs @@ -0,0 +1,237 @@ +/* +* 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; +using System.Xml.Serialization; +using libsecondlife; + +namespace OpenSim.Framework +{ + public enum ProfileShape : byte + { + Circle = 0, + Square = 1, + IsometricTriangle = 2, + EquilateralTriangle = 3, + RightTriangle = 4, + HalfCircle = 5 + } + + public enum HollowShape : byte + { + Same = 0, + Circle = 16, + Square = 32, + Triangle = 48 + } + + public enum PCodeEnum : byte + { + Primitive = 9, + Avatar = 47 + } + + public enum Extrusion : byte + { + Straight = 16, + Curve1 = 32, + Curve2 = 48, + Flexible = 128 + } + + [Serializable] + public class PrimitiveBaseShape + { + private static readonly LLObject.TextureEntry m_defaultTexture; + public byte[] ExtraParams; + private byte[] m_textureEntry; + + public ushort PathBegin; + public byte PathCurve; + public ushort PathEnd; + public sbyte PathRadiusOffset; + public byte PathRevolutions; + public byte PathScaleX; + public byte PathScaleY; + public byte PathShearX; + public byte PathShearY; + public sbyte PathSkew; + public sbyte PathTaperX; + public sbyte PathTaperY; + public sbyte PathTwist; + public sbyte PathTwistBegin; + public byte PCode; + public ushort ProfileBegin; + + public byte ProfileCurve; + + public ushort ProfileEnd; + public ushort ProfileHollow; + public LLVector3 Scale; + public byte State; + + static PrimitiveBaseShape() + { + m_defaultTexture = + new LLObject.TextureEntry(new LLUUID("89556747-24cb-43ed-920b-47caed15465f")); + } + + public PrimitiveBaseShape() + { + PCode = (byte) PCodeEnum.Primitive; + ExtraParams = new byte[1]; + Textures = m_defaultTexture; + } + + [XmlIgnore] + public LLObject.TextureEntry Textures + { + get { return new LLObject.TextureEntry(m_textureEntry, 0, m_textureEntry.Length); } + + set { m_textureEntry = value.ToBytes(); } + } + + public byte[] TextureEntry + { + get { return m_textureEntry; } + + set { m_textureEntry = value; } + } + + public ProfileShape ProfileShape + { + get { return (ProfileShape) (ProfileCurve & 0xf); } + set + { + byte oldValueMasked = (byte) (ProfileCurve & 0xf0); + ProfileCurve = (byte) (oldValueMasked | (byte) value); + } + } + + public HollowShape HollowShape + { + get { return (HollowShape) (ProfileCurve & 0xf0); } + set + { + byte oldValueMasked = (byte) (ProfileCurve & 0x0f); + ProfileCurve = (byte) (oldValueMasked | (byte) value); + } + } + + public static PrimitiveBaseShape Default + { + get + { + PrimitiveBaseShape boxShape = CreateBox(); + + boxShape.SetScale(0.5f); + + return boxShape; + } + } + + + public static PrimitiveBaseShape Create() + { + PrimitiveBaseShape shape = new PrimitiveBaseShape(); + return shape; + } + + public static PrimitiveBaseShape CreateBox() + { + PrimitiveBaseShape shape = Create(); + + shape.PathCurve = (byte) Extrusion.Straight; + shape.ProfileShape = ProfileShape.Square; + shape.PathScaleX = 100; + shape.PathScaleY = 100; + + return shape; + } + + public static PrimitiveBaseShape CreateCylinder() + { + PrimitiveBaseShape shape = Create(); + + shape.PathCurve = (byte) Extrusion.Curve1; + shape.ProfileShape = ProfileShape.Square; + + shape.PathScaleX = 100; + shape.PathScaleY = 100; + + return shape; + } + + public void SetScale(float side) + { + Scale = new LLVector3(side, side, side); + } + + public void SetHeigth(float heigth) + { + Scale.Z = heigth; + } + + public void SetRadius(float radius) + { + Scale.X = Scale.Y = radius*2f; + } + + //void returns need to change of course + public virtual void GetMesh() + { + } + + public PrimitiveBaseShape Copy() + { + return (PrimitiveBaseShape) MemberwiseClone(); + } + + public static PrimitiveBaseShape CreateCylinder(float radius, float heigth) + { + PrimitiveBaseShape shape = CreateCylinder(); + + shape.SetHeigth(heigth); + shape.SetRadius(radius); + + return shape; + } + + public void SetPathRange(LLVector3 pathRange) + { + PathBegin = LLObject.PackBeginCut(pathRange.X); + PathEnd = LLObject.PackEndCut(pathRange.Y); + } + + public void SetProfileRange(LLVector3 profileRange) + { + ProfileBegin = LLObject.PackBeginCut(profileRange.X); + ProfileEnd = LLObject.PackEndCut(profileRange.Y); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/RegionCommsListener.cs b/trunk/OpenSim/Framework/RegionCommsListener.cs new file mode 100644 index 0000000000..41577c64fa --- /dev/null +++ b/trunk/OpenSim/Framework/RegionCommsListener.cs @@ -0,0 +1,195 @@ +/* +* 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.Collections.Generic; +using System; +using libsecondlife; + +namespace OpenSim.Framework +{ + public class RegionCommsListener : IRegionCommsListener + { + public event ExpectUserDelegate OnExpectUser; + public event ExpectPrimDelegate OnExpectPrim; + public event GenericCall2 OnExpectChildAgent; + public event AgentCrossing OnAvatarCrossingIntoRegion; + public event PrimCrossing OnPrimCrossingIntoRegion; + public event UpdateNeighbours OnNeighboursUpdate; + public event AcknowledgeAgentCross OnAcknowledgeAgentCrossed; + public event AcknowledgePrimCross OnAcknowledgePrimCrossed; + public event CloseAgentConnection OnCloseAgentConnection; + public event RegionUp OnRegionUp; + public event ChildAgentUpdate OnChildAgentUpdate; + + + + public string debugRegionName = String.Empty; + + + /// + /// + /// + /// + /// + public virtual bool TriggerExpectUser(ulong regionHandle, AgentCircuitData agent) + { + if (OnExpectUser != null) + { + OnExpectUser(regionHandle, agent); + return true; + } + + return false; + } + + + public virtual bool TriggerExpectPrim(ulong regionHandle, LLUUID primID, string objData) + { + if (OnExpectPrim != null) + { + OnExpectPrim(regionHandle, primID, objData); + return true; + } + return false; + } + + public virtual bool TriggerRegionUp(RegionInfo region) + { + if (OnRegionUp != null) + { + OnRegionUp(region); + return true; + } + return false; + } + + public virtual bool TriggerChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData) + { + if (OnChildAgentUpdate != null) + { + OnChildAgentUpdate(regionHandle, cAgentData); + return true; + } + return false; + } + + public virtual bool TriggerExpectAvatarCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, + bool isFlying) + { + if (OnAvatarCrossingIntoRegion != null) + { + OnAvatarCrossingIntoRegion(regionHandle, agentID, position, isFlying); + return true; + } + return false; + } + + public virtual bool TriggerExpectPrimCrossing(ulong regionHandle, LLUUID primID, LLVector3 position, + bool isPhysical) + { + if (OnPrimCrossingIntoRegion != null) + { + OnPrimCrossingIntoRegion(regionHandle, primID, position, isPhysical); + return true; + } + return false; + } + + public virtual bool TriggerAcknowledgeAgentCrossed(ulong regionHandle, LLUUID agentID) + { + if (OnAcknowledgeAgentCrossed != null) + { + OnAcknowledgeAgentCrossed(regionHandle, agentID); + return true; + } + return false; + } + + public virtual bool TriggerAcknowledgePrimCrossed(ulong regionHandle, LLUUID primID) + { + if (OnAcknowledgePrimCrossed != null) + { + OnAcknowledgePrimCrossed(regionHandle, primID); + return true; + } + return false; + } + + public virtual bool TriggerCloseAgentConnection(ulong regionHandle, LLUUID agentID) + { + if (OnCloseAgentConnection != null) + { + OnCloseAgentConnection(regionHandle, agentID); + return true; + + } + return false; + } + + /// + /// + /// + /// TODO: Doesnt take any args?? + /// + public virtual bool TriggerExpectChildAgent() + { + if (OnExpectChildAgent != null) + { + OnExpectChildAgent(); + return true; + } + + return false; + } + + /// + /// + /// + /// Added to avoid a unused compiler warning on OnNeighboursUpdate, TODO: Check me + /// + /// + public virtual bool TriggerOnNeighboursUpdate(List neighbours) + { + if (OnNeighboursUpdate != null) + { + OnNeighboursUpdate(neighbours); + return true; + } + + return false; + } + + public bool TriggerTellRegionToCloseChildConnection(ulong regionHandle, LLUUID agentID) + { + if (OnCloseAgentConnection != null) + return OnCloseAgentConnection(regionHandle, agentID); + + return false; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/RegionHandle.cs b/trunk/OpenSim/Framework/RegionHandle.cs new file mode 100644 index 0000000000..9cfe53d353 --- /dev/null +++ b/trunk/OpenSim/Framework/RegionHandle.cs @@ -0,0 +1,150 @@ +/* +* 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; +using System.Net; +using System.Net.Sockets; + +namespace OpenSim.Framework +{ + /// + /// A class for manipulating RegionHandle coordinates + /// + internal class RegionHandle + { + private UInt64 handle; + + /// + /// Initialises a new grid-aware RegionHandle + /// + /// IP Address of the Grid Server for this region + /// Grid X Coordinate + /// Grid Y Coordinate + public RegionHandle(string ip, short x, short y) + { + IPAddress addr = IPAddress.Parse(ip); + + if (addr.AddressFamily != AddressFamily.InterNetwork) + throw new Exception("Bad RegionHandle Parameter - must be an IPv4 address"); + + uint baseHandle = BitConverter.ToUInt32(addr.GetAddressBytes(), 0); + + // Split the IP address in half + short a = (short) ((baseHandle << 16) & 0xFFFF); + short b = (short) ((baseHandle << 0) & 0xFFFF); + + // Raise the bounds a little + uint nx = (uint) x; + uint ny = (uint) y; + + // Multiply grid coords to get region coords + nx *= Constants.RegionSize; + ny *= Constants.RegionSize; + + // Stuff the IP address in too + nx = (uint) a << 16; + ny = (uint) b << 16; + + handle = ((UInt64) nx << 32) | (uint) ny; + } + + /// + /// Initialises a new RegionHandle that is not inter-grid aware + /// + /// Grid X Coordinate + /// Grid Y Coordinate + public RegionHandle(uint x, uint y) + { + handle = ((x * Constants.RegionSize) << 32) | (y * Constants.RegionSize); + } + + /// + /// Initialises a new RegionHandle from an existing value + /// + /// A U64 RegionHandle + public RegionHandle(UInt64 Region) + { + handle = Region; + } + + /// + /// Returns the Grid Masked RegionHandle - For use in Teleport packets and other packets where sending the grid IP address may be handy. + /// + /// Do not use for SimulatorEnable packets. The client will choke. + /// Region Handle including IP Address encoding + public UInt64 getTeleportHandle() + { + return handle; + } + + /// + /// Returns a RegionHandle which may be used for SimulatorEnable packets. Removes the IP address encoding and returns the lower bounds. + /// + /// A U64 RegionHandle for use in SimulatorEnable packets. + public UInt64 getNeighbourHandle() + { + UInt64 mask = 0x0000FFFF0000FFFF; + + return handle | mask; + } + + /// + /// Returns the IP Address of the GridServer from a Grid-Encoded RegionHandle + /// + /// Grid Server IP Address + public IPAddress getGridIP() + { + uint a = (uint) ((handle >> 16) & 0xFFFF); + uint b = (uint) ((handle >> 48) & 0xFFFF); + + return new IPAddress((long) (a << 16) | (long) b); + } + + /// + /// Returns the X Coordinate from a Grid-Encoded RegionHandle + /// + /// X Coordinate + public uint getGridX() + { + uint x = (uint) ((handle >> 32) & 0xFFFF); + + return x; + } + + /// + /// Returns the Y Coordinate from a Grid-Encoded RegionHandle + /// + /// Y Coordinate + public uint getGridY() + { + uint y = (uint) ((handle >> 0) & 0xFFFF); + + return y; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/RegionInfo.cs b/trunk/OpenSim/Framework/RegionInfo.cs new file mode 100644 index 0000000000..f97db5c208 --- /dev/null +++ b/trunk/OpenSim/Framework/RegionInfo.cs @@ -0,0 +1,414 @@ +/* +* 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; +using System.Net; +using System.Net.Sockets; +using System.Xml; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework +{ + [Serializable] + public class SimpleRegionInfo + { + public SimpleRegionInfo() + { + } + + public SimpleRegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) + { + m_regionLocX = regionLocX; + m_regionLocY = regionLocY; + + m_internalEndPoint = internalEndPoint; + m_externalHostName = externalUri; + } + + public SimpleRegionInfo(uint regionLocX, uint regionLocY, string externalUri, uint port) + { + m_regionLocX = regionLocX; + m_regionLocY = regionLocY; + + m_externalHostName = externalUri; + + m_internalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int) port); + } + + public SimpleRegionInfo(RegionInfo ConvertFrom) + { + m_regionLocX = ConvertFrom.RegionLocX; + m_regionLocY = ConvertFrom.RegionLocY; + m_internalEndPoint = ConvertFrom.InternalEndPoint; + m_externalHostName = ConvertFrom.ExternalHostName; + m_remotingPort = ConvertFrom.RemotingPort; + m_allow_alternate_ports = ConvertFrom.m_allow_alternate_ports; + RemotingAddress = ConvertFrom.RemotingAddress; + RegionID = LLUUID.Zero; + } + + public LLUUID RegionID = LLUUID.Zero; + + public uint m_remotingPort; + + public uint RemotingPort + { + get { return m_remotingPort; } + set { m_remotingPort = value; } + } + public bool m_allow_alternate_ports; + + public string RemotingAddress; + + public IPEndPoint ExternalEndPoint + { + get + { + // Old one defaults to IPv6 + //return new IPEndPoint( Dns.GetHostAddresses( m_externalHostName )[0], m_internalEndPoint.Port ); + + IPAddress ia = null; + // If it is already an IP, don't resolve it - just return directly + if (IPAddress.TryParse(m_externalHostName, out ia)) + return new IPEndPoint(ia, m_internalEndPoint.Port); + + // Reset for next check + ia = null; + + // New method favors IPv4 + foreach (IPAddress Adr in Dns.GetHostAddresses(m_externalHostName)) + { + if (ia == null) + ia = Adr; + + if (Adr.AddressFamily == AddressFamily.InterNetwork) + { + ia = Adr; + break; + } + } + + return new IPEndPoint(ia, m_internalEndPoint.Port); + } + + set { m_externalHostName = value.ToString(); } + } + + protected string m_externalHostName; + + public string ExternalHostName + { + get { return m_externalHostName; } + set { m_externalHostName = value; } + } + + protected bool Allow_Alternate_Ports; + + protected IPEndPoint m_internalEndPoint; + + public IPEndPoint InternalEndPoint + { + get { return m_internalEndPoint; } + set { m_internalEndPoint = value; } + } + + protected uint? m_regionLocX; + + public uint RegionLocX + { + get { return m_regionLocX.Value; } + set { m_regionLocX = value; } + } + + protected uint? m_regionLocY; + + public uint RegionLocY + { + get { return m_regionLocY.Value; } + set { m_regionLocY = value; } + } + + public ulong RegionHandle + { + get { return Util.UIntsToLong((RegionLocX * (uint)Constants.RegionSize), (RegionLocY * (uint)Constants.RegionSize)); } + } + } + + public class RegionInfo : SimpleRegionInfo + { + public string RegionName = String.Empty; + + public string DataStore = String.Empty; + public bool isSandbox = false; + public bool commFailTF = false; + +// public bool m_allow_alternate_ports; + + public LLUUID MasterAvatarAssignedUUID = LLUUID.Zero; + public LLUUID CovenantID = LLUUID.Zero; + public string MasterAvatarFirstName = String.Empty; + public string MasterAvatarLastName = String.Empty; + public string MasterAvatarSandboxPassword = String.Empty; + + // Apparently, we're applying the same estatesettings regardless of whether it's local or remote. + private EstateSettings m_estateSettings; + + public EstateSettings EstateSettings + { + get + { + if (m_estateSettings == null) + { + m_estateSettings = new EstateSettings(); + } + + return m_estateSettings; + } + } + + public ConfigurationMember configMember; + + public RegionInfo(string description, string filename, bool skipConsoleConfig) + { + configMember = + new ConfigurationMember(filename, description, loadConfigurationOptions, handleIncomingConfiguration, !skipConsoleConfig); + configMember.performConfigurationRetrieve(); + } + + public RegionInfo(string description, XmlNode xmlNode, bool skipConsoleConfig) + { + configMember = + new ConfigurationMember(xmlNode, description, loadConfigurationOptions, handleIncomingConfiguration, !skipConsoleConfig); + configMember.performConfigurationRetrieve(); + } + + public RegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) : + base(regionLocX, regionLocY, internalEndPoint, externalUri) + { + } + + public RegionInfo() + { + } + + public RegionInfo(SearializableRegionInfo ConvertFrom) + { + m_regionLocX = ConvertFrom.RegionLocX; + m_regionLocY = ConvertFrom.RegionLocY; + m_internalEndPoint = ConvertFrom.InternalEndPoint; + m_externalHostName = ConvertFrom.ExternalHostName; + m_remotingPort = ConvertFrom.RemotingPort; + m_allow_alternate_ports = ConvertFrom.m_allow_alternate_ports; + RemotingAddress = ConvertFrom.RemotingAddress; + RegionID = LLUUID.Zero; + } + + public RegionInfo(SimpleRegionInfo ConvertFrom) + { + m_regionLocX = ConvertFrom.RegionLocX; + m_regionLocY = ConvertFrom.RegionLocY; + m_internalEndPoint = ConvertFrom.InternalEndPoint; + m_externalHostName = ConvertFrom.ExternalHostName; + m_remotingPort = ConvertFrom.RemotingPort; + m_allow_alternate_ports = ConvertFrom.m_allow_alternate_ports; + RemotingAddress = ConvertFrom.RemotingAddress; + RegionID = LLUUID.Zero; + } + + //not in use, should swap to nini though. + public void LoadFromNiniSource(IConfigSource source) + { + LoadFromNiniSource(source, "RegionInfo"); + } + + //not in use, should swap to nini though. + public void LoadFromNiniSource(IConfigSource source, string sectionName) + { + string errorMessage = String.Empty; + RegionID = new LLUUID(source.Configs[sectionName].GetString("Region_ID", LLUUID.Random().ToString())); + RegionName = source.Configs[sectionName].GetString("sim_name", "OpenSim Test"); + m_regionLocX = Convert.ToUInt32(source.Configs[sectionName].GetString("sim_location_x", "1000")); + m_regionLocY = Convert.ToUInt32(source.Configs[sectionName].GetString("sim_location_y", "1000")); + // this.DataStore = source.Configs[sectionName].GetString("datastore", "OpenSim.db"); + + string ipAddress = source.Configs[sectionName].GetString("internal_ip_address", "0.0.0.0"); + IPAddress ipAddressResult; + if (IPAddress.TryParse(ipAddress, out ipAddressResult)) + { + m_internalEndPoint = new IPEndPoint(ipAddressResult, 0); + } + else + { + errorMessage = "needs an IP Address (IPAddress)"; + } + m_internalEndPoint.Port = + source.Configs[sectionName].GetInt("internal_ip_port", (int) NetworkServersInfo.DefaultHttpListenerPort); + + string externalHost = source.Configs[sectionName].GetString("external_host_name", "127.0.0.1"); + if (externalHost != "SYSTEMIP") + { + m_externalHostName = externalHost; + } + else + { + m_externalHostName = Util.GetLocalHost().ToString(); + } + + MasterAvatarFirstName = source.Configs[sectionName].GetString("master_avatar_first", "Test"); + MasterAvatarLastName = source.Configs[sectionName].GetString("master_avatar_last", "User"); + MasterAvatarSandboxPassword = source.Configs[sectionName].GetString("master_avatar_pass", "test"); + + if (errorMessage != String.Empty) + { + // a error + } + } + + public void loadConfigurationOptions() + { + configMember.addConfigurationOption("sim_UUID", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + "UUID of Region (Default is recommended, random UUID)", + LLUUID.Random().ToString(), true); + configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "Region Name", "OpenSim Test", false); + configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Grid Location (X Axis)", "1000", false); + configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Grid Location (Y Axis)", "1000", false); + //configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false); + configMember.addConfigurationOption("internal_ip_address", + ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS, + "Internal IP Address for incoming UDP client connections", "0.0.0.0", + false); + configMember.addConfigurationOption("internal_ip_port", ConfigurationOption.ConfigurationTypes.TYPE_INT32, + "Internal IP Port for incoming UDP client connections", + NetworkServersInfo.DefaultHttpListenerPort.ToString(), false); + configMember.addConfigurationOption("allow_alternate_ports", ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN, + "Allow sim to find alternate UDP ports when ports are in use?", + "false", true); + configMember.addConfigurationOption("external_host_name", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "External Host Name", "127.0.0.1", false); + configMember.addConfigurationOption("master_avatar_uuid", ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, + "Master Avatar UUID", LLUUID.Zero.ToString(), true); + configMember.addConfigurationOption("estate_covanant_uuid", + ConfigurationOption.ConfigurationTypes.TYPE_LLUUID, "Estate Covenant", + LLUUID.Zero.ToString(), true); + configMember.addConfigurationOption("master_avatar_first", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "First Name of Master Avatar", "Test", false, + (ConfigurationOption.ConfigurationOptionShouldBeAsked) + shouldMasterAvatarDetailsBeAsked); + configMember.addConfigurationOption("master_avatar_last", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "Last Name of Master Avatar", "User", false, + (ConfigurationOption.ConfigurationOptionShouldBeAsked) + shouldMasterAvatarDetailsBeAsked); + configMember.addConfigurationOption("master_avatar_pass", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "(Sandbox Mode Only)Password for Master Avatar account", "test", false, + (ConfigurationOption.ConfigurationOptionShouldBeAsked) + shouldMasterAvatarDetailsBeAsked); + } + + public bool shouldMasterAvatarDetailsBeAsked(string configuration_key) + { + if (MasterAvatarAssignedUUID.Equals(null) || MasterAvatarAssignedUUID.ToString() == LLUUID.Zero.ToString()) + { + return true; + } + return false; + } + + public bool handleIncomingConfiguration(string configuration_key, object configuration_result) + { + switch (configuration_key) + { + case "sim_UUID": + RegionID = (LLUUID) configuration_result; + break; + case "sim_name": + RegionName = (string) configuration_result; + break; + case "sim_location_x": + m_regionLocX = (uint) configuration_result; + break; + case "sim_location_y": + m_regionLocY = (uint) configuration_result; + break; + case "datastore": + DataStore = (string) configuration_result; + break; + case "internal_ip_address": + IPAddress address = (IPAddress) configuration_result; + m_internalEndPoint = new IPEndPoint(address, 0); + break; + case "internal_ip_port": + m_internalEndPoint.Port = (int)configuration_result; + break; + case "allow_alternate_ports": + m_allow_alternate_ports = (bool)configuration_result; + break; + case "external_host_name": + if ((string) configuration_result != "SYSTEMIP") + { + m_externalHostName = (string) configuration_result; + } + else + { + m_externalHostName = Util.GetLocalHost().ToString(); + } + break; + case "master_avatar_uuid": + MasterAvatarAssignedUUID = (LLUUID) configuration_result; + break; + case "estate_covanant_uuid": + CovenantID = (LLUUID) configuration_result; + break; + + case "master_avatar_first": + MasterAvatarFirstName = (string) configuration_result; + break; + case "master_avatar_last": + MasterAvatarLastName = (string) configuration_result; + break; + case "master_avatar_pass": + string tempMD5Passwd = (string) configuration_result; + MasterAvatarSandboxPassword = Util.Md5Hash(Util.Md5Hash(tempMD5Passwd) + ":" + String.Empty); + break; + } + + return true; + } + public void SaveEstatecovenantUUID(LLUUID notecard) + { + configMember.forceSetConfigurationOption("estate_covanant_uuid", notecard.ToString()); + + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs b/trunk/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs new file mode 100644 index 0000000000..66a6ec8df3 --- /dev/null +++ b/trunk/OpenSim/Framework/RegionLoader/Filesystem/RegionLoaderFileSystem.cs @@ -0,0 +1,66 @@ +/* +* 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.IO; +using Nini.Config; + +namespace OpenSim.Framework.RegionLoader.Filesystem +{ + public class RegionLoaderFileSystem : IRegionLoader + { + public void SetIniConfigSource(IniConfigSource configSource) + { + } + + public RegionInfo[] LoadRegions() + { + string regionConfigPath = Path.Combine(Util.configDir(), "Regions"); + + if (!Directory.Exists(regionConfigPath)) + { + Directory.CreateDirectory(regionConfigPath); + } + + string[] configFiles = Directory.GetFiles(regionConfigPath, "*.xml"); + + if (configFiles.Length == 0) + { + new RegionInfo("DEFAULT REGION CONFIG", Path.Combine(regionConfigPath, "default.xml"),false); + configFiles = Directory.GetFiles(regionConfigPath, "*.xml"); + } + + RegionInfo[] regionInfos = new RegionInfo[configFiles.Length]; + for (int i = 0; i < configFiles.Length; i++) + { + RegionInfo regionInfo = new RegionInfo("REGION CONFIG #" + (i + 1), configFiles[i],false); + regionInfos[i] = regionInfo; + } + + return regionInfos; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs b/trunk/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs new file mode 100644 index 0000000000..76d0b34ec8 --- /dev/null +++ b/trunk/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs @@ -0,0 +1,100 @@ +/* +* 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.IO; +using System.Net; +using System.Xml; +using Nini.Config; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.RegionLoader.Web +{ + public class RegionLoaderWebServer : IRegionLoader + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private IniConfigSource m_configSouce; + + public void SetIniConfigSource(IniConfigSource configSource) + { + m_configSouce = configSource; + } + + public RegionInfo[] LoadRegions() + { + if (m_configSouce == null) + { + m_log.Error("[WEBLOADER]: Unable to load configuration source!"); + return null; + } + else + { + IniConfig startupConfig = (IniConfig) m_configSouce.Configs["Startup"]; + string url = startupConfig.GetString("regionload_webserver_url", System.String.Empty).Trim(); + if (url == System.String.Empty) + { + m_log.Error("[WEBLOADER]: Unable to load webserver URL - URL was empty."); + return null; + } + else + { + HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(url); + webRequest.Timeout = 30000; //30 Second Timeout + m_log.Debug("[WEBLOADER]: Sending Download Request..."); + HttpWebResponse webResponse = (HttpWebResponse) webRequest.GetResponse(); + m_log.Debug("[WEBLOADER]: Downloading Region Information From Remote Server..."); + StreamReader reader = new StreamReader(webResponse.GetResponseStream()); + string xmlSource = System.String.Empty; + string tempStr = reader.ReadLine(); + while (tempStr != null) + { + xmlSource = xmlSource + tempStr; + tempStr = reader.ReadLine(); + } + m_log.Debug("[WEBLOADER]: Done downloading region information from server. Total Bytes: " + + xmlSource.Length); + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(xmlSource); + if (xmlDoc.FirstChild.Name == "Regions") + { + RegionInfo[] regionInfos = new RegionInfo[xmlDoc.FirstChild.ChildNodes.Count]; + int i; + for (i = 0; i < xmlDoc.FirstChild.ChildNodes.Count; i++) + { + m_log.Debug(xmlDoc.FirstChild.ChildNodes[i].OuterXml); + regionInfos[i] = + new RegionInfo("REGION CONFIG #" + (i + 1), xmlDoc.FirstChild.ChildNodes[i],false); + } + + return regionInfos; + } + return null; + } + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Remoting.cs b/trunk/OpenSim/Framework/Remoting.cs new file mode 100644 index 0000000000..ddc1cfb342 --- /dev/null +++ b/trunk/OpenSim/Framework/Remoting.cs @@ -0,0 +1,134 @@ +/* +* 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; +using System.Security.Cryptography; +using System.Text; + +namespace OpenSim.Framework +{ + /// + /// NEEDS AUDIT. + /// + /// + /// Suggested implementation + /// Store two digests for each foreign host. A local copy of the local hash using the local challenge (when issued), and a local copy of the remote hash using the remote challenge. + /// When sending data to the foreign host - run 'Sign' on the data and affix the returned byte[] to the message. + /// When receiving data from the foreign host - run 'Authenticate' against the data and the attached byte[]. + /// Both hosts should be performing these operations for this to be effective. + /// + internal class RemoteDigest + { + private byte[] currentHash; + private byte[] secret; + + private SHA512Managed SHA512; + + /// + /// Initialises a new RemoteDigest authentication mechanism + /// + /// Needs an audit by a cryptographic professional - was not "roll your own"'d by choice but rather a serious lack of decent authentication mechanisms in .NET remoting + /// The shared secret between systems (for inter-sim, this is provided in encrypted form during connection, for grid this is input manually in setup) + /// Binary salt - some common value - to be decided what + /// The challenge key provided by the third party + public RemoteDigest(string sharedSecret, byte[] salt, string challenge) + { + SHA512 = new SHA512Managed(); + Rfc2898DeriveBytes RFC2898 = new Rfc2898DeriveBytes(sharedSecret, salt); + secret = RFC2898.GetBytes(512); + ASCIIEncoding ASCII = new ASCIIEncoding(); + + currentHash = SHA512.ComputeHash(AppendArrays(secret, ASCII.GetBytes(challenge))); + } + + /// + /// Authenticates a piece of incoming data against the local digest. Upon successful authentication, digest string is incremented. + /// + /// The incoming data + /// The remote digest + /// + public bool Authenticate(byte[] data, byte[] digest) + { + byte[] newHash = SHA512.ComputeHash(AppendArrays(AppendArrays(currentHash, secret), data)); + if (digest == newHash) + { + currentHash = newHash; + return true; + } + else + { + throw new Exception("Hash comparison failed. Key resync required."); + } + } + + /// + /// Signs a new bit of data with the current hash. Returns a byte array which should be affixed to the message. + /// Signing a piece of data will automatically increment the hash - if you sign data and do not send it, the + /// hashes will get out of sync and throw an exception when validation is attempted. + /// + /// The outgoing data + /// The local digest + public byte[] Sign(byte[] data) + { + currentHash = SHA512.ComputeHash(AppendArrays(AppendArrays(currentHash, secret), data)); + return currentHash; + } + + /// + /// Generates a new challenge string to be issued to a foreign host. Challenges are 1024-bit (effective strength of less than 512-bits) messages generated using the Crytographic Random Number Generator. + /// + /// A 128-character hexadecimal string containing the challenge. + public static string GenerateChallenge() + { + RNGCryptoServiceProvider RNG = new RNGCryptoServiceProvider(); + byte[] bytes = new byte[64]; + RNG.GetBytes(bytes); + + StringBuilder sb = new StringBuilder(bytes.Length*2); + foreach (byte b in bytes) + { + sb.AppendFormat("{0:x2}", b); + } + return sb.ToString(); + } + + /// + /// Helper function, merges two byte arrays + /// + /// Sourced from MSDN Forum + /// A + /// B + /// C + private byte[] AppendArrays(byte[] a, byte[] b) + { + byte[] c = new byte[a.Length + b.Length]; + Buffer.BlockCopy(a, 0, c, 0, a.Length); + Buffer.BlockCopy(b, 0, c, a.Length, b.Length); + return c; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/SerializableRegionInfo.cs b/trunk/OpenSim/Framework/SerializableRegionInfo.cs new file mode 100644 index 0000000000..077ed8da2f --- /dev/null +++ b/trunk/OpenSim/Framework/SerializableRegionInfo.cs @@ -0,0 +1,161 @@ +/* +* 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; +using System.Net; +using System.Net.Sockets; +using libsecondlife; + +namespace OpenSim.Framework +{ + [Serializable] + public class SearializableRegionInfo + { + /// + /// This is a serializable version of RegionInfo + /// + public SearializableRegionInfo() + { + } + + public SearializableRegionInfo(RegionInfo ConvertFrom) + { + m_regionLocX = ConvertFrom.RegionLocX; + m_regionLocY = ConvertFrom.RegionLocY; + m_internalEndPoint = ConvertFrom.InternalEndPoint; + m_externalHostName = ConvertFrom.ExternalHostName; + m_remotingPort = ConvertFrom.RemotingPort; + m_allow_alternate_ports = ConvertFrom.m_allow_alternate_ports; + RemotingAddress = ConvertFrom.RemotingAddress; + } + + public SearializableRegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) + { + m_regionLocX = regionLocX; + m_regionLocY = regionLocY; + + m_internalEndPoint = internalEndPoint; + m_externalHostName = externalUri; + } + + public SearializableRegionInfo(uint regionLocX, uint regionLocY, string externalUri, uint port) + { + m_regionLocX = regionLocX; + m_regionLocY = regionLocY; + + m_externalHostName = externalUri; + + m_internalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int) port); + } + + public Guid RegionID = LLUUID.Zero.UUID; + + public uint m_remotingPort; + + public uint RemotingPort + { + get { return m_remotingPort; } + set { m_remotingPort = value; } + } + public bool m_allow_alternate_ports; + + public string RemotingAddress; + + + public IPEndPoint ExternalEndPoint + { + get + { + // Old one defaults to IPv6 + //return new IPEndPoint( Dns.GetHostAddresses( m_externalHostName )[0], m_internalEndPoint.Port ); + + IPAddress ia = null; + // If it is already an IP, don't resolve it - just return directly + if (IPAddress.TryParse(m_externalHostName, out ia)) + return new IPEndPoint(ia, m_internalEndPoint.Port); + + // Reset for next check + ia = null; + + + // New method favors IPv4 + foreach (IPAddress Adr in Dns.GetHostAddresses(m_externalHostName)) + { + if (ia == null) + ia = Adr; + + if (Adr.AddressFamily == AddressFamily.InterNetwork) + { + ia = Adr; + break; + } + } + + return new IPEndPoint(ia, m_internalEndPoint.Port); + } + + set { m_externalHostName = value.ToString(); } + } + + protected string m_externalHostName; + + public string ExternalHostName + { + get { return m_externalHostName; } + set { m_externalHostName = value; } + } + + protected IPEndPoint m_internalEndPoint; + + public IPEndPoint InternalEndPoint + { + get { return m_internalEndPoint; } + set { m_internalEndPoint = value; } + } + + protected uint? m_regionLocX; + + public uint RegionLocX + { + get { return m_regionLocX.Value; } + set { m_regionLocX = value; } + } + + protected uint? m_regionLocY; + + public uint RegionLocY + { + get { return m_regionLocY.Value; } + set { m_regionLocY = value; } + } + + public ulong RegionHandle + { + get { return Util.UIntsToLong((RegionLocX * (uint)Constants.RegionSize), (RegionLocY * (uint)Constants.RegionSize)); } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/BaseHttpServer.cs b/trunk/OpenSim/Framework/Servers/BaseHttpServer.cs new file mode 100644 index 0000000000..cc0c0d00db --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/BaseHttpServer.cs @@ -0,0 +1,612 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text; +using System.Threading; +using System.Xml; +using Nwc.XmlRpc; +using libsecondlife.StructuredData; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Servers +{ + public class BaseHttpServer + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected Thread m_workerThread; + protected HttpListener m_httpListener; + protected Dictionary m_rpcHandlers = new Dictionary(); + protected LLSDMethod m_llsdHandler = null; + protected Dictionary m_streamHandlers = new Dictionary(); + protected Dictionary m_HTTPHandlers = new Dictionary(); + + protected uint m_port; + protected bool m_ssl = false; + protected bool m_firstcaps = true; + + public uint Port + { + get { return m_port; } + } + + public BaseHttpServer(uint port) + { + m_port = port; + } + + public BaseHttpServer(uint port, bool ssl) + { + m_ssl = ssl; + m_port = port; + } + + public void AddStreamHandler(IRequestHandler handler) + { + string httpMethod = handler.HttpMethod; + string path = handler.Path; + + string handlerKey = GetHandlerKey(httpMethod, path); + m_streamHandlers.Add(handlerKey, handler); + } + + private static string GetHandlerKey(string httpMethod, string path) + { + return httpMethod + ":" + path; + } + + public bool AddXmlRPCHandler(string method, XmlRpcMethod handler) + { + if (!m_rpcHandlers.ContainsKey(method)) + { + m_rpcHandlers.Add(method, handler); + return true; + } + + //must already have a handler for that path so return false + return false; + } + + public bool AddHTTPHandler(string method, GenericHTTPMethod handler) + { + if (!m_HTTPHandlers.ContainsKey(method)) + { + m_HTTPHandlers.Add(method, handler); + return true; + } + + //must already have a handler for that path so return false + return false; + } + + public bool SetLLSDHandler(LLSDMethod handler) + { + m_llsdHandler = handler; + return true; + } + + public virtual void HandleRequest(Object stateinfo) + { + HttpListenerContext context = (HttpListenerContext) stateinfo; + + HttpListenerRequest request = context.Request; + HttpListenerResponse response = context.Response; + + + response.KeepAlive = false; + response.SendChunked = false; + + string path = request.RawUrl; + string handlerKey = GetHandlerKey(request.HttpMethod, path); + + IRequestHandler requestHandler; + + if (TryGetStreamHandler(handlerKey, out requestHandler)) + { + // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler. + byte[] buffer; + if (requestHandler is IStreamedRequestHandler) + { + IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler; + buffer = streamedRequestHandler.Handle(path, request.InputStream); + } + else + { + IStreamHandler streamHandler = (IStreamHandler) requestHandler; + + using (MemoryStream memoryStream = new MemoryStream()) + { + streamHandler.Handle(path, request.InputStream, memoryStream); + memoryStream.Flush(); + buffer = memoryStream.ToArray(); + } + } + + request.InputStream.Close(); + response.ContentType = requestHandler.ContentType; + response.ContentLength64 = buffer.LongLength; + response.OutputStream.Write(buffer, 0, buffer.Length); + response.OutputStream.Close(); + } + else + { + switch (request.ContentType) + { + case null: + case "text/html": + HandleHTTPRequest(request, response); + break; + case "application/xml+llsd": + HandleLLSDRequests(request, response); + break; + case "text/xml": + case "application/xml": + default: + HandleXmlRpcRequests(request, response); + break; + } + } + } + + private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler) + { + string bestMatch = null; + + foreach (string pattern in m_streamHandlers.Keys) + { + if (handlerKey.StartsWith(pattern)) + { + if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) + { + bestMatch = pattern; + } + } + } + + if (String.IsNullOrEmpty(bestMatch)) + { + streamHandler = null; + return false; + } + else + { + streamHandler = m_streamHandlers[bestMatch]; + return true; + } + } + + private bool TryGetHTTPHandler(string handlerKey, out GenericHTTPMethod HTTPHandler) + { + string bestMatch = null; + + foreach (string pattern in m_HTTPHandlers.Keys) + { + if (handlerKey.StartsWith(pattern)) + { + if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) + { + bestMatch = pattern; + } + } + } + + if (String.IsNullOrEmpty(bestMatch)) + { + HTTPHandler = null; + return false; + } + else + { + HTTPHandler = m_HTTPHandlers[bestMatch]; + return true; + } + } + private void HandleXmlRpcRequests(HttpListenerRequest request, HttpListenerResponse response) + { + Stream requestStream = request.InputStream; + + Encoding encoding = Encoding.UTF8; + StreamReader reader = new StreamReader(requestStream, encoding); + + string requestBody = reader.ReadToEnd(); + reader.Close(); + requestStream.Close(); + + string responseString = String.Empty; + XmlRpcRequest xmlRprcRequest = null; + + try + { + xmlRprcRequest = (XmlRpcRequest) (new XmlRpcRequestDeserializer()).Deserialize(requestBody); + } + catch (XmlException e) + { + + } + + if (xmlRprcRequest != null) + { + string methodName = xmlRprcRequest.MethodName; + if (methodName != null) + { + XmlRpcResponse xmlRpcResponse; + + XmlRpcMethod method; + if (m_rpcHandlers.TryGetValue(methodName, out method)) + { + xmlRpcResponse = method(xmlRprcRequest); + } + else + { + xmlRpcResponse = new XmlRpcResponse(); + Hashtable unknownMethodError = new Hashtable(); + unknownMethodError["reason"] = "XmlRequest"; + ; + unknownMethodError["message"] = "Unknown Rpc Request [" + methodName + "]"; + unknownMethodError["login"] = "false"; + xmlRpcResponse.Value = unknownMethodError; + } + + responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse); + } + else + { + System.Console.WriteLine("Handler not found for http request " + request.RawUrl); + responseString = "Error"; + } + } + + response.ContentType = "text/xml"; + + byte[] buffer = Encoding.UTF8.GetBytes(responseString); + + response.SendChunked = false; + response.ContentLength64 = buffer.Length; + response.ContentEncoding = Encoding.UTF8; + try + { + response.OutputStream.Write(buffer, 0, buffer.Length); + } + catch (Exception ex) + { + m_log.Warn("[HTTPD]: Error - " + ex.Message); + } + finally + { + response.OutputStream.Close(); + } + } + + private void HandleLLSDRequests(HttpListenerRequest request, HttpListenerResponse response) + { + Stream requestStream = request.InputStream; + + Encoding encoding = Encoding.UTF8; + StreamReader reader = new StreamReader(requestStream, encoding); + + string requestBody = reader.ReadToEnd(); + reader.Close(); + requestStream.Close(); + + LLSD llsdRequest = null; + LLSD llsdResponse = null; + + try { llsdRequest = LLSDParser.DeserializeXml(requestBody); } + catch (Exception ex) { m_log.Warn("[HTTPD]: Error - " + ex.Message); } + + if (llsdRequest != null && m_llsdHandler != null) + { + llsdResponse = m_llsdHandler(llsdRequest); + } + else + { + LLSDMap map = new LLSDMap(); + map["reason"] = LLSD.FromString("LLSDRequest"); + map["message"] = LLSD.FromString("No handler registered for LLSD Requests"); + map["login"] = LLSD.FromString("false"); + llsdResponse = map; + } + + response.ContentType = "application/xml+llsd"; + + byte[] buffer = LLSDParser.SerializeXmlBytes(llsdResponse); + + response.SendChunked = false; + response.ContentLength64 = buffer.Length; + response.ContentEncoding = Encoding.UTF8; + + try + { + response.OutputStream.Write(buffer, 0, buffer.Length); + } + catch (Exception ex) + { + m_log.Warn("[HTTPD]: Error - " + ex.Message); + } + finally + { + response.OutputStream.Close(); + } + } + + public void HandleHTTPRequest(HttpListenerRequest request, HttpListenerResponse response) + { + // This is a test. There's a workable alternative.. as this way sucks. + // We'd like to put this into a text file parhaps that's easily editable. + // + // For this test to work, I used the following secondlife.exe parameters + // "C:\Program Files\SecondLifeWindLight\SecondLifeWindLight.exe" -settings settings_windlight.xml -channel "Second Life WindLight" -set SystemLanguage en-us -loginpage http://10.1.1.2:8002/?show_login_form=TRUE -loginuri http://10.1.1.2:8002 -user 10.1.1.2 + // + // Even after all that, there's still an error, but it's a start. + // + // I depend on show_login_form being in the secondlife.exe parameters to figure out + // to display the form, or process it. + // a better way would be nifty. + Stream requestStream = request.InputStream; + + Encoding encoding = Encoding.UTF8; + StreamReader reader = new StreamReader(requestStream, encoding); + + string requestBody = reader.ReadToEnd(); + reader.Close(); + requestStream.Close(); + + string responseString = String.Empty; + + Hashtable keysvals = new Hashtable(); + Hashtable headervals = new Hashtable(); + string host = String.Empty; + + string[] querystringkeys = request.QueryString.AllKeys; + string[] rHeaders = request.Headers.AllKeys; + + + foreach (string queryname in querystringkeys) + { + keysvals.Add(queryname, request.QueryString[queryname]); + + } + + foreach (string headername in rHeaders) + { + //m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); + headervals[headername] = request.Headers[headername]; + } + + if (headervals.Contains("Host")) + { + host = (string)headervals["Host"]; + } + + if (keysvals.Contains("method")) + { + //m_log.Warn("[HTTP]: Contains Method"); + string method = (string) keysvals["method"]; + //m_log.Warn("[HTTP]: " + requestBody); + GenericHTTPMethod requestprocessor; + bool foundHandler = TryGetHTTPHandler(method, out requestprocessor); + if (foundHandler) + { + Hashtable responsedata = requestprocessor(keysvals); + DoHTTPGruntWork(responsedata,response); + + //SendHTML500(response); + + } + else + { + //m_log.Warn("[HTTP]: Handler Not Found"); + SendHTML404(response, host); + } + } + else + { + //m_log.Warn("[HTTP]: No Method specified"); + SendHTML404(response, host); + } + } + + private void DoHTTPGruntWork(Hashtable responsedata, HttpListenerResponse response) + { + int responsecode = (int)responsedata["int_response_code"]; + string responseString = (string)responsedata["str_response_string"]; + + // We're forgoing the usual error status codes here because the client + // ignores anything but 200 and 301 + + response.StatusCode = 200; + + if (responsecode == 301) + { + response.RedirectLocation = (string)responsedata["str_redirect_location"]; + response.StatusCode = responsecode; + } + response.AddHeader("Content-type", "text/html"); + + byte[] buffer = Encoding.UTF8.GetBytes(responseString); + + response.SendChunked = false; + response.ContentLength64 = buffer.Length; + response.ContentEncoding = Encoding.UTF8; + try + { + response.OutputStream.Write(buffer, 0, buffer.Length); + } + catch (Exception ex) + { + m_log.Warn("[HTTPD]: Error - " + ex.Message); + } + finally + { + response.OutputStream.Close(); + } + + + } + public void SendHTML404(HttpListenerResponse response, string host) + { + // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s + response.StatusCode = 200; + response.AddHeader("Content-type", "text/html"); + + string responseString = GetHTTP404(host); + byte[] buffer = Encoding.UTF8.GetBytes(responseString); + + response.SendChunked = false; + response.ContentLength64 = buffer.Length; + response.ContentEncoding = Encoding.UTF8; + try + { + response.OutputStream.Write(buffer, 0, buffer.Length); + } + catch (Exception ex) + { + m_log.Warn("[HTTPD]: Error - " + ex.Message); + } + finally + { + response.OutputStream.Close(); + } + } + public void SendHTML500(HttpListenerResponse response) + { + // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s + response.StatusCode = 200; + response.AddHeader("Content-type", "text/html"); + + string responseString = GetHTTP500(); + byte[] buffer = Encoding.UTF8.GetBytes(responseString); + + response.SendChunked = false; + response.ContentLength64 = buffer.Length; + response.ContentEncoding = Encoding.UTF8; + try + { + response.OutputStream.Write(buffer, 0, buffer.Length); + } + catch (Exception ex) + { + m_log.Warn("[HTTPD]: Error - " + ex.Message); + } + finally + { + response.OutputStream.Close(); + } + } + + public void Start() + { + m_log.Info("[HTTPD]: Starting up HTTP Server"); + + m_workerThread = new Thread(new ThreadStart(StartHTTP)); + m_workerThread.IsBackground = true; + m_workerThread.Start(); + } + + private void StartHTTP() + { + try + { + m_log.Info("[HTTPD]: Spawned main thread OK"); + m_httpListener = new HttpListener(); + + if (!m_ssl) + { + m_httpListener.Prefixes.Add("http://+:" + m_port + "/"); + } + else + { + m_httpListener.Prefixes.Add("https://+:" + m_port + "/"); + } + m_httpListener.Start(); + + HttpListenerContext context; + while (true) + { + context = m_httpListener.GetContext(); + ThreadPool.QueueUserWorkItem(new WaitCallback(HandleRequest), context); + } + } + catch (Exception e) + { + m_log.Warn("[HTTPD]: Error - " + e.Message); + } + } + + + public void RemoveStreamHandler(string httpMethod, string path) + { + m_streamHandlers.Remove(GetHandlerKey(httpMethod, path)); + } + + public void RemoveHTTPHandler(string httpMethod, string path) + { + m_HTTPHandlers.Remove(GetHandlerKey(httpMethod, path)); + } + + public string GetHTTP404(string host) + { + string file = Path.Combine(Util.configDir(), "http_404.html"); + if (!File.Exists(file)) + return getDefaultHTTP404(host); + + StreamReader sr = File.OpenText(file); + string result = sr.ReadToEnd(); + sr.Close(); + return result; + } + + public string GetHTTP500() + { + string file = Path.Combine(Util.configDir(), "http_500.html"); + if (!File.Exists(file)) + return getDefaultHTTP500(); + + StreamReader sr = File.OpenText(file); + string result = sr.ReadToEnd(); + sr.Close(); + return result; + } + + // Fallback HTTP responses in case the HTTP error response files don't exist + private string getDefaultHTTP404(string host) + { + return "404 Page not found

Ooops!

The page you requested has been obsconded with by knomes. Find hippos quick!

If you are trying to log-in, your link parameters should have: "-loginpage http://" + host + "/?method=login -loginuri http://" + host + "/" in your link

"; + } + + private string getDefaultHTTP500() + { + return "500 Internal Server Error

Ooops!

The server you requested is overun by knomes! Find hippos quick!

"; + } + + } +} diff --git a/trunk/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/trunk/OpenSim/Framework/Servers/BaseOpenSimServer.cs new file mode 100644 index 0000000000..4831446b5b --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -0,0 +1,84 @@ +/* +* 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; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Servers +{ + /// + /// Common base for the main OpenSimServers (user, grid, inventory, region, etc) + /// + public abstract class BaseOpenSimServer + { + protected ConsoleBase m_console; + protected DateTime m_startuptime; + + public BaseOpenSimServer() + { + m_startuptime = DateTime.Now; + } + + /// + /// Runs commands issued by the server console from the operator + /// + /// The first argument of the parameter (the command) + /// Additional arguments passed to the command + public virtual void RunCmd(string command, string[] cmdparams) + { + switch (command) + { + case "help": + m_console.Notice("show uptime - show server startup and uptime."); + break; + + case "show": + if (cmdparams.Length > 0) + { + Show(cmdparams[0]); + } + break; + } + } + + /// + /// Outputs to the console information about the region + /// + /// What information to display (valid arguments are "uptime", "users") + public virtual void Show(string ShowWhat) + { + switch (ShowWhat) + { + case "uptime": + m_console.Notice("Server has been running since " + m_startuptime.ToString()); + m_console.Notice("That is " + (DateTime.Now - m_startuptime).ToString()); + break; + } + } + } +} diff --git a/trunk/OpenSim/Framework/Servers/BaseRequestHandler.cs b/trunk/OpenSim/Framework/Servers/BaseRequestHandler.cs new file mode 100644 index 0000000000..3ff9a9faf5 --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/BaseRequestHandler.cs @@ -0,0 +1,63 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Framework.Servers +{ + public class BaseRequestHandler + { + public virtual string ContentType + { + get { return "application/xml"; } + } + + private readonly string m_httpMethod; + + public virtual string HttpMethod + { + get { return m_httpMethod; } + } + + private readonly string m_path; + + protected BaseRequestHandler(string httpMethod, string path) + { + m_httpMethod = httpMethod; + m_path = path; + } + + public virtual string Path + { + get { return m_path; } + } + + protected string GetParam(string path) + { + return path.Substring(m_path.Length); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/BaseStreamHandler.cs b/trunk/OpenSim/Framework/Servers/BaseStreamHandler.cs new file mode 100644 index 0000000000..a17c6ec9ab --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/BaseStreamHandler.cs @@ -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. +* +*/ + +using System.IO; + +namespace OpenSim.Framework.Servers +{ + public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler + { + public abstract byte[] Handle(string path, Stream request); + + protected BaseStreamHandler(string httpMethod, string path) : base(httpMethod, path) + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/BinaryStreamHandler.cs b/trunk/OpenSim/Framework/Servers/BinaryStreamHandler.cs new file mode 100644 index 0000000000..65fa3c9ca7 --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/BinaryStreamHandler.cs @@ -0,0 +1,74 @@ +/* +* 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.IO; +using System.Text; + +namespace OpenSim.Framework.Servers +{ + public delegate string BinaryMethod(byte[] data, string path, string param); + + public class BinaryStreamHandler : BaseStreamHandler + { + private BinaryMethod m_method; + + public override byte[] Handle(string path, Stream request) + { + byte[] data = ReadFully(request); + string param = GetParam(path); + string responseString = m_method(data, path, param); + + return Encoding.UTF8.GetBytes(responseString); + } + + public BinaryStreamHandler(string httpMethod, string path, BinaryMethod binaryMethod) + : base(httpMethod, path) + { + m_method = binaryMethod; + } + + private byte[] ReadFully(Stream stream) + { + byte[] buffer = new byte[32768]; + using (MemoryStream ms = new MemoryStream()) + { + while (true) + { + int read = stream.Read(buffer, 0, buffer.Length); + + if (read <= 0) + { + return ms.ToArray(); + } + + ms.Write(buffer, 0, read); + } + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/CheckSumServer.cs b/trunk/OpenSim/Framework/Servers/CheckSumServer.cs new file mode 100644 index 0000000000..6599d86450 --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/CheckSumServer.cs @@ -0,0 +1,127 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Framework.Servers +{ + /* + public class CheckSumServer : UDPServerBase + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public CheckSumServer(int port) + : base(port) + { + } + + protected override void OnReceivedData(IAsyncResult result) + { + ipeSender = new IPEndPoint(IPAddress.Any, 0); + epSender = (EndPoint)ipeSender; + Packet packet = null; + int numBytes = Server.EndReceiveFrom(result, ref epSender); + int packetEnd = numBytes - 1; + + packet = Packet.BuildPacket(RecvBuffer, ref packetEnd, ZeroBuffer); + + if (packet.Type == PacketType.SecuredTemplateChecksumRequest) + { + SecuredTemplateChecksumRequestPacket checksum = (SecuredTemplateChecksumRequestPacket)packet; + TemplateChecksumReplyPacket checkreply = new TemplateChecksumReplyPacket(); + checkreply.DataBlock.Checksum = 3220703154;//180572585; + checkreply.DataBlock.Flags = 0; + checkreply.DataBlock.MajorVersion = 1; + checkreply.DataBlock.MinorVersion = 15; + checkreply.DataBlock.PatchVersion = 0; + checkreply.DataBlock.ServerVersion = 0; + checkreply.TokenBlock.Token = checksum.TokenBlock.Token; + this.SendPacket(checkreply, epSender); + + /* + //if we wanted to echo the the checksum/ version from the client (so that any client worked) + SecuredTemplateChecksumRequestPacket checkrequest = new SecuredTemplateChecksumRequestPacket(); + checkrequest.TokenBlock.Token = checksum.TokenBlock.Token; + this.SendPacket(checkrequest, epSender); + + } + else if (packet.Type == PacketType.TemplateChecksumReply) + { + //echo back the client checksum reply (Hegemon's method) + TemplateChecksumReplyPacket checksum2 = (TemplateChecksumReplyPacket)packet; + TemplateChecksumReplyPacket checkreply2 = new TemplateChecksumReplyPacket(); + checkreply2.DataBlock.Checksum = checksum2.DataBlock.Checksum; + checkreply2.DataBlock.Flags = checksum2.DataBlock.Flags; + checkreply2.DataBlock.MajorVersion = checksum2.DataBlock.MajorVersion; + checkreply2.DataBlock.MinorVersion = checksum2.DataBlock.MinorVersion; + checkreply2.DataBlock.PatchVersion = checksum2.DataBlock.PatchVersion; + checkreply2.DataBlock.ServerVersion = checksum2.DataBlock.ServerVersion; + checkreply2.TokenBlock.Token = checksum2.TokenBlock.Token; + this.SendPacket(checkreply2, epSender); + } + else + { + } + + Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null); + } + + private void SendPacket(Packet Pack, EndPoint endp) + { + if (!Pack.Header.Resent) + { + Pack.Header.Sequence = 1; + } + + byte[] ZeroOutBuffer = new byte[4096]; + byte[] sendbuffer; + sendbuffer = Pack.ToBytes(); + + try + { + if (Pack.Header.Zerocoded) + { + int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer); + this.SendPackTo(ZeroOutBuffer, packetsize, SocketFlags.None, endp); + } + else + { + this.SendPackTo(sendbuffer, sendbuffer.Length, SocketFlags.None, endp); + } + } + catch (Exception) + { + m_log.Warn("CheckSumServer.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection "); + } + } + + private void SendPackTo(byte[] buffer, int size, SocketFlags flags, EndPoint endp) + { + this.Server.SendTo(buffer, size, flags, endp); + } + * } + */ +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/GenericHTTPMethod.cs b/trunk/OpenSim/Framework/Servers/GenericHTTPMethod.cs new file mode 100644 index 0000000000..76aa8fe852 --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/GenericHTTPMethod.cs @@ -0,0 +1,34 @@ +/* +* 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; +using System.Collections; + +namespace OpenSim.Framework.Servers +{ + public delegate Hashtable GenericHTTPMethod(Hashtable request); +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/IStreamHandler.cs b/trunk/OpenSim/Framework/Servers/IStreamHandler.cs new file mode 100644 index 0000000000..d52f9ac41f --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/IStreamHandler.cs @@ -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 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.Collections; +using System.IO; + +namespace OpenSim.Framework.Servers +{ + public interface IRequestHandler + { + // Return response content type + string ContentType { get; } + + // Return required http method + string HttpMethod { get; } + + // Return path + string Path { get; } + + } + + public interface IStreamedRequestHandler : IRequestHandler + { + // Handle request stream, return byte array + byte[] Handle(string path, Stream request); + } + + public interface IStreamHandler : IRequestHandler + { + // Handle request stream, return byte array + void Handle(string path, Stream request, Stream response); + } + public interface IGenericHTTPHandler : IRequestHandler + { + Hashtable Handle(string path, Hashtable request); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/LLSDMethod.cs b/trunk/OpenSim/Framework/Servers/LLSDMethod.cs new file mode 100644 index 0000000000..5cd225b535 --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/LLSDMethod.cs @@ -0,0 +1,33 @@ +/* +* 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 libsecondlife.StructuredData; + +namespace OpenSim.Framework.Servers +{ + public delegate LLSD LLSDMethod(LLSD request); +} diff --git a/trunk/OpenSim/Framework/Servers/MessageServerInfo.cs b/trunk/OpenSim/Framework/Servers/MessageServerInfo.cs new file mode 100644 index 0000000000..ec4155b462 --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/MessageServerInfo.cs @@ -0,0 +1,48 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Framework.Servers +{ + public class MessageServerInfo + { + public string URI; + public string sendkey; + public string recvkey; + public List responsibleForRegions; + public MessageServerInfo() + { + } + public override string ToString() + { + return URI; + } + } +} diff --git a/trunk/OpenSim/Framework/Servers/RestDeserialiseHandler.cs b/trunk/OpenSim/Framework/Servers/RestDeserialiseHandler.cs new file mode 100644 index 0000000000..1000e9ed78 --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/RestDeserialiseHandler.cs @@ -0,0 +1,66 @@ +/* +* 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.IO; +using System.Xml; +using System.Xml.Serialization; + +namespace OpenSim.Framework.Servers +{ + public delegate TResponse RestDeserialiseMethod(TRequest request); + + public class RestDeserialisehandler : BaseRequestHandler, IStreamHandler + where TRequest : new() + { + private RestDeserialiseMethod m_method; + + public RestDeserialisehandler(string httpMethod, string path, RestDeserialiseMethod method) + : base(httpMethod, path) + { + m_method = method; + } + + public void Handle(string path, Stream request, Stream responseStream) + { + TRequest deserial; + using (XmlTextReader xmlReader = new XmlTextReader(request)) + { + XmlSerializer deserializer = new XmlSerializer(typeof (TRequest)); + deserial = (TRequest) deserializer.Deserialize(xmlReader); + } + + TResponse response = m_method(deserial); + + using (XmlWriter xmlWriter = XmlTextWriter.Create(responseStream)) + { + XmlSerializer serializer = new XmlSerializer(typeof (TResponse)); + serializer.Serialize(xmlWriter, response); + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/RestMethod.cs b/trunk/OpenSim/Framework/Servers/RestMethod.cs new file mode 100644 index 0000000000..ce2239b593 --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/RestMethod.cs @@ -0,0 +1,31 @@ +/* +* 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. +* +*/ +namespace OpenSim.Framework.Servers +{ + public delegate string RestMethod(string request, string path, string param); +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/RestObjectPoster.cs b/trunk/OpenSim/Framework/Servers/RestObjectPoster.cs new file mode 100644 index 0000000000..212361cfaa --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/RestObjectPoster.cs @@ -0,0 +1,81 @@ +/* +* 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; +using System.IO; +using System.Net; +using System.Text; +using System.Xml; +using System.Xml.Serialization; + +namespace OpenSim.Framework.Servers +{ + public class RestObjectPoster + { + public static void BeginPostObject(string requestUrl, TRequest obj) + { + BeginPostObject("POST", requestUrl, obj); + } + + public static void BeginPostObject(string verb, string requestUrl, TRequest obj) + { + Type type = typeof (TRequest); + + WebRequest request = WebRequest.Create(requestUrl); + request.Method = verb; + request.ContentType = "text/xml"; + + MemoryStream buffer = new MemoryStream(); + + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Encoding = Encoding.UTF8; + + using (XmlWriter writer = XmlWriter.Create(buffer, settings)) + { + XmlSerializer serializer = new XmlSerializer(type); + serializer.Serialize(writer, obj); + writer.Flush(); + } + + int length = (int) buffer.Length; + request.ContentLength = length; + + Stream requestStream = request.GetRequestStream(); + requestStream.Write(buffer.ToArray(), 0, length); + IAsyncResult result = request.BeginGetResponse(AsyncCallback, request); + } + + private static void AsyncCallback(IAsyncResult result) + { + WebRequest request = (WebRequest) result.AsyncState; + using (WebResponse resp = request.EndGetResponse(result)) + { + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/RestObjectPosterResponse.cs b/trunk/OpenSim/Framework/Servers/RestObjectPosterResponse.cs new file mode 100644 index 0000000000..2961e044c0 --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/RestObjectPosterResponse.cs @@ -0,0 +1,93 @@ +/* +* 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; +using System.IO; +using System.Net; +using System.Text; +using System.Xml; +using System.Xml.Serialization; + +namespace OpenSim.Framework.Servers +{ + public delegate void ReturnResponse(T reponse); + + public class RestObjectPosterResponse + { + public ReturnResponse ResponseCallback; + + public void BeginPostObject(string requestUrl, TRequest obj) + { + BeginPostObject("POST", requestUrl, obj); + } + + public void BeginPostObject(string verb, string requestUrl, TRequest obj) + { + Type type = typeof (TRequest); + + WebRequest request = WebRequest.Create(requestUrl); + request.Method = verb; + request.ContentType = "text/xml"; + + MemoryStream buffer = new MemoryStream(); + + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Encoding = Encoding.UTF8; + + using (XmlWriter writer = XmlWriter.Create(buffer, settings)) + { + XmlSerializer serializer = new XmlSerializer(type); + serializer.Serialize(writer, obj); + writer.Flush(); + } + + int length = (int) buffer.Length; + request.ContentLength = length; + + Stream requestStream = request.GetRequestStream(); + requestStream.Write(buffer.ToArray(), 0, length); + IAsyncResult result = request.BeginGetResponse(AsyncCallback, request); + } + + private void AsyncCallback(IAsyncResult result) + { + WebRequest request = (WebRequest) result.AsyncState; + using (WebResponse resp = request.EndGetResponse(result)) + { + TResponse deserial; + XmlSerializer deserializer = new XmlSerializer(typeof (TResponse)); + deserial = (TResponse) deserializer.Deserialize(resp.GetResponseStream()); + + if (deserial != null && ResponseCallback != null) + { + ResponseCallback(deserial); + } + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/RestStreamHandler.cs b/trunk/OpenSim/Framework/Servers/RestStreamHandler.cs new file mode 100644 index 0000000000..04503871da --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/RestStreamHandler.cs @@ -0,0 +1,57 @@ +/* +* 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.IO; +using System.Text; + +namespace OpenSim.Framework.Servers +{ + public class RestStreamHandler : BaseStreamHandler + { + private RestMethod m_restMethod; + + public override byte[] Handle(string path, Stream request) + { + Encoding encoding = Encoding.UTF8; + StreamReader streamReader = new StreamReader(request, encoding); + + string requestBody = streamReader.ReadToEnd(); + streamReader.Close(); + + string param = GetParam(path); + string responseString = m_restMethod(requestBody, path, param); + + return Encoding.UTF8.GetBytes(responseString); + } + + public RestStreamHandler(string httpMethod, string path, RestMethod restMethod) : base(httpMethod, path) + { + m_restMethod = restMethod; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/SynchronousRestObjectPoster.cs b/trunk/OpenSim/Framework/Servers/SynchronousRestObjectPoster.cs new file mode 100644 index 0000000000..cfb585bf48 --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/SynchronousRestObjectPoster.cs @@ -0,0 +1,74 @@ +/* +* 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; +using System.IO; +using System.Net; +using System.Text; +using System.Xml; +using System.Xml.Serialization; + +namespace OpenSim.Framework.Servers +{ + public class SynchronousRestObjectPoster + { + public static TResponse BeginPostObject(string verb, string requestUrl, TRequest obj) + { + Type type = typeof (TRequest); + + WebRequest request = WebRequest.Create(requestUrl); + request.Method = verb; + request.ContentType = "text/xml"; + + MemoryStream buffer = new MemoryStream(); + + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Encoding = Encoding.UTF8; + + using (XmlWriter writer = XmlWriter.Create(buffer, settings)) + { + XmlSerializer serializer = new XmlSerializer(type); + serializer.Serialize(writer, obj); + writer.Flush(); + } + + int length = (int) buffer.Length; + request.ContentLength = length; + + Stream requestStream = request.GetRequestStream(); + requestStream.Write(buffer.ToArray(), 0, length); + TResponse deserial = default(TResponse); + using (WebResponse resp = request.GetResponse()) + { + XmlSerializer deserializer = new XmlSerializer(typeof (TResponse)); + deserial = (TResponse) deserializer.Deserialize(resp.GetResponseStream()); + } + return deserial; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Servers/XmlRpcMethod.cs b/trunk/OpenSim/Framework/Servers/XmlRpcMethod.cs new file mode 100644 index 0000000000..b156cddfd1 --- /dev/null +++ b/trunk/OpenSim/Framework/Servers/XmlRpcMethod.cs @@ -0,0 +1,33 @@ +/* +* 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 Nwc.XmlRpc; + +namespace OpenSim.Framework.Servers +{ + public delegate XmlRpcResponse XmlRpcMethod(XmlRpcRequest request); +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Statistics/AssetStatsReporter.cs b/trunk/OpenSim/Framework/Statistics/AssetStatsReporter.cs new file mode 100644 index 0000000000..4f2ef867a8 --- /dev/null +++ b/trunk/OpenSim/Framework/Statistics/AssetStatsReporter.cs @@ -0,0 +1,106 @@ +/* +* 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; +using System.Text; +using System.Timers; + +namespace OpenSim.Framework.Statistics +{ + /// + /// Collects and reports information on the requests made to the asset server + /// + public class AssetStatsReporter + { + private Timer ageStatsTimer = new Timer(24 * 60 * 60 * 1000); + private DateTime startTime = DateTime.Now; + + private long assetRequestsToday; + private long assetRequestsNotFoundToday; + private long assetRequestsYesterday; + private long assetRequestsNotFoundYesterday; + + public long AssetRequestsToday { get { return assetRequestsToday; } } + public long AssetRequestsNotFoundToday { get { return assetRequestsNotFoundToday; } } + public long AssetRequestsYesterday { get { return assetRequestsYesterday; } } + public long AssetRequestsNotFoundYesterday { get { return assetRequestsNotFoundYesterday; } } + + public AssetStatsReporter() + { + ageStatsTimer.Elapsed += new ElapsedEventHandler(OnAgeing); + ageStatsTimer.Enabled = true; + } + + private void OnAgeing(object source, ElapsedEventArgs e) + { + assetRequestsYesterday = assetRequestsToday; + + // There is a possibility that an asset request could occur between the execution of these + // two statements. But we're better off without the synchronization overhead. + assetRequestsToday = 0; + + assetRequestsNotFoundYesterday = assetRequestsNotFoundToday; + assetRequestsNotFoundToday = 0; + } + + /// + /// Record that an asset request failed to find an asset + /// + public void AddNotFoundRequest() + { + assetRequestsNotFoundToday++; + } + + /// + /// Record that a request was made to the asset server + /// + public void AddRequest() + { + assetRequestsToday++; + } + + /// + /// Report back collected statistical information. + /// + /// + public string Report() + { + double elapsedHours = (DateTime.Now - startTime).TotalHours; + if (elapsedHours <= 0) { elapsedHours = 1; } // prevent divide by zero + + long assetRequestsTodayPerHour = (long)Math.Round(AssetRequestsToday / elapsedHours); + long assetRequestsYesterdayPerHour = (long)Math.Round(AssetRequestsYesterday / 24.0); + + return string.Format( +@"Asset requests today : {0} ({1} per hour) of which {2} were not found +Asset requests yesterday : {3} ({4} per hour) of which {5} were not found", + AssetRequestsToday, assetRequestsTodayPerHour, AssetRequestsNotFoundToday, + AssetRequestsYesterday, assetRequestsYesterdayPerHour, AssetRequestsNotFoundYesterday); + } + } +} diff --git a/trunk/OpenSim/Framework/Statistics/SimExtraStatsReporter.cs b/trunk/OpenSim/Framework/Statistics/SimExtraStatsReporter.cs new file mode 100644 index 0000000000..73f36f94a2 --- /dev/null +++ b/trunk/OpenSim/Framework/Statistics/SimExtraStatsReporter.cs @@ -0,0 +1,70 @@ +/* +* 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 OpenSim.Framework; + +namespace OpenSim.Framework.Statistics +{ + public class SimExtraStatsReporter + { + private long assetsInCache; + private long texturesInCache; + private long assetCacheMemoryUsage; + private long textureCacheMemoryUsage; + + public long AssetsInCache { get { return assetsInCache; } } + public long TexturesInCache { get { return texturesInCache; } } + public long AssetCacheMemoryUsage { get { return assetCacheMemoryUsage; } } + public long TextureCacheMemoryUsage { get { return textureCacheMemoryUsage; } } + + public void AddAsset(AssetBase asset) + { + assetsInCache++; + assetCacheMemoryUsage += asset.Data.Length; + } + + public void AddTexture(AssetBase image) + { + texturesInCache++; + textureCacheMemoryUsage += image.Data.Length; + } + + /// + /// Report back collected statistical information. + /// + /// + public string Report() + { + return string.Format( +@"Asset cache contains {0,6} assets using {1,10:0.000}K +Texture cache contains {2,6} textures using {3,10:0.000}K", + AssetsInCache, AssetCacheMemoryUsage / 1024.0, + TexturesInCache, TextureCacheMemoryUsage / 1024.0); + } + } +} diff --git a/trunk/OpenSim/Framework/Statistics/StatsManager.cs b/trunk/OpenSim/Framework/Statistics/StatsManager.cs new file mode 100644 index 0000000000..842f1f18af --- /dev/null +++ b/trunk/OpenSim/Framework/Statistics/StatsManager.cs @@ -0,0 +1,73 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Framework.Statistics +{ + /// + /// Singleton used to provide access to statistics reporters + /// + public class StatsManager + { + private static AssetStatsReporter assetStats; + private static UserStatsReporter userStats; + private static SimExtraStatsReporter simExtraStats; + + public static AssetStatsReporter AssetStats { get { return assetStats; } } + public static UserStatsReporter UserStats { get { return userStats; } } + public static SimExtraStatsReporter SimExtraStats { get { return simExtraStats; } } + + private StatsManager() {} + + /// + /// Start collecting statistics related to assets. + /// Should only be called once. + /// + public static void StartCollectingAssetStats() + { + assetStats = new AssetStatsReporter(); + } + + /// + /// Start collecting statistics related to users. + /// Should only be called once. + /// + public static void StartCollectingUserStats() + { + userStats = new UserStatsReporter(); + } + + /// + /// Start collecting extra sim statistics apart from those collected for the client. + /// Should only be called once. + /// + public static void StartCollectingSimExtraStats() + { + simExtraStats = new SimExtraStatsReporter(); + } + } +} diff --git a/trunk/OpenSim/Framework/Statistics/UserStatsReporter.cs b/trunk/OpenSim/Framework/Statistics/UserStatsReporter.cs new file mode 100644 index 0000000000..bd4f95b418 --- /dev/null +++ b/trunk/OpenSim/Framework/Statistics/UserStatsReporter.cs @@ -0,0 +1,94 @@ +/* +* 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.Text; +using System.Timers; + +namespace OpenSim.Framework.Statistics +{ + /// + /// Description of UserStatsReporter. + /// + public class UserStatsReporter + { + private Timer ageStatsTimer = new Timer(24 * 60 * 60 * 1000); + + private int successfulLoginsToday; + public int SuccessfulLoginsToday { get { return successfulLoginsToday; } } + + private int successfulLoginsYesterday; + public int SuccessfulLoginsYesterday { get { return successfulLoginsYesterday; } } + + private int successfulLogins; + public int SuccessfulLogins { get { return successfulLogins; } } + + private int logouts; + public int Logouts { get { return logouts; } } + + public UserStatsReporter() + { + ageStatsTimer.Elapsed += new ElapsedEventHandler(OnAgeing); + ageStatsTimer.Enabled = true; + } + + private void OnAgeing(object source, ElapsedEventArgs e) + { + successfulLoginsYesterday = successfulLoginsToday; + + // There is a possibility that an asset request could occur between the execution of these + // two statements. But we're better off without the synchronization overhead. + successfulLoginsToday = 0; + } + + /// + /// Record a successful login + /// + public void AddSuccessfulLogin() + { + successfulLogins++; + successfulLoginsToday++; + } + + public void AddLogout() + { + logouts++; + } + + /// + /// Report back collected statistical information. + /// + /// + public string Report() + { + return string.Format( +@"Successful logins total : {0}, today : {1}, yesterday : {2} + Logouts total : {3}", + SuccessfulLogins, SuccessfulLoginsToday, SuccessfulLoginsYesterday, Logouts); + } + } +} diff --git a/trunk/OpenSim/Framework/TaskInventoryItem.cs b/trunk/OpenSim/Framework/TaskInventoryItem.cs new file mode 100644 index 0000000000..3009259882 --- /dev/null +++ b/trunk/OpenSim/Framework/TaskInventoryItem.cs @@ -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 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.Collections.Generic; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +using libsecondlife; +using System; + +namespace OpenSim.Framework +{ + /// + /// A dictionary for task inventory. + /// + /// This class is not thread safe. Callers must synchronize on Dictionary methods. + /// + public class TaskInventoryDictionary : Dictionary, + ICloneable, IXmlSerializable + { + private static XmlSerializer tiiSerializer = new XmlSerializer(typeof(TaskInventoryItem)); + + // The alternative of simply serializing the list doesn't appear to work on mono, since + // we get a + // + // System.TypeInitializationException: An exception was thrown by the type initializer for OpenSim.Framework.TaskInventoryDictionary ---> System.ArgumentOutOfRangeException: < 0 + // Parameter name: length + // at System.String.Substring (Int32 startIndex, Int32 length) [0x00088] in /build/buildd/mono-1.2.4/mcs/class/corlib/System/String.cs:381 + // at System.Xml.Serialization.TypeTranslator.GetTypeData (System.Type runtimeType, System.String xmlDataType) [0x001f6] in /build/buildd/mono-1.2.4/mcs/class/System.XML/System.Xml.Serialization/TypeTranslator.cs:217 + // ... +// private static XmlSerializer tiiSerializer +// = new XmlSerializer(typeof(Dictionary.ValueCollection)); + + // see IXmlSerializable + public XmlSchema GetSchema() + { + return null; + } + + // see IXmlSerializable + public void ReadXml(XmlReader reader) + { + reader.Read(); + while (tiiSerializer.CanDeserialize(reader)) + { + TaskInventoryItem item = (TaskInventoryItem)tiiSerializer.Deserialize(reader); + Add(item.ItemID, item); + } + +// reader.Read(); +// while (reader.Name.Equals("TaskInventoryItem")) +// { +// TaskInventoryItem item = (TaskInventoryItem)tiiSerializer.Deserialize(reader); +// Add(item.ItemID, item); +// } + +// ICollection items +// = (ICollection)tiiSerializer.Deserialize(reader); +// +// foreach (TaskInventoryItem item in items) +// { +// Add(item.ItemID, item); +// } + } + + // see IXmlSerializable + public void WriteXml(XmlWriter writer) + { + lock (this) + { + foreach (TaskInventoryItem item in Values) + { + tiiSerializer.Serialize(writer, item); + } + } + + //tiiSerializer.Serialize(writer, Values); + } + + // see ICloneable + public Object Clone() + { + TaskInventoryDictionary clone = new TaskInventoryDictionary(); + + lock (this) + { + foreach (LLUUID uuid in Keys) + { + clone.Add(uuid, (TaskInventoryItem)this[uuid].Clone()); + } + } + + return clone; + } + } + + /// + /// Represents an item in a task inventory + /// + public class TaskInventoryItem : ICloneable + { + /// + /// XXX This should really be factored out into some constants class. + /// + private const uint FULL_MASK_PERMISSIONS_GENERAL = 2147483647; + + /// + /// Inventory types + /// + public static string[] InvTypes = new string[] + { + "texture", + "sound", + String.Empty, + String.Empty, + String.Empty, + String.Empty, + String.Empty, + String.Empty, + String.Empty, + String.Empty, + "lsl_text", + String.Empty + }; + + /// + /// Asset types + /// + public static string[] Types = new string[] + { + "texture", + "sound", + String.Empty, + String.Empty, + String.Empty, + String.Empty, + String.Empty, + String.Empty, + String.Empty, + String.Empty, + "lsltext", + String.Empty + }; + + public LLUUID ItemID = LLUUID.Zero; + public LLUUID ParentID = LLUUID.Zero; //parent folder id + + public uint BaseMask = FULL_MASK_PERMISSIONS_GENERAL; + public uint OwnerMask = FULL_MASK_PERMISSIONS_GENERAL; + public uint GroupMask = FULL_MASK_PERMISSIONS_GENERAL; + public uint EveryoneMask = FULL_MASK_PERMISSIONS_GENERAL; + public uint NextOwnerMask = FULL_MASK_PERMISSIONS_GENERAL; + public LLUUID CreatorID = LLUUID.Zero; + public LLUUID OwnerID = LLUUID.Zero; + public LLUUID LastOwnerID = LLUUID.Zero; + public LLUUID GroupID = LLUUID.Zero; + + public LLUUID AssetID = LLUUID.Zero; + public int Type = 0; + public int InvType = 0; + public uint Flags = 0; + public string Name = String.Empty; + public string Description = String.Empty; + public uint CreationDate = 0; + + public LLUUID ParentPartID = LLUUID.Zero; + + /// + /// Reset the LLUUIDs for this item. + /// + /// The new part ID to which this item belongs + public void ResetIDs(LLUUID partID) + { + ItemID = LLUUID.Random(); + ParentPartID = partID; + } + + // See ICloneable + public Object Clone() + { + return MemberwiseClone(); + } + } +} diff --git a/trunk/OpenSim/Framework/UserConfig.cs b/trunk/OpenSim/Framework/UserConfig.cs new file mode 100644 index 0000000000..3a2f384bce --- /dev/null +++ b/trunk/OpenSim/Framework/UserConfig.cs @@ -0,0 +1,136 @@ +/* +* 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; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework +{ + /// + /// UserConfig -- For User Server Configuration + /// + public class UserConfig + { + public string DefaultStartupMsg = String.Empty; + public string GridServerURL = String.Empty; + public string GridSendKey = String.Empty; + public string GridRecvKey = String.Empty; + + public string InventoryUrl = String.Empty; + + public string DatabaseProvider = String.Empty; + + public static uint DefaultHttpPort = 8002; + public static bool DefaultHttpSSL = false; + public uint HttpPort = DefaultHttpPort; + public bool HttpSSL = DefaultHttpSSL; + public uint DefaultX = 1000; + public uint DefaultY = 1000; + + private ConfigurationMember configMember; + + public UserConfig(string description, string filename) + { + configMember = + new ConfigurationMember(filename, description, loadConfigurationOptions, handleIncomingConfiguration,true); + configMember.performConfigurationRetrieve(); + } + + public void loadConfigurationOptions() + { + configMember.addConfigurationOption("default_startup_message", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "Default Startup Message", "Welcome to OGS", false); + + configMember.addConfigurationOption("default_grid_server", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "Default Grid Server URI", + "http://127.0.0.1:" + GridConfig.DefaultHttpPort.ToString() + "/", false); + configMember.addConfigurationOption("grid_send_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to send to grid server", "null", false); + configMember.addConfigurationOption("grid_recv_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Key to expect from grid server", "null", false); + + configMember.addConfigurationOption("default_inventory_server", + ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, + "Default Inventory Server URI", + "http://127.0.0.1:" + InventoryConfig.DefaultHttpPort.ToString() + "/", + false); + configMember.addConfigurationOption("database_provider", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "DLL for database provider", "OpenSim.Framework.Data.MySQL.dll", false); + + configMember.addConfigurationOption("http_port", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Http Listener port", DefaultHttpPort.ToString(), false); + configMember.addConfigurationOption("http_ssl", ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN, + "Use SSL? true/false", DefaultHttpSSL.ToString(), false); + configMember.addConfigurationOption("default_X", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Known good region X", "1000", false); + configMember.addConfigurationOption("default_Y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, + "Known good region Y", "1000", false); + } + + public bool handleIncomingConfiguration(string configuration_key, object configuration_result) + { + switch (configuration_key) + { + case "default_startup_message": + DefaultStartupMsg = (string) configuration_result; + break; + case "default_grid_server": + GridServerURL = (string) configuration_result; + break; + case "grid_send_key": + GridSendKey = (string) configuration_result; + break; + case "grid_recv_key": + GridRecvKey = (string) configuration_result; + break; + case "default_inventory_server": + InventoryUrl = (string) configuration_result; + break; + case "database_provider": + DatabaseProvider = (string) configuration_result; + break; + case "http_port": + HttpPort = (uint) configuration_result; + break; + case "http_ssl": + HttpSSL = (bool) configuration_result; + break; + case "default_X": + DefaultX = (uint) configuration_result; + break; + case "default_Y": + DefaultY = (uint) configuration_result; + break; + } + + return true; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/UserProfileData.cs b/trunk/OpenSim/Framework/UserProfileData.cs new file mode 100644 index 0000000000..9c02d78396 --- /dev/null +++ b/trunk/OpenSim/Framework/UserProfileData.cs @@ -0,0 +1,230 @@ +/* +* 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; +using libsecondlife; + +namespace OpenSim.Framework +{ + /// + /// Information about a particular user known to the userserver + /// + public class UserProfileData + { + /// + /// The ID value for this user + /// + public LLUUID UUID; + + /// + /// The last used Web_login_key + /// + public LLUUID webLoginKey; + /// + /// The first component of a users account name + /// + public string username; + + /// + /// The second component of a users account name + /// + public string surname; + + /// + /// A salted hash containing the users password, in the format md5(md5(password) + ":" + salt) + /// + /// This is double MD5'd because the client sends an unsalted MD5 to the loginserver + public string passwordHash; + + /// + /// The salt used for the users hash, should be 32 bytes or longer + /// + public string passwordSalt; + + /// + /// The regionhandle of the users preffered home region. If multiple sims occupy the same spot, the grid may decide which region the user logs into + /// + public ulong homeRegion + { + get { return Helpers.UIntsToLong((homeRegionX * (uint)Constants.RegionSize), (homeRegionY * (uint)Constants.RegionSize)); } + set + { + homeRegionX = (uint) (value >> 40); + homeRegionY = (((uint) (value)) >> 8); + } + } + + public uint homeRegionX; + public uint homeRegionY; + + /// + /// The coordinates inside the region of the home location + /// + public LLVector3 homeLocation; + + /// + /// Where the user will be looking when they rez. + /// + public LLVector3 homeLookAt; + + /// + /// A UNIX Timestamp (seconds since epoch) for the users creation + /// + public int created; + + /// + /// A UNIX Timestamp for the users last login date / time + /// + public int lastLogin; + + public LLUUID rootInventoryFolderID; + + /// + /// A URI to the users inventory server, used for foreigners and large grids + /// + public string userInventoryURI = String.Empty; + + /// + /// A URI to the users asset server, used for foreigners and large grids. + /// + public string userAssetURI = String.Empty; + + /// + /// A uint mask containing the "I can do" fields of the users profile + /// + public uint profileCanDoMask; + + /// + /// A uint mask containing the "I want to do" part of the users profile + /// + public uint profileWantDoMask; // Profile window "I want to" mask + + /// + /// The about text listed in a users profile. + /// + public string profileAboutText = String.Empty; + + /// + /// The first life about text listed in a users profile + /// + public string profileFirstText = String.Empty; + + /// + /// The profile image for an avatar stored on the asset server + /// + public LLUUID profileImage; + + /// + /// The profile image for the users first life tab + /// + public LLUUID profileFirstImage; + + /// + /// The users last registered agent (filled in on the user server) + /// + public UserAgentData currentAgent; + } + + /// + /// Minimal User Data required to service the AvatarPickerReply + /// + //public class AvatarPickerAvatar + //{ + //public LLUUID AvatarID; + //public string firstName; + //public string lastName; + //public AvatarPickerAvatar() + //{ + //} + //} + /// + /// Information about a users session + /// + public class UserAgentData + { + /// + /// The UUID of the users avatar (not the agent!) + /// + public LLUUID UUID; + + /// + /// The IP address of the user + /// + public string agentIP = String.Empty; + + /// + /// The port of the user + /// + public uint agentPort; + + /// + /// Is the user online? + /// + public bool agentOnline; + + /// + /// The session ID for the user (also the agent ID) + /// + public LLUUID sessionID; + + /// + /// The "secure" session ID for the user + /// + /// Not very secure. Dont rely on it for anything more than Linden Lab does. + public LLUUID secureSessionID; + + /// + /// The region the user logged into initially + /// + public LLUUID regionID; + + /// + /// A unix timestamp from when the user logged in + /// + public int loginTime; + + /// + /// When this agent expired and logged out, 0 if still online + /// + public int logoutTime; + + /// + /// Current region the user is logged into + /// + public LLUUID currentRegion; + + /// + /// Region handle of the current region the user is in + /// + public ulong currentHandle; + + /// + /// The position of the user within the region + /// + public LLVector3 currentPos; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Framework/Util.cs b/trunk/OpenSim/Framework/Util.cs new file mode 100644 index 0000000000..856cac3fbc --- /dev/null +++ b/trunk/OpenSim/Framework/Util.cs @@ -0,0 +1,499 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Security.Cryptography; +using System.Text; +using libsecondlife; +using Nini.Config; + +namespace OpenSim.Framework +{ + public class Util + { + private static Random randomClass = new Random(); + private static uint nextXferID = 5000; + private static object XferLock = new object(); + private static Dictionary capsURLS = new Dictionary(); + + #region Vector Equasions + /// + /// Get the distance between two 3d vectors + /// + /// A 3d vector + /// A 3d vector + /// The distance between the two vectors + public static double GetDistanceTo(LLVector3 a, LLVector3 b) + { + float dx = a.X - b.X; + float dy = a.Y - b.Y; + float dz = a.Z - b.Z; + return Math.Sqrt(dx*dx + dy*dy + dz*dz); + } + + /// + /// Get the magnitude of a 3d vector + /// + /// A 3d vector + /// The magnitude of the vector + public static double GetMagnitude(LLVector3 a) { + return Math.Sqrt((a.X * a.X) + (a.Y * a.Y) + (a.Z * a.Z)); + } + + /// + /// Get a normalized form of a 3d vector + /// + /// A 3d vector + /// A new vector which is normalized form of the vector + /// The vector paramater cannot be <0,0,0> + public static LLVector3 GetNormalizedVector(LLVector3 a) + { + if (IsZeroVector(a)) + throw new ArgumentException("Vector paramater cannot be a zero vector."); + + float Mag = (float)GetMagnitude(a); + return new LLVector3(a.X / Mag, a.Y / Mag, a.Z / Mag); + } + + /// + /// Returns if a vector is a zero vector (has all zero components) + /// + /// + public static bool IsZeroVector( LLVector3 v ) + { + if( v.X == 0 && v.Y == 0 && v.Z == 0) + { + return true; + } + + return false; + } + # endregion + + public static ulong UIntsToLong(uint X, uint Y) + { + return Helpers.UIntsToLong(X, Y); + } + + public static Random RandomClass + { + get { return randomClass; } + } + + public static uint GetNextXferID() + { + uint id = 0; + lock (XferLock) + { + id = nextXferID; + nextXferID++; + } + return id; + } + + public Util() + { + } + + public static string GetFileName(string file) + { + // Return just the filename on UNIX platforms + // TODO: this should be customisable with a prefix, but that's something to do later. + if (Environment.OSVersion.Platform == PlatformID.Unix) + { + return file; + } + + // Return %APPDATA%/OpenSim/file for 2K/XP/NT/2K3/VISTA + // TODO: Switch this to System.Enviroment.SpecialFolders.ApplicationData + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + { + if (!Directory.Exists("%APPDATA%\\OpenSim\\")) + { + Directory.CreateDirectory("%APPDATA%\\OpenSim"); + } + + return "%APPDATA%\\OpenSim\\" + file; + } + + // Catch all - covers older windows versions + // (but those probably wont work anyway) + return file; + } + + public static bool IsEnvironmentSupported(ref string reason) + { + // Must have .NET 2.0 (Generics / libsl) + if (Environment.Version.Major < 2) + { + reason = ".NET 1.0/1.1 lacks components that is used by OpenSim"; + return false; + } + + // Windows 95/98/ME are unsupported + if (Environment.OSVersion.Platform == PlatformID.Win32Windows && + Environment.OSVersion.Platform != PlatformID.Win32NT) + { + reason = "Windows 95/98/ME will not run OpenSim"; + return false; + } + + // Windows 2000 / Pre-SP2 XP + if (Environment.OSVersion.Version.Major == 5 && ( + Environment.OSVersion.Version.Minor == 0)) + { + reason = "Please update to Windows XP Service Pack 2 or Server2003"; + return false; + } + + return true; + } + + public static int UnixTimeSinceEpoch() + { + TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1)); + int timestamp = (int) t.TotalSeconds; + return timestamp; + } + + public static string Md5Hash(string pass) + { + MD5 md5 = MD5CryptoServiceProvider.Create(); + byte[] dataMd5 = md5.ComputeHash(Encoding.Default.GetBytes(pass)); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < dataMd5.Length; i++) + sb.AppendFormat("{0:x2}", dataMd5[i]); + return sb.ToString(); + } + + public static string GetRandomCapsPath() + { + LLUUID caps = LLUUID.Random(); + string capsPath = caps.ToString(); + capsPath = capsPath.Remove(capsPath.Length - 4, 4); + return capsPath; + } + + public static int fast_distance2d(int x, int y) + { + x = Math.Abs(x); + y = Math.Abs(y); + + int min = Math.Min(x, y); + + return (x + y - (min >> 1) - (min >> 2) + (min >> 4)); + } + + public static string FieldToString(byte[] bytes) + { + return FieldToString(bytes, String.Empty); + } + + /// + /// Convert a variable length field (byte array) to a string, with a + /// field name prepended to each line of the output + /// + /// If the byte array has unprintable characters in it, a + /// hex dump will be put in the string instead + /// The byte array to convert to a string + /// A field name to prepend to each line of output + /// An ASCII string or a string containing a hex dump, minus + /// the null terminator + public static string FieldToString(byte[] bytes, string fieldName) + { + // Check for a common case + if (bytes.Length == 0) return String.Empty; + + StringBuilder output = new StringBuilder(); + bool printable = true; + + for (int i = 0; i < bytes.Length; ++i) + { + // Check if there are any unprintable characters in the array + if ((bytes[i] < 0x20 || bytes[i] > 0x7E) && bytes[i] != 0x09 + && bytes[i] != 0x0D && bytes[i] != 0x0A && bytes[i] != 0x00) + { + printable = false; + break; + } + } + + if (printable) + { + if (fieldName.Length > 0) + { + output.Append(fieldName); + output.Append(": "); + } + + output.Append(CleanString(UTF8Encoding.UTF8.GetString(bytes, 0, bytes.Length - 1))); + } + else + { + for (int i = 0; i < bytes.Length; i += 16) + { + if (i != 0) + output.Append(Environment.NewLine); + if (fieldName.Length > 0) + { + output.Append(fieldName); + output.Append(": "); + } + + for (int j = 0; j < 16; j++) + { + if ((i + j) < bytes.Length) + output.Append(String.Format("{0:X2} ", bytes[i + j])); + else + output.Append(" "); + } + + for (int j = 0; j < 16 && (i + j) < bytes.Length; j++) + { + if (bytes[i + j] >= 0x20 && bytes[i + j] < 0x7E) + output.Append((char) bytes[i + j]); + else + output.Append("."); + } + } + } + + return output.ToString(); + } + + /// + /// Returns a IP address from a specified DNS, favouring IPv4 addresses. + /// + /// DNS Hostname + /// An IP address, or null + public static IPAddress GetHostFromDNS(string dnsAddress) + { + // Is it already a valid IP? No need to look it up. + IPAddress ipa; + if (IPAddress.TryParse(dnsAddress, out ipa)) + return ipa; + + // Not an IP, lookup required + IPAddress[] hosts = Dns.GetHostEntry(dnsAddress).AddressList; + + foreach (IPAddress host in hosts) + { + if (host.AddressFamily == AddressFamily.InterNetwork) + { + return host; + } + } + + if (hosts.Length > 0) + return hosts[0]; + + return null; + } + + public static IPAddress GetLocalHost() + { + string dnsAddress = "localhost"; + + IPAddress[] hosts = Dns.GetHostEntry(dnsAddress).AddressList; + + foreach (IPAddress host in hosts) + { + if (!IPAddress.IsLoopback(host) && host.AddressFamily == AddressFamily.InterNetwork) + { + return host; + } + } + + if (hosts.Length > 0) + return hosts[0]; + + return null; + } + + // + // directory locations + // + + public static string homeDir() + { + string temp; +// string personal=(Environment.GetFolderPath(Environment.SpecialFolder.Personal)); +// temp = Path.Combine(personal,".OpenSim"); + temp = "."; + return temp; + } + + public static string assetsDir() + { + return Path.Combine(configDir(), "assets"); + } + + public static string inventoryDir() + { + return Path.Combine(configDir(), "inventory"); + } + + public static string configDir() + { + string temp; + temp = "."; + return temp; + } + + public static string dataDir() + { + string temp; + temp = "."; + return temp; + } + + public static string logDir() + { + string temp; + temp = "."; + return temp; + } + + public static string GetCapsURL(LLUUID userID) + { + if (capsURLS.ContainsKey(userID)) + { + return capsURLS[userID]; + } + return String.Empty; + } + + public static void SetCapsURL(LLUUID userID, string url) + { + if (capsURLS.ContainsKey(userID)) + { + capsURLS[userID] = url; + } + else + { + capsURLS.Add(userID, url); + } + } + + // Nini (config) related Methods + public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName) + { + if (!File.Exists(fileName)) + { + //create new file + } + XmlConfigSource config = new XmlConfigSource(fileName); + AddDataRowToConfig(config, row); + config.Save(); + + return config; + } + + public static void AddDataRowToConfig(IConfigSource config, DataRow row) + { + config.Configs.Add((string) row[0]); + for (int i = 0; i < row.Table.Columns.Count; i++) + { + config.Configs[(string) row[0]].Set(row.Table.Columns[i].ColumnName, row[i]); + } + } + + public static float Clip(float x, float min, float max) + { + return Math.Min(Math.Max(x, min), max); + } + + public static int Clip(int x, int min, int max) + { + return Math.Min(Math.Max(x, min), max); + } + + /// + /// Convert an LLUUID to a raw uuid string. Right now this is a string without hyphens. + /// + /// + /// + public static String ToRawUuidString(LLUUID lluuid) + { + return lluuid.UUID.ToString("n"); + } + + public static string CleanString(string input) + { + if(input.Length == 0) + return input; + + int clip=input.Length; + + // Test for ++ string terminator + int pos=input.IndexOf("\0"); + if(pos != -1 && pos < clip) + clip=pos; + + // Test for CR + pos=input.IndexOf("\r"); + if(pos != -1 && pos < clip) + clip=pos; + + // Test for LF + pos=input.IndexOf("\n"); + if(pos != -1 && pos < clip) + clip=pos; + + // Truncate string before first end-of-line character found + return input.Substring(0, clip); + } + + /// + /// returns the contents of /etc/issue on Unix Systems + /// Use this for where it's absolutely necessary to implement platform specific stuff + /// ( like the ODE library :P + /// + /// + public static string ReadEtcIssue() + { + try + { + StreamReader sr = new StreamReader("/etc/issue.net"); + string issue = sr.ReadToEnd(); + sr.Close(); + return issue; + } + catch (System.Exception) + { + return ""; + } + + } + } +} diff --git a/trunk/OpenSim/Framework/sLLVector3.cs b/trunk/OpenSim/Framework/sLLVector3.cs new file mode 100644 index 0000000000..8187597e81 --- /dev/null +++ b/trunk/OpenSim/Framework/sLLVector3.cs @@ -0,0 +1,52 @@ +/* +* 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; +using libsecondlife; + +namespace OpenSim.Framework +{ + [Serializable] + public class sLLVector3 + { + public sLLVector3() + { + } + + public sLLVector3(LLVector3 v) + { + x = v.X; + y = v.Y; + z = v.Z; + } + + public float x=0; + public float y=0; + public float z=0; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/AssetServer/Main.cs b/trunk/OpenSim/Grid/AssetServer/Main.cs new file mode 100644 index 0000000000..35e6495642 --- /dev/null +++ b/trunk/OpenSim/Grid/AssetServer/Main.cs @@ -0,0 +1,195 @@ +/* +* 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; +using System.IO; +using System.Reflection; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.AssetLoader.Filesystem; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Statistics; + +namespace OpenSim.Grid.AssetServer +{ + /// + /// An asset server + /// + public class OpenAsset_Main : BaseOpenSimServer, conscmd_callback + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public AssetConfig m_config; + + public static OpenAsset_Main assetserver; + + // Temporarily hardcoded - should be a plugin + protected IAssetLoader assetLoader = new AssetLoaderFileSystem(); + + private IAssetProvider m_assetProvider; + + [STAThread] + public static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + m_log.Info("Starting...\n"); + + assetserver = new OpenAsset_Main(); + assetserver.Startup(); + + assetserver.Work(); + } + + private void Work() + { + m_console.Notice("Enter help for a list of commands"); + + while (true) + { + m_console.Prompt(); + } + } + + private OpenAsset_Main() + { + m_console = new ConsoleBase("OpenAsset", this); + + MainConsole.Instance = m_console; + } + + public void Startup() + { + m_config = new AssetConfig("ASSET SERVER", (Path.Combine(Util.configDir(), "AssetServer_Config.xml"))); + + m_log.Info("[ASSET]: Setting up asset DB"); + setupDB(m_config); + + m_log.Info("[ASSET]: Loading default asset set.."); + LoadDefaultAssets(); + + m_log.Info("[ASSET]: Starting HTTP process"); + BaseHttpServer httpServer = new BaseHttpServer(m_config.HttpPort); + + StatsManager.StartCollectingAssetStats(); + + httpServer.AddStreamHandler(new GetAssetStreamHandler(this, m_assetProvider)); + httpServer.AddStreamHandler(new PostAssetStreamHandler(this, m_assetProvider)); + + httpServer.Start(); + } + + public byte[] GetAssetData(LLUUID assetID, bool isTexture) + { + return null; + } + + public IAssetProvider LoadDatabasePlugin(string FileName) + { + m_log.Info("[ASSET SERVER]: LoadDatabasePlugin: Attempting to load " + FileName); + Assembly pluginAssembly = Assembly.LoadFrom(FileName); + IAssetProvider assetPlugin = null; + foreach (Type pluginType in pluginAssembly.GetTypes()) + { + if (!pluginType.IsAbstract) + { + Type typeInterface = pluginType.GetInterface("IAssetProvider", true); + + if (typeInterface != null) + { + IAssetProvider plug = + (IAssetProvider) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + assetPlugin = plug; + assetPlugin.Initialise(); + + m_log.Info("[ASSET SERVER]: Added " + assetPlugin.Name + " " + assetPlugin.Version); + break; + } + + typeInterface = null; + } + } + + pluginAssembly = null; + return assetPlugin; + } + + public void setupDB(AssetConfig config) + { + try + { + m_assetProvider = LoadDatabasePlugin(config.DatabaseProvider); + if (m_assetProvider == null) + { + m_log.Error("[ASSET]: Failed to load a database plugin, server halting"); + Environment.Exit(-1); + } + } + catch (Exception e) + { + m_log.Warn("[ASSET]: setupDB() - Exception occured"); + m_log.Warn("[ASSET]: " + e.ToString()); + } + } + + public void LoadDefaultAssets() + { + assetLoader.ForEachDefaultXmlAsset(StoreAsset); + } + + protected void StoreAsset(AssetBase asset) + { + m_assetProvider.CreateAsset(asset); + } + + public override void RunCmd(string cmd, string[] cmdparams) + { + base.RunCmd(cmd, cmdparams); + + switch (cmd) + { + case "help": + m_console.Notice( + @"shutdown - shutdown this asset server (USE CAUTION!) + stats - statistical information for this server"); + + break; + + case "stats": + m_console.Notice("STATS", Environment.NewLine + StatsManager.AssetStats.Report()); + break; + + case "shutdown": + m_console.Close(); + Environment.Exit(0); + break; + } + } + } +} diff --git a/trunk/OpenSim/Grid/AssetServer/Properties/AssemblyInfo.cs b/trunk/OpenSim/Grid/AssetServer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..7c659ddbae --- /dev/null +++ b/trunk/OpenSim/Grid/AssetServer/Properties/AssemblyInfo.cs @@ -0,0 +1,63 @@ +/* +* 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("OGS-AssetServer")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OGS-AssetServer")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("b541b244-3d1d-4625-9003-bc2a3a6a39a4")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Grid/AssetServer/RestService.cs b/trunk/OpenSim/Grid/AssetServer/RestService.cs new file mode 100644 index 0000000000..7e6e84c19b --- /dev/null +++ b/trunk/OpenSim/Grid/AssetServer/RestService.cs @@ -0,0 +1,155 @@ +/* +* 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; +using System.IO; +using System.Text; +using System.Xml; +using System.Xml.Serialization; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Statistics; + +namespace OpenSim.Grid.AssetServer +{ + public class GetAssetStreamHandler : BaseStreamHandler + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private OpenAsset_Main m_assetManager; + private IAssetProvider m_assetProvider; + + /// + /// Constructor. + /// + /// + /// + public GetAssetStreamHandler(OpenAsset_Main assetManager, IAssetProvider assetProvider) + : base("GET", "/assets") + { + m_log.Info("[REST]: In Get Request"); + m_assetManager = assetManager; + m_assetProvider = assetProvider; + } + + public override byte[] Handle(string path, Stream request) + { + string param = GetParam(path); + byte[] result = new byte[] {}; + try + { + string[] p = param.Split(new char[] {'/', '?', '&'}, StringSplitOptions.RemoveEmptyEntries); + + if (p.Length > 0) + { + LLUUID assetID = null; + + if (!LLUUID.TryParse(p[0], out assetID)) + { + m_log.InfoFormat( + "[REST]: GET:/asset ignoring request with malformed UUID {0}", p[0]); + return result; + } + + if (StatsManager.AssetStats != null) + StatsManager.AssetStats.AddRequest(); + + AssetBase asset = m_assetProvider.FetchAsset(assetID); + if (asset != null) + { + XmlSerializer xs = new XmlSerializer(typeof (AssetBase)); + MemoryStream ms = new MemoryStream(); + XmlTextWriter xw = new XmlTextWriter(ms, Encoding.UTF8); + xw.Formatting = Formatting.Indented; + xs.Serialize(xw, asset); + xw.Flush(); + + ms.Seek(0, SeekOrigin.Begin); + //StreamReader sr = new StreamReader(ms); + + result = ms.GetBuffer(); + + m_log.InfoFormat( + "[REST]: GET:/asset found {0} with name {1}, size {2} bytes", + assetID, asset.Name, result.Length); + + Array.Resize(ref result, (int) ms.Length); + } + else + { + if (StatsManager.AssetStats != null) + StatsManager.AssetStats.AddNotFoundRequest(); + + m_log.InfoFormat("[REST]: GET:/asset failed to find {0}", assetID); + } + } + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + return result; + } + } + + public class PostAssetStreamHandler : BaseStreamHandler + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private OpenAsset_Main m_assetManager; + private IAssetProvider m_assetProvider; + + public override byte[] Handle(string path, Stream request) + { + string param = GetParam(path); + + LLUUID assetId; + if (param.Length > 0) + LLUUID.TryParse(param, out assetId); + byte[] txBuffer = new byte[4096]; + + XmlSerializer xs = new XmlSerializer(typeof (AssetBase)); + AssetBase asset = (AssetBase) xs.Deserialize(request); + + m_log.InfoFormat("[REST]: StoreAndCommitAsset {0}", asset.FullID); + m_assetProvider.CreateAsset(asset); + m_assetProvider.CommitAssets(); + + return new byte[] {}; + } + + public PostAssetStreamHandler(OpenAsset_Main assetManager, IAssetProvider assetProvider) + : base("POST", "/assets") + { + m_assetManager = assetManager; + m_assetProvider = assetProvider; + } + } +} diff --git a/trunk/OpenSim/Grid/GridServer.Config/AssemblyInfo.cs b/trunk/OpenSim/Grid/GridServer.Config/AssemblyInfo.cs new file mode 100644 index 0000000000..af40744bb5 --- /dev/null +++ b/trunk/OpenSim/Grid/GridServer.Config/AssemblyInfo.cs @@ -0,0 +1,56 @@ +/* +* 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; +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly: AssemblyTitle("GridConfig")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("GridConfig")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly: AssemblyVersion("1.0.*")] diff --git a/trunk/OpenSim/Grid/GridServer.Config/DbGridConfig.cs b/trunk/OpenSim/Grid/GridServer.Config/DbGridConfig.cs new file mode 100644 index 0000000000..5dde43dfe3 --- /dev/null +++ b/trunk/OpenSim/Grid/GridServer.Config/DbGridConfig.cs @@ -0,0 +1,172 @@ +/* +* 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; +using Db4objects.Db4o; +using OpenSim.Framework.Configuration; +using OpenSim.Framework.Console; +using OpenSim.Framework.Interfaces; + +namespace OpenGrid.Config.GridConfigDb4o +{ + /// + /// A grid configuration interface for returning the DB4o Config Provider + /// + public class Db40ConfigPlugin: IGridConfig + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Loads and returns a configuration objeect + /// + /// A grid configuration object + public GridConfig GetConfigObject() + { + m_log.Info("[DBGRIDCONFIG]: Loading Db40Config dll"); + return new DbGridConfig(); + } + } + + /// + /// A DB4o based Gridserver configuration object + /// + public class DbGridConfig : GridConfig + { + /// + /// The DB4o Database + /// + private IObjectContainer db; + + /// + /// User configuration for the Grid Config interfaces + /// + public void LoadDefaults() + { + MainConsole.Instance.Info("DbGridConfig.cs:LoadDefaults() - Please press enter to retain default or enter new settings"); + + // About the grid options + this.GridOwner = MainConsole.Instance.CmdPrompt("Grid owner", "OGS development team"); + + // Asset Options + this.DefaultAssetServer = MainConsole.Instance.CmdPrompt("Default asset server","http://127.0.0.1:" + AssetConfig.DefaultHttpPort.ToString() + "/"); + this.AssetSendKey = MainConsole.Instance.CmdPrompt("Key to send to asset server","null"); + this.AssetRecvKey = MainConsole.Instance.CmdPrompt("Key to expect from asset server","null"); + + // User Server Options + this.DefaultUserServer = MainConsole.Instance.CmdPrompt("Default user server","http://127.0.0.1:" + UserConfig.DefaultHttpPort.ToString() + "/"); + this.UserSendKey = MainConsole.Instance.CmdPrompt("Key to send to user server","null"); + this.UserRecvKey = MainConsole.Instance.CmdPrompt("Key to expect from user server","null"); + + // Region Server Options + this.SimSendKey = MainConsole.Instance.CmdPrompt("Key to send to sims","null"); + this.SimRecvKey = MainConsole.Instance.CmdPrompt("Key to expect from sims","null"); + } + + /// + /// Initialises a new configuration object + /// + public override void InitConfig() + { + try + { + // Perform Db4o initialisation + db = Db4oFactory.OpenFile("opengrid.yap"); + + // Locate the grid configuration object + IObjectSet result = db.Get(typeof(DbGridConfig)); + // Found? + if (result.Count==1) + { + m_log.Info("[DBGRIDCONFIG]: Found a GridConfig object in the local database, loading"); + foreach (DbGridConfig cfg in result) + { + // Import each setting into this class + // Grid Settings + this.GridOwner=cfg.GridOwner; + // Asset Settings + this.DefaultAssetServer=cfg.DefaultAssetServer; + this.AssetSendKey=cfg.AssetSendKey; + this.AssetRecvKey=cfg.AssetRecvKey; + // User Settings + this.DefaultUserServer=cfg.DefaultUserServer; + this.UserSendKey=cfg.UserSendKey; + this.UserRecvKey=cfg.UserRecvKey; + // Region Settings + this.SimSendKey=cfg.SimSendKey; + this.SimRecvKey=cfg.SimRecvKey; + } + // Create a new configuration object from this class + } + else + { + m_log.Info("[DBGRIDCONFIG]: Could not find object in database, loading precompiled defaults"); + + // Load default settings into this class + LoadDefaults(); + + // Saves to the database file... + m_log.Info("[DBGRIDCONFIG]: Writing out default settings to local database"); + db.Set(this); + + // Closes file locks + db.Close(); + } + } + catch(Exception e) + { + m_log.Warn("DbGridConfig.cs:InitConfig() - Exception occured"); + m_log.Warn(e.ToString()); + } + + // Grid Settings + m_log.Info("[DBGRIDCONFIG]: Grid settings loaded:"); + m_log.Info("[DBGRIDCONFIG]: Grid owner: " + this.GridOwner); + + // Asset Settings + m_log.Info("[DBGRIDCONFIG]: Default asset server: " + this.DefaultAssetServer); + m_log.Info("[DBGRIDCONFIG]: Key to send to asset server: " + this.AssetSendKey); + m_log.Info("[DBGRIDCONFIG]: Key to expect from asset server: " + this.AssetRecvKey); + + // User Settings + m_log.Info("[DBGRIDCONFIG]: Default user server: " + this.DefaultUserServer); + m_log.Info("[DBGRIDCONFIG]: Key to send to user server: " + this.UserSendKey); + m_log.Info("[DBGRIDCONFIG]: Key to expect from user server: " + this.UserRecvKey); + + // Region Settings + m_log.Info("[DBGRIDCONFIG]: Key to send to sims: " + this.SimSendKey); + m_log.Info("[DBGRIDCONFIG]: Key to expect from sims: " + this.SimRecvKey); + } + + /// + /// Closes down the database and releases filesystem locks + /// + public void Shutdown() + { + db.Close(); + } + } +} diff --git a/trunk/OpenSim/Grid/GridServer/GridManager.cs b/trunk/OpenSim/Grid/GridServer/GridManager.cs new file mode 100644 index 0000000000..5cd83ea4f9 --- /dev/null +++ b/trunk/OpenSim/Grid/GridServer/GridManager.cs @@ -0,0 +1,903 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Xml; +using libsecondlife; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Data; +using OpenSim.Framework.Servers; + +namespace OpenSim.Grid.GridServer +{ + internal class GridManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private Dictionary _plugins = new Dictionary(); + private Dictionary _logplugins = new Dictionary(); + + // This is here so that the grid server can hand out MessageServer settings to regions on registration + private List _MessageServers = new List(); + + public GridConfig config; + + /// + /// Adds a new grid server plugin - grid servers will be requested in the order they were loaded. + /// + /// The filename to the grid server plugin DLL + public void AddPlugin(string FileName) + { + m_log.Info("[DATA]: Attempting to load " + FileName); + Assembly pluginAssembly = Assembly.LoadFrom(FileName); + + m_log.Info("[DATA]: Found " + pluginAssembly.GetTypes().Length + " interfaces."); + foreach (Type pluginType in pluginAssembly.GetTypes()) + { + if (!pluginType.IsAbstract) + { + // Regions go here + Type typeInterface = pluginType.GetInterface("IGridData", true); + + if (typeInterface != null) + { + IGridData plug = + (IGridData) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + plug.Initialise(); + _plugins.Add(plug.getName(), plug); + m_log.Info("[DATA]: Added IGridData Interface"); + } + + typeInterface = null; + + // Logs go here + typeInterface = pluginType.GetInterface("ILogData", true); + + if (typeInterface != null) + { + ILogData plug = + (ILogData) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + plug.Initialise(); + _logplugins.Add(plug.getName(), plug); + m_log.Info("[DATA]: Added ILogData Interface"); + } + + typeInterface = null; + } + } + + pluginAssembly = null; + } + + /// + /// Logs a piece of information to the database + /// + /// What you were operating on (in grid server, this will likely be the region UUIDs) + /// Which method is being called? + /// What arguments are being passed? + /// How high priority is this? 1 = Max, 6 = Verbose + /// The message to log + private void logToDB(string target, string method, string args, int priority, string message) + { + foreach (KeyValuePair kvp in _logplugins) + { + try + { + kvp.Value.saveLog("Gridserver", target, method, args, priority, message); + } + catch (Exception) + { + m_log.Warn("[storage]: Unable to write log via " + kvp.Key); + } + } + } + + /// + /// Returns a region by argument + /// + /// A UUID key of the region to return + /// A SimProfileData for the region + public RegionProfileData getRegion(LLUUID uuid) + { + foreach (KeyValuePair kvp in _plugins) + { + try + { + return kvp.Value.GetProfileByLLUUID(uuid); + } + catch (Exception e) + { + m_log.Warn("[storage]: getRegion - " + e.Message); + } + } + return null; + } + + /// + /// Returns a region by argument + /// + /// A regionHandle of the region to return + /// A SimProfileData for the region + public RegionProfileData getRegion(ulong handle) + { + foreach (KeyValuePair kvp in _plugins) + { + try + { + return kvp.Value.GetProfileByHandle(handle); + } + catch + { + m_log.Warn("[storage]: Unable to find region " + handle.ToString() + " via " + kvp.Key); + } + } + return null; + } + + public Dictionary getRegions(uint xmin, uint ymin, uint xmax, uint ymax) + { + Dictionary regions = new Dictionary(); + + foreach (KeyValuePair kvp in _plugins) + { + try + { + RegionProfileData[] neighbours = kvp.Value.GetProfilesInRange(xmin, ymin, xmax, ymax); + foreach (RegionProfileData neighbour in neighbours) + { + regions[neighbour.regionHandle] = neighbour; + } + } + catch + { + m_log.Warn("[storage]: Unable to query regionblock via " + kvp.Key); + } + } + + return regions; + } + + + /// + /// Returns a XML String containing a list of the neighbouring regions + /// + /// The regionhandle for the center sim + /// An XML string containing neighbour entities + public string GetXMLNeighbours(ulong reqhandle) + { + string response = String.Empty; + RegionProfileData central_region = getRegion(reqhandle); + RegionProfileData neighbour; + for (int x = -1; x < 2; x++) + for (int y = -1; y < 2; y++) + { + if ( + getRegion( + Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), + (uint)(central_region.regionLocY + y) * Constants.RegionSize)) != null) + { + neighbour = + getRegion( + Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), + (uint)(central_region.regionLocY + y) * Constants.RegionSize)); + response += ""; + response += "" + neighbour.serverIP + ""; + response += "" + neighbour.serverPort.ToString() + ""; + response += "" + neighbour.regionLocX.ToString() + ""; + response += "" + neighbour.regionLocY.ToString() + ""; + response += "" + neighbour.regionHandle.ToString() + ""; + response += ""; + } + } + return response; + } + + /// + /// Performed when a region connects to the grid server initially. + /// + /// The XMLRPC Request + /// Startup parameters + public XmlRpcResponse XmlRpcSimulatorLoginMethod(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + response.Value = responseData; + + RegionProfileData TheSim = null; + RegionProfileData OldSim = null; + + Hashtable requestData = (Hashtable)request.Params[0]; + string myword; + if (requestData.ContainsKey("UUID")) + { + TheSim = getRegion(new LLUUID((string)requestData["UUID"])); + + // logToDB((new LLUUID((string)requestData["UUID"])).ToString(),"XmlRpcSimulatorLoginMethod",String.Empty, 5,"Region attempting login with UUID."); + } + else + { + m_log.Info("[GRID]: Region connected without a UUID, ignoring."); + responseData["error"] = "No UUID passed to grid server - unable to connect you"; + return response; + } + + if (TheSim == null) // Shouldnt this be in the REST Simulator Set method? + { + m_log.Info("[GRID]: New region connecting"); + myword = "creation"; + } + else + { + myword = "connection"; + } + + TheSim = new RegionProfileData(); + + TheSim.regionRecvKey = String.Empty; + TheSim.regionSendKey = String.Empty; + TheSim.regionSecret = config.SimRecvKey; + TheSim.regionDataURI = String.Empty; + TheSim.regionAssetURI = config.DefaultAssetServer; + TheSim.regionAssetRecvKey = config.AssetRecvKey; + TheSim.regionAssetSendKey = config.AssetSendKey; + TheSim.regionUserURI = config.DefaultUserServer; + TheSim.regionUserSendKey = config.UserSendKey; + TheSim.regionUserRecvKey = config.UserRecvKey; + + TheSim.serverIP = (string)requestData["sim_ip"]; + TheSim.serverPort = Convert.ToUInt32((string)requestData["sim_port"]); + TheSim.httpPort = Convert.ToUInt32((string)requestData["http_port"]); + TheSim.remotingPort = Convert.ToUInt32((string)requestData["remoting_port"]); + TheSim.regionLocX = Convert.ToUInt32((string)requestData["region_locx"]); + TheSim.regionLocY = Convert.ToUInt32((string)requestData["region_locy"]); + TheSim.regionLocZ = 0; + TheSim.regionMapTextureID = new LLUUID((string)requestData["map-image-id"]); + + // Added by daTwitch + // part of an initial brutish effort to provide accurate information (as per the xml region spec) + // wrt the ownership of a given region + // the (very bad) assumption is that this value is being read and handled inconsistently or + // not at all. Current strategy is to put the code in place to support the validity of this information + // and to roll forward debugging any issues from that point + // + // this particular section of the mod attempts to receive a value from the region's xml file by way of + // OSG1GridServices for the region's owner + // + TheSim.owner_uuid = (string)requestData["master_avatar_uuid"]; + // end of daTwitch's mods to this file + + try + { + TheSim.regionRecvKey = (string)requestData["recvkey"]; + TheSim.regionSendKey = (string)requestData["authkey"]; + } + catch (KeyNotFoundException) { } + + TheSim.regionHandle = Helpers.UIntsToLong((TheSim.regionLocX * Constants.RegionSize), (TheSim.regionLocY * Constants.RegionSize)); + TheSim.serverURI = "http://" + TheSim.serverIP + ":" + TheSim.serverPort + "/"; + + TheSim.httpServerURI = "http://" + TheSim.serverIP + ":" + TheSim.httpPort + "/"; + + TheSim.regionName = (string)requestData["sim_name"]; + TheSim.UUID = new LLUUID((string)requestData["UUID"]); + + //make sure there is not an existing region at this location + OldSim = getRegion(TheSim.regionHandle); + if (OldSim == null || OldSim.UUID == TheSim.UUID) + { + bool brandNew = ( OldSim == null && TheSim.regionRecvKey == config.SimSendKey && + TheSim.regionSendKey == config.SimRecvKey); + + bool overwritingOldOne = ( OldSim != null && OldSim.regionRecvKey == TheSim.regionRecvKey && + OldSim.regionSendKey == TheSim.regionSendKey ); + + if (brandNew) + { + m_log.Info("[GRID]: Adding region " + TheSim.regionLocX + " , " + TheSim.regionLocY + " , " + + TheSim.serverURI); + } + + if (overwritingOldOne) + { + m_log.Info("[GRID]: Overwriting region " + OldSim.regionLocX + " , " + OldSim.regionLocY + " , " + + OldSim.serverURI + " with " + TheSim.regionLocX + " , " + TheSim.regionLocY + " , " + + TheSim.serverURI); + } + + if (brandNew || + overwritingOldOne) + { + + foreach (KeyValuePair kvp in _plugins) + { + try + { + DataResponse insertResponse = kvp.Value.AddProfile(TheSim); + switch (insertResponse) + { + case DataResponse.RESPONSE_OK: + m_log.Info("[grid]: New sim " + myword + " successful: " + TheSim.regionName); + break; + case DataResponse.RESPONSE_ERROR: + m_log.Warn("[storage]: New sim creation failed (Error): " + TheSim.regionName); + break; + case DataResponse.RESPONSE_INVALIDCREDENTIALS: + m_log.Warn("[storage]: " + + "New sim creation failed (Invalid Credentials): " + TheSim.regionName); + break; + case DataResponse.RESPONSE_AUTHREQUIRED: + m_log.Warn("[storage]: " + + "New sim creation failed (Authentication Required): " + + TheSim.regionName); + break; + } + } + catch (Exception e) + { + m_log.Warn("[storage]: " + + "Unable to add region " + TheSim.UUID.ToString() + " via " + kvp.Key); + m_log.Warn("[storage]: " + e.ToString()); + } + + + if (getRegion(TheSim.regionHandle) == null) + { + responseData["error"] = "Unable to add new region"; + return response; + } + } + + + + ArrayList SimNeighboursData = new ArrayList(); + + RegionProfileData neighbour; + Hashtable NeighbourBlock; + + bool fastMode = false; // Only compatible with MySQL right now + + if (fastMode) + { + Dictionary neighbours = + getRegions(TheSim.regionLocX - 1, TheSim.regionLocY - 1, TheSim.regionLocX + 1, + TheSim.regionLocY + 1); + + foreach (KeyValuePair aSim in neighbours) + { + NeighbourBlock = new Hashtable(); + NeighbourBlock["sim_ip"] = Util.GetHostFromDNS(aSim.Value.serverIP.ToString()).ToString(); + NeighbourBlock["sim_port"] = aSim.Value.serverPort.ToString(); + NeighbourBlock["region_locx"] = aSim.Value.regionLocX.ToString(); + NeighbourBlock["region_locy"] = aSim.Value.regionLocY.ToString(); + NeighbourBlock["UUID"] = aSim.Value.UUID.ToString(); + NeighbourBlock["regionHandle"] = aSim.Value.regionHandle.ToString(); + + if (aSim.Value.UUID != TheSim.UUID) + { + SimNeighboursData.Add(NeighbourBlock); + } + } + } + else + { + for (int x = -1; x < 2; x++) + for (int y = -1; y < 2; y++) + { + if ( + getRegion( + Helpers.UIntsToLong((uint)((TheSim.regionLocX + x) * Constants.RegionSize), + (uint)(TheSim.regionLocY + y) * Constants.RegionSize)) != null) + { + neighbour = + getRegion( + Helpers.UIntsToLong((uint)((TheSim.regionLocX + x) * Constants.RegionSize), + (uint)(TheSim.regionLocY + y) * Constants.RegionSize)); + + NeighbourBlock = new Hashtable(); + NeighbourBlock["sim_ip"] = Util.GetHostFromDNS(neighbour.serverIP).ToString(); + NeighbourBlock["sim_port"] = neighbour.serverPort.ToString(); + NeighbourBlock["region_locx"] = neighbour.regionLocX.ToString(); + NeighbourBlock["region_locy"] = neighbour.regionLocY.ToString(); + NeighbourBlock["UUID"] = neighbour.UUID.ToString(); + NeighbourBlock["regionHandle"] = neighbour.regionHandle.ToString(); + + if (neighbour.UUID != TheSim.UUID) SimNeighboursData.Add(NeighbourBlock); + } + } + } + + responseData["UUID"] = TheSim.UUID.ToString(); + responseData["region_locx"] = TheSim.regionLocX.ToString(); + responseData["region_locy"] = TheSim.regionLocY.ToString(); + responseData["regionname"] = TheSim.regionName; + responseData["estate_id"] = "1"; + responseData["neighbours"] = SimNeighboursData; + + responseData["sim_ip"] = TheSim.serverIP; + responseData["sim_port"] = TheSim.serverPort.ToString(); + responseData["asset_url"] = TheSim.regionAssetURI; + responseData["asset_sendkey"] = TheSim.regionAssetSendKey; + responseData["asset_recvkey"] = TheSim.regionAssetRecvKey; + responseData["user_url"] = TheSim.regionUserURI; + responseData["user_sendkey"] = TheSim.regionUserSendKey; + responseData["user_recvkey"] = TheSim.regionUserRecvKey; + responseData["authkey"] = TheSim.regionSecret; + + // New! If set, use as URL to local sim storage (ie http://remotehost/region.yap) + responseData["data_uri"] = TheSim.regionDataURI; + + responseData["allow_forceful_banlines"] = config.AllowForcefulBanlines; + + // Instead of sending a multitude of message servers to the registering sim + // we should probably be sending a single one and parhaps it's backup + // that has responsibility over routing it's messages. + + // The Sim won't be contacting us again about any of the message server stuff during it's time up. + + responseData["messageserver_count"] = _MessageServers.Count; + + for (int i = 0; i < _MessageServers.Count; i++) + { + responseData["messageserver_uri" + i] = _MessageServers[i].URI; + responseData["messageserver_sendkey" + i] = _MessageServers[i].sendkey; + responseData["messageserver_recvkey" + i] = _MessageServers[i].recvkey; + } + return response; + } + else + { + if (OldSim == null) + { + m_log.Warn("[grid]: Authentication failed when trying to add new region " + TheSim.regionName + + " at location " + TheSim.regionLocX + + " " + TheSim.regionLocY + " with TheSim.regionRecvKey " + TheSim.regionRecvKey + "(" + config.SimSendKey + ") and TheSim.regionRecvKey " + TheSim.regionSendKey + "(" + config.SimRecvKey + ") "); + } + else + { + m_log.Warn("[grid]: Authentication failed when trying to add new region " + TheSim.regionName + + " at location " + TheSim.regionLocX + + " " + TheSim.regionLocY + " currently occupied by " + OldSim.regionName); + } + + responseData["error"] = + "The key required to connect to your region did not match. Please check your send and recieve keys."; + return response; + } + } + else + { + m_log.Warn("[grid]: Failed to add new region " + TheSim.regionName + " at location " + TheSim.regionLocX + " " + TheSim.regionLocY + " currently occupied by " + OldSim.regionName); + responseData["error"] = "Another region already exists at that location. Try another"; + return response; + } + + } + + public XmlRpcResponse XmlRpcSimulatorDataRequestMethod(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable) request.Params[0]; + Hashtable responseData = new Hashtable(); + RegionProfileData simData = null; + if (requestData.ContainsKey("region_UUID")) + { + simData = getRegion(new LLUUID((string) requestData["region_UUID"])); + } + else if (requestData.ContainsKey("region_handle")) + { + //CFK: The if/else below this makes this message redundant. + //CFK: Console.WriteLine("requesting data for region " + (string) requestData["region_handle"]); + simData = getRegion(Convert.ToUInt64((string) requestData["region_handle"])); + } + + if (simData == null) + { + //Sim does not exist + Console.WriteLine("region not found"); + responseData["error"] = "Sim does not exist"; + } + else + { + m_log.Info("[DATA]: found " + (string) simData.regionName + " regionHandle = " + + (string) requestData["region_handle"]); + responseData["sim_ip"] = Util.GetHostFromDNS(simData.serverIP).ToString(); + responseData["sim_port"] = simData.serverPort.ToString(); + responseData["http_port"] = simData.httpPort.ToString(); + responseData["remoting_port"] = simData.remotingPort.ToString(); + responseData["region_locx"] = simData.regionLocX.ToString(); + responseData["region_locy"] = simData.regionLocY.ToString(); + responseData["region_UUID"] = simData.UUID.UUID.ToString(); + responseData["region_name"] = simData.regionName; + responseData["regionHandle"] = simData.regionHandle.ToString(); + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = responseData; + return response; + } + + public XmlRpcResponse XmlRpcMapBlockMethod(XmlRpcRequest request) + { + int xmin = 980, ymin = 980, xmax = 1020, ymax = 1020; + + Hashtable requestData = (Hashtable) request.Params[0]; + if (requestData.ContainsKey("xmin")) + { + xmin = (Int32) requestData["xmin"]; + } + if (requestData.ContainsKey("ymin")) + { + ymin = (Int32) requestData["ymin"]; + } + if (requestData.ContainsKey("xmax")) + { + xmax = (Int32) requestData["xmax"]; + } + if (requestData.ContainsKey("ymax")) + { + ymax = (Int32) requestData["ymax"]; + } + //CFK: The second log is more meaningful and either standard or fast generally occurs. + //CFK: m_log.Info("[MAP]: World map request for range (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); + + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + response.Value = responseData; + IList simProfileList = new ArrayList(); + + bool fastMode = false; // MySQL Only + fastMode = (config.DatabaseProvider == "OpenSim.Framework.Data.MySQL.dll"); + + if (fastMode) + { + Dictionary neighbours = + getRegions((uint) xmin, (uint) ymin, (uint) xmax, (uint) ymax); + + foreach (KeyValuePair aSim in neighbours) + { + Hashtable simProfileBlock = new Hashtable(); + simProfileBlock["x"] = aSim.Value.regionLocX.ToString(); + simProfileBlock["y"] = aSim.Value.regionLocY.ToString(); + Console.WriteLine("send neighbour info for " + aSim.Value.regionLocX.ToString() + " , " + + aSim.Value.regionLocY.ToString()); + simProfileBlock["name"] = aSim.Value.regionName; + simProfileBlock["access"] = 21; + simProfileBlock["region-flags"] = 512; + simProfileBlock["water-height"] = 0; + simProfileBlock["agents"] = 1; + simProfileBlock["map-image-id"] = aSim.Value.regionMapTextureID.ToString(); + + // For Sugilite compatibility + simProfileBlock["regionhandle"] = aSim.Value.regionHandle.ToString(); + simProfileBlock["sim_ip"] = aSim.Value.serverIP.ToString(); + simProfileBlock["sim_port"] = aSim.Value.serverPort.ToString(); + simProfileBlock["sim_uri"] = aSim.Value.serverURI.ToString(); + simProfileBlock["uuid"] = aSim.Value.UUID.ToString(); + simProfileBlock["remoting_port"] = aSim.Value.remotingPort; + + simProfileList.Add(simProfileBlock); + } + m_log.Info("[MAP]: Fast map " + simProfileList.Count.ToString() + + " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); + } + else + { + RegionProfileData simProfile; + for (int x = xmin; x < xmax + 1; x++) + { + for (int y = ymin; y < ymax + 1; y++) + { + ulong regHandle = Helpers.UIntsToLong((uint)(x * Constants.RegionSize), (uint)(y * Constants.RegionSize)); + simProfile = getRegion(regHandle); + if (simProfile != null) + { + Hashtable simProfileBlock = new Hashtable(); + simProfileBlock["x"] = x; + simProfileBlock["y"] = y; + simProfileBlock["name"] = simProfile.regionName; + simProfileBlock["access"] = 0; + simProfileBlock["region-flags"] = 0; + simProfileBlock["water-height"] = 20; + simProfileBlock["agents"] = 1; + simProfileBlock["map-image-id"] = simProfile.regionMapTextureID.ToString(); + + // For Sugilite compatibility + simProfileBlock["regionhandle"] = simProfile.regionHandle.ToString(); + simProfileBlock["sim_ip"] = simProfile.serverIP.ToString(); + simProfileBlock["sim_port"] = simProfile.serverPort.ToString(); + simProfileBlock["sim_uri"] = simProfile.serverURI.ToString(); + simProfileBlock["uuid"] = simProfile.UUID.ToString(); + + simProfileList.Add(simProfileBlock); + } + } + } + m_log.Info("[MAP]: Std map " + simProfileList.Count.ToString() + + " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); + } + + responseData["sim-profiles"] = simProfileList; + + return response; + } + + + /// + /// Performs a REST Get Operation + /// + /// + /// + /// + /// + public string RestGetRegionMethod(string request, string path, string param) + { + return RestGetSimMethod(String.Empty, "/sims/", param); + } + + /// + /// Performs a REST Set Operation + /// + /// + /// + /// + /// + public string RestSetRegionMethod(string request, string path, string param) + { + return RestSetSimMethod(String.Empty, "/sims/", param); + } + + /// + /// Returns information about a sim via a REST Request + /// + /// + /// + /// A string representing the sim's UUID + /// Information about the sim in XML + public string RestGetSimMethod(string request, string path, string param) + { + string respstring = String.Empty; + + RegionProfileData TheSim; + + LLUUID UUID; + if (LLUUID.TryParse(param, out UUID)) + { + TheSim = getRegion(UUID); + + if (!(TheSim == null)) + { + respstring = ""; + respstring += "" + TheSim.regionSendKey + ""; + respstring += ""; + respstring += "" + TheSim.UUID.ToString() + ""; + respstring += "" + TheSim.regionName + ""; + respstring += "" + Util.GetHostFromDNS(TheSim.serverIP).ToString() + ""; + respstring += "" + TheSim.serverPort.ToString() + ""; + respstring += "" + TheSim.regionLocX.ToString() + ""; + respstring += "" + TheSim.regionLocY.ToString() + ""; + respstring += "1"; + respstring += ""; + respstring += ""; + } + } + else + { + respstring = ""; + respstring += "Param must be a UUID"; + respstring += ""; + } + + return respstring; + } + + /// + /// Creates or updates a sim via a REST Method Request + /// BROKEN with SQL Update + /// + /// + /// + /// + /// "OK" or an error + public string RestSetSimMethod(string request, string path, string param) + { + Console.WriteLine("Processing region update via REST method"); + RegionProfileData TheSim; + TheSim = getRegion(new LLUUID(param)); + if ((TheSim) == null) + { + TheSim = new RegionProfileData(); + LLUUID UUID = new LLUUID(param); + TheSim.UUID = UUID; + TheSim.regionRecvKey = config.SimRecvKey; + } + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(request); + XmlNode rootnode = doc.FirstChild; + XmlNode authkeynode = rootnode.ChildNodes[0]; + if (authkeynode.Name != "authkey") + { + return "ERROR! bad XML - expected authkey tag"; + } + + XmlNode simnode = rootnode.ChildNodes[1]; + if (simnode.Name != "sim") + { + return "ERROR! bad XML - expected sim tag"; + } + + //TheSim.regionSendKey = Cfg; + TheSim.regionRecvKey = config.SimRecvKey; + TheSim.regionSendKey = config.SimSendKey; + TheSim.regionSecret = config.SimRecvKey; + TheSim.regionDataURI = String.Empty; + TheSim.regionAssetURI = config.DefaultAssetServer; + TheSim.regionAssetRecvKey = config.AssetRecvKey; + TheSim.regionAssetSendKey = config.AssetSendKey; + TheSim.regionUserURI = config.DefaultUserServer; + TheSim.regionUserSendKey = config.UserSendKey; + TheSim.regionUserRecvKey = config.UserRecvKey; + + + for (int i = 0; i < simnode.ChildNodes.Count; i++) + { + switch (simnode.ChildNodes[i].Name) + { + case "regionname": + TheSim.regionName = simnode.ChildNodes[i].InnerText; + break; + + case "sim_ip": + TheSim.serverIP = simnode.ChildNodes[i].InnerText; + break; + + case "sim_port": + TheSim.serverPort = Convert.ToUInt32(simnode.ChildNodes[i].InnerText); + break; + + case "region_locx": + TheSim.regionLocX = Convert.ToUInt32((string) simnode.ChildNodes[i].InnerText); + TheSim.regionHandle = Helpers.UIntsToLong((TheSim.regionLocX * Constants.RegionSize), (TheSim.regionLocY * Constants.RegionSize)); + break; + + case "region_locy": + TheSim.regionLocY = Convert.ToUInt32((string) simnode.ChildNodes[i].InnerText); + TheSim.regionHandle = Helpers.UIntsToLong((TheSim.regionLocX * Constants.RegionSize), (TheSim.regionLocY * Constants.RegionSize)); + break; + } + } + + TheSim.serverURI = "http://" + TheSim.serverIP + ":" + TheSim.serverPort + "/"; + + bool requirePublic = false; + bool requireValid = true; + + if (requirePublic && + (TheSim.serverIP.StartsWith("172.16") || TheSim.serverIP.StartsWith("192.168") || + TheSim.serverIP.StartsWith("10.") || TheSim.serverIP.StartsWith("0.") || + TheSim.serverIP.StartsWith("255."))) + { + return "ERROR! Servers must register with public addresses."; + } + + if (requireValid && (TheSim.serverIP.StartsWith("0.") || TheSim.serverIP.StartsWith("255."))) + { + return "ERROR! 0.*.*.* / 255.*.*.* Addresses are invalid, please check your server config and try again"; + } + + + try + { + m_log.Info("[DATA]: " + + "Updating / adding via " + _plugins.Count + " storage provider(s) registered."); + foreach (KeyValuePair kvp in _plugins) + { + try + { + //Check reservations + ReservationData reserveData = + kvp.Value.GetReservationAtPoint(TheSim.regionLocX, TheSim.regionLocY); + if ((reserveData != null && reserveData.gridRecvKey == TheSim.regionRecvKey) || + (reserveData == null && authkeynode.InnerText != TheSim.regionRecvKey)) + { + kvp.Value.AddProfile(TheSim); + m_log.Info("[grid]: New sim added to grid (" + TheSim.regionName + ")"); + logToDB(TheSim.UUID.ToString(), "RestSetSimMethod", String.Empty, 5, + "Region successfully updated and connected to grid."); + } + else + { + m_log.Warn("[grid]: " + + "Unable to update region (RestSetSimMethod): Incorrect reservation auth key."); + // Wanted: " + reserveData.gridRecvKey + ", Got: " + TheSim.regionRecvKey + "."); + return "Unable to update region (RestSetSimMethod): Incorrect auth key."; + } + } + catch (Exception e) + { + m_log.Warn("[GRID]: getRegionPlugin Handle " + kvp.Key + " unable to add new sim: " + + e.ToString()); + } + } + return "OK"; + } + catch (Exception e) + { + return "ERROR! Could not save to database! (" + e.ToString() + ")"; + } + } + public XmlRpcResponse XmlRPCRegisterMessageServer(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData = new Hashtable(); + + if (requestData.Contains("uri")) + { + string URI = (string)requestData["URI"]; + string sendkey = (string)requestData["sendkey"]; + string recvkey = (string)requestData["recvkey"]; + MessageServerInfo m = new MessageServerInfo(); + m.URI = URI; + m.sendkey = sendkey; + m.recvkey = recvkey; + if (!_MessageServers.Contains(m)) + _MessageServers.Add(m); + responseData["responsestring"] = "TRUE"; + response.Value = responseData; + } + return response; + } + public XmlRpcResponse XmlRPCDeRegisterMessageServer(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData = new Hashtable(); + + if (requestData.Contains("uri")) + { + string URI = (string)requestData["uri"]; + string sendkey = (string)requestData["sendkey"]; + string recvkey = (string)requestData["recvkey"]; + MessageServerInfo m = new MessageServerInfo(); + m.URI = URI; + m.sendkey = sendkey; + m.recvkey = recvkey; + if (_MessageServers.Contains(m)) + _MessageServers.Remove(m); + responseData["responsestring"] = "TRUE"; + response.Value = responseData; + } + return response; + } + } +} diff --git a/trunk/OpenSim/Grid/GridServer/Main.cs b/trunk/OpenSim/Grid/GridServer/Main.cs new file mode 100644 index 0000000000..ff4a888842 --- /dev/null +++ b/trunk/OpenSim/Grid/GridServer/Main.cs @@ -0,0 +1,220 @@ +/* +* 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; +using System.IO; +using System.Timers; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; + +namespace OpenSim.Grid.GridServer +{ + /// + /// + public class OpenGrid_Main : BaseOpenSimServer, conscmd_callback + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public GridConfig Cfg; + + public static OpenGrid_Main thegrid; + + public static bool setuponly; + + //public LLUUID highestUUID; + + // private SimProfileManager m_simProfileManager; + + private GridManager m_gridManager; + + [STAThread] + public static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + if (args.Length > 0) + { + if (args[0] == "-setuponly") setuponly = true; + } + m_log.Info("Starting...\n"); + + thegrid = new OpenGrid_Main(); + thegrid.Startup(); + + thegrid.Work(); + } + + private void Work() + { + m_console.Notice("Enter help for a list of commands\n"); + + while (true) + { + m_console.Prompt(); + } + } + + private OpenGrid_Main() + { + m_console = new ConsoleBase("OpenGrid", this); + MainConsole.Instance = m_console; + } + + public void managercallback(string cmd) + { + switch (cmd) + { + case "shutdown": + RunCmd("shutdown", new string[0]); + break; + } + } + + public void Startup() + { + Cfg = new GridConfig("GRID SERVER", (Path.Combine(Util.configDir(), "GridServer_Config.xml"))); + //Yeah srsly, that's it. + if (setuponly) Environment.Exit(0); + + m_log.Info("[GRID]: Connecting to Storage Server"); + m_gridManager = new GridManager(); + m_gridManager.AddPlugin(Cfg.DatabaseProvider); // Made of win + m_gridManager.config = Cfg; + + m_log.Info("[GRID]: Starting HTTP process"); + BaseHttpServer httpServer = new BaseHttpServer(Cfg.HttpPort); + //GridManagementAgent GridManagerAgent = new GridManagementAgent(httpServer, "gridserver", Cfg.SimSendKey, Cfg.SimRecvKey, managercallback); + + httpServer.AddXmlRPCHandler("simulator_login", m_gridManager.XmlRpcSimulatorLoginMethod); + httpServer.AddXmlRPCHandler("simulator_data_request", m_gridManager.XmlRpcSimulatorDataRequestMethod); + httpServer.AddXmlRPCHandler("map_block", m_gridManager.XmlRpcMapBlockMethod); + + // Message Server ---> Grid Server + httpServer.AddXmlRPCHandler("register_messageserver", m_gridManager.XmlRPCRegisterMessageServer); + httpServer.AddXmlRPCHandler("deregister_messageserver", m_gridManager.XmlRPCDeRegisterMessageServer); + + + httpServer.AddStreamHandler(new RestStreamHandler("GET", "/sims/", m_gridManager.RestGetSimMethod)); + httpServer.AddStreamHandler(new RestStreamHandler("POST", "/sims/", m_gridManager.RestSetSimMethod)); + + httpServer.AddStreamHandler(new RestStreamHandler("GET", "/regions/", m_gridManager.RestGetRegionMethod)); + httpServer.AddStreamHandler(new RestStreamHandler("POST", "/regions/", m_gridManager.RestSetRegionMethod)); + + //httpServer.AddRestHandler("GET", "/sims/", m_gridManager.RestGetSimMethod); + //httpServer.AddRestHandler("POST", "/sims/", m_gridManager.RestSetSimMethod); + //httpServer.AddRestHandler("GET", "/regions/", m_gridManager.RestGetRegionMethod); + //httpServer.AddRestHandler("POST", "/regions/", m_gridManager.RestSetRegionMethod); + + httpServer.Start(); + + m_log.Info("[GRID]: Starting sim status checker"); + + Timer simCheckTimer = new Timer(3600000*3); // 3 Hours between updates. + simCheckTimer.Elapsed += new ElapsedEventHandler(CheckSims); + simCheckTimer.Enabled = true; + } + + public void CheckSims(object sender, ElapsedEventArgs e) + { + /* + foreach (SimProfileBase sim in m_simProfileManager.SimProfiles.Values) + { + string SimResponse = String.Empty; + try + { + WebRequest CheckSim = WebRequest.Create("http://" + sim.sim_ip + ":" + sim.sim_port.ToString() + "/checkstatus/"); + CheckSim.Method = "GET"; + CheckSim.ContentType = "text/plaintext"; + CheckSim.ContentLength = 0; + + StreamWriter stOut = new StreamWriter(CheckSim.GetRequestStream(), System.Text.Encoding.ASCII); + stOut.Write(String.Empty); + stOut.Close(); + + StreamReader stIn = new StreamReader(CheckSim.GetResponse().GetResponseStream()); + SimResponse = stIn.ReadToEnd(); + stIn.Close(); + } + catch + { + } + + if (SimResponse == "OK") + { + m_simProfileManager.SimProfiles[sim.UUID].online = true; + } + else + { + m_simProfileManager.SimProfiles[sim.UUID].online = false; + } + } + */ + } + + public override void RunCmd(string cmd, string[] cmdparams) + { + base.RunCmd(cmd, cmdparams); + + switch (cmd) + { + case "help": + m_console.Notice("shutdown - shutdown the grid (USE CAUTION!)"); + break; + + case "shutdown": + m_console.Close(); + Environment.Exit(0); + break; + } + } + + /*private void ConfigDB(IGenericConfig configData) + { + try + { + string attri = String.Empty; + attri = configData.GetAttribute("DataBaseProvider"); + if (attri == String.Empty) + { + GridDll = "OpenSim.Framework.Data.DB4o.dll"; + configData.SetAttribute("DataBaseProvider", "OpenSim.Framework.Data.DB4o.dll"); + } + else + { + GridDll = attri; + } + configData.Commit(); + } + catch + { + + } + }*/ + } +} diff --git a/trunk/OpenSim/Grid/GridServer/Properties/AssemblyInfo.cs b/trunk/OpenSim/Grid/GridServer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..df06c90ef7 --- /dev/null +++ b/trunk/OpenSim/Grid/GridServer/Properties/AssemblyInfo.cs @@ -0,0 +1,63 @@ +/* +* 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("OGS-GridServer")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OGS-GridServer")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("b541b244-3d1d-4625-9003-bc2a3a6a39a4")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Grid/InventoryServer/GridInventoryService.cs b/trunk/OpenSim/Grid/InventoryServer/GridInventoryService.cs new file mode 100644 index 0000000000..a7194529c6 --- /dev/null +++ b/trunk/OpenSim/Grid/InventoryServer/GridInventoryService.cs @@ -0,0 +1,206 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Console; + +namespace OpenSim.Grid.InventoryServer +{ + public class GridInventoryService : InventoryServiceBase + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public override void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, + InventoryItemInfo itemCallBack) + { + } + + private bool TryGetUsersInventory(LLUUID userID, out List folderList, + out List itemsList) + { + List rootFolders = RequestFirstLevelFolders(userID); + List allItems = new List(); + List allFolders = new List(); + + if (rootFolders != null) + { + allFolders.InsertRange(0, rootFolders); + foreach (InventoryFolderBase subfolder in rootFolders) + { + List subFolders = GetAllFolders(subfolder.folderID); + if (subFolders != null) + { + allFolders.InsertRange(0, subFolders); + } + } + } + + foreach (InventoryFolderBase folder in allFolders) + { + List items = RequestFolderItems(folder.folderID); + if (items != null) + { + allItems.InsertRange(0, items); + } + } + + folderList = allFolders; + itemsList = allItems; + if (folderList != null) + { + return true; + } + else + { + return false; + } + } + + private List GetAllFolders(LLUUID folder) + { + List allFolders = new List(); + List folders = RequestSubFolders(folder); + if (folders != null) + { + allFolders.InsertRange(0, folders); + foreach (InventoryFolderBase subfolder in folders) + { + List subFolders = GetAllFolders(subfolder.folderID); + if (subFolders != null) + { + allFolders.InsertRange(0, subFolders); + } + } + } + return allFolders; + } + + + public InventoryCollection GetUserInventory(Guid rawUserID) + { + LLUUID userID = new LLUUID(rawUserID); + + // We get enough verbose messages later on for diagnostics + //m_log.Info("[INVENTORY]: Request for inventory for " + userID.ToString()); + + InventoryCollection invCollection = new InventoryCollection(); + List folders; + List allItems; + if (TryGetUsersInventory(userID, out folders, out allItems)) + { + invCollection.AllItems = allItems; + invCollection.Folders = folders; + invCollection.UserID = userID; + } + return invCollection; + } + + public bool CreateUsersInventory(Guid rawUserID) + { + LLUUID userID = new LLUUID(rawUserID); + + m_log.Info( + "[INVENTORY]: Creating new set of inventory folders for " + userID.ToString()); + + CreateNewUserInventory(userID); + return true; + } + + + public override void AddNewInventoryFolder(LLUUID userID, InventoryFolderBase folder) + { + AddFolder(folder); + } + + public override void MoveExistingInventoryFolder(InventoryFolderBase folder) + { + MoveFolder(folder); + } + + public override void AddNewInventoryItem(LLUUID userID, InventoryItemBase item) + { + AddItem(item); + } + + public bool AddInventoryFolder(InventoryFolderBase folder) + { + // Right now, this actions act more like an update/insert combination than a simple create. + m_log.Info( + "[INVENTORY]: " + + "Updating in " + folder.parentID.ToString() + + ", folder " + folder.name); + + AddNewInventoryFolder(folder.agentID, folder); + return true; + } + + public bool MoveInventoryFolder(InventoryFolderBase folder) + { + m_log.Info( + "[INVENTORY]: " + + "Moving folder " + folder.folderID + + " to " + folder.parentID.ToString()); + + MoveExistingInventoryFolder(folder); + return true; + } + + public bool AddInventoryItem(InventoryItemBase item) + { + // Right now, this actions act more like an update/insert combination than a simple create. + m_log.Info( + "[INVENTORY]: " + + "Updating in " + item.parentFolderID.ToString() + + ", item " + item.inventoryName); + + AddNewInventoryItem(item.avatarID, item); + return true; + } + + public override void DeleteInventoryItem(LLUUID userID, InventoryItemBase item) + { + // extra spaces to align with other inventory messages + m_log.Info( + "[INVENTORY]: " + + "Deleting in " + item.parentFolderID.ToString() + + ", item " + item.inventoryName); + + DeleteItem(item); + } + + public bool DeleteInvItem(InventoryItemBase item) + { + DeleteInventoryItem(item.avatarID, item); + return true; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/InventoryServer/InventoryManager.cs b/trunk/OpenSim/Grid/InventoryServer/InventoryManager.cs new file mode 100644 index 0000000000..a3d8483f78 --- /dev/null +++ b/trunk/OpenSim/Grid/InventoryServer/InventoryManager.cs @@ -0,0 +1,212 @@ +/* +* 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; +using System.IO; +using System.Reflection; +using System.Text; +using System.Xml; +using System.Xml.Serialization; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; + +namespace OpenSim.Grid.InventoryServer +{ + public class InventoryManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private IInventoryData _databasePlugin; + + /// + /// Adds a new inventory server plugin - user servers will be requested in the order they were loaded. + /// + /// The filename to the inventory server plugin DLL + public void AddDatabasePlugin(string FileName) + { + m_log.Info("[" + OpenInventory_Main.LogName + "]: Invenstorage: Attempting to load " + FileName); + Assembly pluginAssembly = Assembly.LoadFrom(FileName); + + m_log.Info("[" + OpenInventory_Main.LogName + "]: " + + "Invenstorage: Found " + pluginAssembly.GetTypes().Length + " interfaces."); + foreach (Type pluginType in pluginAssembly.GetTypes()) + { + if (!pluginType.IsAbstract) + { + Type typeInterface = pluginType.GetInterface("IInventoryData", true); + + if (typeInterface != null) + { + IInventoryData plug = + (IInventoryData) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + plug.Initialise(); + _databasePlugin = plug; + m_log.Info("[" + OpenInventory_Main.LogName + "]: " + + "Invenstorage: Added IInventoryData Interface"); + break; + } + + typeInterface = null; + } + } + + pluginAssembly = null; + } + + protected static SerializableInventory loadInventoryFromXmlFile(string fileName) + { + FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); + XmlReader reader = new XmlTextReader(fs); + XmlSerializer x = new XmlSerializer(typeof (SerializableInventory)); + SerializableInventory inventory = (SerializableInventory) x.Deserialize(reader); + fs.Close(); + fs.Dispose(); + return inventory; + } + + protected static void saveInventoryToStream(SerializableInventory inventory, Stream s) + { + XmlTextWriter writer = new XmlTextWriter(s, Encoding.UTF8); + writer.Formatting = Formatting.Indented; + XmlSerializer x = new XmlSerializer(typeof (SerializableInventory)); + x.Serialize(writer, inventory); + } + + protected static bool fixupFolder(SerializableInventory.SerializableFolder f, + SerializableInventory.SerializableFolder parent) + { + bool modified = false; + + // ensure we have a valid folder id + if (f.folderID == LLUUID.Zero) + { + f.folderID = LLUUID.Random(); + modified = true; + } + + // ensure we have valid agent id + if (f.agentID == LLUUID.Zero) + { + if (parent != null) + f.agentID = parent.agentID; + else + f.agentID = f.folderID; + modified = true; + } + + if (f.parentID == LLUUID.Zero && parent != null) + { + f.parentID = parent.folderID; + modified = true; + } + + + foreach (SerializableInventory.SerializableFolder child in f.SubFolders) + { + modified |= fixupFolder(child, f); + } + + return modified; + } + + protected static bool fixupInventory(SerializableInventory inventory) + { + return fixupFolder(inventory.root, null); + } + + public class GetInventory : BaseStreamHandler + { + private SerializableInventory _inventory; + private InventoryManager _manager; + + public GetInventory(InventoryManager manager) + : base("GET", "/inventory") + { + _manager = manager; + + _inventory = loadInventoryFromXmlFile("attic/inventory/Inventory_Library.xml"); + if (fixupInventory(_inventory)) + { + FileStream fs = new FileStream("attic/inventory/Inventory_Library.xml", FileMode.Truncate, FileAccess.Write); + saveInventoryToStream(_inventory, fs); + fs.Flush(); + fs.Close(); + m_log.Debug("[" + OpenInventory_Main.LogName + "]: Modified"); + } + } + + private void CreateDefaultInventory(LLUUID userID) + { + } + + private byte[] GetUserInventory(LLUUID userID) + { + m_log.InfoFormat("[" + OpenInventory_Main.LogName + "]: Getting Inventory for user {0}", userID.ToString()); + byte[] result = new byte[] {}; + + InventoryFolderBase fb = _manager._databasePlugin.getUserRootFolder(userID); + if (fb == null) + { + m_log.InfoFormat("[" + OpenInventory_Main.LogName + "]: Inventory not found for user {0}, creating new", + userID.ToString()); + CreateDefaultInventory(userID); + } + + return result; + } + + public override byte[] Handle(string path, Stream request) + { + byte[] result = new byte[] {}; + + string[] parms = path.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries); + if (parms.Length > 1) + { + if (string.Compare(parms[1], "library", true) == 0) + { + MemoryStream ms = new MemoryStream(); + saveInventoryToStream(_inventory, ms); + + result = ms.GetBuffer(); + Array.Resize(ref result, (int) ms.Length); + } + else if (string.Compare(parms[1], "user", true) == 0) + { + if (parms.Length > 2) + { + result = GetUserInventory(new LLUUID(parms[2])); + } + } + } + return result; + } + } + } +} diff --git a/trunk/OpenSim/Grid/InventoryServer/Main.cs b/trunk/OpenSim/Grid/InventoryServer/Main.cs new file mode 100644 index 0000000000..5037c7d0de --- /dev/null +++ b/trunk/OpenSim/Grid/InventoryServer/Main.cs @@ -0,0 +1,135 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; + +namespace OpenSim.Grid.InventoryServer +{ + public class OpenInventory_Main : BaseOpenSimServer, conscmd_callback + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private InventoryManager m_inventoryManager; + private InventoryConfig m_config; + private GridInventoryService m_inventoryService; + + public const string LogName = "INVENTORY"; + + [STAThread] + public static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + OpenInventory_Main theServer = new OpenInventory_Main(); + theServer.Startup(); + + theServer.Work(); + } + + public OpenInventory_Main() + { + m_console = new ConsoleBase(LogName, this); + MainConsole.Instance = m_console; + } + + public void Startup() + { + m_log.Info("Initialising inventory manager..."); + m_config = new InventoryConfig(LogName, (Path.Combine(Util.configDir(), "InventoryServer_Config.xml"))); + + m_inventoryService = new GridInventoryService(); + // m_inventoryManager = new InventoryManager(); + m_inventoryService.AddPlugin(m_config.DatabaseProvider); + + m_log.Info("[" + LogName + "]: Starting HTTP server ..."); + BaseHttpServer httpServer = new BaseHttpServer(m_config.HttpPort); + httpServer.AddStreamHandler( + new RestDeserialisehandler("POST", "/GetInventory/", + m_inventoryService.GetUserInventory)); + httpServer.AddStreamHandler( + new RestDeserialisehandler("POST", "/CreateInventory/", + m_inventoryService.CreateUsersInventory)); + httpServer.AddStreamHandler( + new RestDeserialisehandler("POST", "/NewFolder/", + m_inventoryService.AddInventoryFolder)); + + httpServer.AddStreamHandler( + new RestDeserialisehandler("POST", "/MoveFolder/", + m_inventoryService.MoveInventoryFolder)); + + httpServer.AddStreamHandler( + new RestDeserialisehandler("POST", "/NewItem/", + m_inventoryService.AddInventoryItem)); + httpServer.AddStreamHandler( + new RestDeserialisehandler("POST", "/DeleteItem/", + m_inventoryService.DeleteInvItem)); + + httpServer.AddStreamHandler( + new RestDeserialisehandler>("POST", "/RootFolders/", + m_inventoryService.RequestFirstLevelFolders)); + + // httpServer.AddStreamHandler(new InventoryManager.GetInventory(m_inventoryManager)); + + httpServer.Start(); + m_log.Info("[" + LogName + "]: Started HTTP server"); + } + + private void Work() + { + m_console.Notice("Enter help for a list of commands\n"); + + while (true) + { + m_console.Prompt(); + } + } + + public override void RunCmd(string cmd, string[] cmdparams) + { + base.RunCmd(cmd, cmdparams); + + switch (cmd) + { + case "quit": + case "add-user": + m_inventoryService.CreateUsersInventory(LLUUID.Random().UUID); + break; + case "shutdown": + m_console.Close(); + Environment.Exit(0); + break; + } + } + } +} diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager.mds b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager.mds new file mode 100644 index 0000000000..ed7bc24f3a --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager.mds @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager.userprefs b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager.userprefs new file mode 100644 index 0000000000..f221509426 --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager.userprefs @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager.usertasks b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager.usertasks new file mode 100644 index 0000000000..d887d0ef8d --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager.usertasks @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/AssemblyInfo.cs b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/AssemblyInfo.cs new file mode 100644 index 0000000000..cb61a9e566 --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/AssemblyInfo.cs @@ -0,0 +1,60 @@ +/* +* 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.CompilerServices; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes specify the key for the sign of your assembly. See the +// .NET Framework documentation for more information about signing. +// This is not required, if you don't want signing let these attributes like they're. +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/BlockingQueue.cs b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/BlockingQueue.cs new file mode 100644 index 0000000000..646b97717a --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/BlockingQueue.cs @@ -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 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; +using System.Threading; +using System.Collections.Generic; +using System.Text; + +namespace OpenGridServices.Manager +{ + public class BlockingQueue + { + private Queue _queue = new Queue(); + private object _queueSync = new object(); + + public void Enqueue(T value) + { + lock (_queueSync) + { + _queue.Enqueue(value); + Monitor.Pulse(_queueSync); + } + } + + public T Dequeue() + { + lock (_queueSync) + { + if (_queue.Count < 1) + Monitor.Wait(_queueSync); + + return _queue.Dequeue(); + } + } + } +} diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServer.cs b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServer.cs new file mode 100644 index 0000000000..c8bc8c0586 --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServer.cs @@ -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. +* +*/ + + +using System; + +namespace OpenGridServices.Manager +{ + public partial class Connect to grid server : Gtk.Dialog + { + public Connect to grid server() + { + this.Build(); + } + } +} diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServerDialog.cs b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServerDialog.cs new file mode 100644 index 0000000000..1bdb41e77d --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/ConnectToGridServerDialog.cs @@ -0,0 +1,54 @@ +/* +* 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 Gtk; +using System; + +namespace OpenGridServices.Manager +{ + public partial class ConnectToGridServerDialog : Gtk.Dialog + { + public ConnectToGridServerDialog() + { + this.Build(); + } + + protected virtual void OnResponse(object o, Gtk.ResponseArgs args) + { + switch(args.ResponseId) { + case Gtk.ResponseType.Ok: + MainClass.PendingOperations.Enqueue("connect_to_gridserver " + this.entry1.Text + " " + this.entry2.Text + " " + this.entry3.Text); + break; + + case Gtk.ResponseType.Cancel: + break; + } + this.Hide(); + } + } +} diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/GridServerConnectionManager.cs b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/GridServerConnectionManager.cs new file mode 100644 index 0000000000..255c5e36f9 --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/GridServerConnectionManager.cs @@ -0,0 +1,134 @@ +/* +* 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 Nwc.XmlRpc; +using System; +using System.Net; +using System.IO; +using System.Xml; +using System.Collections; +using System.Collections.Generic; +using libsecondlife; + +namespace OpenGridServices.Manager +{ + public class GridServerConnectionManager + { + private string ServerURL; + public LLUUID SessionID; + public bool connected=false; + + public RegionBlock[][] WorldMap; + + public bool Connect(string GridServerURL, string username, string password) + { + try { + this.ServerURL=GridServerURL; + Hashtable LoginParamsHT = new Hashtable(); + LoginParamsHT["username"]=username; + LoginParamsHT["password"]=password; + ArrayList LoginParams = new ArrayList(); + LoginParams.Add(LoginParamsHT); + XmlRpcRequest GridLoginReq = new XmlRpcRequest("manager_login",LoginParams); + XmlRpcResponse GridResp = GridLoginReq.Send(ServerURL,3000); + if(GridResp.IsFault) { + connected=false; + return false; + } else { + Hashtable gridrespData = (Hashtable)GridResp.Value; + this.SessionID = new LLUUID((string)gridrespData["session_id"]); + connected=true; + return true; + } + } catch(Exception e) { + Console.WriteLine(e.ToString()); + connected=false; + return false; + } + } + + public void DownloadMap() + { + System.Net.WebClient mapdownloader = new WebClient(); + Stream regionliststream = mapdownloader.OpenRead(ServerURL + "/regionlist"); + + RegionBlock TempRegionData; + + XmlDocument doc = new XmlDocument(); + doc.Load(regionliststream); + regionliststream.Close(); + XmlNode rootnode = doc.FirstChild; + if (rootnode.Name != "regions") + { + // TODO - ERROR! + } + + for(int i=0; i<=rootnode.ChildNodes.Count; i++) + { + if(rootnode.ChildNodes.Item(i).Name != "region") { + // TODO - ERROR! + } else { + TempRegionData = new RegionBlock(); + + + } + } + } + + public bool RestartServer() + { + return true; + } + + public bool ShutdownServer() + { + try { + Hashtable ShutdownParamsHT = new Hashtable(); + ArrayList ShutdownParams = new ArrayList(); + ShutdownParamsHT["session_id"]=this.SessionID.ToString(); + ShutdownParams.Add(ShutdownParamsHT); + XmlRpcRequest GridShutdownReq = new XmlRpcRequest("shutdown",ShutdownParams); + XmlRpcResponse GridResp = GridShutdownReq.Send(this.ServerURL,3000); + if(GridResp.IsFault) { + return false; + } else { + connected=false; + return true; + } + } catch(Exception e) { + Console.WriteLine(e.ToString()); + return false; + } + } + + public void DisconnectServer() + { + this.connected=false; + } + } +} diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/Main.cs b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/Main.cs new file mode 100644 index 0000000000..a2334e114e --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/Main.cs @@ -0,0 +1,123 @@ +/* +* 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; +using System.Threading; +using Gtk; + +namespace OpenGridServices.Manager +{ + class MainClass + { + + public static bool QuitReq=false; + public static BlockingQueue PendingOperations = new BlockingQueue(); + + private static Thread OperationsRunner; + + private static GridServerConnectionManager gridserverConn; + + private static MainWindow win; + + public static void DoMainLoop() + { + while(!QuitReq) + { + Application.RunIteration(); + } + } + + public static void RunOperations() + { + string operation; + string cmd; + char[] sep = new char[1]; + sep[0]=' '; + while(!QuitReq) + { + operation=PendingOperations.Dequeue(); + Console.WriteLine(operation); + cmd = operation.Split(sep)[0]; + switch(cmd) { + case "connect_to_gridserver": + win.SetStatus("Connecting to grid server..."); + if(gridserverConn.Connect(operation.Split(sep)[1],operation.Split(sep)[2],operation.Split(sep)[3])) { + win.SetStatus("Connected OK with session ID:" + gridserverConn.SessionID); + win.SetGridServerConnected(true); + Thread.Sleep(3000); + win.SetStatus("Downloading region maps..."); + gridserverConn.DownloadMap(); + } else { + win.SetStatus("Could not connect"); + } + break; + + case "restart_gridserver": + win.SetStatus("Restarting grid server..."); + if(gridserverConn.RestartServer()) { + win.SetStatus("Restarted server OK"); + Thread.Sleep(3000); + win.SetStatus(""); + } else { + win.SetStatus("Error restarting grid server!!!"); + } + break; + + case "shutdown_gridserver": + win.SetStatus("Shutting down grid server..."); + if(gridserverConn.ShutdownServer()) { + win.SetStatus("Grid server shutdown"); + win.SetGridServerConnected(false); + Thread.Sleep(3000); + win.SetStatus(""); + } else { + win.SetStatus("Could not shutdown grid server!!!"); + } + break; + + case "disconnect_gridserver": + gridserverConn.DisconnectServer(); + win.SetGridServerConnected(false); + break; + } + } + } + + public static void Main (string[] args) + { + gridserverConn = new GridServerConnectionManager(); + Application.Init (); + win = new MainWindow (); + win.Show (); + OperationsRunner = new Thread(new ThreadStart(RunOperations)); + OperationsRunner.IsBackground=true; + OperationsRunner.Start(); + DoMainLoop(); + } + } +} diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/MainWindow.cs b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/MainWindow.cs new file mode 100644 index 0000000000..312c347ba9 --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/MainWindow.cs @@ -0,0 +1,104 @@ +/* +* 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; +using Gtk; + +namespace OpenGridServices.Manager +{ + public partial class MainWindow: Gtk.Window + { + public MainWindow (): base (Gtk.WindowType.Toplevel) + { + Build(); + } + + public void SetStatus(string statustext) + { + this.statusbar1.Pop(0); + this.statusbar1.Push(0, statustext); + } + + public void DrawGrid(RegionBlock[][] regions) + { + for (int x=0; x<=regions.GetUpperBound(0); x++) + { + for (int y=0; y<=regions.GetUpperBound(1); y++) + { + Gdk.Image themap = new Gdk.Image(Gdk.ImageType.Fastest,Gdk.Visual.System,256,256); + this.drawingarea1.GdkWindow.DrawImage(new Gdk.GC(this.drawingarea1.GdkWindow),themap,0,0,x*256,y*256,256,256); + } + } + } + + public void SetGridServerConnected(bool connected) + { + if (connected) { + this.ConnectToGridserver.Visible=false; + this.DisconnectFromGridServer.Visible=true; + } else { + this.ConnectToGridserver.Visible=true; + this.DisconnectFromGridServer.Visible=false; + } + } + + protected void OnDeleteEvent (object sender, DeleteEventArgs a) + { + Application.Quit (); + MainClass.QuitReq=true; + a.RetVal = true; + } + + protected virtual void QuitMenu(object sender, System.EventArgs e) + { + MainClass.QuitReq=true; + Application.Quit(); + } + + protected virtual void ConnectToGridServerMenu(object sender, System.EventArgs e) + { + ConnectToGridServerDialog griddialog = new ConnectToGridServerDialog (); + griddialog.Show(); + } + + protected virtual void RestartGridserverMenu(object sender, System.EventArgs e) + { + MainClass.PendingOperations.Enqueue("restart_gridserver"); + } + + protected virtual void ShutdownGridserverMenu(object sender, System.EventArgs e) + { + MainClass.PendingOperations.Enqueue("shutdown_gridserver"); + } + + protected virtual void DisconnectGridServerMenu(object sender, System.EventArgs e) + { + MainClass.PendingOperations.Enqueue("disconnect_gridserver"); + } + } +} diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/OpenGridServices.Manager.mdp b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/OpenGridServices.Manager.mdp new file mode 100644 index 0000000000..cfdc085eb8 --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/OpenGridServices.Manager.mdp @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/OpenGridServices.Manager.pidb b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/OpenGridServices.Manager.pidb new file mode 100644 index 0000000000000000000000000000000000000000..44e7a619a3168cd0949fe56768cbac1002c4f6bc GIT binary patch literal 12308 zcmc(lOLr8<6~|{_rZqhRGdyf;Y{&S4ZEQS9V1b2AKuAImB!rOwJANoVGbO3R%(T+o zBT!BjPFBe-i+qQCfg~RwC!4HtPF7jvoa6&|nPr^&yWKsSW*!~^B6ZHKuD(_MzqfAP zx>eQPnQSJL`A!m7QjWqaOItx`8s%xPUN_ay^_oHXniH&tPNi-N(x5o+Ikl@!HT3+E zyT%WsMPb@&Y&gF0OSGK!YUY;jZMrq%7ho*8KR3A>W-GAnI`x(bO6F%Rr|yPZ$zz$! zo;{g-e$Qw@1YEwfA1TFA$?ZL4d$})Bq-5nJJ38+Kp`f|7Whb~l?*`$rci%JvD=(Fa zT9zd@M><-riNJp%h zP2m*h!u#bZwSDIUnaqEs@_?`)I{Io-%~QEMf$?DshjUO`LR~odsUR@n@IZ&9DFo0D zc#MQX)@`#U&cW?)Dm^bPA&_D_M@WSw<8QiE6G+97SVyHL1lH?9n$YU-wAXBkV=sHy zT}-yQ6RW)>I1sQ5peA5Tw@nZ_et2))tDBvT=*t2Efq7B^B?I%|(t0Ztk7_;!D6Rnk z`ks&`Ko875bVC$eaGK8APWsM}KtR5$c#;9RZBkrtrzT}|pl*{+RjXdB8LFa8TVxLB zNpDI^sLQ1L=IUO>so(TMai`(&PDoP-Jg%DPdTGWD2#izp`nT1or5i zjk;_ZcDSre%JUF#Zz+~!z#UMaD0=NIDts&m5Rj<=cBH)~DE3Z!eo^osaPebJsQN}5 zHy*PN_^Y0em1#TNtiB{IA*9d?O-MN$g9~EYpQ#)Uc1l`8z@}ETBipdsz9)@_#GRIw zP?u2-Mzf>C6vKngN>d2X)T)->tauOA>)O38u#38T#d`?+c47}TC$|tVuOwBNvLFuC zsyO}`m~Es{kQSuoilZB>jZP?t^zf~wD6y!Jr1 zm+4L(Lbav1L3;lgsX}+zenLQxMeJxQS-PoDBibM?v!*32qbop*QiK3XZ}r@U>?L{t zU56h5BsoBz$_>;9C~bb#s1MMRfIxkK2&LQOI0)#DG=%y9X|QZN#2}!10s{2`BKi)e z(dW_->H~CcXrM2oCDaFqm_3|EUr9r#570+L1Fc9)s1Fcfe>jaCX$W-z*`aUDrfVLg zeR7{Vw^ZGgDx_>D+_EaS5OAqArzm^-uoXyTNaO9->6g@PgHZy|$Q1(cZJ~C;m8AZ= z{FRnl*F`|(;ep)=q%~nfAiYVGgjo?N7@T!`C**v2dfjW7(`#}_57$pGZkT4W#B;1F z$7g~56>H)B57t`l>Fr}~xf<*jc~uclXCUp-vyp@}MAEmxXK!u6F!hR#z{DvhSK8)y zu>p^F9oj23HRgqEA)R{Izmu_7D%uI4{fo^RQ#YZR-HgvJh|nO@ZbyOF2y9ZLM4V0~ zpt4THqI{UXbO2BJYeDJ(Rd-Za5a3f(qb`gCF{4Y}!lx}aWRatFZ)f}-P4#^TPe&59 zlw^oMC^rx=GgKtZBQc{(r=#utQ{t`0-&GZP(F36(%ZjQ9<52X`~e=wtbDR}=<`r5Bs&StGqg9dOpb zIUt@+oi(hwQ!(}QenK~v^YEp0M@k|kqYY4c^DWDZztsb17Jdhc6ahLcSEvhUq|ypQ zubJ+ePUkCH(GB&yuppq03u(eeF;sd>I1uWnJPW0uBEUy-@b5pN-zNK+LH^73=0zbq z2-3m-zX(S7A4LVUp!YTl#dO^X0`6Yvx1Hm$D5?5Aow~CHU^$>+{+g_7KMD|mI7*); z1=uPB20q3%2_h`%K|NtI6<`bwOE;fzchAT(uHLiA}zpxwe28JT~I5wHW6+&kBD zxmru1k+;oMs}7N&dJabN=&0LtLs?_xyIGCreo1zgES0b+-Geap$0k zF-uIjFZw1o=X~ z6fesS#3;6RDllG+8L3f39S{PBlp`0-F9QF zUlI{-2;oq>>Qr5Vv~P(=aV3=~5E8dPc-wl5ZaI9W*Jt@D-*>k7_Dz({uLKe=( zrqeLNhEp}Vv!HpQ>NP{ze*_la|C?d1DNXj~vc1%8|3&cL@G?*qvQfQQ%wd#)*xGK_ z|4<+v#eXQ^)HV)W%<5oCDI@gAQ`1zFf4i*Q2U3pPv5#gW39<_uw>dfRUVrzImPKlUq6I$&z$=;Hzl)Qms5T^uiul_$o=#>!)-j!(;1;g)YMHccz^o%*Tcw_26DTa~|; z^arDhmGkGFiR#3;@yW9vnz4^2vrJ-iwBAd}U?&r-JO0MDm^0-MMbHp3&Q6%|vGK`? zno~Jjot#|F5+hW``)L`qrznFEq%uxP;cnYjYjwBs^g2R_Qz0Kn;a-Ojr)Hj>6k@1K zDW{}tIL$Th=}93-tCZ7H_`Ka0*0%C3FK{1jkNi#?Z0!8mk4$B9b^PoZQ#(I#F3UQg za>i1$dDR0<-Kk%t0;9`o8DiHlgpDU|%)* z$&VicgOMtyWD`hO$nDu*I5|kvvLpWoCO}1e|k5{U=8O9ao=Z~ ztp<&uPgu+(=?}2hMJaVmOkHS;`5y{*Ah5jQVuP;wf;Y0sKe#I^ndcC3Y;XROTm~Ah z-HFuWdw4vPzbx56`JEk00UQ8;ZwFbN59|EM@@aH-sQb5zIX)rCy@Mc%KPBHp1spjPQOerOQH!hXHl8 zzL0|brDWDuu;fii784+gcLk)#+FuLjd);S68X>qilKqKXBEgQ7E(_s4C5(sLS{2Dg z;_u`otO-{&DPcaew5pO}CaWfeR7Xo#mo^<y> 1) - (min >> 2) + (min >> 4)); + //} + + public static string FieldToString(byte[] bytes) + { + return FieldToString(bytes, String.Empty); + } + + /// + /// Convert a variable length field (byte array) to a string, with a + /// field name prepended to each line of the output + /// + /// If the byte array has unprintable characters in it, a + /// hex dump will be put in the string instead + /// The byte array to convert to a string + /// A field name to prepend to each line of output + /// An ASCII string or a string containing a hex dump, minus + /// the null terminator + public static string FieldToString(byte[] bytes, string fieldName) + { + // Check for a common case + if (bytes.Length == 0) return String.Empty; + + StringBuilder output = new StringBuilder(); + bool printable = true; + + for (int i = 0; i < bytes.Length; ++i) + { + // Check if there are any unprintable characters in the array + if ((bytes[i] < 0x20 || bytes[i] > 0x7E) && bytes[i] != 0x09 + && bytes[i] != 0x0D && bytes[i] != 0x0A && bytes[i] != 0x00) + { + printable = false; + break; + } + } + + if (printable) + { + if (fieldName.Length > 0) + { + output.Append(fieldName); + output.Append(": "); + } + + if (bytes[bytes.Length - 1] == 0x00) + output.Append(UTF8Encoding.UTF8.GetString(bytes, 0, bytes.Length - 1)); + else + output.Append(UTF8Encoding.UTF8.GetString(bytes)); + } + else + { + for (int i = 0; i < bytes.Length; i += 16) + { + if (i != 0) + output.Append(Environment.NewLine); + if (fieldName.Length > 0) + { + output.Append(fieldName); + output.Append(": "); + } + + for (int j = 0; j < 16; j++) + { + if ((i + j) < bytes.Length) + output.Append(String.Format("{0:X2} ", bytes[i + j])); + else + output.Append(" "); + } + + for (int j = 0; j < 16 && (i + j) < bytes.Length; j++) + { + if (bytes[i + j] >= 0x20 && bytes[i + j] < 0x7E) + output.Append((char)bytes[i + j]); + else + output.Append("."); + } + } + } + + return output.ToString(); + } + public Util() + { + + } + } +} diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/OpenGridServices.Manager.ConnectToGridServerDialog.cs b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/OpenGridServices.Manager.ConnectToGridServerDialog.cs new file mode 100644 index 0000000000..b5a246b765 --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/OpenGridServices.Manager.ConnectToGridServerDialog.cs @@ -0,0 +1,254 @@ +/* +* 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. +* +*/ + +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Mono Runtime Version: 2.0.50727.42 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +namespace OpenGridServices.Manager { + + + public partial class ConnectToGridServerDialog { + + private Gtk.VBox vbox2; + + private Gtk.VBox vbox3; + + private Gtk.HBox hbox1; + + private Gtk.Label label1; + + private Gtk.Entry entry1; + + private Gtk.HBox hbox2; + + private Gtk.Label label2; + + private Gtk.Entry entry2; + + private Gtk.HBox hbox3; + + private Gtk.Label label3; + + private Gtk.Entry entry3; + + private Gtk.Button button2; + + private Gtk.Button button8; + + protected virtual void Build() { + Stetic.Gui.Initialize(); + // Widget OpenGridServices.Manager.ConnectToGridServerDialog + this.Events = ((Gdk.EventMask)(256)); + this.Name = "OpenGridServices.Manager.ConnectToGridServerDialog"; + this.Title = Mono.Unix.Catalog.GetString("Connect to Grid server"); + this.WindowPosition = ((Gtk.WindowPosition)(4)); + this.HasSeparator = false; + // Internal child OpenGridServices.Manager.ConnectToGridServerDialog.VBox + Gtk.VBox w1 = this.VBox; + w1.Events = ((Gdk.EventMask)(256)); + w1.Name = "dialog_VBox"; + w1.BorderWidth = ((uint)(2)); + // Container child dialog_VBox.Gtk.Box+BoxChild + this.vbox2 = new Gtk.VBox(); + this.vbox2.Name = "vbox2"; + // Container child vbox2.Gtk.Box+BoxChild + this.vbox3 = new Gtk.VBox(); + this.vbox3.Name = "vbox3"; + // Container child vbox3.Gtk.Box+BoxChild + this.hbox1 = new Gtk.HBox(); + this.hbox1.Name = "hbox1"; + // Container child hbox1.Gtk.Box+BoxChild + this.label1 = new Gtk.Label(); + this.label1.Name = "label1"; + this.label1.Xalign = 1F; + this.label1.LabelProp = Mono.Unix.Catalog.GetString("Grid server URL: "); + this.label1.Justify = ((Gtk.Justification)(1)); + this.hbox1.Add(this.label1); + Gtk.Box.BoxChild w2 = ((Gtk.Box.BoxChild)(this.hbox1[this.label1])); + w2.Position = 0; + // Container child hbox1.Gtk.Box+BoxChild + this.entry1 = new Gtk.Entry(); + this.entry1.CanFocus = true; + this.entry1.Name = "entry1"; + this.entry1.Text = Mono.Unix.Catalog.GetString("http://gridserver:8001"); + this.entry1.IsEditable = true; + this.entry1.MaxLength = 255; + this.entry1.InvisibleChar = '•'; + this.hbox1.Add(this.entry1); + Gtk.Box.BoxChild w3 = ((Gtk.Box.BoxChild)(this.hbox1[this.entry1])); + w3.Position = 1; + this.vbox3.Add(this.hbox1); + Gtk.Box.BoxChild w4 = ((Gtk.Box.BoxChild)(this.vbox3[this.hbox1])); + w4.Position = 0; + w4.Expand = false; + w4.Fill = false; + // Container child vbox3.Gtk.Box+BoxChild + this.hbox2 = new Gtk.HBox(); + this.hbox2.Name = "hbox2"; + // Container child hbox2.Gtk.Box+BoxChild + this.label2 = new Gtk.Label(); + this.label2.Name = "label2"; + this.label2.Xalign = 1F; + this.label2.LabelProp = Mono.Unix.Catalog.GetString("Username:"); + this.label2.Justify = ((Gtk.Justification)(1)); + this.hbox2.Add(this.label2); + Gtk.Box.BoxChild w5 = ((Gtk.Box.BoxChild)(this.hbox2[this.label2])); + w5.Position = 0; + // Container child hbox2.Gtk.Box+BoxChild + this.entry2 = new Gtk.Entry(); + this.entry2.CanFocus = true; + this.entry2.Name = "entry2"; + this.entry2.IsEditable = true; + this.entry2.InvisibleChar = '•'; + this.hbox2.Add(this.entry2); + Gtk.Box.BoxChild w6 = ((Gtk.Box.BoxChild)(this.hbox2[this.entry2])); + w6.Position = 1; + this.vbox3.Add(this.hbox2); + Gtk.Box.BoxChild w7 = ((Gtk.Box.BoxChild)(this.vbox3[this.hbox2])); + w7.Position = 1; + w7.Expand = false; + w7.Fill = false; + // Container child vbox3.Gtk.Box+BoxChild + this.hbox3 = new Gtk.HBox(); + this.hbox3.Name = "hbox3"; + // Container child hbox3.Gtk.Box+BoxChild + this.label3 = new Gtk.Label(); + this.label3.Name = "label3"; + this.label3.Xalign = 1F; + this.label3.LabelProp = Mono.Unix.Catalog.GetString("Password:"); + this.label3.Justify = ((Gtk.Justification)(1)); + this.hbox3.Add(this.label3); + Gtk.Box.BoxChild w8 = ((Gtk.Box.BoxChild)(this.hbox3[this.label3])); + w8.Position = 0; + // Container child hbox3.Gtk.Box+BoxChild + this.entry3 = new Gtk.Entry(); + this.entry3.CanFocus = true; + this.entry3.Name = "entry3"; + this.entry3.IsEditable = true; + this.entry3.InvisibleChar = '•'; + this.hbox3.Add(this.entry3); + Gtk.Box.BoxChild w9 = ((Gtk.Box.BoxChild)(this.hbox3[this.entry3])); + w9.Position = 1; + this.vbox3.Add(this.hbox3); + Gtk.Box.BoxChild w10 = ((Gtk.Box.BoxChild)(this.vbox3[this.hbox3])); + w10.Position = 2; + w10.Expand = false; + w10.Fill = false; + this.vbox2.Add(this.vbox3); + Gtk.Box.BoxChild w11 = ((Gtk.Box.BoxChild)(this.vbox2[this.vbox3])); + w11.Position = 2; + w11.Expand = false; + w11.Fill = false; + w1.Add(this.vbox2); + Gtk.Box.BoxChild w12 = ((Gtk.Box.BoxChild)(w1[this.vbox2])); + w12.Position = 0; + // Internal child OpenGridServices.Manager.ConnectToGridServerDialog.ActionArea + Gtk.HButtonBox w13 = this.ActionArea; + w13.Events = ((Gdk.EventMask)(256)); + w13.Name = "OpenGridServices.Manager.ConnectToGridServerDialog_ActionArea"; + w13.Spacing = 6; + w13.BorderWidth = ((uint)(5)); + w13.LayoutStyle = ((Gtk.ButtonBoxStyle)(4)); + // Container child OpenGridServices.Manager.ConnectToGridServerDialog_ActionArea.Gtk.ButtonBox+ButtonBoxChild + this.button2 = new Gtk.Button(); + this.button2.CanDefault = true; + this.button2.CanFocus = true; + this.button2.Name = "button2"; + this.button2.UseUnderline = true; + // Container child button2.Gtk.Container+ContainerChild + Gtk.Alignment w14 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F); + w14.Name = "GtkAlignment"; + // Container child GtkAlignment.Gtk.Container+ContainerChild + Gtk.HBox w15 = new Gtk.HBox(); + w15.Name = "GtkHBox"; + w15.Spacing = 2; + // Container child GtkHBox.Gtk.Container+ContainerChild + Gtk.Image w16 = new Gtk.Image(); + w16.Name = "image1"; + w16.Pixbuf = Gtk.IconTheme.Default.LoadIcon("gtk-apply", 16, 0); + w15.Add(w16); + // Container child GtkHBox.Gtk.Container+ContainerChild + Gtk.Label w18 = new Gtk.Label(); + w18.Name = "GtkLabel"; + w18.LabelProp = Mono.Unix.Catalog.GetString("Connect"); + w18.UseUnderline = true; + w15.Add(w18); + w14.Add(w15); + this.button2.Add(w14); + this.AddActionWidget(this.button2, -5); + Gtk.ButtonBox.ButtonBoxChild w22 = ((Gtk.ButtonBox.ButtonBoxChild)(w13[this.button2])); + w22.Expand = false; + w22.Fill = false; + // Container child OpenGridServices.Manager.ConnectToGridServerDialog_ActionArea.Gtk.ButtonBox+ButtonBoxChild + this.button8 = new Gtk.Button(); + this.button8.CanDefault = true; + this.button8.CanFocus = true; + this.button8.Name = "button8"; + this.button8.UseUnderline = true; + // Container child button8.Gtk.Container+ContainerChild + Gtk.Alignment w23 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F); + w23.Name = "GtkAlignment1"; + // Container child GtkAlignment1.Gtk.Container+ContainerChild + Gtk.HBox w24 = new Gtk.HBox(); + w24.Name = "GtkHBox1"; + w24.Spacing = 2; + // Container child GtkHBox1.Gtk.Container+ContainerChild + Gtk.Image w25 = new Gtk.Image(); + w25.Name = "image2"; + w25.Pixbuf = Gtk.IconTheme.Default.LoadIcon("gtk-cancel", 16, 0); + w24.Add(w25); + // Container child GtkHBox1.Gtk.Container+ContainerChild + Gtk.Label w27 = new Gtk.Label(); + w27.Name = "GtkLabel1"; + w27.LabelProp = Mono.Unix.Catalog.GetString("Cancel"); + w27.UseUnderline = true; + w24.Add(w27); + w23.Add(w24); + this.button8.Add(w23); + this.AddActionWidget(this.button8, -6); + Gtk.ButtonBox.ButtonBoxChild w31 = ((Gtk.ButtonBox.ButtonBoxChild)(w13[this.button8])); + w31.Position = 1; + w31.Expand = false; + w31.Fill = false; + if ((this.Child != null)) { + this.Child.ShowAll(); + } + this.DefaultWidth = 476; + this.DefaultHeight = 137; + this.Show(); + this.Response += new Gtk.ResponseHandler(this.OnResponse); + } + } +} diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/OpenGridServices.Manager.MainWindow.cs b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/OpenGridServices.Manager.MainWindow.cs new file mode 100644 index 0000000000..694bc54b4b --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/OpenGridServices.Manager.MainWindow.cs @@ -0,0 +1,284 @@ +/* +* 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. +* +*/ + +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Mono Runtime Version: 2.0.50727.42 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +namespace OpenGridServices.Manager { + + + public partial class MainWindow { + + private Gtk.Action Grid; + + private Gtk.Action User; + + private Gtk.Action Asset; + + private Gtk.Action Region; + + private Gtk.Action Services; + + private Gtk.Action ConnectToGridserver; + + private Gtk.Action RestartWholeGrid; + + private Gtk.Action ShutdownWholeGrid; + + private Gtk.Action ExitGridManager; + + private Gtk.Action ConnectToUserserver; + + private Gtk.Action AccountManagment; + + private Gtk.Action GlobalNotice; + + private Gtk.Action DisableAllLogins; + + private Gtk.Action DisableNonGodUsersOnly; + + private Gtk.Action ShutdownUserServer; + + private Gtk.Action ShutdownGridserverOnly; + + private Gtk.Action RestartGridserverOnly; + + private Gtk.Action DefaultLocalGridUserserver; + + private Gtk.Action CustomUserserver; + + private Gtk.Action RemoteGridDefaultUserserver; + + private Gtk.Action DisconnectFromGridServer; + + private Gtk.Action UploadAsset; + + private Gtk.Action AssetManagement; + + private Gtk.Action ConnectToAssetServer; + + private Gtk.Action ConnectToDefaultAssetServerForGrid; + + private Gtk.Action DefaultForLocalGrid; + + private Gtk.Action DefaultForRemoteGrid; + + private Gtk.Action CustomAssetServer; + + private Gtk.VBox vbox1; + + private Gtk.MenuBar menubar2; + + private Gtk.HBox hbox1; + + private Gtk.ScrolledWindow scrolledwindow1; + + private Gtk.DrawingArea drawingarea1; + + private Gtk.TreeView treeview1; + + private Gtk.Statusbar statusbar1; + + protected virtual void Build() { + Stetic.Gui.Initialize(); + // Widget OpenGridServices.Manager.MainWindow + Gtk.UIManager w1 = new Gtk.UIManager(); + Gtk.ActionGroup w2 = new Gtk.ActionGroup("Default"); + this.Grid = new Gtk.Action("Grid", Mono.Unix.Catalog.GetString("Grid"), null, null); + this.Grid.HideIfEmpty = false; + this.Grid.ShortLabel = Mono.Unix.Catalog.GetString("Grid"); + w2.Add(this.Grid, "g"); + this.User = new Gtk.Action("User", Mono.Unix.Catalog.GetString("User"), null, null); + this.User.HideIfEmpty = false; + this.User.ShortLabel = Mono.Unix.Catalog.GetString("User"); + w2.Add(this.User, null); + this.Asset = new Gtk.Action("Asset", Mono.Unix.Catalog.GetString("Asset"), null, null); + this.Asset.HideIfEmpty = false; + this.Asset.ShortLabel = Mono.Unix.Catalog.GetString("Asset"); + w2.Add(this.Asset, null); + this.Region = new Gtk.Action("Region", Mono.Unix.Catalog.GetString("Region"), null, null); + this.Region.ShortLabel = Mono.Unix.Catalog.GetString("Region"); + w2.Add(this.Region, null); + this.Services = new Gtk.Action("Services", Mono.Unix.Catalog.GetString("Services"), null, null); + this.Services.ShortLabel = Mono.Unix.Catalog.GetString("Services"); + w2.Add(this.Services, null); + this.ConnectToGridserver = new Gtk.Action("ConnectToGridserver", Mono.Unix.Catalog.GetString("Connect to gridserver..."), null, "gtk-connect"); + this.ConnectToGridserver.HideIfEmpty = false; + this.ConnectToGridserver.ShortLabel = Mono.Unix.Catalog.GetString("Connect to gridserver"); + w2.Add(this.ConnectToGridserver, null); + this.RestartWholeGrid = new Gtk.Action("RestartWholeGrid", Mono.Unix.Catalog.GetString("Restart whole grid"), null, "gtk-refresh"); + this.RestartWholeGrid.ShortLabel = Mono.Unix.Catalog.GetString("Restart whole grid"); + w2.Add(this.RestartWholeGrid, null); + this.ShutdownWholeGrid = new Gtk.Action("ShutdownWholeGrid", Mono.Unix.Catalog.GetString("Shutdown whole grid"), null, "gtk-stop"); + this.ShutdownWholeGrid.ShortLabel = Mono.Unix.Catalog.GetString("Shutdown whole grid"); + w2.Add(this.ShutdownWholeGrid, null); + this.ExitGridManager = new Gtk.Action("ExitGridManager", Mono.Unix.Catalog.GetString("Exit grid manager"), null, "gtk-close"); + this.ExitGridManager.ShortLabel = Mono.Unix.Catalog.GetString("Exit grid manager"); + w2.Add(this.ExitGridManager, null); + this.ConnectToUserserver = new Gtk.Action("ConnectToUserserver", Mono.Unix.Catalog.GetString("Connect to userserver"), null, "gtk-connect"); + this.ConnectToUserserver.ShortLabel = Mono.Unix.Catalog.GetString("Connect to userserver"); + w2.Add(this.ConnectToUserserver, null); + this.AccountManagment = new Gtk.Action("AccountManagment", Mono.Unix.Catalog.GetString("Account managment"), null, "gtk-properties"); + this.AccountManagment.ShortLabel = Mono.Unix.Catalog.GetString("Account managment"); + w2.Add(this.AccountManagment, null); + this.GlobalNotice = new Gtk.Action("GlobalNotice", Mono.Unix.Catalog.GetString("Global notice"), null, "gtk-network"); + this.GlobalNotice.ShortLabel = Mono.Unix.Catalog.GetString("Global notice"); + w2.Add(this.GlobalNotice, null); + this.DisableAllLogins = new Gtk.Action("DisableAllLogins", Mono.Unix.Catalog.GetString("Disable all logins"), null, "gtk-no"); + this.DisableAllLogins.ShortLabel = Mono.Unix.Catalog.GetString("Disable all logins"); + w2.Add(this.DisableAllLogins, null); + this.DisableNonGodUsersOnly = new Gtk.Action("DisableNonGodUsersOnly", Mono.Unix.Catalog.GetString("Disable non-god users only"), null, "gtk-no"); + this.DisableNonGodUsersOnly.ShortLabel = Mono.Unix.Catalog.GetString("Disable non-god users only"); + w2.Add(this.DisableNonGodUsersOnly, null); + this.ShutdownUserServer = new Gtk.Action("ShutdownUserServer", Mono.Unix.Catalog.GetString("Shutdown user server"), null, "gtk-stop"); + this.ShutdownUserServer.ShortLabel = Mono.Unix.Catalog.GetString("Shutdown user server"); + w2.Add(this.ShutdownUserServer, null); + this.ShutdownGridserverOnly = new Gtk.Action("ShutdownGridserverOnly", Mono.Unix.Catalog.GetString("Shutdown gridserver only"), null, "gtk-stop"); + this.ShutdownGridserverOnly.ShortLabel = Mono.Unix.Catalog.GetString("Shutdown gridserver only"); + w2.Add(this.ShutdownGridserverOnly, null); + this.RestartGridserverOnly = new Gtk.Action("RestartGridserverOnly", Mono.Unix.Catalog.GetString("Restart gridserver only"), null, "gtk-refresh"); + this.RestartGridserverOnly.ShortLabel = Mono.Unix.Catalog.GetString("Restart gridserver only"); + w2.Add(this.RestartGridserverOnly, null); + this.DefaultLocalGridUserserver = new Gtk.Action("DefaultLocalGridUserserver", Mono.Unix.Catalog.GetString("Default local grid userserver"), null, null); + this.DefaultLocalGridUserserver.ShortLabel = Mono.Unix.Catalog.GetString("Default local grid userserver"); + w2.Add(this.DefaultLocalGridUserserver, null); + this.CustomUserserver = new Gtk.Action("CustomUserserver", Mono.Unix.Catalog.GetString("Custom userserver..."), null, null); + this.CustomUserserver.ShortLabel = Mono.Unix.Catalog.GetString("Custom userserver"); + w2.Add(this.CustomUserserver, null); + this.RemoteGridDefaultUserserver = new Gtk.Action("RemoteGridDefaultUserserver", Mono.Unix.Catalog.GetString("Remote grid default userserver..."), null, null); + this.RemoteGridDefaultUserserver.ShortLabel = Mono.Unix.Catalog.GetString("Remote grid default userserver"); + w2.Add(this.RemoteGridDefaultUserserver, null); + this.DisconnectFromGridServer = new Gtk.Action("DisconnectFromGridServer", Mono.Unix.Catalog.GetString("Disconnect from grid server"), null, "gtk-disconnect"); + this.DisconnectFromGridServer.ShortLabel = Mono.Unix.Catalog.GetString("Disconnect from grid server"); + this.DisconnectFromGridServer.Visible = false; + w2.Add(this.DisconnectFromGridServer, null); + this.UploadAsset = new Gtk.Action("UploadAsset", Mono.Unix.Catalog.GetString("Upload asset"), null, null); + this.UploadAsset.ShortLabel = Mono.Unix.Catalog.GetString("Upload asset"); + w2.Add(this.UploadAsset, null); + this.AssetManagement = new Gtk.Action("AssetManagement", Mono.Unix.Catalog.GetString("Asset management"), null, null); + this.AssetManagement.ShortLabel = Mono.Unix.Catalog.GetString("Asset management"); + w2.Add(this.AssetManagement, null); + this.ConnectToAssetServer = new Gtk.Action("ConnectToAssetServer", Mono.Unix.Catalog.GetString("Connect to asset server"), null, null); + this.ConnectToAssetServer.ShortLabel = Mono.Unix.Catalog.GetString("Connect to asset server"); + w2.Add(this.ConnectToAssetServer, null); + this.ConnectToDefaultAssetServerForGrid = new Gtk.Action("ConnectToDefaultAssetServerForGrid", Mono.Unix.Catalog.GetString("Connect to default asset server for grid"), null, null); + this.ConnectToDefaultAssetServerForGrid.ShortLabel = Mono.Unix.Catalog.GetString("Connect to default asset server for grid"); + w2.Add(this.ConnectToDefaultAssetServerForGrid, null); + this.DefaultForLocalGrid = new Gtk.Action("DefaultForLocalGrid", Mono.Unix.Catalog.GetString("Default for local grid"), null, null); + this.DefaultForLocalGrid.ShortLabel = Mono.Unix.Catalog.GetString("Default for local grid"); + w2.Add(this.DefaultForLocalGrid, null); + this.DefaultForRemoteGrid = new Gtk.Action("DefaultForRemoteGrid", Mono.Unix.Catalog.GetString("Default for remote grid..."), null, null); + this.DefaultForRemoteGrid.ShortLabel = Mono.Unix.Catalog.GetString("Default for remote grid..."); + w2.Add(this.DefaultForRemoteGrid, null); + this.CustomAssetServer = new Gtk.Action("CustomAssetServer", Mono.Unix.Catalog.GetString("Custom asset server..."), null, null); + this.CustomAssetServer.ShortLabel = Mono.Unix.Catalog.GetString("Custom asset server..."); + w2.Add(this.CustomAssetServer, null); + w1.InsertActionGroup(w2, 0); + this.AddAccelGroup(w1.AccelGroup); + this.WidthRequest = 800; + this.HeightRequest = 600; + this.Name = "OpenGridServices.Manager.MainWindow"; + this.Title = Mono.Unix.Catalog.GetString("Open Grid Services Manager"); + this.Icon = Gtk.IconTheme.Default.LoadIcon("gtk-network", 48, 0); + // Container child OpenGridServices.Manager.MainWindow.Gtk.Container+ContainerChild + this.vbox1 = new Gtk.VBox(); + this.vbox1.Name = "vbox1"; + // Container child vbox1.Gtk.Box+BoxChild + w1.AddUiFromString(""); + this.menubar2 = ((Gtk.MenuBar)(w1.GetWidget("/menubar2"))); + this.menubar2.HeightRequest = 25; + this.menubar2.Name = "menubar2"; + this.vbox1.Add(this.menubar2); + Gtk.Box.BoxChild w3 = ((Gtk.Box.BoxChild)(this.vbox1[this.menubar2])); + w3.Position = 0; + w3.Expand = false; + w3.Fill = false; + // Container child vbox1.Gtk.Box+BoxChild + this.hbox1 = new Gtk.HBox(); + this.hbox1.Name = "hbox1"; + // Container child hbox1.Gtk.Box+BoxChild + this.scrolledwindow1 = new Gtk.ScrolledWindow(); + this.scrolledwindow1.CanFocus = true; + this.scrolledwindow1.Name = "scrolledwindow1"; + this.scrolledwindow1.VscrollbarPolicy = ((Gtk.PolicyType)(1)); + this.scrolledwindow1.HscrollbarPolicy = ((Gtk.PolicyType)(1)); + // Container child scrolledwindow1.Gtk.Container+ContainerChild + Gtk.Viewport w4 = new Gtk.Viewport(); + w4.Name = "GtkViewport"; + w4.ShadowType = ((Gtk.ShadowType)(0)); + // Container child GtkViewport.Gtk.Container+ContainerChild + this.drawingarea1 = new Gtk.DrawingArea(); + this.drawingarea1.Name = "drawingarea1"; + w4.Add(this.drawingarea1); + this.scrolledwindow1.Add(w4); + this.hbox1.Add(this.scrolledwindow1); + Gtk.Box.BoxChild w7 = ((Gtk.Box.BoxChild)(this.hbox1[this.scrolledwindow1])); + w7.Position = 1; + // Container child hbox1.Gtk.Box+BoxChild + this.treeview1 = new Gtk.TreeView(); + this.treeview1.CanFocus = true; + this.treeview1.Name = "treeview1"; + this.hbox1.Add(this.treeview1); + Gtk.Box.BoxChild w8 = ((Gtk.Box.BoxChild)(this.hbox1[this.treeview1])); + w8.Position = 2; + this.vbox1.Add(this.hbox1); + Gtk.Box.BoxChild w9 = ((Gtk.Box.BoxChild)(this.vbox1[this.hbox1])); + w9.Position = 1; + // Container child vbox1.Gtk.Box+BoxChild + this.statusbar1 = new Gtk.Statusbar(); + this.statusbar1.Name = "statusbar1"; + this.statusbar1.Spacing = 5; + this.vbox1.Add(this.statusbar1); + Gtk.Box.BoxChild w10 = ((Gtk.Box.BoxChild)(this.vbox1[this.statusbar1])); + w10.PackType = ((Gtk.PackType)(1)); + w10.Position = 2; + w10.Expand = false; + w10.Fill = false; + this.Add(this.vbox1); + if ((this.Child != null)) { + this.Child.ShowAll(); + } + this.DefaultWidth = 800; + this.DefaultHeight = 800; + this.Show(); + this.DeleteEvent += new Gtk.DeleteEventHandler(this.OnDeleteEvent); + this.ConnectToGridserver.Activated += new System.EventHandler(this.ConnectToGridServerMenu); + this.ExitGridManager.Activated += new System.EventHandler(this.QuitMenu); + this.ShutdownGridserverOnly.Activated += new System.EventHandler(this.ShutdownGridserverMenu); + this.RestartGridserverOnly.Activated += new System.EventHandler(this.RestartGridserverMenu); + this.DisconnectFromGridServer.Activated += new System.EventHandler(this.DisconnectGridServerMenu); + } + } +} diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/generated.cs b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/generated.cs new file mode 100644 index 0000000000..a5cedc26aa --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/generated.cs @@ -0,0 +1,63 @@ +/* +* 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. +* +*/ + +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Mono Runtime Version: 2.0.50727.42 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +namespace Stetic { + + + internal class Gui { + + private static bool initialized; + + internal static void Initialize() { + if ((Stetic.Gui.initialized == false)) { + Stetic.Gui.initialized = true; + } + } + } + + internal class ActionGroups { + + public static Gtk.ActionGroup GetActionGroup(System.Type type) { + return Stetic.ActionGroups.GetActionGroup(type.FullName); + } + + public static Gtk.ActionGroup GetActionGroup(string name) { + return null; + } + } +} diff --git a/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/gui.stetic b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/gui.stetic new file mode 100644 index 0000000000..c883f08b63 --- /dev/null +++ b/trunk/OpenSim/Grid/Manager/OpenGridServices.Manager/gtk-gui/gui.stetic @@ -0,0 +1,502 @@ + + + + + + Action + <Alt><Mod2>g + False + Grid + Grid + + + Action + False + User + User + + + Action + False + Asset + Asset + + + Action + Region + Region + + + Action + Services + Services + + + Action + False + Connect to gridserver... + Connect to gridserver + gtk-connect + + + + Action + Restart whole grid + Restart whole grid + gtk-refresh + + + Action + Shutdown whole grid + Shutdown whole grid + gtk-stop + + + Action + Exit grid manager + Exit grid manager + gtk-close + + + + Action + Connect to userserver + Connect to userserver + gtk-connect + + + Action + Account managment + Account managment + gtk-properties + + + Action + Global notice + Global notice + gtk-network + + + Action + Disable all logins + Disable all logins + gtk-no + + + Action + Disable non-god users only + Disable non-god users only + gtk-no + + + Action + Shutdown user server + Shutdown user server + gtk-stop + + + Action + Shutdown gridserver only + Shutdown gridserver only + gtk-stop + + + + Action + Restart gridserver only + Restart gridserver only + gtk-refresh + + + + Action + Default local grid userserver + Default local grid userserver + + + Action + Custom userserver... + Custom userserver + + + Action + Remote grid default userserver... + Remote grid default userserver + + + Action + Disconnect from grid server + Disconnect from grid server + gtk-disconnect + False + + + + Action + Upload asset + Upload asset + + + Action + Asset management + Asset management + + + Action + Connect to asset server + Connect to asset server + + + Action + Connect to default asset server for grid + Connect to default asset server for grid + + + Action + Default for local grid + Default for local grid + + + Action + Default for remote grid... + Default for remote grid... + + + Action + Custom asset server... + Custom asset server... + + + + 800 + 600 + Open Grid Services Manager + stock:gtk-network Dialog + + + + + + + + 25 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + False + False + False + + + + + + + + + + + + True + Automatic + Automatic + + + + None + + + + + + + + + + 1 + True + + + + + + True + + + 2 + True + + + + + 1 + True + + + + + statusBar1 + 5 + + + + + + + + + End + 2 + False + False + False + + + + + + + + ButtonPressMask + Connect to Grid server + CenterOnParent + 2 + False + False + + + + + ButtonPressMask + 2 + + + + + + + + + + + + + + + + + + + 1 + Grid server URL: + Right + + + 0 + False + + + + + + True + http://gridserver:8001 + True + 255 + • + + + 1 + False + + + + + + + + 0 + True + False + False + + + + + + + + + 1 + Username: + Right + + + 0 + False + + + + + + True + True + • + + + 1 + True + + + + + + + + 1 + False + False + False + + + + + + + + + 1 + Password: + Right + + + 0 + False + + + + + + True + True + • + + + 1 + True + + + + + + + + 2 + True + False + False + + + + + 2 + True + False + False + + + + + 0 + True + + + + + + + + ButtonPressMask + 6 + 5 + 2 + End + + + + True + True + TextAndIcon + stock:gtk-apply Menu + Connect + True + True + -5 + + + False + False + + + + + + True + True + TextAndIcon + stock:gtk-cancel Menu + Cancel + True + True + -6 + + + 1 + False + False + + + + + + \ No newline at end of file diff --git a/trunk/OpenSim/Grid/MessagingServer/Main.cs b/trunk/OpenSim/Grid/MessagingServer/Main.cs new file mode 100644 index 0000000000..6ac70f022c --- /dev/null +++ b/trunk/OpenSim/Grid/MessagingServer/Main.cs @@ -0,0 +1,157 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; + +namespace OpenSim.Grid.MessagingServer +{ + /// + /// + public class OpenMessage_Main : BaseOpenSimServer, conscmd_callback + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private MessageServerConfig Cfg; + + //public UserManager m_userManager; + //public UserLoginService m_loginService; + + private LLUUID m_lastCreatedUser = LLUUID.Random(); + + [STAThread] + public static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + m_log.Info("Launching MessagingServer..."); + + OpenMessage_Main messageserver = new OpenMessage_Main(); + + messageserver.Startup(); + messageserver.Work(); + } + + private OpenMessage_Main() + { + m_console = new ConsoleBase("OpenMessage", this); + MainConsole.Instance = m_console; + } + + private void Work() + { + m_console.Notice("Enter help for a list of commands\n"); + + while (true) + { + m_console.Prompt(); + } + } + + public void Startup() + { + Cfg = new MessageServerConfig("MESSAGING SERVER", (Path.Combine(Util.configDir(), "MessagingServer_Config.xml"))); + + m_log.Info("[REGION]: Starting HTTP process"); + BaseHttpServer httpServer = new BaseHttpServer(Cfg.HttpPort); + + //httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod); + + //httpServer.AddXmlRPCHandler("get_user_by_name", m_userManager.XmlRPCGetUserMethodName); + //httpServer.AddXmlRPCHandler("get_user_by_uuid", m_userManager.XmlRPCGetUserMethodUUID); + //httpServer.AddXmlRPCHandler("get_avatar_picker_avatar", m_userManager.XmlRPCGetAvatarPickerAvatar); + //httpServer.AddXmlRPCHandler("add_new_user_friend", m_userManager.XmlRpcResponseXmlRPCAddUserFriend); + //httpServer.AddXmlRPCHandler("remove_user_friend", m_userManager.XmlRpcResponseXmlRPCRemoveUserFriend); + //httpServer.AddXmlRPCHandler("update_user_friend_perms", m_userManager.XmlRpcResponseXmlRPCUpdateUserFriendPerms); + //httpServer.AddXmlRPCHandler("get_user_friend_list", m_userManager.XmlRpcResponseXmlRPCGetUserFriendList); + + + //httpServer.AddStreamHandler( + //new RestStreamHandler("DELETE", "/usersessions/", m_userManager.RestDeleteUserSessionMethod)); + + httpServer.Start(); + m_log.Info("[SERVER]: Messageserver 0.5 - Startup complete"); + } + + public void do_create(string what) + { + switch (what) + { + case "user": + + try + { + //userID = + //m_userManager.AddUserProfile(tempfirstname, templastname, tempMD5Passwd, regX, regY); + } catch (Exception ex) + { + m_console.Error("[SERVER]: Error creating user: {0}", ex.ToString()); + } + + try + { + //RestObjectPoster.BeginPostObject(m_userManager._config.InventoryUrl + "CreateInventory/", + //userID.UUID); + } + catch (Exception ex) + { + m_console.Error("[SERVER]: Error creating inventory for user: {0}", ex.ToString()); + } + // m_lastCreatedUser = userID; + break; + } + } + + public override void RunCmd(string cmd, string[] cmdparams) + { + base.RunCmd(cmd, cmdparams); + + switch (cmd) + { + case "help": + m_console.Notice("shutdown - shutdown the message server (USE CAUTION!)"); + break; + + case "shutdown": + m_console.Close(); + Environment.Exit(0); + break; + } + } + + public void Show(string ShowWhat) + { + } + } +} diff --git a/trunk/OpenSim/Grid/MessagingServer/MessageService.cs b/trunk/OpenSim/Grid/MessagingServer/MessageService.cs new file mode 100644 index 0000000000..059a6b0932 --- /dev/null +++ b/trunk/OpenSim/Grid/MessagingServer/MessageService.cs @@ -0,0 +1,478 @@ +/* +* 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; +using System.Net; +using System.Net.Sockets; +using System.Collections; +using System.Collections.Generic; +//using System.Xml; +using libsecondlife; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Data; +using OpenSim.Framework.Servers; +using FriendRights = libsecondlife.FriendRights; + +namespace OpenSim.Grid.MessagingServer +{ + public class MessageService + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private MessageServerConfig m_cfg; + + //A hashtable of all current presences this server knows about + private Hashtable m_presences = new Hashtable(); + + //a hashtable of all current regions this server knows about + private Hashtable m_regionInfoCache = new Hashtable(); + + //A hashtable containing lists of UUIDs keyed by UUID for fast backreferencing + private Hashtable m_presence_BackReferences = new Hashtable(); + + // Hashtable containing work units that need to be processed + private Hashtable m_unProcessedWorkUnits = new Hashtable(); + + public MessageService(MessageServerConfig cfg) + { + m_cfg = cfg; + } + + #region RegionComms Methods + + /// + /// Informs a region about an Agent + /// + /// User to talk about + /// User we're sending this too (contains the region) + public void SendRegionPresenceUpdate(UserPresenceData TalkingAbout, UserPresenceData UserToUpdate) + { + // TODO: Fill in pertenant Presence Data from 'TalkingAbout' + + RegionProfileData whichRegion = UserToUpdate.regionData; + //whichRegion.httpServerURI + + Hashtable PresenceParams = new Hashtable(); + ArrayList SendParams = new ArrayList(); + SendParams.Add(PresenceParams); + + m_log.Info("[PRESENCE]: Informing " + whichRegion.regionName + " at " + whichRegion.httpServerURI); + // Send + XmlRpcRequest RegionReq = new XmlRpcRequest("presence_update", SendParams); + XmlRpcResponse RegionResp = RegionReq.Send(whichRegion.httpServerURI, 6000); + } + + + #endregion + + #region FriendList Methods + + + /// + /// Process Friendlist subscriptions for a user + /// The login method calls this for a User + /// + /// The Agent we're processing the friendlist subscriptions + public void ProcessFriendListSubscriptions(UserPresenceData userpresence) + { + List uFriendList = userpresence.friendData; + for (int i = 0; i < uFriendList.Count; i++) + { + m_presence_BackReferences.Add(userpresence.agentData.AgentID, uFriendList[i].Friend); + m_presence_BackReferences.Add(uFriendList[i].Friend, userpresence.agentData.AgentID); + + if (m_presences.Contains(uFriendList[i].Friend)) + { + UserPresenceData friendup = (UserPresenceData)m_presences[uFriendList[i]]; + // Add backreference + + SubscribeToPresenceUpdates(userpresence, friendup, uFriendList[i],i); + } + } + + m_presences.Add(userpresence.agentData.AgentID, userpresence); + } + + /// + /// Does the necessary work to subscribe one agent to another's presence notifications + /// Gets called by ProcessFriendListSubscriptions. You shouldn't call this directly + /// unless you know what you're doing + /// + /// P1 + /// P2 + /// + /// + public void SubscribeToPresenceUpdates(UserPresenceData userpresence, UserPresenceData friendpresence, + FriendListItem uFriendListItem, int uFriendListIndex) + { + + if ((uFriendListItem.FriendListOwnerPerms & (uint)FriendRights.CanSeeOnline) != 0) + { + // Subscribe and Send Out updates + if (!friendpresence.subscriptionData.Contains(friendpresence.agentData.AgentID)) + { + userpresence.subscriptionData.Add(friendpresence.agentData.AgentID); + //Send Region Notice.... + + } + else + { + // we need to send out online status update, but the user is already subscribed + + } + SendRegionPresenceUpdate(friendpresence, userpresence); + } + if ((uFriendListItem.FriendPerms & (uint)FriendRights.CanSeeOnline) != 0) + { + if (!friendpresence.subscriptionData.Contains(userpresence.agentData.AgentID)) + { + friendpresence.subscriptionData.Add(userpresence.agentData.AgentID); + //Send Region Notice.... + } + else + { + // we need to send out online status update, but the user is already subscribed + + } + SendRegionPresenceUpdate(userpresence, friendpresence); + } + + } + + + /// + /// Adds a backreference so presence specific data doesn't have to be + /// enumerated for each logged in user every time someone logs on or off. + /// + /// + /// + public void addBackReference(LLUUID agentID, LLUUID friendID) + { + if (m_presence_BackReferences.Contains(friendID)) + { + List presenseBackReferences = (List)m_presence_BackReferences[friendID]; + if (!presenseBackReferences.Contains(agentID)) + { + presenseBackReferences.Add(agentID); + } + m_presence_BackReferences[friendID] = presenseBackReferences; + } + else + { + List presenceBackReferences = new List(); + presenceBackReferences.Add(agentID); + m_presence_BackReferences[friendID] = presenceBackReferences; + } + } + + /// + /// Removes a backreference to free up some memory + /// + /// + /// + public void removeBackReference(LLUUID agentID, LLUUID friendID) + { + if (m_presence_BackReferences.Contains(friendID)) + { + List presenseBackReferences = (List)m_presence_BackReferences[friendID]; + if (presenseBackReferences.Contains(agentID)) + { + presenseBackReferences.Remove(agentID); + } + + // If there are no more backreferences for this agent, + // remove it to free up memory. + if (presenseBackReferences.Count == 0) + { + m_presence_BackReferences.Remove(agentID); + } + } + } + /// + /// Logoff Processor. Call this to clean up agent presence data and send logoff presence notifications + /// + /// + private void ProcessLogOff(LLUUID AgentID) + { + if (m_presences.Contains(AgentID)) + { + UserPresenceData AgentData = (UserPresenceData)m_presences[AgentID]; + + if (m_presence_BackReferences.Contains(AgentID)) + { + List AgentsNeedingNotification = (List)m_presence_BackReferences[AgentID]; + for (int i = 0; i < AgentsNeedingNotification.Count; i++) + { + // TODO: Do Region Notifications + if (m_presences.Contains(AgentsNeedingNotification[i])) + { + UserPresenceData friendd = (UserPresenceData)m_presences[AgentsNeedingNotification[i]]; + + // This might need to be enumerated and checked before we try to remove it. + friendd.subscriptionData.Remove(AgentID); + + List fl = friendd.friendData; + for (int j = 0; j < fl.Count; j++) + { + if (fl[j].Friend == AgentID) + { + fl[j].onlinestatus = false; + } + + } + friendd.friendData = fl; + + SendRegionPresenceUpdate(AgentData, friendd); + + } + removeBackReference(AgentID, AgentsNeedingNotification[i]); + + } + } + } + } + + + #endregion + + #region UserServer Comms + + /// + /// Returns a list of FriendsListItems that describe the friends and permissions in the friend relationship for LLUUID friendslistowner + /// + /// The agent that we're retreiving the friends Data. + public List GetUserFriendList(LLUUID friendlistowner) + { + List buddylist = new List(); + + try + { + Hashtable param = new Hashtable(); + param["ownerID"] = friendlistowner.UUID.ToString(); + + IList parameters = new ArrayList(); + parameters.Add(param); + XmlRpcRequest req = new XmlRpcRequest("get_user_friend_list", parameters); + XmlRpcResponse resp = req.Send(m_cfg.UserServerURL, 3000); + Hashtable respData = (Hashtable)resp.Value; + + if (respData.Contains("avcount")) + { + buddylist = ConvertXMLRPCDataToFriendListItemList(respData); + } + + } + catch (WebException e) + { + m_log.Warn("Error when trying to fetch Avatar's friends list: " + + e.Message); + // Return Empty list (no friends) + } + return buddylist; + + } + + /// + /// Converts XMLRPC Friend List to FriendListItem Object + /// + /// XMLRPC response data Hashtable + /// + public List ConvertXMLRPCDataToFriendListItemList(Hashtable data) + { + List buddylist = new List(); + int buddycount = Convert.ToInt32((string)data["avcount"]); + + + for (int i = 0; i < buddycount; i++) + { + FriendListItem buddylistitem = new FriendListItem(); + + buddylistitem.FriendListOwner = new LLUUID((string)data["ownerID" + i.ToString()]); + buddylistitem.Friend = new LLUUID((string)data["friendID" + i.ToString()]); + buddylistitem.FriendListOwnerPerms = (uint)Convert.ToInt32((string)data["ownerPerms" + i.ToString()]); + buddylistitem.FriendPerms = (uint)Convert.ToInt32((string)data["friendPerms" + i.ToString()]); + + buddylist.Add(buddylistitem); + } + + + return buddylist; + } + /// + /// UserServer sends an expect_user method + /// this handles the method and provisions the + /// necessary info for presence to work + /// + /// UserServer Data + /// + public XmlRpcResponse UserLoggedOn(XmlRpcRequest request) + { + + Hashtable requestData = (Hashtable)request.Params[0]; + AgentCircuitData agentData = new AgentCircuitData(); + agentData.SessionID = new LLUUID((string)requestData["session_id"]); + agentData.SecureSessionID = new LLUUID((string)requestData["secure_session_id"]); + agentData.firstname = (string)requestData["firstname"]; + agentData.lastname = (string)requestData["lastname"]; + agentData.AgentID = new LLUUID((string)requestData["agent_id"]); + agentData.circuitcode = Convert.ToUInt32(requestData["circuit_code"]); + agentData.CapsPath = (string)requestData["caps_path"]; + + if (requestData.ContainsKey("child_agent") && requestData["child_agent"].Equals("1")) + { + agentData.child = true; + } + else + { + agentData.startpos = + new LLVector3(Convert.ToUInt32(requestData["startpos_x"]), + Convert.ToUInt32(requestData["startpos_y"]), + Convert.ToUInt32(requestData["startpos_z"])); + agentData.child = false; + } + + ulong regionHandle = Convert.ToUInt64((string)requestData["regionhandle"]); + + UserPresenceData up = new UserPresenceData(); + up.agentData = agentData; + List flData = GetUserFriendList(agentData.AgentID); + up.friendData = flData; + RegionProfileData riData = GetRegionInfo(regionHandle); + up.regionData = riData; + + ProcessFriendListSubscriptions(up); + + + return new XmlRpcResponse(); + } + + /// + /// The UserServer got a Logoff message + /// Cleanup time for that user. Send out presence notifications + /// + /// + /// + public XmlRpcResponse UserLoggedOff(XmlRpcRequest request) + { + + Hashtable requestData = (Hashtable)request.Params[0]; + + LLUUID AgentID = new LLUUID((string)requestData["agent_id"]); + + + //ProcessLogOff(AgentID); + + + return new XmlRpcResponse(); + } + + #endregion + #region regioninfo gathering + + /// + /// Gets and caches a RegionInfo object from the gridserver based on regionhandle + /// if the regionhandle is already cached, use the cached values + /// + /// handle to the XY of the region we're looking for + /// A RegionInfo object to stick in the presence info + public RegionProfileData GetRegionInfo(ulong regionhandle) + { + RegionProfileData regionInfo = null; + if (m_regionInfoCache.Contains(regionhandle)) + { + regionInfo = (RegionProfileData)m_regionInfoCache[regionhandle]; + } + else + { + regionInfo = RequestRegionInfo(regionhandle); + } + return regionInfo; + } + /// + /// Get RegionProfileData from the GridServer + /// We'll Cache this information and use it for presence updates + /// + /// + /// + public RegionProfileData RequestRegionInfo(ulong regionHandle) + { RegionProfileData regionProfile = null; + try + { + + Hashtable requestData = new Hashtable(); + requestData["region_handle"] = regionHandle.ToString(); + requestData["authkey"] = m_cfg.GridSendKey; + ArrayList SendParams = new ArrayList(); + SendParams.Add(requestData); + XmlRpcRequest GridReq = new XmlRpcRequest("simulator_data_request", SendParams); + XmlRpcResponse GridResp = GridReq.Send(m_cfg.GridServerURL, 3000); + + Hashtable responseData = (Hashtable)GridResp.Value; + + if (responseData.ContainsKey("error")) + { + m_log.Error("[GRID]: error received from grid server" + responseData["error"]); + return null; + } + + uint regX = Convert.ToUInt32((string)responseData["region_locx"]); + uint regY = Convert.ToUInt32((string)responseData["region_locy"]); + string internalIpStr = (string)responseData["sim_ip"]; + uint port = Convert.ToUInt32(responseData["sim_port"]); + string externalUri = (string)responseData["sim_uri"]; + string neighbourExternalUri = externalUri; + + regionProfile = new RegionProfileData(); + regionProfile.httpPort = (uint)Convert.ToInt32((string)responseData["http_port"]); + regionProfile.httpServerURI = "http://" + internalIpStr + ":" + regionProfile.httpPort + "/"; + regionProfile.regionHandle = Helpers.UIntsToLong((regX * Constants.RegionSize), (regY * Constants.RegionSize)); + regionProfile.regionLocX = regX; + regionProfile.regionLocY = regY; + + regionProfile.remotingPort = Convert.ToUInt32((string)responseData["remoting_port"]); + regionProfile.UUID = new LLUUID((string)responseData["region_UUID"]); + regionProfile.regionName = (string)responseData["region_name"]; + + m_regionInfoCache.Add(regionHandle, regionProfile); + } + catch (WebException) + { + m_log.Error("[GRID]: " + + "Region lookup failed for: " + regionHandle.ToString() + + " - Is the GridServer down?"); + return null; + } + + + return regionProfile; + } + #endregion + } + +} diff --git a/trunk/OpenSim/Grid/MessagingServer/UserPresenceData.cs b/trunk/OpenSim/Grid/MessagingServer/UserPresenceData.cs new file mode 100644 index 0000000000..5470d32713 --- /dev/null +++ b/trunk/OpenSim/Grid/MessagingServer/UserPresenceData.cs @@ -0,0 +1,53 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Data; + + +namespace OpenSim.Grid.MessagingServer +{ + public class UserPresenceData + { + public AgentCircuitData agentData = new AgentCircuitData(); + public RegionProfileData regionData = new RegionProfileData(); + public string httpURI = String.Empty; + public List friendData = new List (); + public List subscriptionData = new List(); + + public UserPresenceData() + { + + + } + + } +} diff --git a/trunk/OpenSim/Grid/MessagingServer/WorkUnitBase.cs b/trunk/OpenSim/Grid/MessagingServer/WorkUnitBase.cs new file mode 100644 index 0000000000..67a535ff13 --- /dev/null +++ b/trunk/OpenSim/Grid/MessagingServer/WorkUnitBase.cs @@ -0,0 +1,37 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Grid.MessagingServer +{ + public class WorkUnitBase + { + } +} diff --git a/trunk/OpenSim/Grid/MessagingServer/WorkUnitPresenceUpdate.cs b/trunk/OpenSim/Grid/MessagingServer/WorkUnitPresenceUpdate.cs new file mode 100644 index 0000000000..9a729c2274 --- /dev/null +++ b/trunk/OpenSim/Grid/MessagingServer/WorkUnitPresenceUpdate.cs @@ -0,0 +1,37 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Grid.MessagingServer +{ + public class WorkUnitPresenceUpdate : WorkUnitBase + { + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/Common/Executor.cs b/trunk/OpenSim/Grid/ScriptEngine/Common/Executor.cs new file mode 100644 index 0000000000..495c26703d --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/Common/Executor.cs @@ -0,0 +1,139 @@ +/* +* 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; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.Remoting.Lifetime; + +namespace OpenSim.Grid.ScriptEngine.Common +{ + public class Executor : MarshalByRefObject + { + // Private instance for each script + + private IScript m_Script; + private Dictionary Events = new Dictionary(); + private bool m_Running = true; + //private List Scripts = new List(); + + public Executor(IScript Script) + { + m_Script = Script; + } + + // Object never expires + public override Object InitializeLifetimeService() + { + //Console.WriteLine("Executor: InitializeLifetimeService()"); + // return null; + ILease lease = (ILease) base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); +// lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); +// lease.RenewOnCallTime = TimeSpan.FromSeconds(2); + } + return lease; + } + + public AppDomain GetAppDomain() + { + return AppDomain.CurrentDomain; + } + + public void ExecuteEvent(string FunctionName, object[] args) + { + // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. + // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! + //try + //{ + if (m_Running == false) + { + // Script is inactive, do not execute! + return; + } + + string EventName = m_Script.State() + "_event_" + FunctionName; + + //type.InvokeMember(EventName, BindingFlags.InvokeMethod, null, m_Script, args); + + //Console.WriteLine("ScriptEngine Executor.ExecuteEvent: \"" + EventName + "\""); + + if (Events.ContainsKey(EventName) == false) + { + // Not found, create + Type type = m_Script.GetType(); + try + { + MethodInfo mi = type.GetMethod(EventName); + Events.Add(EventName, mi); + } + catch + { + // Event name not found, cache it as not found + Events.Add(EventName, null); + } + } + + // Get event + MethodInfo ev = null; + Events.TryGetValue(EventName, out ev); + + if (ev == null) // No event by that name! + { + //Console.WriteLine("ScriptEngine Can not find any event named: \"" + EventName + "\""); + return; + } + + // Found + //try + //{ + // Invoke it + ev.Invoke(m_Script, args); + + //} + //catch (Exception e) + //{ + // // TODO: Send to correct place + // Console.WriteLine("ScriptEngine Exception attempting to executing script function: " + e.ToString()); + //} + + + //} + //catch { } + } + + + public void StopScript() + { + m_Running = false; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/Common/IScript.cs b/trunk/OpenSim/Grid/ScriptEngine/Common/IScript.cs new file mode 100644 index 0000000000..eb8205b9aa --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/Common/IScript.cs @@ -0,0 +1,36 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Grid.ScriptEngine.Common +{ + public interface IScript + { + string State(); + Executor Exec { get; } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs b/trunk/OpenSim/Grid/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs new file mode 100644 index 0000000000..d4f698f495 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs @@ -0,0 +1,636 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System.Collections.Generic; + +namespace OpenSim.Grid.ScriptEngine.Common +{ + public interface LSL_BuiltIn_Commands_Interface + { + string State(); + + double llSin(double f); + double llCos(double f); + double llTan(double f); + double llAtan2(double x, double y); + double llSqrt(double f); + double llPow(double fbase, double fexponent); + int llAbs(int i); + double llFabs(double f); + double llFrand(double mag); + int llFloor(double f); + int llCeil(double f); + int llRound(double f); + double llVecMag(LSL_Types.Vector3 v); + LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v); + double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b); + LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r); + LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v); + LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up); + LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r); + LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r); + LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r); + LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 start, LSL_Types.Vector3 end); + void llWhisper(int channelID, string text); + //void llSay(int channelID, string text); + void llSay(int channelID, string text); + void llShout(int channelID, string text); + int llListen(int channelID, string name, string ID, string msg); + void llListenControl(int number, int active); + void llListenRemove(int number); + void llSensor(string name, string id, int type, double range, double arc); + void llSensorRepeat(string name, string id, int type, double range, double arc, double rate); + void llSensorRemove(); + string llDetectedName(int number); + string llDetectedKey(int number); + string llDetectedOwner(int number); + int llDetectedType(int number); + LSL_Types.Vector3 llDetectedPos(int number); + LSL_Types.Vector3 llDetectedVel(int number); + LSL_Types.Vector3 llDetectedGrab(int number); + LSL_Types.Quaternion llDetectedRot(int number); + int llDetectedGroup(int number); + int llDetectedLinkNumber(int number); + void llDie(); + double llGround(LSL_Types.Vector3 offset); + double llCloud(LSL_Types.Vector3 offset); + LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset); + void llSetStatus(int status, int value); + int llGetStatus(int status); + void llSetScale(LSL_Types.Vector3 scale); + LSL_Types.Vector3 llGetScale(); + void llSetColor(LSL_Types.Vector3 color, int face); + double llGetAlpha(int face); + void llSetAlpha(double alpha, int face); + LSL_Types.Vector3 llGetColor(int face); + void llSetTexture(string texture, int face); + void llScaleTexture(double u, double v, int face); + void llOffsetTexture(double u, double v, int face); + void llRotateTexture(double rotation, int face); + string llGetTexture(int face); + void llSetPos(LSL_Types.Vector3 pos); + + //wiki: vector llGetPos() + LSL_Types.Vector3 llGetPos(); + //wiki: vector llGetLocalPos() + LSL_Types.Vector3 llGetLocalPos(); + //wiki: llSetRot(rotation rot) + void llSetRot(LSL_Types.Quaternion rot); + //wiki: rotation llGetRot() + LSL_Types.Quaternion llGetRot(); + //wiki: rotation llGetLocalRot() + LSL_Types.Quaternion llGetLocalRot(); + //wiki: llSetForce(vector force, integer local) + void llSetForce(LSL_Types.Vector3 force, int local); + //wiki: vector llGetForce() + LSL_Types.Vector3 llGetForce(); + //wiki: integer llTarget(vector position, double range) + int llTarget(LSL_Types.Vector3 position, double range); + //wiki: llTargetRemove(integer number) + void llTargetRemove(int number); + //wiki: integer llRotTarget(rotation rot, double error) + int llRotTarget(LSL_Types.Quaternion rot, double error); + //wiki: integer llRotTargetRemove(integer number) + void llRotTargetRemove(int number); + //wiki: llMoveToTarget(vector target, double tau) + void llMoveToTarget(LSL_Types.Vector3 target, double tau); + //wiki: llStopMoveToTarget() + void llStopMoveToTarget(); + //wiki: llApplyImpulse(vector force, integer local) + void llApplyImpulse(LSL_Types.Vector3 force, int local); + //wiki: llapplyRotationalImpulse(vector force, integer local) + void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local); + //wiki: llSetTorque(vector torque, integer local) + void llSetTorque(LSL_Types.Vector3 torque, int local); + //wiki: vector llGetTorque() + LSL_Types.Vector3 llGetTorque(); + //wiki: llSeForceAndTorque(vector force, vector torque, integer local) + void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local); + //wiki: vector llGetVel() + LSL_Types.Vector3 llGetVel(); + //wiki: vector llGetAccel() + LSL_Types.Vector3 llGetAccel(); + //wiki: vector llGetOmega() + LSL_Types.Vector3 llGetOmega(); + //wiki: double llGetTimeOfDay() + double llGetTimeOfDay(); + //wiki: double llGetWallclock() + double llGetWallclock(); + //wiki: double llGetTime() + double llGetTime(); + //wiki: llResetTime() + void llResetTime(); + //wiki: double llGetAndResetTime() + double llGetAndResetTime(); + //wiki (deprecated) llSound(string sound, double volume, integer queue, integer loop) + void llSound(); + //wiki: llPlaySound(string sound, double volume) + void llPlaySound(string sound, double volume); + //wiki: llLoopSound(string sound, double volume) + void llLoopSound(string sound, double volume); + //wiki: llLoopSoundMaster(string sound, double volume) + void llLoopSoundMaster(string sound, double volume); + //wiki: llLoopSoundSlave(string sound, double volume) + void llLoopSoundSlave(string sound, double volume); + //wiki llPlaySoundSlave(string sound, double volume) + void llPlaySoundSlave(string sound, double volume); + //wiki: llTriggerSound(string sound, double volume) + void llTriggerSound(string sound, double volume); + //wiki: llStopSound() + void llStopSound(); + //wiki: llPreloadSound(string sound) + void llPreloadSound(string sound); + //wiki: string llGetSubString(string src, integer start, integer end) + string llGetSubString(string src, int start, int end); + //wiki: string llDeleteSubString(string src, integer start, integer end) + string llDeleteSubString(string src, int start, int end); + //wiki string llInsertString(string dst, integer position, string src) + string llInsertString(string dst, int position, string src); + //wiki: string llToUpper(string source) + string llToUpper(string source); + //wiki: string llToLower(string source) + string llToLower(string source); + //wiki: integer llGiveMoney(key destination, integer amount) + int llGiveMoney(string destination, int amount); + //wiki: (deprecated) + void llMakeExplosion(); + //wiki: (deprecated) + void llMakeFountain(); + //wiki: (deprecated) + void llMakeSmoke(); + //wiki: (deprecated) + void llMakeFire(); + //wiki: llRezObject(string inventory, vector pos, vector rel, rotation rot, integer param) + void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Quaternion rot, int param); + //wiki: llLookAt(vector target, double strength, double damping) + void llLookAt(LSL_Types.Vector3 target, double strength, double damping); + //wiki: llStopLookAt() + void llStopLookAt(); + //wiki: llSetTimerEvent(double sec) + void llSetTimerEvent(double sec); + //wiki: llSleep(double sec) + void llSleep(double sec); + //wiki: double llGetMass() + double llGetMass(); + //wiki: llCollisionFilter(string name, key id, integer accept) + void llCollisionFilter(string name, string id, int accept); + //wiki: llTakeControls(integer controls, integer accept, integer pass_on) + void llTakeControls(int controls, int accept, int pass_on); + //wiki: llReleaseControls() + void llReleaseControls(); + //wiki: llAttachToAvatar(integer attachment) + void llAttachToAvatar(int attachment); + //wiki: llDetachFromAvatar() + void llDetachFromAvatar(); + //wiki: (deprecated) llTakeCamera() + void llTakeCamera(); + //wiki: (deprecated) llReleaseCamera() + void llReleaseCamera(); + //wiki: key llGetOwner() + string llGetOwner(); + //wiki: llInstantMessage(key user, string message) + void llInstantMessage(string user, string message); + //wiki: llEmail(string address, string subject, string message) + void llEmail(string address, string subject, string message); + //wiki: llGetNextEmail(string address, string subject) + void llGetNextEmail(string address, string subject); + //wiki: key llGetKey() + string llGetKey(); + //wiki: llSetBuoyancy(double buoyancy) + void llSetBuoyancy(double buoyancy); + //wiki: llSetHoverHeight(double height, integer water, double tau) + void llSetHoverHeight(double height, int water, double tau); + //wiki: llStopHover + void llStopHover(); + //wiki: llMinEventDelay(double delay) + void llMinEventDelay(double delay); + //wiki: (deprecated) llSoundPreload() + void llSoundPreload(); + //wiki: llRotLookAt(rotation target, double strength, double damping) + void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping); + //wiki: integer llStringLength(string str) + int llStringLength(string str); + //wiki: llStartAnimation(string anim) + void llStartAnimation(string anim); + //wiki: llStopAnimation(string anim) + void llStopAnimation(string anim); + //wiki: (deprecated) llPointAt + void llPointAt(); + //wiki: (deprecated) llStopPointAt + void llStopPointAt(); + //wiki: llTargetOmega(vector axis, double spinrate, double gain) + void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain); + //wiki: integer llGetStartParameter() + int llGetStartParameter(); + //wiki: llGodLikeRezObject(key inventory, vector pos) + void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos); + //wiki: llRequestPermissions(key agent, integer perm) + void llRequestPermissions(string agent, int perm); + //wiki: key llGetPermissionsKey() + string llGetPermissionsKey(); + //wiki: integer llGetPermissions() + int llGetPermissions(); + //wiki integer llGetLinkNumber() + int llGetLinkNumber(); + //wiki: llSetLinkColor(integer linknumber, vector color, integer face) + void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face); + //wiki: llCreateLink(key target, integer parent) + void llCreateLink(string target, int parent); + //wiki: llBreakLink(integer linknum) + void llBreakLink(int linknum); + //wiki: llBreakAllLinks() + void llBreakAllLinks(); + //wiki: key llGetLinkKey(integer linknum) + string llGetLinkKey(int linknum); + //wiki: llGetLinkName(integer linknum) + void llGetLinkName(int linknum); + //wiki: integer llGetInventoryNumber(integer type) + int llGetInventoryNumber(int type); + //wiki: string llGetInventoryName(integer type, integer number) + string llGetInventoryName(int type, int number); + //wiki: llSetScriptState(string name, integer run) + void llSetScriptState(string name, int run); + //wiki: double llGetEnergy() + double llGetEnergy(); + //wiki: llGiveInventory(key destination, string inventory) + void llGiveInventory(string destination, string inventory); + //wiki: llRemoveInventory(string item) + void llRemoveInventory(string item); + //wiki: llSetText(string text, vector color, double alpha) + void llSetText(string text, LSL_Types.Vector3 color, double alpha); + //wiki: double llWater(vector offset) + double llWater(LSL_Types.Vector3 offset); + //wiki: llPassTouches(integer pass) + void llPassTouches(int pass); + //wiki: key llRequestAgentData(key id, integer data) + string llRequestAgentData(string id, int data); + //wiki: key llRequestInventoryData(string name) + string llRequestInventoryData(string name); + //wiki: llSetDamage(double damage) + void llSetDamage(double damage); + //wiki: llTeleportAgentHome(key agent) + void llTeleportAgentHome(string agent); + //wiki: llModifyLand(integer action, integer brush) + void llModifyLand(int action, int brush); + //wiki: llCollisionSound(string impact_sound, double impact_volume) + void llCollisionSound(string impact_sound, double impact_volume); + //wiki: llCollisionSprite(string impact_sprite) + void llCollisionSprite(string impact_sprite); + //wiki: string llGetAnimation(key id) + string llGetAnimation(string id); + //wiki: llResetScript() + void llResetScript(); + //wiki: llMessageLinked(integer linknum, integer num, string str, key id) + void llMessageLinked(int linknum, int num, string str, string id); + //wiki: llPushObject(key target, vector impulse, vector ang_impulse, integer local) + void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local); + //wiki: llPassCollisions(integer pass) + void llPassCollisions(int pass); + //wiki: string llGetScriptName() + string llGetScriptName(); + //wiki: integer llGetNumberOfSides() + int llGetNumberOfSides(); + //wiki: rotation llAxisAngle2Rot(vector axis, double angle) + LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle); + //wiki: vector llRot2Axis(rotation rot) + LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot); + void llRot2Angle(); + //wiki: double llAcos(double val) + double llAcos(double val); + //wiki: double llAsin(double val) + double llAsin(double val); + //wiki: double llAngleBetween(rotation a, rotation b) + double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b); + //wiki: string llGetInventoryKey(string name) + string llGetInventoryKey(string name); + //wiki: llAllowInventoryDrop(integer add) + void llAllowInventoryDrop(int add); + //wiki: vector llGetSunDirection() + LSL_Types.Vector3 llGetSunDirection(); + //wiki: vector llGetTextureOffset(integer face) + LSL_Types.Vector3 llGetTextureOffset(int face); + //wiki: vector llGetTextureScale(integer side) + LSL_Types.Vector3 llGetTextureScale(int side); + //wiki: double llGetTextureRot(integer side) + double llGetTextureRot(int side); + //wiki: integer llSubStringIndex(string source, string pattern) + int llSubStringIndex(string source, string pattern); + //wiki: key llGetOwnerKey(key id) + string llGetOwnerKey(string id); + //wiki: vector llGetCenterOfMass() + LSL_Types.Vector3 llGetCenterOfMass(); + //wiki: list llListSort(list src, integer stride, integer ascending) + List llListSort(List src, int stride, int ascending); + //integer llGetListLength(list src) + int llGetListLength(List src); + //wiki: integer llList2Integer(list src, integer index) + int llList2Integer(List src, int index); + //wiki: double llList2double(list src, integer index) + double llList2double(List src, int index); + //wiki: string llList2String(list src, integer index) + string llList2String(List src, int index); + //wiki: key llList2Key(list src, integer index) + string llList2Key(List src, int index); + //wiki: vector llList2Vector(list src, integer index) + LSL_Types.Vector3 llList2Vector(List src, int index); + //wiki rotation llList2Rot(list src, integer index) + LSL_Types.Quaternion llList2Rot(List src, int index); + //wiki: list llList2List(list src, integer start, integer end) + List llList2List(List src, int start, int end); + //wiki: llDeleteSubList(list src, integer start, integer end) + List llDeleteSubList(List src, int start, int end); + //wiki: integer llGetListEntryType( list src, integer index ) + int llGetListEntryType(List src, int index); + //wiki: string llList2CSV( list src ) + string llList2CSV(List src); + //wiki: list llCSV2List( string src ) + List llCSV2List(string src); + //wiki: list llListRandomize( list src, integer stride ) + List llListRandomize(List src, int stride); + //wiki: list llList2ListStrided( list src, integer start, integer end, integer stride ) + List llList2ListStrided(List src, int start, int end, int stride); + //wiki: vector llGetRegionCorner( ) + LSL_Types.Vector3 llGetRegionCorner(); + //wiki: list llListInsertList( list dest, list src, integer start ) + List llListInsertList(List dest, List src, int start); + //wiki: integer llListFindList( list src, list test ) + int llListFindList(List src, List test); + //wiki: string llGetObjectName() + string llGetObjectName(); + //wiki: llSetObjectName(string name) + void llSetObjectName(string name); + //wiki: string llGetDate() + string llGetDate(); + //wiki: integer llEdgeOfWorld(vector pos, vector dir) + int llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir); + //wiki: integer llGetAgentInfo(key id) + int llGetAgentInfo(string id); + //wiki: llAdjustSoundVolume(double volume) + void llAdjustSoundVolume(double volume); + //wiki: llSetSoundQueueing(integer queue) + void llSetSoundQueueing(int queue); + //wiki: llSetSoundRadius(double radius) + void llSetSoundRadius(double radius); + //wiki: string llKey2Name(key id) + string llKey2Name(string id); + //wiki: llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, double start, double length, double rate) + void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate); + //wiki: llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west) + void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east, + LSL_Types.Vector3 bottom_south_west); + + //wiki: llEjectFromLand(key pest) + void llEjectFromLand(string pest); + void llParseString2List(); + //wiki: integer llOverMyLand(key id) + int llOverMyLand(string id); + //wiki: key llGetLandOwnerAt(vector pos) + string llGetLandOwnerAt(LSL_Types.Vector3 pos); + //wiki: key llGetNotecardLine(string name, integer line) + string llGetNotecardLine(string name, int line); + //wiki: vector llGetAgentSize(key id) + LSL_Types.Vector3 llGetAgentSize(string id); + //wiki: integer llSameGroup(key agent) + int llSameGroup(string agent); + //wiki: llUnSit(key id) + void llUnSit(string id); + //wiki: vector llGroundSlope(vector offset) + LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset); + //wiki: vector llGroundNormal(vector offset) + LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset); + //wiki: vector llGroundContour(vector offset) + LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset); + //wiki: integer llGetAttached() + int llGetAttached(); + //wiki: integer llGetFreeMemory() + int llGetFreeMemory(); + //wiki: string llGetRegionName() + string llGetRegionName(); + //wiki: double llGetRegionTimeDilation() + double llGetRegionTimeDilation(); + //wiki: double llGetRegionFPS() + double llGetRegionFPS(); + //wiki: llParticleSystem(List rules + void llParticleSystem(List rules); + //wiki: llGroundRepel(double height, integer water, double tau) + void llGroundRepel(double height, int water, double tau); + void llGiveInventoryList(); + //wiki: llSetVehicleType(integer type) + void llSetVehicleType(int type); + //wiki: llSetVehicledoubleParam(integer param, double value) + void llSetVehicledoubleParam(int param, double value); + //wiki: llSetVehicleVectorParam(integer param, vector vec) + void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec); + //wiki: llSetVehicleRotationParam(integer param, rotation rot) + void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot); + //wiki: llSetVehicleFlags(integer flags) + void llSetVehicleFlags(int flags); + //wiki: llRemoveVehicleFlags(integer flags) + void llRemoveVehicleFlags(int flags); + //wiki: llSitTarget(vector offset, rotation rot) + void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot); + //wiki key llAvatarOnSitTarget() + string llAvatarOnSitTarget(); + //wiki: llAddToLandPassList(key avatar, double hours) + void llAddToLandPassList(string avatar, double hours); + //wiki: llSetTouchText(string text) + void llSetTouchText(string text); + //wiki: llSetSitText(string text) + void llSetSitText(string text); + //wiki: llSetCameraEyeOffset(vector offset) + void llSetCameraEyeOffset(LSL_Types.Vector3 offset); + //wiki: llSeteCameraAtOffset(vector offset) + void llSetCameraAtOffset(LSL_Types.Vector3 offset); + void llDumpList2String(); + //wiki: integer llScriptDanger(vector pos) + void llScriptDanger(LSL_Types.Vector3 pos); + //wiki: llDialog( key avatar, string message, list buttons, integer chat_channel ) + void llDialog(string avatar, string message, List buttons, int chat_channel); + //wiki: llVolumeDetect(integer detect) + void llVolumeDetect(int detect); + //wiki: llResetOtherScript(string name) + void llResetOtherScript(string name); + //wiki: integer llGetScriptState(string name) + int llGetScriptState(string name); + //wiki: (deprecated) + void llRemoteLoadScript(); + //wiki: llSetRemoteScriptAccessPin(integer pin) + void llSetRemoteScriptAccessPin(int pin); + //wiki: llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param) + void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param); + //wiki: llOpenRemoteDataChannel() + void llOpenRemoteDataChannel(); + //wiki: key llSendRemoteData(key channel, string dest, integer idata, string sdata) + string llSendRemoteData(string channel, string dest, int idata, string sdata); + //wiki: llRemoteDataReply(key channel, key message_id, string sdata, integer idata) + void llRemoteDataReply(string channel, string message_id, string sdata, int idata); + //wiki: llCloseRemoteDataChannel(key channel) + void llCloseRemoteDataChannel(string channel); + //wiki: string llMD5String(string src, integer nonce) + string llMD5String(string src, int nonce); + //wiki: llSetPrimitiveParams( list rules ) + void llSetPrimitiveParams(List rules); + //wiki: string llStringToBase64(string str) + string llStringToBase64(string str); + //wiki: string llBase64ToString(string str) + string llBase64ToString(string str); + //wiki: (deprecated) + void llXorBase64Strings(); + //wiki: llRemoteDataSetRegion() + void llRemoteDataSetRegion(); + //wiki: double llLog10(double val) + double llLog10(double val); + //wiki: double llLog(double val) + double llLog(double val); + //wiki: list llGetAnimationList( key id ) + List llGetAnimationList(string id); + //wiki: llSetParcelMusicURL(string url) + void llSetParcelMusicURL(string url); + //wiki: vector llGetRootPosition() + LSL_Types.Vector3 llGetRootPosition(); + //wiki: rotation llGetRootRotation() + LSL_Types.Quaternion llGetRootRotation(); + //wiki: string llGetObjectDesc() + string llGetObjectDesc(); + //wiki: llSetObjectDesc(string desc) + void llSetObjectDesc(string desc); + //wiki: key llGetCreator() + string llGetCreator(); + //wiki: string llGetTimestamp() + string llGetTimestamp(); + //wiki: llSetLinkAlpha(integer linknumber, double alpha, integer face) + void llSetLinkAlpha(int linknumber, double alpha, int face); + //wiki: integer llGetNumberOfPrims() + int llGetNumberOfPrims(); + //wiki: key llGetNumberOfNotecardLines(string name) + string llGetNumberOfNotecardLines(string name); + //wiki: list llGetBoundingBox( key object ) + List llGetBoundingBox(string obj); + //wiki: vector llGetGeometricCenter() + LSL_Types.Vector3 llGetGeometricCenter(); + void llGetPrimitiveParams(); + //wiki: string llIntegerToBase64(integer number) + string llIntegerToBase64(int number); + //wiki integer llBase64ToInteger(string str) + int llBase64ToInteger(string str); + //wiki: double llGetGMTclock() + double llGetGMTclock(); + //wiki: string llGetSimulatorHostname() + string llGetSimulatorHostname(); + //llSetLocalRot(rotation rot) + void llSetLocalRot(LSL_Types.Quaternion rot); + //wiki: list llParseStringKeepNulls( string src, list separators, list spacers ) + List llParseStringKeepNulls(string src, List seperators, List spacers); + //wiki: llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, integer param) + void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity, + LSL_Types.Quaternion rot, int param); + + //wiki: integer llGetObjectPermMask(integer mask) + int llGetObjectPermMask(int mask); + //wiki: llSetObjectPermMask(integer mask, integer value) + void llSetObjectPermMask(int mask, int value); + //wiki integer llGetInventoryPermMask(string item, integer mask) + void llGetInventoryPermMask(string item, int mask); + //wiki: llSetInventoryPermMask(string item, integer mask, integer value) + void llSetInventoryPermMask(string item, int mask, int value); + //wiki: key llGetInventoryCreator(string item) + string llGetInventoryCreator(string item); + //wiki: llOwnerSay(string msg) + void llOwnerSay(string msg); + //wiki: key llRequestSimulatorData(string simulator, integer data) + void llRequestSimulatorData(string simulator, int data); + //wiki: llForceMouselook(integer mouselook) + void llForceMouselook(int mouselook); + //wiki: double llGetObjectMass(key id) + double llGetObjectMass(string id); + void llListReplaceList(); + //wiki: llLoadURL(key avatar_id, string message, string url) + void llLoadURL(string avatar_id, string message, string url); + //wiki: llParcelMediaCommandList( list commandList ) + void llParcelMediaCommandList(List commandList); + void llParcelMediaQuery(); + //wiki integer llModPow(integer a, integer b, integer c) + int llModPow(int a, int b, int c); + //wiki: integer llGetInventoryType(string name) + int llGetInventoryType(string name); + //wiki: llSetPayPrice( integer price, list quick_pay_buttons ) + void llSetPayPrice(int price, List quick_pay_buttons); + //wiki: vector llGetCameraPos() + LSL_Types.Vector3 llGetCameraPos(); + //wiki rotation llGetCameraRot() + LSL_Types.Quaternion llGetCameraRot(); + //wiki: (deprecated) + void llSetPrimURL(); + //wiki: (deprecated) + void llRefreshPrimURL(); + //wiki: string llEscapeURL(string url) + string llEscapeURL(string url); + //wiki: string llUnescapeURL(string url) + string llUnescapeURL(string url); + //wiki: llMapDestination(string simname, vector pos, vector look_at) + void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at); + //wiki: llAddToLandBanList(key avatar, double hours) + void llAddToLandBanList(string avatar, double hours); + //wiki: llRemoveFromLandPassList(key avatar) + void llRemoveFromLandPassList(string avatar); + //wiki: llRemoveFromLandBanList(key avatar) + void llRemoveFromLandBanList(string avatar); + //wiki: llSetCameraParams( list rules ) + void llSetCameraParams(List rules); + //wiki: llClearCameraParams() + void llClearCameraParams(); + //wiki: double llListStatistics( integer operation, list src ) + double llListStatistics(int operation, List src); + //wiki: integer llGetUnixTime() + int llGetUnixTime(); + //wiki: integer llGetParcelFlags(vector pos) + int llGetParcelFlags(LSL_Types.Vector3 pos); + //wiki: integer llGetRegionFlags() + int llGetRegionFlags(); + //wiki: string llXorBase64StringsCorrect(string str1, string str2) + string llXorBase64StringsCorrect(string str1, string str2); + void llHTTPRequest(string url, List parameters, string body); + //wiki: llResetLandBanList() + void llResetLandBanList(); + //wiki: llResetLandPassList() + void llResetLandPassList(); + //wiki integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide) + int llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide); + //wiki: list llGetParcelPrimOwners( vector pos ) + List llGetParcelPrimOwners(LSL_Types.Vector3 pos); + //wiki: integer llGetObjectPrimCount(key object_id) + int llGetObjectPrimCount(string object_id); + //wiki: integer llGetParcelMaxPrims( vector pos, integer sim_wide ) + int llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide); + //wiki list llGetParcelDetails(vector pos, list params) + List llGetParcelDetails(LSL_Types.Vector3 pos, List param); + + //OpenSim functions + string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, int timer); + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/Common/LSL_Types.cs b/trunk/OpenSim/Grid/ScriptEngine/Common/LSL_Types.cs new file mode 100644 index 0000000000..d10a5efaa3 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/Common/LSL_Types.cs @@ -0,0 +1,83 @@ +/* +* 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; + +namespace OpenSim.Grid.ScriptEngine.Common +{ + [Serializable] + public class LSL_Types + { + [Serializable] + public struct Vector3 + { + public double X; + public double Y; + public double Z; + + public Vector3(Vector3 vector) + { + X = (float) vector.X; + Y = (float) vector.Y; + Z = (float) vector.Z; + } + + public Vector3(double x, double y, double z) + { + X = x; + Y = y; + Z = z; + } + } + + [Serializable] + public struct Quaternion + { + public double X; + public double Y; + public double Z; + public double R; + + public Quaternion(Quaternion Quat) + { + X = (float) Quat.X; + Y = (float) Quat.Y; + Z = (float) Quat.Z; + R = (float) Quat.R; + } + + public Quaternion(double x, double y, double z, double r) + { + X = x; + Y = y; + Z = z; + R = r; + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/Common/Properties/AssemblyInfo.cs b/trunk/OpenSim/Grid/ScriptEngine/Common/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..79899f93f1 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/Common/Properties/AssemblyInfo.cs @@ -0,0 +1,64 @@ +/* +* 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.Grid.ScriptEngine.Common")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Grid.ScriptEngine.Common")] +[assembly : AssemblyCopyright("Copyright © 2007")] +[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("0bf07c53-ae51-487f-a907-e9b30c251602")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs new file mode 100644 index 0000000000..e6c167864f --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/AppDomainManager.cs @@ -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 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; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSL; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine +{ + public class AppDomainManager + { + private int maxScriptsPerAppDomain = 1; + + /// + /// Internal list of all AppDomains + /// + private List appDomains = new List(); + + /// + /// Structure to keep track of data around AppDomain + /// + private class AppDomainStructure + { + /// + /// The AppDomain itself + /// + public AppDomain CurrentAppDomain; + + /// + /// Number of scripts loaded into AppDomain + /// + public int ScriptsLoaded; + + /// + /// Number of dead scripts + /// + public int ScriptsWaitingUnload; + } + + /// + /// Current AppDomain + /// + private AppDomainStructure currentAD; + + private object getLock = new object(); // Mutex + private object freeLock = new object(); // Mutex + + //private ScriptEngine m_scriptEngine; + //public AppDomainManager(ScriptEngine scriptEngine) + public AppDomainManager() + { + //m_scriptEngine = scriptEngine; + } + + /// + /// Find a free AppDomain, creating one if necessary + /// + /// Free AppDomain + private AppDomainStructure GetFreeAppDomain() + { + Console.WriteLine("Finding free AppDomain"); + lock (getLock) + { + // Current full? + if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain) + { + // Add it to AppDomains list and empty current + appDomains.Add(currentAD); + currentAD = null; + } + // No current + if (currentAD == null) + { + // Create a new current AppDomain + currentAD = new AppDomainStructure(); + currentAD.CurrentAppDomain = PrepareNewAppDomain(); + } + + Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded); + return currentAD; + } // lock + } + + private int AppDomainNameCount; + + /// + /// Create and prepare a new AppDomain for scripts + /// + /// The new AppDomain + private AppDomain PrepareNewAppDomain() + { + // Create and prepare a new AppDomain + AppDomainNameCount++; + // TODO: Currently security match current appdomain + + // Construct and initialize settings for a second AppDomain. + AppDomainSetup ads = new AppDomainSetup(); + ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; + ads.DisallowBindingRedirects = false; + ads.DisallowCodeDownload = true; + ads.LoaderOptimization = LoaderOptimization.MultiDomain; // Sounds good ;) + ads.ShadowCopyFiles = "true"; // Enabled shadowing + ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; + + AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads); + Console.WriteLine("Loading: " + + AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString()); + AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll")); + + // Return the new AppDomain + return AD; + } + + /// + /// Unload appdomains that are full and have only dead scripts + /// + private void UnloadAppDomains() + { + lock (freeLock) + { + // Go through all + foreach (AppDomainStructure ads in new ArrayList(appDomains)) + { + // Don't process current AppDomain + if (ads.CurrentAppDomain != currentAD.CurrentAppDomain) + { + // Not current AppDomain + // Is number of unloaded bigger or equal to number of loaded? + if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload) + { + Console.WriteLine("Found empty AppDomain, unloading"); + // Remove from internal list + appDomains.Remove(ads); +#if DEBUG + long m = GC.GetTotalMemory(true); +#endif + // Unload + AppDomain.Unload(ads.CurrentAppDomain); +#if DEBUG + Console.WriteLine("AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + + " bytes of memory"); +#endif + } + } + } // foreach + } // lock + } + + + public LSL_BaseClass LoadScript(string FileName) + { + // Find next available AppDomain to put it in + AppDomainStructure FreeAppDomain = GetFreeAppDomain(); + + Console.WriteLine("Loading into AppDomain: " + FileName); + LSL_BaseClass mbrt = + (LSL_BaseClass) + FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script"); + //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); + FreeAppDomain.ScriptsLoaded++; + + return mbrt; + } + + + /// + /// Increase "dead script" counter for an AppDomain + /// + /// + //[Obsolete("Needs fixing, needs a real purpose in life!!!")] + public void StopScript(AppDomain ad) + { + lock (freeLock) + { + Console.WriteLine("Stopping script in AppDomain"); + // Check if it is current AppDomain + if (currentAD.CurrentAppDomain == ad) + { + // Yes - increase + currentAD.ScriptsWaitingUnload++; + return; + } + + // Lopp through all AppDomains + foreach (AppDomainStructure ads in new ArrayList(appDomains)) + { + if (ads.CurrentAppDomain == ad) + { + // Found it + ads.ScriptsWaitingUnload++; + break; + } + } // foreach + } // lock + + UnloadAppDomains(); // Outsite lock, has its own GetLock + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Common.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Common.cs new file mode 100644 index 0000000000..bcfeefc963 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Common.cs @@ -0,0 +1,58 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine +{ + public static class Common + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public static bool debug = true; + public static ScriptEngine mySE; + + //public delegate void SendToDebugEventDelegate(string Message); + //public delegate void SendToLogEventDelegate(string Message); + //static public event SendToDebugEventDelegate SendToDebugEvent; + //static public event SendToLogEventDelegate SendToLogEvent; + + public static void SendToDebug(string Message) + { + //if (Debug == true) + mySE.m_log.Info("[ScriptEngine]: Debug: " + Message); + //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + + public static void SendToLog(string Message) + { + //if (Debug == true) + mySE.m_log.Info("[ScriptEngine]: LOG: " + Message); + //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs new file mode 100644 index 0000000000..4be8a0b789 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs @@ -0,0 +1,146 @@ +/* +* 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; +using System.CodeDom.Compiler; +using System.IO; +using System.Reflection; +using Microsoft.CSharp; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSL +{ + public class Compiler + { + private LSL2CSConverter LSL_Converter = new LSL2CSConverter(); + private CSharpCodeProvider codeProvider = new CSharpCodeProvider(); + private static UInt64 scriptCompileCounter = 0; + //private ICodeCompiler icc = codeProvider.CreateCompiler(); + public string CompileFromFile(string LSOFileName) + { + switch (Path.GetExtension(LSOFileName).ToLower()) + { + case ".txt": + case ".lsl": + Common.SendToDebug("Source code is LSL, converting to CS"); + return CompileFromLSLText(File.ReadAllText(LSOFileName)); + case ".cs": + Common.SendToDebug("Source code is CS"); + return CompileFromCSText(File.ReadAllText(LSOFileName)); + default: + throw new Exception("Unknown script type."); + } + } + + /// + /// Converts script from LSL to CS and calls CompileFromCSText + /// + /// LSL script + /// Filename to .dll assembly + public string CompileFromLSLText(string Script) + { + if (Script.Substring(0, 4).ToLower() == "//c#") + { + return CompileFromCSText(Script); + } + else + { + return CompileFromCSText(LSL_Converter.Convert(Script)); + } + } + + /// + /// Compile CS script to .Net assembly (.dll) + /// + /// CS script + /// Filename to .dll assembly + public string CompileFromCSText(string Script) + { + // Output assembly name + scriptCompileCounter++; + string OutFile = Path.Combine("ScriptEngines", "Script_" + scriptCompileCounter + ".dll"); + try + { + File.Delete(OutFile); + } + catch (Exception e) + { + Console.WriteLine("Exception attempting to delete old compiled script: " + e.ToString()); + } + //string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll"); + + // DEBUG - write source to disk + try + { + File.WriteAllText( + Path.Combine("ScriptEngines", "debug_" + Path.GetFileNameWithoutExtension(OutFile) + ".cs"), Script); + } + catch + { + } + + // Do actual compile + CompilerParameters parameters = new CompilerParameters(); + parameters.IncludeDebugInformation = true; + // Add all available assemblies + foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) + { + //Console.WriteLine("Adding assembly: " + asm.Location); + //parameters.ReferencedAssemblies.Add(asm.Location); + } + + string rootPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory); + string rootPathSE = Path.GetDirectoryName(GetType().Assembly.Location); + //Console.WriteLine("Assembly location: " + rootPath); + parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Common.dll")); + parameters.ReferencedAssemblies.Add(Path.Combine(rootPathSE, "OpenSim.Grid.ScriptEngine.DotNetEngine.dll")); + + //parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment"); + parameters.GenerateExecutable = false; + parameters.OutputAssembly = OutFile; + parameters.IncludeDebugInformation = false; + CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, Script); + + // Go through errors + // TODO: Return errors to user somehow + if (results.Errors.Count > 0) + { + string errtext = ""; + foreach (CompilerError CompErr in results.Errors) + { + errtext += "Line number " + (CompErr.Line - 1) + + ", Error Number: " + CompErr.ErrorNumber + + ", '" + CompErr.ErrorText + "'\r\n"; + } + throw new Exception(errtext); + } + + + return OutFile; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs new file mode 100644 index 0000000000..9046db3595 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs @@ -0,0 +1,316 @@ +/* +* 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.Collections.Generic; +using System.Text.RegularExpressions; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSL +{ + public class LSL2CSConverter + { + //private Regex rnw = new Regex(@"[a-zA-Z0-9_\-]", RegexOptions.Compiled); + private Dictionary dataTypes = new Dictionary(); + private Dictionary quotes = new Dictionary(); + + public LSL2CSConverter() + { + // Only the types we need to convert + dataTypes.Add("void", "void"); + dataTypes.Add("integer", "int"); + dataTypes.Add("float", "double"); + dataTypes.Add("string", "string"); + dataTypes.Add("key", "string"); + dataTypes.Add("vector", "LSL_Types.Vector3"); + dataTypes.Add("rotation", "LSL_Types.Quaternion"); + dataTypes.Add("list", "list"); + dataTypes.Add("null", "null"); + } + + public string Convert(string Script) + { + string Return = ""; + Script = " \r\n" + Script; + + // + // Prepare script for processing + // + + // Clean up linebreaks + Script = Regex.Replace(Script, @"\r\n", "\n"); + Script = Regex.Replace(Script, @"\n", "\r\n"); + + + // QUOTE REPLACEMENT + // temporarily replace quotes so we can work our magic on the script without + // always considering if we are inside our outside ""'s + string _Script = ""; + string C; + bool in_quote = false; + bool quote_replaced = false; + string quote_replacement_string = "Q_U_O_T_E_REPLACEMENT_"; + string quote = ""; + bool last_was_escape = false; + int quote_replaced_count = 0; + for (int p = 0; p < Script.Length; p++) + { + C = Script.Substring(p, 1); + while (true) + { + // found " and last was not \ so this is not an escaped \" + if (C == "\"" && last_was_escape == false) + { + // Toggle inside/outside quote + in_quote = !in_quote; + if (in_quote) + { + quote_replaced_count++; + } + else + { + if (quote == "") + { + // We didn't replace quote, probably because of empty string? + _Script += quote_replacement_string + + quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]); + } + // We just left a quote + quotes.Add( + quote_replacement_string + + quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]), quote); + quote = ""; + } + break; + } + + if (!in_quote) + { + // We are not inside a quote + quote_replaced = false; + } + else + { + // We are inside a quote + if (!quote_replaced) + { + // Replace quote + _Script += quote_replacement_string + + quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]); + quote_replaced = true; + } + quote += C; + break; + } + _Script += C; + break; + } + last_was_escape = false; + if (C == @"\") + { + last_was_escape = true; + } + } + Script = _Script; + // + // END OF QUOTE REPLACEMENT + // + + + // + // PROCESS STATES + // Remove state definitions and add state names to start of each event within state + // + int ilevel = 0; + int lastlevel = 0; + string ret = ""; + string cache = ""; + bool in_state = false; + string current_statename = ""; + for (int p = 0; p < Script.Length; p++) + { + C = Script.Substring(p, 1); + while (true) + { + // inc / dec level + if (C == @"{") + ilevel++; + if (C == @"}") + ilevel--; + if (ilevel < 0) + ilevel = 0; + cache += C; + + // if level == 0, add to return + if (ilevel == 1 && lastlevel == 0) + { + // 0 => 1: Get last + Match m = + Regex.Match(cache, @"(?![a-zA-Z_]+)\s*([a-zA-Z_]+)[^a-zA-Z_\(\)]*{", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + in_state = false; + if (m.Success) + { + // Go back to level 0, this is not a state + in_state = true; + current_statename = m.Groups[1].Captures[0].Value; + //Console.WriteLine("Current statename: " + current_statename); + cache = + Regex.Replace(cache, + @"(?(?![a-zA-Z_]+)\s*)" + @"([a-zA-Z_]+)(?[^a-zA-Z_\(\)]*){", + "${s1}${s2}", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + } + ret += cache; + cache = ""; + } + if (ilevel == 0 && lastlevel == 1) + { + // 1 => 0: Remove last } + if (in_state == true) + { + cache = cache.Remove(cache.Length - 1, 1); + //cache = Regex.Replace(cache, "}$", "", RegexOptions.Multiline | RegexOptions.Singleline); + + //Replace function names + // void dataserver(key query_id, string data) { + //cache = Regex.Replace(cache, @"([^a-zA-Z_]\s*)((?!if|switch|for)[a-zA-Z_]+\s*\([^\)]*\)[^{]*{)", "$1" + "" + "$2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + //Console.WriteLine("Replacing using statename: " + current_statename); + cache = + Regex.Replace(cache, + @"^(\s*)((?!(if|switch|for)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", + @"$1public " + current_statename + "_event_$2", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + } + + ret += cache; + cache = ""; + in_state = true; + current_statename = ""; + } + + break; + } + lastlevel = ilevel; + } + ret += cache; + cache = ""; + + Script = ret; + ret = ""; + + + foreach (string key in dataTypes.Keys) + { + string val; + dataTypes.TryGetValue(key, out val); + + // Replace CAST - (integer) with (int) + Script = + Regex.Replace(Script, @"\(" + key + @"\)", @"(" + val + ")", + RegexOptions.Compiled | RegexOptions.Multiline); + // Replace return types and function variables - integer a() and f(integer a, integer a) + Script = + Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s*)", @"$1$2" + val + "$3", + RegexOptions.Compiled | RegexOptions.Multiline); + } + + // Add "void" in front of functions that needs it + Script = + Regex.Replace(Script, + @"^(\s*public\s+)((?!(if|switch|for)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", + @"$1void $2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + // Replace and + Script = + Regex.Replace(Script, @"<([^,>]*,[^,>]*,[^,>]*,[^,>]*)>", @"new LSL_Types.Quaternion($1)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + Script = + Regex.Replace(Script, @"<([^,>]*,[^,>]*,[^,>]*)>", @"new LSL_Types.Vector3($1)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + // Replace List []'s + Script = + Regex.Replace(Script, @"\[([^\]]*)\]", @"List.Parse($1)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + + // Replace (string) to .ToString() // + Script = + Regex.Replace(Script, @"\(string\)\s*([a-zA-Z0-9_]+(\s*\([^\)]*\))?)", @"$1.ToString()", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + Script = + Regex.Replace(Script, @"\((float|int)\)\s*([a-zA-Z0-9_]+(\s*\([^\)]*\))?)", @"$1.Parse($2)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + + // REPLACE BACK QUOTES + foreach (string key in quotes.Keys) + { + string val; + quotes.TryGetValue(key, out val); + Script = Script.Replace(key, "\"" + val + "\""); + } + + + // Add namespace, class name and inheritance + + Return = "" + + "using OpenSim.Region.ScriptEngine.Common;"; + //"using System; " + + //"using System.Collections.Generic; " + + //"using System.Text; " + + //"using OpenSim.Region.ScriptEngine.Common; " + + //"using integer = System.Int32; " + + //"using key = System.String; "; + + //// Make a Using out of DataTypes + //// Using integer = System.Int32; + //string _val; + //foreach (string key in DataTypes.Keys) + //{ + // DataTypes.TryGetValue(key, out _val); + // if (key != _val) + // { + // Return += "using " + key + " = " + _val + "; "; + // } + //} + + + Return += "" + + "namespace SecondLife { "; + Return += "" + + //"[Serializable] " + + "public class Script : OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass { "; + Return += @"public Script() { } "; + Return += Script; + Return += "} }\r\n"; + + return Return; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs new file mode 100644 index 0000000000..e0a5461f7f --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs @@ -0,0 +1,2123 @@ +/* +* 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; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using System.Threading; +using OpenSim.Region.ScriptEngine.Common; +using integer = System.Int32; +using key = System.String; +using vector = OpenSim.Region.ScriptEngine.Common.LSL_Types.Vector3; +using rotation = OpenSim.Region.ScriptEngine.Common.LSL_Types.Quaternion; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSL +{ + //[Serializable] + public class LSL_BaseClass : MarshalByRefObject, LSL_BuiltIn_Commands_Interface, IScript + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Object never expires + public override Object InitializeLifetimeService() + { + //Console.WriteLine("LSL_BaseClass: InitializeLifetimeService()"); + // return null; + ILease lease = (ILease) base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); + //lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); + //lease.RenewOnCallTime = TimeSpan.FromSeconds(2); + } + return lease; + } + + + private Executor m_Exec; + + public Executor Exec + { + get + { + if (m_Exec == null) + m_Exec = new Executor(this); + return m_Exec; + } + } + + public LSL_BuiltIn_Commands_Interface m_LSL_Functions; + public string SourceCode = ""; + + public LSL_BaseClass() + { + } + + public string State() + { + return m_LSL_Functions.State(); + } + + + public void Start(LSL_BuiltIn_Commands_Interface LSL_Functions) + { + m_LSL_Functions = LSL_Functions; + + //m_log.Info("[ScriptEngine]: LSL_BaseClass.Start() called."); + + // Get this AppDomain's settings and display some of them. + AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation; + Console.WriteLine("AppName={0}, AppBase={1}, ConfigFile={2}", + ads.ApplicationName, + ads.ApplicationBase, + ads.ConfigurationFile + ); + + // Display the name of the calling AppDomain and the name + // of the second domain. + // NOTE: The application's thread has transitioned between + // AppDomains. + Console.WriteLine("Calling to '{0}'.", + Thread.GetDomain().FriendlyName + ); + + return; + } + + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + // They are only forwarders to LSL_BuiltIn_Commands.cs + // + public double llSin(double f) + { + return m_LSL_Functions.llSin(f); + } + + public double llCos(double f) + { + return m_LSL_Functions.llCos(f); + } + + public double llTan(double f) + { + return m_LSL_Functions.llTan(f); + } + + public double llAtan2(double x, double y) + { + return m_LSL_Functions.llAtan2(x, y); + } + + public double llSqrt(double f) + { + return m_LSL_Functions.llSqrt(f); + } + + public double llPow(double fbase, double fexponent) + { + return m_LSL_Functions.llPow(fbase, fexponent); + } + + public int llAbs(int i) + { + return m_LSL_Functions.llAbs(i); + } + + public double llFabs(double f) + { + return m_LSL_Functions.llFabs(f); + } + + public double llFrand(double mag) + { + return m_LSL_Functions.llFrand(mag); + } + + public int llFloor(double f) + { + return m_LSL_Functions.llFloor(f); + } + + public int llCeil(double f) + { + return m_LSL_Functions.llCeil(f); + } + + public int llRound(double f) + { + return m_LSL_Functions.llRound(f); + } + + public double llVecMag(vector v) + { + return m_LSL_Functions.llVecMag(v); + } + + public vector llVecNorm(vector v) + { + return m_LSL_Functions.llVecNorm(v); + } + + public double llVecDist(vector a, vector b) + { + return m_LSL_Functions.llVecDist(a, b); + } + + public vector llRot2Euler(rotation r) + { + return m_LSL_Functions.llRot2Euler(r); + } + + public rotation llEuler2Rot(vector v) + { + return m_LSL_Functions.llEuler2Rot(v); + } + + public rotation llAxes2Rot(vector fwd, vector left, vector up) + { + return m_LSL_Functions.llAxes2Rot(fwd, left, up); + } + + public vector llRot2Fwd(rotation r) + { + return m_LSL_Functions.llRot2Fwd(r); + } + + public vector llRot2Left(rotation r) + { + return m_LSL_Functions.llRot2Left(r); + } + + public vector llRot2Up(rotation r) + { + return m_LSL_Functions.llRot2Up(r); + } + + public rotation llRotBetween(vector start, vector end) + { + return m_LSL_Functions.llRotBetween(start, end); + } + + public void llWhisper(int channelID, string text) + { + m_LSL_Functions.llWhisper(channelID, text); + } + + public void llSay(int channelID, string text) + { + m_LSL_Functions.llSay(channelID, text); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llShout(int channelID, string text) + { + m_LSL_Functions.llShout(channelID, text); + } + + public int llListen(int channelID, string name, string ID, string msg) + { + return m_LSL_Functions.llListen(channelID, name, ID, msg); + } + + public void llListenControl(int number, int active) + { + m_LSL_Functions.llListenControl(number, active); + } + + public void llListenRemove(int number) + { + m_LSL_Functions.llListenRemove(number); + } + + public void llSensor(string name, string id, int type, double range, double arc) + { + m_LSL_Functions.llSensor(name, id, type, range, arc); + } + + public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) + { + m_LSL_Functions.llSensorRepeat(name, id, type, range, arc, rate); + } + + public void llSensorRemove() + { + m_LSL_Functions.llSensorRemove(); + } + + public string llDetectedName(int number) + { + return m_LSL_Functions.llDetectedName(number); + } + + public string llDetectedKey(int number) + { + return m_LSL_Functions.llDetectedKey(number); + } + + public string llDetectedOwner(int number) + { + return m_LSL_Functions.llDetectedOwner(number); + } + + public int llDetectedType(int number) + { + return m_LSL_Functions.llDetectedType(number); + } + + public vector llDetectedPos(int number) + { + return m_LSL_Functions.llDetectedPos(number); + } + + public vector llDetectedVel(int number) + { + return m_LSL_Functions.llDetectedVel(number); + } + + public vector llDetectedGrab(int number) + { + return m_LSL_Functions.llDetectedGrab(number); + } + + public rotation llDetectedRot(int number) + { + return m_LSL_Functions.llDetectedRot(number); + } + + public int llDetectedGroup(int number) + { + return m_LSL_Functions.llDetectedGroup(number); + } + + public int llDetectedLinkNumber(int number) + { + return m_LSL_Functions.llDetectedLinkNumber(number); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llDie() + { + m_LSL_Functions.llDie(); + } + + public double llGround(vector offset) + { + return m_LSL_Functions.llGround(offset); + } + + public double llCloud(vector offset) + { + return m_LSL_Functions.llCloud(offset); + } + + public vector llWind(vector offset) + { + return m_LSL_Functions.llWind(offset); + } + + public void llSetStatus(int status, int value) + { + m_LSL_Functions.llSetStatus(status, value); + } + + public int llGetStatus(int status) + { + return m_LSL_Functions.llGetStatus(status); + } + + public void llSetScale(vector scale) + { + m_LSL_Functions.llSetScale(scale); + } + + public vector llGetScale() + { + return m_LSL_Functions.llGetScale(); + } + + public void llSetColor(vector color, int face) + { + m_LSL_Functions.llSetColor(color, face); + } + + public double llGetAlpha(int face) + { + return m_LSL_Functions.llGetAlpha(face); + } + + public void llSetAlpha(double alpha, int face) + { + m_LSL_Functions.llSetAlpha(alpha, face); + } + + public vector llGetColor(int face) + { + return m_LSL_Functions.llGetColor(face); + } + + public void llSetTexture(string texture, int face) + { + m_LSL_Functions.llSetTexture(texture, face); + } + + public void llScaleTexture(double u, double v, int face) + { + m_LSL_Functions.llScaleTexture(u, v, face); + } + + public void llOffsetTexture(double u, double v, int face) + { + m_LSL_Functions.llOffsetTexture(u, v, face); + } + + public void llRotateTexture(double rotation, int face) + { + m_LSL_Functions.llRotateTexture(rotation, face); + } + + public string llGetTexture(int face) + { + return m_LSL_Functions.llGetTexture(face); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llSetPos(vector pos) + { + m_LSL_Functions.llSetPos(pos); + } + + public vector llGetPos() + { + return m_LSL_Functions.llGetPos(); + } + + public vector llGetLocalPos() + { + return m_LSL_Functions.llGetLocalPos(); + } + + public void llSetRot(rotation rot) + { + m_LSL_Functions.llSetRot(rot); + } + + public rotation llGetRot() + { + return m_LSL_Functions.llGetRot(); + } + + public rotation llGetLocalRot() + { + return m_LSL_Functions.llGetLocalRot(); + } + + public void llSetForce(vector force, int local) + { + m_LSL_Functions.llSetForce(force, local); + } + + public vector llGetForce() + { + return m_LSL_Functions.llGetForce(); + } + + public int llTarget(vector position, double range) + { + return m_LSL_Functions.llTarget(position, range); + } + + public void llTargetRemove(int number) + { + m_LSL_Functions.llTargetRemove(number); + } + + public int llRotTarget(rotation rot, double error) + { + return m_LSL_Functions.llRotTarget(rot, error); + } + + public void llRotTargetRemove(int number) + { + m_LSL_Functions.llRotTargetRemove(number); + } + + public void llMoveToTarget(vector target, double tau) + { + m_LSL_Functions.llMoveToTarget(target, tau); + } + + public void llStopMoveToTarget() + { + m_LSL_Functions.llStopMoveToTarget(); + } + + public void llApplyImpulse(vector force, int local) + { + m_LSL_Functions.llApplyImpulse(force, local); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llApplyRotationalImpulse(vector force, int local) + { + m_LSL_Functions.llApplyRotationalImpulse(force, local); + } + + public void llSetTorque(vector torque, int local) + { + m_LSL_Functions.llSetTorque(torque, local); + } + + public vector llGetTorque() + { + return m_LSL_Functions.llGetTorque(); + } + + public void llSetForceAndTorque(vector force, vector torque, int local) + { + m_LSL_Functions.llSetForceAndTorque(force, torque, local); + } + + public vector llGetVel() + { + return m_LSL_Functions.llGetVel(); + } + + public vector llGetAccel() + { + return m_LSL_Functions.llGetAccel(); + } + + public vector llGetOmega() + { + return m_LSL_Functions.llGetOmega(); + } + + public double llGetTimeOfDay() + { + return m_LSL_Functions.llGetTimeOfDay(); + } + + public double llGetWallclock() + { + return m_LSL_Functions.llGetWallclock(); + } + + public double llGetTime() + { + return m_LSL_Functions.llGetTime(); + } + + public void llResetTime() + { + m_LSL_Functions.llResetTime(); + } + + public double llGetAndResetTime() + { + return m_LSL_Functions.llGetAndResetTime(); + } + + public void llSound() + { + m_LSL_Functions.llSound(); + } + + public void llPlaySound(string sound, double volume) + { + m_LSL_Functions.llPlaySound(sound, volume); + } + + public void llLoopSound(string sound, double volume) + { + m_LSL_Functions.llLoopSound(sound, volume); + } + + public void llLoopSoundMaster(string sound, double volume) + { + m_LSL_Functions.llLoopSoundMaster(sound, volume); + } + + public void llLoopSoundSlave(string sound, double volume) + { + m_LSL_Functions.llLoopSoundSlave(sound, volume); + } + + public void llPlaySoundSlave(string sound, double volume) + { + m_LSL_Functions.llPlaySoundSlave(sound, volume); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llTriggerSound(string sound, double volume) + { + m_LSL_Functions.llTriggerSound(sound, volume); + } + + public void llStopSound() + { + m_LSL_Functions.llStopSound(); + } + + public void llPreloadSound(string sound) + { + m_LSL_Functions.llPreloadSound(sound); + } + + public string llGetSubString(string src, int start, int end) + { + return m_LSL_Functions.llGetSubString(src, start, end); + } + + public string llDeleteSubString(string src, int start, int end) + { + return m_LSL_Functions.llDeleteSubString(src, start, end); + } + + public string llInsertString(string dst, int position, string src) + { + return m_LSL_Functions.llInsertString(dst, position, src); + } + + public string llToUpper(string source) + { + return m_LSL_Functions.llToUpper(source); + } + + public string llToLower(string source) + { + return m_LSL_Functions.llToLower(source); + } + + public int llGiveMoney(string destination, int amount) + { + return m_LSL_Functions.llGiveMoney(destination, amount); + } + + public void llMakeExplosion() + { + m_LSL_Functions.llMakeExplosion(); + } + + public void llMakeFountain() + { + m_LSL_Functions.llMakeFountain(); + } + + public void llMakeSmoke() + { + m_LSL_Functions.llMakeSmoke(); + } + + public void llMakeFire() + { + m_LSL_Functions.llMakeFire(); + } + + public void llRezObject(string inventory, vector pos, rotation rot, int param) + { + m_LSL_Functions.llRezObject(inventory, pos, rot, param); + } + + public void llLookAt(vector target, double strength, double damping) + { + m_LSL_Functions.llLookAt(target, strength, damping); + } + + public void llStopLookAt() + { + m_LSL_Functions.llStopLookAt(); + } + + public void llSetTimerEvent(double sec) + { + m_LSL_Functions.llSetTimerEvent(sec); + } + + public void llSleep(double sec) + { + m_LSL_Functions.llSleep(sec); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public double llGetMass() + { + return m_LSL_Functions.llGetMass(); + } + + public void llCollisionFilter(string name, string id, int accept) + { + m_LSL_Functions.llCollisionFilter(name, id, accept); + } + + public void llTakeControls(int controls, int accept, int pass_on) + { + m_LSL_Functions.llTakeControls(controls, accept, pass_on); + } + + public void llReleaseControls() + { + m_LSL_Functions.llReleaseControls(); + } + + public void llAttachToAvatar(int attachment) + { + m_LSL_Functions.llAttachToAvatar(attachment); + } + + public void llDetachFromAvatar() + { + m_LSL_Functions.llDetachFromAvatar(); + } + + public void llTakeCamera() + { + m_LSL_Functions.llTakeCamera(); + } + + public void llReleaseCamera() + { + m_LSL_Functions.llReleaseCamera(); + } + + public string llGetOwner() + { + return m_LSL_Functions.llGetOwner(); + } + + public void llInstantMessage(string user, string message) + { + m_LSL_Functions.llInstantMessage(user, message); + } + + public void llEmail(string address, string subject, string message) + { + m_LSL_Functions.llEmail(address, subject, message); + } + + public void llGetNextEmail(string address, string subject) + { + m_LSL_Functions.llGetNextEmail(address, subject); + } + + public string llGetKey() + { + return m_LSL_Functions.llGetKey(); + } + + public void llSetBuoyancy(double buoyancy) + { + m_LSL_Functions.llSetBuoyancy(buoyancy); + } + + public void llSetHoverHeight(double height, int water, double tau) + { + m_LSL_Functions.llSetHoverHeight(height, water, tau); + } + + public void llStopHover() + { + m_LSL_Functions.llStopHover(); + } + + public void llMinEventDelay(double delay) + { + m_LSL_Functions.llMinEventDelay(delay); + } + + public void llSoundPreload() + { + m_LSL_Functions.llSoundPreload(); + } + + public void llRotLookAt(rotation target, double strength, double damping) + { + m_LSL_Functions.llRotLookAt(target, strength, damping); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public int llStringLength(string str) + { + return m_LSL_Functions.llStringLength(str); + } + + public void llStartAnimation(string anim) + { + m_LSL_Functions.llStartAnimation(anim); + } + + public void llStopAnimation(string anim) + { + m_LSL_Functions.llStopAnimation(anim); + } + + public void llPointAt() + { + m_LSL_Functions.llPointAt(); + } + + public void llStopPointAt() + { + m_LSL_Functions.llStopPointAt(); + } + + public void llTargetOmega(vector axis, double spinrate, double gain) + { + m_LSL_Functions.llTargetOmega(axis, spinrate, gain); + } + + public int llGetStartParameter() + { + return m_LSL_Functions.llGetStartParameter(); + } + + public void llGodLikeRezObject(string inventory, vector pos) + { + m_LSL_Functions.llGodLikeRezObject(inventory, pos); + } + + public void llRequestPermissions(string agent, int perm) + { + m_LSL_Functions.llRequestPermissions(agent, perm); + } + + public string llGetPermissionsKey() + { + return m_LSL_Functions.llGetPermissionsKey(); + } + + public int llGetPermissions() + { + return m_LSL_Functions.llGetPermissions(); + } + + public int llGetLinkNumber() + { + return m_LSL_Functions.llGetLinkNumber(); + } + + public void llSetLinkColor(int linknumber, vector color, int face) + { + m_LSL_Functions.llSetLinkColor(linknumber, color, face); + } + + public void llCreateLink(string target, int parent) + { + m_LSL_Functions.llCreateLink(target, parent); + } + + public void llBreakLink(int linknum) + { + m_LSL_Functions.llBreakLink(linknum); + } + + public void llBreakAllLinks() + { + m_LSL_Functions.llBreakAllLinks(); + } + + public string llGetLinkKey(int linknum) + { + return m_LSL_Functions.llGetLinkKey(linknum); + } + + public void llGetLinkName(int linknum) + { + m_LSL_Functions.llGetLinkName(linknum); + } + + public int llGetInventoryNumber(int type) + { + return m_LSL_Functions.llGetInventoryNumber(type); + } + + public string llGetInventoryName(int type, int number) + { + return m_LSL_Functions.llGetInventoryName(type, number); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llSetScriptState(string name, int run) + { + m_LSL_Functions.llSetScriptState(name, run); + } + + public double llGetEnergy() + { + return m_LSL_Functions.llGetEnergy(); + } + + public void llGiveInventory(string destination, string inventory) + { + m_LSL_Functions.llGiveInventory(destination, inventory); + } + + public void llRemoveInventory(string item) + { + m_LSL_Functions.llRemoveInventory(item); + } + + public void llSetText(string text, vector color, double alpha) + { + m_LSL_Functions.llSetText(text, color, alpha); + } + + public double llWater(vector offset) + { + return m_LSL_Functions.llWater(offset); + } + + public void llPassTouches(int pass) + { + m_LSL_Functions.llPassTouches(pass); + } + + public string llRequestAgentData(string id, int data) + { + return m_LSL_Functions.llRequestAgentData(id, data); + } + + public string llRequestInventoryData(string name) + { + return m_LSL_Functions.llRequestInventoryData(name); + } + + public void llSetDamage(double damage) + { + m_LSL_Functions.llSetDamage(damage); + } + + public void llTeleportAgentHome(string agent) + { + m_LSL_Functions.llTeleportAgentHome(agent); + } + + public void llModifyLand(int action, int brush) + { + m_LSL_Functions.llModifyLand(action, brush); + } + + public void llCollisionSound(string impact_sound, double impact_volume) + { + m_LSL_Functions.llCollisionSound(impact_sound, impact_volume); + } + + public void llCollisionSprite(string impact_sprite) + { + m_LSL_Functions.llCollisionSprite(impact_sprite); + } + + public string llGetAnimation(string id) + { + return m_LSL_Functions.llGetAnimation(id); + } + + public void llResetScript() + { + m_LSL_Functions.llResetScript(); + } + + public void llMessageLinked(int linknum, int num, string str, string id) + { + m_LSL_Functions.llMessageLinked(linknum, num, str, id); + } + + public void llPushObject(string target, vector impulse, vector ang_impulse, int local) + { + m_LSL_Functions.llPushObject(target, impulse, ang_impulse, local); + } + + public void llPassCollisions(int pass) + { + m_LSL_Functions.llPassCollisions(pass); + } + + public string llGetScriptName() + { + return m_LSL_Functions.llGetScriptName(); + } + + public int llGetNumberOfSides() + { + return m_LSL_Functions.llGetNumberOfSides(); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public rotation llAxisAngle2Rot(vector axis, double angle) + { + return m_LSL_Functions.llAxisAngle2Rot(axis, angle); + } + + public vector llRot2Axis(rotation rot) + { + return m_LSL_Functions.llRot2Axis(rot); + } + + public void llRot2Angle() + { + m_LSL_Functions.llRot2Angle(); + } + + public double llAcos(double val) + { + return m_LSL_Functions.llAcos(val); + } + + public double llAsin(double val) + { + return m_LSL_Functions.llAsin(val); + } + + public double llAngleBetween(rotation a, rotation b) + { + return m_LSL_Functions.llAngleBetween(a, b); + } + + public string llGetInventoryKey(string name) + { + return m_LSL_Functions.llGetInventoryKey(name); + } + + public void llAllowInventoryDrop(int add) + { + m_LSL_Functions.llAllowInventoryDrop(add); + } + + public vector llGetSunDirection() + { + return m_LSL_Functions.llGetSunDirection(); + } + + public vector llGetTextureOffset(int face) + { + return m_LSL_Functions.llGetTextureOffset(face); + } + + public vector llGetTextureScale(int side) + { + return m_LSL_Functions.llGetTextureScale(side); + } + + public double llGetTextureRot(int side) + { + return m_LSL_Functions.llGetTextureRot(side); + } + + public int llSubStringIndex(string source, string pattern) + { + return m_LSL_Functions.llSubStringIndex(source, pattern); + } + + public string llGetOwnerKey(string id) + { + return m_LSL_Functions.llGetOwnerKey(id); + } + + public vector llGetCenterOfMass() + { + return m_LSL_Functions.llGetCenterOfMass(); + } + + public List llListSort(List src, int stride, int ascending) + { + return m_LSL_Functions.llListSort(src, stride, ascending); + } + + public int llGetListLength(List src) + { + return m_LSL_Functions.llGetListLength(src); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public int llList2Integer(List src, int index) + { + return m_LSL_Functions.llList2Integer(src, index); + } + + public double llList2double(List src, int index) + { + return m_LSL_Functions.llList2double(src, index); + } + + public string llList2String(List src, int index) + { + return m_LSL_Functions.llList2String(src, index); + } + + public string llList2Key(List src, int index) + { + return m_LSL_Functions.llList2Key(src, index); + } + + public vector llList2Vector(List src, int index) + { + return m_LSL_Functions.llList2Vector(src, index); + } + + public rotation llList2Rot(List src, int index) + { + return m_LSL_Functions.llList2Rot(src, index); + } + + public List llList2List(List src, int start, int end) + { + return m_LSL_Functions.llList2List(src, start, end); + } + + public List llDeleteSubList(List src, int start, int end) + { + return m_LSL_Functions.llDeleteSubList(src, start, end); + } + + public int llGetListEntryType(List src, int index) + { + return m_LSL_Functions.llGetListEntryType(src, index); + } + + public string llList2CSV(List src) + { + return m_LSL_Functions.llList2CSV(src); + } + + public List llCSV2List(string src) + { + return m_LSL_Functions.llCSV2List(src); + } + + public List llListRandomize(List src, int stride) + { + return m_LSL_Functions.llListRandomize(src, stride); + } + + public List llList2ListStrided(List src, int start, int end, int stride) + { + return m_LSL_Functions.llList2ListStrided(src, start, end, stride); + } + + public vector llGetRegionCorner() + { + return m_LSL_Functions.llGetRegionCorner(); + } + + public List llListInsertList(List dest, List src, int start) + { + return m_LSL_Functions.llListInsertList(dest, src, start); + } + + public int llListFindList(List src, List test) + { + return m_LSL_Functions.llListFindList(src, test); + } + + public string llGetObjectName() + { + return m_LSL_Functions.llGetObjectName(); + } + + public void llSetObjectName(string name) + { + m_LSL_Functions.llSetObjectName(name); + } + + public string llGetDate() + { + return m_LSL_Functions.llGetDate(); + } + + public int llEdgeOfWorld(vector pos, vector dir) + { + return m_LSL_Functions.llEdgeOfWorld(pos, dir); + } + + public int llGetAgentInfo(string id) + { + return m_LSL_Functions.llGetAgentInfo(id); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llAdjustSoundVolume(double volume) + { + m_LSL_Functions.llAdjustSoundVolume(volume); + } + + public void llSetSoundQueueing(int queue) + { + m_LSL_Functions.llSetSoundQueueing(queue); + } + + public void llSetSoundRadius(double radius) + { + m_LSL_Functions.llSetSoundRadius(radius); + } + + public string llKey2Name(string id) + { + return m_LSL_Functions.llKey2Name(id); + } + + public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + m_LSL_Functions.llSetTextureAnim(mode, face, sizex, sizey, start, length, rate); + } + + public void llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west) + { + m_LSL_Functions.llTriggerSoundLimited(sound, volume, top_north_east, bottom_south_west); + } + + public void llEjectFromLand(string pest) + { + m_LSL_Functions.llEjectFromLand(pest); + } + + public void llParseString2List() + { + m_LSL_Functions.llParseString2List(); + } + + public int llOverMyLand(string id) + { + return m_LSL_Functions.llOverMyLand(id); + } + + public string llGetLandOwnerAt(vector pos) + { + return m_LSL_Functions.llGetLandOwnerAt(pos); + } + + public string llGetNotecardLine(string name, int line) + { + return m_LSL_Functions.llGetNotecardLine(name, line); + } + + public vector llGetAgentSize(string id) + { + return m_LSL_Functions.llGetAgentSize(id); + } + + public int llSameGroup(string agent) + { + return m_LSL_Functions.llSameGroup(agent); + } + + public void llUnSit(string id) + { + m_LSL_Functions.llUnSit(id); + } + + public vector llGroundSlope(vector offset) + { + return m_LSL_Functions.llGroundSlope(offset); + } + + public vector llGroundNormal(vector offset) + { + return m_LSL_Functions.llGroundNormal(offset); + } + + public vector llGroundContour(vector offset) + { + return m_LSL_Functions.llGroundContour(offset); + } + + public int llGetAttached() + { + return m_LSL_Functions.llGetAttached(); + } + + public int llGetFreeMemory() + { + return m_LSL_Functions.llGetFreeMemory(); + } + + public string llGetRegionName() + { + return m_LSL_Functions.llGetRegionName(); + } + + public double llGetRegionTimeDilation() + { + return m_LSL_Functions.llGetRegionTimeDilation(); + } + + public double llGetRegionFPS() + { + return m_LSL_Functions.llGetRegionFPS(); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llParticleSystem(List rules) + { + m_LSL_Functions.llParticleSystem(rules); + } + + public void llGroundRepel(double height, int water, double tau) + { + m_LSL_Functions.llGroundRepel(height, water, tau); + } + + public void llGiveInventoryList() + { + m_LSL_Functions.llGiveInventoryList(); + } + + public void llSetVehicleType(int type) + { + m_LSL_Functions.llSetVehicleType(type); + } + + public void llSetVehicledoubleParam(int param, double value) + { + m_LSL_Functions.llSetVehicledoubleParam(param, value); + } + + public void llSetVehicleVectorParam(int param, vector vec) + { + m_LSL_Functions.llSetVehicleVectorParam(param, vec); + } + + public void llSetVehicleRotationParam(int param, rotation rot) + { + m_LSL_Functions.llSetVehicleRotationParam(param, rot); + } + + public void llSetVehicleFlags(int flags) + { + m_LSL_Functions.llSetVehicleFlags(flags); + } + + public void llRemoveVehicleFlags(int flags) + { + m_LSL_Functions.llRemoveVehicleFlags(flags); + } + + public void llSitTarget(vector offset, rotation rot) + { + m_LSL_Functions.llSitTarget(offset, rot); + } + + public string llAvatarOnSitTarget() + { + return m_LSL_Functions.llAvatarOnSitTarget(); + } + + public void llAddToLandPassList(string avatar, double hours) + { + m_LSL_Functions.llAddToLandPassList(avatar, hours); + } + + public void llSetTouchText(string text) + { + m_LSL_Functions.llSetTouchText(text); + } + + public void llSetSitText(string text) + { + m_LSL_Functions.llSetSitText(text); + } + + public void llSetCameraEyeOffset(vector offset) + { + m_LSL_Functions.llSetCameraEyeOffset(offset); + } + + public void llSetCameraAtOffset(vector offset) + { + m_LSL_Functions.llSetCameraAtOffset(offset); + } + + public void llDumpList2String() + { + m_LSL_Functions.llDumpList2String(); + } + + public void llScriptDanger(vector pos) + { + m_LSL_Functions.llScriptDanger(pos); + } + + public void llDialog(string avatar, string message, List buttons, int chat_channel) + { + m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel); + } + + public void llVolumeDetect(int detect) + { + m_LSL_Functions.llVolumeDetect(detect); + } + + public void llResetOtherScript(string name) + { + m_LSL_Functions.llResetOtherScript(name); + } + + public int llGetScriptState(string name) + { + return m_LSL_Functions.llGetScriptState(name); + } + + public void llRemoteLoadScript() + { + m_LSL_Functions.llRemoteLoadScript(); + } + + public void llSetRemoteScriptAccessPin(int pin) + { + m_LSL_Functions.llSetRemoteScriptAccessPin(pin); + } + + public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) + { + m_LSL_Functions.llRemoteLoadScriptPin(target, name, pin, running, start_param); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llOpenRemoteDataChannel() + { + m_LSL_Functions.llOpenRemoteDataChannel(); + } + + public string llSendRemoteData(string channel, string dest, int idata, string sdata) + { + return m_LSL_Functions.llSendRemoteData(channel, dest, idata, sdata); + } + + public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) + { + m_LSL_Functions.llRemoteDataReply(channel, message_id, sdata, idata); + } + + public void llCloseRemoteDataChannel(string channel) + { + m_LSL_Functions.llCloseRemoteDataChannel(channel); + } + + public string llMD5String(string src, int nonce) + { + return m_LSL_Functions.llMD5String(src, nonce); + } + + public void llSetPrimitiveParams(List rules) + { + m_LSL_Functions.llSetPrimitiveParams(rules); + } + + public string llStringToBase64(string str) + { + return m_LSL_Functions.llStringToBase64(str); + } + + public string llBase64ToString(string str) + { + return m_LSL_Functions.llBase64ToString(str); + } + + public void llXorBase64Strings() + { + m_LSL_Functions.llXorBase64Strings(); + } + + public void llRemoteDataSetRegion() + { + m_LSL_Functions.llRemoteDataSetRegion(); + } + + public double llLog10(double val) + { + return m_LSL_Functions.llLog10(val); + } + + public double llLog(double val) + { + return m_LSL_Functions.llLog(val); + } + + public List llGetAnimationList(string id) + { + return m_LSL_Functions.llGetAnimationList(id); + } + + public void llSetParcelMusicURL(string url) + { + m_LSL_Functions.llSetParcelMusicURL(url); + } + + public vector llGetRootPosition() + { + return m_LSL_Functions.llGetRootPosition(); + } + + public rotation llGetRootRotation() + { + return m_LSL_Functions.llGetRootRotation(); + } + + public string llGetObjectDesc() + { + return m_LSL_Functions.llGetObjectDesc(); + } + + public void llSetObjectDesc(string desc) + { + m_LSL_Functions.llSetObjectDesc(desc); + } + + public string llGetCreator() + { + return m_LSL_Functions.llGetCreator(); + } + + public string llGetTimestamp() + { + return m_LSL_Functions.llGetTimestamp(); + } + + public void llSetLinkAlpha(int linknumber, double alpha, int face) + { + m_LSL_Functions.llSetLinkAlpha(linknumber, alpha, face); + } + + public int llGetNumberOfPrims() + { + return m_LSL_Functions.llGetNumberOfPrims(); + } + + public string llGetNumberOfNotecardLines(string name) + { + return m_LSL_Functions.llGetNumberOfNotecardLines(name); + } + + public List llGetBoundingBox(string obj) + { + return m_LSL_Functions.llGetBoundingBox(obj); + } + + public vector llGetGeometricCenter() + { + return m_LSL_Functions.llGetGeometricCenter(); + } + + public void llGetPrimitiveParams() + { + m_LSL_Functions.llGetPrimitiveParams(); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public string llIntegerToBase64(int number) + { + return m_LSL_Functions.llIntegerToBase64(number); + } + + public int llBase64ToInteger(string str) + { + return m_LSL_Functions.llBase64ToInteger(str); + } + + public double llGetGMTclock() + { + return m_LSL_Functions.llGetGMTclock(); + } + + public string llGetSimulatorHostname() + { + return m_LSL_Functions.llGetSimulatorHostname(); + } + + public void llSetLocalRot(rotation rot) + { + m_LSL_Functions.llSetLocalRot(rot); + } + + public List llParseStringKeepNulls(string src, List seperators, List spacers) + { + return m_LSL_Functions.llParseStringKeepNulls(src, seperators, spacers); + } + + public void llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, int param) + { + m_LSL_Functions.llRezAtRoot(inventory, position, velocity, rot, param); + } + + public int llGetObjectPermMask(int mask) + { + return m_LSL_Functions.llGetObjectPermMask(mask); + } + + public void llSetObjectPermMask(int mask, int value) + { + m_LSL_Functions.llSetObjectPermMask(mask, value); + } + + public void llGetInventoryPermMask(string item, int mask) + { + m_LSL_Functions.llGetInventoryPermMask(item, mask); + } + + public void llSetInventoryPermMask(string item, int mask, int value) + { + m_LSL_Functions.llSetInventoryPermMask(item, mask, value); + } + + public string llGetInventoryCreator(string item) + { + return m_LSL_Functions.llGetInventoryCreator(item); + } + + public void llOwnerSay(string msg) + { + m_LSL_Functions.llOwnerSay(msg); + } + + public void llRequestSimulatorData(string simulator, int data) + { + m_LSL_Functions.llRequestSimulatorData(simulator, data); + } + + public void llForceMouselook(int mouselook) + { + m_LSL_Functions.llForceMouselook(mouselook); + } + + public double llGetObjectMass(string id) + { + return m_LSL_Functions.llGetObjectMass(id); + } + + public void llListReplaceList() + { + m_LSL_Functions.llListReplaceList(); + } + + public void llLoadURL(string avatar_id, string message, string url) + { + m_LSL_Functions.llLoadURL(avatar_id, message, url); + } + + public void llParcelMediaCommandList(List commandList) + { + m_LSL_Functions.llParcelMediaCommandList(commandList); + } + + public void llParcelMediaQuery() + { + m_LSL_Functions.llParcelMediaQuery(); + } + + public int llModPow(int a, int b, int c) + { + return m_LSL_Functions.llModPow(a, b, c); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public int llGetInventoryType(string name) + { + return m_LSL_Functions.llGetInventoryType(name); + } + + public void llSetPayPrice(int price, List quick_pay_buttons) + { + m_LSL_Functions.llSetPayPrice(price, quick_pay_buttons); + } + + public vector llGetCameraPos() + { + return m_LSL_Functions.llGetCameraPos(); + } + + public rotation llGetCameraRot() + { + return m_LSL_Functions.llGetCameraRot(); + } + + public void llSetPrimURL() + { + m_LSL_Functions.llSetPrimURL(); + } + + public void llRefreshPrimURL() + { + m_LSL_Functions.llRefreshPrimURL(); + } + + public string llEscapeURL(string url) + { + return m_LSL_Functions.llEscapeURL(url); + } + + public string llUnescapeURL(string url) + { + return m_LSL_Functions.llUnescapeURL(url); + } + + public void llMapDestination(string simname, vector pos, vector look_at) + { + m_LSL_Functions.llMapDestination(simname, pos, look_at); + } + + public void llAddToLandBanList(string avatar, double hours) + { + m_LSL_Functions.llAddToLandBanList(avatar, hours); + } + + public void llRemoveFromLandPassList(string avatar) + { + m_LSL_Functions.llRemoveFromLandPassList(avatar); + } + + public void llRemoveFromLandBanList(string avatar) + { + m_LSL_Functions.llRemoveFromLandBanList(avatar); + } + + public void llSetCameraParams(List rules) + { + m_LSL_Functions.llSetCameraParams(rules); + } + + public void llClearCameraParams() + { + m_LSL_Functions.llClearCameraParams(); + } + + public double llListStatistics(int operation, List src) + { + return m_LSL_Functions.llListStatistics(operation, src); + } + + public int llGetUnixTime() + { + return m_LSL_Functions.llGetUnixTime(); + } + + public int llGetParcelFlags(vector pos) + { + return m_LSL_Functions.llGetParcelFlags(pos); + } + + public int llGetRegionFlags() + { + return m_LSL_Functions.llGetRegionFlags(); + } + + public string llXorBase64StringsCorrect(string str1, string str2) + { + return m_LSL_Functions.llXorBase64StringsCorrect(str1, str2); + } + + public void llHTTPRequest(string url, List parameters, string body) + { + m_LSL_Functions.llHTTPRequest(url, parameters, body); + } + + public void llResetLandBanList() + { + m_LSL_Functions.llResetLandBanList(); + } + + public void llResetLandPassList() + { + m_LSL_Functions.llResetLandPassList(); + } + + public int llGetParcelPrimCount(vector pos, int category, int sim_wide) + { + return m_LSL_Functions.llGetParcelPrimCount(pos, category, sim_wide); + } + + public List llGetParcelPrimOwners(vector pos) + { + return m_LSL_Functions.llGetParcelPrimOwners(pos); + } + + public int llGetObjectPrimCount(string object_id) + { + return m_LSL_Functions.llGetObjectPrimCount(object_id); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public int llGetParcelMaxPrims(vector pos, int sim_wide) + { + return m_LSL_Functions.llGetParcelMaxPrims(pos, sim_wide); + } + + public List llGetParcelDetails(vector pos, List param) + { + return m_LSL_Functions.llGetParcelDetails(pos, param); + } + + // + // OpenSim Functions + // + public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, + int timer) + { + return m_LSL_Functions.osSetDynamicTextureURL(dynamicID, contentType, url, extraParams, timer); + } + + // LSL CONSTANTS + public const int TRUE = 1; + public const int FALSE = 0; + public const int STATUS_PHYSICS = 1; + public const int STATUS_ROTATE_X = 2; + public const int STATUS_ROTATE_Y = 4; + public const int STATUS_ROTATE_Z = 8; + public const int STATUS_PHANTOM = 16; + public const int STATUS_SANDBOX = 32; + public const int STATUS_BLOCK_GRAB = 64; + public const int STATUS_DIE_AT_EDGE = 128; + public const int STATUS_RETURN_AT_EDGE = 256; + public const int AGENT = 1; + public const int ACTIVE = 2; + public const int PASSIVE = 4; + public const int SCRIPTED = 8; + public const int CONTROL_FWD = 1; + public const int CONTROL_BACK = 2; + public const int CONTROL_LEFT = 4; + public const int CONTROL_RIGHT = 8; + public const int CONTROL_UP = 16; + public const int CONTROL_DOWN = 32; + public const int CONTROL_ROT_LEFT = 256; + public const int CONTROL_ROT_RIGHT = 512; + public const int CONTROL_LBUTTON = 268435456; + public const int CONTROL_ML_LBUTTON = 1073741824; + public const int PERMISSION_DEBIT = 2; + public const int PERMISSION_TAKE_CONTROLS = 4; + public const int PERMISSION_REMAP_CONTROLS = 8; + public const int PERMISSION_TRIGGER_ANIMATION = 16; + public const int PERMISSION_ATTACH = 32; + public const int PERMISSION_RELEASE_OWNERSHIP = 64; + public const int PERMISSION_CHANGE_LINKS = 128; + public const int PERMISSION_CHANGE_JOINTS = 256; + public const int PERMISSION_CHANGE_PERMISSIONS = 512; + public const int PERMISSION_TRACK_CAMERA = 1024; + public const int AGENT_FLYING = 1; + public const int AGENT_ATTACHMENTS = 2; + public const int AGENT_SCRIPTED = 4; + public const int AGENT_MOUSELOOK = 8; + public const int AGENT_SITTING = 16; + public const int AGENT_ON_OBJECT = 32; + public const int AGENT_AWAY = 64; + public const int AGENT_WALKING = 128; + public const int AGENT_IN_AIR = 256; + public const int AGENT_TYPING = 512; + public const int AGENT_CROUCHING = 1024; + public const int AGENT_BUSY = 2048; + public const int AGENT_ALWAYS_RUN = 4096; + public const int PSYS_PART_INTERP_COLOR_MASK = 1; + public const int PSYS_PART_INTERP_SCALE_MASK = 2; + public const int PSYS_PART_BOUNCE_MASK = 4; + public const int PSYS_PART_WIND_MASK = 8; + public const int PSYS_PART_FOLLOW_SRC_MASK = 16; + public const int PSYS_PART_FOLLOW_VELOCITY_MASK = 32; + public const int PSYS_PART_TARGET_POS_MASK = 64; + public const int PSYS_PART_TARGET_LINEAR_MASK = 128; + public const int PSYS_PART_EMISSIVE_MASK = 256; + public const int PSYS_PART_FLAGS = 0; + public const int PSYS_PART_START_COLOR = 1; + public const int PSYS_PART_START_ALPHA = 2; + public const int PSYS_PART_END_COLOR = 3; + public const int PSYS_PART_END_ALPHA = 4; + public const int PSYS_PART_START_SCALE = 5; + public const int PSYS_PART_END_SCALE = 6; + public const int PSYS_PART_MAX_AGE = 7; + public const int PSYS_SRC_ACCEL = 8; + public const int PSYS_SRC_PATTERN = 9; + public const int PSYS_SRC_INNERANGLE = 10; + public const int PSYS_SRC_OUTERANGLE = 11; + public const int PSYS_SRC_TEXTURE = 12; + public const int PSYS_SRC_BURST_RATE = 13; + public const int PSYS_SRC_BURST_PART_COUNT = 15; + public const int PSYS_SRC_BURST_RADIUS = 16; + public const int PSYS_SRC_BURST_SPEED_MIN = 17; + public const int PSYS_SRC_BURST_SPEED_MAX = 18; + public const int PSYS_SRC_MAX_AGE = 19; + public const int PSYS_SRC_TARGET_KEY = 20; + public const int PSYS_SRC_OMEGA = 21; + public const int PSYS_SRC_ANGLE_BEGIN = 22; + public const int PSYS_SRC_ANGLE_END = 23; + public const int PSYS_SRC_PATTERN_DROP = 1; + public const int PSYS_SRC_PATTERN_EXPLODE = 2; + public const int PSYS_SRC_PATTERN_ANGLE = 4; + public const int PSYS_SRC_PATTERN_ANGLE_CONE = 8; + public const int PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY = 16; + public const int VEHICLE_TYPE_NONE = 0; + public const int VEHICLE_TYPE_SLED = 1; + public const int VEHICLE_TYPE_CAR = 2; + public const int VEHICLE_TYPE_BOAT = 3; + public const int VEHICLE_TYPE_AIRPLANE = 4; + public const int VEHICLE_TYPE_BALLOON = 5; + public const int VEHICLE_LINEAR_FRICTION_TIMESCALE = 16; + public const int VEHICLE_ANGULAR_FRICTION_TIMESCALE = 17; + public const int VEHICLE_LINEAR_MOTOR_DIRECTION = 18; + public const int VEHICLE_LINEAR_MOTOR_OFFSET = 20; + public const int VEHICLE_ANGULAR_MOTOR_DIRECTION = 19; + public const int VEHICLE_HOVER_HEIGHT = 24; + public const int VEHICLE_HOVER_EFFICIENCY = 25; + public const int VEHICLE_HOVER_TIMESCALE = 26; + public const int VEHICLE_BUOYANCY = 27; + public const int VEHICLE_LINEAR_DEFLECTION_EFFICIENCY = 28; + public const int VEHICLE_LINEAR_DEFLECTION_TIMESCALE = 29; + public const int VEHICLE_LINEAR_MOTOR_TIMESCALE = 30; + public const int VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE = 31; + public const int VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY = 32; + public const int VEHICLE_ANGULAR_DEFLECTION_TIMESCALE = 33; + public const int VEHICLE_ANGULAR_MOTOR_TIMESCALE = 34; + public const int VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE = 35; + public const int VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY = 36; + public const int VEHICLE_VERTICAL_ATTRACTION_TIMESCALE = 37; + public const int VEHICLE_BANKING_EFFICIENCY = 38; + public const int VEHICLE_BANKING_MIX = 39; + public const int VEHICLE_BANKING_TIMESCALE = 40; + public const int VEHICLE_REFERENCE_FRAME = 44; + public const int VEHICLE_FLAG_NO_DEFLECTION_UP = 1; + public const int VEHICLE_FLAG_LIMIT_ROLL_ONLY = 2; + public const int VEHICLE_FLAG_HOVER_WATER_ONLY = 4; + public const int VEHICLE_FLAG_HOVER_TERRAIN_ONLY = 8; + public const int VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT = 16; + public const int VEHICLE_FLAG_HOVER_UP_ONLY = 32; + public const int VEHICLE_FLAG_LIMIT_MOTOR_UP = 64; + public const int VEHICLE_FLAG_MOUSELOOK_STEER = 128; + public const int VEHICLE_FLAG_MOUSELOOK_BANK = 256; + public const int VEHICLE_FLAG_CAMERA_DECOUPLED = 512; + public const int INVENTORY_ALL = -1; + public const int INVENTORY_NONE = -1; + public const int INVENTORY_TEXTURE = 0; + public const int INVENTORY_SOUND = 1; + public const int INVENTORY_LANDMARK = 3; + public const int INVENTORY_CLOTHING = 5; + public const int INVENTORY_OBJECT = 6; + public const int INVENTORY_NOTECARD = 7; + public const int INVENTORY_SCRIPT = 10; + public const int INVENTORY_BODYPART = 13; + public const int INVENTORY_ANIMATION = 20; + public const int INVENTORY_GESTURE = 21; + public const int ATTACH_CHEST = 1; + public const int ATTACH_HEAD = 2; + public const int ATTACH_LSHOULDER = 3; + public const int ATTACH_RSHOULDER = 4; + public const int ATTACH_LHAND = 5; + public const int ATTACH_RHAND = 6; + public const int ATTACH_LFOOT = 7; + public const int ATTACH_RFOOT = 8; + public const int ATTACH_BACK = 9; + public const int ATTACH_PELVIS = 10; + public const int ATTACH_MOUTH = 11; + public const int ATTACH_CHIN = 12; + public const int ATTACH_LEAR = 13; + public const int ATTACH_REAR = 14; + public const int ATTACH_LEYE = 15; + public const int ATTACH_REYE = 16; + public const int ATTACH_NOSE = 17; + public const int ATTACH_RUARM = 18; + public const int ATTACH_RLARM = 19; + public const int ATTACH_LUARM = 20; + public const int ATTACH_LLARM = 21; + public const int ATTACH_RHIP = 22; + public const int ATTACH_RULEG = 23; + public const int ATTACH_RLLEG = 24; + public const int ATTACH_LHIP = 25; + public const int ATTACH_LULEG = 26; + public const int ATTACH_LLLEG = 27; + public const int ATTACH_BELLY = 28; + public const int ATTACH_RPEC = 29; + public const int ATTACH_LPEC = 30; + public const int LAND_LEVEL = 0; + public const int LAND_RAISE = 1; + public const int LAND_LOWER = 2; + public const int LAND_SMOOTH = 3; + public const int LAND_NOISE = 4; + public const int LAND_REVERT = 5; + public const int LAND_SMALL_BRUSH = 1; + public const int LAND_MEDIUM_BRUSH = 2; + public const int LAND_LARGE_BRUSH = 3; + public const int DATA_ONLINE = 1; + public const int DATA_NAME = 2; + public const int DATA_BORN = 3; + public const int DATA_RATING = 4; + public const int DATA_SIM_POS = 5; + public const int DATA_SIM_STATUS = 6; + public const int DATA_SIM_RATING = 7; + public const int ANIM_ON = 1; + public const int LOOP = 2; + public const int REVERSE = 4; + public const int PING_PONG = 8; + public const int SMOOTH = 16; + public const int ROTATE = 32; + public const int SCALE = 64; + public const int ALL_SIDES = -1; + public const int LINK_SET = -1; + public const int LINK_ROOT = 1; + public const int LINK_ALL_OTHERS = -2; + public const int LINK_ALL_CHILDREN = -3; + public const int LINK_THIS = -4; + public const int CHANGED_INVENTORY = 1; + public const int CHANGED_COLOR = 2; + public const int CHANGED_SHAPE = 4; + public const int CHANGED_SCALE = 8; + public const int CHANGED_TEXTURE = 16; + public const int CHANGED_LINK = 32; + public const int CHANGED_ALLOWED_DROP = 64; + public const int CHANGED_OWNER = 128; + public const int TYPE_INVALID = 0; + public const int TYPE_INTEGER = 1; + public const int TYPE_double = 2; + public const int TYPE_STRING = 3; + public const int TYPE_KEY = 4; + public const int TYPE_VECTOR = 5; + public const int TYPE_ROTATION = 6; + public const int REMOTE_DATA_CHANNEL = 1; + public const int REMOTE_DATA_REQUEST = 2; + public const int REMOTE_DATA_REPLY = 3; + //public const int PRIM_TYPE = 1; + public const int PRIM_MATERIAL = 2; + public const int PRIM_PHYSICS = 3; + public const int PRIM_TEMP_ON_REZ = 4; + public const int PRIM_PHANTOM = 5; + public const int PRIM_POSITION = 6; + public const int PRIM_SIZE = 7; + public const int PRIM_ROTATION = 8; + public const int PRIM_TYPE = 9; + public const int PRIM_TEXTURE = 17; + public const int PRIM_COLOR = 18; + public const int PRIM_BUMP_SHINY = 19; + public const int PRIM_FULLBRIGHT = 20; + public const int PRIM_FLEXIBLE = 21; + public const int PRIM_TEXGEN = 22; + public const int PRIM_TEXGEN_DEFAULT = 0; + public const int PRIM_TEXGEN_PLANAR = 1; + public const int PRIM_TYPE_BOX = 0; + public const int PRIM_TYPE_CYLINDER = 1; + public const int PRIM_TYPE_PRISM = 2; + public const int PRIM_TYPE_SPHERE = 3; + public const int PRIM_TYPE_TORUS = 4; + public const int PRIM_TYPE_TUBE = 5; + public const int PRIM_TYPE_RING = 6; + public const int PRIM_HOLE_DEFAULT = 0; + public const int PRIM_HOLE_CIRCLE = 16; + public const int PRIM_HOLE_SQUARE = 32; + public const int PRIM_HOLE_TRIANGLE = 48; + public const int PRIM_MATERIAL_STONE = 0; + public const int PRIM_MATERIAL_METAL = 1; + public const int PRIM_MATERIAL_GLASS = 2; + public const int PRIM_MATERIAL_WOOD = 3; + public const int PRIM_MATERIAL_FLESH = 4; + public const int PRIM_MATERIAL_PLASTIC = 5; + public const int PRIM_MATERIAL_RUBBER = 6; + public const int PRIM_MATERIAL_LIGHT = 7; + public const int PRIM_SHINY_NONE = 0; + public const int PRIM_SHINY_LOW = 1; + public const int PRIM_SHINY_MEDIUM = 2; + public const int PRIM_SHINY_HIGH = 3; + public const int PRIM_BUMP_NONE = 0; + public const int PRIM_BUMP_BRIGHT = 1; + public const int PRIM_BUMP_DARK = 2; + public const int PRIM_BUMP_WOOD = 3; + public const int PRIM_BUMP_BARK = 4; + public const int PRIM_BUMP_BRICKS = 5; + public const int PRIM_BUMP_CHECKER = 6; + public const int PRIM_BUMP_CONCRETE = 7; + public const int PRIM_BUMP_TILE = 8; + public const int PRIM_BUMP_STONE = 9; + public const int PRIM_BUMP_DISKS = 10; + public const int PRIM_BUMP_GRAVEL = 11; + public const int PRIM_BUMP_BLOBS = 12; + public const int PRIM_BUMP_SIDING = 13; + public const int PRIM_BUMP_LARGETILE = 14; + public const int PRIM_BUMP_STUCCO = 15; + public const int PRIM_BUMP_SUCTION = 16; + public const int PRIM_BUMP_WEAVE = 17; + public const int MASK_BASE = 0; + public const int MASK_OWNER = 1; + public const int MASK_GROUP = 2; + public const int MASK_EVERYONE = 3; + public const int MASK_NEXT = 4; + public const int PERM_TRANSFER = 8192; + public const int PERM_MODIFY = 16384; + public const int PERM_COPY = 32768; + public const int PERM_MOVE = 524288; + public const int PERM_ALL = 2147483647; + public const int PARCEL_MEDIA_COMMAND_STOP = 0; + public const int PARCEL_MEDIA_COMMAND_PAUSE = 1; + public const int PARCEL_MEDIA_COMMAND_PLAY = 2; + public const int PARCEL_MEDIA_COMMAND_LOOP = 3; + public const int PARCEL_MEDIA_COMMAND_TEXTURE = 4; + public const int PARCEL_MEDIA_COMMAND_URL = 5; + public const int PARCEL_MEDIA_COMMAND_TIME = 6; + public const int PARCEL_MEDIA_COMMAND_AGENT = 7; + public const int PARCEL_MEDIA_COMMAND_UNLOAD = 8; + public const int PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9; + public const int PAY_HIDE = -1; + public const int PAY_DEFAULT = -2; + public const string NULL_KEY = "00000000-0000-0000-0000-000000000000"; + public const string EOF = "\n\n\n"; + public const double PI = 3.14159274f; + public const double TWO_PI = 6.28318548f; + public const double PI_BY_TWO = 1.57079637f; + public const double DEG_TO_RAD = 0.01745329238f; + public const double RAD_TO_DEG = 57.29578f; + public const double SQRT2 = 1.414213538f; + + // Can not be public const? + public vector ZERO_VECTOR = new vector(0, 0, 0); + public rotation ZERO_ROTATION = new rotation(0, 0, 0, 0); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/Common.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/Common.cs new file mode 100644 index 0000000000..6fe194a072 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/Common.cs @@ -0,0 +1,87 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO +{ + public static class Common + { + public static bool Debug = true; + public static bool IL_UseTryCatch = true; + public static bool IL_CreateConstructor = true; + public static bool IL_CreateFunctionList = true; + public static bool IL_ProcessCodeChunks = true; + + public delegate void SendToDebugEventDelegate(string Message); + + public delegate void SendToLogEventDelegate(string Message); + + public static event SendToDebugEventDelegate SendToDebugEvent; + public static event SendToLogEventDelegate SendToLogEvent; + + public static void SendToDebug(string Message) + { + //if (Debug == true) + Console.WriteLine("COMPILER:Debug: " + Message); + SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + + public static void SendToLog(string Message) + { + //if (Debug == true) + Console.WriteLine("COMPILER:LOG: " + Message); + SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + } + + // TEMPORARY TEST THINGIES + public static class IL_Helper + { + public static string ReverseFormatString(string text1, string format) + { + Common.SendToDebug("ReverseFormatString text1: " + text1); + Common.SendToDebug("ReverseFormatString format: " + format); + return string.Format(format, text1); + } + + public static string ReverseFormatString(string text1, UInt32 text2, string format) + { + Common.SendToDebug("ReverseFormatString text1: " + text1); + Common.SendToDebug("ReverseFormatString text2: " + text2.ToString()); + Common.SendToDebug("ReverseFormatString format: " + format); + return string.Format(format, text1, text2.ToString()); + } + + public static string Cast_ToString(object obj) + { + Common.SendToDebug("OBJECT TO BE CASTED: " + obj.GetType().ToString()); + return "ABCDEFGIHJKLMNOPQ123"; + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/Engine.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/Engine.cs new file mode 100644 index 0000000000..aedf6e2a67 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/Engine.cs @@ -0,0 +1,291 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.IO; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO +{ + public class Engine + { + //private string LSO_FileName = @"LSO\AdditionTest.lso"; + private string LSO_FileName; // = @"LSO\CloseToDefault.lso"; + private AppDomain appDomain; + + public string Compile(string LSOFileName) + { + LSO_FileName = LSOFileName; + + + //appDomain = AppDomain.CreateDomain("AlternateAppDomain"); + appDomain = Thread.GetDomain(); + + // Create Assembly Name + AssemblyName asmName = new AssemblyName(); + asmName.Name = Path.GetFileNameWithoutExtension(LSO_FileName); + //asmName.Name = "TestAssembly"; + + string DLL_FileName = asmName.Name + ".dll"; + string DLL_FileName_WithPath = Path.GetDirectoryName(LSO_FileName) + @"\" + DLL_FileName; + + Common.SendToLog("LSO File Name: " + Path.GetFileName(LSO_FileName)); + Common.SendToLog("Assembly name: " + asmName.Name); + Common.SendToLog("Assembly File Name: " + asmName.Name + ".dll"); + Common.SendToLog("Starting processing of LSL ByteCode..."); + Common.SendToLog(""); + + + // Create Assembly + AssemblyBuilder asmBuilder = appDomain.DefineDynamicAssembly( + asmName, + AssemblyBuilderAccess.RunAndSave + ); + //// Create Assembly + //AssemblyBuilder asmBuilder = + // Thread.GetDomain().DefineDynamicAssembly + //(asmName, AssemblyBuilderAccess.RunAndSave); + + // Create a module (and save to disk) + ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule + (asmName.Name, + DLL_FileName); + + //Common.SendToDebug("asmName.Name is still \"" + asmName.Name + "\""); + // Create a Class (/Type) + TypeBuilder typeBuilder = modBuilder.DefineType( + "LSL_ScriptObject", + TypeAttributes.Public | TypeAttributes.BeforeFieldInit, + typeof (LSL_BaseClass)); + //, + // typeof()); + //, typeof(LSL_BuiltIn_Commands_Interface)); + //, + // typeof(object), + // new Type[] { typeof(LSL_CLRInterface.LSLScript) }); + + + /* + * Generate the IL itself + */ + + LSO_Parser LSOP = new LSO_Parser(LSO_FileName, typeBuilder); + LSOP.OpenFile(); + LSOP.Parse(); + + // Constructor has to be created AFTER LSO_Parser because of accumulated variables + if (Common.IL_CreateConstructor) + IL_CREATE_CONSTRUCTOR(typeBuilder, LSOP); + + LSOP.CloseFile(); + /* + * Done generating. Create a type and run it. + */ + + + Common.SendToLog("Attempting to compile assembly..."); + // Compile it + Type type = typeBuilder.CreateType(); + Common.SendToLog("Compilation successful!"); + + Common.SendToLog("Saving assembly: " + DLL_FileName); + asmBuilder.Save(DLL_FileName); + + Common.SendToLog("Returning assembly filename: " + DLL_FileName); + + + return DLL_FileName; + + + //Common.SendToLog("Creating an instance of new assembly..."); + //// Create an instance we can play with + ////LSLScript hello = (LSLScript)Activator.CreateInstance(type); + ////LSL_CLRInterface.LSLScript MyScript = (LSL_CLRInterface.LSLScript)Activator.CreateInstance(type); + //object MyScript = (object)Activator.CreateInstance(type); + + + //System.Reflection.MemberInfo[] Members = type.GetMembers(); + + //Common.SendToLog("Members of assembly " + type.ToString() + ":"); + //foreach (MemberInfo member in Members) + // Common.SendToLog(member.ToString()); + + + //// Play with it + ////MyScript.event_state_entry("Test"); + //object[] args = { null }; + ////System.Collections.Generic.List Functions = (System.Collections.Generic.List)type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, MyScript, null); + + //string[] ret = { }; + //if (Common.IL_CreateFunctionList) + // ret = (string[])type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, MyScript, null); + + //foreach (string s in ret) + //{ + // Common.SendToLog(""); + // Common.SendToLog("*** Executing LSL Server Event: " + s); + // //object test = type.GetMember(s); + // //object runner = type.InvokeMember(s, BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, MyScript, args); + // //runner(); + // //objBooks_Late = type.InvokeMember(s, BindingFlags.CreateInstance, null, objApp_Late, null); + // type.InvokeMember(s, BindingFlags.InvokeMethod, null, MyScript, new object[] { "Test" }); + + //} + } + + + private static void IL_CREATE_CONSTRUCTOR(TypeBuilder typeBuilder, LSO_Parser LSOP) + { + Common.SendToDebug("IL_CREATE_CONSTRUCTOR()"); + //ConstructorBuilder constructor = typeBuilder.DefineConstructor( + // MethodAttributes.Public, + // CallingConventions.Standard, + // new Type[0]); + ConstructorBuilder constructor = typeBuilder.DefineConstructor( + MethodAttributes.Public | + MethodAttributes.SpecialName | + MethodAttributes.RTSpecialName, + CallingConventions.Standard, + new Type[0]); + + //Define the reflection ConstructorInfor for System.Object + ConstructorInfo conObj = typeof (LSL_BaseClass).GetConstructor(new Type[0]); + + //call constructor of base object + ILGenerator il = constructor.GetILGenerator(); + + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, conObj); + + + //Common.SendToDebug("IL_CREATE_CONSTRUCTOR: Creating global: UInt32 State = 0;"); + //string FieldName; + //// Create state object + //FieldName = "State"; + //FieldBuilder State_fb = typeBuilder.DefineField( + // FieldName, + // typeof(UInt32), + // FieldAttributes.Public); + //il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Ldc_I4, 0); + //il.Emit(OpCodes.Stfld, State_fb); + + + //Common.SendToDebug("IL_CREATE_CONSTRUCTOR: Creating global: LSL_BuiltIn_Commands_TestImplementation LSL_BuiltIns = New LSL_BuiltIn_Commands_TestImplementation();"); + ////Type objType1 = typeof(object); + //Type objType1 = typeof(LSL_BuiltIn_Commands_TestImplementation); + + //FieldName = "LSL_BuiltIns"; + //FieldBuilder LSL_BuiltIns_fb = typeBuilder.DefineField( + // FieldName, + // objType1, + // FieldAttributes.Public); + + ////LSL_BuiltIn_Commands_TestImplementation _ti = new LSL_BuiltIn_Commands_TestImplementation(); + //il.Emit(OpCodes.Ldarg_0); + ////il.Emit(OpCodes.Ldstr, "Test 123"); + //il.Emit(OpCodes.Newobj, objType1.GetConstructor(new Type[] { })); + //il.Emit(OpCodes.Stfld, LSL_BuiltIns_fb); + + foreach (UInt32 pos in LSOP.StaticBlocks.Keys) + { + LSO_Struct.StaticBlock sb; + LSOP.StaticBlocks.TryGetValue(pos, out sb); + + if (sb.ObjectType > 0 && sb.ObjectType < 8) + { + // We don't want void or null's + + il.Emit(OpCodes.Ldarg_0); + // Push position to stack + il.Emit(OpCodes.Ldc_I4, pos); + //il.Emit(OpCodes.Box, typeof(UInt32)); + + + Type datatype = null; + + // Push data to stack + Common.SendToDebug("Adding to static (" + pos + ") type: " + + ((LSO_Enums.Variable_Type_Codes) sb.ObjectType).ToString() + " (" + sb.ObjectType + + ")"); + switch ((LSO_Enums.Variable_Type_Codes) sb.ObjectType) + { + case LSO_Enums.Variable_Type_Codes.Float: + case LSO_Enums.Variable_Type_Codes.Integer: + //UInt32 + il.Emit(OpCodes.Ldc_I4, BitConverter.ToUInt32(sb.BlockVariable, 0)); + datatype = typeof (UInt32); + il.Emit(OpCodes.Box, datatype); + break; + case LSO_Enums.Variable_Type_Codes.String: + case LSO_Enums.Variable_Type_Codes.Key: + //String + LSO_Struct.HeapBlock hb = + LSOP.GetHeap(LSOP.myHeader.HR + BitConverter.ToUInt32(sb.BlockVariable, 0) - 1); + il.Emit(OpCodes.Ldstr, Encoding.UTF8.GetString(hb.Data)); + datatype = typeof (string); + break; + case LSO_Enums.Variable_Type_Codes.Vector: + datatype = typeof (LSO_Enums.Vector); + //TODO: Not implemented + break; + case LSO_Enums.Variable_Type_Codes.Rotation: + //Object + //TODO: Not implemented + datatype = typeof (LSO_Enums.Rotation); + break; + default: + datatype = typeof (object); + break; + } + + + // Make call + il.Emit(OpCodes.Call, + typeof (LSL_BaseClass).GetMethod("AddToStatic", new Type[] {typeof (UInt32), datatype})); + } + } + + + ////il.Emit(OpCodes.Newobj, typeof(UInt32)); + //il.Emit(OpCodes.Starg_0); + //// Create LSL function library + //FieldBuilder LSL_BuiltIns_fb = typeBuilder.DefineField("LSL_BuiltIns", typeof(LSL_BuiltIn_Commands_Interface), FieldAttributes.Public); + //il.Emit(OpCodes.Newobj, typeof(LSL_BuiltIn_Commands_Interface)); + //il.Emit(OpCodes.Stloc_1); + + il.Emit(OpCodes.Ret); + } + + + // End of class + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/IL_common_functions.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/IL_common_functions.cs new file mode 100644 index 0000000000..a27d71ad4f --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/IL_common_functions.cs @@ -0,0 +1,51 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Reflection; +using System.Reflection.Emit; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO +{ + internal partial class LSO_Parser + { + private static TypeBuilder CreateType(ModuleBuilder modBuilder, string typeName) + { + TypeBuilder typeBuilder = modBuilder.DefineType(typeName, + TypeAttributes.Public | + TypeAttributes.Class | + TypeAttributes.AutoClass | + TypeAttributes.AnsiClass | + TypeAttributes.BeforeFieldInit | + TypeAttributes.AutoLayout, + typeof (object), + new Type[] {typeof (object)}); + return typeBuilder; + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_BaseClass.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_BaseClass.cs new file mode 100644 index 0000000000..46da5f8363 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_BaseClass.cs @@ -0,0 +1,86 @@ +/* +* 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; +using System.Collections.Generic; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO +{ + public partial class LSL_BaseClass + { + //public MemoryStream LSLStack = new MemoryStream(); + public Stack LSLStack = new Stack(); + public Dictionary StaticVariables = new Dictionary(); + public Dictionary GlobalVariables = new Dictionary(); + public Dictionary LocalVariables = new Dictionary(); + //public System.Collections.Generic.List FunctionList = new System.Collections.Generic.List(); + //public void AddFunction(String x) { + // FunctionList.Add(x); + //} + //public Stack LSLStack = new Stack; + //public struct StackItemStruct + //{ + // public LSO_Enums.Variable_Type_Codes ItemType; + // public object Data; + //} + public UInt32 State = 0; + public LSL_BuiltIn_Commands_Interface LSL_Builtins; + + public LSL_BuiltIn_Commands_Interface GetLSL_BuiltIn() + { + return LSL_Builtins; + } + + + public LSL_BaseClass() + { + } + + + public virtual int OverrideMe() + { + return 0; + } + + public void Start(LSL_BuiltIn_Commands_Interface LSLBuiltins) + { + LSL_Builtins = LSLBuiltins; + + Common.SendToLog("OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO.LSL_BaseClass.Start() called"); + //LSL_Builtins.llSay(0, "Test"); + return; + } + + public void AddToStatic(UInt32 index, object obj) + { + Common.SendToDebug("AddToStatic: " + index + " type: " + obj.GetType()); + StaticVariables.Add(index, obj); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_BaseClass_Builtins.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_BaseClass_Builtins.cs new file mode 100644 index 0000000000..b9958f49b1 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_BaseClass_Builtins.cs @@ -0,0 +1,401 @@ +/* +* 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; +//using System.Collections.Generic; +//using System.Text; + +//namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO +//{ +// public partial class LSL_BaseClass +// { + + +// public float llSin() { +// float f = (float)LSLStack.Pop(); +// return LSL_Builtins.llSin(f); +// } +// public float llCos() { +// float f = (float)LSLStack.Pop(); +// return LSL_Builtins.llCos(f); +// } +// public float llTan() { +// float f = (float)LSLStack.Pop(); +// return LSL_Builtins.llTan(f); +// } +// public float llAtan2() { +// float x = (float)LSLStack.Pop(); +// float y = (float)LSLStack.Pop(); +// return LSL_Builtins.llAtan2(x, y); +// } +// public float llSqrt() { +// float f = (float)LSLStack.Pop(); +// return LSL_Builtins.llSqrt(f); +// } +// float llPow() +// { +// float fexponent = (float)LSLStack.Pop(); +// float fbase = (float)LSLStack.Pop(); +// return LSL_Builtins.llPow(fbase, fexponent); +// } +// //UInt32 llAbs(UInt32 i){ return; } +// //float llFabs(float f){ return; } +// //float llFrand(float mag){ return; } +// //UInt32 llFloor(float f){ return; } +// //UInt32 llCeil(float f){ return; } +// //UInt32 llRound(float f){ return; } +// //float llVecMag(LSO_Enums.Vector v){ return; } +// //LSO_Enums.Vector llVecNorm(LSO_Enums.Vector v){ return; } +// //float llVecDist(LSO_Enums.Vector a, LSO_Enums.Vector b){ return; } +// //LSO_Enums.Vector llRot2Euler(LSO_Enums.Rotation r){ return; } +// //LSO_Enums.Rotation llEuler2Rot(LSO_Enums.Vector v){ return; } +// //LSO_Enums.Rotation llAxes2Rot(LSO_Enums.Vector fwd, LSO_Enums.Vector left, LSO_Enums.Vector up){ return; } +// //LSO_Enums.Vector llRot2Fwd(LSO_Enums.Rotation r){ return; } +// //LSO_Enums.Vector llRot2Left(LSO_Enums.Rotation r){ return; } +// //LSO_Enums.Vector llRot2Up(LSO_Enums.Rotation r){ return; } +// //LSO_Enums.Rotation llRotBetween(LSO_Enums.Vector start, LSO_Enums.Vector end){ return; } +// public void llWhisper() +// { +// UInt16 i = (UInt16)LSLStack.Pop(); +// string s = (string)LSLStack.Pop(); +// LSL_Builtins.llWhisper(i, s); +// } +// public void llSay() +// { +// UInt16 i = (UInt16)LSLStack.Pop(); +// string s = (string)LSLStack.Pop(); +// LSL_Builtins.llSay(i, s); +// } +// //void llShout(UInt16 channelID, string text); +// //UInt32 llListen(UInt16 channelID, string name, LSO_Enums.Key ID, string msg); +// //void llListenControl(UInt32 number, UInt32 active); +// //void llListenRemove(UInt32 number); +// //void llSensor(string name, LSO_Enums.Key id, UInt32 type, float range, float arc); +// //void llSensorRepeat(string name, LSO_Enums.Key id, UInt32 type, float range, float arc, float rate); +// //void llSensorRemove(); +// //string llDetectedName(UInt32 number); +// //LSO_Enums.Key llDetectedKey(UInt32 number); +// //LSO_Enums.Key llDetectedOwner(UInt32 number); +// //UInt32 llDetectedType(UInt32 number); +// //LSO_Enums.Vector llDetectedPos(UInt32 number); +// //LSO_Enums.Vector llDetectedVel(UInt32 number); +// //LSO_Enums.Vector llDetectedGrab(UInt32 number); +// //LSO_Enums.Rotation llDetectedRot(UInt32 number); +// //UInt32 llDetectedGroup(UInt32 number); +// //UInt32 llDetectedLinkNumber(UInt32 number); +// //void llDie(); +// //float llGround(LSO_Enums.Vector offset); +// //float llCloud(LSO_Enums.Vector offset); +// //LSO_Enums.Vector llWind(LSO_Enums.Vector offset); +// //void llSetStatus(UInt32 status, UInt32 value); +// //UInt32 llGetStatus(UInt32 status); +// //void llSetScale(LSO_Enums.Vector scale); +// //LSO_Enums.Vector llGetScale(); +// //void llSetColor(); +// //float llGetAlpha(); +// //void llSetAlpha(); +// //LSO_Enums.Vector llGetColor(); +// //void llSetTexture(); +// //void llScaleTexture(); +// //void llOffsetTexture(); +// //void llRotateTexture(); +// //string llGetTexture(); +// //void llSetPos(); + +// public void llGetPos() { } +// public void llGetLocalPos() { } +// public void llSetRot() { } +// public void llGetRot() { } +// public void llGetLocalRot() { } +// public void llSetForce() { } +// public void llGetForce() { } +// public void llTarget() { } +// public void llTargetRemove() { } +// public void llRotTarget() { } +// public void llRotTargetRemove() { } +// public void llMoveToTarget() { } +// public void llStopMoveToTarget() { } +// public void llApplyImpulse() { } +// public void llApplyRotationalImpulse() { } +// public void llSetTorque() { } +// public void llGetTorque() { } +// public void llSetForceAndTorque() { } +// public void llGetVel() { } +// public void llGetAccel() { } +// public void llGetOmega() { } +// public void llGetTimeOfDay() { } +// public void llGetWallclock() { } +// public void llGetTime() { } +// public void llResetTime() { } +// public void llGetAndResetTime() { } +// public void llSound() { } +// public void llPlaySound() { } +// public void llLoopSound() { } +// public void llLoopSoundMaster() { } +// public void llLoopSoundSlave() { } +// public void llPlaySoundSlave() { } +// public void llTriggerSound() { } +// public void llStopSound() { } +// public void llPreloadSound() { } +// public void llGetSubString() { } +// public void llDeleteSubString() { } +// public void llInsertString() { } +// public void llToUpper() { } +// public void llToLower() { } +// public void llGiveMoney() { } +// public void llMakeExplosion() { } +// public void llMakeFountain() { } +// public void llMakeSmoke() { } +// public void llMakeFire() { } +// public void llRezObject() { } +// public void llLookAt() { } +// public void llStopLookAt() { } +// public void llSetTimerEvent() { } +// public void llSleep() { } +// public void llGetMass() { } +// public void llCollisionFilter() { } +// public void llTakeControls() { } +// public void llReleaseControls() { } +// public void llAttachToAvatar() { } +// public void llDetachFromAvatar() { } +// public void llTakeCamera() { } +// public void llReleaseCamera() { } +// public void llGetOwner() { } +// public void llInstantMessage() { } +// public void llEmail() { } +// public void llGetNextEmail() { } +// public void llGetKey() { } +// public void llSetBuoyancy() { } +// public void llSetHoverHeight() { } +// public void llStopHover() { } +// public void llMinEventDelay() { } +// public void llSoundPreload() { } +// public void llRotLookAt() { } +// public void llStringLength() { } +// public void llStartAnimation() { } +// public void llStopAnimation() { } +// public void llPointAt() { } +// public void llStopPointAt() { } +// public void llTargetOmega() { } +// public void llGetStartParameter() { } +// public void llGodLikeRezObject() { } +// public void llRequestPermissions() { } +// public void llGetPermissionsKey() { } +// public void llGetPermissions() { } +// public void llGetLinkNumber() { } +// public void llSetLinkColor() { } +// public void llCreateLink() { } +// public void llBreakLink() { } +// public void llBreakAllLinks() { } +// public void llGetLinkKey() { } +// public void llGetLinkName() { } +// public void llGetInventoryNumber() { } +// public void llGetInventoryName() { } +// public void llSetScriptState() { } +// public void llGetEnergy() { } +// public void llGiveInventory() { } +// public void llRemoveInventory() { } +// public void llSetText() { } +// public void llWater() { } +// public void llPassTouches() { } +// public void llRequestAgentData() { } +// public void llRequestInventoryData() { } +// public void llSetDamage() { } +// public void llTeleportAgentHome() { } +// public void llModifyLand() { } +// public void llCollisionSound() { } +// public void llCollisionSprite() { } +// public void llGetAnimation() { } +// public void llResetScript() { } +// public void llMessageLinked() { } +// public void llPushObject() { } +// public void llPassCollisions() { } +// public void llGetScriptName() { } +// public void llGetNumberOfSides() { } +// public void llAxisAngle2Rot() { } +// public void llRot2Axis() { } +// public void llRot2Angle() { } +// public void llAcos() { } +// public void llAsin() { } +// public void llAngleBetween() { } +// public void llGetInventoryKey() { } +// public void llAllowInventoryDrop() { } +// public void llGetSunDirection() { } +// public void llGetTextureOffset() { } +// public void llGetTextureScale() { } +// public void llGetTextureRot() { } +// public void llSubStringIndex() { } +// public void llGetOwnerKey() { } +// public void llGetCenterOfMass() { } +// public void llListSort() { } +// public void llGetListLength() { } +// public void llList2Integer() { } +// public void llList2Float() { } +// public void llList2String() { } +// public void llList2Key() { } +// public void llList2Vector() { } +// public void llList2Rot() { } +// public void llList2List() { } +// public void llDeleteSubList() { } +// public void llGetListEntryType() { } +// public void llList2CSV() { } +// public void llCSV2List() { } +// public void llListRandomize() { } +// public void llList2ListStrided() { } +// public void llGetRegionCorner() { } +// public void llListInsertList() { } +// public void llListFindList() { } +// public void llGetObjectName() { } +// public void llSetObjectName() { } +// public void llGetDate() { } +// public void llEdgeOfWorld() { } +// public void llGetAgentInfo() { } +// public void llAdjustSoundVolume() { } +// public void llSetSoundQueueing() { } +// public void llSetSoundRadius() { } +// public void llKey2Name() { } +// public void llSetTextureAnim() { } +// public void llTriggerSoundLimited() { } +// public void llEjectFromLand() { } +// public void llParseString2List() { } +// public void llOverMyLand() { } +// public void llGetLandOwnerAt() { } +// public void llGetNotecardLine() { } +// public void llGetAgentSize() { } +// public void llSameGroup() { } +// public void llUnSit() { } +// public void llGroundSlope() { } +// public void llGroundNormal() { } +// public void llGroundContour() { } +// public void llGetAttached() { } +// public void llGetFreeMemory() { } +// public void llGetRegionName() { } +// public void llGetRegionTimeDilation() { } +// public void llGetRegionFPS() { } +// public void llParticleSystem() { } +// public void llGroundRepel() { } +// public void llGiveInventoryList() { } +// public void llSetVehicleType() { } +// public void llSetVehicleFloatParam() { } +// public void llSetVehicleVectorParam() { } +// public void llSetVehicleRotationParam() { } +// public void llSetVehicleFlags() { } +// public void llRemoveVehicleFlags() { } +// public void llSitTarget() { } +// public void llAvatarOnSitTarget() { } +// public void llAddToLandPassList() { } +// public void llSetTouchText() { } +// public void llSetSitText() { } +// public void llSetCameraEyeOffset() { } +// public void llSetCameraAtOffset() { } +// public void llDumpList2String() { } +// public void llScriptDanger() { } +// public void llDialog() { } +// public void llVolumeDetect() { } +// public void llResetOtherScript() { } +// public void llGetScriptState() { } +// public void llRemoteLoadScript() { } +// public void llSetRemoteScriptAccessPin() { } +// public void llRemoteLoadScriptPin() { } +// public void llOpenRemoteDataChannel() { } +// public void llSendRemoteData() { } +// public void llRemoteDataReply() { } +// public void llCloseRemoteDataChannel() { } +// public void llMD5String() { } +// public void llSetPrimitiveParams() { } +// public void llStringToBase64() { } +// public void llBase64ToString() { } +// public void llXorBase64Strings() { } +// public void llRemoteDataSetRegion() { } +// public void llLog10() { } +// public void llLog() { } +// public void llGetAnimationList() { } +// public void llSetParcelMusicURL() { } +// public void llGetRootPosition() { } +// public void llGetRootRotation() { } +// public void llGetObjectDesc() { } +// public void llSetObjectDesc() { } +// public void llGetCreator() { } +// public void llGetTimestamp() { } +// public void llSetLinkAlpha() { } +// public void llGetNumberOfPrims() { } +// public void llGetNumberOfNotecardLines() { } +// public void llGetBoundingBox() { } +// public void llGetGeometricCenter() { } +// public void llGetPrimitiveParams() { } +// public void llIntegerToBase64() { } +// public void llBase64ToInteger() { } +// public void llGetGMTclock() { } +// public void llGetSimulatorHostname() { } +// public void llSetLocalRot() { } +// public void llParseStringKeepNulls() { } +// public void llRezAtRoot() { } +// public void llGetObjectPermMask() { } +// public void llSetObjectPermMask() { } +// public void llGetInventoryPermMask() { } +// public void llSetInventoryPermMask() { } +// public void llGetInventoryCreator() { } +// public void llOwnerSay() { } +// public void llRequestSimulatorData() { } +// public void llForceMouselook() { } +// public void llGetObjectMass() { } +// public void llListReplaceList() { } +// public void llLoadURL() { } +// public void llParcelMediaCommandList() { } +// public void llParcelMediaQuery() { } +// public void llModPow() { } +// public void llGetInventoryType() { } +// public void llSetPayPrice() { } +// public void llGetCameraPos() { } +// public void llGetCameraRot() { } +// public void llSetPrimURL() { } +// public void llRefreshPrimURL() { } +// public void llEscapeURL() { } +// public void llUnescapeURL() { } +// public void llMapDestination() { } +// public void llAddToLandBanList() { } +// public void llRemoveFromLandPassList() { } +// public void llRemoveFromLandBanList() { } +// public void llSetCameraParams() { } +// public void llClearCameraParams() { } +// public void llListStatistics() { } +// public void llGetUnixTime() { } +// public void llGetParcelFlags() { } +// public void llGetRegionFlags() { } +// public void llXorBase64StringsCorrect() { } +// public void llHTTPRequest() { } +// public void llResetLandBanList() { } +// public void llResetLandPassList() { } +// public void llGetParcelPrimCount() { } +// public void llGetParcelPrimOwners() { } +// public void llGetObjectPrimCount() { } +// public void llGetParcelMaxPrims() { } +// public void llGetParcelDetails() { } + +// } +//} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_BaseClass_OPCODES.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_BaseClass_OPCODES.cs new file mode 100644 index 0000000000..0b6970a1de --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_BaseClass_OPCODES.cs @@ -0,0 +1,394 @@ +/* +* 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; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO +{ + public partial class LSL_BaseClass + { + /* + * OPCODES + * + * These are internal "assembly" commands, + * basic operators like "ADD", "PUSH" and "POP" + * + * It also contains managed stack and keeps track of internal variables, etc. + * + */ + + + public void StoreToLocal(UInt32 index) + { + // TODO: How to determine local? + Common.SendToDebug("::StoreToLocal " + index); + if (LocalVariables.ContainsKey(index)) + LocalVariables.Remove(index); + LocalVariables.Add(index, LSLStack.Peek()); + } + + public void StoreToGlobal(UInt32 index) + { + Common.SendToDebug("::StoreToGlobal " + index); + if (GlobalVariables.ContainsKey(index)) + GlobalVariables.Remove(index); + GlobalVariables.Add(index, LSLStack.Peek()); + } + + public void StoreToStatic(UInt32 index) + { + Common.SendToDebug("::StoreToStatic " + index); + //if (StaticVariables.ContainsKey(index)) + // StaticVariables.Remove(index); + StaticVariables.Add(index, LSLStack.Peek()); + } + + public void GetFromLocal(UInt32 index) + { + // TODO: How to determine local? + Common.SendToDebug("::GetFromLocal " + index); + object ret; + LocalVariables.TryGetValue(index, out ret); + LSLStack.Push(ret); + //return ret; + } + + public void GetFromGlobal(UInt32 index) + { + Common.SendToDebug("::GetFromGlobal " + index); + object ret; + GlobalVariables.TryGetValue(index, out ret); + LSLStack.Push(ret); + //return ret; + } + + public void GetFromStatic(UInt32 index) + { + Common.SendToDebug("::GetFromStatic " + index); + object ret; + StaticVariables.TryGetValue(index, out ret); + Common.SendToDebug("::GetFromStatic - ObjectType: " + ret.GetType().ToString()); + LSLStack.Push(ret); + //return ret; + } + + public object POPToStack() + { + Common.SendToDebug("::POPToStack"); + //return LSLStack.Pop(); + object p = LSLStack.Pop(); + if (p.GetType() == typeof (UInt32)) + return (UInt32) p; + if (p.GetType() == typeof (string)) + return (string) p; + if (p.GetType() == typeof (Int32)) + return (Int32) p; + if (p.GetType() == typeof (UInt16)) + return (UInt16) p; + if (p.GetType() == typeof (float)) + return (float) p; + if (p.GetType() == typeof (LSO_Enums.Vector)) + return (LSO_Enums.Vector) p; + if (p.GetType() == typeof (LSO_Enums.Rotation)) + return (LSO_Enums.Rotation) p; + if (p.GetType() == typeof (LSO_Enums.Key)) + return (LSO_Enums.Key) p; + + return p; + } + + //public object POPToStack(UInt32 count) + //{ + // // POP NUMBER FROM TOP OF STACK + // //LSLStack.SetLength(LSLStack.Length - 4); + // Common.SendToDebug("::POPToStack " + count); + // if (count < 2) + // return LSLStack.Pop(); + + // Stack s = new Stack(); + // for (int i = 0; i < count; i++) + // { + // s.Push(LSLStack.Pop); + + // } + + //} + + public void POP() + { + // POP NUMBER FROM TOP OF STACK + //LSLStack.SetLength(LSLStack.Length - 4); + Common.SendToDebug("::POP"); + if (LSLStack.Count < 1) + { + //TODO: Temporary fix + Common.SendToDebug("ERROR: TRYING TO POP EMPTY STACK!"); + } + else + { + LSLStack.Pop(); + } + } + + public void PUSH(object Param) + { + if (Param == null) + { + Common.SendToDebug("::PUSH: "); + } + else + { + //Common.SendToDebug("::PUSH: " + Param.GetType()); + } + + LSLStack.Push(Param); + } + + public void ADD(UInt32 Param) + { + Common.SendToDebug("::ADD: " + Param); + object o2 = LSLStack.Pop(); + object o1 = LSLStack.Pop(); + Common.SendToDebug("::ADD: Debug: o1: " + o1.GetType() + " (" + o1.ToString() + "), o2: " + o2.GetType() + + " (" + o2.ToString() + ")"); + if (o2.GetType() == typeof (string)) + { + LSLStack.Push((string) o1 + (string) o2); + return; + } + if (o2.GetType() == typeof (UInt32)) + { + LSLStack.Push((UInt32) o1 + (UInt32) o2); + return; + } + } + + public void SUB(UInt32 Param) + { + Common.SendToDebug("::SUB: " + Param); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + LSLStack.Push((UInt32) (i1 - i2)); + } + + public void MUL(UInt32 Param) + { + Common.SendToDebug("::SUB: " + Param); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + LSLStack.Push((UInt32) (i1*i2)); + } + + public void DIV(UInt32 Param) + { + Common.SendToDebug("::DIV: " + Param); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + LSLStack.Push((UInt32) (i1/i2)); + } + + + public void MOD(UInt32 Param) + { + Common.SendToDebug("::MOD: " + Param); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + LSLStack.Push((UInt32) (i1%i2)); + } + + public void EQ(UInt32 Param) + { + Common.SendToDebug("::EQ: " + Param); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + if (i1 == i2) + { + LSLStack.Push((UInt32) 1); + } + else + { + LSLStack.Push((UInt32) 0); + } + } + + public void NEQ(UInt32 Param) + { + Common.SendToDebug("::NEQ: " + Param); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + if (i1 != i2) + { + LSLStack.Push((UInt32) 1); + } + else + { + LSLStack.Push((UInt32) 0); + } + } + + public void LEQ(UInt32 Param) + { + Common.SendToDebug("::LEQ: " + Param); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + if (i1 <= i2) + { + LSLStack.Push((UInt32) 1); + } + else + { + LSLStack.Push((UInt32) 0); + } + } + + public void GEQ(UInt32 Param) + { + Common.SendToDebug("::GEQ: " + Param); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + if (i1 >= i2) + { + LSLStack.Push((UInt32) 1); + } + else + { + LSLStack.Push((UInt32) 0); + } + } + + public void LESS(UInt32 Param) + { + Common.SendToDebug("::LESS: " + Param); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + if (i1 < i2) + { + LSLStack.Push((UInt32) 1); + } + else + { + LSLStack.Push((UInt32) 0); + } + } + + public void GREATER(UInt32 Param) + { + Common.SendToDebug("::GREATER: " + Param); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + if (i1 > i2) + { + LSLStack.Push((UInt32) 1); + } + else + { + LSLStack.Push((UInt32) 0); + } + } + + + public void BITAND() + { + Common.SendToDebug("::BITAND"); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + LSLStack.Push((UInt32) (i1 & i2)); + } + + public void BITOR() + { + Common.SendToDebug("::BITOR"); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + LSLStack.Push((UInt32) (i1 | i2)); + } + + public void BITXOR() + { + Common.SendToDebug("::BITXOR"); + UInt32 i2 = (UInt32) LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + LSLStack.Push((UInt32) (i1 ^ i2)); + } + + public void BOOLAND() + { + Common.SendToDebug("::BOOLAND"); + bool b2 = bool.Parse((string) LSLStack.Pop()); + bool b1 = bool.Parse((string) LSLStack.Pop()); + if (b1 && b2) + { + LSLStack.Push((UInt32) 1); + } + else + { + LSLStack.Push((UInt32) 0); + } + } + + public void BOOLOR() + { + Common.SendToDebug("::BOOLOR"); + bool b2 = bool.Parse((string) LSLStack.Pop()); + bool b1 = bool.Parse((string) LSLStack.Pop()); + + if (b1 || b2) + { + LSLStack.Push((UInt32) 1); + } + else + { + LSLStack.Push((UInt32) 0); + } + } + + public void NEG(UInt32 Param) + { + Common.SendToDebug("::NEG: " + Param); + //UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32) LSLStack.Pop(); + LSLStack.Push((UInt32) (i1*-1)); + } + + public void BITNOT() + { + //Common.SendToDebug("::BITNOT"); + //UInt32 i2 = (UInt32)LSLStack.Pop(); + //UInt32 i1 = (UInt32)LSLStack.Pop(); + //LSLStack.Push((UInt32)(i1 / i2)); + } + + public void BOOLNOT() + { + //Common.SendToDebug("::BOOLNOT"); + ////UInt32 i2 = (UInt32)LSLStack.Pop(); + //UInt32 i1 = (UInt32)LSLStack.Pop(); + //LSLStack.Push((UInt32)(i1)); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_CLRInterface.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_CLRInterface.cs new file mode 100644 index 0000000000..b616286a73 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_CLRInterface.cs @@ -0,0 +1,75 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO +{ + public class LSL_CLRInterface + { + public interface LSLScript + { + //public virtual void Run(object arg) + //{ + //} + //void Run(object arg); + + //void event_state_entry(object arg); + //void event_state_exit(); + //void event_touch_start(object arg); + //void event_touch(); + //void event_touch_end(); + //void event_collision_start(); + //void event_collision(); + //void event_collision_end(); + //void event_land_collision_start(); + //void event_land_collision(); + //void event_land_collision_end(); + //void event_timer(); + //void event_listen(); + //void event_on_rez(); + //void event_sensor(); + //void event_no_sensor(); + //void event_control(); + //void event_money(); + //void event_email(); + //void event_at_target(); + //void event_not_at_target(); + //void event_at_rot_target(); + //void event_not_at_rot_target(); + //void event_run_time_permissions(); + //void event_changed(); + //void event_attach(); + //void event_dataserver(); + //void event_link_message(); + //void event_moving_start(); + //void event_moving_end(); + //void event_object_rez(); + //void event_remote_data(); + //void event_http_response(); + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_OPCODE_IL_processor.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_OPCODE_IL_processor.cs new file mode 100644 index 0000000000..5c54a15e41 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSL_OPCODE_IL_processor.cs @@ -0,0 +1,435 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Reflection; +using System.Reflection.Emit; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO +{ + internal partial class LSO_Parser + { + //internal Stack ILStack = new Stack(); + //LSO_Enums MyLSO_Enums = new LSO_Enums(); + + internal bool LSL_PROCESS_OPCODE(ILGenerator il) + { + byte bp1; + UInt32 u32p1; + float fp1; + UInt16 opcode = br_read(1)[0]; + Common.SendToDebug("OPCODE: " + ((LSO_Enums.Operation_Table) opcode).ToString()); + string idesc = ((LSO_Enums.Operation_Table) opcode).ToString(); + switch ((LSO_Enums.Operation_Table) opcode) + { + /*************** + * IMPLEMENTED * + ***************/ + case LSO_Enums.Operation_Table.NOOP: + break; + case LSO_Enums.Operation_Table.PUSHSP: + // Push Stack Top (Memory Address) to stack + Common.SendToDebug("Instruction " + idesc); + Common.SendToDebug("Instruction " + idesc + + ": Description: Pushing Stack Top (Memory Address from header) to stack"); + IL_Push(il, (UInt32) myHeader.SP); + break; + // BYTE + case LSO_Enums.Operation_Table.PUSHARGB: + Common.SendToDebug("Param1: " + br_read(1)[0]); + break; + // INTEGER + case LSO_Enums.Operation_Table.PUSHARGI: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Instruction " + idesc + ", Param1: " + u32p1); + IL_Push(il, u32p1); + break; + // FLOAT + case LSO_Enums.Operation_Table.PUSHARGF: + fp1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Instruction " + idesc + ", Param1: " + fp1); + IL_Push(il, fp1); + break; + // STRING + case LSO_Enums.Operation_Table.PUSHARGS: + string s = Read_String(); + Common.SendToDebug("Instruction " + idesc + ", Param1: " + s); + IL_Debug(il, "OPCODE: " + idesc + ":" + s); + IL_Push(il, s); + break; + // VECTOR z,y,x + case LSO_Enums.Operation_Table.PUSHARGV: + LSO_Enums.Vector v = new LSO_Enums.Vector(); + v.Z = BitConverter.ToUInt32(br_read(4), 0); + v.Y = BitConverter.ToUInt32(br_read(4), 0); + v.X = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1 Z: " + v.Z); + Common.SendToDebug("Param1 Y: " + v.Y); + Common.SendToDebug("Param1 X: " + v.X); + IL_Push(il, v); + break; + // ROTATION s,z,y,x + case LSO_Enums.Operation_Table.PUSHARGQ: + LSO_Enums.Rotation r = new LSO_Enums.Rotation(); + r.S = BitConverter.ToUInt32(br_read(4), 0); + r.Z = BitConverter.ToUInt32(br_read(4), 0); + r.Y = BitConverter.ToUInt32(br_read(4), 0); + r.X = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1 S: " + r.S); + Common.SendToDebug("Param1 Z: " + r.Z); + Common.SendToDebug("Param1 Y: " + r.Y); + Common.SendToDebug("Param1 X: " + r.X); + IL_Push(il, r); + break; + + case LSO_Enums.Operation_Table.PUSHE: + IL_Push(il, (UInt32) 0); + break; + + case LSO_Enums.Operation_Table.PUSHARGE: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1); + //IL_Push(il, new string(" ".ToCharArray()[0], Convert.ToInt32(u32p1))); + IL_Push(il, u32p1); + break; + // BYTE + case LSO_Enums.Operation_Table.ADD: + case LSO_Enums.Operation_Table.SUB: + case LSO_Enums.Operation_Table.MUL: + case LSO_Enums.Operation_Table.DIV: + case LSO_Enums.Operation_Table.EQ: + case LSO_Enums.Operation_Table.NEQ: + case LSO_Enums.Operation_Table.LEQ: + case LSO_Enums.Operation_Table.GEQ: + case LSO_Enums.Operation_Table.LESS: + case LSO_Enums.Operation_Table.GREATER: + case LSO_Enums.Operation_Table.NEG: + case LSO_Enums.Operation_Table.MOD: + bp1 = br_read(1)[0]; + Common.SendToDebug("Param1: " + bp1); + IL_CallBaseFunction(il, idesc, (UInt32) bp1); + break; + + // NO ARGUMENTS + case LSO_Enums.Operation_Table.BITAND: + case LSO_Enums.Operation_Table.BITOR: + case LSO_Enums.Operation_Table.BITXOR: + case LSO_Enums.Operation_Table.BOOLAND: + case LSO_Enums.Operation_Table.BOOLOR: + case LSO_Enums.Operation_Table.BITNOT: + case LSO_Enums.Operation_Table.BOOLNOT: + IL_CallBaseFunction(il, idesc); + break; + // SHORT + case LSO_Enums.Operation_Table.CALLLIB_TWO_BYTE: + // TODO: What is size of short? + UInt16 U16p1 = BitConverter.ToUInt16(br_read(2), 0); + Common.SendToDebug("Instruction " + idesc + ": Builtin Command: " + + ((LSO_Enums.BuiltIn_Functions) U16p1).ToString()); + //Common.SendToDebug("Param1: " + U16p1); + string fname = ((LSO_Enums.BuiltIn_Functions) U16p1).ToString(); + + bool cmdFound = false; + foreach (MethodInfo mi in typeof (LSL_BuiltIn_Commands_Interface).GetMethods()) + { + // Found command + if (mi.Name == fname) + { + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod("GetLSL_BuiltIn", new Type[] {})); + // Pop required number of items from my stack to .Net stack + IL_PopToStack(il, mi.GetParameters().Length); + il.Emit(OpCodes.Callvirt, mi); + cmdFound = true; + break; + } + } + if (cmdFound == false) + { + Common.SendToDebug("ERROR: UNABLE TO LOCATE OPCODE " + idesc + " IN BASECLASS"); + } + + break; + + // RETURN + case LSO_Enums.Operation_Table.RETURN: + + Common.SendToDebug("OPCODE: RETURN"); + return true; + + case LSO_Enums.Operation_Table.POP: + case LSO_Enums.Operation_Table.POPS: + case LSO_Enums.Operation_Table.POPL: + case LSO_Enums.Operation_Table.POPV: + case LSO_Enums.Operation_Table.POPQ: + // Pops a specific datatype from the stack + // We just ignore the datatype for now + IL_Pop(il); + break; + + // LONG + case LSO_Enums.Operation_Table.STORE: + case LSO_Enums.Operation_Table.STORES: + case LSO_Enums.Operation_Table.STOREL: + case LSO_Enums.Operation_Table.STOREV: + case LSO_Enums.Operation_Table.STOREQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToLocal", u32p1); + break; + + case LSO_Enums.Operation_Table.STOREG: + case LSO_Enums.Operation_Table.STOREGS: + case LSO_Enums.Operation_Table.STOREGL: + case LSO_Enums.Operation_Table.STOREGV: + case LSO_Enums.Operation_Table.STOREGQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToGlobal", u32p1); + break; + + case LSO_Enums.Operation_Table.LOADP: + case LSO_Enums.Operation_Table.LOADSP: + case LSO_Enums.Operation_Table.LOADLP: + case LSO_Enums.Operation_Table.LOADVP: + case LSO_Enums.Operation_Table.LOADQP: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToLocal", u32p1); + IL_Pop(il); + break; + + case LSO_Enums.Operation_Table.LOADGP: + case LSO_Enums.Operation_Table.LOADGSP: + case LSO_Enums.Operation_Table.LOADGLP: + case LSO_Enums.Operation_Table.LOADGVP: + case LSO_Enums.Operation_Table.LOADGQP: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToStatic", u32p1 - 6 + myHeader.GVR); + IL_Pop(il); + break; + + // PUSH FROM LOCAL FRAME + case LSO_Enums.Operation_Table.PUSH: + case LSO_Enums.Operation_Table.PUSHS: + case LSO_Enums.Operation_Table.PUSHL: + case LSO_Enums.Operation_Table.PUSHV: + case LSO_Enums.Operation_Table.PUSHQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "GetFromLocal", u32p1); + + break; + + // PUSH FROM STATIC FRAME + case LSO_Enums.Operation_Table.PUSHG: + case LSO_Enums.Operation_Table.PUSHGS: + case LSO_Enums.Operation_Table.PUSHGL: + case LSO_Enums.Operation_Table.PUSHGV: + case LSO_Enums.Operation_Table.PUSHGQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "GetFromStatic", u32p1 - 6 + myHeader.GVR); + break; + + + /*********************** + * NOT IMPLEMENTED YET * + ***********************/ + + + case LSO_Enums.Operation_Table.POPIP: + case LSO_Enums.Operation_Table.POPSP: + case LSO_Enums.Operation_Table.POPSLR: + case LSO_Enums.Operation_Table.POPARG: + case LSO_Enums.Operation_Table.POPBP: + //Common.SendToDebug("Instruction " + idesc + ": Ignored"); + Common.SendToDebug("Instruction " + idesc + + ": Description: Drop x bytes from the stack (TODO: Only popping 1)"); + //Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + IL_Pop(il); + break; + + + // None + case LSO_Enums.Operation_Table.PUSHIP: + // PUSH INSTRUCTION POINTER + break; + case LSO_Enums.Operation_Table.PUSHBP: + + case LSO_Enums.Operation_Table.PUSHEV: + break; + case LSO_Enums.Operation_Table.PUSHEQ: + break; + + + // LONG + case LSO_Enums.Operation_Table.JUMP: + Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + break; + // BYTE, LONG + case LSO_Enums.Operation_Table.JUMPIF: + case LSO_Enums.Operation_Table.JUMPNIF: + Common.SendToDebug("Param1: " + br_read(1)[0]); + Common.SendToDebug("Param2: " + BitConverter.ToUInt32(br_read(4), 0)); + break; + // LONG + case LSO_Enums.Operation_Table.STATE: + bp1 = br_read(1)[0]; + //il.Emit(OpCodes.Ld); // Load local variable 0 onto stack + //il.Emit(OpCodes.Ldc_I4, 0); // Push index position + //il.Emit(OpCodes.Ldstr, EventList[p1]); // Push value + //il.Emit(OpCodes.Stelem_Ref); // Perform array[index] = value + break; + case LSO_Enums.Operation_Table.CALL: + Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + Common.SendToDebug("ERROR: Function CALL not implemented yet."); + break; + // BYTE + case LSO_Enums.Operation_Table.CAST: + bp1 = br_read(1)[0]; + Common.SendToDebug("Instruction " + idesc + ": Cast to type: " + + ((LSO_Enums.OpCode_Cast_TypeDefs) bp1)); + Common.SendToDebug("Param1: " + bp1); + switch ((LSO_Enums.OpCode_Cast_TypeDefs) bp1) + { + case LSO_Enums.OpCode_Cast_TypeDefs.String: + Common.SendToDebug("Instruction " + idesc + ": il.Emit(OpCodes.Box, ILStack.Pop());"); + break; + default: + Common.SendToDebug("Instruction " + idesc + ": Unknown cast type!"); + break; + } + break; + // LONG + case LSO_Enums.Operation_Table.STACKTOS: + case LSO_Enums.Operation_Table.STACKTOL: + Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + break; + // BYTE + case LSO_Enums.Operation_Table.PRINT: + case LSO_Enums.Operation_Table.CALLLIB: + Common.SendToDebug("Param1: " + br_read(1)[0]); + break; + } + return false; + } + + private void IL_PopToStack(ILGenerator il) + { + IL_PopToStack(il, 1); + } + + private void IL_PopToStack(ILGenerator il, int count) + { + Common.SendToDebug("IL_PopToStack();"); + for (int i = 0; i < count; i++) + { + IL_CallBaseFunction(il, "POPToStack"); + //il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Call, + // typeof(LSL_BaseClass).GetMethod("POPToStack", + // new Type[] { })); + } + } + + private void IL_Pop(ILGenerator il) + { + Common.SendToDebug("IL_Pop();"); + IL_CallBaseFunction(il, "POP"); + } + + private void IL_Debug(ILGenerator il, string text) + { + il.Emit(OpCodes.Ldstr, text); + il.Emit(OpCodes.Call, typeof (Common).GetMethod("SendToDebug", + new Type[] {typeof (string)} + )); + } + + private void IL_CallBaseFunction(ILGenerator il, string methodname) + { + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod(methodname, new Type[] {})); + } + + private void IL_CallBaseFunction(ILGenerator il, string methodname, object data) + { + il.Emit(OpCodes.Ldarg_0); + if (data.GetType() == typeof (string)) + il.Emit(OpCodes.Ldstr, (string) data); + if (data.GetType() == typeof (UInt32)) + il.Emit(OpCodes.Ldc_I4, (UInt32) data); + il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod(methodname, new Type[] {data.GetType()})); + } + + private void IL_Push(ILGenerator il, object data) + { + il.Emit(OpCodes.Ldarg_0); + Common.SendToDebug("PUSH datatype: " + data.GetType()); + + IL_PushDataTypeToILStack(il, data); + + il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod("PUSH", new Type[] {data.GetType()})); + } + + private void IL_PushDataTypeToILStack(ILGenerator il, object data) + { + if (data.GetType() == typeof (UInt16)) + { + il.Emit(OpCodes.Ldc_I4, (UInt16) data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof (UInt32)) + { + il.Emit(OpCodes.Ldc_I4, (UInt32) data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof (Int32)) + { + il.Emit(OpCodes.Ldc_I4, (Int32) data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof (float)) + { + il.Emit(OpCodes.Ldc_I4, (float) data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof (string)) + il.Emit(OpCodes.Ldstr, (string) data); + //if (data.GetType() == typeof(LSO_Enums.Rotation)) + // il.Emit(OpCodes.Ldobj, (LSO_Enums.Rotation)data); + //if (data.GetType() == typeof(LSO_Enums.Vector)) + // il.Emit(OpCodes.Ldobj, (LSO_Enums.Vector)data); + //if (data.GetType() == typeof(LSO_Enums.Key)) + // il.Emit(OpCodes.Ldobj, (LSO_Enums.Key)data); + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSO_Enums.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSO_Enums.cs new file mode 100644 index 0000000000..ef1fd06057 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSO_Enums.cs @@ -0,0 +1,560 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO +{ + public static class LSO_Enums + { + //public System.Collections.Generic.Dictionary OpCode_Add_Types; + + //LSO_Enums() { + // OpCode_Add_Types.Add(51, typeof(String)); + // OpCode_Add_Types.Add(17, typeof(UInt32)); + //} + + [Serializable] + public enum OpCode_Add_TypeDefs + { + String = 51, + UInt32 = 17 + } + + [Serializable] + public enum OpCode_Cast_TypeDefs + { + String = 19 + } + + [Serializable] + public struct Key + { + public string KeyString; + } + + [Serializable] + public struct Vector + { + public UInt32 Z; + public UInt32 Y; + public UInt32 X; + } + + [Serializable] + public struct Rotation + { + public UInt32 S; + public UInt32 Z; + public UInt32 Y; + public UInt32 X; + } + + [Serializable] + public enum Variable_Type_Codes + { + Void = 0, + Integer = 1, + Float = 2, + String = 3, + Key = 4, + Vector = 5, + Rotation = 6, + List = 7, + Null = 8 + } + + [Serializable] + public enum Event_Mask_Values + { + state_entry = 0, + state_exit = 1, + touch_start = 2, + touch = 3, + touch_end = 4, + collision_start = 5, + collision = 6, + collision_end = 7, + land_collision_start = 8, + land_collision = 9, + land_collision_end = 10, + timer = 11, + listen = 12, + on_rez = 13, + sensor = 14, + no_sensor = 15, + control = 16, + money = 17, + email = 18, + at_target = 19, + not_at_target = 20, + at_rot_target = 21, + not_at_rot_target = 22, + run_time_permissions = 23, + changed = 24, + attach = 25, + dataserver = 26, + link_message = 27, + moving_start = 28, + moving_end = 29, + object_rez = 30, + remote_data = 31, + http_response = 32 + } + + [Serializable] + public enum Operation_Table + { + NOOP = 0x0, + POP = 0x1, + POPS = 0x2, + POPL = 0x3, + POPV = 0x4, + POPQ = 0x5, + POPARG = 0x6, + POPIP = 0x7, + POPBP = 0x8, + POPSP = 0x9, + POPSLR = 0xa, + DUP = 0x20, + DUPS = 0x21, + DUPL = 0x22, + DUPV = 0x23, + DUPQ = 0x24, + STORE = 0x30, + STORES = 0x31, + STOREL = 0x32, + STOREV = 0x33, + STOREQ = 0x34, + STOREG = 0x35, + STOREGS = 0x36, + STOREGL = 0x37, + STOREGV = 0x38, + STOREGQ = 0x39, + LOADP = 0x3a, + LOADSP = 0x3b, + LOADLP = 0x3c, + LOADVP = 0x3d, + LOADQP = 0x3e, + LOADGP = 0x3f, + LOADGSP = 0x40, + LOADGLP = 0x41, + LOADGVP = 0x42, + LOADGQP = 0x43, + PUSH = 0x50, + PUSHS = 0x51, + PUSHL = 0x52, + PUSHV = 0x53, + PUSHQ = 0x54, + PUSHG = 0x55, + PUSHGS = 0x56, + PUSHGL = 0x57, + PUSHGV = 0x58, + PUSHGQ = 0x59, + PUSHIP = 0x5a, + PUSHBP = 0x5b, + PUSHSP = 0x5c, + PUSHARGB = 0x5d, + PUSHARGI = 0x5e, + PUSHARGF = 0x5f, + PUSHARGS = 0x60, + PUSHARGV = 0x61, + PUSHARGQ = 0x62, + PUSHE = 0x63, + PUSHEV = 0x64, + PUSHEQ = 0x65, + PUSHARGE = 0x66, + ADD = 0x70, + SUB = 0x71, + MUL = 0x72, + DIV = 0x73, + MOD = 0x74, + EQ = 0x75, + NEQ = 0x76, + LEQ = 0x77, + GEQ = 0x78, + LESS = 0x79, + GREATER = 0x7a, + BITAND = 0x7b, + BITOR = 0x7c, + BITXOR = 0x7d, + BOOLAND = 0x7e, + BOOLOR = 0x7f, + NEG = 0x80, + BITNOT = 0x81, + BOOLNOT = 0x82, + JUMP = 0x90, + JUMPIF = 0x91, + JUMPNIF = 0x92, + STATE = 0x93, + CALL = 0x94, + RETURN = 0x95, + CAST = 0xa0, + STACKTOS = 0xb0, + STACKTOL = 0xb1, + PRINT = 0xc0, + CALLLIB = 0xd0, + CALLLIB_TWO_BYTE = 0xd1, + SHL = 0xe0, + SHR = 0xe1 + } + + [Serializable] + public enum BuiltIn_Functions + { + llSin = 0, + llCos = 1, + llTan = 2, + llAtan2 = 3, + llSqrt = 4, + llPow = 5, + llAbs = 6, + llFabs = 7, + llFrand = 8, + llFloor = 9, + llCeil = 10, + llRound = 11, + llVecMag = 12, + llVecNorm = 13, + llVecDist = 14, + llRot2Euler = 15, + llEuler2Rot = 16, + llAxes2Rot = 17, + llRot2Fwd = 18, + llRot2Left = 19, + llRot2Up = 20, + llRotBetween = 21, + llWhisper = 22, + llSay = 23, + llShout = 24, + llListen = 25, + llListenControl = 26, + llListenRemove = 27, + llSensor = 28, + llSensorRepeat = 29, + llSensorRemove = 30, + llDetectedName = 31, + llDetectedKey = 32, + llDetectedOwner = 33, + llDetectedType = 34, + llDetectedPos = 35, + llDetectedVel = 36, + llDetectedGrab = 37, + llDetectedRot = 38, + llDetectedGroup = 39, + llDetectedLinkNumber = 40, + llDie = 41, + llGround = 42, + llCloud = 43, + llWind = 44, + llSetStatus = 45, + llGetStatus = 46, + llSetScale = 47, + llGetScale = 48, + llSetColor = 49, + llGetAlpha = 50, + llSetAlpha = 51, + llGetColor = 52, + llSetTexture = 53, + llScaleTexture = 54, + llOffsetTexture = 55, + llRotateTexture = 56, + llGetTexture = 57, + llSetPos = 58, + llGetPos = 59, + llGetLocalPos = 60, + llSetRot = 61, + llGetRot = 62, + llGetLocalRot = 63, + llSetForce = 64, + llGetForce = 65, + llTarget = 66, + llTargetRemove = 67, + llRotTarget = 68, + llRotTargetRemove = 69, + llMoveToTarget = 70, + llStopMoveToTarget = 71, + llApplyImpulse = 72, + llApplyRotationalImpulse = 73, + llSetTorque = 74, + llGetTorque = 75, + llSetForceAndTorque = 76, + llGetVel = 77, + llGetAccel = 78, + llGetOmega = 79, + llGetTimeOfDay = 80, + llGetWallclock = 81, + llGetTime = 82, + llResetTime = 83, + llGetAndResetTime = 84, + llSound = 85, + llPlaySound = 86, + llLoopSound = 87, + llLoopSoundMaster = 88, + llLoopSoundSlave = 89, + llPlaySoundSlave = 90, + llTriggerSound = 91, + llStopSound = 92, + llPreloadSound = 93, + llGetSubString = 94, + llDeleteSubString = 95, + llInsertString = 96, + llToUpper = 97, + llToLower = 98, + llGiveMoney = 99, + llMakeExplosion = 100, + llMakeFountain = 101, + llMakeSmoke = 102, + llMakeFire = 103, + llRezObject = 104, + llLookAt = 105, + llStopLookAt = 106, + llSetTimerEvent = 107, + llSleep = 108, + llGetMass = 109, + llCollisionFilter = 110, + llTakeControls = 111, + llReleaseControls = 112, + llAttachToAvatar = 113, + llDetachFromAvatar = 114, + llTakeCamera = 115, + llReleaseCamera = 116, + llGetOwner = 117, + llInstantMessage = 118, + llEmail = 119, + llGetNextEmail = 120, + llGetKey = 121, + llSetBuoyancy = 122, + llSetHoverHeight = 123, + llStopHover = 124, + llMinEventDelay = 125, + llSoundPreload = 126, + llRotLookAt = 127, + llStringLength = 128, + llStartAnimation = 129, + llStopAnimation = 130, + llPointAt = 131, + llStopPointAt = 132, + llTargetOmega = 133, + llGetStartParameter = 134, + llGodLikeRezObject = 135, + llRequestPermissions = 136, + llGetPermissionsKey = 137, + llGetPermissions = 138, + llGetLinkNumber = 139, + llSetLinkColor = 140, + llCreateLink = 141, + llBreakLink = 142, + llBreakAllLinks = 143, + llGetLinkKey = 144, + llGetLinkName = 145, + llGetInventoryNumber = 146, + llGetInventoryName = 147, + llSetScriptState = 148, + llGetEnergy = 149, + llGiveInventory = 150, + llRemoveInventory = 151, + llSetText = 152, + llWater = 153, + llPassTouches = 154, + llRequestAgentData = 155, + llRequestInventoryData = 156, + llSetDamage = 157, + llTeleportAgentHome = 158, + llModifyLand = 159, + llCollisionSound = 160, + llCollisionSprite = 161, + llGetAnimation = 162, + llResetScript = 163, + llMessageLinked = 164, + llPushObject = 165, + llPassCollisions = 166, + llGetScriptName = 167, + llGetNumberOfSides = 168, + llAxisAngle2Rot = 169, + llRot2Axis = 170, + llRot2Angle = 171, + llAcos = 172, + llAsin = 173, + llAngleBetween = 174, + llGetInventoryKey = 175, + llAllowInventoryDrop = 176, + llGetSunDirection = 177, + llGetTextureOffset = 178, + llGetTextureScale = 179, + llGetTextureRot = 180, + llSubStringIndex = 181, + llGetOwnerKey = 182, + llGetCenterOfMass = 183, + llListSort = 184, + llGetListLength = 185, + llList2Integer = 186, + llList2Float = 187, + llList2String = 188, + llList2Key = 189, + llList2Vector = 190, + llList2Rot = 191, + llList2List = 192, + llDeleteSubList = 193, + llGetListEntryType = 194, + llList2CSV = 195, + llCSV2List = 196, + llListRandomize = 197, + llList2ListStrided = 198, + llGetRegionCorner = 199, + llListInsertList = 200, + llListFindList = 201, + llGetObjectName = 202, + llSetObjectName = 203, + llGetDate = 204, + llEdgeOfWorld = 205, + llGetAgentInfo = 206, + llAdjustSoundVolume = 207, + llSetSoundQueueing = 208, + llSetSoundRadius = 209, + llKey2Name = 210, + llSetTextureAnim = 211, + llTriggerSoundLimited = 212, + llEjectFromLand = 213, + llParseString2List = 214, + llOverMyLand = 215, + llGetLandOwnerAt = 216, + llGetNotecardLine = 217, + llGetAgentSize = 218, + llSameGroup = 219, + llUnSit = 220, + llGroundSlope = 221, + llGroundNormal = 222, + llGroundContour = 223, + llGetAttached = 224, + llGetFreeMemory = 225, + llGetRegionName = 226, + llGetRegionTimeDilation = 227, + llGetRegionFPS = 228, + llParticleSystem = 229, + llGroundRepel = 230, + llGiveInventoryList = 231, + llSetVehicleType = 232, + llSetVehicleFloatParam = 233, + llSetVehicleVectorParam = 234, + llSetVehicleRotationParam = 235, + llSetVehicleFlags = 236, + llRemoveVehicleFlags = 237, + llSitTarget = 238, + llAvatarOnSitTarget = 239, + llAddToLandPassList = 240, + llSetTouchText = 241, + llSetSitText = 242, + llSetCameraEyeOffset = 243, + llSetCameraAtOffset = 244, + llDumpList2String = 245, + llScriptDanger = 246, + llDialog = 247, + llVolumeDetect = 248, + llResetOtherScript = 249, + llGetScriptState = 250, + llRemoteLoadScript = 251, + llSetRemoteScriptAccessPin = 252, + llRemoteLoadScriptPin = 253, + llOpenRemoteDataChannel = 254, + llSendRemoteData = 255, + llRemoteDataReply = 256, + llCloseRemoteDataChannel = 257, + llMD5String = 258, + llSetPrimitiveParams = 259, + llStringToBase64 = 260, + llBase64ToString = 261, + llXorBase64Strings = 262, + llRemoteDataSetRegion = 263, + llLog10 = 264, + llLog = 265, + llGetAnimationList = 266, + llSetParcelMusicURL = 267, + llGetRootPosition = 268, + llGetRootRotation = 269, + llGetObjectDesc = 270, + llSetObjectDesc = 271, + llGetCreator = 272, + llGetTimestamp = 273, + llSetLinkAlpha = 274, + llGetNumberOfPrims = 275, + llGetNumberOfNotecardLines = 276, + llGetBoundingBox = 277, + llGetGeometricCenter = 278, + llGetPrimitiveParams = 279, + llIntegerToBase64 = 280, + llBase64ToInteger = 281, + llGetGMTclock = 282, + llGetSimulatorHostname = 283, + llSetLocalRot = 284, + llParseStringKeepNulls = 285, + llRezAtRoot = 286, + llGetObjectPermMask = 287, + llSetObjectPermMask = 288, + llGetInventoryPermMask = 289, + llSetInventoryPermMask = 290, + llGetInventoryCreator = 291, + llOwnerSay = 292, + llRequestSimulatorData = 293, + llForceMouselook = 294, + llGetObjectMass = 295, + llListReplaceList = 296, + llLoadURL = 297, + llParcelMediaCommandList = 298, + llParcelMediaQuery = 299, + llModPow = 300, + llGetInventoryType = 301, + llSetPayPrice = 302, + llGetCameraPos = 303, + llGetCameraRot = 304, + llSetPrimURL = 305, + llRefreshPrimURL = 306, + llEscapeURL = 307, + llUnescapeURL = 308, + llMapDestination = 309, + llAddToLandBanList = 310, + llRemoveFromLandPassList = 311, + llRemoveFromLandBanList = 312, + llSetCameraParams = 313, + llClearCameraParams = 314, + llListStatistics = 315, + llGetUnixTime = 316, + llGetParcelFlags = 317, + llGetRegionFlags = 318, + llXorBase64StringsCorrect = 319, + llHTTPRequest = 320, + llResetLandBanList = 321, + llResetLandPassList = 322, + llGetParcelPrimCount = 323, + llGetParcelPrimOwners = 324, + llGetObjectPrimCount = 325, + llGetParcelMaxPrims = 326, + llGetParcelDetails = 327 + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSO_Parser.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSO_Parser.cs new file mode 100644 index 0000000000..f18d68935e --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSO_Parser.cs @@ -0,0 +1,728 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO +{ + internal partial class LSO_Parser + { + private string FileName; + private FileStream fs; + private BinaryReader br; + internal LSO_Struct.Header myHeader; + internal Dictionary StaticBlocks = new Dictionary(); + //private System.Collections.Hashtable StaticBlocks = new System.Collections.Hashtable(); + + private TypeBuilder typeBuilder; + private List EventList = new List(); + + public LSO_Parser(string _FileName, TypeBuilder _typeBuilder) + { + FileName = _FileName; + typeBuilder = _typeBuilder; + } + + internal void OpenFile() + { + // Open + Common.SendToDebug("Opening filename: " + FileName); + fs = File.Open(FileName, FileMode.Open, FileAccess.Read, FileShare.Read); + br = new BinaryReader(fs, Encoding.BigEndianUnicode); + } + + internal void CloseFile() + { + // Close + br.Close(); + fs.Close(); + } + + + /// + /// Parse LSO file. + /// + public void Parse() + { + // The LSO Format consist of 6 major blocks: header, statics, functions, states, heap, and stack. + + + // HEADER BLOCK + Common.SendToDebug("Reading HEADER BLOCK at: 0"); + fs.Seek(0, SeekOrigin.Begin); + myHeader = new LSO_Struct.Header(); + myHeader.TM = BitConverter.ToUInt32(br_read(4), 0); + myHeader.IP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.VN = BitConverter.ToUInt32(br_read(4), 0); + myHeader.BP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.SP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.HR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.HP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.CS = BitConverter.ToUInt32(br_read(4), 0); + myHeader.NS = BitConverter.ToUInt32(br_read(4), 0); + myHeader.CE = BitConverter.ToUInt32(br_read(4), 0); + myHeader.IE = BitConverter.ToUInt32(br_read(4), 0); + myHeader.ER = BitConverter.ToUInt32(br_read(4), 0); + myHeader.FR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.SLR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.GVR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.GFR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.PR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.ESR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.SR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.NCE = BitConverter.ToUInt64(br_read(8), 0); + myHeader.NIE = BitConverter.ToUInt64(br_read(8), 0); + myHeader.NER = BitConverter.ToUInt64(br_read(8), 0); + + // Print Header Block to debug + Common.SendToDebug("TM - Top of memory (size): " + myHeader.TM); + Common.SendToDebug("IP - Instruction Pointer (0=not running): " + myHeader.IP); + Common.SendToDebug("VN - Version number: " + myHeader.VN); + Common.SendToDebug("BP - Local Frame Pointer: " + myHeader.BP); + Common.SendToDebug("SP - Stack Pointer: " + myHeader.SP); + Common.SendToDebug("HR - Heap Register: " + myHeader.HR); + Common.SendToDebug("HP - Heap Pointer: " + myHeader.HP); + Common.SendToDebug("CS - Current State: " + myHeader.CS); + Common.SendToDebug("NS - Next State: " + myHeader.NS); + Common.SendToDebug("CE - Current Events: " + myHeader.CE); + Common.SendToDebug("IE - In Event: " + myHeader.IE); + Common.SendToDebug("ER - Event Register: " + myHeader.ER); + Common.SendToDebug("FR - Fault Register: " + myHeader.FR); + Common.SendToDebug("SLR - Sleep Register: " + myHeader.SLR); + Common.SendToDebug("GVR - Global Variable Register: " + myHeader.GVR); + Common.SendToDebug("GFR - Global Function Register: " + myHeader.GFR); + Common.SendToDebug("PR - Parameter Register: " + myHeader.PR); + Common.SendToDebug("ESR - Energy Supply Register: " + myHeader.ESR); + Common.SendToDebug("SR - State Register: " + myHeader.SR); + Common.SendToDebug("NCE - 64-bit Current Events: " + myHeader.NCE); + Common.SendToDebug("NIE - 64-bit In Events: " + myHeader.NIE); + Common.SendToDebug("NER - 64-bit Event Register: " + myHeader.NER); + Common.SendToDebug("Read position when exiting HEADER BLOCK: " + fs.Position); + + // STATIC BLOCK + Common.SendToDebug("Reading STATIC BLOCK at: " + myHeader.GVR); + fs.Seek(myHeader.GVR, SeekOrigin.Begin); + int StaticBlockCount = 0; + // Read function blocks until we hit GFR + while (fs.Position < myHeader.GFR) + { + StaticBlockCount++; + long startReadPos = fs.Position; + Common.SendToDebug("Reading Static Block " + StaticBlockCount + " at: " + startReadPos); + + //fs.Seek(myHeader.GVR, SeekOrigin.Begin); + LSO_Struct.StaticBlock myStaticBlock = new LSO_Struct.StaticBlock(); + myStaticBlock.Static_Chunk_Header_Size = BitConverter.ToUInt32(br_read(4), 0); + myStaticBlock.ObjectType = br_read(1)[0]; + Common.SendToDebug("Static Block ObjectType: " + + ((LSO_Enums.Variable_Type_Codes) myStaticBlock.ObjectType).ToString()); + myStaticBlock.Unknown = br_read(1)[0]; + // Size of datatype varies -- what about strings? + if (myStaticBlock.ObjectType != 0) + myStaticBlock.BlockVariable = br_read(getObjectSize(myStaticBlock.ObjectType)); + + StaticBlocks.Add((UInt32) startReadPos, myStaticBlock); + } + Common.SendToDebug("Number of Static Blocks read: " + StaticBlockCount); + + + // FUNCTION BLOCK + // Always right after STATIC BLOCK + LSO_Struct.FunctionBlock myFunctionBlock = new LSO_Struct.FunctionBlock(); + if (myHeader.GFR == myHeader.SR) + { + // If GFR and SR are at same position then there is no fuction block + Common.SendToDebug("No FUNCTION BLOCK found"); + } + else + { + Common.SendToDebug("Reading FUNCTION BLOCK at: " + myHeader.GFR); + fs.Seek(myHeader.GFR, SeekOrigin.Begin); + myFunctionBlock.FunctionCount = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Number of functions in Fuction Block: " + myFunctionBlock.FunctionCount); + if (myFunctionBlock.FunctionCount > 0) + { + myFunctionBlock.CodeChunkPointer = new UInt32[myFunctionBlock.FunctionCount]; + for (int i = 0; i < myFunctionBlock.FunctionCount; i++) + { + Common.SendToDebug("Reading function " + i + " at: " + fs.Position); + // TODO: ADD TO FUNCTION LIST (How do we identify it later?) + // Note! Absolute position + myFunctionBlock.CodeChunkPointer[i] = BitConverter.ToUInt32(br_read(4), 0) + myHeader.GFR; + Common.SendToDebug("Fuction " + i + " code chunk position: " + + myFunctionBlock.CodeChunkPointer[i]); + } + } + } + + + // STATE FRAME BLOCK + // Always right after FUNCTION BLOCK + Common.SendToDebug("Reading STATE BLOCK at: " + myHeader.SR); + fs.Seek(myHeader.SR, SeekOrigin.Begin); + LSO_Struct.StateFrameBlock myStateFrameBlock = new LSO_Struct.StateFrameBlock(); + myStateFrameBlock.StateCount = BitConverter.ToUInt32(br_read(4), 0); + if (myStateFrameBlock.StateCount > 0) + { + // Initialize array + myStateFrameBlock.StatePointer = new LSO_Struct.StatePointerBlock[myStateFrameBlock.StateCount]; + for (int i = 0; i < myStateFrameBlock.StateCount; i++) + { + Common.SendToDebug("Reading STATE POINTER BLOCK " + (i + 1) + " at: " + fs.Position); + // Position is relative to state frame + myStateFrameBlock.StatePointer[i].Location = myHeader.SR + BitConverter.ToUInt32(br_read(4), 0); + myStateFrameBlock.StatePointer[i].EventMask = new BitArray(br_read(8)); + Common.SendToDebug("Pointer: " + myStateFrameBlock.StatePointer[i].Location); + Common.SendToDebug("Total potential EventMask bits: " + + myStateFrameBlock.StatePointer[i].EventMask.Count); + + //// Read STATE BLOCK + //long CurPos = fs.Position; + //fs.Seek(CurPos, SeekOrigin.Begin); + } + } + + + // STATE BLOCK + // For each StateFrameBlock there is one StateBlock with multiple event handlers + + if (myStateFrameBlock.StateCount > 0) + { + // Go through all State Frame Pointers found + for (int i = 0; i < myStateFrameBlock.StateCount; i++) + { + fs.Seek(myStateFrameBlock.StatePointer[i].Location, SeekOrigin.Begin); + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " at: " + fs.Position); + + // READ: STATE BLOCK HEADER + myStateFrameBlock.StatePointer[i].StateBlock = new LSO_Struct.StateBlock(); + myStateFrameBlock.StatePointer[i].StateBlock.StartPos = (UInt32) fs.Position; // Note + myStateFrameBlock.StatePointer[i].StateBlock.HeaderSize = BitConverter.ToUInt32(br_read(4), 0); + myStateFrameBlock.StatePointer[i].StateBlock.Unknown = br_read(1)[0]; + myStateFrameBlock.StatePointer[i].StateBlock.EndPos = (UInt32) fs.Position; // Note + Common.SendToDebug("State block Start Pos: " + myStateFrameBlock.StatePointer[i].StateBlock.StartPos); + Common.SendToDebug("State block Header Size: " + + myStateFrameBlock.StatePointer[i].StateBlock.HeaderSize); + Common.SendToDebug("State block Header End Pos: " + + myStateFrameBlock.StatePointer[i].StateBlock.EndPos); + + // We need to count number of bits flagged in EventMask? + + + // for each bit in myStateFrameBlock.StatePointer[i].EventMask + + // ADDING TO ALL RIGHT NOW, SHOULD LIMIT TO ONLY THE ONES IN USE + //TODO: Create event hooks + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers = + new LSO_Struct.StateBlockHandler[myStateFrameBlock.StatePointer[i].EventMask.Count - 1]; + for (int ii = 0; ii < myStateFrameBlock.StatePointer[i].EventMask.Count - 1; ii++) + { + if (myStateFrameBlock.StatePointer[i].EventMask.Get(ii) == true) + { + // We got an event + // READ: STATE BLOCK HANDLER + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER matching EVENT MASK " + ii + + " (" + ((LSO_Enums.Event_Mask_Values) ii).ToString() + ") at: " + + fs.Position); + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer = + myStateFrameBlock.StatePointer[i].StateBlock.EndPos + + BitConverter.ToUInt32(br_read(4), 0); + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CallFrameSize = + BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER EVENT MASK " + ii + " (" + + ((LSO_Enums.Event_Mask_Values) ii).ToString() + ") Code Chunk Pointer: " + + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii]. + CodeChunkPointer); + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER EVENT MASK " + ii + " (" + + ((LSO_Enums.Event_Mask_Values) ii).ToString() + ") Call Frame Size: " + + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii]. + CallFrameSize); + } + } + } + } + + + //// READ FUNCTION CODE CHUNKS + //// Functions + Function start pos (GFR) + //// TODO: Somehow be able to identify and reference this + //LSO_Struct.CodeChunk[] myFunctionCodeChunk; + //if (myFunctionBlock.FunctionCount > 0) + //{ + // myFunctionCodeChunk = new LSO_Struct.CodeChunk[myFunctionBlock.FunctionCount]; + // for (int i = 0; i < myFunctionBlock.FunctionCount; i++) + // { + // Common.SendToDebug("Reading Function Code Chunk " + i); + // myFunctionCodeChunk[i] = GetCodeChunk((UInt32)myFunctionBlock.CodeChunkPointer[i]); + // } + + //} + // READ EVENT CODE CHUNKS + LSO_Struct.CodeChunk[] myEventCodeChunk; + if (myStateFrameBlock.StateCount > 0) + { + myEventCodeChunk = new LSO_Struct.CodeChunk[myStateFrameBlock.StateCount]; + for (int i = 0; i < myStateFrameBlock.StateCount; i++) + { + // TODO: Somehow organize events and functions so they can be found again, + // two level search ain't no good + for (int ii = 0; ii < myStateFrameBlock.StatePointer[i].EventMask.Count - 1; ii++) + { + if (myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer > 0) + { + Common.SendToDebug("Reading Event Code Chunk state " + i + ", event " + + (LSO_Enums.Event_Mask_Values) ii); + + + // Override a Method / Function + string eventname = i + "_event_" + (LSO_Enums.Event_Mask_Values) ii; + Common.SendToDebug("Event Name: " + eventname); + if (Common.IL_ProcessCodeChunks) + { + EventList.Add(eventname); + + // JUMP TO CODE PROCESSOR + ProcessCodeChunk( + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer, + typeBuilder, eventname); + } + } + } + } + } + + + if (Common.IL_CreateFunctionList) + IL_INSERT_FUNCTIONLIST(); + } + + internal LSO_Struct.HeapBlock GetHeap(UInt32 pos) + { + // HEAP BLOCK + // TODO:? Special read for strings/keys (null terminated) and lists (pointers to other HEAP entries) + Common.SendToDebug("Reading HEAP BLOCK at: " + pos); + fs.Seek(pos, SeekOrigin.Begin); + + LSO_Struct.HeapBlock myHeapBlock = new LSO_Struct.HeapBlock(); + myHeapBlock.DataBlockSize = BitConverter.ToInt32(br_read(4), 0); + myHeapBlock.ObjectType = br_read(1)[0]; + myHeapBlock.ReferenceCount = BitConverter.ToUInt16(br_read(2), 0); + //myHeapBlock.Data = br_read(getObjectSize(myHeapBlock.ObjectType)); + // Don't read it reversed + myHeapBlock.Data = new byte[myHeapBlock.DataBlockSize - 1]; + br.Read(myHeapBlock.Data, 0, myHeapBlock.DataBlockSize - 1); + + + Common.SendToDebug("Heap Block Data Block Size: " + myHeapBlock.DataBlockSize); + Common.SendToDebug("Heap Block ObjectType: " + + ((LSO_Enums.Variable_Type_Codes) myHeapBlock.ObjectType).ToString()); + Common.SendToDebug("Heap Block Reference Count: " + myHeapBlock.ReferenceCount); + + return myHeapBlock; + } + + private byte[] br_read(int len) + { + if (len <= 0) + return null; + + try + { + byte[] bytes = new byte[len]; + for (int i = len - 1; i > -1; i--) + bytes[i] = br.ReadByte(); + return bytes; + } + catch (Exception e) + { + Common.SendToDebug("Exception: " + e.ToString()); + throw (e); + } + } + + //private byte[] br_read_smallendian(int len) + //{ + // byte[] bytes = new byte[len]; + // br.Read(bytes,0, len); + // return bytes; + //} + private Type getLLObjectType(byte objectCode) + { + switch ((LSO_Enums.Variable_Type_Codes) objectCode) + { + case LSO_Enums.Variable_Type_Codes.Void: + return typeof (void); + case LSO_Enums.Variable_Type_Codes.Integer: + return typeof (UInt32); + case LSO_Enums.Variable_Type_Codes.Float: + return typeof (float); + case LSO_Enums.Variable_Type_Codes.String: + return typeof (string); + case LSO_Enums.Variable_Type_Codes.Key: + return typeof (string); + case LSO_Enums.Variable_Type_Codes.Vector: + return typeof (LSO_Enums.Vector); + case LSO_Enums.Variable_Type_Codes.Rotation: + return typeof (LSO_Enums.Rotation); + case LSO_Enums.Variable_Type_Codes.List: + Common.SendToDebug("TODO: List datatype not implemented yet!"); + return typeof (ArrayList); + case LSO_Enums.Variable_Type_Codes.Null: + Common.SendToDebug("TODO: Datatype null is not implemented, using string instead.!"); + return typeof (string); + default: + Common.SendToDebug("Lookup of LSL datatype " + objectCode + + " to .Net datatype failed: Unknown LSL datatype. Defaulting to object."); + return typeof (object); + } + } + + private int getObjectSize(byte ObjectType) + { + switch ((LSO_Enums.Variable_Type_Codes) ObjectType) + { + case LSO_Enums.Variable_Type_Codes.Integer: + case LSO_Enums.Variable_Type_Codes.Float: + case LSO_Enums.Variable_Type_Codes.String: + case LSO_Enums.Variable_Type_Codes.Key: + case LSO_Enums.Variable_Type_Codes.List: + return 4; + case LSO_Enums.Variable_Type_Codes.Vector: + return 12; + case LSO_Enums.Variable_Type_Codes.Rotation: + return 16; + default: + return 0; + } + } + + private string Read_String() + { + string ret = ""; + byte reader = br_read(1)[0]; + while (reader != 0x000) + { + ret += (char) reader; + reader = br_read(1)[0]; + } + return ret; + } + + /// + /// Reads a code chunk and creates IL + /// + /// Absolute position in file. REMEMBER TO ADD myHeader.GFR! + /// TypeBuilder for assembly + /// Name of event (function) to generate + private void ProcessCodeChunk(UInt32 pos, TypeBuilder typeBuilder, string eventname) + { + LSO_Struct.CodeChunk myCodeChunk = new LSO_Struct.CodeChunk(); + + Common.SendToDebug("Reading Function Code Chunk at: " + pos); + fs.Seek(pos, SeekOrigin.Begin); + myCodeChunk.CodeChunkHeaderSize = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("CodeChunk Header Size: " + myCodeChunk.CodeChunkHeaderSize); + // Read until null + myCodeChunk.Comment = Read_String(); + Common.SendToDebug("Function comment: " + myCodeChunk.Comment); + myCodeChunk.ReturnTypePos = br_read(1)[0]; + myCodeChunk.ReturnType = GetStaticBlock((long) myCodeChunk.ReturnTypePos + (long) myHeader.GVR); + Common.SendToDebug("Return type #" + myCodeChunk.ReturnType.ObjectType + ": " + + ((LSO_Enums.Variable_Type_Codes) myCodeChunk.ReturnType.ObjectType).ToString()); + + + // TODO: How to determine number of codechunks -- does this method work? + myCodeChunk.CodeChunkArguments = new List(); + byte reader = br_read(1)[0]; + reader = br_read(1)[0]; + + // NOTE ON CODE CHUNK ARGUMENTS + // This determins type definition + int ccount = 0; + while (reader != 0x000) + { + ccount++; + Common.SendToDebug("Reading Code Chunk Argument " + ccount); + LSO_Struct.CodeChunkArgument CCA = new LSO_Struct.CodeChunkArgument(); + CCA.FunctionReturnTypePos = reader; + reader = br_read(1)[0]; + CCA.NullString = reader; + CCA.FunctionReturnType = GetStaticBlock(CCA.FunctionReturnTypePos + myHeader.GVR); + myCodeChunk.CodeChunkArguments.Add(CCA); + Common.SendToDebug("Code Chunk Argument " + ccount + " type #" + CCA.FunctionReturnType.ObjectType + + ": " + (LSO_Enums.Variable_Type_Codes) CCA.FunctionReturnType.ObjectType); + } + // Create string array + Type[] MethodArgs = new Type[myCodeChunk.CodeChunkArguments.Count]; + for (int _ic = 0; _ic < myCodeChunk.CodeChunkArguments.Count; _ic++) + { + MethodArgs[_ic] = getLLObjectType(myCodeChunk.CodeChunkArguments[_ic].FunctionReturnType.ObjectType); + Common.SendToDebug("Method argument " + _ic + ": " + + getLLObjectType(myCodeChunk.CodeChunkArguments[_ic].FunctionReturnType.ObjectType). + ToString()); + } + // End marker is 0x000 + myCodeChunk.EndMarker = reader; + + + // + // Emit: START OF METHOD (FUNCTION) + // + + Common.SendToDebug("CLR:" + eventname + ":MethodBuilder methodBuilder = typeBuilder.DefineMethod..."); + MethodBuilder methodBuilder = typeBuilder.DefineMethod(eventname, + MethodAttributes.Public, + typeof (void), + new Type[] {typeof (object)}); + //MethodArgs); + //typeof(void), //getLLObjectType(myCodeChunk.ReturnType), + // new Type[] { typeof(object) }, //); + + //Common.SendToDebug("CLR:" + eventname + ":typeBuilder.DefineMethodOverride(methodBuilder..."); + //typeBuilder.DefineMethodOverride(methodBuilder, + // typeof(LSL_CLRInterface.LSLScript).GetMethod(eventname)); + + // Create the IL generator + + Common.SendToDebug("CLR:" + eventname + ":ILGenerator il = methodBuilder.GetILGenerator();"); + ILGenerator il = methodBuilder.GetILGenerator(); + + + if (Common.IL_UseTryCatch) + IL_INSERT_TRY(il, eventname); + + + // Push Console.WriteLine command to stack ... Console.WriteLine("Hello World!"); + //Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); + //il.Emit(OpCodes.Call, typeof(Console).GetMethod + // ("WriteLine", new Type[] { typeof(string) })); + + //Common.SendToDebug("STARTUP: il.Emit(OpCodes.Ldc_I4_S, 0);"); + + //il.Emit(OpCodes.Ldc_I4_S, 0); + for (int _ic = 0; _ic < myCodeChunk.CodeChunkArguments.Count; _ic++) + { + Common.SendToDebug("PARAMS: il.Emit(OpCodes.Ldarg, " + _ic + ");"); + il.Emit(OpCodes.Ldarg, _ic); + } + + + // + // CALLING OPCODE PROCESSOR, one command at the time TO GENERATE IL + // + bool FoundRet = false; + while (FoundRet == false) + { + FoundRet = LSL_PROCESS_OPCODE(il); + } + + + if (Common.IL_UseTryCatch) + IL_INSERT_END_TRY(il, eventname); + + // Emit: RETURN FROM METHOD + il.Emit(OpCodes.Ret); + + return; + } + + private void IL_INSERT_FUNCTIONLIST() + { + Common.SendToDebug("Creating function list"); + + + string eventname = "GetFunctions"; + + Common.SendToDebug("Creating IL " + eventname); + // Define a private String field. + //FieldBuilder myField = myTypeBuilder.DefineField("EventList", typeof(String[]), FieldAttributes.Public); + + + //FieldBuilder mem = typeBuilder.DefineField("mem", typeof(Array), FieldAttributes.Private); + + + MethodBuilder methodBuilder = typeBuilder.DefineMethod(eventname, + MethodAttributes.Public, + typeof (string[]), + null); + + //typeBuilder.DefineMethodOverride(methodBuilder, + // typeof(LSL_CLRInterface.LSLScript).GetMethod(eventname)); + + ILGenerator il = methodBuilder.GetILGenerator(); + + + // IL_INSERT_TRY(il, eventname); + + // // Push string to stack + // il.Emit(OpCodes.Ldstr, "Inside " + eventname); + + //// Push Console.WriteLine command to stack ... Console.WriteLine("Hello World!"); + //il.Emit(OpCodes.Call, typeof(Console).GetMethod + // ("WriteLine", new Type[] { typeof(string) })); + + //initIL.Emit(OpCodes.Newobj, typeof(string[])); + + //string[] MyArray = new string[2] { "TestItem1" , "TestItem2" }; + + ////il.Emit(OpCodes.Ldarg_0); + + il.DeclareLocal(typeof (string[])); + + ////il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldc_I4, EventList.Count); // Specify array length + il.Emit(OpCodes.Newarr, typeof (String)); // create new string array + il.Emit(OpCodes.Stloc_0); // Store array as local variable 0 in stack + ////SetFunctionList + + for (int lv = 0; lv < EventList.Count; lv++) + { + il.Emit(OpCodes.Ldloc_0); // Load local variable 0 onto stack + il.Emit(OpCodes.Ldc_I4, lv); // Push index position + il.Emit(OpCodes.Ldstr, EventList[lv]); // Push value + il.Emit(OpCodes.Stelem_Ref); // Perform array[index] = value + + //il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Ldstr, EventList[lv]); // Push value + //il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("AddFunction", new Type[] { typeof(string) })); + } + + + // IL_INSERT_END_TRY(il, eventname); + + + il.Emit(OpCodes.Ldloc_0); // Load local variable 0 onto stack + // il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("SetFunctionList", new Type[] { typeof(Array) })); + + il.Emit(OpCodes.Ret); // Return + } + + + private void IL_INSERT_TRY(ILGenerator il, string eventname) + { + /* + * CLR TRY + */ + //Common.SendToDebug("CLR:" + eventname + ":il.BeginExceptionBlock()"); + il.BeginExceptionBlock(); + + // Push "Hello World!" string to stack + //Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Ldstr..."); + //il.Emit(OpCodes.Ldstr, "Starting CLR dynamic execution of: " + eventname); + } + + private void IL_INSERT_END_TRY(ILGenerator il, string eventname) + { + /* + * CATCH + */ + Common.SendToDebug("CLR:" + eventname + ":il.BeginCatchBlock(typeof(Exception));"); + il.BeginCatchBlock(typeof (Exception)); + + // Push "Hello World!" string to stack + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Ldstr..."); + il.Emit(OpCodes.Ldstr, "Execption executing dynamic CLR function " + eventname + ": "); + + //call void [mscorlib]System.Console::WriteLine(string) + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); + il.Emit(OpCodes.Call, typeof (Console).GetMethod + ("Write", new Type[] {typeof (string)})); + + //callvirt instance string [mscorlib]System.Exception::get_Message() + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Callvirt..."); + il.Emit(OpCodes.Callvirt, typeof (Exception).GetMethod + ("get_Message")); + + //call void [mscorlib]System.Console::WriteLine(string) + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); + il.Emit(OpCodes.Call, typeof (Console).GetMethod + ("WriteLine", new Type[] {typeof (string)})); + + /* + * CLR END TRY + */ + //Common.SendToDebug("CLR:" + eventname + ":il.EndExceptionBlock();"); + il.EndExceptionBlock(); + } + + private LSO_Struct.StaticBlock GetStaticBlock(long pos) + { + long FirstPos = fs.Position; + try + { + UInt32 position = (UInt32) pos; + // STATIC BLOCK + Common.SendToDebug("Reading STATIC BLOCK at: " + position); + fs.Seek(position, SeekOrigin.Begin); + + if (StaticBlocks.ContainsKey(position) == true) + { + Common.SendToDebug("Found cached STATIC BLOCK"); + + + return StaticBlocks[pos]; + } + + //int StaticBlockCount = 0; + // Read function blocks until we hit GFR + //while (fs.Position < myHeader.GFR) + //{ + //StaticBlockCount++; + + //Common.SendToDebug("Reading Static Block at: " + position); + + //fs.Seek(myHeader.GVR, SeekOrigin.Begin); + LSO_Struct.StaticBlock myStaticBlock = new LSO_Struct.StaticBlock(); + myStaticBlock.Static_Chunk_Header_Size = BitConverter.ToUInt32(br_read(4), 0); + myStaticBlock.ObjectType = br_read(1)[0]; + Common.SendToDebug("Static Block ObjectType: " + + ((LSO_Enums.Variable_Type_Codes) myStaticBlock.ObjectType).ToString()); + myStaticBlock.Unknown = br_read(1)[0]; + // Size of datatype varies + if (myStaticBlock.ObjectType != 0) + myStaticBlock.BlockVariable = br_read(getObjectSize(myStaticBlock.ObjectType)); + + StaticBlocks.Add(position, myStaticBlock); + //} + Common.SendToDebug("Done reading Static Block."); + return myStaticBlock; + } + finally + { + // Go back to original read pos + fs.Seek(FirstPos, SeekOrigin.Begin); + } + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSO_Struct.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSO_Struct.cs new file mode 100644 index 0000000000..9b1a3b71a5 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/LSO/LSO_Struct.cs @@ -0,0 +1,143 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSO +{ + internal static class LSO_Struct + { + public struct Header + { + public UInt32 TM; + public UInt32 IP; + public UInt32 VN; + public UInt32 BP; + public UInt32 SP; + public UInt32 HR; + public UInt32 HP; + public UInt32 CS; + public UInt32 NS; + public UInt32 CE; + public UInt32 IE; + public UInt32 ER; + public UInt32 FR; + public UInt32 SLR; + public UInt32 GVR; + public UInt32 GFR; + public UInt32 PR; + public UInt32 ESR; + public UInt32 SR; + public UInt64 NCE; + public UInt64 NIE; + public UInt64 NER; + } + + public struct StaticBlock + { + public UInt32 Static_Chunk_Header_Size; + public byte ObjectType; + public byte Unknown; + public byte[] BlockVariable; + } + + /* Not actually a structure + public struct StaticBlockVariable + { + public UInt32 Integer1; + public UInt32 Float1; + public UInt32 HeapPointer_String; + public UInt32 HeapPointer_Key; + public byte[] Vector_12; + public byte[] Rotation_16; + public UInt32 Pointer_List_Structure; + } */ + + public struct HeapBlock + { + public Int32 DataBlockSize; + public byte ObjectType; + public UInt16 ReferenceCount; + public byte[] Data; + } + + public struct StateFrameBlock + { + public UInt32 StateCount; + public StatePointerBlock[] StatePointer; + } + + public struct StatePointerBlock + { + public UInt32 Location; + public BitArray EventMask; + public StateBlock StateBlock; + } + + public struct StateBlock + { + public UInt32 StartPos; + public UInt32 EndPos; + public UInt32 HeaderSize; + public byte Unknown; + public StateBlockHandler[] StateBlockHandlers; + } + + public struct StateBlockHandler + { + public UInt32 CodeChunkPointer; + public UInt32 CallFrameSize; + } + + public struct FunctionBlock + { + public UInt32 FunctionCount; + public UInt32[] CodeChunkPointer; + } + + public struct CodeChunk + { + public UInt32 CodeChunkHeaderSize; + public string Comment; + public List CodeChunkArguments; + public byte EndMarker; + public byte ReturnTypePos; + public StaticBlock ReturnType; + } + + public struct CodeChunkArgument + { + public byte FunctionReturnTypePos; + public byte NullString; + public StaticBlock FunctionReturnType; + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs new file mode 100644 index 0000000000..1ffbd3af66 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs @@ -0,0 +1,2286 @@ +/* +* 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; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using System.Text; +using System.Threading; +using Axiom.Math; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSL; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler +{ + // + // !!!IMPORTANT!!! + // + // REMEMBER TO UPDATE http://opensimulator.org/wiki/LlFunction_implementation_status + // + + /// + /// Contains all LSL ll-functions. This class will be in Default AppDomain. + /// + public class LSL_BuiltIn_Commands : MarshalByRefObject, LSL_BuiltIn_Commands_Interface + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private ASCIIEncoding enc = new ASCIIEncoding(); + private ScriptEngine m_ScriptEngine; + private SceneObjectPart m_host; + private uint m_localID; + private LLUUID m_itemID; + private bool throwErrorOnNotImplemented = true; + + + public LSL_BuiltIn_Commands(ScriptEngine ScriptEngine, SceneObjectPart host, uint localID, LLUUID itemID) + { + m_ScriptEngine = ScriptEngine; + m_host = host; + m_localID = localID; + m_itemID = itemID; + + + //m_log.Info("[ScriptEngine]: LSL_BaseClass.Start() called. Hosted by [" + m_host.Name + ":" + m_host.UUID + "@" + m_host.AbsolutePosition + "]"); + } + + + private string m_state = "default"; + + public string State() + { + return m_state; + } + + // Object never expires + public override Object InitializeLifetimeService() + { + //Console.WriteLine("LSL_BuiltIn_Commands: InitializeLifetimeService()"); + // return null; + ILease lease = (ILease) base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); + // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); + // lease.RenewOnCallTime = TimeSpan.FromSeconds(2); + } + return lease; + } + + + public Scene World + { + get { return m_ScriptEngine.World; } + } + + //These are the implementations of the various ll-functions used by the LSL scripts. + //starting out, we use the System.Math library for trig functions. - ckrinke 8-14-07 + public double llSin(double f) + { + return (double) Math.Sin(f); + } + + public double llCos(double f) + { + return (double) Math.Cos(f); + } + + public double llTan(double f) + { + return (double) Math.Tan(f); + } + + public double llAtan2(double x, double y) + { + return (double) Math.Atan2(y, x); + } + + public double llSqrt(double f) + { + return (double) Math.Sqrt(f); + } + + public double llPow(double fbase, double fexponent) + { + return (double) Math.Pow(fbase, fexponent); + } + + public int llAbs(int i) + { + return (int) Math.Abs(i); + } + + public double llFabs(double f) + { + return (double) Math.Abs(f); + } + + public double llFrand(double mag) + { + lock (Util.RandomClass) + { + return Util.RandomClass.Next((int) mag); + } + } + + public int llFloor(double f) + { + return (int) Math.Floor(f); + } + + public int llCeil(double f) + { + return (int) Math.Ceiling(f); + } + + public int llRound(double f) + { + return (int) Math.Round(f, 3); + } + + //This next group are vector operations involving squaring and square root. ckrinke + public double llVecMag(LSL_Types.Vector3 v) + { + return (v.X*v.X + v.Y*v.Y + v.Z*v.Z); + } + + public LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v) + { + double mag = v.X*v.X + v.Y*v.Y + v.Z*v.Z; + LSL_Types.Vector3 nor = new LSL_Types.Vector3(); + nor.X = v.X/mag; + nor.Y = v.Y/mag; + nor.Z = v.Z/mag; + return nor; + } + + public double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b) + { + double dx = a.X - b.X; + double dy = a.Y - b.Y; + double dz = a.Z - b.Z; + return Math.Sqrt(dx*dx + dy*dy + dz*dz); + } + + //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke + public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r) + { + //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke + LSL_Types.Quaternion t = new LSL_Types.Quaternion(r.X*r.X, r.Y*r.Y, r.Z*r.Z, r.R*r.R); + double m = (t.X + t.Y + t.Z + t.R); + if (m == 0) return new LSL_Types.Vector3(); + double n = 2*(r.Y*r.R + r.X*r.Z); + double p = m*m - n*n; + if (p > 0) + return new LSL_Types.Vector3(Math.Atan2(2.0*(r.X*r.R - r.Y*r.Z), (-t.X - t.Y + t.Z + t.R)), + Math.Atan2(n, Math.Sqrt(p)), + Math.Atan2(2.0*(r.Z*r.R - r.X*r.Y), (t.X - t.Y - t.Z + t.R))); + else if (n > 0) + return new LSL_Types.Vector3(0.0, Math.PI/2, Math.Atan2((r.Z*r.R + r.X*r.Y), 0.5 - t.X - t.Z)); + else + return new LSL_Types.Vector3(0.0, -Math.PI/2, Math.Atan2((r.Z*r.R + r.X*r.Y), 0.5 - t.X - t.Z)); + } + + public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v) + { + //this comes from from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions but is incomplete as of 8/19/07 + float err = 0.00001f; + double ax = Math.Sin(v.X/2); + double aw = Math.Cos(v.X/2); + double by = Math.Sin(v.Y/2); + double bw = Math.Cos(v.Y/2); + double cz = Math.Sin(v.Z/2); + double cw = Math.Cos(v.Z/2); + LSL_Types.Quaternion a1 = new LSL_Types.Quaternion(0.0, 0.0, cz, cw); + LSL_Types.Quaternion a2 = new LSL_Types.Quaternion(0.0, by, 0.0, bw); + LSL_Types.Quaternion a3 = new LSL_Types.Quaternion(ax, 0.0, 0.0, aw); + LSL_Types.Quaternion a = new LSL_Types.Quaternion(); + //This multiplication doesnt compile, yet. a = a1 * a2 * a3; + LSL_Types.Quaternion b = new LSL_Types.Quaternion(ax*bw*cw + aw*by*cz, + aw*by*cw - ax*bw*cz, aw*bw*cz + ax*by*cw, + aw*bw*cw - ax*by*cz); + LSL_Types.Quaternion c = new LSL_Types.Quaternion(); + //This addition doesnt compile yet c = a + b; + LSL_Types.Quaternion d = new LSL_Types.Quaternion(); + //This addition doesnt compile yet d = a - b; + if ((Math.Abs(c.X) > err && Math.Abs(d.X) > err) || + (Math.Abs(c.Y) > err && Math.Abs(d.Y) > err) || + (Math.Abs(c.Z) > err && Math.Abs(d.Z) > err) || + (Math.Abs(c.R) > err && Math.Abs(d.R) > err)) + { + //return a new Quaternion that is null until I figure this out + // return b; + // return a; + } + return new LSL_Types.Quaternion(); + } + + public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up) + { + return new LSL_Types.Quaternion(); + } + + public LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r) + { + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r) + { + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r) + { + return new LSL_Types.Vector3(); + } + + public LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 start, LSL_Types.Vector3 end) + { + return new LSL_Types.Quaternion(); + } + + public void llWhisper(int channelID, string text) + { + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); + } + + public void llSay(int channelID, string text) + { + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); + } + + public void llShout(int channelID, string text) + { + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); + } + + public int llListen(int channelID, string name, string ID, string msg) + { + NotImplemented("llListen"); + return 0; + } + + public void llListenControl(int number, int active) + { + NotImplemented("llListenControl"); + return; + } + + public void llListenRemove(int number) + { + NotImplemented("llListenRemove"); + return; + } + + public void llSensor(string name, string id, int type, double range, double arc) + { + NotImplemented("llSensor"); + return; + } + + public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) + { + NotImplemented("llSensorRepeat"); + return; + } + + public void llSensorRemove() + { + NotImplemented("llSensorRemove"); + return; + } + + public string llDetectedName(int number) + { + NotImplemented("llDetectedName"); + return ""; + } + + public string llDetectedKey(int number) + { + NotImplemented("llDetectedKey"); + return ""; + } + + public string llDetectedOwner(int number) + { + NotImplemented("llDetectedOwner"); + return ""; + } + + public int llDetectedType(int number) + { + NotImplemented("llDetectedType"); + return 0; + } + + public LSL_Types.Vector3 llDetectedPos(int number) + { + NotImplemented("llDetectedPos"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llDetectedVel(int number) + { + NotImplemented("llDetectedVel"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llDetectedGrab(int number) + { + NotImplemented("llDetectedGrab"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Quaternion llDetectedRot(int number) + { + NotImplemented("llDetectedRot"); + return new LSL_Types.Quaternion(); + } + + public int llDetectedGroup(int number) + { + NotImplemented("llDetectedGroup"); + return 0; + } + + public int llDetectedLinkNumber(int number) + { + NotImplemented("llDetectedLinkNumber"); + return 0; + } + + public void llDie() + { + NotImplemented("llDie"); + return; + } + + public double llGround(LSL_Types.Vector3 offset) + { + NotImplemented("llGround"); + return 0; + } + + public double llCloud(LSL_Types.Vector3 offset) + { + NotImplemented("llCloud"); + return 0; + } + + public LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset) + { + NotImplemented("llWind"); + return new LSL_Types.Vector3(); + } + + public void llSetStatus(int status, int value) + { + NotImplemented("llSetStatus"); + return; + } + + public int llGetStatus(int status) + { + NotImplemented("llGetStatus"); + return 0; + } + + public void llSetScale(LSL_Types.Vector3 scale) + { + // TODO: this needs to trigger a persistance save as well + LLVector3 tmp = m_host.Scale; + tmp.X = (float) scale.X; + tmp.Y = (float) scale.Y; + tmp.Z = (float) scale.Z; + m_host.Scale = tmp; + return; + } + + public LSL_Types.Vector3 llGetScale() + { + return new LSL_Types.Vector3(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z); + } + + public void llSetColor(LSL_Types.Vector3 color, int face) + { + NotImplemented("llSetColor"); + return; + } + + public double llGetAlpha(int face) + { + NotImplemented("llGetAlpha"); + return 0; + } + + public void llSetAlpha(double alpha, int face) + { + NotImplemented("llSetAlpha"); + return; + } + + public LSL_Types.Vector3 llGetColor(int face) + { + NotImplemented("llGetColor"); + return new LSL_Types.Vector3(); + } + + public void llSetTexture(string texture, int face) + { + NotImplemented("llSetTexture"); + return; + } + + public void llScaleTexture(double u, double v, int face) + { + NotImplemented("llScaleTexture"); + return; + } + + public void llOffsetTexture(double u, double v, int face) + { + NotImplemented("llOffsetTexture"); + return; + } + + public void llRotateTexture(double rotation, int face) + { + NotImplemented("llRotateTexture"); + return; + } + + public string llGetTexture(int face) + { + NotImplemented("llGetTexture"); + return ""; + } + + public void llSetPos(LSL_Types.Vector3 pos) + { + if (m_host.ParentID != 0) + { + m_host.UpdateOffSet(new LLVector3((float) pos.X, (float) pos.Y, (float) pos.Z)); + } + else + { + m_host.UpdateGroupPosition(new LLVector3((float) pos.X, (float) pos.Y, (float) pos.Z)); + } + } + + public LSL_Types.Vector3 llGetPos() + { + return new LSL_Types.Vector3(m_host.AbsolutePosition.X, + m_host.AbsolutePosition.Y, + m_host.AbsolutePosition.Z); + } + + public LSL_Types.Vector3 llGetLocalPos() + { + if (m_host.ParentID != 0) + { + return new LSL_Types.Vector3(m_host.OffsetPosition.X, + m_host.OffsetPosition.Y, + m_host.OffsetPosition.Z); + } + else + { + return new LSL_Types.Vector3(m_host.AbsolutePosition.X, + m_host.AbsolutePosition.Y, + m_host.AbsolutePosition.Z); + } + } + + public void llSetRot(LSL_Types.Quaternion rot) + { + m_host.UpdateRotation(new LLQuaternion((float) rot.X, (float) rot.Y, (float) rot.Z, (float) rot.R)); + } + + public LSL_Types.Quaternion llGetRot() + { + LLQuaternion q = m_host.RotationOffset; + return new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); + } + + public LSL_Types.Quaternion llGetLocalRot() + { + NotImplemented("llGetLocalRot"); + return new LSL_Types.Quaternion(); + } + + public void llSetForce(LSL_Types.Vector3 force, int local) + { + NotImplemented("llSetForce"); + } + + public LSL_Types.Vector3 llGetForce() + { + NotImplemented("llGetForce"); + return new LSL_Types.Vector3(); + } + + public int llTarget(LSL_Types.Vector3 position, double range) + { + NotImplemented("llTarget"); + return 0; + } + + public void llTargetRemove(int number) + { + NotImplemented("llTargetRemove"); + } + + public int llRotTarget(LSL_Types.Quaternion rot, double error) + { + NotImplemented("llRotTarget"); + return 0; + } + + public void llRotTargetRemove(int number) + { + NotImplemented("llRotTargetRemove"); + } + + public void llMoveToTarget(LSL_Types.Vector3 target, double tau) + { + NotImplemented("llMoveToTarget"); + } + + public void llStopMoveToTarget() + { + NotImplemented("llStopMoveToTarget"); + } + + public void llApplyImpulse(LSL_Types.Vector3 force, int local) + { + NotImplemented("llApplyImpulse"); + } + + public void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local) + { + NotImplemented("llApplyRotationalImpulse"); + } + + public void llSetTorque(LSL_Types.Vector3 torque, int local) + { + NotImplemented("llSetTorque"); + } + + public LSL_Types.Vector3 llGetTorque() + { + NotImplemented("llGetTorque"); + return new LSL_Types.Vector3(); + } + + public void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local) + { + NotImplemented("llSetForceAndTorque"); + } + + public LSL_Types.Vector3 llGetVel() + { + NotImplemented("llGetVel"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGetAccel() + { + NotImplemented("llGetAccel"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGetOmega() + { + NotImplemented("llGetOmega"); + return new LSL_Types.Vector3(); + } + + public double llGetTimeOfDay() + { + NotImplemented("llGetTimeOfDay"); + return 0; + } + + public double llGetWallclock() + { + return DateTime.Now.TimeOfDay.TotalSeconds; + } + + public double llGetTime() + { + NotImplemented("llGetTime"); + return 0; + } + + public void llResetTime() + { + NotImplemented("llResetTime"); + } + + public double llGetAndResetTime() + { + NotImplemented("llGetAndResetTime"); + return 0; + } + + public void llSound() + { + NotImplemented("llSound"); + } + + public void llPlaySound(string sound, double volume) + { + NotImplemented("llPlaySound"); + } + + public void llLoopSound(string sound, double volume) + { + NotImplemented("llLoopSound"); + } + + public void llLoopSoundMaster(string sound, double volume) + { + NotImplemented("llLoopSoundMaster"); + } + + public void llLoopSoundSlave(string sound, double volume) + { + NotImplemented("llLoopSoundSlave"); + } + + public void llPlaySoundSlave(string sound, double volume) + { + NotImplemented("llPlaySoundSlave"); + } + + public void llTriggerSound(string sound, double volume) + { + NotImplemented("llTriggerSound"); + } + + public void llStopSound() + { + NotImplemented("llStopSound"); + } + + public void llPreloadSound(string sound) + { + NotImplemented("llPreloadSound"); + } + + public string llGetSubString(string src, int start, int end) + { + return src.Substring(start, end); + } + + public string llDeleteSubString(string src, int start, int end) + { + return src.Remove(start, end - start); + } + + public string llInsertString(string dst, int position, string src) + { + return dst.Insert(position, src); + } + + public string llToUpper(string src) + { + return src.ToUpper(); + } + + public string llToLower(string src) + { + return src.ToLower(); + } + + public int llGiveMoney(string destination, int amount) + { + NotImplemented("llGiveMoney"); + return 0; + } + + public void llMakeExplosion() + { + NotImplemented("llMakeExplosion"); + } + + public void llMakeFountain() + { + NotImplemented("llMakeFountain"); + } + + public void llMakeSmoke() + { + NotImplemented("llMakeSmoke"); + } + + public void llMakeFire() + { + NotImplemented("llMakeFire"); + } + + public void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Quaternion rot, int param) + { + NotImplemented("llRezObject"); + } + + public void llLookAt(LSL_Types.Vector3 target, double strength, double damping) + { + NotImplemented("llLookAt"); + } + + public void llStopLookAt() + { + NotImplemented("llStopLookAt"); + } + + public void llSetTimerEvent(double sec) + { + // Setting timer repeat + m_ScriptEngine.m_LSLLongCmdHandler.SetTimerEvent(m_localID, m_itemID, sec); + } + + public void llSleep(double sec) + { + Thread.Sleep((int) (sec*1000)); + } + + public double llGetMass() + { + NotImplemented("llGetMass"); + return 0; + } + + public void llCollisionFilter(string name, string id, int accept) + { + NotImplemented("llCollisionFilter"); + } + + public void llTakeControls(int controls, int accept, int pass_on) + { + NotImplemented("llTakeControls"); + } + + public void llReleaseControls() + { + NotImplemented("llReleaseControls"); + } + + public void llAttachToAvatar(int attachment) + { + NotImplemented("llAttachToAvatar"); + } + + public void llDetachFromAvatar() + { + NotImplemented("llDetachFromAvatar"); + } + + public void llTakeCamera() + { + NotImplemented("llTakeCamera"); + } + + public void llReleaseCamera() + { + NotImplemented("llReleaseCamera"); + } + + public string llGetOwner() + { + return m_host.ObjectOwner.ToString(); + } + + public void llInstantMessage(string user, string message) + { + NotImplemented("llInstantMessage"); + } + + public void llEmail(string address, string subject, string message) + { + NotImplemented("llEmail"); + } + + public void llGetNextEmail(string address, string subject) + { + NotImplemented("llGetNextEmail"); + } + + public string llGetKey() + { + return m_host.UUID.ToString(); + } + + public void llSetBuoyancy(double buoyancy) + { + NotImplemented("llSetBuoyancy"); + } + + public void llSetHoverHeight(double height, int water, double tau) + { + NotImplemented("llSetHoverHeight"); + } + + public void llStopHover() + { + NotImplemented("llStopHover"); + } + + public void llMinEventDelay(double delay) + { + NotImplemented("llMinEventDelay"); + } + + public void llSoundPreload() + { + NotImplemented("llSoundPreload"); + } + + public void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping) + { + NotImplemented("llRotLookAt"); + } + + public int llStringLength(string str) + { + if (str.Length > 0) + { + return str.Length; + } + else + { + return 0; + } + } + + public void llStartAnimation(string anim) + { + NotImplemented("llStartAnimation"); + } + + public void llStopAnimation(string anim) + { + NotImplemented("llStopAnimation"); + } + + public void llPointAt() + { + NotImplemented("llPointAt"); + } + + public void llStopPointAt() + { + NotImplemented("llStopPointAt"); + } + + public void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain) + { + NotImplemented("llTargetOmega"); + } + + public int llGetStartParameter() + { + NotImplemented("llGetStartParameter"); + return 0; + } + + public void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos) + { + NotImplemented("llGodLikeRezObject"); + } + + public void llRequestPermissions(string agent, int perm) + { + NotImplemented("llRequestPermissions"); + } + + public string llGetPermissionsKey() + { + NotImplemented("llGetPermissionsKey"); + return ""; + } + + public int llGetPermissions() + { + NotImplemented("llGetPermissions"); + return 0; + } + + public int llGetLinkNumber() + { + NotImplemented("llGetLinkNumber"); + return 0; + } + + public void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face) + { + NotImplemented("llSetLinkColor"); + } + + public void llCreateLink(string target, int parent) + { + NotImplemented("llCreateLink"); + } + + public void llBreakLink(int linknum) + { + NotImplemented("llBreakLink"); + } + + public void llBreakAllLinks() + { + NotImplemented("llBreakAllLinks"); + } + + public string llGetLinkKey(int linknum) + { + NotImplemented("llGetLinkKey"); + return ""; + } + + public void llGetLinkName(int linknum) + { + NotImplemented("llGetLinkName"); + } + + public int llGetInventoryNumber(int type) + { + NotImplemented("llGetInventoryNumber"); + return 0; + } + + public string llGetInventoryName(int type, int number) + { + NotImplemented("llGetInventoryName"); + return ""; + } + + public void llSetScriptState(string name, int run) + { + NotImplemented("llSetScriptState"); + } + + public double llGetEnergy() + { + return 1.0f; + } + + public void llGiveInventory(string destination, string inventory) + { + NotImplemented("llGiveInventory"); + } + + public void llRemoveInventory(string item) + { + NotImplemented("llRemoveInventory"); + } + + public void llSetText(string text, LSL_Types.Vector3 color, double alpha) + { + Vector3 av3 = new Vector3((float) color.X, (float) color.Y, (float) color.Z); + m_host.SetText(text, av3, alpha); + } + + + public double llWater(LSL_Types.Vector3 offset) + { + NotImplemented("llWater"); + return 0; + } + + public void llPassTouches(int pass) + { + NotImplemented("llPassTouches"); + } + + public string llRequestAgentData(string id, int data) + { + NotImplemented("llRequestAgentData"); + return ""; + } + + public string llRequestInventoryData(string name) + { + NotImplemented("llRequestInventoryData"); + return ""; + } + + public void llSetDamage(double damage) + { + NotImplemented("llSetDamage"); + } + + public void llTeleportAgentHome(string agent) + { + NotImplemented("llTeleportAgentHome"); + } + + public void llModifyLand(int action, int brush) + { + } + + public void llCollisionSound(string impact_sound, double impact_volume) + { + NotImplemented("llCollisionSound"); + } + + public void llCollisionSprite(string impact_sprite) + { + NotImplemented("llCollisionSprite"); + } + + public string llGetAnimation(string id) + { + NotImplemented("llGetAnimation"); + return ""; + } + + public void llResetScript() + { + m_ScriptEngine.m_ScriptManager.ResetScript(m_localID, m_itemID); + } + + public void llMessageLinked(int linknum, int num, string str, string id) + { + } + + public void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local) + { + } + + public void llPassCollisions(int pass) + { + } + + public string llGetScriptName() + { + return ""; + } + + public int llGetNumberOfSides() + { + return 0; + } + + public LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle) + { + return new LSL_Types.Quaternion(); + } + + public LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot) + { + return new LSL_Types.Vector3(); + } + + public void llRot2Angle() + { + } + + public double llAcos(double val) + { + return (double) Math.Acos(val); + } + + public double llAsin(double val) + { + return (double) Math.Asin(val); + } + + public double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b) + { + return 0; + } + + public string llGetInventoryKey(string name) + { + return ""; + } + + public void llAllowInventoryDrop(int add) + { + } + + public LSL_Types.Vector3 llGetSunDirection() + { + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGetTextureOffset(int face) + { + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGetTextureScale(int side) + { + return new LSL_Types.Vector3(); + } + + public double llGetTextureRot(int side) + { + return 0; + } + + public int llSubStringIndex(string source, string pattern) + { + return source.IndexOf(pattern); + } + + public string llGetOwnerKey(string id) + { + NotImplemented("llGetOwnerKey"); + return ""; + } + + public LSL_Types.Vector3 llGetCenterOfMass() + { + NotImplemented("llGetCenterOfMass"); + return new LSL_Types.Vector3(); + } + + public List llListSort(List src, int stride, int ascending) + { + SortedList> sorted = new SortedList>(); + // Add chunks to an array + int s = stride; + if (s < 1) + s = 1; + int c = 0; + List chunk = new List(); + string chunkString = ""; + foreach (string element in src) + { + c++; + if (c > s) + { + sorted.Add(chunkString, chunk); + chunkString = ""; + chunk = new List(); + c = 0; + } + chunk.Add(element); + chunkString += element.ToString(); + } + if (chunk.Count > 0) + sorted.Add(chunkString, chunk); + + List ret = new List(); + foreach (List ls in sorted.Values) + { + ret.AddRange(ls); + } + + if (ascending == LSL_BaseClass.TRUE) + return ret; + ret.Reverse(); + return ret; + } + + public int llGetListLength(List src) + { + return src.Count; + } + + public int llList2Integer(List src, int index) + { + return Convert.ToInt32(src[index]); + } + + public double llList2double(List src, int index) + { + return Convert.ToDouble(src[index]); + } + + public float llList2Float(List src, int index) + { + return Convert.ToSingle(src[index]); + } + + public string llList2String(List src, int index) + { + return src[index]; + } + + public string llList2Key(List src, int index) + { + //return OpenSim.Framework.ToString(src[index]); + return src[index].ToString(); + } + + public LSL_Types.Vector3 llList2Vector(List src, int index) + { + return + new LSL_Types.Vector3(double.Parse(src[index]), double.Parse(src[index + 1]), + double.Parse(src[index + 2])); + } + + public LSL_Types.Quaternion llList2Rot(List src, int index) + { + return + new LSL_Types.Quaternion(double.Parse(src[index]), double.Parse(src[index + 1]), + double.Parse(src[index + 2]), double.Parse(src[index + 3])); + } + + public List llList2List(List src, int start, int end) + { + if (end > start) + { + // Simple straight forward chunk + return src.GetRange(start, end - start); + } + else + { + // Some of the end + some of the beginning + // First chunk + List ret = new List(); + ret.AddRange(src.GetRange(start, src.Count - start)); + ret.AddRange(src.GetRange(0, end)); + return ret; + } + } + + public List llDeleteSubList(List src, int start, int end) + { + List ret = new List(src); + ret.RemoveRange(start, end - start); + return ret; + } + + public int llGetListEntryType(List src, int index) + { + NotImplemented("llGetListEntryType"); + return 0; + } + + public string llList2CSV(List src) + { + string ret = ""; + foreach (string s in src) + { + if (s.Length > 0) + ret += ","; + ret += s; + } + return ret; + } + + public List llCSV2List(string src) + { + List ret = new List(); + foreach (string s in src.Split(",".ToCharArray())) + { + ret.Add(s); + } + return ret; + } + + public List llListRandomize(List src, int stride) + { + int s = stride; + if (s < 1) + s = 1; + + // This is a cowardly way of doing it ;) + // TODO: Instead, randomize and check if random is mod stride or if it can not be, then array.removerange + List> tmp = new List>(); + + // Add chunks to an array + int c = 0; + List chunk = new List(); + foreach (string element in src) + { + c++; + if (c > s) + { + tmp.Add(chunk); + chunk = new List(); + c = 0; + } + chunk.Add(element); + } + if (chunk.Count > 0) + tmp.Add(chunk); + + // Decreate (<- what kind of word is that? :D ) array back into a list + int rnd; + List ret = new List(); + while (tmp.Count > 0) + { + rnd = Util.RandomClass.Next(tmp.Count); + foreach (string str in tmp[rnd]) + { + ret.Add(str); + } + tmp.RemoveAt(rnd); + } + + return ret; + } + + public List llList2ListStrided(List src, int start, int end, int stride) + { + List ret = new List(); + int s = stride; + if (s < 1) + s = 1; + + int sc = s; + for (int i = start; i < src.Count; i++) + { + sc--; + if (sc == 0) + { + sc = s; + // Addthis + ret.Add(src[i]); + } + if (i == end) + break; + } + return ret; + } + + public LSL_Types.Vector3 llGetRegionCorner() + { + return new LSL_Types.Vector3(World.RegionInfo.RegionLocX*256, World.RegionInfo.RegionLocY*256, 0); + } + + public List llListInsertList(List dest, List src, int start) + { + List ret = new List(dest); + //foreach (string s in src.Reverse()) + for (int ci = src.Count - 1; ci > -1; ci--) + { + ret.Insert(start, src[ci]); + } + return ret; + } + + public int llListFindList(List src, List test) + { + foreach (string s in test) + { + for (int ci = 0; ci < src.Count; ci++) + { + if (s == src[ci]) + return ci; + } + } + return -1; + } + + public string llGetObjectName() + { + return m_host.Name; + } + + public void llSetObjectName(string name) + { + m_host.Name = name; + } + + public string llGetDate() + { + DateTime date = DateTime.Now.ToUniversalTime(); + string result = date.ToString("yyyy-MM-dd"); + return result; + } + + public int llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir) + { + NotImplemented("llEdgeOfWorld"); + return 0; + } + + public int llGetAgentInfo(string id) + { + NotImplemented("llGetAgentInfo"); + return 0; + } + + public void llAdjustSoundVolume(double volume) + { + NotImplemented("llAdjustSoundVolume"); + } + + public void llSetSoundQueueing(int queue) + { + NotImplemented("llSetSoundQueueing"); + } + + public void llSetSoundRadius(double radius) + { + NotImplemented("llSetSoundRadius"); + } + + public string llKey2Name(string id) + { + NotImplemented("llKey2Name"); + return ""; + } + + public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + NotImplemented("llSetTextureAnim"); + } + + public void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east, + LSL_Types.Vector3 bottom_south_west) + { + NotImplemented("llTriggerSoundLimited"); + } + + public void llEjectFromLand(string pest) + { + NotImplemented("llEjectFromLand"); + } + + public void llParseString2List() + { + NotImplemented("llParseString2List"); + } + + public int llOverMyLand(string id) + { + NotImplemented("llOverMyLand"); + return 0; + } + + public string llGetLandOwnerAt(LSL_Types.Vector3 pos) + { + NotImplemented("llGetLandOwnerAt"); + return ""; + } + + public string llGetNotecardLine(string name, int line) + { + NotImplemented("llGetNotecardLine"); + return ""; + } + + public LSL_Types.Vector3 llGetAgentSize(string id) + { + NotImplemented("llGetAgentSize"); + return new LSL_Types.Vector3(); + } + + public int llSameGroup(string agent) + { + NotImplemented("llSameGroup"); + return 0; + } + + public void llUnSit(string id) + { + NotImplemented("llUnSit"); + } + + public LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset) + { + NotImplemented("llGroundSlope"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset) + { + NotImplemented("llGroundNormal"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset) + { + NotImplemented("llGroundContour"); + return new LSL_Types.Vector3(); + } + + public int llGetAttached() + { + NotImplemented("llGetAttached"); + return 0; + } + + public int llGetFreeMemory() + { + NotImplemented("llGetFreeMemory"); + return 0; + } + + public string llGetRegionName() + { + return World.RegionInfo.RegionName; + } + + public double llGetRegionTimeDilation() + { + return 1.0f; + } + + public double llGetRegionFPS() + { + return 10.0f; + } + + /* particle system rules should be coming into this routine as doubles, that is + rule[0] should be an integer from this list and rule[1] should be the arg + for the same integer. wiki.secondlife.com has most of this mapping, but some + came from http://www.caligari-designs.com/p4u2 + + We iterate through the list for 'Count' elements, incrementing by two for each + iteration and set the members of Primitive.ParticleSystem, one at a time. + */ + + public enum PrimitiveRule : int + { + PSYS_PART_FLAGS = 0, + PSYS_PART_START_COLOR = 1, + PSYS_PART_START_ALPHA = 2, + PSYS_PART_END_COLOR = 3, + PSYS_PART_END_ALPHA = 4, + PSYS_PART_START_SCALE = 5, + PSYS_PART_END_SCALE = 6, + PSYS_PART_MAX_AGE = 7, + PSYS_SRC_ACCEL = 8, + PSYS_SRC_PATTERN = 9, + PSYS_SRC_TEXTURE = 12, + PSYS_SRC_BURST_RATE = 13, + PSYS_SRC_BURST_PART_COUNT = 15, + PSYS_SRC_BURST_RADIUS = 16, + PSYS_SRC_BURST_SPEED_MIN = 17, + PSYS_SRC_BURST_SPEED_MAX = 18, + PSYS_SRC_MAX_AGE = 19, + PSYS_SRC_TARGET_KEY = 20, + PSYS_SRC_OMEGA = 21, + PSYS_SRC_ANGLE_BEGIN = 22, + PSYS_SRC_ANGLE_END = 23 + } + + public void llParticleSystem(List rules) + { + Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); + for (int i = 0; i < rules.Count; i += 2) + { + switch ((int) rules[i]) + { + case (int) PrimitiveRule.PSYS_PART_FLAGS: + prules.PartFlags = (uint) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_PART_START_COLOR: + prules.PartStartColor = (LLColor) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_PART_START_ALPHA: + //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_PART_END_COLOR: + prules.PartEndColor = (LLColor) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_PART_END_ALPHA: + //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_PART_START_SCALE: + //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_PART_END_SCALE: + //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_PART_MAX_AGE: + prules.MaxAge = (float) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_ACCEL: + //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_PATTERN: + //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_TEXTURE: + prules.Texture = (LLUUID) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_BURST_RATE: + prules.BurstRate = (float) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_BURST_PART_COUNT: + prules.BurstPartCount = (byte) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_BURST_RADIUS: + prules.BurstRadius = (float) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_BURST_SPEED_MIN: + prules.BurstSpeedMin = (float) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_BURST_SPEED_MAX: + prules.BurstSpeedMax = (float) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_MAX_AGE: + prules.MaxAge = (float) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_TARGET_KEY: + prules.Target = (LLUUID) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_OMEGA: + //cast?? prules.MaxAge = (float)rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_ANGLE_BEGIN: + prules.InnerAngle = (float) rules[i + 1]; + break; + + case (int) PrimitiveRule.PSYS_SRC_ANGLE_END: + prules.OuterAngle = (float) rules[i + 1]; + break; + } + } + + m_host.AddNewParticleSystem(prules); + } + + public void llGroundRepel(double height, int water, double tau) + { + NotImplemented("llGroundRepel"); + } + + public void llGiveInventoryList() + { + NotImplemented("llGiveInventoryList"); + } + + public void llSetVehicleType(int type) + { + NotImplemented("llSetVehicleType"); + } + + public void llSetVehicledoubleParam(int param, double value) + { + NotImplemented("llSetVehicledoubleParam"); + } + + public void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec) + { + NotImplemented("llSetVehicleVectorParam"); + } + + public void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot) + { + NotImplemented("llSetVehicleRotationParam"); + } + + public void llSetVehicleFlags(int flags) + { + NotImplemented("llSetVehicleFlags"); + } + + public void llRemoveVehicleFlags(int flags) + { + NotImplemented("llRemoveVehicleFlags"); + } + + public void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot) + { + NotImplemented("llSitTarget"); + } + + public string llAvatarOnSitTarget() + { + NotImplemented("llAvatarOnSitTarget"); + return ""; + } + + public void llAddToLandPassList(string avatar, double hours) + { + NotImplemented("llAddToLandPassList"); + } + + public void llSetTouchText(string text) + { + m_host.TouchName = text; + } + + public void llSetSitText(string text) + { + m_host.SitName = text; + } + + public void llSetCameraEyeOffset(LSL_Types.Vector3 offset) + { + NotImplemented("llSetCameraEyeOffset"); + } + + public void llSetCameraAtOffset(LSL_Types.Vector3 offset) + { + NotImplemented("llSetCameraAtOffset"); + } + + public void llDumpList2String() + { + NotImplemented("llDumpList2String"); + } + + public void llScriptDanger(LSL_Types.Vector3 pos) + { + NotImplemented("llScriptDanger"); + } + + public void llDialog(string avatar, string message, List buttons, int chat_channel) + { + NotImplemented("llDialog"); + } + + public void llVolumeDetect(int detect) + { + NotImplemented("llVolumeDetect"); + } + + public void llResetOtherScript(string name) + { + NotImplemented("llResetOtherScript"); + } + + public int llGetScriptState(string name) + { + NotImplemented("llGetScriptState"); + return 0; + } + + public void llRemoteLoadScript() + { + NotImplemented("llRemoteLoadScript"); + } + + public void llSetRemoteScriptAccessPin(int pin) + { + NotImplemented("llSetRemoteScriptAccessPin"); + } + + public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) + { + NotImplemented("llRemoteLoadScriptPin"); + } + + public void llOpenRemoteDataChannel() + { + NotImplemented("llOpenRemoteDataChannel"); + } + + public string llSendRemoteData(string channel, string dest, int idata, string sdata) + { + NotImplemented("llSendRemoteData"); + return ""; + } + + public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) + { + NotImplemented("llRemoteDataReply"); + } + + public void llCloseRemoteDataChannel(string channel) + { + NotImplemented("llCloseRemoteDataChannel"); + } + + public string llMD5String(string src, int nonce) + { + return Util.Md5Hash(src + ":" + nonce.ToString()); + } + + public void llSetPrimitiveParams(List rules) + { + NotImplemented("llSetPrimitiveParams"); + } + + public string llStringToBase64(string str) + { + try + { + byte[] encData_byte = new byte[str.Length]; + encData_byte = Encoding.UTF8.GetBytes(str); + string encodedData = Convert.ToBase64String(encData_byte); + return encodedData; + } + catch (Exception e) + { + throw new Exception("Error in base64Encode" + e.Message); + } + } + + public string llBase64ToString(string str) + { + UTF8Encoding encoder = new UTF8Encoding(); + Decoder utf8Decode = encoder.GetDecoder(); + try + { + byte[] todecode_byte = Convert.FromBase64String(str); + int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length); + char[] decoded_char = new char[charCount]; + utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0); + string result = new String(decoded_char); + return result; + } + catch (Exception e) + { + throw new Exception("Error in base64Decode" + e.Message); + } + } + + public void llXorBase64Strings() + { + throw new Exception("Command deprecated! Use llXorBase64StringsCorrect instead."); + } + + public void llRemoteDataSetRegion() + { + NotImplemented("llRemoteDataSetRegion"); + } + + public double llLog10(double val) + { + return (double) Math.Log10(val); + } + + public double llLog(double val) + { + return (double) Math.Log(val); + } + + public List llGetAnimationList(string id) + { + NotImplemented("llGetAnimationList"); + return new List(); + } + + public void llSetParcelMusicURL(string url) + { + NotImplemented("llSetParcelMusicURL"); + } + + public LSL_Types.Vector3 llGetRootPosition() + { + NotImplemented("llGetRootPosition"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Quaternion llGetRootRotation() + { + NotImplemented("llGetRootRotation"); + return new LSL_Types.Quaternion(); + } + + public string llGetObjectDesc() + { + return m_host.Description; + } + + public void llSetObjectDesc(string desc) + { + m_host.Description = desc; + } + + public string llGetCreator() + { + return m_host.ObjectCreator.ToString(); + } + + public string llGetTimestamp() + { + return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); + } + + public void llSetLinkAlpha(int linknumber, double alpha, int face) + { + NotImplemented("llSetLinkAlpha"); + } + + public int llGetNumberOfPrims() + { + NotImplemented("llGetNumberOfPrims"); + return 0; + } + + public string llGetNumberOfNotecardLines(string name) + { + NotImplemented("llGetNumberOfNotecardLines"); + return ""; + } + + public List llGetBoundingBox(string obj) + { + NotImplemented("llGetBoundingBox"); + return new List(); + } + + public LSL_Types.Vector3 llGetGeometricCenter() + { + NotImplemented("llGetGeometricCenter"); + return new LSL_Types.Vector3(); + } + + public void llGetPrimitiveParams() + { + NotImplemented("llGetPrimitiveParams"); + } + + public string llIntegerToBase64(int number) + { + NotImplemented("llIntegerToBase64"); + return ""; + } + + public int llBase64ToInteger(string str) + { + NotImplemented("llBase64ToInteger"); + return 0; + } + + public double llGetGMTclock() + { + return DateTime.UtcNow.TimeOfDay.TotalSeconds; + } + + public string llGetSimulatorHostname() + { + return Environment.MachineName; + } + + public void llSetLocalRot(LSL_Types.Quaternion rot) + { + NotImplemented("llSetLocalRot"); + } + + public List llParseStringKeepNulls(string src, List seperators, List spacers) + { + NotImplemented("llParseStringKeepNulls"); + return new List(); + } + + public void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity, + LSL_Types.Quaternion rot, int param) + { + NotImplemented("llRezAtRoot"); + } + + public int llGetObjectPermMask(int mask) + { + NotImplemented("llGetObjectPermMask"); + return 0; + } + + public void llSetObjectPermMask(int mask, int value) + { + NotImplemented("llSetObjectPermMask"); + } + + public void llGetInventoryPermMask(string item, int mask) + { + NotImplemented("llGetInventoryPermMask"); + } + + public void llSetInventoryPermMask(string item, int mask, int value) + { + NotImplemented("llSetInventoryPermMask"); + } + + public string llGetInventoryCreator(string item) + { + NotImplemented("llGetInventoryCreator"); + return ""; + } + + public void llOwnerSay(string msg) + { + NotImplemented("llOwnerSay"); + } + + public void llRequestSimulatorData(string simulator, int data) + { + NotImplemented("llRequestSimulatorData"); + } + + public void llForceMouselook(int mouselook) + { + NotImplemented("llForceMouselook"); + } + + public double llGetObjectMass(string id) + { + NotImplemented("llGetObjectMass"); + return 0; + } + + public void llListReplaceList() + { + NotImplemented("llListReplaceList"); + } + + public void llLoadURL(string avatar_id, string message, string url) + { + LLUUID avatarId = new LLUUID(avatar_id); + m_ScriptEngine.World.SendUrlToUser(avatarId, m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message, + url); + } + + public void llParcelMediaCommandList(List commandList) + { + NotImplemented("llParcelMediaCommandList"); + } + + public void llParcelMediaQuery() + { + NotImplemented("llParcelMediaQuery"); + } + + public int llModPow(int a, int b, int c) + { + Int64 tmp = 0; + Int64 val = Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); + return Convert.ToInt32(tmp); + } + + public int llGetInventoryType(string name) + { + NotImplemented("llGetInventoryType"); + return 0; + } + + public void llSetPayPrice(int price, List quick_pay_buttons) + { + NotImplemented("llSetPayPrice"); + } + + public LSL_Types.Vector3 llGetCameraPos() + { + NotImplemented("llGetCameraPos"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Quaternion llGetCameraRot() + { + NotImplemented("llGetCameraRot"); + return new LSL_Types.Quaternion(); + } + + public void llSetPrimURL() + { + NotImplemented("llSetPrimURL"); + } + + public void llRefreshPrimURL() + { + NotImplemented("llRefreshPrimURL"); + } + + public string llEscapeURL(string url) + { + try + { + return Uri.EscapeUriString(url); + } + catch (Exception ex) + { + return "llEscapeURL: " + ex.ToString(); + } + } + + public string llUnescapeURL(string url) + { + try + { + return Uri.UnescapeDataString(url); + } + catch (Exception ex) + { + return "llUnescapeURL: " + ex.ToString(); + } + } + + public void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at) + { + NotImplemented("llMapDestination"); + } + + public void llAddToLandBanList(string avatar, double hours) + { + NotImplemented("llAddToLandBanList"); + } + + public void llRemoveFromLandPassList(string avatar) + { + NotImplemented("llRemoveFromLandPassList"); + } + + public void llRemoveFromLandBanList(string avatar) + { + NotImplemented("llRemoveFromLandBanList"); + } + + public void llSetCameraParams(List rules) + { + NotImplemented("llSetCameraParams"); + } + + public void llClearCameraParams() + { + NotImplemented("llClearCameraParams"); + } + + public double llListStatistics(int operation, List src) + { + NotImplemented("llListStatistics"); + return 0; + } + + public int llGetUnixTime() + { + return Util.UnixTimeSinceEpoch(); + } + + public int llGetParcelFlags(LSL_Types.Vector3 pos) + { + NotImplemented("llGetParcelFlags"); + return 0; + } + + public int llGetRegionFlags() + { + NotImplemented("llGetRegionFlags"); + return 0; + } + + public string llXorBase64StringsCorrect(string str1, string str2) + { + string ret = ""; + string src1 = llBase64ToString(str1); + string src2 = llBase64ToString(str2); + int c = 0; + for (int i = 0; i < src1.Length; i++) + { + ret += src1[i] ^ src2[c]; + + c++; + if (c > src2.Length) + c = 0; + } + return llStringToBase64(ret); + } + + public void llHTTPRequest(string url, List parameters, string body) + { + m_ScriptEngine.m_LSLLongCmdHandler.StartHttpRequest(m_localID, m_itemID, url, parameters, body); + } + + public void llResetLandBanList() + { + NotImplemented("llResetLandBanList"); + } + + public void llResetLandPassList() + { + NotImplemented("llResetLandPassList"); + } + + public int llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide) + { + NotImplemented("llGetParcelPrimCount"); + return 0; + } + + public List llGetParcelPrimOwners(LSL_Types.Vector3 pos) + { + NotImplemented("llGetParcelPrimOwners"); + return new List(); + } + + public int llGetObjectPrimCount(string object_id) + { + NotImplemented("llGetObjectPrimCount"); + return 0; + } + + public int llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide) + { + NotImplemented("llGetParcelMaxPrims"); + return 0; + } + + public List llGetParcelDetails(LSL_Types.Vector3 pos, List param) + { + NotImplemented("llGetParcelDetails"); + return new List(); + } + + // + // OpenSim functions + // + public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, + int timer) + { + if (dynamicID == "") + { + IDynamicTextureManager textureManager = World.RequestModuleInterface(); + LLUUID createdTexture = + textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, + extraParams, timer); + return createdTexture.ToString(); + } + else + { + //TODO update existing dynamic textures + } + + return LLUUID.Zero.ToString(); + } + + private void NotImplemented(string Command) + { + if (throwErrorOnNotImplemented) + throw new NotImplementedException("Command not implemented: " + Command); + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/c_sharp_example.txt b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/c_sharp_example.txt new file mode 100644 index 0000000000..a39d1dbbc0 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Compiler/c_sharp_example.txt @@ -0,0 +1,12 @@ +//c# +namespace SecondLife { + public class Script : OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass +{ + public Script() { } + + public void default_event_state_entry( ) + { + llSay(0, "testing, I've been touched"); + } + +}} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/EventManager.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/EventManager.cs new file mode 100644 index 0000000000..3aa2216a90 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/EventManager.cs @@ -0,0 +1,222 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using libsecondlife; +using OpenSim.Framework; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine +{ + /// + /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it. + /// + [Serializable] + internal class EventManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private ScriptEngine myScriptEngine; + //public IScriptHost TEMP_OBJECT_ID; + public EventManager(ScriptEngine _ScriptEngine) + { + myScriptEngine = _ScriptEngine; + // TODO: HOOK EVENTS UP TO SERVER! + //myScriptEngine.m_log.Info("[ScriptEngine]: EventManager Start"); + // TODO: ADD SERVER HOOK TO LOAD A SCRIPT THROUGH myScriptEngine.ScriptManager + + // Hook up a test event to our test form + myScriptEngine.m_log.Info("[ScriptEngine]: Hooking up to server events"); + myScriptEngine.World.EventManager.OnObjectGrab += touch_start; + myScriptEngine.World.EventManager.OnRezScript += OnRezScript; + myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript; + } + + public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient) + { + // Add to queue for all scripts in ObjectID object + //myScriptEngine.m_log.Info("[ScriptEngine]: EventManager Event: touch_start"); + //Console.WriteLine("touch_start localID: " + localID); + myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "touch_start", new object[] {(int) 1}); + } + + public void OnRezScript(uint localID, LLUUID itemID, string script) + { + //myScriptEngine.myScriptManager.StartScript( + // Path.Combine("ScriptEngines", "Default.lsl"), + // new OpenSim.Region.Environment.Scenes.Scripting.NullScriptHost() + //); + Console.WriteLine("OnRezScript localID: " + localID + " LLUID: " + itemID.ToString() + " Size: " + + script.Length); + myScriptEngine.m_ScriptManager.StartScript(localID, itemID, script); + } + + public void OnRemoveScript(uint localID, LLUUID itemID) + { + //myScriptEngine.myScriptManager.StartScript( + // Path.Combine("ScriptEngines", "Default.lsl"), + // new OpenSim.Region.Environment.Scenes.Scripting.NullScriptHost() + //); + Console.WriteLine("OnRemoveScript localID: " + localID + " LLUID: " + itemID.ToString()); + myScriptEngine.m_ScriptManager.StopScript( + localID, + itemID + ); + } + + // TODO: Replace placeholders below + // These needs to be hooked up to OpenSim during init of this class + // then queued in EventQueueManager. + // When queued in EventQueueManager they need to be LSL compatible (name and params) + + //public void state_entry() { } // + public void state_exit() + { + } + + //public void touch_start() { } + public void touch() + { + } + + public void touch_end() + { + } + + public void collision_start() + { + } + + public void collision() + { + } + + public void collision_end() + { + } + + public void land_collision_start() + { + } + + public void land_collision() + { + } + + public void land_collision_end() + { + } + + public void timer() + { + } + + public void listen() + { + } + + public void on_rez() + { + } + + public void sensor() + { + } + + public void no_sensor() + { + } + + public void control() + { + } + + public void money() + { + } + + public void email() + { + } + + public void at_target() + { + } + + public void not_at_target() + { + } + + public void at_rot_target() + { + } + + public void not_at_rot_target() + { + } + + public void run_time_permissions() + { + } + + public void changed() + { + } + + public void attach() + { + } + + public void dataserver() + { + } + + public void link_message() + { + } + + public void moving_start() + { + } + + public void moving_end() + { + } + + public void object_rez() + { + } + + public void remote_data() + { + } + + public void http_response() + { + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/EventQueueManager.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/EventQueueManager.cs new file mode 100644 index 0000000000..260686213c --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/EventQueueManager.cs @@ -0,0 +1,336 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSL; +using OpenSim.Region.Environment.Scenes.Scripting; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine +{ + /// + /// EventQueueManager handles event queues + /// Events are queued and executed in separate thread + /// + [Serializable] + internal class EventQueueManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// List of threads processing event queue + /// + private List eventQueueThreads = new List(); + + private object queueLock = new object(); // Mutex lock object + + /// + /// How many ms to sleep if queue is empty + /// + private int nothingToDoSleepms = 50; + + /// + /// How many threads to process queue with + /// + private int numberOfThreads = 2; + + /// + /// Queue containing events waiting to be executed + /// + private Queue eventQueue = new Queue(); + + /// + /// Queue item structure + /// + private struct QueueItemStruct + { + public uint localID; + public LLUUID itemID; + public string functionName; + public object[] param; + } + + /// + /// List of localID locks for mutex processing of script events + /// + private List objectLocks = new List(); + + private object tryLockLock = new object(); // Mutex lock object + + private ScriptEngine m_ScriptEngine; + + public EventQueueManager(ScriptEngine _ScriptEngine) + { + m_ScriptEngine = _ScriptEngine; + + // + // Start event queue processing threads (worker threads) + // + for (int ThreadCount = 0; ThreadCount <= numberOfThreads; ThreadCount++) + { + Thread EventQueueThread = new Thread(EventQueueThreadLoop); + eventQueueThreads.Add(EventQueueThread); + EventQueueThread.IsBackground = true; + EventQueueThread.Priority = ThreadPriority.BelowNormal; + EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount; + EventQueueThread.Start(); + } + } + + ~EventQueueManager() + { + // Kill worker threads + foreach (Thread EventQueueThread in new ArrayList(eventQueueThreads)) + { + if (EventQueueThread != null && EventQueueThread.IsAlive == true) + { + try + { + EventQueueThread.Abort(); + EventQueueThread.Join(); + } + catch (Exception) + { + //myScriptEngine.m_log.Info("[ScriptEngine]: EventQueueManager Exception killing worker thread: " + e.ToString()); + } + } + } + eventQueueThreads.Clear(); + // Todo: Clean up our queues + eventQueue.Clear(); + } + + /// + /// Queue processing thread loop + /// + private void EventQueueThreadLoop() + { + //myScriptEngine.m_log.Info("[ScriptEngine]: EventQueueManager Worker thread spawned"); + try + { + QueueItemStruct BlankQIS = new QueueItemStruct(); + while (true) + { + try + { + QueueItemStruct QIS = BlankQIS; + bool GotItem = false; + + if (eventQueue.Count == 0) + { + // Nothing to do? Sleep a bit waiting for something to do + Thread.Sleep(nothingToDoSleepms); + } + else + { + // Something in queue, process + //myScriptEngine.m_log.Info("[ScriptEngine]: Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName); + + // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD + lock (queueLock) + { + GotItem = false; + for (int qc = 0; qc < eventQueue.Count; qc++) + { + // Get queue item + QIS = eventQueue.Dequeue(); + + // Check if object is being processed by someone else + if (TryLock(QIS.localID) == false) + { + // Object is already being processed, requeue it + eventQueue.Enqueue(QIS); + } + else + { + // We have lock on an object and can process it + GotItem = true; + break; + } + } // go through queue + } // lock + + if (GotItem == true) + { + // Execute function + try + { + m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, QIS.itemID, + QIS.functionName, QIS.param); + } + catch (Exception e) + { + // DISPLAY ERROR INWORLD + string text = "Error executing script function \"" + QIS.functionName + "\":\r\n"; + if (e.InnerException != null) + { + // Send inner exception + text += e.InnerException.Message.ToString(); + } + else + { + // Send normal + text += e.Message.ToString(); + } + try + { + if (text.Length > 1500) + text = text.Substring(0, 1500); + IScriptHost m_host = m_ScriptEngine.World.GetSceneObjectPart(QIS.localID); + //if (m_host != null) + //{ + m_ScriptEngine.World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0, + m_host.AbsolutePosition, m_host.Name, m_host.UUID); + } + catch + { + //} + //else + //{ + // T oconsole + Console.WriteLine("Unable to send text in-world:\r\n" + text); + } + } + finally + { + ReleaseLock(QIS.localID); + } + } + } // Something in queue + } + catch (ThreadAbortException tae) + { + throw tae; + } + catch (Exception e) + { + Console.WriteLine("Exception in EventQueueThreadLoop: " + e.ToString()); + } + } // while + } // try + catch (ThreadAbortException) + { + //myScriptEngine.m_log.Info("[ScriptEngine]: EventQueueManager Worker thread killed: " + tae.Message); + } + } + + /// + /// Try to get a mutex lock on localID + /// + /// + /// + private bool TryLock(uint localID) + { + lock (tryLockLock) + { + if (objectLocks.Contains(localID) == true) + { + return false; + } + else + { + objectLocks.Add(localID); + return true; + } + } + } + + /// + /// Release mutex lock on localID + /// + /// + private void ReleaseLock(uint localID) + { + lock (tryLockLock) + { + if (objectLocks.Contains(localID) == true) + { + objectLocks.Remove(localID); + } + } + } + + + /// + /// Add event to event execution queue + /// + /// + /// Name of the function, will be state + "_event_" + FunctionName + /// Array of parameters to match event mask + public void AddToObjectQueue(uint localID, string FunctionName, object[] param) + { + // Determine all scripts in Object and add to their queue + //myScriptEngine.m_log.Info("[ScriptEngine]: EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName); + + + // Do we have any scripts in this object at all? If not, return + if (m_ScriptEngine.m_ScriptManager.Scripts.ContainsKey(localID) == false) + { + //Console.WriteLine("Event \"" + FunctionName + "\" for localID: " + localID + ". No scripts found on this localID."); + return; + } + + Dictionary.KeyCollection scriptKeys = + m_ScriptEngine.m_ScriptManager.GetScriptKeys(localID); + + foreach (LLUUID itemID in scriptKeys) + { + // Add to each script in that object + // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter? + AddToScriptQueue(localID, itemID, FunctionName, param); + } + } + + /// + /// Add event to event execution queue + /// + /// + /// + /// Name of the function, will be state + "_event_" + FunctionName + /// Array of parameters to match event mask + public void AddToScriptQueue(uint localID, LLUUID itemID, string FunctionName, object[] param) + { + lock (queueLock) + { + // Create a structure and add data + QueueItemStruct QIS = new QueueItemStruct(); + QIS.localID = localID; + QIS.itemID = itemID; + QIS.functionName = FunctionName; + QIS.param = param; + + // Add it to queue + eventQueue.Enqueue(QIS); + } + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs new file mode 100644 index 0000000000..303bddbbea --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs @@ -0,0 +1,355 @@ +/* +* 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; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Modules; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine +{ + /// + /// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc. + /// + internal class LSLLongCmdHandler + { + private Thread cmdHandlerThread; + private int cmdHandlerThreadCycleSleepms = 100; + + private ScriptEngine m_ScriptEngine; + + public LSLLongCmdHandler(ScriptEngine _ScriptEngine) + { + m_ScriptEngine = _ScriptEngine; + + // Start the thread that will be doing the work + cmdHandlerThread = new Thread(CmdHandlerThreadLoop); + cmdHandlerThread.Name = "CmdHandlerThread"; + cmdHandlerThread.Priority = ThreadPriority.BelowNormal; + cmdHandlerThread.IsBackground = true; + cmdHandlerThread.Start(); + } + + ~LSLLongCmdHandler() + { + // Shut down thread + try + { + if (cmdHandlerThread != null) + { + if (cmdHandlerThread.IsAlive == true) + { + cmdHandlerThread.Abort(); + cmdHandlerThread.Join(); + } + } + } + catch + { + } + } + + private void CmdHandlerThreadLoop() + { + while (true) + { + // Check timers + CheckTimerEvents(); + Thread.Sleep(25); + // Check HttpRequests + CheckHttpRequests(); + Thread.Sleep(25); + // Check XMLRPCRequests + CheckXMLRPCRequests(); + Thread.Sleep(25); + // Check Listeners + CheckListeners(); + Thread.Sleep(25); + + // Sleep before next cycle + //Thread.Sleep(cmdHandlerThreadCycleSleepms); + } + } + + /// + /// Remove a specific script (and all its pending commands) + /// + /// + /// + public void RemoveScript(uint localID, LLUUID itemID) + { + // Remove a specific script + + // Remove from: Timers + UnSetTimerEvents(localID, itemID); + // Remove from: HttpRequest + StopHttpRequest(localID, itemID); + } + + #region TIMER + + // + // TIMER + // + private class TimerClass + { + public uint localID; + public LLUUID itemID; + public double interval; + public DateTime next; + } + + private List Timers = new List(); + private object TimerListLock = new object(); + + public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec) + { + Console.WriteLine("SetTimerEvent"); + + // Always remove first, in case this is a re-set + UnSetTimerEvents(m_localID, m_itemID); + if (sec == 0) // Disabling timer + return; + + // Add to timer + TimerClass ts = new TimerClass(); + ts.localID = m_localID; + ts.itemID = m_itemID; + ts.interval = sec; + ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + lock (TimerListLock) + { + Timers.Add(ts); + } + } + + public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID) + { + // Remove from timer + lock (TimerListLock) + { + List NewTimers = new List(); + foreach (TimerClass ts in Timers) + { + if (ts.localID != m_localID && ts.itemID != m_itemID) + { + NewTimers.Add(ts); + } + } + Timers.Clear(); + Timers = NewTimers; + } + } + + public void CheckTimerEvents() + { + // Nothing to do here? + if (Timers.Count == 0) + return; + + lock (TimerListLock) + { + // Go through all timers + foreach (TimerClass ts in Timers) + { + // Time has passed? + if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) + { + // Add it to queue + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer", + new object[] {}); + // set next interval + + + ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + } + } + } // lock + } + + #endregion + + #region HTTP REQUEST + + // + // HTTP REAQUEST + // + private class HttpClass + { + public uint localID; + public LLUUID itemID; + public string url; + public List parameters; + public string body; + public DateTime next; + + public string response_request_id; + public int response_status; + public List response_metadata; + public string response_body; + + public void SendRequest() + { + // TODO: SEND REQUEST!!! + } + + public void Stop() + { + // TODO: Cancel any ongoing request + } + + public bool CheckResponse() + { + // TODO: Check if we got a response yet, return true if so -- false if not + return true; + + // TODO: If we got a response, set the following then return true + //response_request_id + //response_status + //response_metadata + //response_body + } + } + + private List HttpRequests = new List(); + private object HttpListLock = new object(); + + public void StartHttpRequest(uint localID, LLUUID itemID, string url, List parameters, string body) + { + Console.WriteLine("StartHttpRequest"); + + HttpClass htc = new HttpClass(); + htc.localID = localID; + htc.itemID = itemID; + htc.url = url; + htc.parameters = parameters; + htc.body = body; + lock (HttpListLock) + { + //ADD REQUEST + HttpRequests.Add(htc); + } + } + + public void StopHttpRequest(uint m_localID, LLUUID m_itemID) + { + // Remove from list + lock (HttpListLock) + { + List NewHttpList = new List(); + foreach (HttpClass ts in HttpRequests) + { + if (ts.localID != m_localID && ts.itemID != m_itemID) + { + // Keeping this one + NewHttpList.Add(ts); + } + else + { + // Shutting this one down + ts.Stop(); + } + } + HttpRequests.Clear(); + HttpRequests = NewHttpList; + } + } + + public void CheckHttpRequests() + { + // Nothing to do here? + if (HttpRequests.Count == 0) + return; + + lock (HttpListLock) + { + foreach (HttpClass ts in HttpRequests) + { + if (ts.CheckResponse() == true) + { + // Add it to event queue + //key request_id, integer status, list metadata, string body + object[] resobj = + new object[] + {ts.response_request_id, ts.response_status, ts.response_metadata, ts.response_body}; + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "http_response", + resobj); + // Now stop it + StopHttpRequest(ts.localID, ts.itemID); + } + } + } // lock + } + + #endregion + + public void CheckXMLRPCRequests() + { + IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface(); + + while (xmlrpc.hasRequests()) + { + RPCRequestInfo rInfo = xmlrpc.GetNextRequest(); + Console.WriteLine("PICKED REQUEST"); + + //Deliver data to prim's remote_data handler + object[] resobj = new object[] + { + 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), "", rInfo.GetIntValue(), + rInfo.GetStrVal() + }; + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", resobj + ); + } + } + + public void CheckListeners() + { + IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface(); + + while (comms.HasMessages()) + { + ListenerInfo lInfo = comms.GetNextMessage(); + Console.WriteLine("PICKED LISTENER"); + + //Deliver data to prim's listen handler + object[] resobj = new object[] + { + lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage() + }; + + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + lInfo.GetLocalID(), lInfo.GetItemID(), "listen", resobj + ); + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..e53e9e525b --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* 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.Grid.ScriptEngine.DotNetEngine")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Grid.ScriptEngine.DotNetEngine")] +[assembly : AssemblyCopyright("Copyright © 2007")] +[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("2842257e-6fde-4460-9368-4cde57fa9cc4")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/ScriptEngine.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/ScriptEngine.cs new file mode 100644 index 0000000000..a45efe9ff8 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/ScriptEngine.cs @@ -0,0 +1,119 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine +{ + /// + /// This is the root object for ScriptEngine + /// + [Serializable] + public class ScriptEngine : IRegionModule + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + internal Scene World; + internal EventManager m_EventManager; // Handles and queues incoming events from OpenSim + internal EventQueueManager m_EventQueueManager; // Executes events + internal ScriptManager m_ScriptManager; // Load, unload and execute scripts + internal AppDomainManager m_AppDomainManager; + internal LSLLongCmdHandler m_LSLLongCmdHandler; + + + public ScriptEngine() + { + //Common.SendToDebug("ScriptEngine Object Initialized"); + Common.mySE = this; + } + + public void InitializeEngine(Scene Sceneworld) + { + World = Sceneworld; + + m_log.Info("[ScriptEngine]: DotNet & LSL ScriptEngine initializing"); + + //m_log.Info("[ScriptEngine]: InitializeEngine"); + + // Create all objects we'll be using + m_EventQueueManager = new EventQueueManager(this); + m_EventManager = new EventManager(this); + m_ScriptManager = new ScriptManager(this); + m_AppDomainManager = new AppDomainManager(); + m_LSLLongCmdHandler = new LSLLongCmdHandler(this); + + // Should we iterate the region for scripts that needs starting? + // Or can we assume we are loaded before anything else so we can use proper events? + } + + public void Shutdown() + { + // We are shutting down + } + + //// !!!FOR DEBUGGING ONLY!!! (for executing script directly from test app) + //[Obsolete("!!!FOR DEBUGGING ONLY!!!")] + //public void StartScript(string ScriptID, IScriptHost ObjectID) + //{ + // this.myEventManager.TEMP_OBJECT_ID = ObjectID; + // m_log.Info("[ScriptEngine]: DEBUG FUNCTION: StartScript: " + ScriptID); + // myScriptManager.StartScript(ScriptID, ObjectID); + //} + + #region IRegionModule + + public void Initialise(Scene scene, IConfigSource config) + { + InitializeEngine(scene); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "LSLScriptingModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/ScriptManager.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/ScriptManager.cs new file mode 100644 index 0000000000..28463990ee --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/ScriptManager.cs @@ -0,0 +1,421 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.Serialization.Formatters.Binary; +using System.Threading; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler; +using OpenSim.Grid.ScriptEngine.DotNetEngine.Compiler.LSL; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine +{ + /// + /// Loads scripts + /// Compiles them if necessary + /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution) + /// + [Serializable] + public class ScriptManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #region Declares + + private Thread scriptLoadUnloadThread; + private int scriptLoadUnloadThread_IdleSleepms = 100; + private Queue loadQueue = new Queue(); + private Queue unloadQueue = new Queue(); + + private struct LoadStruct + { + public uint localID; + public LLUUID itemID; + public string script; + } + + private struct UnloadStruct + { + public uint localID; + public LLUUID itemID; + } + + // Object> + // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. + // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! + internal Dictionary> Scripts = + new Dictionary>(); + + public Scene World + { + get { return m_scriptEngine.World; } + } + + #endregion + + #region Object init/shutdown + + private ScriptEngine m_scriptEngine; + + public ScriptManager(ScriptEngine scriptEngine) + { + m_scriptEngine = scriptEngine; + AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); + scriptLoadUnloadThread = new Thread(ScriptLoadUnloadThreadLoop); + scriptLoadUnloadThread.Name = "ScriptLoadUnloadThread"; + scriptLoadUnloadThread.IsBackground = true; + scriptLoadUnloadThread.Priority = ThreadPriority.BelowNormal; + scriptLoadUnloadThread.Start(); + } + + ~ScriptManager() + { + // Abort load/unload thread + try + { + if (scriptLoadUnloadThread != null) + { + if (scriptLoadUnloadThread.IsAlive == true) + { + scriptLoadUnloadThread.Abort(); + scriptLoadUnloadThread.Join(); + } + } + } + catch + { + } + } + + #endregion + + #region Load / Unload scripts (Thread loop) + + private void ScriptLoadUnloadThreadLoop() + { + try + { + while (true) + { + if (loadQueue.Count == 0 && unloadQueue.Count == 0) + Thread.Sleep(scriptLoadUnloadThread_IdleSleepms); + + if (loadQueue.Count > 0) + { + LoadStruct item = loadQueue.Dequeue(); + _StartScript(item.localID, item.itemID, item.script); + } + + if (unloadQueue.Count > 0) + { + UnloadStruct item = unloadQueue.Dequeue(); + _StopScript(item.localID, item.itemID); + } + } + } + catch (ThreadAbortException tae) + { + string a = tae.ToString(); + a = ""; + // Expected + } + } + + #endregion + + #region Helper functions + + private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) + { + //Console.WriteLine("ScriptManager.CurrentDomain_AssemblyResolve: " + args.Name); + return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null; + } + + #endregion + + #region Internal functions to keep track of script + + internal Dictionary.KeyCollection GetScriptKeys(uint localID) + { + if (Scripts.ContainsKey(localID) == false) + return null; + + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + + return Obj.Keys; + } + + internal LSL_BaseClass GetScript(uint localID, LLUUID itemID) + { + if (Scripts.ContainsKey(localID) == false) + return null; + + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == false) + return null; + + // Get script + LSL_BaseClass Script; + Obj.TryGetValue(itemID, out Script); + + return Script; + } + + internal void SetScript(uint localID, LLUUID itemID, LSL_BaseClass Script) + { + // Create object if it doesn't exist + if (Scripts.ContainsKey(localID) == false) + { + Scripts.Add(localID, new Dictionary()); + } + + // Delete script if it exists + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == true) + Obj.Remove(itemID); + + // Add to object + Obj.Add(itemID, Script); + } + + internal void RemoveScript(uint localID, LLUUID itemID) + { + // Don't have that object? + if (Scripts.ContainsKey(localID) == false) + return; + + // Delete script if it exists + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == true) + Obj.Remove(itemID); + } + + #endregion + + #region Start/Stop/Reset script + + /// + /// Fetches, loads and hooks up a script to an objects events + /// + /// + /// + public void StartScript(uint localID, LLUUID itemID, string Script) + { + LoadStruct ls = new LoadStruct(); + ls.localID = localID; + ls.itemID = itemID; + ls.script = Script; + loadQueue.Enqueue(ls); + } + + /// + /// Disables and unloads a script + /// + /// + /// + public void StopScript(uint localID, LLUUID itemID) + { + UnloadStruct ls = new UnloadStruct(); + ls.localID = localID; + ls.itemID = itemID; + unloadQueue.Enqueue(ls); + } + + public void ResetScript(uint localID, LLUUID itemID) + { + string script = GetScript(localID, itemID).SourceCode; + StopScript(localID, itemID); + StartScript(localID, itemID, script); + } + + private void _StartScript(uint localID, LLUUID itemID, string Script) + { + //IScriptHost root = host.GetRoot(); + Console.WriteLine("ScriptManager StartScript: localID: " + localID + ", itemID: " + itemID); + + // We will initialize and start the script. + // It will be up to the script itself to hook up the correct events. + string ScriptSource = ""; + + SceneObjectPart m_host = World.GetSceneObjectPart(localID); + + try + { + // Create a new instance of the compiler (currently we don't want reuse) + Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler(); + // Compile (We assume LSL) + ScriptSource = LSLCompiler.CompileFromLSLText(Script); + //Console.WriteLine("Compilation of " + FileName + " done"); + // * Insert yield into code + ScriptSource = ProcessYield(ScriptSource); + + +#if DEBUG + long before; + before = GC.GetTotalMemory(true); +#endif + + LSL_BaseClass CompiledScript; + CompiledScript = m_scriptEngine.m_AppDomainManager.LoadScript(ScriptSource); + +#if DEBUG + Console.WriteLine("Script " + itemID + " occupies {0} bytes", GC.GetTotalMemory(true) - before); +#endif + + CompiledScript.SourceCode = ScriptSource; + // Add it to our script memstruct + SetScript(localID, itemID, CompiledScript); + + // We need to give (untrusted) assembly a private instance of BuiltIns + // this private copy will contain Read-Only FullitemID so that it can bring that on to the server whenever needed. + + + LSL_BuiltIn_Commands LSLB = new LSL_BuiltIn_Commands(m_scriptEngine, m_host, localID, itemID); + + // Start the script - giving it BuiltIns + CompiledScript.Start(LSLB); + + // Fire the first start-event + m_scriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_entry", new object[] {}); + } + catch (Exception e) + { + //m_scriptEngine.m_log.Error("[ScriptEngine]: Error compiling script: " + e.ToString()); + try + { + // DISPLAY ERROR INWORLD + string text = "Error compiling script:\r\n" + e.Message.ToString(); + if (text.Length > 1500) + text = text.Substring(0, 1500); + World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID); + } + catch (Exception e2) + { + m_scriptEngine.m_log.Error("[ScriptEngine]: Error displaying error in-world: " + e2.ToString()); + } + } + } + + private void _StopScript(uint localID, LLUUID itemID) + { + // Stop script + Console.WriteLine("Stop script localID: " + localID + " LLUID: " + itemID.ToString()); + + + // Stop long command on script + m_scriptEngine.m_LSLLongCmdHandler.RemoveScript(localID, itemID); + + LSL_BaseClass LSLBC = GetScript(localID, itemID); + if (LSLBC == null) + return; + + // TEMP: First serialize it + //GetSerializedScript(localID, itemID); + + + try + { + // Get AppDomain + AppDomain ad = LSLBC.Exec.GetAppDomain(); + // Tell script not to accept new requests + GetScript(localID, itemID).Exec.StopScript(); + // Remove from internal structure + RemoveScript(localID, itemID); + // Tell AppDomain that we have stopped script + m_scriptEngine.m_AppDomainManager.StopScript(ad); + } + catch (Exception e) + { + Console.WriteLine("Exception stopping script localID: " + localID + " LLUID: " + itemID.ToString() + + ": " + e.ToString()); + } + } + + private string ProcessYield(string FileName) + { + // TODO: Create a new assembly and copy old but insert Yield Code + //return TempDotNetMicroThreadingCodeInjector.TestFix(FileName); + return FileName; + } + + #endregion + + #region Perform event execution in script + + /// + /// Execute a LL-event-function in Script + /// + /// Object the script is located in + /// Script ID + /// Name of function + /// Arguments to pass to function + internal void ExecuteEvent(uint localID, LLUUID itemID, string FunctionName, object[] args) + { + // Execute a function in the script + //m_scriptEngine.m_log.Info("[ScriptEngine]: Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName); + LSL_BaseClass Script = m_scriptEngine.m_ScriptManager.GetScript(localID, itemID); + if (Script == null) + return; + + // Must be done in correct AppDomain, so leaving it up to the script itself + Script.Exec.ExecuteEvent(FunctionName, args); + } + + #endregion + + #region Script serialization/deserialization + + public void GetSerializedScript(uint localID, LLUUID itemID) + { + // Serialize the script and return it + // Should not be a problem + FileStream fs = File.Create("SERIALIZED_SCRIPT_" + itemID); + BinaryFormatter b = new BinaryFormatter(); + b.Serialize(fs, GetScript(localID, itemID)); + fs.Close(); + } + + public void PutSerializedScript(uint localID, LLUUID itemID) + { + // Deserialize the script and inject it into an AppDomain + + // How to inject into an AppDomain? + } + + #endregion + } +} diff --git a/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/TempDotNetMicroThreadingCodeInjector.cs b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/TempDotNetMicroThreadingCodeInjector.cs new file mode 100644 index 0000000000..8a8c96d5ea --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptEngine/DotNetEngine/TempDotNetMicroThreadingCodeInjector.cs @@ -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 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; +using System.IO; +using Rail.Reflect; +using Rail.Transformation; + +namespace OpenSim.Grid.ScriptEngine.DotNetEngine +{ + /// + /// Tedds Sandbox for RAIL/microtrheading. This class is only for testing purposes! + /// Its offspring will be the actual implementation. + /// + internal class TempDotNetMicroThreadingCodeInjector + { + public static string TestFix(string FileName) + { + string ret = Path.GetFileNameWithoutExtension(FileName + "_fixed.dll"); + + Console.WriteLine("Loading: \"" + FileName + "\""); + RAssemblyDef rAssembly = RAssemblyDef.LoadAssembly(FileName); + + + //Get the type of the method to copy from assembly Teste2.exe to assembly Teste.exe + RTypeDef type = (RTypeDef) rAssembly.RModuleDef.GetType("SecondLife.Script"); + + //Get the methods in the type + RMethod[] m = type.GetMethods(); + + //Create a MethodPrologueAdder visitor object with the method to add + //and with the flag that enables local variable creation set to true + MethodPrologueAdder mpa = new MethodPrologueAdder((RMethodDef) m[0], true); + + //Apply the changes to the assembly + rAssembly.Accept(mpa); + + //Save the new assembly + rAssembly.SaveAssembly(ret); + + return ret; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptServer/Application.cs b/trunk/OpenSim/Grid/ScriptServer/Application.cs new file mode 100644 index 0000000000..26bd42617d --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptServer/Application.cs @@ -0,0 +1,60 @@ +/* +* 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; + +namespace OpenSim.Grid.ScriptServer +{ + internal class OpenScript_Main + { + public static ScriptServerMain SE; + + private static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + AppDomain.CurrentDomain.UnhandledException += + new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); + + // Application is starting + SE = new ScriptServerMain(); + + } + + private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + Console.WriteLine(String.Empty); + Console.WriteLine("APPLICATION EXCEPTION DETECTED"); + Console.WriteLine(String.Empty); + Console.WriteLine("Application is terminating: " + e.IsTerminating.ToString()); + //Console.WriteLine("Exception:"); + //Console.WriteLine(e.ExceptionObject.ToString()); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptServer/FakeScene.cs b/trunk/OpenSim/Grid/ScriptServer/FakeScene.cs new file mode 100644 index 0000000000..2064c56835 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptServer/FakeScene.cs @@ -0,0 +1,55 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Servers; +using OpenSim.Region.Environment; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Grid.ScriptServer +{ + public class FakeScene: Scene + { + public FakeScene(RegionInfo regInfo, AgentCircuitManager authen, PermissionManager permissionManager, + CommunicationsManager commsMan, SceneCommunicationService sceneGridService, + AssetCache assetCach, StorageManager storeManager, BaseHttpServer httpServer, + ModuleLoader moduleLoader, bool dumpAssetsToFile, bool physicalPrim, bool sendTasksToChild) + : base( + regInfo, authen, permissionManager, commsMan, sceneGridService, assetCach, storeManager, httpServer, + moduleLoader, dumpAssetsToFile, physicalPrim, sendTasksToChild) + { + } + + // What does a scene have to do? :P + } +} diff --git a/trunk/OpenSim/Grid/ScriptServer/Properties/AssemblyInfo.cs b/trunk/OpenSim/Grid/ScriptServer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..539d55a665 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptServer/Properties/AssemblyInfo.cs @@ -0,0 +1,64 @@ +/* +* 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.Grid.ScriptServer")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Grid.ScriptServer")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("b6861b87-5203-4040-b756-fd4774932f82")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptServer/RemotingObject.cs b/trunk/OpenSim/Grid/ScriptServer/RemotingObject.cs new file mode 100644 index 0000000000..1bca6d1807 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptServer/RemotingObject.cs @@ -0,0 +1,47 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Grid.ScriptServer +{ + public class RemotingObject : MarshalByRefObject, ScriptServerInterfaces.ServerRemotingObject + { + // This object will be exposed over remoting. It is a singleton, so it exists only in as one instance. + + + ScriptServerInterfaces.RemoteEvents ScriptServerInterfaces.ServerRemotingObject.Events() + { + return ScriptServerMain.Engine.EventManager(); + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptServer/RemotingServer.cs b/trunk/OpenSim/Grid/ScriptServer/RemotingServer.cs new file mode 100644 index 0000000000..bb5847a79d --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptServer/RemotingServer.cs @@ -0,0 +1,57 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; +using System.Runtime.Remoting.Channels.Tcp; +using OpenSim.Region.ScriptEngine.Common; + + +namespace OpenSim.Grid.ScriptServer +{ + class RemotingServer + { + TcpChannel channel; + public RemotingServer(int port, string instanceName) + { + // Create an instance of a channel + channel = new TcpChannel(port); + ChannelServices.RegisterChannel(channel, true); + + // Register as an available service with the name HelloWorld + RemotingConfiguration.RegisterWellKnownServiceType( + typeof(RemotingObject), + instanceName, + WellKnownObjectMode.Singleton); + + } + } +} diff --git a/trunk/OpenSim/Grid/ScriptServer/ScriptServer/Region/RegionBase.cs b/trunk/OpenSim/Grid/ScriptServer/ScriptServer/Region/RegionBase.cs new file mode 100644 index 0000000000..cb6734f57c --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptServer/ScriptServer/Region/RegionBase.cs @@ -0,0 +1,244 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Grid.ScriptServer +{ + public abstract class RegionBase + { + // These are events that the region needs to have + + // TEMP: Using System.Delegate -- needs replacing with a real delegate + public delegate void DefaultDelegate(); + + public event DefaultDelegate onScriptRez; + public event DefaultDelegate onstate_entry; + public event DefaultDelegate onstate_exit; + public event DefaultDelegate ontouch_start; + public event DefaultDelegate ontouch; + public event DefaultDelegate ontouch_end; + public event DefaultDelegate oncollision_start; + public event DefaultDelegate oncollision; + public event DefaultDelegate oncollision_end; + public event DefaultDelegate onland_collision_start; + public event DefaultDelegate onland_collision; + public event DefaultDelegate onland_collision_end; + public event DefaultDelegate ontimer; + public event DefaultDelegate onlisten; + public event DefaultDelegate onon_rez; + public event DefaultDelegate onsensor; + public event DefaultDelegate onno_sensor; + public event DefaultDelegate oncontrol; + public event DefaultDelegate onmoney; + public event DefaultDelegate onemail; + public event DefaultDelegate onat_target; + public event DefaultDelegate onnot_at_target; + public event DefaultDelegate onat_rot_target; + public event DefaultDelegate onnot_at_rot_target; + public event DefaultDelegate onrun_time_permissions; + public event DefaultDelegate onchanged; + public event DefaultDelegate onattach; + public event DefaultDelegate ondataserver; + public event DefaultDelegate onlink_message; + public event DefaultDelegate onmoving_start; + public event DefaultDelegate onmoving_end; + public event DefaultDelegate onobject_rez; + public event DefaultDelegate onremote_data; + public event DefaultDelegate onhttp_response; + + + public void ScriptRez() + { + onScriptRez(); + } + + public void state_entry() + { + onstate_entry(); + } + + public void state_exit() + { + onstate_exit(); + } + + public void touch_start() + { + ontouch_start(); + } + + public void touch() + { + ontouch(); + } + + public void touch_end() + { + ontouch_end(); + } + + public void collision_start() + { + oncollision_start(); + } + + public void collision() + { + oncollision(); + } + + public void collision_end() + { + oncollision_end(); + } + + public void land_collision_start() + { + onland_collision_start(); + } + + public void land_collision() + { + onland_collision(); + } + + public void land_collision_end() + { + onland_collision_end(); + } + + public void timer() + { + ontimer(); + } + + public void listen() + { + onlisten(); + } + + public void on_rez() + { + onon_rez(); + } + + public void sensor() + { + onsensor(); + } + + public void no_sensor() + { + onno_sensor(); + } + + public void control() + { + oncontrol(); + } + + public void money() + { + onmoney(); + } + + public void email() + { + onemail(); + } + + public void at_target() + { + onat_target(); + } + + public void not_at_target() + { + onnot_at_target(); + } + + public void at_rot_target() + { + onat_rot_target(); + } + + public void not_at_rot_target() + { + onnot_at_rot_target(); + } + + public void run_time_permissions() + { + onrun_time_permissions(); + } + + public void changed() + { + onchanged(); + } + + public void attach() + { + onattach(); + } + + public void dataserver() + { + ondataserver(); + } + + public void link_message() + { + onlink_message(); + } + + public void moving_start() + { + onmoving_start(); + } + + public void moving_end() + { + onmoving_end(); + } + + public void object_rez() + { + onobject_rez(); + } + + public void remote_data() + { + onremote_data(); + } + + public void http_response() + { + onhttp_response(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptServer/ScriptServer/Region/RegionConnectionManager.cs b/trunk/OpenSim/Grid/ScriptServer/ScriptServer/Region/RegionConnectionManager.cs new file mode 100644 index 0000000000..595acea47b --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptServer/ScriptServer/Region/RegionConnectionManager.cs @@ -0,0 +1,57 @@ +/* +* 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 OpenSim.Framework.Console; + +namespace OpenSim.Grid.ScriptServer +{ + // Maintains connection and communication to a region + public class RegionConnectionManager : RegionBase + { + private ScriptServerMain m_ScriptServerMain; + private object m_Connection; + + public RegionConnectionManager(ScriptServerMain scm, object Connection) + { + m_ScriptServerMain = scm; + m_Connection = Connection; + } + + private void DataReceived(object objectID, object scriptID) + { + // TODO: HOW DO WE RECEIVE DATA? ASYNC? + // ANYHOW WE END UP HERE? + + // NEW SCRIPT? ASK SCRIPTENGINE TO INITIALIZE IT + ScriptRez(); + + // EVENT? DELIVER EVENT DIRECTLY TO SCRIPTENGINE + touch_start(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptServer/ScriptServer/RegionCommManager.cs b/trunk/OpenSim/Grid/ScriptServer/ScriptServer/RegionCommManager.cs new file mode 100644 index 0000000000..524b8c4852 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptServer/ScriptServer/RegionCommManager.cs @@ -0,0 +1,101 @@ +/* +* 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.Collections.Generic; +using System.Threading; +using OpenSim.Framework.Console; + +namespace OpenSim.Grid.ScriptServer +{ + // Waiting for incoming script requests from region + internal class RegionCommManager + { + private Thread listenThread; + + private List Regions = new List(); + + private ScriptServerMain m_ScriptServerMain; + + public RegionCommManager(ScriptServerMain scm) + { + m_ScriptServerMain = scm; + } + + ~RegionCommManager() + { + Stop(); + } + + /// + /// Starts listening for region requests + /// + public void Start() + { + // Start listener + Stop(); + listenThread = new Thread(ListenThreadLoop); + listenThread.Name = "listenThread"; + listenThread.IsBackground = true; + listenThread.Start(); + } + + /// + /// Stops listening for region requests + /// + public void Stop() + { + // Stop listener, clean up + if (listenThread != null) + { + try + { + if (listenThread.IsAlive) + listenThread.Abort(); + listenThread.Join(1000); // Wait 1 second for thread to shut down + } + catch + { + } + listenThread = null; + } + } + + private void ListenThreadLoop() + { + // * Listen for requests from regions + // * When a request is received: + // - Authenticate region + // - Authenticate user + // - Have correct scriptengine load script + // ~ ask scriptengines if they will accept script? + // - Add script to shared communication channel towards that region + + // TODO: FAKING A CONNECTION + Regions.Add(new RegionConnectionManager(m_ScriptServerMain, null)); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptServer/ScriptServer/ScriptEngineLoader.cs b/trunk/OpenSim/Grid/ScriptServer/ScriptServer/ScriptEngineLoader.cs new file mode 100644 index 0000000000..4bb74f538b --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptServer/ScriptServer/ScriptEngineLoader.cs @@ -0,0 +1,117 @@ +/* +* 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; +using System.IO; +using System.Reflection; +using OpenSim.Framework.Console; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Grid.ScriptServer.ScriptServer +{ + internal class ScriptEngineLoader + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public ScriptServerInterfaces.ScriptEngine LoadScriptEngine(string EngineName) + { + ScriptServerInterfaces.ScriptEngine ret = null; + try + { + ret = + LoadAndInitAssembly( + Path.Combine("ScriptEngines", "OpenSim.Region.ScriptEngine." + EngineName + ".dll"), + "OpenSim.Region.ScriptEngine." + EngineName + ".ScriptEngine"); + } + catch (Exception e) + { + m_log.Error("[ScriptEngine]: " + + "Error loading assembly \"" + EngineName + "\": " + e.Message + ", " + + e.StackTrace.ToString()); + } + return ret; + } + + /// + /// Does actual loading and initialization of script Assembly + /// + /// + private ScriptServerInterfaces.ScriptEngine LoadAndInitAssembly(string FileName, string NameSpace) + { + //Common.SendToDebug("Loading ScriptEngine Assembly " + FileName); + // Load .Net Assembly (.dll) + // Initialize and return it + + // TODO: Add error handling + + Assembly a; + //try + //{ + + + // Load to default appdomain (temporary) + a = Assembly.LoadFrom(FileName); + // Load to specified appdomain + // TODO: Insert security + //a = FreeAppDomain.Load(FileName); + //} + //catch (Exception e) + //{ + // m_log.Error("[ScriptEngine]: Error loading assembly \String.Empty + FileName + "\": " + e.ToString()); + //} + + + //Console.WriteLine("Loading: " + FileName); + //foreach (Type _t in a.GetTypes()) + //{ + // Console.WriteLine("Type: " + _t.ToString()); + //} + + Type t; + //try + //{ + t = a.GetType(NameSpace, true); + //} + //catch (Exception e) + //{ + // m_log.Error("[ScriptEngine]: Error initializing type \String.Empty + NameSpace + "\" from \String.Empty + FileName + "\": " + e.ToString()); + //} + + ScriptServerInterfaces.ScriptEngine ret; + //try + //{ + ret = (ScriptServerInterfaces.ScriptEngine)Activator.CreateInstance(t); + //} + //catch (Exception e) + //{ + // m_log.Error("[ScriptEngine]: Error initializing type \String.Empty + NameSpace + "\" from \String.Empty + FileName + "\": " + e.ToString()); + //} + + return ret; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptServer/ScriptServer/ScriptEnginesManager.cs b/trunk/OpenSim/Grid/ScriptServer/ScriptServer/ScriptEnginesManager.cs new file mode 100644 index 0000000000..7976cb58a1 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptServer/ScriptServer/ScriptEnginesManager.cs @@ -0,0 +1,63 @@ +/* +* 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.Collections.Generic; +using OpenSim.Framework.Console; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Grid.ScriptServer.ScriptServer +{ + internal class ScriptEngineManager + { + private ScriptEngineLoader ScriptEngineLoader; + private List scriptEngines = new List(); + private ScriptServerMain m_ScriptServerMain; + + // Initialize + public ScriptEngineManager(ScriptServerMain scm) + { + m_ScriptServerMain = scm; + ScriptEngineLoader = new ScriptEngineLoader(); + } + + ~ScriptEngineManager() + { + } + + public ScriptServerInterfaces.ScriptEngine LoadEngine(string engineName) + { + // Load and add to list of ScriptEngines + ScriptServerInterfaces.ScriptEngine sei = ScriptEngineLoader.LoadScriptEngine(engineName); + if (sei != null) + { + scriptEngines.Add(sei); + } + return sei; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Grid/ScriptServer/ScriptServerMain.cs b/trunk/OpenSim/Grid/ScriptServer/ScriptServerMain.cs new file mode 100644 index 0000000000..e2c83f1428 --- /dev/null +++ b/trunk/OpenSim/Grid/ScriptServer/ScriptServerMain.cs @@ -0,0 +1,110 @@ +/* +* 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.IO; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Grid.ScriptServer.ScriptServer; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.TRPC; + +namespace OpenSim.Grid.ScriptServer +{ + public class ScriptServerMain : BaseOpenSimServer, conscmd_callback + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // + // Root object. Creates objects used. + // + private int listenPort = 8010; + + // TEMP + public static ScriptServerInterfaces.ScriptEngine Engine; + //public static FakeScene m_Scene = new FakeScene(null,null,null,null,null,null,null,null,null,false, false, false); + + // Objects we use + internal RegionCommManager RegionScriptDaemon; // Listen for incoming from region + internal ScriptEngineManager ScriptEngines; // Loads scriptengines + //internal RemotingServer m_RemotingServer; + internal TCPServer m_TCPServer; + internal TRPC_Remote RPC; + + public ScriptServerMain() + { + m_console = CreateConsole(); + + // Set up script engine mananger + ScriptEngines = new ScriptEngineManager(this); + + // Load DotNetEngine + Engine = ScriptEngines.LoadEngine("DotNetEngine"); + IConfigSource config = null; + Engine.InitializeEngine(null, null, false, Engine.GetScriptManager()); + + + // Set up server + //m_RemotingServer = new RemotingServer(listenPort, "DotNetEngine"); + m_TCPServer = new TCPServer(listenPort); + RPC = new TRPC_Remote(m_TCPServer); + RPC.ReceiveCommand += new TRPC_Remote.ReceiveCommandDelegate(RPC_ReceiveCommand); + m_TCPServer.StartListen(); + + System.Console.ReadLine(); + } + + private void RPC_ReceiveCommand(int ID, string Command, object[] p) + { + m_log.Info("[SERVER]: Received command: '" + Command + "'"); + if (p != null) + { + for (int i = 0; i < p.Length; i++) + { + m_log.Info("[SERVER]: Param " + i + ": " + p[i].ToString()); + } + } + + if (Command == "OnRezScript") + { + Engine.EventManager().OnRezScript((uint)p[0], new LLUUID((string)p[1]), (string)p[2]); + } + } + + ~ScriptServerMain() + { + } + + protected ConsoleBase CreateConsole() + { + return new ConsoleBase("ScriptServer", this); + } + } +} diff --git a/trunk/OpenSim/Grid/UserServer.Config/AssemblyInfo.cs b/trunk/OpenSim/Grid/UserServer.Config/AssemblyInfo.cs new file mode 100644 index 0000000000..7379b2b33e --- /dev/null +++ b/trunk/OpenSim/Grid/UserServer.Config/AssemblyInfo.cs @@ -0,0 +1,56 @@ +/* +* 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; +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly: AssemblyTitle("UserConfig")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("UserConfig")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly: AssemblyVersion("1.0.*")] diff --git a/trunk/OpenSim/Grid/UserServer.Config/DbUserConfig.cs b/trunk/OpenSim/Grid/UserServer.Config/DbUserConfig.cs new file mode 100644 index 0000000000..865dfea689 --- /dev/null +++ b/trunk/OpenSim/Grid/UserServer.Config/DbUserConfig.cs @@ -0,0 +1,106 @@ +/* + * 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; +using Db4objects.Db4o; +using OpenSim.Framework.Configuration; +using OpenSim.Framework.Console; +using OpenSim.Framework.Interfaces; + +namespace OpenUser.Config.UserConfigDb4o +{ + public class Db4oConfigPlugin: IUserConfig + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public UserConfig GetConfigObject() + { + m_log.Info("[DBUSERCONFIG]: Loading Db40Config dll"); + return ( new DbUserConfig()); + } + } + + public class DbUserConfig : UserConfig + { + private IObjectContainer db; + + public void LoadDefaults() + { + m_log.Info("DbUserConfig.cs:LoadDefaults() - Please press enter to retain default or enter new settings"); + + this.DefaultStartupMsg = m_log.CmdPrompt("Default startup message", "Welcome to OGS"); + + this.GridServerURL = m_log.CmdPrompt("Grid server URL","http://127.0.0.1:" + GridConfig.DefaultHttpPort.ToString() + "/"); + this.GridSendKey = m_log.CmdPrompt("Key to send to grid server","null"); + this.GridRecvKey = m_log.CmdPrompt("Key to expect from grid server","null"); + } + + public override void InitConfig() + { + try + { + db = Db4oFactory.OpenFile("openuser.yap"); + IObjectSet result = db.Get(typeof(DbUserConfig)); + if(result.Count==1) + { + m_log.Info("[DBUSERCONFIG]: DbUserConfig.cs:InitConfig() - Found a UserConfig object in the local database, loading"); + foreach (DbUserConfig cfg in result) + { + this.GridServerURL=cfg.GridServerURL; + this.GridSendKey=cfg.GridSendKey; + this.GridRecvKey=cfg.GridRecvKey; + this.DefaultStartupMsg=cfg.DefaultStartupMsg; + } + } + else + { + m_log.Info("[DBUSERCONFIG]: DbUserConfig.cs:InitConfig() - Could not find object in database, loading precompiled defaults"); + LoadDefaults(); + m_log.Info("[DBUSERCONFIG]: Writing out default settings to local database"); + db.Set(this); + db.Close(); + } + } + catch(Exception e) + { + m_log.Warn("DbUserConfig.cs:InitConfig() - Exception occured"); + m_log.Warn(e.ToString()); + } + + m_log.Info("[DBUSERCONFIG]: User settings loaded:"); + m_log.Info("[DBUSERCONFIG]: Default startup message: " + this.DefaultStartupMsg); + m_log.Info("[DBUSERCONFIG]: Grid server URL: " + this.GridServerURL); + m_log.Info("[DBUSERCONFIG]: Key to send to grid: " + this.GridSendKey); + m_log.Info("[DBUSERCONFIG]: Key to expect from grid: " + this.GridRecvKey); + } + + public void Shutdown() + { + db.Close(); + } + } +} diff --git a/trunk/OpenSim/Grid/UserServer/Main.cs b/trunk/OpenSim/Grid/UserServer/Main.cs new file mode 100644 index 0000000000..8c05d862dc --- /dev/null +++ b/trunk/OpenSim/Grid/UserServer/Main.cs @@ -0,0 +1,251 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Statistics; + +namespace OpenSim.Grid.UserServer +{ + /// + /// + public class OpenUser_Main : BaseOpenSimServer, conscmd_callback + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private UserConfig Cfg; + + public UserManager m_userManager; + public UserLoginService m_loginService; + public MessageServersConnector m_messagesService; + + private LLUUID m_lastCreatedUser = LLUUID.Random(); + + [STAThread] + public static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + m_log.Info("Launching UserServer..."); + + OpenUser_Main userserver = new OpenUser_Main(); + + userserver.Startup(); + userserver.Work(); + } + + private OpenUser_Main() + { + m_console = new ConsoleBase("OpenUser", this); + MainConsole.Instance = m_console; + } + + private void Work() + { + m_console.Notice("Enter help for a list of commands\n"); + + while (true) + { + m_console.Prompt(); + } + } + + public void Startup() + { + Cfg = new UserConfig("USER SERVER", (Path.Combine(Util.configDir(), "UserServer_Config.xml"))); + + StatsManager.StartCollectingUserStats(); + + m_log.Info("[REGION]: Establishing data connection"); + m_userManager = new UserManager(); + m_userManager._config = Cfg; + m_userManager.AddPlugin(Cfg.DatabaseProvider); + + m_loginService = new UserLoginService( + m_userManager, new LibraryRootFolder(), Cfg, Cfg.DefaultStartupMsg); + + m_messagesService = new MessageServersConnector(); + + m_loginService.OnUserLoggedInAtLocation += NotifyMessageServersUserLoggedInToLocation; + + m_log.Info("[REGION]: Starting HTTP process"); + BaseHttpServer httpServer = new BaseHttpServer(Cfg.HttpPort); + + httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod); + + httpServer.AddHTTPHandler("login", m_loginService.ProcessHTMLLogin); + + httpServer.SetLLSDHandler(m_loginService.LLSDLoginMethod); + + httpServer.AddXmlRPCHandler("get_user_by_name", m_userManager.XmlRPCGetUserMethodName); + httpServer.AddXmlRPCHandler("get_user_by_uuid", m_userManager.XmlRPCGetUserMethodUUID); + httpServer.AddXmlRPCHandler("get_avatar_picker_avatar", m_userManager.XmlRPCGetAvatarPickerAvatar); + httpServer.AddXmlRPCHandler("add_new_user_friend", m_userManager.XmlRpcResponseXmlRPCAddUserFriend); + httpServer.AddXmlRPCHandler("remove_user_friend", m_userManager.XmlRpcResponseXmlRPCRemoveUserFriend); + httpServer.AddXmlRPCHandler("update_user_friend_perms", m_userManager.XmlRpcResponseXmlRPCUpdateUserFriendPerms); + httpServer.AddXmlRPCHandler("get_user_friend_list", m_userManager.XmlRpcResponseXmlRPCGetUserFriendList); + httpServer.AddXmlRPCHandler("logout_of_simulator", m_userManager.XmlRPCLogOffUserMethodUUID); + + // Message Server ---> User Server + httpServer.AddXmlRPCHandler("register_messageserver", m_messagesService.XmlRPCRegisterMessageServer); + httpServer.AddXmlRPCHandler("agent_change_region", m_messagesService.XmlRPCUserMovedtoRegion); + httpServer.AddXmlRPCHandler("deregister_messageserver", m_messagesService.XmlRPCDeRegisterMessageServer); + + + httpServer.AddStreamHandler( + new RestStreamHandler("DELETE", "/usersessions/", m_userManager.RestDeleteUserSessionMethod)); + + httpServer.Start(); + m_log.Info("[SERVER]: Userserver 0.5 - Startup complete"); + } + + public void do_create(string what) + { + switch (what) + { + case "user": + string tempfirstname; + string templastname; + string tempMD5Passwd; + uint regX = 1000; + uint regY = 1000; + + tempfirstname = m_console.CmdPrompt("First name"); + templastname = m_console.CmdPrompt("Last name"); + //tempMD5Passwd = m_console.PasswdPrompt("Password"); + tempMD5Passwd = m_console.CmdPrompt("Password"); + regX = Convert.ToUInt32(m_console.CmdPrompt("Start Region X")); + regY = Convert.ToUInt32(m_console.CmdPrompt("Start Region Y")); + + tempMD5Passwd = Util.Md5Hash(Util.Md5Hash(tempMD5Passwd) + ":" + String.Empty); + + LLUUID userID = new LLUUID(); + try + { + userID = + m_userManager.AddUserProfile(tempfirstname, templastname, tempMD5Passwd, regX, regY); + } catch (Exception ex) + { + m_log.ErrorFormat("[SERVER]: Error creating user: {0}", ex.ToString()); + } + + try + { + RestObjectPoster.BeginPostObject(m_userManager._config.InventoryUrl + "CreateInventory/", + userID.UUID); + } + catch (Exception ex) + { + m_log.ErrorFormat("[SERVER]: Error creating inventory for user: {0}", ex.ToString()); + } + m_lastCreatedUser = userID; + break; + } + } + + public override void RunCmd(string cmd, string[] cmdparams) + { + base.RunCmd(cmd, cmdparams); + + switch (cmd) + { + case "help": + m_console.Notice("create user - create a new user"); + m_console.Notice("stats - statistical information for this server"); + m_console.Notice("shutdown - shutdown the grid (USE CAUTION!)"); + break; + + case "create": + do_create(cmdparams[0]); + break; + + case "shutdown": + m_loginService.OnUserLoggedInAtLocation -= NotifyMessageServersUserLoggedInToLocation; + m_console.Close(); + Environment.Exit(0); + break; + + case "stats": + m_console.Notice(StatsManager.UserStats.Report()); + break; + + case "test-inventory": + // RestObjectPosterResponse> requester = new RestObjectPosterResponse>(); + // requester.ReturnResponseVal = TestResponse; + // requester.BeginPostObject(m_userManager._config.InventoryUrl + "RootFolders/", m_lastCreatedUser); + List folders = + SynchronousRestObjectPoster.BeginPostObject>("POST", + m_userManager. + _config. + InventoryUrl + + "RootFolders/", + m_lastCreatedUser); + break; + } + } + + public void TestResponse(List resp) + { + m_console.Notice("response got"); + } + + public void NotifyMessageServersUserLoggedInToLocation(LLUUID agentID, LLUUID sessionID, LLUUID RegionID, ulong regionhandle, LLVector3 Position) + { + m_messagesService.TellMessageServersAboutUser(agentID, sessionID, RegionID, regionhandle, Position); + } + + /*private void ConfigDB(IGenericConfig configData) + { + try + { + string attri = String.Empty; + attri = configData.GetAttribute("DataBaseProvider"); + if (attri == String.Empty) + { + StorageDll = "OpenSim.Framework.Data.DB4o.dll"; + configData.SetAttribute("DataBaseProvider", "OpenSim.Framework.Data.DB4o.dll"); + } + else + { + StorageDll = attri; + } + configData.Commit(); + } + catch + { + + } + }*/ + } +} diff --git a/trunk/OpenSim/Grid/UserServer/MessageServersConnector.cs b/trunk/OpenSim/Grid/UserServer/MessageServersConnector.cs new file mode 100644 index 0000000000..251644bd5b --- /dev/null +++ b/trunk/OpenSim/Grid/UserServer/MessageServersConnector.cs @@ -0,0 +1,180 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using libsecondlife; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; + +namespace OpenSim.Grid.UserServer +{ + public class MessageServersConnector + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public Dictionary MessageServers; + + public MessageServersConnector() + { + MessageServers = new Dictionary(); + } + + public void RegisterMessageServer(string URI, MessageServerInfo serverData) + { + MessageServers.Add(URI, serverData); + } + + public void DeRegisterMessageServer(string URI) + { + MessageServers.Remove(URI); + } + + public void AddResponsibleRegion(string URI, ulong regionhandle) + { + if (!MessageServers.ContainsKey(URI)) + { + m_log.Warn("[MSGSERVER]: Got addResponsibleRegion Request for a MessageServer that isn't registered"); + } + else + { + MessageServerInfo msginfo = MessageServers["URI"]; + msginfo.responsibleForRegions.Add(regionhandle); + MessageServers["URI"] = msginfo; + } + } + public void RemoveResponsibleRegion(string URI, ulong regionhandle) + { + if (!MessageServers.ContainsKey(URI)) + { + m_log.Warn("[MSGSERVER]: Got RemoveResponsibleRegion Request for a MessageServer that isn't registered"); + } + else + { + MessageServerInfo msginfo = MessageServers["URI"]; + if (msginfo.responsibleForRegions.Contains(regionhandle)) + { + msginfo.responsibleForRegions.Remove(regionhandle); + MessageServers["URI"] = msginfo; + } + } + + } + public XmlRpcResponse XmlRPCRegisterMessageServer(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData = new Hashtable(); + + if (requestData.Contains("uri")) + { + string URI = (string)requestData["uri"]; + string sendkey=(string)requestData["sendkey"]; + string recvkey=(string)requestData["recvkey"]; + MessageServerInfo m = new MessageServerInfo(); + m.URI = URI; + m.sendkey = sendkey; + m.recvkey = recvkey; + RegisterMessageServer(URI, m); + responseData["responsestring"] = "TRUE"; + response.Value = responseData; + } + return response; + } + public XmlRpcResponse XmlRPCDeRegisterMessageServer(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData = new Hashtable(); + + if (requestData.Contains("uri")) + { + string URI = (string)requestData["URI"]; + + DeRegisterMessageServer(URI); + responseData["responsestring"] = "TRUE"; + response.Value = responseData; + } + return response; + } + public XmlRpcResponse XmlRPCUserMovedtoRegion(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData = new Hashtable(); + + if (requestData.Contains("fromuri")) + { + string sURI = (string)requestData["fromuri"]; + string sagentID = (string)requestData["agentid"]; + string ssessionID = (string)requestData["sessionid"]; + string scurrentRegionID = (string)requestData["regionid"]; + string sregionhandle = (string)requestData["regionhandle"]; + string scurrentpos = (string)requestData["currentpos"]; + //LLVector3.TryParse((string)reader["currentPos"], out retval.currentPos); + // TODO: Okay now raise event so the user server can pass this data to the Usermanager + + responseData["responsestring"] = "TRUE"; + response.Value = responseData; + } + return response; + } + + public void TellMessageServersAboutUser(LLUUID agentID, LLUUID sessionID, LLUUID RegionID, ulong regionhandle, LLVector3 Position) + { + // Loop over registered Message Servers ( AND THERE WILL BE MORE THEN ONE :D ) + foreach (MessageServerInfo serv in MessageServers.Values) + { + NotifyMessageServerAboutUser(serv, agentID, sessionID, RegionID, regionhandle, Position); + } + } + + private void NotifyMessageServerAboutUser(MessageServerInfo serv, LLUUID agentID, LLUUID sessionID, LLUUID RegionID, ulong regionhandle, LLVector3 Position) + { + Hashtable reqparams = new Hashtable(); + reqparams["sendkey"] = serv.sendkey; + reqparams["agentid"] = agentID.ToString(); + reqparams["sessionid"] = sessionID.ToString(); + reqparams["regionid"] = RegionID.ToString(); + reqparams["regionhandle"] = regionhandle.ToString(); + reqparams["position"] = Position.ToString(); + + ArrayList SendParams = new ArrayList(); + SendParams.Add(reqparams); + + XmlRpcRequest GridReq = new XmlRpcRequest("login_to_simulator", SendParams); + XmlRpcResponse GridResp = GridReq.Send(serv.URI, 6000); + m_log.Info("[LOGIN]: Notified : " + serv.URI + " about user login"); + } + } +} diff --git a/trunk/OpenSim/Grid/UserServer/Properties/AssemblyInfo.cs b/trunk/OpenSim/Grid/UserServer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..06d4a0ea19 --- /dev/null +++ b/trunk/OpenSim/Grid/UserServer/Properties/AssemblyInfo.cs @@ -0,0 +1,64 @@ +/* +* 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("OGS-UserServer")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OGS-UserServer")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("e266513a-090b-4d38-80f6-8599eef68c8c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Grid/UserServer/UserLoginService.cs b/trunk/OpenSim/Grid/UserServer/UserLoginService.cs new file mode 100644 index 0000000000..09cd9fd87b --- /dev/null +++ b/trunk/OpenSim/Grid/UserServer/UserLoginService.cs @@ -0,0 +1,294 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using Nwc.XmlRpc; + +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Data; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Statistics; +using OpenSim.Framework.UserManagement; +using InventoryFolder=OpenSim.Framework.InventoryFolder; + +namespace OpenSim.Grid.UserServer +{ + public delegate void UserLoggedInAtLocation(LLUUID agentID, LLUUID sessionID, LLUUID RegionID, ulong regionhandle, LLVector3 Position); + + public class UserLoginService : LoginService + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public event UserLoggedInAtLocation OnUserLoggedInAtLocation; + + public UserConfig m_config; + + public UserLoginService( + UserManagerBase userManager, LibraryRootFolder libraryRootFolder, + UserConfig config, string welcomeMess) + : base(userManager, libraryRootFolder, welcomeMess) + { + m_config = config; + } + + /// + /// Customises the login response and fills in missing values. + /// + /// The existing response + /// The user profile + public override void CustomiseResponse(LoginResponse response, UserProfileData theUser) + { + bool tryDefault = false; + //CFK: Since the try is always "tried", the "Home Location" message should always appear, so comment this one. + //CFK: m_log.Info("[LOGIN]: Load information from the gridserver"); + RegionProfileData SimInfo = new RegionProfileData(); + try + { + SimInfo = + SimInfo.RequestSimProfileData(theUser.currentAgent.currentHandle, m_config.GridServerURL, + m_config.GridSendKey, m_config.GridRecvKey); + + // Customise the response + //CFK: This is redundant and the next message should always appear. + //CFK: m_log.Info("[LOGIN]: Home Location"); + response.Home = "{'region_handle':[r" + (SimInfo.regionLocX * Constants.RegionSize).ToString() + ",r" + + (SimInfo.regionLocY * Constants.RegionSize).ToString() + "], " + + "'position':[r" + theUser.homeLocation.X.ToString() + ",r" + + theUser.homeLocation.Y.ToString() + ",r" + theUser.homeLocation.Z.ToString() + "], " + + "'look_at':[r" + theUser.homeLocation.X.ToString() + ",r" + + theUser.homeLocation.Y.ToString() + ",r" + theUser.homeLocation.Z.ToString() + "]}"; + + // Destination + //CFK: The "Notifying" message always seems to appear, so subsume the data from this message into + //CFK: the next one for X & Y and comment this one. + //CFK: m_log.Info("[LOGIN]: CUSTOMISERESPONSE: Region X: " + SimInfo.regionLocX + + //CFK: "; Region Y: " + SimInfo.regionLocY); + response.SimAddress = Util.GetHostFromDNS(SimInfo.serverIP).ToString(); + response.SimPort = (uint) SimInfo.serverPort; + response.RegionX = SimInfo.regionLocX; + response.RegionY = SimInfo.regionLocY; + + //Not sure if the + "/CAPS/" should in fact be +"CAPS/" depending if there is already a / as part of httpServerURI + string capsPath = Util.GetRandomCapsPath(); + response.SeedCapability = SimInfo.httpServerURI + "CAPS/" + capsPath + "0000/"; + + // Notify the target of an incoming user + //CFK: The "Notifying" message always seems to appear, so subsume the data from this message into + //CFK: the next one for X & Y and comment this one. + //CFK: m_log.Info("[LOGIN]: " + SimInfo.regionName + " (" + SimInfo.serverURI + ") " + + //CFK: SimInfo.regionLocX + "," + SimInfo.regionLocY); + + // Prepare notification + Hashtable SimParams = new Hashtable(); + SimParams["session_id"] = theUser.currentAgent.sessionID.ToString(); + SimParams["secure_session_id"] = theUser.currentAgent.secureSessionID.ToString(); + SimParams["firstname"] = theUser.username; + SimParams["lastname"] = theUser.surname; + SimParams["agent_id"] = theUser.UUID.ToString(); + SimParams["circuit_code"] = (Int32) Convert.ToUInt32(response.CircuitCode); + SimParams["startpos_x"] = theUser.currentAgent.currentPos.X.ToString(); + SimParams["startpos_y"] = theUser.currentAgent.currentPos.Y.ToString(); + SimParams["startpos_z"] = theUser.currentAgent.currentPos.Z.ToString(); + SimParams["regionhandle"] = theUser.currentAgent.currentHandle.ToString(); + SimParams["caps_path"] = capsPath; + ArrayList SendParams = new ArrayList(); + SendParams.Add(SimParams); + + // Update agent with target sim + theUser.currentAgent.currentRegion = SimInfo.UUID; + theUser.currentAgent.currentHandle = SimInfo.regionHandle; + + m_log.Info("[LOGIN]: " + SimInfo.regionName + " @ " + SimInfo.httpServerURI + " " + + SimInfo.regionLocX + "," + SimInfo.regionLocY); + + XmlRpcRequest GridReq = new XmlRpcRequest("expect_user", SendParams); + XmlRpcResponse GridResp = GridReq.Send(SimInfo.httpServerURI, 6000); + } + catch (Exception) + { + tryDefault = true; + } + if (tryDefault) + { + // Send him to default region instead + // Load information from the gridserver + + ulong defaultHandle = (((ulong)m_config.DefaultX * Constants.RegionSize) << 32) | ((ulong)m_config.DefaultY * Constants.RegionSize); + + m_log.Warn( + "[LOGIN]: Home region not available: sending to default " + defaultHandle.ToString()); + + SimInfo = new RegionProfileData(); + try + { + SimInfo = + SimInfo.RequestSimProfileData(defaultHandle, m_config.GridServerURL, + m_config.GridSendKey, m_config.GridRecvKey); + + // Customise the response + m_log.Info("[LOGIN]: Home Location"); + response.Home = "{'region_handle':[r" + (SimInfo.regionLocX * Constants.RegionSize).ToString() + ",r" + + (SimInfo.regionLocY * Constants.RegionSize).ToString() + "], " + + "'position':[r" + theUser.homeLocation.X.ToString() + ",r" + + theUser.homeLocation.Y.ToString() + ",r" + theUser.homeLocation.Z.ToString() + "], " + + "'look_at':[r" + theUser.homeLocation.X.ToString() + ",r" + + theUser.homeLocation.Y.ToString() + ",r" + theUser.homeLocation.Z.ToString() + "]}"; + + // Destination + m_log.Info("[LOGIN]: " + + "CUSTOMISERESPONSE: Region X: " + SimInfo.regionLocX + "; Region Y: " + + SimInfo.regionLocY); + response.SimAddress = Util.GetHostFromDNS(SimInfo.serverIP).ToString(); + response.SimPort = (uint) SimInfo.serverPort; + response.RegionX = SimInfo.regionLocX; + response.RegionY = SimInfo.regionLocY; + + //Not sure if the + "/CAPS/" should in fact be +"CAPS/" depending if there is already a / as part of httpServerURI + string capsPath = Util.GetRandomCapsPath(); + response.SeedCapability = SimInfo.httpServerURI + "CAPS/" + capsPath + "0000/"; + + // Notify the target of an incoming user + m_log.Info("[LOGIN]: Notifying " + SimInfo.regionName + " (" + SimInfo.serverURI + ")"); + + // Update agent with target sim + theUser.currentAgent.currentRegion = SimInfo.UUID; + theUser.currentAgent.currentHandle = SimInfo.regionHandle; + + // Prepare notification + Hashtable SimParams = new Hashtable(); + SimParams["session_id"] = theUser.currentAgent.sessionID.ToString(); + SimParams["secure_session_id"] = theUser.currentAgent.secureSessionID.ToString(); + SimParams["firstname"] = theUser.username; + SimParams["lastname"] = theUser.surname; + SimParams["agent_id"] = theUser.UUID.ToString(); + SimParams["circuit_code"] = (Int32) Convert.ToUInt32(response.CircuitCode); + SimParams["startpos_x"] = theUser.currentAgent.currentPos.X.ToString(); + SimParams["startpos_y"] = theUser.currentAgent.currentPos.Y.ToString(); + SimParams["startpos_z"] = theUser.currentAgent.currentPos.Z.ToString(); + SimParams["regionhandle"] = theUser.currentAgent.currentHandle.ToString(); + SimParams["caps_path"] = capsPath; + ArrayList SendParams = new ArrayList(); + SendParams.Add(SimParams); + + m_log.Info("[LOGIN]: Informing region at " + SimInfo.httpServerURI); + // Send + XmlRpcRequest GridReq = new XmlRpcRequest("expect_user", SendParams); + XmlRpcResponse GridResp = GridReq.Send(SimInfo.httpServerURI, 6000); + if (OnUserLoggedInAtLocation != null) + { + OnUserLoggedInAtLocation(theUser.UUID, theUser.currentAgent.sessionID, theUser.currentAgent.currentRegion, theUser.currentAgent.currentHandle, theUser.currentAgent.currentPos); + } + } + + catch (Exception e) + { + m_log.Warn("[LOGIN]: Default region also not available"); + m_log.Warn("[LOGIN]: " + e.ToString()); + } + } + } + + protected override InventoryData CreateInventoryData(LLUUID userID) + { + List folders + = SynchronousRestObjectPoster.BeginPostObject>( + "POST", m_config.InventoryUrl + "RootFolders/", userID.UUID); + + // In theory, the user will only ever be missing a root folder in situations where a grid + // which didn't previously run a grid wide inventory server is being transitioned to one + // which does. + if (null == folders | folders.Count == 0) + { + m_log.Warn( + "[LOGIN]: " + + "root inventory folder user " + userID + " not found. Creating."); + + RestObjectPoster.BeginPostObject( + m_config.InventoryUrl + "CreateInventory/", userID.UUID); + + // A big delay should be okay here since the recreation of the user's root folders should + // only ever happen once. We need to sleep to let the inventory server do its work - + // previously 1000ms has been found to be too short. + Thread.Sleep(10000); + folders = SynchronousRestObjectPoster.BeginPostObject>( + "POST", m_config.InventoryUrl + "RootFolders/", userID.UUID); + } + + if (folders.Count > 0) + { + LLUUID rootID = LLUUID.Zero; + ArrayList AgentInventoryArray = new ArrayList(); + Hashtable TempHash; + foreach (InventoryFolderBase InvFolder in folders) + { + if (InvFolder.parentID == LLUUID.Zero) + { + rootID = InvFolder.folderID; + } + TempHash = new Hashtable(); + TempHash["name"] = InvFolder.name; + TempHash["parent_id"] = InvFolder.parentID.ToString(); + TempHash["version"] = (Int32) InvFolder.version; + TempHash["type_default"] = (Int32) InvFolder.type; + TempHash["folder_id"] = InvFolder.folderID.ToString(); + AgentInventoryArray.Add(TempHash); + } + return new InventoryData(AgentInventoryArray, rootID); + } + else + { + m_log.Warn("[LOGIN]: The root inventory folder could still not be retrieved" + + " for user ID " + userID); + + AgentInventory userInventory = new AgentInventory(); + userInventory.CreateRootFolder(userID, false); + + ArrayList AgentInventoryArray = new ArrayList(); + Hashtable TempHash; + foreach (InventoryFolder InvFolder in userInventory.InventoryFolders.Values) + { + TempHash = new Hashtable(); + TempHash["name"] = InvFolder.FolderName; + TempHash["parent_id"] = InvFolder.ParentID.ToString(); + TempHash["version"] = (Int32) InvFolder.Version; + TempHash["type_default"] = (Int32) InvFolder.DefaultType; + TempHash["folder_id"] = InvFolder.FolderID.ToString(); + AgentInventoryArray.Add(TempHash); + } + + return new InventoryData(AgentInventoryArray, userInventory.InventoryRoot.FolderID); + } + } + } +} diff --git a/trunk/OpenSim/Grid/UserServer/UserManager.cs b/trunk/OpenSim/Grid/UserServer/UserManager.cs new file mode 100644 index 0000000000..8f2d83ce24 --- /dev/null +++ b/trunk/OpenSim/Grid/UserServer/UserManager.cs @@ -0,0 +1,364 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using libsecondlife; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Statistics; +using OpenSim.Framework.UserManagement; + +namespace OpenSim.Grid.UserServer +{ + public class UserManager : UserManagerBase + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Deletes an active agent session + /// + /// The request + /// The path (eg /bork/narf/test) + /// Parameters sent + /// Success "OK" else error + public string RestDeleteUserSessionMethod(string request, string path, string param) + { + // TODO! Important! + + return "OK"; + } + + /// + /// Returns an error message that the user could not be found in the database + /// + /// XML string consisting of a error element containing individual error(s) + public XmlRpcResponse CreateUnknownUserErrorResponse() + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + responseData["error_type"] = "unknown_user"; + responseData["error_desc"] = "The user requested is not in the database"; + + response.Value = responseData; + return response; + } + + public XmlRpcResponse AvatarPickerListtoXmlRPCResponse(LLUUID queryID, List returnUsers) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + // Query Result Information + responseData["queryid"] = (string) queryID.ToString(); + responseData["avcount"] = (string) returnUsers.Count.ToString(); + + for (int i = 0; i < returnUsers.Count; i++) + { + responseData["avatarid" + i.ToString()] = returnUsers[i].AvatarID.ToString(); + responseData["firstname" + i.ToString()] = returnUsers[i].firstName; + responseData["lastname" + i.ToString()] = returnUsers[i].lastName; + } + response.Value = responseData; + + return response; + } + + public XmlRpcResponse FriendListItemListtoXmlRPCResponse(List returnUsers) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + // Query Result Information + + responseData["avcount"] = (string)returnUsers.Count.ToString(); + + for (int i = 0; i < returnUsers.Count; i++) + { + responseData["ownerID" + i.ToString()] = returnUsers[i].FriendListOwner.UUID.ToString(); + responseData["friendID" + i.ToString()] = returnUsers[i].Friend.UUID.ToString(); + responseData["ownerPerms" + i.ToString()] = returnUsers[i].FriendListOwnerPerms.ToString(); + responseData["friendPerms" + i.ToString()] = returnUsers[i].FriendPerms.ToString(); + } + response.Value = responseData; + + return response; + } + + /// + /// Converts a user profile to an XML element which can be returned + /// + /// The user profile + /// A string containing an XML Document of the user profile + public XmlRpcResponse ProfileToXmlRPCResponse(UserProfileData profile) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + + // Account information + responseData["firstname"] = profile.username; + responseData["lastname"] = profile.surname; + responseData["uuid"] = profile.UUID.ToString(); + // Server Information + responseData["server_inventory"] = profile.userInventoryURI; + responseData["server_asset"] = profile.userAssetURI; + // Profile Information + responseData["profile_about"] = profile.profileAboutText; + responseData["profile_firstlife_about"] = profile.profileFirstText; + responseData["profile_firstlife_image"] = profile.profileFirstImage.ToString(); + responseData["profile_can_do"] = profile.profileCanDoMask.ToString(); + responseData["profile_want_do"] = profile.profileWantDoMask.ToString(); + responseData["profile_image"] = profile.profileImage.ToString(); + responseData["profile_created"] = profile.created.ToString(); + responseData["profile_lastlogin"] = profile.lastLogin.ToString(); + // Home region information + responseData["home_coordinates_x"] = profile.homeLocation.X.ToString(); + responseData["home_coordinates_y"] = profile.homeLocation.Y.ToString(); + responseData["home_coordinates_z"] = profile.homeLocation.Z.ToString(); + + responseData["home_region"] = profile.homeRegion.ToString(); + + responseData["home_look_x"] = profile.homeLookAt.X.ToString(); + responseData["home_look_y"] = profile.homeLookAt.Y.ToString(); + responseData["home_look_z"] = profile.homeLookAt.Z.ToString(); + response.Value = responseData; + + return response; + } + + #region XMLRPC User Methods + + public XmlRpcResponse XmlRPCGetAvatarPickerAvatar(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable) request.Params[0]; + List returnAvatar = new List(); + LLUUID queryID = new LLUUID(LLUUID.Zero.ToString()); + + if (requestData.Contains("avquery") && requestData.Contains("queryid")) + { + queryID = new LLUUID((string) requestData["queryid"]); + returnAvatar = GenerateAgentPickerRequestResponse(queryID, (string) requestData["avquery"]); + } + + Console.WriteLine("[AVATARINFO]: Servicing Avatar Query: " + (string) requestData["avquery"]); + return AvatarPickerListtoXmlRPCResponse(queryID, returnAvatar); + } + + public XmlRpcResponse XmlRpcResponseXmlRPCAddUserFriend(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData = new Hashtable(); + string returnString = "FALSE"; + // Query Result Information + + if (requestData.Contains("ownerID") && requestData.Contains("friendID") && requestData.Contains("friendPerms")) + { + // UserManagerBase.AddNewuserFriend + AddNewUserFriend(new LLUUID((string)requestData["ownerID"]), new LLUUID((string)requestData["friendID"]), (uint)Convert.ToInt32((string)requestData["friendPerms"])); + returnString = "TRUE"; + } + responseData["returnString"] = returnString; + response.Value = responseData; + return response; + } + + public XmlRpcResponse XmlRpcResponseXmlRPCRemoveUserFriend(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData = new Hashtable(); + string returnString = "FALSE"; + // Query Result Information + + if (requestData.Contains("ownerID") && requestData.Contains("friendID")) + { + // UserManagerBase.AddNewuserFriend + RemoveUserFriend(new LLUUID((string)requestData["ownerID"]), new LLUUID((string)requestData["friendID"])); + returnString = "TRUE"; + } + responseData["returnString"] = returnString; + response.Value = responseData; + return response; + } + + public XmlRpcResponse XmlRpcResponseXmlRPCUpdateUserFriendPerms(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData = new Hashtable(); + string returnString = "FALSE"; + + if (requestData.Contains("ownerID") && requestData.Contains("friendID") && requestData.Contains("friendPerms")) + { + UpdateUserFriendPerms(new LLUUID((string)requestData["ownerID"]), new LLUUID((string)requestData["friendID"]), (uint)Convert.ToInt32((string)requestData["friendPerms"])); + // UserManagerBase. + returnString = "TRUE"; + } + responseData["returnString"] = returnString; + response.Value = responseData; + return response; + } + + public XmlRpcResponse XmlRpcResponseXmlRPCGetUserFriendList(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData = new Hashtable(); + + List returndata = new List(); + + if (requestData.Contains("ownerID")) + { + returndata = this.GetUserFriendList(new LLUUID((string)requestData["ownerID"])); + } + + return FriendListItemListtoXmlRPCResponse(returndata); + } + + public XmlRpcResponse XmlRPCGetUserMethodName(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable) request.Params[0]; + UserProfileData userProfile; + if (requestData.Contains("avatar_name")) + { + string query = (string) requestData["avatar_name"]; + + Regex objAlphaNumericPattern = new Regex("[^a-zA-Z0-9]"); + + string[] querysplit; + querysplit = query.Split(' '); + + if (querysplit.Length == 2) + { + userProfile = GetUserProfile(querysplit[0], querysplit[1]); + if (userProfile == null) + { + return CreateUnknownUserErrorResponse(); + } + } + else + { + return CreateUnknownUserErrorResponse(); + } + } + else + { + return CreateUnknownUserErrorResponse(); + } + + return ProfileToXmlRPCResponse(userProfile); + } + + public XmlRpcResponse XmlRPCGetUserMethodUUID(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable) request.Params[0]; + UserProfileData userProfile; + //CFK: this clogs the UserServer log and is not necessary at this time. + //CFK: Console.WriteLine("METHOD BY UUID CALLED"); + if (requestData.Contains("avatar_uuid")) + { + LLUUID guess = new LLUUID(); + try + { + guess = new LLUUID((string) requestData["avatar_uuid"]); + + userProfile = GetUserProfile(guess); + } + catch (FormatException) + { + return CreateUnknownUserErrorResponse(); + } + + if (userProfile == null) + { + return CreateUnknownUserErrorResponse(); + } + } + else + { + return CreateUnknownUserErrorResponse(); + } + + return ProfileToXmlRPCResponse(userProfile); + } + + public XmlRpcResponse XmlRPCLogOffUserMethodUUID(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + + UserProfileData userProfile; + + if (requestData.Contains("avatar_uuid")) + { + try + { + LLUUID userUUID = new LLUUID((string)requestData["avatar_uuid"]); + LLUUID RegionID = new LLUUID((string)requestData["region_uuid"]); + ulong regionhandle = (ulong)Convert.ToInt64((string)requestData["region_handle"]); + float posx = (float)Convert.ToDecimal((string)requestData["region_pos_x"]); + float posy = (float)Convert.ToDecimal((string)requestData["region_pos_y"]); + float posz = (float)Convert.ToDecimal((string)requestData["region_pos_z"]); + + LogOffUser(userUUID, RegionID, regionhandle, posx, posy, posz); + } + catch (FormatException) + { + m_log.Warn("[LOGOUT]: Error in Logout XMLRPC Params"); + return response; + } + } + else + { + return CreateUnknownUserErrorResponse(); + } + + return response; + } + + #endregion + + public override UserProfileData SetupMasterUser(string firstName, string lastName) + { + throw new Exception("The method or operation is not implemented."); + } + + public override UserProfileData SetupMasterUser(string firstName, string lastName, string password) + { + throw new Exception("The method or operation is not implemented."); + } + + public override UserProfileData SetupMasterUser(LLUUID uuid) + { + throw new Exception("The method or operation is not implemented."); + } + } +} diff --git a/trunk/OpenSim/Region/Application/Application.cs b/trunk/OpenSim/Region/Application/Application.cs new file mode 100644 index 0000000000..0bf1c55e66 --- /dev/null +++ b/trunk/OpenSim/Region/Application/Application.cs @@ -0,0 +1,138 @@ +/* +* 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; +using System.Net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; + +namespace OpenSim +{ + public class Application + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public static string iniFilePath = ""; + + //could move our main function into OpenSimMain and kill this class + [STAThread] + public static void Main(string[] args) + { + // First line + AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); + + log4net.Config.XmlConfigurator.Configure(); + + Console.WriteLine("OpenSim " + VersionInfo.Version + "\n"); + + Console.Write("Performing compatibility checks... "); + string supported = String.Empty; + if (Util.IsEnvironmentSupported(ref supported)) + { + Console.WriteLine(" Environment is compatible.\n"); + } + else + { + Console.WriteLine(" Environment is unsupported (" + supported + ")\n"); + } + + Console.WriteLine("Starting...\n"); + + Culture.SetCurrentCulture(); + + ArgvConfigSource configSource = new ArgvConfigSource(args); + + configSource.AddSwitch("Startup", "inifile"); + configSource.AddSwitch("Startup", "gridmode"); + configSource.AddSwitch("Startup", "physics"); + configSource.AddSwitch("Startup", "verbose"); + configSource.AddSwitch("Startup", "useexecutepath"); + + configSource.AddConfig("StandAlone"); + configSource.AddConfig("Network"); + + OpenSimMain sim = new OpenSimMain(configSource); + + sim.StartUp(); + + while (true) + { + MainConsole.Instance.Prompt(); + } + } + + private static bool _IsHandlingException = false; // Make sure we don't go recursive on ourself + /// + /// Global exception handler -- all unhandlet exceptions end up here :) + /// + /// + /// + private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + if (_IsHandlingException) + return; + _IsHandlingException = true; + // TODO: Add config option to allow users to turn off error reporting + // TODO: Post error report (disabled for now) + + string msg = String.Empty; + msg += "\r\n"; + msg += "APPLICATION EXCEPTION DETECTED: " + e.ToString() + "\r\n"; + msg += "\r\n"; + + msg += "Exception: " + e.ExceptionObject.ToString() + "\r\n"; + Exception ex = (Exception)e.ExceptionObject; + if (ex.InnerException != null) + msg += "InnerException: " + ex.InnerException.ToString() + "\r\n"; + + msg += "\r\n"; + msg += "Application is terminating: " + e.IsTerminating.ToString() + "\r\n"; + + // Do we not always want to see exception messages? +// if (e.IsTerminating) + MainConsole.Instance.Error("[APPLICATION]: " + msg); + + // Try to post errormessage to an URL + try + { + // DISABLED UNTIL WE CAN DISCUSS IF THIS IS MORALLY RIGHT OR NOT + // Note! Needs reference to System.Web + //System.Net.WebClient wc = new WebClient(); + //wc.DownloadData("http://www.opensimulator.org/ErrorReport.php?Msg=" + + // System.Web.HttpUtility.UrlEncode(msg)); + //wc.Dispose(); + } + catch (Exception) + { + // Ignore + } + + _IsHandlingException=false; + } + } +} diff --git a/trunk/OpenSim/Region/Application/IApplicationPlugin.cs b/trunk/OpenSim/Region/Application/IApplicationPlugin.cs new file mode 100644 index 0000000000..be6e75b457 --- /dev/null +++ b/trunk/OpenSim/Region/Application/IApplicationPlugin.cs @@ -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. +* +*/ + +using Mono.Addins; + +[assembly : AddinRoot("OpenSim", "0.5")] + +namespace OpenSim +{ + [TypeExtensionPoint("/OpenSim/Startup")] + public interface IApplicationPlugin + { + void Initialise(OpenSimMain openSim); + void Close(); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Application/OpenSimMain.cs b/trunk/OpenSim/Region/Application/OpenSimMain.cs new file mode 100644 index 0000000000..1e5fcfbc96 --- /dev/null +++ b/trunk/OpenSim/Region/Application/OpenSimMain.cs @@ -0,0 +1,1126 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading; +using System.Timers; +using libsecondlife; +using Mono.Addins; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Statistics; +using OpenSim.Region.ClientStack; +using OpenSim.Region.Communications.Local; +using OpenSim.Region.Communications.OGS1; +using OpenSim.Region.Environment; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.Physics.Manager; +using Timer=System.Timers.Timer; + +namespace OpenSim +{ + public delegate void ConsoleCommand(string[] comParams); + + public class OpenSimMain : RegionApplicationBase, conscmd_callback + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private const string DEFAULT_PRIM_BACKUP_FILENAME = "prim-backup.xml"; + + public string m_physicsEngine; + public string m_meshEngineName; + public string m_scriptEngine; + public bool m_sandbox; + public bool user_accounts; + public bool m_gridLocalAsset; + public bool m_see_into_region_from_neighbor; + + protected LocalLoginService m_loginService; + + protected string m_storageDll; + + protected string m_startupCommandsFile; + protected string m_shutdownCommandsFile; + + protected List m_udpServers = new List(); + protected List m_regionData = new List(); + + private bool m_verbose; + private bool m_physicalPrim; + private bool m_permissions = false; + + private bool m_standaloneAuthenticate = false; + private string m_standaloneWelcomeMessage = null; + private string m_standaloneInventoryPlugin; + private string m_standaloneAssetPlugin; + private string m_standaloneUserPlugin; + + private string m_assetStorage = "sqlite"; + + private string m_timedScript = "disabled"; + private Timer m_scriptTimer; + + public ConsoleCommand CreateAccount = null; + private bool m_dumpAssetsToFile; + + private List m_plugins = new List(); + + private IniConfigSource m_config; + + public IniConfigSource ConfigSource + { + get { return m_config; } + set { m_config = value; } + } + + public BaseHttpServer HttpServer + { + get { return m_httpServer; } + } + + private ModuleLoader m_moduleLoader; + + public ModuleLoader ModuleLoader + { + get { return m_moduleLoader; } + set { m_moduleLoader = value; } + } + + public OpenSimMain(IConfigSource configSource) + : base() + { + IConfig startupConfig = configSource.Configs["Startup"]; + + // The Mono addin manager (in Mono.Addins.dll version 0.2.0.0) occasionally seems to corrupt its addin cache + // Hence, as a temporary solution we'll remove it before each startup + if (Directory.Exists("addin-db-000")) + { + Directory.Delete("addin-db-000", true); + } + + AddinManager.Initialize("."); + AddinManager.Registry.Update(null); + + Application.iniFilePath = startupConfig.GetString("inifile", "OpenSim.ini"); + + m_config = new IniConfigSource(); + //check for .INI file (either default or name passed in command line) + if (File.Exists(Application.iniFilePath)) + { + m_config.Merge(new IniConfigSource(Application.iniFilePath)); + m_config.Merge(configSource); + } + else + { + Application.iniFilePath = Path.Combine(Util.configDir(), Application.iniFilePath); + if (File.Exists(Application.iniFilePath)) + { + m_config.Merge(new IniConfigSource(Application.iniFilePath)); + m_config.Merge(configSource); + } + else + { + // no default config files, so set default values, and save it + m_config.Merge(DefaultConfig()); + m_config.Merge(configSource); + m_config.Save(Application.iniFilePath); + } + } + + ReadConfigSettings(); + } + + public static IConfigSource DefaultConfig() + { + IConfigSource DefaultConfig = new IniConfigSource(); + if (DefaultConfig.Configs["Startup"] == null) + DefaultConfig.AddConfig("Startup"); + IConfig config = DefaultConfig.Configs["Startup"]; + if (config != null) + { + config.Set("gridmode", false); + config.Set("physics", "basicphysics"); + config.Set("verbose", true); + config.Set("physical_prim", true); + config.Set("see_into_this_sim_from_neighbor", true); + config.Set("serverside_object_permissions", false); + config.Set("storage_plugin", "OpenSim.Framework.Data.SQLite.dll"); + config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3"); + config.Set("storage_prim_inventories", true); + config.Set("startup_console_commands_file", String.Empty); + config.Set("shutdown_console_commands_file", String.Empty); + config.Set("script_engine", "OpenSim.Region.ScriptEngine.DotNetEngine.dll"); + config.Set("asset_database", "sqlite"); + } + + if (DefaultConfig.Configs["StandAlone"] == null) + DefaultConfig.AddConfig("StandAlone"); + + config = DefaultConfig.Configs["StandAlone"]; + if (config != null) + { + config.Set("accounts_authenticate", false); + config.Set("welcome_message", "Welcome to OpenSim"); + config.Set("inventory_plugin", "OpenSim.Framework.Data.SQLite.dll"); + config.Set("userDatabase_plugin", "OpenSim.Framework.Data.SQLite.dll"); + config.Set("asset_plugin", "OpenSim.Framework.Data.SQLite.dll"); + config.Set("dump_assets_to_file", false); + } + + if (DefaultConfig.Configs["Network"] == null) + DefaultConfig.AddConfig("Network"); + config = DefaultConfig.Configs["Network"]; + if (config != null) + { + config.Set("default_location_x", 1000); + config.Set("default_location_y", 1000); + config.Set("http_listener_port", NetworkServersInfo.DefaultHttpListenerPort); + config.Set("remoting_listener_port", NetworkServersInfo.RemotingListenerPort); + config.Set("grid_server_url", "http://127.0.0.1:" + GridConfig.DefaultHttpPort.ToString()); + config.Set("grid_send_key", "null"); + config.Set("grid_recv_key", "null"); + config.Set("user_server_url", "http://127.0.0.1:" + UserConfig.DefaultHttpPort.ToString()); + config.Set("user_send_key", "null"); + config.Set("user_recv_key", "null"); + config.Set("asset_server_url", "http://127.0.0.1:" + AssetConfig.DefaultHttpPort.ToString()); + config.Set("inventory_server_url", "http://127.0.0.1:" + InventoryConfig.DefaultHttpPort.ToString()); + } + + if (DefaultConfig.Configs["RemoteAdmin"] == null) + DefaultConfig.AddConfig("RemoteAdmin"); + config = DefaultConfig.Configs["RemoteAdmin"]; + if (config != null) + { + config.Set("enabled", "false"); + } + return DefaultConfig; + } + + protected void ReadConfigSettings() + { + m_networkServersInfo = new NetworkServersInfo(); + + IConfig startupConfig = m_config.Configs["Startup"]; + + if (startupConfig != null) + { + m_sandbox = !startupConfig.GetBoolean("gridmode", false); + m_physicsEngine = startupConfig.GetString("physics", "basicphysics"); + m_meshEngineName = startupConfig.GetString("meshing", "ZeroMesher"); + + // TODO: since log4net changes, verbose flag doesn't do anything + m_verbose = startupConfig.GetBoolean("verbose", true); + + m_physicalPrim = startupConfig.GetBoolean("physical_prim", true); + + m_see_into_region_from_neighbor = startupConfig.GetBoolean("see_into_this_sim_from_neighbor", true); + + m_permissions = startupConfig.GetBoolean("serverside_object_permissions", false); + + m_storageDll = startupConfig.GetString("storage_plugin", "OpenSim.Framework.Data.SQLite.dll"); + if (m_storageDll == "OpenSim.DataStore.MonoSqlite.dll") + { + m_storageDll = "OpenSim.Framework.Data.SQLite.dll"; + Console.WriteLine("WARNING: OpenSim.DataStore.MonoSqlite.dll is deprecated. Set storage_plugin to OpenSim.Framework.Data.SQLite.dll."); + Thread.Sleep(3000); + } + m_storageConnectionString + = startupConfig.GetString("storage_connection_string", "URI=file:OpenSim.db,version=3"); + m_storagePersistPrimInventories + = startupConfig.GetBoolean("storage_prim_inventories", true); + + m_startupCommandsFile = startupConfig.GetString("startup_console_commands_file", String.Empty); + m_shutdownCommandsFile = startupConfig.GetString("shutdown_console_commands_file", String.Empty); + + m_scriptEngine = startupConfig.GetString("script_engine", "OpenSim.Region.ScriptEngine.DotNetEngine.dll"); + + m_assetStorage = startupConfig.GetString("asset_database", "sqlite"); + + m_timedScript = startupConfig.GetString("timer_Script", "disabled"); + } + + IConfig standaloneConfig = m_config.Configs["StandAlone"]; + if (standaloneConfig != null) + { + m_standaloneAuthenticate = standaloneConfig.GetBoolean("accounts_authenticate", false); + m_standaloneWelcomeMessage = standaloneConfig.GetString("welcome_message", "Welcome to OpenSim"); + m_standaloneInventoryPlugin = + standaloneConfig.GetString("inventory_plugin", "OpenSim.Framework.Data.SQLite.dll"); + m_standaloneUserPlugin = + standaloneConfig.GetString("userDatabase_plugin", "OpenSim.Framework.Data.SQLite.dll"); + m_standaloneAssetPlugin = + standaloneConfig.GetString("asset_plugin", "OpenSim.Framework.Data.SQLite.dll"); + + m_dumpAssetsToFile = standaloneConfig.GetBoolean("dump_assets_to_file", false); + } + //if (!m_sandbox) + //m_SendChildAgentTaskData = false; + + m_networkServersInfo.loadFromConfiguration(m_config); + } + + /// + /// Performs initialisation of the scene, such as loading configuration from disk. + /// + public override void StartUp() + { + // + // Called from app startup (OpenSim.Application) + // + + m_console = CreateConsole(); + MainConsole.Instance = m_console; + + StatsManager.StartCollectingSimExtraStats(); + + // Do baseclass startup sequence: OpenSim.Region.ClientStack.RegionApplicationBase.StartUp + // TerrainManager, StorageManager, HTTP Server + // This base will call abstract Initialize + base.StartUp(); + + // StandAlone mode? m_sandbox is determined by !startupConfig.GetBoolean("gridmode", false) + if (m_sandbox) + { + LocalInventoryService inventoryService = new LocalInventoryService(); + inventoryService.AddPlugin(m_standaloneInventoryPlugin); + + LocalUserServices userService = + new LocalUserServices(m_networkServersInfo, m_networkServersInfo.DefaultHomeLocX, + m_networkServersInfo.DefaultHomeLocY, inventoryService); + userService.AddPlugin(m_standaloneUserPlugin); + + LocalBackEndServices backendService = new LocalBackEndServices(); + + CommunicationsLocal localComms = + new CommunicationsLocal(m_networkServersInfo, m_httpServer, m_assetCache, userService, + inventoryService, backendService, backendService, m_dumpAssetsToFile); + m_commsManager = localComms; + + m_loginService = + new LocalLoginService(userService, m_standaloneWelcomeMessage, localComms, m_networkServersInfo, + m_standaloneAuthenticate); + m_loginService.OnLoginToRegion += backendService.AddNewSession; + + // XMLRPC action + m_httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod); + + // provides the web form login + m_httpServer.AddHTTPHandler("login", m_loginService.ProcessHTMLLogin); + + // Provides the LLSD login + m_httpServer.SetLLSDHandler(m_loginService.LLSDLoginMethod); + + if (m_standaloneAuthenticate) + { + CreateAccount = localComms.doCreate; + } + } + else + { + // We are in grid mode + m_commsManager = new CommunicationsOGS1(m_networkServersInfo, m_httpServer, m_assetCache); + m_httpServer.AddStreamHandler(new SimStatusHandler()); + } + + // Create a ModuleLoader instance + m_moduleLoader = new ModuleLoader(m_config); + + ExtensionNodeList nodes = AddinManager.GetExtensionNodes("/OpenSim/Startup"); + m_log.InfoFormat("[PLUGINS]: Loading {0} OpenSim application plugins", nodes.Count); + + foreach (TypeExtensionNode node in nodes) + { + IApplicationPlugin plugin = (IApplicationPlugin)node.CreateInstance(); + + plugin.Initialise(this); + m_plugins.Add(plugin); + } + + // Start UDP servers + //for (int i = 0; i < m_udpServers.Count; i++) + //{ + // m_udpServers[i].ServerListener(); + // } + + //Run Startup Commands + if (m_startupCommandsFile != String.Empty) + { + RunCommandScript(m_startupCommandsFile); + } + else + { + m_log.Info("[STARTUP]: No startup command script specified. Moving on..."); + } + + // Start timer script (run a script every xx seconds) + if (m_timedScript != "disabled") + { + m_scriptTimer = new Timer(); + m_scriptTimer.Enabled = true; + m_scriptTimer.Interval = (int)(1200 * 1000); + m_scriptTimer.Elapsed += new ElapsedEventHandler(RunAutoTimerScript); + } + + // We are done with startup + m_log.Info("[STARTUP]: Startup complete, serving " + m_udpServers.Count.ToString() + " region(s)"); + } + + protected override void Initialize() + { + // + // Called from base.StartUp() + // + + m_httpServerPort = m_networkServersInfo.HttpListenerPort; + + IAssetServer assetServer; + if (m_assetStorage == "db4o") + { + assetServer = new LocalAssetServer(); + } + else if (m_assetStorage == "grid") + { + assetServer = new GridAssetClient(m_networkServersInfo.AssetURL); + } + else if (m_assetStorage == "mssql") + { + SQLAssetServer sqlAssetServer = new SQLAssetServer("OpenSim.Framework.Data.MSSQL.dll"); + sqlAssetServer.LoadDefaultAssets(); + assetServer = sqlAssetServer; + //assetServer = new GridAssetClient(String.Empty); + } + else + { + SQLAssetServer sqlAssetServer = new SQLAssetServer(m_standaloneAssetPlugin); + sqlAssetServer.LoadDefaultAssets(); + assetServer = sqlAssetServer; + } + + m_assetCache = new AssetCache(assetServer); + // m_assetCache = new assetCache("OpenSim.Region.GridInterfaces.Local.dll", m_networkServersInfo.AssetURL, m_networkServersInfo.AssetSendKey); + + m_sceneManager.OnRestartSim += handleRestartRegion; + } + + public LLUUID CreateUser(string tempfirstname, string templastname, string tempPasswd, uint regX, uint regY) + { + return m_commsManager.AddUser(tempfirstname,templastname,tempPasswd,regX,regY); + } + + public UDPServer CreateRegion(RegionInfo regionInfo) + { + UDPServer udpServer; + Scene scene = SetupScene(regionInfo, out udpServer, m_permissions); + + m_log.Info("[MODULES]: Loading Region's modules"); + + m_moduleLoader.PickupModules(scene, "."); + //m_moduleLoader.PickupModules(scene, "ScriptEngines"); + //m_moduleLoader.LoadRegionModules(Path.Combine("ScriptEngines", m_scriptEngine), scene); + m_log.Info("[MODULES]: Loading scripting engine modules"); + foreach (string module in m_scriptEngine.Split(',')) + { + string mod = module.Trim(" \t".ToCharArray()); // Clean up name + m_log.Info("[MODULES]: Loading scripting engine: " + mod); + try + { + m_moduleLoader.LoadRegionModules(Path.Combine("ScriptEngines", mod), scene); + } + catch (Exception ex) + { + m_log.Error("[MODULES]: Failed to load script engine: " + ex.ToString()); + } + } + + m_moduleLoader.InitialiseSharedModules(scene); + scene.SetModuleInterfaces(); + + //Server side object editing permissions checking + scene.PermissionsMngr.BypassPermissions = !m_permissions; + + // We need to do this after we've initialized the scripting engines. + scene.StartScripts(); + + m_sceneManager.Add(scene); + + m_udpServers.Add(udpServer); + m_regionData.Add(regionInfo); + udpServer.ServerListener(); + + return udpServer; + } + + private static void CreateDefaultRegionInfoXml(string fileName) + { + new RegionInfo("DEFAULT REGION CONFIG", fileName,false); + } + + protected override StorageManager CreateStorageManager(string connectionstring) + { + return new StorageManager(m_storageDll, connectionstring, m_storagePersistPrimInventories); + } + + protected override Scene CreateScene(RegionInfo regionInfo, StorageManager storageManager, + AgentCircuitManager circuitManager) + { + PermissionManager permissionManager = new PermissionManager(); + SceneCommunicationService sceneGridService = new SceneCommunicationService(m_commsManager); + return + new Scene(regionInfo, circuitManager, permissionManager, m_commsManager, sceneGridService, m_assetCache, + storageManager, m_httpServer, + m_moduleLoader, m_dumpAssetsToFile, m_physicalPrim, m_see_into_region_from_neighbor); + } + + + public void handleRestartRegion(RegionInfo whichRegion) + { + m_log.Error("[MAIN]: Got restart signal from SceneManager"); + // Shutting down the UDP server + bool foundUDPServer = false; + int UDPServerElement = 0; + + for (int i = 0; i < m_udpServers.Count; i++) + { + if (m_udpServers[i].RegionHandle == whichRegion.RegionHandle) + { + UDPServerElement = i; + foundUDPServer = true; + break; + } + } + if (foundUDPServer) + { + // m_udpServers[UDPServerElement].Server.End + m_udpServers[UDPServerElement].Server.Close(); + m_udpServers.RemoveAt(UDPServerElement); + } + + //Removing the region from the sim's database of regions.. + int RegionHandleElement = -1; + for (int i = 0; i < m_regionData.Count; i++) + { + if (whichRegion.RegionHandle == m_regionData[i].RegionHandle) + { + RegionHandleElement = i; + } + } + if (RegionHandleElement >= 0) + { + m_regionData.RemoveAt(RegionHandleElement); + } + + CreateRegion(whichRegion); + //UDPServer restartingRegion = CreateRegion(whichRegion); + //restartingRegion.ServerListener(); + //m_sceneManager.SendSimOnlineNotification(restartingRegion.RegionHandle); + } + + protected override ConsoleBase CreateConsole() + { + return new ConsoleBase("Region", this); + } + + # region Setup methods + + protected override PhysicsScene GetPhysicsScene() + { + return GetPhysicsScene(m_physicsEngine, m_meshEngineName); + } + + private class SimStatusHandler : IStreamedRequestHandler + { + public byte[] Handle(string path, Stream request) + { + return Encoding.UTF8.GetBytes("OK"); + } + + public string ContentType + { + get { return "text/plain"; } + } + + public string HttpMethod + { + get { return "GET"; } + } + + public string Path + { + get { return "/simstatus/"; } + } + } + + #endregion + + /// + /// Performs any last-minute sanity checking and shuts down the region server + /// + public virtual void Shutdown() + { + if (m_startupCommandsFile != String.Empty) + { + RunCommandScript(m_shutdownCommandsFile); + } + + m_log.Info("[SHUTDOWN]: Closing all threads"); + m_log.Info("[SHUTDOWN]: Killing listener thread"); + m_log.Info("[SHUTDOWN]: Killing clients"); + // TODO: implement this + m_log.Info("[SHUTDOWN]: Closing console and terminating"); + + m_sceneManager.Close(); + + m_console.Close(); + Environment.Exit(0); + } + + private void RunAutoTimerScript(object sender, EventArgs e) + { + if (m_timedScript != "disabled") + { + RunCommandScript(m_timedScript); + } + } + + #region Console Commands + + /// + /// + /// + /// + private void RunCommandScript(string fileName) + { + m_log.Info("[COMMANDFILE]: Running " + fileName); + if (File.Exists(fileName)) + { + StreamReader readFile = File.OpenText(fileName); + string currentCommand = String.Empty; + while ((currentCommand = readFile.ReadLine()) != null) + { + if (currentCommand != String.Empty) + { + m_log.Info("[COMMANDFILE]: Running '" + currentCommand + "'"); + m_console.RunCommand(currentCommand); + } + } + } + else + { + m_log.Error("[COMMANDFILE]: Command script missing. Can not run commands"); + } + } + + /// + /// Runs commands issued by the server console from the operator + /// + /// The first argument of the parameter (the command) + /// Additional arguments passed to the command + public override void RunCmd(string command, string[] cmdparams) + { + base.RunCmd(command, cmdparams); + + switch (command) + { + case "clear-assets": + m_assetCache.Clear(); + break; + + case "set-time": + m_sceneManager.SetCurrentSceneTimePhase(Convert.ToInt32(cmdparams[0])); + break; + + case "force-update": + m_console.Notice("Updating all clients"); + m_sceneManager.ForceCurrentSceneClientUpdate(); + break; + + case "edit-scale": + if (cmdparams.Length == 4) + { + m_sceneManager.HandleEditCommandOnCurrentScene(cmdparams); + } + break; + + case "debug": + if (cmdparams.Length > 0) + { + Debug(cmdparams); + } + break; + + case "scene-debug": + if (cmdparams.Length == 3) { + if (m_sceneManager.CurrentScene == null) { + m_console.Error("CONSOLE", "Please use 'change-region ' first"); + } else { + m_sceneManager.CurrentScene.SetSceneCoreDebug(!System.Convert.ToBoolean(cmdparams[0]), !System.Convert.ToBoolean(cmdparams[1]), !System.Convert.ToBoolean(cmdparams[2])); + } + } else { + m_console.Error("scene-debug (where inside <> is true/false)"); + } + break; + + case "help": + m_console.Notice("alert - send alert to a designated user or all users."); + m_console.Notice(" alert [First] [Last] [Message] - send an alert to a user. Case sensitive."); + m_console.Notice(" alert general [Message] - send an alert to all users."); + m_console.Notice("backup - trigger a simulator backup"); + m_console.Notice("clear-assets - clear asset cache"); + m_console.Notice("create user - adds a new user"); + m_console.Notice("change-region [name] - sets the region that many of these commands affect."); + m_console.Notice("command-script [filename] - Execute command in a file."); + m_console.Notice("debug - debugging commands"); + m_console.Notice(" packet 0..255 - print incoming/outgoing packets (0=off)"); + m_console.Notice("scene-debug [scripting] [collision] [physics] - Enable/Disable debug stuff, each can be True/False"); + m_console.Notice("edit-scale [prim name] [x] [y] [z] - resize given prim"); + m_console.Notice("export-map [filename] - save image of world map"); + m_console.Notice("force-update - force an update of prims in the scene"); + m_console.Notice("load-xml [filename] - load prims from XML"); + m_console.Notice("load-xml2 [filename] - load prims from XML using version 2 format"); + m_console.Notice("permissions [true/false] - turn on/off permissions on the scene"); + m_console.Notice("quit - equivalent to shutdown."); + m_console.Notice("restart - disconnects all clients and restarts the sims in the instance."); + m_console.Notice("remove-region [name] - remove a region"); + m_console.Notice("save-xml [filename] - save prims to XML"); + m_console.Notice("save-xml2 [filename] - save prims to XML using version 2 format"); + m_console.Notice("script - manually trigger scripts? or script commands?"); + m_console.Notice("set-time [x] - set the current scene time phase"); + m_console.Notice("show assets - show state of asset cache."); + m_console.Notice("show users - show info about connected users."); + m_console.Notice("show modules - shows info about loaded modules."); + m_console.Notice("show stats - statistical information for this server not displayed in the client"); + m_console.Notice("shutdown - disconnect all clients and shutdown."); + m_console.Notice("config set section field value - set a config value"); + m_console.Notice("config get section field - get a config value"); + m_console.Notice("config save - save OpenSim.ini"); + m_console.Notice("terrain help - show help for terrain commands."); + break; + + case "save-xml": + if (cmdparams.Length > 0) + { + m_sceneManager.SaveCurrentSceneToXml(cmdparams[0]); + } + else + { + m_sceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME); + } + break; + + case "load-xml": + LLVector3 loadOffset = new LLVector3(0, 0, 0); + if (cmdparams.Length > 0) + { + bool generateNewIDS = false; + if (cmdparams.Length > 1) + { + if (cmdparams[1] == "-newUID") + { + generateNewIDS = true; + } + if (cmdparams.Length > 2) + { + loadOffset.X = (float) Convert.ToDecimal(cmdparams[2]); + if (cmdparams.Length > 3) + { + loadOffset.Y = (float) Convert.ToDecimal(cmdparams[3]); + } + if (cmdparams.Length > 4) + { + loadOffset.Z = (float) Convert.ToDecimal(cmdparams[4]); + } + m_console.Error("loadOffsets = <" + loadOffset.X + "," + loadOffset.Y + "," + + loadOffset.Z + ">"); + } + } + m_sceneManager.LoadCurrentSceneFromXml(cmdparams[0], generateNewIDS, loadOffset); + } + else + { + m_sceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset); + } + break; + + case "save-xml2": + if (cmdparams.Length > 0) + { + m_sceneManager.SaveCurrentSceneToXml2(cmdparams[0]); + } + else + { + m_sceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME); + } + break; + + case "load-xml2": + if (cmdparams.Length > 0) + { + m_sceneManager.LoadCurrentSceneFromXml2(cmdparams[0]); + } + else + { + m_sceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME); + } + break; + + case "terrain": + string result = String.Empty; + + if (!m_sceneManager.RunTerrainCmdOnCurrentScene(cmdparams, ref result)) + { + m_console.Error(result); + } + break; + + case "script": + m_sceneManager.SendCommandToCurrentSceneScripts(cmdparams); + break; + + case "command-script": + if (cmdparams.Length > 0) + { + RunCommandScript(cmdparams[0]); + } + break; + + case "permissions": + // Treats each user as a super-admin when disabled + bool permissions = Convert.ToBoolean(cmdparams[0]); + m_sceneManager.SetBypassPermissionsOnCurrentScene(!permissions); + break; + + case "backup": + m_sceneManager.BackupCurrentScene(); + break; + + case "alert": + m_sceneManager.HandleAlertCommandOnCurrentScene(cmdparams); + break; + + case "create": + if (CreateAccount != null) + { + CreateAccount(cmdparams); + } + break; + + case "create-region": + CreateRegion(new RegionInfo(cmdparams[0], "Regions/" + cmdparams[1],false)); + break; + + case "remove-region": + string regName = CombineParams(cmdparams, 0); + + Scene killScene; + if (m_sceneManager.TryGetScene(regName, out killScene)) + { + if (m_sceneManager.CurrentScene.RegionInfo.RegionID == killScene.RegionInfo.RegionID) + { + m_sceneManager.TrySetCurrentScene(".."); + } + m_regionData.Remove(killScene.RegionInfo); + m_sceneManager.CloseScene(killScene); + } + break; + + case "quit": + case "shutdown": + Shutdown(); + break; + + case "restart": + m_sceneManager.RestartCurrentScene(); + break; + + case "change-region": + if (cmdparams.Length > 0) + { + string regionName = CombineParams(cmdparams, 0); + + if (!m_sceneManager.TrySetCurrentScene(regionName)) + { + m_console.Error("Couldn't set current region to: " + regionName); + } + } + + if (m_sceneManager.CurrentScene == null) + { + m_console.Error("CONSOLE", "Currently at Root level. To change region please use 'change-region '"); + } + else + { + m_console.Error("CONSOLE", "Current Region: " + m_sceneManager.CurrentScene.RegionInfo.RegionName + + ". To change region please use 'change-region '"); + } + + break; + + case "export-map": + if (cmdparams.Length > 0) + { + m_sceneManager.CurrentOrFirstScene.ExportWorldMap(cmdparams[0]); + } + else + { + m_sceneManager.CurrentOrFirstScene.ExportWorldMap("exportmap.jpg"); + } + break; + + case "config": + string n = command.ToUpper(); + if (cmdparams.Length > 0) + { + switch (cmdparams[0].ToLower()) + { + case "set": + if (cmdparams.Length < 4) + { + m_console.Error(n, "SYNTAX: " + n + " SET SECTION KEY VALUE"); + m_console.Error(n, "EXAMPLE: " + n + " SET ScriptEngine.DotNetEngine NumberOfScriptThreads 5"); + } + else + { + IConfig c = DefaultConfig().Configs[cmdparams[1]]; + if (c == null) + c = DefaultConfig().AddConfig(cmdparams[1]); + string _value = String.Join(" ", cmdparams, 3, cmdparams.Length - 3); + c.Set(cmdparams[2], _value); + m_config.Merge(c.ConfigSource); + + m_console.Error(n, n + " " + n + " " + cmdparams[1] + " " + cmdparams[2] + " " + + _value); + } + break; + case "get": + if (cmdparams.Length < 3) + { + m_console.Error(n, "SYNTAX: " + n + " GET SECTION KEY"); + m_console.Error(n, "EXAMPLE: " + n + " GET ScriptEngine.DotNetEngine NumberOfScriptThreads"); + } + else + { + IConfig c = DefaultConfig().Configs[cmdparams[1]]; + if (c == null) + { + m_console.Notice(n, "Section \"" + cmdparams[1] + "\" does not exist."); + break; + } + else + { + m_console.Notice(n + " GET " + cmdparams[1] + " " + cmdparams[2] + ": " + + c.GetString(cmdparams[2])); + } + } + + break; + case "save": + m_console.Notice("Saving configuration file: " + Application.iniFilePath); + m_config.Save(Application.iniFilePath); + break; + } + } + break; + case "modules": + if (cmdparams.Length > 0) + { + switch (cmdparams[0].ToLower()) + { + case "list": + foreach (IRegionModule irm in m_moduleLoader.GetLoadedSharedModules) + { + m_console.Notice("Shared region module: " + irm.Name); + } + break; + case "unload": + if (cmdparams.Length > 1) + { + foreach (IRegionModule rm in new System.Collections.ArrayList(m_moduleLoader.GetLoadedSharedModules)) + { + if (rm.Name.ToLower() == cmdparams[1].ToLower()) + { + m_console.Notice("Unloading module: " + rm.Name); + m_moduleLoader.UnloadModule(rm); + } + } + } + break; + case "load": + if (cmdparams.Length > 1) + { + foreach (Scene s in new System.Collections.ArrayList(m_sceneManager.Scenes)) + { + + m_console.Notice("Loading module: " + cmdparams[1]); + m_moduleLoader.LoadRegionModules(cmdparams[1], s); + } + } + break; + } + } + + break; + /* + * Temporarily disabled but it would be good to have this - needs to be levered + * in to BaseOpenSimServer (which requires a RunCmd method restrcuture probably) + default: + m_console.Error("Unknown command"); + break; + */ + } + } + + public void Debug(string[] args) + { + switch (args[0]) + { + case "packet": + if (args.Length > 1) + { + int newDebug; + if (int.TryParse(args[1], out newDebug)) + { + m_sceneManager.SetDebugPacketOnCurrentScene(newDebug); + } + else + { + m_console.Error("packet debug should be 0..2"); + } + m_console.Notice("New packet debug: " + newDebug.ToString()); + } + + break; + default: + m_console.Error("Unknown debug"); + break; + } + } + + // see BaseOpenSimServer + public override void Show(string ShowWhat) + { + base.Show(ShowWhat); + + switch (ShowWhat) + { + case "assets": + m_assetCache.ShowState(); + break; + + case "users": + m_console.Notice( + String.Format("{0,-16}{1,-16}{2,-37}{3,-16}{4,-22}{5,-16}", "Firstname", "Lastname", + "Agent ID", "Circuit", "IP", "Region")); + + foreach (ScenePresence presence in m_sceneManager.GetCurrentSceneAvatars()) + { + RegionInfo regionInfo = m_sceneManager.GetRegionInfo(presence.RegionHandle); + string regionName; + System.Net.EndPoint ep = null; + + if (regionInfo == null) + { + regionName = "Unresolvable"; + } + else + { + regionName = regionInfo.RegionName; + } + + for (int i = 0; i < m_udpServers.Count; i++) + { + if (m_udpServers[i].RegionHandle == presence.RegionHandle) + { + + m_udpServers[i].clientCircuits_reverse.TryGetValue(presence.ControllingClient.CircuitCode, out ep); + } + } + + m_console.Notice( + String.Format("{0,-16}{1,-16}{2,-37}{3,-16}{4,-22}{5,-16}", + presence.Firstname, + presence.Lastname, + presence.UUID, + presence.ControllingClient.CircuitCode, + ep, + regionName)); + } + + break; + case "modules": + m_console.Notice("The currently loaded shared modules are:"); + foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules) + { + m_console.Notice("Shared Module: " + module.Name); + } + break; + + case "regions": + m_sceneManager.ForEachScene( + delegate(Scene scene) + { + m_console.Notice("Region Name: " + scene.RegionInfo.RegionName + " , Region XLoc: " + + scene.RegionInfo.RegionLocX + " , Region YLoc: " + + scene.RegionInfo.RegionLocY); + }); + break; + + case "stats": + if (StatsManager.SimExtraStats != null) + { + m_console.Notice( + "STATS", Environment.NewLine + StatsManager.SimExtraStats.Report()); + } + else + { + m_console.Notice("Extra sim statistics collection has not been enabled"); + } + break; + } + } + + private string CombineParams(string[] commandParams, int pos) + { + string result = String.Empty; + for (int i = pos; i < commandParams.Length; i++) + { + result += commandParams[i] + " "; + } + result = result.TrimEnd(' '); + return result; + } + + #endregion + } +} diff --git a/trunk/OpenSim/Region/Application/VersionInfo.cs b/trunk/OpenSim/Region/Application/VersionInfo.cs new file mode 100644 index 0000000000..b140bc8bfb --- /dev/null +++ b/trunk/OpenSim/Region/Application/VersionInfo.cs @@ -0,0 +1,36 @@ +/* +* 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. +* +*/ +namespace OpenSim +{ + /// + /// + public class VersionInfo + { + public static string Version = "0.5, SVN build "; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ClientStack/ClientStackNetworkHandler.cs b/trunk/OpenSim/Region/ClientStack/ClientStackNetworkHandler.cs new file mode 100644 index 0000000000..b3af1cc9e1 --- /dev/null +++ b/trunk/OpenSim/Region/ClientStack/ClientStackNetworkHandler.cs @@ -0,0 +1,38 @@ +/* +* 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.Net.Sockets; + +namespace OpenSim.Region.ClientStack +{ + public interface ClientStackNetworkHandler + { + void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode); // EndPoint packetSender); + void RemoveClientCircuit(uint circuitcode); + void RegisterPacketServer(PacketServer server); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ClientStack/ClientView.cs b/trunk/OpenSim/Region/ClientStack/ClientView.cs new file mode 100644 index 0000000000..5c179be522 --- /dev/null +++ b/trunk/OpenSim/Region/ClientStack/ClientView.cs @@ -0,0 +1,3848 @@ +/* +* 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; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Timers; +using Axiom.Math; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Scenes; +using Timer = System.Timers.Timer; + +namespace OpenSim.Region.ClientStack +{ + public delegate bool PacketMethod(IClientAPI simClient, Packet packet); + + /// + /// Handles new client connections + /// Constructor takes a single Packet and authenticates everything + /// + public class ClientView : IClientAPI + { +// ~ClientView() +// { +// System.Console.WriteLine("[CLIENTVIEW]: Destructor called"); +// } + + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /* static variables */ + public static TerrainManager TerrainManager; + + /* private variables */ + private readonly LLUUID m_sessionId; + private LLUUID m_secureSessionId = LLUUID.Zero; + //private AgentAssetUpload UploadAssets; + private int m_debug = 0; + private readonly AssetCache m_assetCache; + // private InventoryCache m_inventoryCache; + private int m_cachedTextureSerial = 0; + private Timer m_clientPingTimer; + + private int m_packetsReceived = 0; + private int m_lastPacketsReceivedSentToScene = 0; + private int m_unAckedBytes = 0; + + private int m_packetsSent = 0; + private int m_lastPacketsSentSentToScene = 0; + + private int m_probesWithNoIngressPackets = 0; + private int m_lastPacketsReceived = 0; + private byte[] ZeroOutBuffer = new byte[4096]; + + private readonly Encoding m_encoding = Encoding.ASCII; + private readonly LLUUID m_agentId; + private readonly uint m_circuitCode; + private int m_moneyBalance; + + private byte[] m_channelVersion = Helpers.StringToField("OpenSimulator 0.5"); // Dummy value needed by libSL + + /* protected variables */ + + protected static Dictionary PacketHandlers = + new Dictionary(); //Global/static handlers for all clients + + protected Dictionary m_packetHandlers = new Dictionary(); + + protected IScene m_scene; + protected AgentCircuitManager m_authenticateSessionsHandler; + + protected PacketQueue m_packetQueue; + + protected Dictionary m_pendingAcks = new Dictionary(); + protected Dictionary m_needAck = new Dictionary(); + + protected Timer m_ackTimer; + protected uint m_sequence = 0; + protected object m_sequenceLock = new object(); + protected const int MAX_APPENDED_ACKS = 10; + protected const int RESEND_TIMEOUT = 4000; + protected const int MAX_SEQUENCE = 0xFFFFFF; + protected PacketServer m_networkServer; + + /* public variables */ + protected string m_firstName; + protected string m_lastName; + protected Thread m_clientThread; + protected LLVector3 m_startpos; + protected EndPoint m_userEndPoint; + + /* Properties */ + + public LLUUID SecureSessionId + { + get { return m_secureSessionId; } + } + + public IScene Scene + { + get { return m_scene; } + } + + public LLUUID SessionId + { + get { return m_sessionId; } + } + + public LLVector3 StartPos + { + get { return m_startpos; } + set { m_startpos = value; } + } + + public LLUUID AgentId + { + get { return m_agentId; } + } + + /// + /// This is a utility method used by single states to not duplicate kicks and blue card of death messages. + /// + public bool ChildAgentStatus() + { + return m_scene.PresenceChildStatus(AgentId); + } + + /// + /// First name of the agent/avatar represented by the client + /// + public string FirstName + { + get { return m_firstName; } + } + + /// + /// Last name of the agent/avatar represented by the client + /// + public string LastName + { + get { return m_lastName; } + } + + /// + /// Full name of the client (first name and last name) + /// + public string Name + { + get { return FirstName + " " + LastName; } + } + + public uint CircuitCode + { + get { return m_circuitCode; } + } + + public int MoneyBalance + { + get { return m_moneyBalance; } + } + + /* METHODS */ + + public ClientView(EndPoint remoteEP, IScene scene, AssetCache assetCache, PacketServer packServer, + AgentCircuitManager authenSessions, LLUUID agentId, LLUUID sessionId, uint circuitCode) + { + m_moneyBalance = 1000; + + m_channelVersion = Helpers.StringToField(scene.GetSimulatorVersion()); + + m_scene = scene; + m_assetCache = assetCache; + + m_networkServer = packServer; + // m_inventoryCache = inventoryCache; + m_authenticateSessionsHandler = authenSessions; + + m_log.Info("[CLIENT]: Started up new client thread to handle incoming request"); + + m_agentId = agentId; + m_sessionId = sessionId; + m_circuitCode = circuitCode; + + m_userEndPoint = remoteEP; + + m_startpos = m_authenticateSessionsHandler.GetPosition(circuitCode); + + // While working on this, the BlockingQueue had me fooled for a bit. + // The Blocking queue causes the thread to stop until there's something + // in it to process. It's an on-purpose threadlock though because + // without it, the clientloop will suck up all sim resources. + + m_packetQueue = new PacketQueue(); + + RegisterLocalPacketHandlers(); + + m_clientThread = new Thread(new ThreadStart(AuthUser)); + m_clientThread.IsBackground = true; + m_clientThread.Start(); + } + + public void SetDebug(int newDebug) + { + m_debug = newDebug; + } + + # region Client Methods + + private void CloseCleanup() + { + m_scene.RemoveClient(AgentId); + + //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); + //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true)); + + // Send the STOP packet + DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); + OutPacket(disable, ThrottleOutPacketType.Task); + + + // FLUSH Packets + m_packetQueue.Close(); + m_packetQueue.Flush(); + + Thread.Sleep(2000); + + + // Shut down timers + m_ackTimer.Stop(); + m_clientPingTimer.Stop(); + + // This is just to give the client a reasonable chance of + // flushing out all it's packets. There should probably + // be a better mechanism here + + // We can't reach into other scenes and close the connection + // We need to do this over grid communications + //m_scene.CloseAllAgents(CircuitCode); + + m_clientThread.Abort(); + } + + /// + /// Close down the client view. This *must* be the last method called, since the last # + /// statement of CloseCleanup() aborts the thread. + /// + /// + public void Close(bool ShutdownCircult) + { + // Pull Client out of Region + m_log.Info("[CLIENT]: Close has been called"); + + //raiseevent on the packet server to Shutdown the circuit + if (ShutdownCircult) + OnConnectionClosed(this); + + CloseCleanup(); + } + + public void Kick(string message) + { + if (!ChildAgentStatus()) + { + KickUserPacket kupack = (KickUserPacket)PacketPool.Instance.GetPacket(PacketType.KickUser); + kupack.UserInfo.AgentID = AgentId; + kupack.UserInfo.SessionID = SessionId; + kupack.TargetBlock.TargetIP = (uint)0; + kupack.TargetBlock.TargetPort = (ushort)0; + kupack.UserInfo.Reason = Helpers.StringToField(message); + OutPacket(kupack, ThrottleOutPacketType.Task); + } + } + + public void Stop() + { + m_log.Info("[BUG]: Stop called, please find out where and remove it"); + } + + #endregion + + # region Packet Handling + + public static bool AddPacketHandler(PacketType packetType, PacketMethod handler) + { + bool result = false; + lock (PacketHandlers) + { + if (!PacketHandlers.ContainsKey(packetType)) + { + PacketHandlers.Add(packetType, handler); + result = true; + } + } + return result; + } + + public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler) + { + bool result = false; + lock (m_packetHandlers) + { + if (!m_packetHandlers.ContainsKey(packetType)) + { + m_packetHandlers.Add(packetType, handler); + result = true; + } + } + return result; + } + + protected virtual bool ProcessPacketMethod(Packet packet) + { + bool result = false; + bool found = false; + PacketMethod method; + if (m_packetHandlers.TryGetValue(packet.Type, out method)) + { + //there is a local handler for this packet type + result = method(this, packet); + } + else + { + //there is not a local handler so see if there is a Global handler + lock (PacketHandlers) + { + found = PacketHandlers.TryGetValue(packet.Type, out method); + } + if (found) + { + result = method(this, packet); + } + } + return result; + } + + protected void DebugPacket(string direction, Packet packet) + { + if (m_debug > 0) + { + string info = String.Empty; + + if (m_debug < 255 && packet.Type == PacketType.AgentUpdate) + return; + if (m_debug < 254 && packet.Type == PacketType.ViewerEffect) + return; + if (m_debug < 253 && ( + packet.Type == PacketType.CompletePingCheck || + packet.Type == PacketType.StartPingCheck + )) + return; + if (m_debug < 252 && packet.Type == PacketType.PacketAck) + return; + + if (m_debug > 1) + { + info = packet.ToString(); + } + else + { + info = packet.Type.ToString(); + } + Console.WriteLine(m_circuitCode + ":" + direction + ": " + info); + } + } + + protected virtual void ClientLoop() + { + m_log.Info("[CLIENT]: Entered loop"); + while (true) + { + QueItem nextPacket = m_packetQueue.Dequeue(); + if (nextPacket.Incoming) + { + if (nextPacket.Packet.Type != PacketType.AgentUpdate) + { + m_packetsReceived++; + } + DebugPacket("IN", nextPacket.Packet); + ProcessInPacket(nextPacket.Packet); + } + else + { + DebugPacket("OUT", nextPacket.Packet); + ProcessOutPacket(nextPacket.Packet); + } + } + } + + # endregion + + protected void CheckClientConnectivity(object sender, ElapsedEventArgs e) + { + if (m_packetsReceived == m_lastPacketsReceived) + { + m_probesWithNoIngressPackets++; + if (m_probesWithNoIngressPackets > 30) + { + if (OnConnectionClosed != null) + { + OnConnectionClosed(this); + } + } + else + { + // this will normally trigger at least one packet (ping response) + SendStartPingCheck(0); + + } + } + else + { + // Something received in the meantime - we can reset the counters + m_probesWithNoIngressPackets = 0; + m_lastPacketsReceived = m_packetsReceived; + + } + //SendPacketStats(); + } + + # region Setup + + protected virtual void InitNewClient() + { + //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache); + + // Establish our two timers. We could probably get this down to one + m_ackTimer = new Timer(750); + m_ackTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed); + m_ackTimer.Start(); + + m_clientPingTimer = new Timer(5000); + m_clientPingTimer.Elapsed += new ElapsedEventHandler(CheckClientConnectivity); + m_clientPingTimer.Enabled = true; + + m_log.Info("[CLIENT]: Adding viewer agent to scene"); + m_scene.AddNewClient(this, true); + } + + protected virtual void AuthUser() + { + // AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(m_cirpack.m_circuitCode.m_sessionId, m_cirpack.m_circuitCode.ID, m_cirpack.m_circuitCode.Code); + AuthenticateResponse sessionInfo = + m_authenticateSessionsHandler.AuthenticateSession(m_sessionId, m_agentId, + m_circuitCode); + if (!sessionInfo.Authorised) + { + //session/circuit not authorised + m_log.Info("[CLIENT]: New user request denied to " + m_userEndPoint.ToString()); + m_packetQueue.Flush(); + m_packetQueue.Close(); + m_clientThread.Abort(); + } + else + { + m_log.Info("[CLIENT]: Got authenticated connection from " + m_userEndPoint.ToString()); + //session is authorised + m_firstName = sessionInfo.LoginInfo.First; + m_lastName = sessionInfo.LoginInfo.Last; + + if (sessionInfo.LoginInfo.SecureSession != LLUUID.Zero) + { + m_secureSessionId = sessionInfo.LoginInfo.SecureSession; + } + // This sets up all the timers + InitNewClient(); + + ClientLoop(); + } + } + + # endregion + + // Previously ClientView.API partial class + public event Action OnLogout; + public event ObjectPermissions OnObjectPermissions; + + public event Action OnConnectionClosed; + public event ViewerEffectEventHandler OnViewerEffect; + public event ImprovedInstantMessage OnInstantMessage; + public event ChatFromViewer OnChatFromViewer; + public event TextureRequest OnRequestTexture; + public event RezObject OnRezObject; + public event GenericCall4 OnDeRezObject; + public event ModifyTerrain OnModifyTerrain; + public event Action OnRegionHandShakeReply; + public event GenericCall2 OnRequestWearables; + public event SetAppearance OnSetAppearance; + public event AvatarNowWearing OnAvatarNowWearing; + public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; + public event ObjectAttach OnObjectAttach; + public event GenericCall2 OnCompleteMovementToRegion; + public event UpdateAgent OnAgentUpdate; + public event AgentRequestSit OnAgentRequestSit; + public event AgentSit OnAgentSit; + public event AvatarPickerRequest OnAvatarPickerRequest; + public event StartAnim OnStartAnim; + public event StopAnim OnStopAnim; + public event Action OnRequestAvatarsData; + public event LinkObjects OnLinkObjects; + public event DelinkObjects OnDelinkObjects; + public event UpdateVector OnGrabObject; + public event ObjectSelect OnDeGrabObject; + public event ObjectDuplicate OnObjectDuplicate; + public event MoveObject OnGrabUpdate; + public event AddNewPrim OnAddPrim; + public event RequestGodlikePowers OnRequestGodlikePowers; + public event GodKickUser OnGodKickUser; + public event ObjectExtraParams OnUpdateExtraParams; + public event UpdateShape OnUpdatePrimShape; + public event ObjectSelect OnObjectSelect; + public event ObjectDeselect OnObjectDeselect; + public event GenericCall7 OnObjectDescription; + public event GenericCall7 OnObjectName; + public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; + public event UpdatePrimFlags OnUpdatePrimFlags; + public event UpdatePrimTexture OnUpdatePrimTexture; + public event UpdateVector OnUpdatePrimGroupPosition; + public event UpdateVector OnUpdatePrimSinglePosition; + public event UpdatePrimRotation OnUpdatePrimGroupRotation; + public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation; + public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; + public event UpdateVector OnUpdatePrimScale; + public event StatusChange OnChildAgentStatus; + public event GenericCall2 OnStopMovement; + public event Action OnRemoveAvatar; + public event RequestMapBlocks OnRequestMapBlocks; + public event RequestMapName OnMapNameRequest; + public event TeleportLocationRequest OnTeleportLocationRequest; + public event DisconnectUser OnDisconnectUser; + public event RequestAvatarProperties OnRequestAvatarProperties; + public event SetAlwaysRun OnSetAlwaysRun; + + public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event CreateInventoryFolder OnCreateNewInventoryFolder; + public event UpdateInventoryFolder OnUpdateInventoryFolder; + public event MoveInventoryFolder OnMoveInventoryFolder; + public event FetchInventoryDescendents OnFetchInventoryDescendents; + public event PurgeInventoryDescendents OnPurgeInventoryDescendents; + public event FetchInventory OnFetchInventory; + public event RequestTaskInventory OnRequestTaskInventory; + public event UpdateInventoryItem OnUpdateInventoryItem; + public event CopyInventoryItem OnCopyInventoryItem; + public event MoveInventoryItem OnMoveInventoryItem; + public event RemoveInventoryItem OnRemoveInventoryItem; + public event RemoveInventoryFolder OnRemoveInventoryFolder; + public event UDPAssetUploadRequest OnAssetUploadRequest; + public event XferReceive OnXferReceive; + public event RequestXfer OnRequestXfer; + public event ConfirmXfer OnConfirmXfer; + public event RezScript OnRezScript; + public event UpdateTaskInventory OnUpdateTaskInventory; + public event RemoveTaskInventory OnRemoveTaskItem; + + public event UUIDNameRequest OnNameFromUUIDRequest; + + public event ParcelAccessListRequest OnParcelAccessListRequest; + public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest; + public event ParcelPropertiesRequest OnParcelPropertiesRequest; + public event ParcelDivideRequest OnParcelDivideRequest; + public event ParcelJoinRequest OnParcelJoinRequest; + public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; + public event ParcelSelectObjects OnParcelSelectObjects; + public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest; + public event EstateOwnerMessageRequest OnEstateOwnerMessage; + public event RegionInfoRequest OnRegionInfoRequest; + public event EstateCovenantRequest OnEstateCovenantRequest; + + public event FriendActionDelegate OnApproveFriendRequest; + public event FriendActionDelegate OnDenyFriendRequest; + public event FriendshipTermination OnTerminateFriendship; + + public event PacketStats OnPacketStats; + + public event MoneyTransferRequest OnMoneyTransferRequest; + + public event MoneyBalanceRequest OnMoneyBalanceRequest; + + + #region Scene/Avatar to Client + + /// + /// + /// + /// + public void SendRegionHandshake(RegionInfo regionInfo) + { + RegionHandshakePacket handshake = (RegionHandshakePacket)PacketPool.Instance.GetPacket(PacketType.RegionHandshake); + + bool estatemanager = false; + LLUUID[] EstateManagers = regionInfo.EstateSettings.estateManagers; + for (int i = 0; i < EstateManagers.Length; i++) + { + if (EstateManagers[i] == AgentId) + estatemanager = true; + } + + handshake.RegionInfo.BillableFactor = regionInfo.EstateSettings.billableFactor; + handshake.RegionInfo.IsEstateManager = estatemanager; + handshake.RegionInfo.TerrainHeightRange00 = regionInfo.EstateSettings.terrainHeightRange0; + handshake.RegionInfo.TerrainHeightRange01 = regionInfo.EstateSettings.terrainHeightRange1; + handshake.RegionInfo.TerrainHeightRange10 = regionInfo.EstateSettings.terrainHeightRange2; + handshake.RegionInfo.TerrainHeightRange11 = regionInfo.EstateSettings.terrainHeightRange3; + handshake.RegionInfo.TerrainStartHeight00 = regionInfo.EstateSettings.terrainStartHeight0; + handshake.RegionInfo.TerrainStartHeight01 = regionInfo.EstateSettings.terrainStartHeight1; + handshake.RegionInfo.TerrainStartHeight10 = regionInfo.EstateSettings.terrainStartHeight2; + handshake.RegionInfo.TerrainStartHeight11 = regionInfo.EstateSettings.terrainStartHeight3; + handshake.RegionInfo.SimAccess = (byte)regionInfo.EstateSettings.simAccess; + handshake.RegionInfo.WaterHeight = regionInfo.EstateSettings.waterHeight; + + handshake.RegionInfo.RegionFlags = (uint)regionInfo.EstateSettings.regionFlags; + handshake.RegionInfo.SimName = Helpers.StringToField(regionInfo.RegionName); + handshake.RegionInfo.SimOwner = regionInfo.MasterAvatarAssignedUUID; + handshake.RegionInfo.TerrainBase0 = regionInfo.EstateSettings.terrainBase0; + handshake.RegionInfo.TerrainBase1 = regionInfo.EstateSettings.terrainBase1; + handshake.RegionInfo.TerrainBase2 = regionInfo.EstateSettings.terrainBase2; + handshake.RegionInfo.TerrainBase3 = regionInfo.EstateSettings.terrainBase3; + handshake.RegionInfo.TerrainDetail0 = regionInfo.EstateSettings.terrainDetail0; + handshake.RegionInfo.TerrainDetail1 = regionInfo.EstateSettings.terrainDetail1; + handshake.RegionInfo.TerrainDetail2 = regionInfo.EstateSettings.terrainDetail2; + handshake.RegionInfo.TerrainDetail3 = regionInfo.EstateSettings.terrainDetail3; + handshake.RegionInfo.CacheID = LLUUID.Random(); //I guess this is for the client to remember an old setting? + + OutPacket(handshake, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + public void MoveAgentIntoRegion(RegionInfo regInfo, LLVector3 pos, LLVector3 look) + { + AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); + mov.SimData.ChannelVersion = m_channelVersion; + mov.AgentData.SessionID = m_sessionId; + mov.AgentData.AgentID = AgentId; + mov.Data.RegionHandle = regInfo.RegionHandle; + mov.Data.Timestamp = 1172750370; // TODO - dynamicalise this + + if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0)) + { + mov.Data.Position = m_startpos; + } + else + { + mov.Data.Position = pos; + } + mov.Data.LookAt = look; + + // Hack to get this out immediately and skip the throttles + OutPacket(mov, ThrottleOutPacketType.Unknown); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public void SendChatMessage(string message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID) + { + SendChatMessage(Helpers.StringToField(message), type, fromPos, fromName, fromAgentID); + } + + public void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID) + { + ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); + reply.ChatData.Audible = 1; + reply.ChatData.Message = message; + reply.ChatData.ChatType = type; + reply.ChatData.SourceType = 1; + reply.ChatData.Position = fromPos; + reply.ChatData.FromName = Helpers.StringToField(fromName); + reply.ChatData.OwnerID = fromAgentID; + reply.ChatData.SourceID = fromAgentID; + + OutPacket(reply, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + /// + public void SendInstantMessage(LLUUID fromAgent, LLUUID fromAgentSession, string message, LLUUID toAgent, + LLUUID imSessionID, string fromName, byte dialog, uint timeStamp) + { + ImprovedInstantMessagePacket msg = (ImprovedInstantMessagePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedInstantMessage); + msg.AgentData.AgentID = fromAgent; + msg.AgentData.SessionID = fromAgentSession; + msg.MessageBlock.FromAgentName = Helpers.StringToField(fromName); + msg.MessageBlock.Dialog = dialog; + msg.MessageBlock.FromGroup = false; + msg.MessageBlock.ID = imSessionID; + msg.MessageBlock.Offline = 0; + msg.MessageBlock.ParentEstateID = 0; + msg.MessageBlock.Position = new LLVector3(); + msg.MessageBlock.RegionID = LLUUID.Random(); + msg.MessageBlock.Timestamp = timeStamp; + msg.MessageBlock.ToAgentID = toAgent; + msg.MessageBlock.Message = Helpers.StringToField(message); + msg.MessageBlock.BinaryBucket = new byte[0]; + + OutPacket(msg, ThrottleOutPacketType.Task); + } + + /// + /// Send the region heightmap to the client + /// + /// heightmap + public virtual void SendLayerData(float[] map) + { + try + { + int[] patches = new int[4]; + + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 16; x += 4) + { + patches[0] = x + 0 + y * 16; + patches[1] = x + 1 + y * 16; + patches[2] = x + 2 + y * 16; + patches[3] = x + 3 + y * 16; + + Packet layerpack = TerrainManager.CreateLandPacket(map, patches); + OutPacket(layerpack, ThrottleOutPacketType.Land); + } + } + } + catch (Exception e) + { + m_log.Warn("[client]: " + + "ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString()); + } + } + + /// + /// Sends a specified patch to a client + /// + /// Patch coordinate (x) 0..16 + /// Patch coordinate (y) 0..16 + /// heightmap + public void SendLayerData(int px, int py, float[] map) + { + try + { + int[] patches = new int[1]; + int patchx, patchy; + patchx = px; + patchy = py; + + patches[0] = patchx + 0 + patchy * 16; + + Packet layerpack = TerrainManager.CreateLandPacket(map, patches); + OutPacket(layerpack, ThrottleOutPacketType.Land); + } + catch (Exception e) + { + m_log.Warn("[client]: " + + "ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString()); + } + } + + /// + /// + /// + /// + /// + /// + public void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourEndPoint) + { + IPAddress neighbourIP = neighbourEndPoint.Address; + ushort neighbourPort = (ushort)neighbourEndPoint.Port; + + EnableSimulatorPacket enablesimpacket = (EnableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.EnableSimulator); + // TODO: don't create new blocks if recycling an old packet + enablesimpacket.SimulatorInfo = new EnableSimulatorPacket.SimulatorInfoBlock(); + enablesimpacket.SimulatorInfo.Handle = neighbourHandle; + + byte[] byteIP = neighbourIP.GetAddressBytes(); + enablesimpacket.SimulatorInfo.IP = (uint)byteIP[3] << 24; + enablesimpacket.SimulatorInfo.IP += (uint)byteIP[2] << 16; + enablesimpacket.SimulatorInfo.IP += (uint)byteIP[1] << 8; + enablesimpacket.SimulatorInfo.IP += (uint)byteIP[0]; + enablesimpacket.SimulatorInfo.Port = neighbourPort; + OutPacket(enablesimpacket, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + public AgentCircuitData RequestClientInfo() + { + AgentCircuitData agentData = new AgentCircuitData(); + agentData.AgentID = AgentId; + agentData.SessionID = m_sessionId; + agentData.SecureSessionID = SecureSessionId; + agentData.circuitcode = m_circuitCode; + agentData.child = false; + agentData.firstname = m_firstName; + agentData.lastname = m_lastName; + agentData.CapsPath = String.Empty; + return agentData; + } + + public void CrossRegion(ulong newRegionHandle, LLVector3 pos, LLVector3 lookAt, IPEndPoint externalIPEndPoint, + string capsURL) + { + LLVector3 look = new LLVector3(lookAt.X * 10, lookAt.Y * 10, lookAt.Z * 10); + + //CrossedRegionPacket newSimPack = (CrossedRegionPacket)PacketPool.Instance.GetPacket(PacketType.CrossedRegion); + CrossedRegionPacket newSimPack = new CrossedRegionPacket(); + // TODO: don't create new blocks if recycling an old packet + newSimPack.AgentData = new CrossedRegionPacket.AgentDataBlock(); + newSimPack.AgentData.AgentID = AgentId; + newSimPack.AgentData.SessionID = m_sessionId; + newSimPack.Info = new CrossedRegionPacket.InfoBlock(); + newSimPack.Info.Position = pos; + newSimPack.Info.LookAt = look; + newSimPack.RegionData = new CrossedRegionPacket.RegionDataBlock(); + newSimPack.RegionData.RegionHandle = newRegionHandle; + byte[] byteIP = externalIPEndPoint.Address.GetAddressBytes(); + newSimPack.RegionData.SimIP = (uint)byteIP[3] << 24; + newSimPack.RegionData.SimIP += (uint)byteIP[2] << 16; + newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8; + newSimPack.RegionData.SimIP += (uint)byteIP[0]; + newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port; + newSimPack.RegionData.SeedCapability = Helpers.StringToField(capsURL); + + // Hack to get this out immediately and skip throttles + OutPacket(newSimPack, ThrottleOutPacketType.Unknown); + } + + public void SendMapBlock(List mapBlocks) + { + MapBlockReplyPacket mapReply = (MapBlockReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapBlockReply); + // TODO: don't create new blocks if recycling an old packet + mapReply.AgentData.AgentID = AgentId; + mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks.Count]; + mapReply.AgentData.Flags = 0; + + for (int i = 0; i < mapBlocks.Count; i++) + { + mapReply.Data[i] = new MapBlockReplyPacket.DataBlock(); + mapReply.Data[i].MapImageID = mapBlocks[i].MapImageId; + mapReply.Data[i].X = mapBlocks[i].X; + mapReply.Data[i].Y = mapBlocks[i].Y; + mapReply.Data[i].WaterHeight = mapBlocks[i].WaterHeight; + mapReply.Data[i].Name = Helpers.StringToField(mapBlocks[i].Name); + mapReply.Data[i].RegionFlags = mapBlocks[i].RegionFlags; + mapReply.Data[i].Access = mapBlocks[i].Access; + mapReply.Data[i].Agents = mapBlocks[i].Agents; + } + OutPacket(mapReply, ThrottleOutPacketType.Land); + } + + public void SendLocalTeleport(LLVector3 position, LLVector3 lookAt, uint flags) + { + TeleportLocalPacket tpLocal = (TeleportLocalPacket)PacketPool.Instance.GetPacket(PacketType.TeleportLocal); + tpLocal.Info.AgentID = AgentId; + tpLocal.Info.TeleportFlags = flags; + tpLocal.Info.LocationID = 2; + tpLocal.Info.LookAt = lookAt; + tpLocal.Info.Position = position; + + // Hack to get this out immediately and skip throttles + OutPacket(tpLocal, ThrottleOutPacketType.Unknown); + } + + public void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint newRegionEndPoint, uint locationID, + uint flags, string capsURL) + { + //TeleportFinishPacket teleport = (TeleportFinishPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFinish); + + TeleportFinishPacket teleport = new TeleportFinishPacket(); + teleport.Info.AgentID = AgentId; + teleport.Info.RegionHandle = regionHandle; + teleport.Info.SimAccess = simAccess; + + teleport.Info.SeedCapability = Helpers.StringToField(capsURL); + + IPAddress oIP = newRegionEndPoint.Address; + byte[] byteIP = oIP.GetAddressBytes(); + uint ip = (uint)byteIP[3] << 24; + ip += (uint)byteIP[2] << 16; + ip += (uint)byteIP[1] << 8; + ip += (uint)byteIP[0]; + + teleport.Info.SimIP = ip; + teleport.Info.SimPort = (ushort)newRegionEndPoint.Port; + teleport.Info.LocationID = 4; + teleport.Info.TeleportFlags = 1 << 4; + + // Hack to get this out immediately and skip throttles. + OutPacket(teleport, ThrottleOutPacketType.Unknown); + } + + /// + /// + /// + public void SendTeleportFailed(string reason) + { + TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed); + tpFailed.Info.AgentID = AgentId; + tpFailed.Info.Reason = Helpers.StringToField(reason); + + // Hack to get this out immediately and skip throttles + OutPacket(tpFailed, ThrottleOutPacketType.Unknown); + } + + /// + /// + /// + public void SendTeleportLocationStart() + { + //TeleportStartPacket tpStart = (TeleportStartPacket)PacketPool.Instance.GetPacket(PacketType.TeleportStart); + TeleportStartPacket tpStart = new TeleportStartPacket(); + tpStart.Info.TeleportFlags = 16; // Teleport via location + + // Hack to get this out immediately and skip throttles + OutPacket(tpStart, ThrottleOutPacketType.Unknown); + } + + public void SendMoneyBalance(LLUUID transaction, bool success, byte[] description, int balance) + { + MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply); + money.MoneyData.AgentID = AgentId; + money.MoneyData.TransactionID = transaction; + money.MoneyData.TransactionSuccess = success; + money.MoneyData.Description = description; + money.MoneyData.MoneyBalance = balance; + OutPacket(money, ThrottleOutPacketType.Task); + } + + public void SendStartPingCheck(byte seq) + { + StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); + pc.PingID.PingID = seq; + pc.Header.Reliable = false; + OutPacket(pc, ThrottleOutPacketType.Task); + } + + public void SendKillObject(ulong regionHandle, uint localID) + { + KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); + // TODO: don't create new blocks if recycling an old packet + kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; + kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); + kill.ObjectData[0].ID = localID; + kill.Header.Reliable = false; + OutPacket(kill, ThrottleOutPacketType.Task); + } + + /// + /// Send information about the items contained in a folder to the client. + /// + /// XXX This method needs some refactoring loving + /// + /// The owner of the folder + /// The id of the folder + /// The items contained in the folder identified by folderID + /// Do we need to send folder information? + /// Do we need to send item information? + public void SendInventoryFolderDetails(LLUUID ownerID, LLUUID folderID, List items, + List folders, + bool fetchFolders, bool fetchItems) + { + // An inventory descendents packet consists of a single agent section and an inventory details + // section for each inventory item. The size of each inventory item is approximately 550 bytes. + // In theory, UDP has a maximum packet size of 64k, so it should be possible to send descendent + // packets containing metadata for in excess of 100 items. But in practice, there may be other + // factors (e.g. firewalls) restraining the maximum UDP packet size. See, + // + // http://opensimulator.org/mantis/view.php?id=226 + // + // for one example of this kind of thing. In fact, the Linden servers appear to only send about + // 6 to 7 items at a time, so let's stick with 6 + int MAX_ITEMS_PER_PACKET = 6; + + Encoding enc = Encoding.ASCII; + uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; + InventoryDescendentsPacket descend; + int i; + int count; + + if (fetchItems) + { + descend = CreateInventoryDescendentsPacket(ownerID, folderID); + + if (items.Count < MAX_ITEMS_PER_PACKET) + { + descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count]; + descend.AgentData.Descendents = items.Count; + } + else + { + descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[MAX_ITEMS_PER_PACKET]; + descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET; + } + + // Even if we aren't fetching the folders, we still need to include the folder count + // in the total number of descendents. Failure to do so will cause subtle bugs such + // as the failure of textures which haven't been expanded in inventory to show up + // in the texture prim edit selection panel. + if (!fetchFolders) + { + descend.AgentData.Descendents += folders.Count; + } + + count = 0; + i = 0; + foreach (InventoryItemBase item in items) + { + descend.ItemData[i] = new InventoryDescendentsPacket.ItemDataBlock(); + descend.ItemData[i].ItemID = item.inventoryID; + descend.ItemData[i].AssetID = item.assetID; + descend.ItemData[i].CreatorID = item.creatorsID; + descend.ItemData[i].BaseMask = item.inventoryBasePermissions; + descend.ItemData[i].CreationDate = 1000; + descend.ItemData[i].Description = Helpers.StringToField(item.inventoryDescription); + descend.ItemData[i].EveryoneMask = item.inventoryEveryOnePermissions; + descend.ItemData[i].Flags = 1; + descend.ItemData[i].FolderID = item.parentFolderID; + descend.ItemData[i].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000"); + descend.ItemData[i].GroupMask = 0; + descend.ItemData[i].InvType = (sbyte)item.invType; + descend.ItemData[i].Name = Helpers.StringToField(item.inventoryName); + descend.ItemData[i].NextOwnerMask = item.inventoryNextPermissions; + descend.ItemData[i].OwnerID = item.avatarID; + descend.ItemData[i].OwnerMask = item.inventoryCurrentPermissions; + descend.ItemData[i].SalePrice = 0; + descend.ItemData[i].SaleType = 0; + descend.ItemData[i].Type = (sbyte)item.assetType; + descend.ItemData[i].CRC = + Helpers.InventoryCRC(descend.ItemData[i].CreationDate, descend.ItemData[i].SaleType, + descend.ItemData[i].InvType, descend.ItemData[i].Type, + descend.ItemData[i].AssetID, descend.ItemData[i].GroupID, + descend.ItemData[i].SalePrice, + descend.ItemData[i].OwnerID, descend.ItemData[i].CreatorID, + descend.ItemData[i].ItemID, descend.ItemData[i].FolderID, + descend.ItemData[i].EveryoneMask, + descend.ItemData[i].Flags, descend.ItemData[i].OwnerMask, + descend.ItemData[i].GroupMask, item.inventoryCurrentPermissions); + + i++; + count++; + if (i == MAX_ITEMS_PER_PACKET) + { + OutPacket(descend, ThrottleOutPacketType.Asset); + + if ((items.Count - count) > 0) + { + descend = CreateInventoryDescendentsPacket(ownerID, folderID); + if ((items.Count - count) < MAX_ITEMS_PER_PACKET) + { + descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count - count]; + descend.AgentData.Descendents = items.Count - count; + } + else + { + descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[MAX_ITEMS_PER_PACKET]; + descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET; + } + i = 0; + } + } + } + + if (i < MAX_ITEMS_PER_PACKET) + { + OutPacket(descend, ThrottleOutPacketType.Asset); + } + } + + //send subfolders + + descend = CreateInventoryDescendentsPacket(ownerID, folderID); + + if (folders.Count < MAX_ITEMS_PER_PACKET) + { + descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[folders.Count]; + descend.AgentData.Descendents = folders.Count; + } + else + { + descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[MAX_ITEMS_PER_PACKET]; + descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET; + } + + // Not sure if this scenario ever actually occurs, but nonetheless we include the items + // count even if we're not sending item data for the same reasons as above. + if (!fetchItems) + { + descend.AgentData.Descendents += items.Count; + } + + i = 0; + count = 0; + foreach (InventoryFolderBase folder in folders) + { + descend.FolderData[i] = new InventoryDescendentsPacket.FolderDataBlock(); + descend.FolderData[i].FolderID = folder.folderID; + descend.FolderData[i].Name = Helpers.StringToField(folder.name); + descend.FolderData[i].ParentID = folder.parentID; + descend.FolderData[i].Type = (sbyte)folder.type; + + i++; + count++; + if (i == MAX_ITEMS_PER_PACKET) + { + OutPacket(descend, ThrottleOutPacketType.Asset); + + if ((folders.Count - count) > 0) + { + descend = CreateInventoryDescendentsPacket(ownerID, folderID); + if ((folders.Count - count) < MAX_ITEMS_PER_PACKET) + { + descend.FolderData = + new InventoryDescendentsPacket.FolderDataBlock[folders.Count - count]; + descend.AgentData.Descendents = folders.Count - count; + } + else + { + descend.FolderData = + new InventoryDescendentsPacket.FolderDataBlock[MAX_ITEMS_PER_PACKET]; + descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET; + } + i = 0; + } + } + } + + if (i < MAX_ITEMS_PER_PACKET) + { + OutPacket(descend, ThrottleOutPacketType.Asset); + } + + } + + private InventoryDescendentsPacket CreateInventoryDescendentsPacket(LLUUID ownerID, LLUUID folderID) + { + InventoryDescendentsPacket descend = (InventoryDescendentsPacket)PacketPool.Instance.GetPacket(PacketType.InventoryDescendents); + descend.AgentData.AgentID = AgentId; + descend.AgentData.OwnerID = ownerID; + descend.AgentData.FolderID = folderID; + descend.AgentData.Version = 0; + + return descend; + } + + public void SendInventoryItemDetails(LLUUID ownerID, InventoryItemBase item) + { + Encoding enc = Encoding.ASCII; + uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; + FetchInventoryReplyPacket inventoryReply = (FetchInventoryReplyPacket)PacketPool.Instance.GetPacket(PacketType.FetchInventoryReply); + // TODO: don't create new blocks if recycling an old packet + inventoryReply.AgentData.AgentID = AgentId; + inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[1]; + inventoryReply.InventoryData[0] = new FetchInventoryReplyPacket.InventoryDataBlock(); + inventoryReply.InventoryData[0].ItemID = item.inventoryID; + inventoryReply.InventoryData[0].AssetID = item.assetID; + inventoryReply.InventoryData[0].CreatorID = item.creatorsID; + inventoryReply.InventoryData[0].BaseMask = item.inventoryBasePermissions; + inventoryReply.InventoryData[0].CreationDate = + (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; + inventoryReply.InventoryData[0].Description = Helpers.StringToField(item.inventoryDescription); + inventoryReply.InventoryData[0].EveryoneMask = item.inventoryEveryOnePermissions; + inventoryReply.InventoryData[0].Flags = 0; + inventoryReply.InventoryData[0].FolderID = item.parentFolderID; + inventoryReply.InventoryData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000"); + inventoryReply.InventoryData[0].GroupMask = 0; + inventoryReply.InventoryData[0].InvType = (sbyte)item.invType; + inventoryReply.InventoryData[0].Name = Helpers.StringToField(item.inventoryName); + inventoryReply.InventoryData[0].NextOwnerMask = item.inventoryNextPermissions; + inventoryReply.InventoryData[0].OwnerID = item.avatarID; + inventoryReply.InventoryData[0].OwnerMask = item.inventoryCurrentPermissions; + inventoryReply.InventoryData[0].SalePrice = 0; + inventoryReply.InventoryData[0].SaleType = 0; + inventoryReply.InventoryData[0].Type = (sbyte)item.assetType; + inventoryReply.InventoryData[0].CRC = + Helpers.InventoryCRC(1000, 0, inventoryReply.InventoryData[0].InvType, + inventoryReply.InventoryData[0].Type, inventoryReply.InventoryData[0].AssetID, + inventoryReply.InventoryData[0].GroupID, 100, + inventoryReply.InventoryData[0].OwnerID, inventoryReply.InventoryData[0].CreatorID, + inventoryReply.InventoryData[0].ItemID, inventoryReply.InventoryData[0].FolderID, + FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, + FULL_MASK_PERMISSIONS); + + OutPacket(inventoryReply, ThrottleOutPacketType.Asset); + } + + /// IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase) + public void SendInventoryItemCreateUpdate(InventoryItemBase Item) + { + Encoding enc = Encoding.ASCII; + uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; + UpdateCreateInventoryItemPacket InventoryReply = (UpdateCreateInventoryItemPacket)PacketPool.Instance.GetPacket(PacketType.UpdateCreateInventoryItem); + // TODO: don't create new blocks if recycling an old packet + InventoryReply.AgentData.AgentID = AgentId; + InventoryReply.AgentData.SimApproved = true; + InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; + InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); + InventoryReply.InventoryData[0].ItemID = Item.inventoryID; + InventoryReply.InventoryData[0].AssetID = Item.assetID; + InventoryReply.InventoryData[0].CreatorID = Item.creatorsID; + InventoryReply.InventoryData[0].BaseMask = Item.inventoryBasePermissions; + InventoryReply.InventoryData[0].CreationDate = 1000; + InventoryReply.InventoryData[0].Description = Helpers.StringToField(Item.inventoryDescription); + InventoryReply.InventoryData[0].EveryoneMask = Item.inventoryEveryOnePermissions; + InventoryReply.InventoryData[0].Flags = 0; + InventoryReply.InventoryData[0].FolderID = Item.parentFolderID; + InventoryReply.InventoryData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000"); + InventoryReply.InventoryData[0].GroupMask = 0; + InventoryReply.InventoryData[0].InvType = (sbyte)Item.invType; + InventoryReply.InventoryData[0].Name = Helpers.StringToField(Item.inventoryName); + InventoryReply.InventoryData[0].NextOwnerMask = Item.inventoryNextPermissions; + InventoryReply.InventoryData[0].OwnerID = Item.avatarID; + InventoryReply.InventoryData[0].OwnerMask = Item.inventoryCurrentPermissions; + InventoryReply.InventoryData[0].SalePrice = 100; + InventoryReply.InventoryData[0].SaleType = 0; + InventoryReply.InventoryData[0].Type = (sbyte)Item.assetType; + InventoryReply.InventoryData[0].CRC = + Helpers.InventoryCRC(1000, 0, InventoryReply.InventoryData[0].InvType, + InventoryReply.InventoryData[0].Type, InventoryReply.InventoryData[0].AssetID, + InventoryReply.InventoryData[0].GroupID, 100, + InventoryReply.InventoryData[0].OwnerID, InventoryReply.InventoryData[0].CreatorID, + InventoryReply.InventoryData[0].ItemID, InventoryReply.InventoryData[0].FolderID, + FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, + FULL_MASK_PERMISSIONS); + + OutPacket(InventoryReply, ThrottleOutPacketType.Asset); + } + + public void SendRemoveInventoryItem(LLUUID itemID) + { + RemoveInventoryItemPacket remove = (RemoveInventoryItemPacket)PacketPool.Instance.GetPacket(PacketType.RemoveInventoryItem); + // TODO: don't create new blocks if recycling an old packet + remove.AgentData.AgentID = AgentId; + remove.AgentData.SessionID = m_sessionId; + remove.InventoryData = new RemoveInventoryItemPacket.InventoryDataBlock[1]; + remove.InventoryData[0] = new RemoveInventoryItemPacket.InventoryDataBlock(); + remove.InventoryData[0].ItemID = itemID; + + OutPacket(remove, ThrottleOutPacketType.Asset); + } + + public void SendTaskInventory(LLUUID taskID, short serial, byte[] fileName) + { + ReplyTaskInventoryPacket replytask = (ReplyTaskInventoryPacket)PacketPool.Instance.GetPacket(PacketType.ReplyTaskInventory); + replytask.InventoryData.TaskID = taskID; + replytask.InventoryData.Serial = serial; + replytask.InventoryData.Filename = fileName; + OutPacket(replytask, ThrottleOutPacketType.Asset); + } + + public void SendXferPacket(ulong xferID, uint packet, byte[] data) + { + SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket); + sendXfer.XferID.ID = xferID; + sendXfer.XferID.Packet = packet; + sendXfer.DataPacket.Data = data; + OutPacket(sendXfer, ThrottleOutPacketType.Task); + } + + public void SendAvatarPickerReply(AvatarPickerReplyPacket replyPacket) + { + OutPacket(replyPacket, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + public void SendAlertMessage(string message) + { + AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage); + alertPack.AlertData.Message = Helpers.StringToField(message); + OutPacket(alertPack, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + /// + public void SendAgentAlertMessage(string message, bool modal) + { + AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); + alertPack.AgentData.AgentID = AgentId; + alertPack.AlertData.Message = Helpers.StringToField(message); + alertPack.AlertData.Modal = modal; + OutPacket(alertPack, ThrottleOutPacketType.Task); + } + + public void SendLoadURL(string objectname, LLUUID objectID, LLUUID ownerID, bool groupOwned, string message, + string url) + { + LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL); + loadURL.Data.ObjectName = Helpers.StringToField(objectname); + loadURL.Data.ObjectID = objectID; + loadURL.Data.OwnerID = ownerID; + loadURL.Data.OwnerIsGroup = groupOwned; + loadURL.Data.Message = Helpers.StringToField(message); + loadURL.Data.URL = Helpers.StringToField(url); + OutPacket(loadURL, ThrottleOutPacketType.Task); + } + + public void SendDialog(string objectname, LLUUID objectID, LLUUID ownerID, string msg, LLUUID textureID, int ch, string[] buttonlabels) + { + ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog); + dialog.Data.ObjectID = objectID; + dialog.Data.ObjectName = Helpers.StringToField(objectname); + dialog.Data.FirstName = Helpers.StringToField(this.FirstName); + dialog.Data.LastName = Helpers.StringToField(this.LastName); + dialog.Data.Message = Helpers.StringToField(msg); + dialog.Data.ImageID = textureID; + dialog.Data.ChatChannel = ch; + ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length]; + for (int i = 0; i < buttonlabels.Length; i++) + { + buttons[i] = new ScriptDialogPacket.ButtonsBlock(); + buttons[i].ButtonLabel = Helpers.StringToField(buttonlabels[i]); + } + dialog.Buttons = buttons; + OutPacket(dialog, ThrottleOutPacketType.Task); + } + + public void SendPreLoadSound(LLUUID objectID, LLUUID ownerID, LLUUID soundID) + { + PreloadSoundPacket preSound = (PreloadSoundPacket)PacketPool.Instance.GetPacket(PacketType.PreloadSound); + // TODO: don't create new blocks if recycling an old packet + preSound.DataBlock = new PreloadSoundPacket.DataBlockBlock[1]; + preSound.DataBlock[0] = new PreloadSoundPacket.DataBlockBlock(); + preSound.DataBlock[0].ObjectID = objectID; + preSound.DataBlock[0].OwnerID = ownerID; + preSound.DataBlock[0].SoundID = soundID; + OutPacket(preSound, ThrottleOutPacketType.Task); + } + + public void SendPlayAttachedSound(LLUUID soundID, LLUUID objectID, LLUUID ownerID, float gain, byte flags) + { + AttachedSoundPacket sound = (AttachedSoundPacket)PacketPool.Instance.GetPacket(PacketType.AttachedSound); + sound.DataBlock.SoundID = soundID; + sound.DataBlock.ObjectID = objectID; + sound.DataBlock.OwnerID = ownerID; + sound.DataBlock.Gain = gain; + sound.DataBlock.Flags = flags; + + OutPacket(sound, ThrottleOutPacketType.Task); + } + + public void SendTriggeredSound(LLUUID soundID, LLUUID ownerID, LLUUID objectID, LLUUID parentID, ulong handle, LLVector3 position, float gain) + { + SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); + sound.SoundData.SoundID = soundID; + sound.SoundData.OwnerID = ownerID; + sound.SoundData.ObjectID = objectID; + sound.SoundData.ParentID = parentID; + sound.SoundData.Handle = handle; + sound.SoundData.Position = position; + sound.SoundData.Gain = gain; + + OutPacket(sound, ThrottleOutPacketType.Task); + } + + public void SendSunPos(LLVector3 sunPos, LLVector3 sunVel) + { + SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); + viewertime.TimeInfo.SunDirection = sunPos; + viewertime.TimeInfo.SunAngVelocity = sunVel; + viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch(); + viewertime.Header.Reliable = false; + OutPacket(viewertime, ThrottleOutPacketType.Task); + } + + public void SendViewerTime(int phase) + { + Console.WriteLine("SunPhase: {0}", phase); + SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); + //viewertime.TimeInfo.SecPerDay = 86400; + //viewertime.TimeInfo.SecPerYear = 31536000; + viewertime.TimeInfo.SecPerDay = 1000; + viewertime.TimeInfo.SecPerYear = 365000; + viewertime.TimeInfo.SunPhase = 1; + int sunPhase = (phase + 2) / 2; + if ((sunPhase < 6) || (sunPhase > 36)) + { + viewertime.TimeInfo.SunDirection = new LLVector3(0f, 0.8f, -0.8f); + Console.WriteLine("sending night"); + } + else + { + if (sunPhase < 12) + { + sunPhase = 12; + } + sunPhase = sunPhase - 12; + + float yValue = 0.1f * (sunPhase); + Console.WriteLine("Computed SunPhase: {0}, yValue: {1}", sunPhase, yValue); + if (yValue > 1.2f) + { + yValue = yValue - 1.2f; + } + + yValue = Util.Clip(yValue, 0, 1); + + if (sunPhase < 14) + { + yValue = 1 - yValue; + } + if (sunPhase < 12) + { + yValue *= -1; + } + viewertime.TimeInfo.SunDirection = new LLVector3(0f, yValue, 0.3f); + Console.WriteLine("sending sun update " + yValue); + } + viewertime.TimeInfo.SunAngVelocity = new LLVector3(0, 0.0f, 10.0f); + viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch(); + viewertime.Header.Reliable = false; + OutPacket(viewertime, ThrottleOutPacketType.Task); + } + + public void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember, + string flAbout, uint flags, LLUUID flImageID, LLUUID imageID, string profileURL, + LLUUID partnerID) + { + AvatarPropertiesReplyPacket avatarReply = (AvatarPropertiesReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPropertiesReply); + avatarReply.AgentData.AgentID = AgentId; + avatarReply.AgentData.AvatarID = avatarID; + avatarReply.PropertiesData.AboutText = Helpers.StringToField(aboutText); + avatarReply.PropertiesData.BornOn = Helpers.StringToField(bornOn); + avatarReply.PropertiesData.CharterMember = Helpers.StringToField(charterMember); + avatarReply.PropertiesData.FLAboutText = Helpers.StringToField(flAbout); + avatarReply.PropertiesData.Flags = 0; + avatarReply.PropertiesData.FLImageID = flImageID; + avatarReply.PropertiesData.ImageID = imageID; + avatarReply.PropertiesData.ProfileURL = Helpers.StringToField(profileURL); + avatarReply.PropertiesData.PartnerID = partnerID; + OutPacket(avatarReply, ThrottleOutPacketType.Task); + } + + #endregion + + #region Appearance/ Wearables Methods + + /// + /// + /// + /// + public void SendWearables(AvatarWearable[] wearables, int serial) + { + AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate); + aw.AgentData.AgentID = AgentId; + aw.AgentData.SerialNum = (uint)serial; + aw.AgentData.SessionID = m_sessionId; + + // TODO: don't create new blocks if recycling an old packet + aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13]; + AgentWearablesUpdatePacket.WearableDataBlock awb; + for (int i = 0; i < wearables.Length; i++) + { + awb = new AgentWearablesUpdatePacket.WearableDataBlock(); + awb.WearableType = (byte)i; + awb.AssetID = wearables[i].AssetID; + awb.ItemID = wearables[i].ItemID; + aw.WearableData[i] = awb; + } + + OutPacket(aw, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + /// + /// + public void SendAppearance(LLUUID agentID, byte[] visualParams, byte[] textureEntry) + { + AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); + // TODO: don't create new blocks if recycling an old packet + avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; + avp.ObjectData.TextureEntry = textureEntry; + + AvatarAppearancePacket.VisualParamBlock avblock = null; + for (int i = 0; i < visualParams.Length; i++) + { + avblock = new AvatarAppearancePacket.VisualParamBlock(); + avblock.ParamValue = visualParams[i]; + avp.VisualParam[i] = avblock; + } + + avp.Sender.IsTrial = false; + avp.Sender.ID = agentID; + OutPacket(avp, ThrottleOutPacketType.Task); + } + + public void SendAnimations(LLUUID[] animations, int[] seqs, LLUUID sourceAgentId) + { + AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); + // TODO: don't create new blocks if recycling an old packet + ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[1]; + ani.AnimationSourceList[0] = new AvatarAnimationPacket.AnimationSourceListBlock(); + ani.AnimationSourceList[0].ObjectID = sourceAgentId; + ani.Sender = new AvatarAnimationPacket.SenderBlock(); + ani.Sender.ID = sourceAgentId; + ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; + + for (int i = 0; i < animations.Length; ++i) + { + ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); + ani.AnimationList[i].AnimID = animations[i]; + ani.AnimationList[i].AnimSequenceID = seqs[i]; + } + ani.Header.Reliable = false; + OutPacket(ani, ThrottleOutPacketType.Task); + } + + #endregion + + #region Avatar Packet/data sending Methods + + /// + /// send a objectupdate packet with information about the clients avatar + /// + /// + /// + /// + /// + /// + /// + public void SendAvatarData(ulong regionHandle, string firstName, string lastName, LLUUID avatarID, + uint avatarLocalID, LLVector3 Pos, byte[] textureEntry, uint parentID) + { + ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); + // TODO: don't create new blocks if recycling an old packet + objupdate.RegionData.RegionHandle = regionHandle; + objupdate.RegionData.TimeDilation = ushort.MaxValue; + objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry); + + //give this avatar object a local id and assign the user a name + objupdate.ObjectData[0].ID = avatarLocalID; + objupdate.ObjectData[0].FullID = avatarID; + objupdate.ObjectData[0].ParentID = parentID; + objupdate.ObjectData[0].NameValue = + Helpers.StringToField("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName); + LLVector3 pos2 = new LLVector3((float)Pos.X, (float)Pos.Y, (float)Pos.Z); + byte[] pb = pos2.GetBytes(); + Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); + + OutPacket(objupdate, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, + LLVector3 velocity, LLQuaternion rotation) + { + ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = + CreateAvatarImprovedBlock(localID, position, velocity, rotation); + ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + // TODO: don't create new blocks if recycling an old packet + terse.RegionData.RegionHandle = regionHandle; + terse.RegionData.TimeDilation = timeDilation; + terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + terse.ObjectData[0] = terseBlock; + + terse.Header.Reliable = false; + + + OutPacket(terse, ThrottleOutPacketType.Task); + } + + public void SendCoarseLocationUpdate(List CoarseLocations) + { + CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); + // TODO: don't create new blocks if recycling an old packet + int total = CoarseLocations.Count; + CoarseLocationUpdatePacket.IndexBlock ib = + new CoarseLocationUpdatePacket.IndexBlock(); + loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; + for (int i = 0; i < total; i++) + { + CoarseLocationUpdatePacket.LocationBlock lb = + new CoarseLocationUpdatePacket.LocationBlock(); + lb.X = (byte)CoarseLocations[i].X; + lb.Y = (byte)CoarseLocations[i].Y; + lb.Z = (byte)(CoarseLocations[i].Z / 4); + loc.Location[i] = lb; + } + ib.You = -1; + ib.Prey = -1; + loc.Index = ib; + loc.Header.Reliable = false; + OutPacket(loc, ThrottleOutPacketType.Task); + } + + #endregion + + #region Primitive Packet/data Sending Methods + + /// + /// + /// + /// + /// + /// + public void AttachObject(uint localID, LLQuaternion rotation, byte attachPoint) + { + ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); + System.Console.WriteLine("Attach object!"); + // TODO: don't create new blocks if recycling an old packet + attach.AgentData.AgentID = AgentId; + attach.AgentData.SessionID = m_sessionId; + attach.AgentData.AttachmentPoint = attachPoint; + attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1]; + attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock(); + attach.ObjectData[0].ObjectLocalID = localID; + attach.ObjectData[0].Rotation = rotation; + + OutPacket(attach, ThrottleOutPacketType.Task); + } + + public void SendPrimitiveToClient( + ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, LLVector3 pos, + uint flags, + LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, + LLQuaternion rotation, byte clickAction) + { + byte[] textureanim = new byte[0]; + + SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, flags, + objectID, ownerID, text, color, parentID, particleSystem, + rotation, clickAction, textureanim); + } + public void SendPrimitiveToClient( + ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, LLVector3 pos, + uint flags, + LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, + LLQuaternion rotation, byte clickAction, byte[] textureanim) + { + ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); + // TODO: don't create new blocks if recycling an old packet + outPacket.RegionData.RegionHandle = regionHandle; + outPacket.RegionData.TimeDilation = timeDilation; + outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; + + outPacket.ObjectData[0] = CreatePrimUpdateBlock(primShape, flags); + + outPacket.ObjectData[0].ID = localID; + outPacket.ObjectData[0].FullID = objectID; + outPacket.ObjectData[0].OwnerID = ownerID; + outPacket.ObjectData[0].Text = Helpers.StringToField(text); + outPacket.ObjectData[0].TextColor[0] = color[0]; + outPacket.ObjectData[0].TextColor[1] = color[1]; + outPacket.ObjectData[0].TextColor[2] = color[2]; + outPacket.ObjectData[0].TextColor[3] = color[3]; + outPacket.ObjectData[0].ParentID = parentID; + outPacket.ObjectData[0].PSBlock = particleSystem; + outPacket.ObjectData[0].ClickAction = clickAction; + //outPacket.ObjectData[0].Flags = 0; + + // Sound Radius + outPacket.ObjectData[0].Radius = 20; + + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, outPacket.ObjectData[0].ObjectData, 0, pb.Length); + + byte[] rot = rotation.GetBytes(); + Array.Copy(rot, 0, outPacket.ObjectData[0].ObjectData, 36, rot.Length); + + if (textureanim.Length > 0) + { + outPacket.ObjectData[0].TextureAnim = textureanim; + } + + OutPacket(outPacket, ThrottleOutPacketType.Task); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, + LLQuaternion rotation) + { + LLVector3 velocity = new LLVector3(0f, 0f, 0f); + LLVector3 rotationalvelocity = new LLVector3(0f, 0f, 0f); + ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + // TODO: don't create new blocks if recycling an old packet + terse.RegionData.RegionHandle = regionHandle; + terse.RegionData.TimeDilation = timeDilation; + terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity); + terse.Header.Reliable = false; + OutPacket(terse, ThrottleOutPacketType.Task); + } + + public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, + LLQuaternion rotation, LLVector3 velocity, LLVector3 rotationalvelocity) + { + ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + // TODO: don't create new blocks if recycling an old packet + terse.RegionData.RegionHandle = regionHandle; + terse.RegionData.TimeDilation = timeDilation; + terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity); + terse.Header.Reliable = false; + OutPacket(terse, ThrottleOutPacketType.Task); + } + + #endregion + + #region Helper Methods + + protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, LLVector3 pos, + LLVector3 velocity, + LLQuaternion rotation) + { + byte[] bytes = new byte[60]; + int i = 0; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); + + dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry; + + uint ID = localID; + + bytes[i++] = (byte)(ID % 256); + bytes[i++] = (byte)((ID >> 8) % 256); + bytes[i++] = (byte)((ID >> 16) % 256); + bytes[i++] = (byte)((ID >> 24) % 256); + bytes[i++] = 0; + bytes[i++] = 1; + i += 14; + bytes[i++] = 128; + bytes[i++] = 63; + + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, bytes, i, pb.Length); + i += 12; + ushort InternVelocityX; + ushort InternVelocityY; + ushort InternVelocityZ; + Vector3 internDirec = new Vector3(0, 0, 0); + + internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z); + + internDirec = internDirec / 128.0f; + internDirec.x += 1; + internDirec.y += 1; + internDirec.z += 1; + + InternVelocityX = (ushort)(32768 * internDirec.x); + InternVelocityY = (ushort)(32768 * internDirec.y); + InternVelocityZ = (ushort)(32768 * internDirec.z); + + ushort ac = 32767; + bytes[i++] = (byte)(InternVelocityX % 256); + bytes[i++] = (byte)((InternVelocityX >> 8) % 256); + bytes[i++] = (byte)(InternVelocityY % 256); + bytes[i++] = (byte)((InternVelocityY >> 8) % 256); + bytes[i++] = (byte)(InternVelocityZ % 256); + bytes[i++] = (byte)((InternVelocityZ >> 8) % 256); + + //accel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + //rotation + ushort rw, rx, ry, rz; + rw = (ushort)(32768 * (rotation.W + 1)); + rx = (ushort)(32768 * (rotation.X + 1)); + ry = (ushort)(32768 * (rotation.Y + 1)); + rz = (ushort)(32768 * (rotation.Z + 1)); + + //rot + bytes[i++] = (byte)(rx % 256); + bytes[i++] = (byte)((rx >> 8) % 256); + bytes[i++] = (byte)(ry % 256); + bytes[i++] = (byte)((ry >> 8) % 256); + bytes[i++] = (byte)(rz % 256); + bytes[i++] = (byte)((rz >> 8) % 256); + bytes[i++] = (byte)(rw % 256); + bytes[i++] = (byte)((rw >> 8) % 256); + + //rotation vel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + dat.Data = bytes; + + return (dat); + } + + /// + /// + /// + /// + /// + /// + /// + protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID, + LLVector3 position, + LLQuaternion rotation, + LLVector3 velocity, + LLVector3 rotationalvelocity) + { + uint ID = localID; + byte[] bytes = new byte[60]; + + int i = 0; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); + dat.TextureEntry = new byte[0]; + bytes[i++] = (byte)(ID % 256); + bytes[i++] = (byte)((ID >> 8) % 256); + bytes[i++] = (byte)((ID >> 16) % 256); + bytes[i++] = (byte)((ID >> 24) % 256); + bytes[i++] = 0; + bytes[i++] = 0; + + byte[] pb = position.GetBytes(); + Array.Copy(pb, 0, bytes, i, pb.Length); + i += 12; + ushort ac = 32767; + + ushort velx, vely, velz; + Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z); + + vel = vel / 128.0f; + vel.x += 1; + vel.y += 1; + vel.z += 1; + //vel + velx = (ushort)(32768 * (vel.x)); + vely = (ushort)(32768 * (vel.y)); + velz = (ushort)(32768 * (vel.z)); + + bytes[i++] = (byte)(velx % 256); + bytes[i++] = (byte)((velx >> 8) % 256); + bytes[i++] = (byte)(vely % 256); + bytes[i++] = (byte)((vely >> 8) % 256); + bytes[i++] = (byte)(velz % 256); + bytes[i++] = (byte)((velz >> 8) % 256); + + //accel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + ushort rw, rx, ry, rz; + rw = (ushort)(32768 * (rotation.W + 1)); + rx = (ushort)(32768 * (rotation.X + 1)); + ry = (ushort)(32768 * (rotation.Y + 1)); + rz = (ushort)(32768 * (rotation.Z + 1)); + + //rot + bytes[i++] = (byte)(rx % 256); + bytes[i++] = (byte)((rx >> 8) % 256); + bytes[i++] = (byte)(ry % 256); + bytes[i++] = (byte)((ry >> 8) % 256); + bytes[i++] = (byte)(rz % 256); + bytes[i++] = (byte)((rz >> 8) % 256); + bytes[i++] = (byte)(rw % 256); + bytes[i++] = (byte)((rw >> 8) % 256); + + //rotation vel + ushort rvelx, rvely, rvelz; + Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z); + + rvel = rvel / 128.0f; + rvel.x += 1; + rvel.y += 1; + rvel.z += 1; + //vel + rvelx = (ushort)(32768 * (rvel.x)); + rvely = (ushort)(32768 * (rvel.y)); + rvelz = (ushort)(32768 * (rvel.z)); + + bytes[i++] = (byte)(rvelx % 256); + bytes[i++] = (byte)((rvelx >> 8) % 256); + bytes[i++] = (byte)(rvely % 256); + bytes[i++] = (byte)((rvely >> 8) % 256); + bytes[i++] = (byte)(rvelz % 256); + bytes[i++] = (byte)((rvelz >> 8) % 256); + + dat.Data = bytes; + return dat; + } + + /// + /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) + /// + /// + /// + protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) + { + ObjectUpdatePacket.ObjectDataBlock objupdate = new ObjectUpdatePacket.ObjectDataBlock(); + SetDefaultPrimPacketValues(objupdate); + objupdate.UpdateFlags = flags; + SetPrimPacketShapeData(objupdate, primShape); + + return objupdate; + } + + protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData) + { + objectData.TextureEntry = primData.TextureEntry; + objectData.PCode = primData.PCode; + objectData.State = primData.State; + objectData.PathBegin = primData.PathBegin; + objectData.PathEnd = primData.PathEnd; + objectData.PathScaleX = primData.PathScaleX; + objectData.PathScaleY = primData.PathScaleY; + objectData.PathShearX = primData.PathShearX; + objectData.PathShearY = primData.PathShearY; + objectData.PathSkew = primData.PathSkew; + objectData.ProfileBegin = primData.ProfileBegin; + objectData.ProfileEnd = primData.ProfileEnd; + objectData.Scale = primData.Scale; + objectData.PathCurve = primData.PathCurve; + objectData.ProfileCurve = primData.ProfileCurve; + objectData.ProfileHollow = primData.ProfileHollow; + objectData.PathRadiusOffset = primData.PathRadiusOffset; + objectData.PathRevolutions = primData.PathRevolutions; + objectData.PathTaperX = primData.PathTaperX; + objectData.PathTaperY = primData.PathTaperY; + objectData.PathTwist = primData.PathTwist; + objectData.PathTwistBegin = primData.PathTwistBegin; + objectData.ExtraParams = primData.ExtraParams; + } + + /// + /// Set some default values in a ObjectUpdatePacket + /// + /// + protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata) + { + objdata.PSBlock = new byte[0]; + objdata.ExtraParams = new byte[1]; + objdata.MediaURL = new byte[0]; + objdata.NameValue = new byte[0]; + objdata.Text = new byte[0]; + objdata.TextColor = new byte[4]; + objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0); + objdata.JointPivot = new LLVector3(0, 0, 0); + objdata.Material = 3; + objdata.TextureAnim = new byte[0]; + objdata.Sound = LLUUID.Zero; + objdata.State = 0; + objdata.Data = new byte[0]; + + objdata.ObjectData = new byte[60]; + objdata.ObjectData[46] = 128; + objdata.ObjectData[47] = 63; + } + + + /// + /// + /// + /// + public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) + { + ObjectUpdatePacket.ObjectDataBlock objdata = new ObjectUpdatePacket.ObjectDataBlock(); + // new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); + + SetDefaultAvatarPacketValues(ref objdata); + objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); + objdata.PathCurve = 16; + objdata.ProfileCurve = 1; + objdata.PathScaleX = 100; + objdata.PathScaleY = 100; + objdata.ParentID = 0; + objdata.OwnerID = LLUUID.Zero; + objdata.Scale = new LLVector3(1, 1, 1); + objdata.PCode = 47; + if (textureEntry != null) + { + objdata.TextureEntry = textureEntry; + } + Encoding enc = Encoding.ASCII; + LLVector3 pos = new LLVector3(objdata.ObjectData, 16); + pos.X = 100f; + objdata.ID = 8880000; + objdata.NameValue = enc.GetBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User \0"); + //LLVector3 pos2 = new LLVector3(100f, 100f, 23f); + //objdata.FullID=user.AgentId; + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length); + + return objdata; + } + + /// + /// + /// + /// + protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) + { + objdata.PSBlock = new byte[0]; + objdata.ExtraParams = new byte[1]; + objdata.MediaURL = new byte[0]; + objdata.NameValue = new byte[0]; + objdata.Text = new byte[0]; + objdata.TextColor = new byte[4]; + objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0); + objdata.JointPivot = new LLVector3(0, 0, 0); + objdata.Material = 4; + objdata.TextureAnim = new byte[0]; + objdata.Sound = LLUUID.Zero; + LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("00000000-0000-0000-5005-000000000005")); + objdata.TextureEntry = ntex.ToBytes(); + + objdata.State = 0; + objdata.Data = new byte[0]; + + objdata.ObjectData = new byte[76]; + objdata.ObjectData[15] = 128; + objdata.ObjectData[16] = 63; + objdata.ObjectData[56] = 128; + objdata.ObjectData[61] = 102; + objdata.ObjectData[62] = 40; + objdata.ObjectData[63] = 61; + objdata.ObjectData[64] = 189; + } + + public void SendNameReply(LLUUID profileId, string firstname, string lastname) + { + UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); + // TODO: don't create new blocks if recycling an old packet + packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1]; + packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock(); + packet.UUIDNameBlock[0].ID = profileId; + packet.UUIDNameBlock[0].FirstName = Helpers.StringToField(firstname); + packet.UUIDNameBlock[0].LastName = Helpers.StringToField(lastname); + + OutPacket(packet, ThrottleOutPacketType.Task); + } + + #endregion + + protected virtual void RegisterLocalPacketHandlers() + { + AddLocalPacketHandler(PacketType.LogoutRequest, Logout); + AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect); + AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached); + AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate); + AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest); + } + + private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) + { + MoneyTransferRequestPacket money = (MoneyTransferRequestPacket)Pack; + // validate the agent owns the agentID and sessionID + if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && money.AgentData.SessionID == sender.SessionId) + { + + if (OnMoneyTransferRequest != null) + { + OnMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID, + money.MoneyData.Amount, money.MoneyData.TransactionType, + Util.FieldToString(money.MoneyData.Description)); + } + + return true; + } + else + { + return false; + } + } + + private bool HandleViewerEffect(IClientAPI sender, Packet Pack) + { + ViewerEffectPacket viewer = (ViewerEffectPacket)Pack; + + if (OnViewerEffect != null) + { + OnViewerEffect(sender, viewer.Effect); + } + + return true; + } + + protected virtual bool Logout(IClientAPI client, Packet packet) + { + m_log.Info("[CLIENT]: Got a logout request"); + + if (OnLogout != null) + { + OnLogout(client); + } + + return true; + } + + protected bool AgentTextureCached(IClientAPI simclient, Packet packet) + { + //System.Console.WriteLine("texture cached: " + packet.ToString()); + AgentCachedTexturePacket chechedtex = (AgentCachedTexturePacket)packet; + AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse); + // TODO: don't create new blocks if recycling an old packet + cachedresp.AgentData.AgentID = AgentId; + cachedresp.AgentData.SessionID = m_sessionId; + cachedresp.AgentData.SerialNum = m_cachedTextureSerial; + m_cachedTextureSerial++; + cachedresp.WearableData = + new AgentCachedTextureResponsePacket.WearableDataBlock[chechedtex.WearableData.Length]; + for (int i = 0; i < chechedtex.WearableData.Length; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = chechedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].TextureID = LLUUID.Zero; + cachedresp.WearableData[i].HostName = new byte[0]; + } + OutPacket(cachedresp, ThrottleOutPacketType.Texture); + return true; + } + + protected bool MultipleObjUpdate(IClientAPI simClient, Packet packet) + { + MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; + // System.Console.WriteLine("new multi update packet " + multipleupdate.ToString()); + Scene tScene = (Scene)m_scene; + + for (int i = 0; i < multipleupdate.ObjectData.Length; i++) + { + MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i]; + + // Can't act on Null Data + if (block.Data != null) + { + uint localId = block.ObjectLocalID; + SceneObjectPart part = tScene.GetSceneObjectPart(localId); + + if (part == null) + { + // It's a ghost! tell the client to delete it from view. + simClient.SendKillObject(Scene.RegionInfo.RegionHandle, + localId); + } + else + { + LLUUID partId = part.UUID; + + + switch (block.Type) + { + case 1: + if (OnUpdatePrimSinglePosition != null) + { + LLVector3 pos = new LLVector3(block.Data, 0); + // System.Console.WriteLine("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + OnUpdatePrimSinglePosition(localId, pos, this); + } + break; + case 2: + if (OnUpdatePrimSingleRotation != null) + { + LLQuaternion rot = new LLQuaternion(block.Data, 0, true); + //System.Console.WriteLine("new tab rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W); + OnUpdatePrimSingleRotation(localId, rot, this); + } + break; + case 3: + if (OnUpdatePrimSingleRotation != null) + { + LLQuaternion rot = new LLQuaternion(block.Data, 12, true); + //System.Console.WriteLine("new mouse rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W); + OnUpdatePrimSingleRotation(localId, rot, this); + } + break; + case 5: + if (OnUpdatePrimScale != null) + { + LLVector3 scale = new LLVector3(block.Data, 12); + // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + OnUpdatePrimScale(localId, scale, this); + } + break; + case 9: + if (OnUpdatePrimGroupPosition != null) + { + LLVector3 pos = new LLVector3(block.Data, 0); + OnUpdatePrimGroupPosition(localId, pos, this); + } + break; + case 10: + if (OnUpdatePrimGroupRotation != null) + { + LLQuaternion rot = new LLQuaternion(block.Data, 0, true); + // Console.WriteLine("new rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W); + OnUpdatePrimGroupRotation(localId, rot, this); + } + break; + case 11: + if (OnUpdatePrimGroupMouseRotation != null) + { + LLVector3 pos = new LLVector3(block.Data, 0); + LLQuaternion rot = new LLQuaternion(block.Data, 12, true); + //Console.WriteLine("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + // Console.WriteLine("new rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W); + OnUpdatePrimGroupMouseRotation(localId, pos, rot, + this); + } + break; + case 13: + if (OnUpdatePrimScale != null) + { + LLVector3 scale = new LLVector3(block.Data, 12); + //Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + OnUpdatePrimScale(localId, scale, this); + + // Change the position based on scale (for bug number 246) + LLVector3 pos = new LLVector3(block.Data, 0); + // System.Console.WriteLine("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); + OnUpdatePrimSinglePosition(localId, pos, this); + } + break; + case 29: + if (OnUpdatePrimScale != null) + { + LLVector3 scale = new LLVector3(block.Data, 12); + // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z ); + OnUpdatePrimScale(localId, scale, this); + LLVector3 pos = new LLVector3(block.Data, 0); + OnUpdatePrimSinglePosition(localId, pos, this); + } + break; + case 21: + if (OnUpdatePrimScale != null) + { + LLVector3 scale = new LLVector3(block.Data, 12); + // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + OnUpdatePrimScale(localId, scale, this); + } + break; + } + } + } + } + return true; + } + + public void RequestMapLayer() + { + //should be getting the map layer from the grid server + //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area) + MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply); + // TODO: don't create new blocks if recycling an old packet + mapReply.AgentData.AgentID = AgentId; + mapReply.AgentData.Flags = 0; + mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1]; + mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock(); + mapReply.LayerData[0].Bottom = 0; + mapReply.LayerData[0].Left = 0; + mapReply.LayerData[0].Top = 30000; + mapReply.LayerData[0].Right = 30000; + mapReply.LayerData[0].ImageID = new LLUUID("00000000-0000-0000-9999-000000000006"); + OutPacket(mapReply, ThrottleOutPacketType.Land); + } + + public void RequestMapBlocks(int minX, int minY, int maxX, int maxY) + { + /* + IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY); + MapBlockReplyPacket mbReply = new MapBlockReplyPacket(); + mbReply.AgentData.AgentId = this.AgentId; + int len; + if (simMapProfiles == null) + len = 0; + else + len = simMapProfiles.Count; + + mbReply.Data = new MapBlockReplyPacket.DataBlock[len]; + int iii; + for (iii = 0; iii < len; iii++) + { + Hashtable mp = (Hashtable)simMapProfiles[iii]; + mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock(); + mbReply.Data[iii].Name = System.Text.Encoding.UTF8.GetBytes((string)mp["name"]); + mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]); + mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]); + mbReply.Data[iii].MapImageID = new LLUUID((string)mp["map-image-id"]); + mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]); + mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]); + mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]); + mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]); + } + this.OutPacket(mbReply, ThrottleOutPacketType.Land); + */ + } + + public byte[] GetThrottlesPacked(float multiplier) + { + return m_packetQueue.GetThrottlesPacked(multiplier); + } + + public void SetChildAgentThrottle(byte[] throttles) + { + m_packetQueue.SetThrottleFromClient(throttles); + } + + // Previously ClientView.m_packetQueue + + // A thread safe sequence number allocator. + protected uint NextSeqNum() + { + // Set the sequence number + uint seq = 1; + lock (m_sequenceLock) + { + if (m_sequence >= MAX_SEQUENCE) + { + m_sequence = 1; + } + else + { + m_sequence++; + } + seq = m_sequence; + } + return seq; + } + + protected void AddAck(Packet Pack) + { + lock (m_needAck) + { + if (!m_needAck.ContainsKey(Pack.Header.Sequence)) + { + try + { + m_needAck.Add(Pack.Header.Sequence, Pack); + m_unAckedBytes += Pack.ToBytes().Length; + } + catch (Exception) // HACKY + { + // Ignore + // Seems to throw a exception here occasionally + // of 'duplicate key' despite being locked. + // !?!?!? + } + } + else + { + // Client.Log("Attempted to add a duplicate sequence number (" + + // packet.Header.m_sequence + ") to the m_needAck dictionary for packet type " + + // packet.Type.ToString(), Helpers.LogLevel.Warning); + } + } + } + + protected virtual void SetPendingAcks(ref Packet Pack) + { + // Append any ACKs that need to be sent out to this packet + lock (m_pendingAcks) + { + // TODO: If we are over MAX_APPENDED_ACKS we should drain off some of these + if (m_pendingAcks.Count > 0 && m_pendingAcks.Count < MAX_APPENDED_ACKS) + { + Pack.Header.AckList = new uint[m_pendingAcks.Count]; + int i = 0; + + foreach (uint ack in m_pendingAcks.Values) + { + Pack.Header.AckList[i] = ack; + i++; + } + + m_pendingAcks.Clear(); + Pack.Header.AppendedAcks = true; + } + } + } + + protected virtual void ProcessOutPacket(Packet Pack) + { + // Keep track of when this packet was sent out + Pack.TickCount = System.Environment.TickCount; + + if (!Pack.Header.Resent) + { + Pack.Header.Sequence = NextSeqNum(); + + if (Pack.Header.Reliable) //DIRTY HACK + { + AddAck(Pack); // this adds the need to ack this packet later + + + if (Pack.Type != PacketType.PacketAck && Pack.Type != PacketType.LogoutRequest) + { + SetPendingAcks(ref Pack); + } + } + } + + // Actually make the byte array and send it + try + { + byte[] sendbuffer = Pack.ToBytes(); + PacketPool.Instance.ReturnPacket(Pack); + + if (Pack.Header.Zerocoded) + { + int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer); + m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, m_circuitCode); + } + else + { + m_networkServer.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, m_circuitCode); + } + } + catch (Exception e) + { + m_log.Warn("[client]: " + + "ClientView.m_packetQueue.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + + m_userEndPoint.ToString() + " - killing thread"); + m_log.Error(e.ToString()); + Close(true); + } + } + + public virtual void InPacket(Packet NewPack) + { + // Handle appended ACKs + if (NewPack != null) + { + if (NewPack.Header.AppendedAcks) + { + lock (m_needAck) + { + foreach (uint ackedPacketId in NewPack.Header.AckList) + { + Packet ackedPacket; + + if (m_needAck.TryGetValue(ackedPacketId, out ackedPacket)) + { + m_unAckedBytes -= ackedPacket.ToBytes().Length; + m_needAck.Remove(ackedPacketId); + } + } + } + } + + + // Handle PacketAck packets + if (NewPack.Type == PacketType.PacketAck) + { + PacketAckPacket ackPacket = (PacketAckPacket)NewPack; + + lock (m_needAck) + { + foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) + { + uint ackedPackId = block.ID; + Packet ackedPacket; + if (m_needAck.TryGetValue(ackedPackId, out ackedPacket)) + { + m_unAckedBytes -= ackedPacket.ToBytes().Length; + m_needAck.Remove(ackedPackId); + } + } + } + } + else if ((NewPack.Type == PacketType.StartPingCheck)) + { + //reply to pingcheck + StartPingCheckPacket startPing = (StartPingCheckPacket)NewPack; + CompletePingCheckPacket endPing = (CompletePingCheckPacket)PacketPool.Instance.GetPacket(PacketType.CompletePingCheck); + endPing.PingID.PingID = startPing.PingID.PingID; + OutPacket(endPing, ThrottleOutPacketType.Task); + } + else + { + QueItem item = new QueItem(); + item.Packet = NewPack; + item.Incoming = true; + m_packetQueue.Enqueue(item); + } + } + } + + public virtual void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType) + { + QueItem item = new QueItem(); + item.Packet = NewPack; + item.Incoming = false; + item.throttleType = throttlePacketType; // Packet throttle type + m_packetQueue.Enqueue(item); + m_packetsSent++; + } + + # region Low Level Packet Methods + + protected void ack_pack(Packet Pack) + { + if (Pack.Header.Reliable) + { + PacketAckPacket ack_it = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck); + // TODO: don't create new blocks if recycling an old packet + ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; + ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); + ack_it.Packets[0].ID = Pack.Header.Sequence; + ack_it.Header.Reliable = false; + + OutPacket(ack_it, ThrottleOutPacketType.Unknown); + } + /* + if (Pack.Header.Reliable) + { + lock (m_pendingAcks) + { + uint sequence = (uint)Pack.Header.m_sequence; + if (!m_pendingAcks.ContainsKey(sequence)) { m_pendingAcks[sequence] = sequence; } + } + }*/ + } + + protected void ResendUnacked() + { + int now = System.Environment.TickCount; + + lock (m_needAck) + { + foreach (Packet packet in m_needAck.Values) + { + if ((now - packet.TickCount > RESEND_TIMEOUT) && (!packet.Header.Resent)) + { + m_log.Info("[NETWORK]: Resending " + packet.Type.ToString() + " packet, " + + (now - packet.TickCount) + "ms have passed"); + + packet.Header.Resent = true; + OutPacket(packet, ThrottleOutPacketType.Resend); + } + } + } + } + + protected void SendAcks() + { + lock (m_pendingAcks) + { + if (m_pendingAcks.Count > 0) + { + if (m_pendingAcks.Count > 250) + { + // FIXME: Handle the odd case where we have too many pending ACKs queued up + m_log.Info("[NETWORK]: Too many ACKs queued up!"); + return; + } + + //m_log.Info("[NETWORK]: Sending PacketAck"); + + int i = 0; + PacketAckPacket acks = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck); + // TODO: don't create new blocks if recycling an old packet + acks.Packets = new PacketAckPacket.PacketsBlock[m_pendingAcks.Count]; + + foreach (uint ack in m_pendingAcks.Values) + { + acks.Packets[i] = new PacketAckPacket.PacketsBlock(); + acks.Packets[i].ID = ack; + i++; + } + + acks.Header.Reliable = false; + OutPacket(acks, ThrottleOutPacketType.Unknown); + + m_pendingAcks.Clear(); + } + } + } + + protected void AckTimer_Elapsed(object sender, ElapsedEventArgs ea) + { + + SendAcks(); + ResendUnacked(); + SendPacketStats(); + + } + + protected void SendPacketStats() + { + if (OnPacketStats != null) + { + OnPacketStats(m_packetsReceived - m_lastPacketsReceivedSentToScene, m_packetsSent - m_lastPacketsSentSentToScene, m_unAckedBytes); + m_lastPacketsReceivedSentToScene = m_packetsReceived; + m_lastPacketsSentSentToScene = m_packetsSent; + } + } + + #endregion + + // Previously ClientView.ProcessPackets + + public bool AddMoney(int debit) + { + if (m_moneyBalance + debit >= 0) + { + m_moneyBalance += debit; + SendMoneyBalance(LLUUID.Zero, true, Helpers.StringToField("Poof Poof!"), m_moneyBalance); + return true; + } + else + { + return false; + } + } + + protected void ProcessInPacket(Packet Pack) + { + ack_pack(Pack); + + if (ProcessPacketMethod(Pack)) + { + //there is a handler registered that handled this packet type + return; + } + else + { + Encoding _enc = Encoding.ASCII; + + switch (Pack.Type) + { + #region Scene/Avatar + + case PacketType.AvatarPropertiesRequest: + AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; + if (OnRequestAvatarProperties != null) + { + OnRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID); + } + break; + case PacketType.ChatFromViewer: + ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; + + string fromName = String.Empty; //ClientAvatar.firstname + " " + ClientAvatar.lastname; + byte[] message = inchatpack.ChatData.Message; + byte type = inchatpack.ChatData.Type; + LLVector3 fromPos = new LLVector3(); // ClientAvatar.Pos; + LLUUID fromAgentID = AgentId; + + int channel = inchatpack.ChatData.Channel; + + if (OnChatFromViewer != null) + { + ChatFromViewerArgs args = new ChatFromViewerArgs(); + args.Channel = channel; + args.From = fromName; + args.Message = Helpers.FieldToUTF8String(message); + args.Type = (ChatTypeEnum)type; + args.Position = fromPos; + + args.Scene = Scene; + args.Sender = this; + + OnChatFromViewer(this, args); + } + break; + case PacketType.ScriptDialogReply: + ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack; + int ch = rdialog.Data.ChatChannel; + byte[] msg = rdialog.Data.ButtonLabel; + if (OnChatFromViewer != null) + { + ChatFromViewerArgs args = new ChatFromViewerArgs(); + args.Channel = ch; + args.From = String.Empty; + args.Message = Helpers.FieldToUTF8String(msg); + args.Type = ChatTypeEnum.Shout; + args.Position = new LLVector3(); + args.Scene = Scene; + args.Sender = this; + OnChatFromViewer(this, args); + } + break; + case PacketType.ImprovedInstantMessage: + ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack; + string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName); + string IMmessage = Helpers.FieldToUTF8String(msgpack.MessageBlock.Message); + if (OnInstantMessage != null) + { + OnInstantMessage(this, msgpack.AgentData.AgentID, msgpack.AgentData.SessionID, + msgpack.MessageBlock.ToAgentID, msgpack.MessageBlock.ID, + msgpack.MessageBlock.Timestamp, IMfromName, IMmessage, + msgpack.MessageBlock.Dialog, msgpack.MessageBlock.FromGroup, + msgpack.MessageBlock.Offline, msgpack.MessageBlock.ParentEstateID, + msgpack.MessageBlock.Position, msgpack.MessageBlock.RegionID, + msgpack.MessageBlock.BinaryBucket); + } + break; + + case PacketType.AcceptFriendship: + AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack; + + // My guess is this is the folder to stick the calling card into + List callingCardFolders = new List(); + + LLUUID agentID = afriendpack.AgentData.AgentID; + LLUUID transactionID = afriendpack.TransactionBlock.TransactionID; + + for (int fi = 0; fi < afriendpack.FolderData.Length; fi++) + { + callingCardFolders.Add(afriendpack.FolderData[fi].FolderID); + } + + if (OnApproveFriendRequest != null) + { + OnApproveFriendRequest(this, agentID, transactionID, callingCardFolders); + } + + + break; + case PacketType.TerminateFriendship: + TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack; + LLUUID listOwnerAgentID = tfriendpack.AgentData.AgentID; + LLUUID exFriendID = tfriendpack.ExBlock.OtherID; + + if (OnTerminateFriendship != null) + { + OnTerminateFriendship(this, listOwnerAgentID, exFriendID); + } + + break; + case PacketType.RezObject: + RezObjectPacket rezPacket = (RezObjectPacket)Pack; + if (OnRezObject != null) + { + //rezPacket.RezData.BypassRaycast; + //rezPacket.RezData.RayEnd; + //rezPacket.RezData.RayEndIsIntersection; + //rezPacket.RezData.RayStart; + //rezPacket.RezData.RayTargetID; + //rezPacket.RezData.RemoveItem; + //rezPacket.RezData.RezSelected; + //rezPacket.RezData.FromTaskID; + //m_log.Info("[REZData]: " + rezPacket.ToString()); + OnRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd, + rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID, + rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection, + rezPacket.RezData.EveryoneMask, rezPacket.RezData.GroupMask, + rezPacket.RezData.NextOwnerMask, rezPacket.RezData.ItemFlags, + rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem, + rezPacket.RezData.FromTaskID); + } + break; + case PacketType.DeRezObject: + if (OnDeRezObject != null) + { + OnDeRezObject(Pack, this); + } + break; + case PacketType.ModifyLand: + ModifyLandPacket modify = (ModifyLandPacket)Pack; + //m_log.Info("[LAND]: LAND:" + modify.ToString()); + if (modify.ParcelData.Length > 0) + { + if (OnModifyTerrain != null) + { + for (int i = 0; i < modify.ParcelData.Length; i++) + { + OnModifyTerrain(modify.ModifyBlock.Height, modify.ModifyBlock.Seconds, + modify.ModifyBlock.BrushSize, + modify.ModifyBlock.Action, modify.ParcelData[i].North, + modify.ParcelData[i].West, modify.ParcelData[i].South, + modify.ParcelData[i].East, this); + } + } + } + break; + case PacketType.RegionHandshakeReply: + if (OnRegionHandShakeReply != null) + { + OnRegionHandShakeReply(this); + } + break; + case PacketType.AgentWearablesRequest: + if (OnRequestWearables != null) + { + OnRequestWearables(); + } + if (OnRequestAvatarsData != null) + { + OnRequestAvatarsData(this); + } + break; + case PacketType.AgentSetAppearance: + AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack; + if (OnSetAppearance != null) + { + OnSetAppearance(appear.ObjectData.TextureEntry, appear.VisualParam); + } + break; + case PacketType.AgentIsNowWearing: + if (OnAvatarNowWearing != null) + { + AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack; + AvatarWearingArgs wearingArgs = new AvatarWearingArgs(); + for (int i = 0; i < nowWearing.WearableData.Length; i++) + { + AvatarWearingArgs.Wearable wearable = + new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID, + nowWearing.WearableData[i].WearableType); + wearingArgs.NowWearing.Add(wearable); + } + OnAvatarNowWearing(this, wearingArgs); + } + break; + case PacketType.RezSingleAttachmentFromInv: + if (OnRezSingleAttachmentFromInv != null) + { + RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket) Pack; + OnRezSingleAttachmentFromInv(this, rez.ObjectData.ItemID, + rez.ObjectData.AttachmentPt, rez.ObjectData.ItemFlags, rez.ObjectData.NextOwnerMask); + } + break; + case PacketType.ObjectAttach: + if (OnObjectAttach != null) + { + ObjectAttachPacket att = (ObjectAttachPacket) Pack; + OnObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation); + } + break; + case PacketType.SetAlwaysRun: + SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack; + + if (OnSetAlwaysRun != null) + OnSetAlwaysRun(this, run.AgentData.AlwaysRun); + + break; + case PacketType.CompleteAgentMovement: + if (OnCompleteMovementToRegion != null) + { + OnCompleteMovementToRegion(); + } + break; + case PacketType.AgentUpdate: + if (OnAgentUpdate != null) + { + AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; + + OnAgentUpdate(this, agenUpdate); + //agenUpdate.AgentData.ControlFlags, agenUpdate.AgentData.BodyRotationa); + } + break; + case PacketType.AgentAnimation: + AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack; + for (int i = 0; i < AgentAni.AnimationList.Length; i++) + { + if (AgentAni.AnimationList[i].StartAnim) + { + if (OnStartAnim != null) + { + OnStartAnim(this, AgentAni.AnimationList[i].AnimID, 1); + } + } + else + { + if (OnStopAnim != null) + { + OnStopAnim(this, AgentAni.AnimationList[i].AnimID); + } + } + } + break; + case PacketType.AgentRequestSit: + if (OnAgentRequestSit != null) + { + AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack; + OnAgentRequestSit(this, agentRequestSit.AgentData.AgentID, + agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); + } + break; + case PacketType.AgentSit: + if (OnAgentSit != null) + { + AgentSitPacket agentSit = (AgentSitPacket)Pack; + OnAgentSit(this, agentSit.AgentData.AgentID); + } + break; + case PacketType.AvatarPickerRequest: + AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack; + AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData; + AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data; + //System.Console.WriteLine("Agent Sends:" + Helpers.FieldToUTF8String(querydata.Name)); + if (OnAvatarPickerRequest != null) + { + OnAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID, + Helpers.FieldToUTF8String(querydata.Name)); + } + break; + + #endregion + + #region Objects/m_sceneObjects + + case PacketType.ObjectLink: + ObjectLinkPacket link = (ObjectLinkPacket)Pack; + uint parentprimid = 0; + List childrenprims = new List(); + if (link.ObjectData.Length > 1) + { + parentprimid = link.ObjectData[0].ObjectLocalID; + + for (int i = 1; i < link.ObjectData.Length; i++) + { + childrenprims.Add(link.ObjectData[i].ObjectLocalID); + } + } + if (OnLinkObjects != null) + { + OnLinkObjects(parentprimid, childrenprims); + } + break; + case PacketType.ObjectDelink: + ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack; + + // It appears the prim at index 0 is not always the root prim (for + // instance, when one prim of a link set has been edited independently + // of the others). Therefore, we'll pass all the ids onto the delink + // method for it to decide which is the root. + List prims = new List(); + for (int i = 0; i < delink.ObjectData.Length; i++) + { + prims.Add(delink.ObjectData[i].ObjectLocalID); + } + + if (OnDelinkObjects != null) + { + OnDelinkObjects(prims); + } + + break; + case PacketType.ObjectAdd: + if (OnAddPrim != null) + { + ObjectAddPacket addPacket = (ObjectAddPacket)Pack; + PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket); + // m_log.Info("[REZData]: " + addPacket.ToString()); + //BypassRaycast: 1 + //RayStart: <69.79469, 158.2652, 98.40343> + //RayEnd: <61.97724, 141.995, 92.58341> + //RayTargetID: 00000000-0000-0000-0000-000000000000 + + OnAddPrim(AgentId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection); + } + break; + case PacketType.ObjectShape: + ObjectShapePacket shapePacket = (ObjectShapePacket)Pack; + for (int i = 0; i < shapePacket.ObjectData.Length; i++) + { + if (OnUpdatePrimShape != null) + { + OnUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID, + shapePacket.ObjectData[i]); + } + } + break; + case PacketType.ObjectExtraParams: + ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack; + if (OnUpdateExtraParams != null) + { + OnUpdateExtraParams(m_agentId, extraPar.ObjectData[0].ObjectLocalID, + extraPar.ObjectData[0].ParamType, + extraPar.ObjectData[0].ParamInUse, extraPar.ObjectData[0].ParamData); + } + break; + case PacketType.ObjectDuplicate: + ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack; + ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData; + for (int i = 0; i < dupe.ObjectData.Length; i++) + { + if (OnObjectDuplicate != null) + { + OnObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, + dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID, + AgentandGroupData.GroupID); + } + } + + break; + + case PacketType.ObjectSelect: + ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack; + for (int i = 0; i < incomingselect.ObjectData.Length; i++) + { + if (OnObjectSelect != null) + { + OnObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this); + } + } + break; + case PacketType.ObjectDeselect: + ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack; + for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) + { + if (OnObjectDeselect != null) + { + OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this); + } + } + break; + case PacketType.ObjectFlagUpdate: + ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack; + if (OnUpdatePrimFlags != null) + { + OnUpdatePrimFlags(flags.AgentData.ObjectLocalID, Pack, this); + } + break; + case PacketType.ObjectImage: + ObjectImagePacket imagePack = (ObjectImagePacket)Pack; + for (int i = 0; i < imagePack.ObjectData.Length; i++) + { + if (OnUpdatePrimTexture != null) + { + OnUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID, + imagePack.ObjectData[i].TextureEntry, this); + } + } + break; + case PacketType.ObjectGrab: + ObjectGrabPacket grab = (ObjectGrabPacket)Pack; + if (OnGrabObject != null) + { + OnGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this); + } + break; + case PacketType.ObjectGrabUpdate: + ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack; + if (OnGrabUpdate != null) + { + OnGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial, + grabUpdate.ObjectData.GrabPosition, this); + } + break; + case PacketType.ObjectDeGrab: + ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack; + if (OnDeGrabObject != null) + { + OnDeGrabObject(deGrab.ObjectData.LocalID, this); + } + break; + case PacketType.ObjectDescription: + ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack; + for (int i = 0; i < objDes.ObjectData.Length; i++) + { + if (OnObjectDescription != null) + { + OnObjectDescription(this, objDes.ObjectData[i].LocalID, + m_encoding.GetString(objDes.ObjectData[i].Description)); + } + } + break; + case PacketType.ObjectName: + ObjectNamePacket objName = (ObjectNamePacket)Pack; + for (int i = 0; i < objName.ObjectData.Length; i++) + { + if (OnObjectName != null) + { + OnObjectName(this, objName.ObjectData[i].LocalID, + m_encoding.GetString(objName.ObjectData[i].Name)); + } + } + break; + case PacketType.ObjectPermissions: + if (OnObjectPermissions != null) + { + ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack; + + LLUUID AgentID = newobjPerms.AgentData.AgentID; + LLUUID SessionID = newobjPerms.AgentData.SessionID; + + for (int i = 0; i < newobjPerms.ObjectData.Length; i++) + { + ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i]; + + + byte field = permChanges.Field; + uint localID = permChanges.ObjectLocalID; + uint mask = permChanges.Mask; + byte set = permChanges.Set; + + OnObjectPermissions(this, AgentID, SessionID, field, localID, mask, set); + } + } + + // Here's our data, + // PermField contains the field the info goes into + // PermField determines which mask we're changing + // + // chmask is the mask of the change + // setTF is whether we're adding it or taking it away + // + // objLocalID is the localID of the object. + + // Unfortunately, we have to pass the event the packet because objData is an array + // That means multiple object perms may be updated in a single packet. + + + break; + + case PacketType.RequestObjectPropertiesFamily: + //This powers the little tooltip that appears when you move your mouse over an object + RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack; + + + RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData; + + if (OnRequestObjectPropertiesFamily != null) + { + OnRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags, + packObjBlock.ObjectID); + } + + break; + + #endregion + + #region Inventory/Asset/Other related packets + + case PacketType.RequestImage: + RequestImagePacket imageRequest = (RequestImagePacket)Pack; + //Console.WriteLine("image request: " + Pack.ToString()); + for (int i = 0; i < imageRequest.RequestImage.Length; i++) + { + if (OnRequestTexture != null) + { + TextureRequestArgs args = new TextureRequestArgs(); + args.RequestedAssetID = imageRequest.RequestImage[i].Image; + args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel; + args.PacketNumber = imageRequest.RequestImage[i].Packet; + args.Priority = imageRequest.RequestImage[i].DownloadPriority; + + OnRequestTexture(this, args); + } + } + break; + case PacketType.TransferRequest: + //Console.WriteLine("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); + TransferRequestPacket transfer = (TransferRequestPacket)Pack; + m_assetCache.AddAssetRequest(this, transfer); + break; + case PacketType.AssetUploadRequest: + AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; + // Console.WriteLine("upload request " + Pack.ToString()); + // Console.WriteLine("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString()); + if (OnAssetUploadRequest != null) + { + LLUUID temp = LLUUID.Combine(request.AssetBlock.TransactionID, SecureSessionId); + OnAssetUploadRequest(this, temp, + request.AssetBlock.TransactionID, request.AssetBlock.Type, + request.AssetBlock.AssetData, request.AssetBlock.StoreLocal, + request.AssetBlock.Tempfile); + } + break; + case PacketType.RequestXfer: + RequestXferPacket xferReq = (RequestXferPacket)Pack; + if (OnRequestXfer != null) + { + OnRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename)); + } + break; + case PacketType.SendXferPacket: + SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack; + if (OnXferReceive != null) + { + OnXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); + } + break; + case PacketType.ConfirmXferPacket: + ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; + if (OnConfirmXfer != null) + { + OnConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); + } + break; + case PacketType.CreateInventoryFolder: + if (OnCreateNewInventoryFolder != null) + { + CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack; + OnCreateNewInventoryFolder(this, invFolder.FolderData.FolderID, + (ushort)invFolder.FolderData.Type, + Util.FieldToString(invFolder.FolderData.Name), + invFolder.FolderData.ParentID); + } + break; + case PacketType.UpdateInventoryFolder: + if (OnUpdateInventoryFolder != null) + { + UpdateInventoryFolderPacket invFolder = (UpdateInventoryFolderPacket)Pack; + for (int i = 0; i < invFolder.FolderData.Length; i++) + { + OnUpdateInventoryFolder(this, invFolder.FolderData[i].FolderID, + (ushort)invFolder.FolderData[i].Type, + Util.FieldToString(invFolder.FolderData[i].Name), + invFolder.FolderData[i].ParentID); + } + } + break; + case PacketType.MoveInventoryFolder: + if (OnMoveInventoryFolder != null) + { + MoveInventoryFolderPacket invFolder = (MoveInventoryFolderPacket)Pack; + for (int i = 0; i < invFolder.InventoryData.Length; i++) + { + OnMoveInventoryFolder(this, invFolder.InventoryData[i].FolderID, + invFolder.InventoryData[i].ParentID); + } + } + break; + case PacketType.CreateInventoryItem: + CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack; + if (OnCreateNewInventoryItem != null) + { + OnCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID, + createItem.InventoryBlock.FolderID, + createItem.InventoryBlock.CallbackID, + Util.FieldToString(createItem.InventoryBlock.Description), + Util.FieldToString(createItem.InventoryBlock.Name), + createItem.InventoryBlock.InvType, + createItem.InventoryBlock.Type, + createItem.InventoryBlock.WearableType, + createItem.InventoryBlock.NextOwnerMask); + } + break; + case PacketType.FetchInventory: + if (OnFetchInventory != null) + { + FetchInventoryPacket FetchInventory = (FetchInventoryPacket)Pack; + for (int i = 0; i < FetchInventory.InventoryData.Length; i++) + { + OnFetchInventory(this, FetchInventory.InventoryData[i].ItemID, + FetchInventory.InventoryData[i].OwnerID); + } + } + break; + case PacketType.FetchInventoryDescendents: + if (OnFetchInventoryDescendents != null) + { + FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack; + OnFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID, + Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems, + Fetch.InventoryData.SortOrder); + } + break; + case PacketType.PurgeInventoryDescendents: + if (OnPurgeInventoryDescendents != null) + { + PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack; + OnPurgeInventoryDescendents(this, Purge.InventoryData.FolderID); + } + break; + case PacketType.UpdateInventoryItem: + UpdateInventoryItemPacket update = (UpdateInventoryItemPacket)Pack; + if (OnUpdateInventoryItem != null) + { + for (int i = 0; i < update.InventoryData.Length; i++) + { + OnUpdateInventoryItem(this, update.InventoryData[i].TransactionID, + update.InventoryData[i].ItemID, + Util.FieldToString(update.InventoryData[i].Name), + Util.FieldToString(update.InventoryData[i].Description), + update.InventoryData[i].NextOwnerMask); + } + } + //Console.WriteLine(Pack.ToString()); + /*for (int i = 0; i < update.InventoryData.Length; i++) + { + if (update.InventoryData[i].TransactionID != LLUUID.Zero) + { + AssetBase asset = m_assetCache.GetAsset(update.InventoryData[i].TransactionID.Combine(this.SecureSessionId)); + if (asset != null) + { + // Console.WriteLine("updating inventory item, found asset" + asset.FullID.ToString() + " already in cache"); + m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset); + } + else + { + asset = this.UploadAssets.AddUploadToAssetCache(update.InventoryData[i].TransactionID); + if (asset != null) + { + //Console.WriteLine("updating inventory item, adding asset" + asset.FullID.ToString() + " to cache"); + m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset); + } + else + { + //Console.WriteLine("trying to update inventory item, but asset is null"); + } + } + } + else + { + m_inventoryCache.UpdateInventoryItemDetails(this, update.InventoryData[i].ItemID, update.InventoryData[i]); ; + } + }*/ + break; + case PacketType.CopyInventoryItem: + CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack; + if (OnCopyInventoryItem != null) + { + foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData) + { + OnCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID, + datablock.OldItemID, datablock.NewFolderID, + Util.FieldToString(datablock.NewName)); + } + } + break; + case PacketType.MoveInventoryItem: + MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack; + if (OnMoveInventoryItem != null) + { + foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData) + { + OnMoveInventoryItem(this, datablock.FolderID, datablock.ItemID, datablock.Length, + Util.FieldToString(datablock.NewName)); + } + } + break; + case PacketType.RemoveInventoryItem: + RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack; + if (OnRemoveInventoryItem != null) + { + foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData) + { + OnRemoveInventoryItem(this, datablock.ItemID); + } + } + break; + case PacketType.RemoveInventoryFolder: + RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack; + if (OnRemoveInventoryFolder != null) + { + foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData) + { + OnRemoveInventoryFolder(this, datablock.FolderID); + } + } + break; + case PacketType.RequestTaskInventory: + RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack; + if (OnRequestTaskInventory != null) + { + OnRequestTaskInventory(this, requesttask.InventoryData.LocalID); + } + break; + case PacketType.UpdateTaskInventory: + UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack; + if (OnUpdateTaskInventory != null) + { + if (updatetask.UpdateData.Key == 0) + { + OnUpdateTaskInventory(this, updatetask.InventoryData.ItemID, + updatetask.InventoryData.FolderID, updatetask.UpdateData.LocalID); + } + } + break; + case PacketType.RemoveTaskInventory: + RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack; + if (OnRemoveTaskItem != null) + { + OnRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID); + } + break; + case PacketType.MoveTaskInventory: + m_log.Warn("[CLIENT]: unhandled MoveTaskInventory packet"); + break; + case PacketType.RezScript: + //Console.WriteLine(Pack.ToString()); + RezScriptPacket rezScript = (RezScriptPacket)Pack; + if (OnRezScript != null) + { + OnRezScript(this, rezScript.InventoryBlock.ItemID, rezScript.UpdateBlock.ObjectLocalID); + } + break; + case PacketType.MapLayerRequest: + RequestMapLayer(); + break; + case PacketType.MapBlockRequest: + MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack; + if (OnRequestMapBlocks != null) + { + OnRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY, + MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY); + } + break; + case PacketType.MapNameRequest: + MapNameRequestPacket map = (MapNameRequestPacket)Pack; + string mapName = UTF8Encoding.UTF8.GetString(map.NameData.Name, 0, + map.NameData.Name.Length - 1); + if (OnMapNameRequest != null) + { + OnMapNameRequest(this, mapName); + } + break; + case PacketType.TeleportLandmarkRequest: + TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack; + + TeleportStartPacket tpStart = (TeleportStartPacket)PacketPool.Instance.GetPacket(PacketType.TeleportStart); + tpStart.Info.TeleportFlags = 8; // tp via lm + OutPacket(tpStart, ThrottleOutPacketType.Task); + + TeleportProgressPacket tpProgress = (TeleportProgressPacket)PacketPool.Instance.GetPacket(PacketType.TeleportProgress); + tpProgress.Info.Message = (new ASCIIEncoding()).GetBytes("sending_landmark"); + tpProgress.Info.TeleportFlags = 8; + tpProgress.AgentData.AgentID = tpReq.Info.AgentID; + OutPacket(tpProgress, ThrottleOutPacketType.Task); + + // Fetch landmark + LLUUID lmid = tpReq.Info.LandmarkID; + AssetBase lma = m_assetCache.GetAsset(lmid, false); + if (lma != null) + { + AssetLandmark lm = new AssetLandmark(lma); + + if (lm.RegionID == m_scene.RegionInfo.RegionID) + { + TeleportLocalPacket tpLocal = (TeleportLocalPacket)PacketPool.Instance.GetPacket(PacketType.TeleportLocal); + + tpLocal.Info.AgentID = tpReq.Info.AgentID; + tpLocal.Info.TeleportFlags = 8; // Teleport via landmark + tpLocal.Info.LocationID = 2; + tpLocal.Info.Position = lm.Position; + OutPacket(tpLocal, ThrottleOutPacketType.Task); + } + else + { + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.AgentID = tpReq.Info.AgentID; + tpCancel.Info.SessionID = tpReq.Info.SessionID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } + } + else + { + Console.WriteLine("Cancelling Teleport - fetch asset not yet implemented"); + + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.AgentID = tpReq.Info.AgentID; + tpCancel.Info.SessionID = tpReq.Info.SessionID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } + break; + case PacketType.TeleportLocationRequest: + TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; + // Console.WriteLine(tpLocReq.ToString()); + + if (OnTeleportLocationRequest != null) + { + OnTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, + tpLocReq.Info.LookAt, 16); + } + else + { + //no event handler so cancel request + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID; + tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } + break; + + #endregion + + case PacketType.MoneyBalanceRequest: + MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack; + if (OnMoneyBalanceRequest != null) + { + OnMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID); + } + + + break; + case PacketType.UUIDNameRequest: + UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; + foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) + { + OnNameFromUUIDRequest(UUIDBlock.ID, this); + } + break; + + #region Parcel related packets + + case PacketType.ParcelAccessListRequest: + ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack; + if (OnParcelAccessListRequest != null) + { + OnParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID, + requestPacket.Data.Flags, requestPacket.Data.SequenceID, + requestPacket.Data.LocalID, this); + } + break; + + case PacketType.ParcelAccessListUpdate: + ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack; + List entries = new List(); + foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = block.ID; + entry.Flags = (ParcelManager.AccessList)block.Flags; + entry.Time = new DateTime(); + entries.Add(entry); + } + + if (OnParcelAccessListUpdateRequest != null) + { + OnParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID, + updatePacket.AgentData.SessionID, updatePacket.Data.Flags, + updatePacket.Data.LocalID, entries, this); + } + break; + case PacketType.ParcelPropertiesRequest: + + ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack; + if (OnParcelPropertiesRequest != null) + { + OnParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West), + (int)Math.Round(propertiesRequest.ParcelData.South), + (int)Math.Round(propertiesRequest.ParcelData.East), + (int)Math.Round(propertiesRequest.ParcelData.North), + propertiesRequest.ParcelData.SequenceID, + propertiesRequest.ParcelData.SnapSelection, this); + } + break; + case PacketType.ParcelDivide: + ParcelDividePacket landDivide = (ParcelDividePacket)Pack; + if (OnParcelDivideRequest != null) + { + OnParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West), + (int)Math.Round(landDivide.ParcelData.South), + (int)Math.Round(landDivide.ParcelData.East), + (int)Math.Round(landDivide.ParcelData.North), this); + } + break; + case PacketType.ParcelJoin: + ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack; + if (OnParcelJoinRequest != null) + { + OnParcelJoinRequest((int)Math.Round(landJoin.ParcelData.West), + (int)Math.Round(landJoin.ParcelData.South), + (int)Math.Round(landJoin.ParcelData.East), + (int)Math.Round(landJoin.ParcelData.North), this); + } + break; + case PacketType.ParcelPropertiesUpdate: + ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack; + if (OnParcelPropertiesUpdateRequest != null) + { + OnParcelPropertiesUpdateRequest(parcelPropertiesPacket, this); + } + break; + case PacketType.ParcelSelectObjects: + ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack; + if (OnParcelSelectObjects != null) + { + OnParcelSelectObjects(selectPacket.ParcelData.LocalID, + Convert.ToInt32(selectPacket.ParcelData.ReturnType), this); + } + break; + case PacketType.ParcelObjectOwnersRequest: + //System.Console.WriteLine(Pack.ToString()); + ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack; + if (OnParcelObjectOwnerRequest != null) + { + OnParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this); + } + break; + + #endregion + + #region Estate Packets + + case PacketType.EstateOwnerMessage: + EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack; + if (OnEstateOwnerMessage != null) + { + OnEstateOwnerMessage(messagePacket, this); + } + break; + case PacketType.RequestRegionInfo: + RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData; + if (OnRegionInfoRequest != null) + { + OnRegionInfoRequest(this, mPacket.SessionID); + } + break; + case PacketType.EstateCovenantRequest: + // TODO: handle this packet + EstateCovenantRequestPacket.AgentDataBlock epack = + ((EstateCovenantRequestPacket)Pack).AgentData; + if (OnEstateCovenantRequest != null) + { + OnEstateCovenantRequest(this, epack.SessionID); + } + break; + case PacketType.AgentThrottle: + AgentThrottlePacket atpack = (AgentThrottlePacket)Pack; + m_packetQueue.SetThrottleFromClient(atpack.Throttle.Throttles); + break; + + #endregion + + #region unimplemented handlers + + case PacketType.RequestGodlikePowers: + RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack; + RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock; + LLUUID token = rblock.Token; + RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData; + + OnRequestGodlikePowers(ablock.AgentID, ablock.SessionID, token, this); + + break; + case PacketType.GodKickUser: + m_log.Warn("[CLIENT]: unhandled GodKickUser packet"); + + GodKickUserPacket gkupack = (GodKickUserPacket)Pack; + + if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID) + { + OnGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID, + gkupack.UserInfo.AgentID, (uint)0, gkupack.UserInfo.Reason); + } + else + { + SendAgentAlertMessage("Kick request denied", false); + } + //KickUserPacket kupack = new KickUserPacket(); + //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo; + + //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID; + //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID; + + //kupack.TargetBlock.TargetIP = (uint)0; + //kupack.TargetBlock.TargetPort = (ushort)0; + //kupack.UserInfo.Reason = gkupack.UserInfo.Reason; + + //OutPacket(kupack, ThrottleOutPacketType.Task); + break; + + case PacketType.StartPingCheck: + // Send the client the ping response back + // Pass the same PingID in the matching packet + // Handled In the packet processing + //m_log.Debug("[CLIENT]: possibly unhandled StartPingCheck packet"); + break; + case PacketType.CompletePingCheck: + // TODO: Perhaps this should be processed on the Sim to determine whether or not to drop a dead client + //m_log.Warn("[CLIENT]: unhandled CompletePingCheck packet"); + break; + case PacketType.ObjectScale: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled ObjectScale packet"); + break; + case PacketType.ViewerStats: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled ViewerStats packet"); + break; + + case PacketType.CreateGroupRequest: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled CreateGroupRequest packet"); + break; + case PacketType.GenericMessage: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled GenericMessage packet"); + break; + case PacketType.MapItemRequest: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled MapItemRequest packet"); + break; + case PacketType.AgentResume: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled AgentResume packet"); + break; + case PacketType.AgentPause: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled AgentPause packet"); + break; + case PacketType.TransferAbort: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled TransferAbort packet"); + break; + case PacketType.MuteListRequest: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled MuteListRequest packet"); + break; + case PacketType.AgentDataUpdateRequest: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled AgentDataUpdateRequest packet"); + break; + + case PacketType.ParcelDwellRequest: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled ParcelDwellRequest packet"); + break; + case PacketType.UseCircuitCode: + // TODO: handle this packet + //m_log.Warn("[CLIENT]: unhandled UseCircuitCode packet"); + break; + case PacketType.EconomyDataRequest: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled EconomyDataRequest packet"); + break; + case PacketType.AgentHeightWidth: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled AgentHeightWidth packet"); + break; + case PacketType.ObjectSpinStop: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet"); + break; + case PacketType.SoundTrigger: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled SoundTrigger packet"); + break; + case PacketType.UserInfoRequest: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled UserInfoRequest packet"); + break; + case PacketType.InventoryDescendents: + // TODO: handle this packet + m_log.Warn("[CLIENT]: unhandled InventoryDescent packet"); + break; + default: + m_log.Warn("[CLIENT]: unhandled packet " + Pack.ToString()); + break; + + #endregion + } + } + + PacketPool.Instance.ReturnPacket(Pack); + } + + private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) + { + PrimitiveBaseShape shape = new PrimitiveBaseShape(); + + shape.PCode = addPacket.ObjectData.PCode; + shape.State = addPacket.ObjectData.State; + shape.PathBegin = addPacket.ObjectData.PathBegin; + shape.PathEnd = addPacket.ObjectData.PathEnd; + shape.PathScaleX = addPacket.ObjectData.PathScaleX; + shape.PathScaleY = addPacket.ObjectData.PathScaleY; + shape.PathShearX = addPacket.ObjectData.PathShearX; + shape.PathShearY = addPacket.ObjectData.PathShearY; + shape.PathSkew = addPacket.ObjectData.PathSkew; + shape.ProfileBegin = addPacket.ObjectData.ProfileBegin; + shape.ProfileEnd = addPacket.ObjectData.ProfileEnd; + shape.Scale = addPacket.ObjectData.Scale; + shape.PathCurve = addPacket.ObjectData.PathCurve; + shape.ProfileCurve = addPacket.ObjectData.ProfileCurve; + shape.ProfileHollow = addPacket.ObjectData.ProfileHollow; + shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset; + shape.PathRevolutions = addPacket.ObjectData.PathRevolutions; + shape.PathTaperX = addPacket.ObjectData.PathTaperX; + shape.PathTaperY = addPacket.ObjectData.PathTaperY; + shape.PathTwist = addPacket.ObjectData.PathTwist; + shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin; + LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("89556747-24cb-43ed-920b-47caed15465f")); + shape.TextureEntry = ntex.ToBytes(); + //shape.Textures = ntex; + return shape; + } + + public void SendBlueBoxMessage(LLUUID FromAvatarID, LLUUID fromSessionID, String FromAvatarName, String Message) + { + if (!ChildAgentStatus()) + SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)1, (uint)Util.UnixTimeSinceEpoch()); + + //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch()); + } + + public void SendLogoutPacket() + { + LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply); + // TODO: don't create new blocks if recycling an old packet + logReply.AgentData.AgentID = AgentId; + logReply.AgentData.SessionID = SessionId; + logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1]; + logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock(); + logReply.InventoryData[0].ItemID = LLUUID.Zero; + + OutPacket(logReply, ThrottleOutPacketType.Task); + } + } +} diff --git a/trunk/OpenSim/Region/ClientStack/PacketQueue.cs b/trunk/OpenSim/Region/ClientStack/PacketQueue.cs new file mode 100644 index 0000000000..8b2a93a7ca --- /dev/null +++ b/trunk/OpenSim/Region/ClientStack/PacketQueue.cs @@ -0,0 +1,487 @@ +/* +* 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; +using System.Collections.Generic; +using System.Threading; +using System.Timers; +using libsecondlife.Packets; +using OpenSim.Framework; +using Timer=System.Timers.Timer; + +namespace OpenSim.Region.ClientStack +{ + public class PacketQueue + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private bool m_enabled = true; + + private BlockingQueue SendQueue; + + private Queue IncomingPacketQueue; + private Queue OutgoingPacketQueue; + private Queue ResendOutgoingPacketQueue; + private Queue LandOutgoingPacketQueue; + private Queue WindOutgoingPacketQueue; + private Queue CloudOutgoingPacketQueue; + private Queue TaskOutgoingPacketQueue; + private Queue TextureOutgoingPacketQueue; + private Queue AssetOutgoingPacketQueue; + + private Dictionary PendingAcks = new Dictionary(); + private Dictionary NeedAck = new Dictionary(); + + // All throttle times and number of bytes are calculated by dividing by this value + // This value also determines how many times per throttletimems the timer will run + // If throttleimems is 1000 ms, then the timer will fire every 1000/7 milliseconds + + private int throttleTimeDivisor = 7; + + private int throttletimems = 1000; + + private PacketThrottle ResendThrottle; + private PacketThrottle LandThrottle; + private PacketThrottle WindThrottle; + private PacketThrottle CloudThrottle; + private PacketThrottle TaskThrottle; + private PacketThrottle AssetThrottle; + private PacketThrottle TextureThrottle; + private PacketThrottle TotalThrottle; + + // private long LastThrottle; + // private long ThrottleInterval; + private Timer throttleTimer; + + public PacketQueue() + { + // While working on this, the BlockingQueue had me fooled for a bit. + // The Blocking queue causes the thread to stop until there's something + // in it to process. it's an on-purpose threadlock though because + // without it, the clientloop will suck up all sim resources. + + SendQueue = new BlockingQueue(); + + IncomingPacketQueue = new Queue(); + OutgoingPacketQueue = new Queue(); + ResendOutgoingPacketQueue = new Queue(); + LandOutgoingPacketQueue = new Queue(); + WindOutgoingPacketQueue = new Queue(); + CloudOutgoingPacketQueue = new Queue(); + TaskOutgoingPacketQueue = new Queue(); + TextureOutgoingPacketQueue = new Queue(); + AssetOutgoingPacketQueue = new Queue(); + + + // Set up the throttle classes (min, max, current) in bytes + ResendThrottle = new PacketThrottle(5000, 100000, 50000); + LandThrottle = new PacketThrottle(1000, 100000, 100000); + WindThrottle = new PacketThrottle(1000, 100000, 10000); + CloudThrottle = new PacketThrottle(1000, 100000, 50000); + TaskThrottle = new PacketThrottle(1000, 800000, 100000); + AssetThrottle = new PacketThrottle(1000, 800000, 80000); + TextureThrottle = new PacketThrottle(1000, 800000, 100000); + // Total Throttle trumps all + // Number of bytes allowed to go out per second. (256kbps per client) + TotalThrottle = new PacketThrottle(0, 162144, 1536000); + + throttleTimer = new Timer((int) (throttletimems/throttleTimeDivisor)); + throttleTimer.Elapsed += new ElapsedEventHandler(ThrottleTimerElapsed); + throttleTimer.Start(); + + // TIMERS needed for this + // LastThrottle = DateTime.Now.Ticks; + // ThrottleInterval = (long)(throttletimems/throttleTimeDivisor); + } + + /* STANDARD QUEUE MANIPULATION INTERFACES */ + + + public void Enqueue(QueItem item) + { + if (!m_enabled) + { + return; + } + // We could micro lock, but that will tend to actually + // probably be worse than just synchronizing on SendQueue + + lock (this) + { + switch (item.throttleType) + { + case ThrottleOutPacketType.Resend: + ThrottleCheck(ref ResendThrottle, ref ResendOutgoingPacketQueue, item); + break; + case ThrottleOutPacketType.Texture: + ThrottleCheck(ref TextureThrottle, ref TextureOutgoingPacketQueue, item); + break; + case ThrottleOutPacketType.Task: + ThrottleCheck(ref TaskThrottle, ref TaskOutgoingPacketQueue, item); + break; + case ThrottleOutPacketType.Land: + ThrottleCheck(ref LandThrottle, ref LandOutgoingPacketQueue, item); + break; + case ThrottleOutPacketType.Asset: + ThrottleCheck(ref AssetThrottle, ref AssetOutgoingPacketQueue, item); + break; + case ThrottleOutPacketType.Cloud: + ThrottleCheck(ref CloudThrottle, ref CloudOutgoingPacketQueue, item); + break; + case ThrottleOutPacketType.Wind: + ThrottleCheck(ref WindThrottle, ref WindOutgoingPacketQueue, item); + break; + + default: + // Acknowledgements and other such stuff should go directly to the blocking Queue + // Throttling them may and likely 'will' be problematic + SendQueue.Enqueue(item); + break; + } + } + } + + public QueItem Dequeue() + { + return SendQueue.Dequeue(); + } + + public void Flush() + { + lock (this) + { + while (PacketsWaiting()) + { + //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up. + if (ResendOutgoingPacketQueue.Count > 0) + { + SendQueue.Enqueue(ResendOutgoingPacketQueue.Dequeue()); + } + if (LandOutgoingPacketQueue.Count > 0) + { + SendQueue.Enqueue(LandOutgoingPacketQueue.Dequeue()); + } + if (WindOutgoingPacketQueue.Count > 0) + { + SendQueue.Enqueue(WindOutgoingPacketQueue.Dequeue()); + } + if (CloudOutgoingPacketQueue.Count > 0) + { + SendQueue.Enqueue(CloudOutgoingPacketQueue.Dequeue()); + } + if (TaskOutgoingPacketQueue.Count > 0) + { + SendQueue.Enqueue(TaskOutgoingPacketQueue.Dequeue()); + } + if (TextureOutgoingPacketQueue.Count > 0) + { + SendQueue.Enqueue(TextureOutgoingPacketQueue.Dequeue()); + } + if (AssetOutgoingPacketQueue.Count > 0) + { + SendQueue.Enqueue(AssetOutgoingPacketQueue.Dequeue()); + } + } + // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); + } + } + + public void Close() + { + m_enabled = false; + throttleTimer.Stop(); + } + + private void ResetCounters() + { + ResendThrottle.Reset(); + LandThrottle.Reset(); + WindThrottle.Reset(); + CloudThrottle.Reset(); + TaskThrottle.Reset(); + AssetThrottle.Reset(); + TextureThrottle.Reset(); + TotalThrottle.Reset(); + } + + private bool PacketsWaiting() + { + return (ResendOutgoingPacketQueue.Count > 0 || + LandOutgoingPacketQueue.Count > 0 || + WindOutgoingPacketQueue.Count > 0 || + CloudOutgoingPacketQueue.Count > 0 || + TaskOutgoingPacketQueue.Count > 0 || + AssetOutgoingPacketQueue.Count > 0 || + TextureOutgoingPacketQueue.Count > 0); + } + + public void ProcessThrottle() + { + // I was considering this.. Will an event fire if the thread it's on is blocked? + + // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long + // The General overhead of the UDP protocol gets sent to the queue un-throttled by this + // so This'll pick up about around the right time. + + int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once. + int throttleLoops = 0; + + // We're going to dequeue all of the saved up packets until + // we've hit the throttle limit or there's no more packets to send + lock (this) + { + ResetCounters(); + // m_log.Info("[THROTTLE]: Entering Throttle"); + while (TotalThrottle.UnderLimit() && PacketsWaiting() && + (throttleLoops <= MaxThrottleLoops)) + { + throttleLoops++; + //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up. + if (ResendThrottle.UnderLimit() && ResendOutgoingPacketQueue.Count > 0) + { + QueItem qpack = ResendOutgoingPacketQueue.Dequeue(); + + SendQueue.Enqueue(qpack); + TotalThrottle.Add(qpack.Packet.ToBytes().Length); + ResendThrottle.Add(qpack.Packet.ToBytes().Length); + } + if (LandThrottle.UnderLimit() && LandOutgoingPacketQueue.Count > 0) + { + QueItem qpack = LandOutgoingPacketQueue.Dequeue(); + + SendQueue.Enqueue(qpack); + TotalThrottle.Add(qpack.Packet.ToBytes().Length); + LandThrottle.Add(qpack.Packet.ToBytes().Length); + } + if (WindThrottle.UnderLimit() && WindOutgoingPacketQueue.Count > 0) + { + QueItem qpack = WindOutgoingPacketQueue.Dequeue(); + + SendQueue.Enqueue(qpack); + TotalThrottle.Add(qpack.Packet.ToBytes().Length); + WindThrottle.Add(qpack.Packet.ToBytes().Length); + } + if (CloudThrottle.UnderLimit() && CloudOutgoingPacketQueue.Count > 0) + { + QueItem qpack = CloudOutgoingPacketQueue.Dequeue(); + + SendQueue.Enqueue(qpack); + TotalThrottle.Add(qpack.Packet.ToBytes().Length); + CloudThrottle.Add(qpack.Packet.ToBytes().Length); + } + if (TaskThrottle.UnderLimit() && TaskOutgoingPacketQueue.Count > 0) + { + QueItem qpack = TaskOutgoingPacketQueue.Dequeue(); + + SendQueue.Enqueue(qpack); + TotalThrottle.Add(qpack.Packet.ToBytes().Length); + TaskThrottle.Add(qpack.Packet.ToBytes().Length); + } + if (TextureThrottle.UnderLimit() && TextureOutgoingPacketQueue.Count > 0) + { + QueItem qpack = TextureOutgoingPacketQueue.Dequeue(); + + SendQueue.Enqueue(qpack); + TotalThrottle.Add(qpack.Packet.ToBytes().Length); + TextureThrottle.Add(qpack.Packet.ToBytes().Length); + } + if (AssetThrottle.UnderLimit() && AssetOutgoingPacketQueue.Count > 0) + { + QueItem qpack = AssetOutgoingPacketQueue.Dequeue(); + + SendQueue.Enqueue(qpack); + TotalThrottle.Add(qpack.Packet.ToBytes().Length); + AssetThrottle.Add(qpack.Packet.ToBytes().Length); + } + } + // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); + } + } + + private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e) + { + // just to change the signature, and that ProcessThrottle + // will be used elsewhere possibly + ProcessThrottle(); + } + + private void ThrottleCheck(ref PacketThrottle throttle, ref Queue q, QueItem item) + { + // The idea.. is if the packet throttle queues are empty + // and the client is under throttle for the type. Queue + // it up directly. This basically short cuts having to + // wait for the timer to fire to put things into the + // output queue + + if ((q.Count == 0) && (throttle.UnderLimit())) + { + Monitor.Enter(this); + throttle.Add(item.Packet.ToBytes().Length); + TotalThrottle.Add(item.Packet.ToBytes().Length); + SendQueue.Enqueue(item); + Monitor.Pulse(this); + Monitor.Exit(this); + } + else + { + q.Enqueue(item); + } + } + + + private int ScaleThrottle(int value, int curmax, int newmax) + { + return (int) (((float) value/(float) curmax)*newmax); + } + + public byte[] GetThrottlesPacked(float multiplier) + { + int singlefloat = 4; + float tResend = ResendThrottle.Throttle*multiplier; + float tLand = LandThrottle.Throttle*multiplier; + float tWind = WindThrottle.Throttle*multiplier; + float tCloud = CloudThrottle.Throttle*multiplier; + float tTask = TaskThrottle.Throttle*multiplier; + float tTexture = TextureThrottle.Throttle*multiplier; + float tAsset = AssetThrottle.Throttle*multiplier; + + byte[] throttles = new byte[singlefloat*7]; + int i = 0; + Buffer.BlockCopy(BitConverter.GetBytes(tResend), 0, throttles, singlefloat*i, singlefloat); + i++; + Buffer.BlockCopy(BitConverter.GetBytes(tLand), 0, throttles, singlefloat*i, singlefloat); + i++; + Buffer.BlockCopy(BitConverter.GetBytes(tWind), 0, throttles, singlefloat*i, singlefloat); + i++; + Buffer.BlockCopy(BitConverter.GetBytes(tCloud), 0, throttles, singlefloat*i, singlefloat); + i++; + Buffer.BlockCopy(BitConverter.GetBytes(tTask), 0, throttles, singlefloat*i, singlefloat); + i++; + Buffer.BlockCopy(BitConverter.GetBytes(tTexture), 0, throttles, singlefloat*i, singlefloat); + i++; + Buffer.BlockCopy(BitConverter.GetBytes(tAsset), 0, throttles, singlefloat*i, singlefloat); + + return throttles; + } + + public void SetThrottleFromClient(byte[] throttle) + { + int tResend = -1; + int tLand = -1; + int tWind = -1; + int tCloud = -1; + int tTask = -1; + int tTexture = -1; + int tAsset = -1; + int tall = -1; + int singlefloat = 4; + + //Agent Throttle Block contains 7 single floatingpoint values. + int j = 0; + + // Some Systems may be big endian... + // it might be smart to do this check more often... + if (!BitConverter.IsLittleEndian) + for (int i = 0; i < 7; i++) + Array.Reverse(throttle, j + i*singlefloat, singlefloat); + + // values gotten from libsecondlife.org/wiki/Throttle. Thanks MW_ + // bytes + // Convert to integer, since.. the full fp space isn't used. + tResend = (int) BitConverter.ToSingle(throttle, j); + j += singlefloat; + tLand = (int) BitConverter.ToSingle(throttle, j); + j += singlefloat; + tWind = (int) BitConverter.ToSingle(throttle, j); + j += singlefloat; + tCloud = (int) BitConverter.ToSingle(throttle, j); + j += singlefloat; + tTask = (int) BitConverter.ToSingle(throttle, j); + j += singlefloat; + tTexture = (int) BitConverter.ToSingle(throttle, j); + j += singlefloat; + tAsset = (int) BitConverter.ToSingle(throttle, j); + + tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset; + /* + m_log.Info("[CLIENT]: Client AgentThrottle - Got throttle:resendbytes=" + tResend + + " landbytes=" + tLand + + " windbytes=" + tWind + + " cloudbytes=" + tCloud + + " taskbytes=" + tTask + + " texturebytes=" + tTexture + + " Assetbytes=" + tAsset + + " Allbytes=" + tall); + */ + + // Total Sanity + // Make sure that the client sent sane total values. + + // If the client didn't send acceptable values.... + // Scale the clients values down until they are acceptable. + + if (tall <= TotalThrottle.Max) + { + ResendThrottle.Throttle = tResend; + LandThrottle.Throttle = tLand; + WindThrottle.Throttle = tWind; + CloudThrottle.Throttle = tCloud; + TaskThrottle.Throttle = tTask; + TextureThrottle.Throttle = tTexture; + AssetThrottle.Throttle = tAsset; + TotalThrottle.Throttle = tall; + } + else if (tall < 1) + { + // client is stupid, penalize him by minning everything + ResendThrottle.Throttle = ResendThrottle.Min; + LandThrottle.Throttle = LandThrottle.Min; + WindThrottle.Throttle = WindThrottle.Min; + CloudThrottle.Throttle = CloudThrottle.Min; + TaskThrottle.Throttle = TaskThrottle.Min; + TextureThrottle.Throttle = TextureThrottle.Min; + AssetThrottle.Throttle = AssetThrottle.Min; + TotalThrottle.Throttle = TotalThrottle.Min; + } + else + { + // we're over so figure out percentages and use those + ResendThrottle.Throttle = tResend; + + LandThrottle.Throttle = ScaleThrottle(tLand, tall, TotalThrottle.Max); + WindThrottle.Throttle = ScaleThrottle(tWind, tall, TotalThrottle.Max); + CloudThrottle.Throttle = ScaleThrottle(tCloud, tall, TotalThrottle.Max); + TaskThrottle.Throttle = ScaleThrottle(tTask, tall, TotalThrottle.Max); + TextureThrottle.Throttle = ScaleThrottle(tTexture, tall, TotalThrottle.Max); + AssetThrottle.Throttle = ScaleThrottle(tAsset, tall, TotalThrottle.Max); + TotalThrottle.Throttle = TotalThrottle.Max; + } + // effectively wiggling the slider causes things reset + ResetCounters(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ClientStack/PacketServer.cs b/trunk/OpenSim/Region/ClientStack/PacketServer.cs new file mode 100644 index 0000000000..5d8234ad05 --- /dev/null +++ b/trunk/OpenSim/Region/ClientStack/PacketServer.cs @@ -0,0 +1,151 @@ +/* +* 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; +using System.Net; +using System.Net.Sockets; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; + +namespace OpenSim.Region.ClientStack +{ + public class PacketServer + { + private static readonly log4net.ILog m_log + = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private ClientStackNetworkHandler m_networkHandler; + private IScene m_scene; + + //private readonly ClientManager m_clientManager = new ClientManager(); + //public ClientManager ClientManager + //{ + // get { return m_clientManager; } + //} + + public PacketServer(ClientStackNetworkHandler networkHandler) + { + m_networkHandler = networkHandler; + m_networkHandler.RegisterPacketServer(this); + } + + public IScene LocalScene + { + set { m_scene = value; } + } + + /// + /// + /// + /// + /// + public virtual void InPacket(uint circuitCode, Packet packet) + { + m_scene.ClientManager.InPacket(circuitCode, packet); + } + + protected virtual IClientAPI CreateNewClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, + ClientManager clientManager, IScene scene, AssetCache assetCache, + PacketServer packServer, AgentCircuitManager authenSessions, + LLUUID agentId, LLUUID sessionId, uint circuitCode) + { + return + new ClientView(remoteEP, scene, assetCache, packServer, authenSessions, agentId, sessionId, circuitCode); + } + + public virtual bool AddNewClient(EndPoint epSender, UseCircuitCodePacket useCircuit, AssetCache assetCache, + AgentCircuitManager authenticateSessionsClass) + { + IClientAPI newuser; + + if (m_scene.ClientManager.TryGetClient(useCircuit.CircuitCode.Code, out newuser)) + { + return false; + } + else + { + newuser = CreateNewClient(epSender, useCircuit, m_scene.ClientManager, m_scene, assetCache, this, + authenticateSessionsClass, useCircuit.CircuitCode.ID, + useCircuit.CircuitCode.SessionID, useCircuit.CircuitCode.Code); + + m_scene.ClientManager.Add(useCircuit.CircuitCode.Code, newuser); + + newuser.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler; + newuser.OnLogout += LogoutHandler; + newuser.OnConnectionClosed += CloseClient; + + return true; + } + } + + public void LogoutHandler(IClientAPI client) + { + client.SendLogoutPacket(); + + CloseClient(client); + } + + /// + /// + /// + /// + /// + /// + /// + public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode) + { + m_networkHandler.SendPacketTo(buffer, size, flags, circuitcode); + } + + /// + /// + /// + /// + public virtual void CloseCircuit(uint circuitcode) + { + m_networkHandler.RemoveClientCircuit(circuitcode); + + //m_scene.ClientManager.CloseAllAgents(circuitcode); + } + + /// + /// Completely close down the given client. + /// + /// + public virtual void CloseClient(IClientAPI client) + { + //m_log.Info("PacketServer:CloseClient()"); + + CloseCircuit(client.CircuitCode); + m_scene.ClientManager.Remove(client.CircuitCode); + client.Close(false); + } + } +} diff --git a/trunk/OpenSim/Region/ClientStack/PacketThrottle.cs b/trunk/OpenSim/Region/ClientStack/PacketThrottle.cs new file mode 100644 index 0000000000..f56f4f8b7d --- /dev/null +++ b/trunk/OpenSim/Region/ClientStack/PacketThrottle.cs @@ -0,0 +1,93 @@ +/* +* 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. +* +*/ +namespace OpenSim.Region.ClientStack +{ + public class PacketThrottle + { + private int max; // max allowable throttle + private int min; // min allowable throttle + private int throttle; // current throttle setting + private static int divisor = 7; // the throttle time divisor, this probably should factor out + private int sent; // current number of bytes sent + + public PacketThrottle(int Min, int Max, int Throttle) + { + max = Max; + min = Min; + throttle = Throttle; + sent = 0; + } + + public void Reset() + { + sent = 0; + } + + public bool UnderLimit() + { + return (sent < (throttle/divisor)); + } + + public int Add(int bytes) + { + sent += bytes; + return sent; + } + + // Properties + public int Max + { + get { return max; } + } + + public int Min + { + get { return min; } + } + + public int Throttle + { + get { return throttle; } + set + { + if (value > max) + { + throttle = max; + } + else if (value < min) + { + throttle = min; + } + else + { + throttle = value; + } + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ClientStack/QueItem.cs b/trunk/OpenSim/Region/ClientStack/QueItem.cs new file mode 100644 index 0000000000..ea0f680104 --- /dev/null +++ b/trunk/OpenSim/Region/ClientStack/QueItem.cs @@ -0,0 +1,44 @@ +/* +* 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 libsecondlife.Packets; +using OpenSim.Framework; + +namespace OpenSim.Region.ClientStack +{ + public class QueItem + { + public QueItem() + { + } + + public Packet Packet; + public bool Incoming; + public ThrottleOutPacketType throttleType; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/trunk/OpenSim/Region/ClientStack/RegionApplicationBase.cs new file mode 100644 index 0000000000..8a042b10db --- /dev/null +++ b/trunk/OpenSim/Region/ClientStack/RegionApplicationBase.cs @@ -0,0 +1,161 @@ +/* +* 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; +using System.Collections.Generic; +using System.Net; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Region.Environment; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.ClientStack +{ + public abstract class RegionApplicationBase : BaseOpenSimServer + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected AssetCache m_assetCache; + protected Dictionary m_clientCircuits = new Dictionary(); + protected NetworkServersInfo m_networkServersInfo; + + protected BaseHttpServer m_httpServer; + protected uint m_httpServerPort; + + protected CommunicationsManager m_commsManager; + + protected SceneManager m_sceneManager = new SceneManager(); + + protected StorageManager m_storageManager; + protected string m_storageConnectionString; + + // An attribute to indicate whether prim inventories should be persisted. + // Probably will be temporary until this stops being experimental. + protected bool m_storagePersistPrimInventories; + + public SceneManager SceneManager + { + get { return m_sceneManager; } + } + + public virtual void StartUp() + { + ClientView.TerrainManager = new TerrainManager(new SecondLife()); + + m_storageManager = CreateStorageManager(m_storageConnectionString); + + Initialize(); + + m_httpServer = new BaseHttpServer(m_httpServerPort); + + m_log.Info("[REGION]: Starting HTTP server"); + + m_httpServer.Start(); + } + + protected abstract void Initialize(); + + protected void StartConsole() + { + m_console = CreateConsole(); + MainConsole.Instance = m_console; + } + + protected abstract ConsoleBase CreateConsole(); + protected abstract PhysicsScene GetPhysicsScene(); + protected abstract StorageManager CreateStorageManager(string connectionstring); + + protected PhysicsScene GetPhysicsScene(string engine, string meshEngine) + { + PhysicsPluginManager physicsPluginManager; + physicsPluginManager = new PhysicsPluginManager(); + physicsPluginManager.LoadPlugins(); + return physicsPluginManager.GetPhysicsScene(engine, meshEngine); + } + + protected Scene SetupScene(RegionInfo regionInfo, out UDPServer udpServer, bool m_permissions) + { + AgentCircuitManager circuitManager = new AgentCircuitManager(); + IPAddress listenIP = regionInfo.InternalEndPoint.Address; + //if (!IPAddress.TryParse(regionInfo.InternalEndPoint, out listenIP)) + // listenIP = IPAddress.Parse("0.0.0.0"); + + uint port = (uint) regionInfo.InternalEndPoint.Port; + udpServer = new UDPServer(listenIP, ref port, regionInfo.m_allow_alternate_ports, m_assetCache, circuitManager); + regionInfo.InternalEndPoint.Port = (int)port; + + Scene scene = CreateScene(regionInfo, m_storageManager, circuitManager); + + udpServer.LocalScene = scene; + + scene.LoadWorldMap(); + scene.RegisterRegionWithGrid(); + + scene.PhysicsScene = GetPhysicsScene(); + scene.PhysicsScene.SetTerrain(scene.Terrain.GetHeights1D()); + + //Master Avatar Setup + UserProfileData masterAvatar; + if (scene.RegionInfo.MasterAvatarAssignedUUID != LLUUID.Zero) + { + masterAvatar = m_commsManager.UserService.SetupMasterUser(scene.RegionInfo.MasterAvatarAssignedUUID); + } + else + { + masterAvatar = + m_commsManager.UserService.SetupMasterUser(scene.RegionInfo.MasterAvatarFirstName, + scene.RegionInfo.MasterAvatarLastName, + scene.RegionInfo.MasterAvatarSandboxPassword); + } + + if (masterAvatar != null) + { + m_log.Info("[PARCEL]: Found master avatar [" + masterAvatar.UUID.ToString() + "]"); + scene.RegionInfo.MasterAvatarAssignedUUID = masterAvatar.UUID; + } + else + { + m_log.Info("[PARCEL]: No master avatar found, using null."); + scene.RegionInfo.MasterAvatarAssignedUUID = LLUUID.Zero; + } + + scene.LoadPrimsFromStorage(m_permissions); + scene.loadAllLandObjectsFromStorage(); + scene.performParcelPrimCountUpdate(); + scene.StartTimer(); + return scene; + } + + protected abstract Scene CreateScene(RegionInfo regionInfo, StorageManager storageManager, + AgentCircuitManager circuitManager); + } +} diff --git a/trunk/OpenSim/Region/ClientStack/UDPServer.cs b/trunk/OpenSim/Region/ClientStack/UDPServer.cs new file mode 100644 index 0000000000..7b32490803 --- /dev/null +++ b/trunk/OpenSim/Region/ClientStack/UDPServer.cs @@ -0,0 +1,402 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.ClientStack +{ + public class UDPServer : ClientStackNetworkHandler + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected Dictionary clientCircuits = new Dictionary(); + public Dictionary clientCircuits_reverse = new Dictionary(); + public Socket Server; + protected IPEndPoint ServerIncoming; + protected byte[] RecvBuffer = new byte[4096]; + protected byte[] ZeroBuffer = new byte[8192]; + protected IPEndPoint ipeSender; + protected EndPoint epSender; + protected AsyncCallback ReceivedData; + protected PacketServer m_packetServer; + protected ulong m_regionHandle; + + protected uint listenPort; + protected bool Allow_Alternate_Port; + protected IPAddress listenIP = IPAddress.Parse("0.0.0.0"); + protected IScene m_localScene; + protected AssetCache m_assetCache; + protected AgentCircuitManager m_authenticateSessionsClass; + + public PacketServer PacketServer + { + get { return m_packetServer; } + set { m_packetServer = value; } + } + + public IScene LocalScene + { + set + { + m_localScene = value; + m_packetServer.LocalScene = m_localScene; + m_regionHandle = m_localScene.RegionInfo.RegionHandle; + } + } + + public ulong RegionHandle + { + get { return m_regionHandle; } + } + + public UDPServer() + { + } + + public UDPServer(IPAddress _listenIP, ref uint port, bool allow_alternate_port, AssetCache assetCache, AgentCircuitManager authenticateClass) + { + listenIP = _listenIP; + listenPort = port; + Allow_Alternate_Port = allow_alternate_port; + m_assetCache = assetCache; + m_authenticateSessionsClass = authenticateClass; + CreatePacketServer(); + + // Return new port + // This because in Grid mode it is not really important what port the region listens to as long as it is correctly registered. + // So the option allow_alternate_ports="true" was added to default.xml + port = listenPort; + } + + protected virtual void CreatePacketServer() + { + PacketServer packetServer = new PacketServer(this); + } + + protected virtual void OnReceivedData(IAsyncResult result) + { + ipeSender = new IPEndPoint(listenIP, 0); + epSender = (EndPoint) ipeSender; + Packet packet = null; + + int numBytes = 1; + + try + { + numBytes = Server.EndReceiveFrom(result, ref epSender); + } + catch (SocketException e) + { + // TODO : Actually only handle those states that we have control over, re-throw everything else, + // TODO: implement cases as we encounter them. + //m_log.Error("[UDPSERVER]: Connection Error! - " + e.ToString()); + switch (e.SocketErrorCode) + { + case SocketError.AlreadyInProgress: + case SocketError.NetworkReset: + case SocketError.ConnectionReset: + + try + { + CloseEndPoint(epSender); + } + catch (Exception a) + { + m_log.Info("[UDPSERVER]: " + a.ToString()); + } + try + { + Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, + ReceivedData, null); + + // Ter: For some stupid reason ConnectionReset basically kills our async event structure.. + // so therefore.. we've got to tell the server to BeginReceiveFrom again. + // This will happen over and over until we've gone through all packets + // sent to and from this particular user. + // Stupid I know.. + // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method. + } + catch (SocketException) + { + } + break; + default: + try + { + CloseEndPoint(epSender); + } + catch (Exception) + { + //m_log.Info("[UDPSERVER]" + a.ToString()); + } + try + { + Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, + ReceivedData, null); + + // Ter: For some stupid reason ConnectionReset basically kills our async event structure.. + // so therefore.. we've got to tell the server to BeginReceiveFrom again. + // This will happen over and over until we've gone through all packets + // sent to and from this particular user. + // Stupid I know.. + // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method. + } + catch (SocketException e2) + { + m_log.Error("[UDPSERVER]: " + e2.ToString()); + } + + // Here's some reference code! :D + // Shutdown and restart the UDP listener! hehe + // Shiny + + //Server.Shutdown(SocketShutdown.Both); + //CloseEndPoint(epSender); + //ServerListener(); + break; + } + + //return; + } + catch (ObjectDisposedException e) + { + m_log.Debug("[UDPSERVER]: " + e.ToString()); + try + { + Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, + ReceivedData, null); + + // Ter: For some stupid reason ConnectionReset basically kills our async event structure.. + // so therefore.. we've got to tell the server to BeginReceiveFrom again. + // This will happen over and over until we've gone through all packets + // sent to and from this particular user. + // Stupid I know.. + // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method. + } + catch (SocketException e2) + { + m_log.Error("[UDPSERVER]: " + e2.ToString()); + } + //return; + } + + int packetEnd = numBytes - 1; + + try + { + packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer); + + } + catch (Exception e) + { + m_log.Debug("[UDPSERVER]: " + e.ToString()); + } + + try + { + Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null); + } + catch (SocketException e4) + { + try + { + CloseEndPoint(epSender); + } + catch (Exception a) + { + m_log.Info("[UDPSERVER]: " + a.ToString()); + } + try + { + Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, + ReceivedData, null); + + // Ter: For some stupid reason ConnectionReset basically kills our async event structure.. + // so therefore.. we've got to tell the server to BeginReceiveFrom again. + // This will happen over and over until we've gone through all packets + // sent to and from this particular user. + // Stupid I know.. + // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method. + } + catch (SocketException e5) + { + m_log.Error("[UDPSERVER]: " + e5.ToString()); + } + + } + + if (packet != null) + { + try + { + // do we already have a circuit for this endpoint + uint circuit; + + bool ret = false; + lock (clientCircuits) + { + ret = clientCircuits.TryGetValue(epSender, out circuit); + } + if (ret) + { + //if so then send packet to the packetserver + //m_log.Warn("[UDPSERVER]: ALREADY HAVE Circuit!"); + m_packetServer.InPacket(circuit, packet); + } + else if (packet.Type == PacketType.UseCircuitCode) + { + // new client + m_log.Debug("[UDPSERVER]: Adding New Client"); + AddNewClient(packet); + } + else + { + // invalid client + //CFK: This message seems to have served its usefullness as of 12-15 so I am commenting it out for now + //m_log.Warn("[UDPSERVER]: Got a packet from an invalid client - " + packet.ToString()); + + } + } + catch (Exception ex) + { + m_log.Error("[UDPSERVER]: Exception in processing packet."); + m_log.Debug("[UDPSERVER]: Adding New Client"); + try + { + AddNewClient(packet); + } + catch (Exception e3) + { + m_log.Error("[UDPSERVER]: Adding New Client threw exception " + e3.ToString()); + Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, + ReceivedData, null); + } + } + } + + } + + private void CloseEndPoint(EndPoint sender) + { + uint circuit; + if (clientCircuits.TryGetValue(sender, out circuit)) + { + m_packetServer.CloseCircuit(circuit); + } + } + + protected virtual void AddNewClient(Packet packet) + { + UseCircuitCodePacket useCircuit = (UseCircuitCodePacket) packet; + lock (clientCircuits) + { + clientCircuits.Add(epSender, useCircuit.CircuitCode.Code); + } + lock (clientCircuits_reverse) + { + if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code)) + clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender); + } + + PacketServer.AddNewClient(epSender, useCircuit, m_assetCache, m_authenticateSessionsClass); + } + + public void ServerListener() + { + uint newPort = listenPort; + for (uint i = 0; i < 20; i++) + { + newPort = listenPort + i; + m_log.Info("[SERVER]: Opening UDP socket on " + listenIP.ToString() + " " + newPort + ".");// Allow alternate ports: " + Allow_Alternate_Port.ToString()); + try + { + ServerIncoming = new IPEndPoint(listenIP, (int) newPort); + Server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + Server.Bind(ServerIncoming); + listenPort = newPort; + break; + } + catch (Exception ex) + { + // We are not looking for alternate ports? + //if (!Allow_Alternate_Port) + throw (ex); + + // We are looking for alternate ports! + m_log.Info("[SERVER]: UDP socket on " + listenIP.ToString() + " " + listenPort.ToString() + " is not available, trying next."); + } + System.Threading.Thread.Sleep(100); // Wait before we retry socket + } + + m_log.Info("[SERVER]: UDP socket bound, getting ready to listen"); + + ipeSender = new IPEndPoint(listenIP, 0); + epSender = (EndPoint) ipeSender; + ReceivedData = new AsyncCallback(OnReceivedData); + Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null); + + m_log.Info("[SERVER]: Listening on port " + newPort); + } + + public virtual void RegisterPacketServer(PacketServer server) + { + m_packetServer = server; + } + + public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode) + //EndPoint packetSender) + { + // find the endpoint for this circuit + EndPoint sendto = null; + if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto)) + { + //we found the endpoint so send the packet to it + Server.SendTo(buffer, size, flags, sendto); + } + } + + public virtual void RemoveClientCircuit(uint circuitcode) + { + EndPoint sendto = null; + if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto)) + { + clientCircuits.Remove(sendto); + + + clientCircuits_reverse.Remove(circuitcode); + } + } + } +} diff --git a/trunk/OpenSim/Region/Communications/Local/CommunicationsLocal.cs b/trunk/OpenSim/Region/Communications/Local/CommunicationsLocal.cs new file mode 100644 index 0000000000..575d9d5dd0 --- /dev/null +++ b/trunk/OpenSim/Region/Communications/Local/CommunicationsLocal.cs @@ -0,0 +1,53 @@ +/* +* 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 OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Servers; + +namespace OpenSim.Region.Communications.Local +{ + public class CommunicationsLocal : CommunicationsManager + { + public CommunicationsLocal( + NetworkServersInfo serversInfo, + BaseHttpServer httpServer, + AssetCache assetCache, + IUserService userService, + LocalInventoryService inventoryService, + IInterRegionCommunications interRegionService, + IGridServices gridService, bool dumpAssetsToFile) + : base(serversInfo, httpServer, assetCache, dumpAssetsToFile) + { + m_inventoryService = inventoryService; + m_userService = userService; + m_gridService = gridService; + m_interRegion = interRegionService; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Communications/Local/LocalBackEndServices.cs b/trunk/OpenSim/Region/Communications/Local/LocalBackEndServices.cs new file mode 100644 index 0000000000..98419ab29f --- /dev/null +++ b/trunk/OpenSim/Region/Communications/Local/LocalBackEndServices.cs @@ -0,0 +1,462 @@ +/* +* 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.Collections; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Communications.Local +{ + public class LocalBackEndServices : IGridServices, IInterRegionCommunications + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected Dictionary m_regions = new Dictionary(); + + protected Dictionary m_regionListeners = + new Dictionary(); + + private Dictionary m_remoteRegionInfoCache = new Dictionary(); + + private Dictionary m_queuedGridSettings = new Dictionary(); + + public string _gdebugRegionName = System.String.Empty; + + bool m_bAvailable=true; + + public void CheckRegion(string address, uint port) + { + m_bAvailable = true; + } + + public bool Available + { + get { return m_bAvailable; } + } + + public string gdebugRegionName + { + get { return _gdebugRegionName; } + set { _gdebugRegionName = value; } + } + + public string _rdebugRegionName = System.String.Empty; + + public string rdebugRegionName + { + get { return _rdebugRegionName; } + set { _rdebugRegionName = value; } + } + + public LocalBackEndServices() + { + } + + /// + /// Register a region method with the BackEnd Services. + /// + /// + /// + public RegionCommsListener RegisterRegion(RegionInfo regionInfo) + { + //Console.WriteLine("CommsManager - Region " + regionInfo.RegionHandle + " , " + regionInfo.RegionLocX + " , "+ regionInfo.RegionLocY +" is registering"); + if (!m_regions.ContainsKey(regionInfo.RegionHandle)) + { + //Console.WriteLine("CommsManager - Adding Region " + regionInfo.RegionHandle ); + m_regions.Add(regionInfo.RegionHandle, regionInfo); + + RegionCommsListener regionHost = new RegionCommsListener(); + if (m_regionListeners.ContainsKey(regionInfo.RegionHandle)) + { + m_log.Error("[INTERREGION]: " + + "Error:Region registered twice as an Events listener for Interregion Communications but not as a listed region. " + + "In Standalone mode this will cause BIG issues. In grid mode, it means a region went down and came back up."); + m_regionListeners.Remove(regionInfo.RegionHandle); + } + m_regionListeners.Add(regionInfo.RegionHandle, regionHost); + + return regionHost; + } + else + { + // Already in our list, so the region went dead and restarted. + m_regions.Remove(regionInfo.RegionHandle); + m_log.Warn("[INTERREGION]: Region registered twice. Region went down and came back up."); + + RegionCommsListener regionHost = new RegionCommsListener(); + if (m_regionListeners.ContainsKey(regionInfo.RegionHandle)) + { + m_regionListeners.Remove(regionInfo.RegionHandle); + } + m_regionListeners.Add(regionInfo.RegionHandle, regionHost); + + return regionHost; + } + } + + public bool DeregisterRegion(RegionInfo regionInfo) + { + if (m_regions.ContainsKey(regionInfo.RegionHandle)) + { + m_regions.Remove(regionInfo.RegionHandle); + if (m_regionListeners.ContainsKey(regionInfo.RegionHandle)) + { + m_regionListeners.Remove(regionInfo.RegionHandle); + } + return true; + } + return false; + } + + /// + /// + /// + /// + public List RequestNeighbours(uint x, uint y) + { + // Console.WriteLine("Finding Neighbours to " + regionInfo.RegionHandle); + List neighbours = new List(); + + foreach (RegionInfo reg in m_regions.Values) + { + // Console.WriteLine("CommsManager- RequestNeighbours() checking region " + reg.RegionLocX + " , "+ reg.RegionLocY); + if (reg.RegionLocX != x || reg.RegionLocY != y) + { + //Console.WriteLine("CommsManager- RequestNeighbours() - found a different region in list, checking location"); + if ((reg.RegionLocX > (x - 2)) && (reg.RegionLocX < (x + 2))) + { + if ((reg.RegionLocY > (y - 2)) && (reg.RegionLocY < (y + 2))) + { + neighbours.Add(reg); + } + } + } + } + return neighbours; + } + + /// + /// + /// + /// + /// + public RegionInfo RequestNeighbourInfo(ulong regionHandle) + { + if (m_regions.ContainsKey(regionHandle)) + { + return m_regions[regionHandle]; + } + return null; + } + + /// + /// + /// + /// + /// + /// + /// + /// + public List RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY) + { + List mapBlocks = new List(); + foreach (RegionInfo regInfo in m_regions.Values) + { + if (((regInfo.RegionLocX >= minX) && (regInfo.RegionLocX <= maxX)) && + ((regInfo.RegionLocY >= minY) && (regInfo.RegionLocY <= maxY))) + { + MapBlockData map = new MapBlockData(); + map.Name = regInfo.RegionName; + map.X = (ushort) regInfo.RegionLocX; + map.Y = (ushort) regInfo.RegionLocY; + map.WaterHeight = (byte) regInfo.EstateSettings.waterHeight; + map.MapImageId = regInfo.EstateSettings.terrainImageID; + map.Agents = 1; + map.RegionFlags = 72458694; + map.Access = 13; + mapBlocks.Add(map); + } + } + return mapBlocks; + } + public bool TellRegionToCloseChildConnection(ulong regionHandle, LLUUID agentID) + { + if (m_regionListeners.ContainsKey(regionHandle)) + { + return m_regionListeners[regionHandle].TriggerTellRegionToCloseChildConnection(regionHandle, agentID); + } + return false; + } + + public virtual bool RegionUp(SearializableRegionInfo sregion, ulong regionhandle) + { + RegionInfo region = new RegionInfo(sregion); + if (m_regionListeners.ContainsKey(regionhandle)) + { + return m_regionListeners[regionhandle].TriggerRegionUp(region); + } + + return false; + } + + public virtual bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData) + { + if (m_regionListeners.ContainsKey(regionHandle)) + { + // Console.WriteLine("CommsManager- Informing a region to expect child agent"); + m_regionListeners[regionHandle].TriggerChildAgentUpdate(regionHandle, cAgentData); + //m_log.Info("[INTER]: " + rdebugRegionName + ":Local BackEnd: Got Listener trigginering local event: " + agentData.firstname + " " + agentData.lastname); + + return true; + } + return false; + } + + // This function Is only here to keep this class in line with the Grid Interface. + // It never gets called. + public virtual Dictionary GetGridSettings() + { + Dictionary returnGridSettings = new Dictionary(); + lock (m_queuedGridSettings) + { + returnGridSettings = m_queuedGridSettings; + m_queuedGridSettings.Clear(); + } + + return returnGridSettings; + } + + public virtual void SetForcefulBanlistsDisallowed(ulong regionHandle) + { + m_queuedGridSettings.Add("allow_forceful_banlines", "FALSE"); + } + + public bool TriggerRegionUp(RegionInfo region, ulong regionhandle) + { + if (m_regionListeners.ContainsKey(regionhandle)) + { + return m_regionListeners[regionhandle].TriggerRegionUp(region); + } + + return false; + } + + public bool TriggerChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData) + { + if (m_regionListeners.ContainsKey(regionHandle)) + { + return m_regionListeners[regionHandle].TriggerChildAgentUpdate(regionHandle, cAgentData); + } + return false; + } + + public bool TriggerTellRegionToCloseChildConnection(ulong regionHandle, LLUUID agentID) + { + if (m_regionListeners.ContainsKey(regionHandle)) + { + return m_regionListeners[regionHandle].TriggerTellRegionToCloseChildConnection(regionHandle, agentID); + } + return false; + } + /// + /// + /// + /// + /// + /// + public bool InformRegionOfChildAgent(ulong regionHandle, AgentCircuitData agentData) + //should change from agentCircuitData + { + //Console.WriteLine("CommsManager- Trying to Inform a region to expect child agent"); + //m_log.Info("[INTER]: " + rdebugRegionName + ":Local BackEnd: Trying to inform region of child agent: " + agentData.firstname + " " + agentData.lastname); + + if (m_regionListeners.ContainsKey(regionHandle)) + { + // Console.WriteLine("CommsManager- Informing a region to expect child agent"); + m_regionListeners[regionHandle].TriggerExpectUser(regionHandle, agentData); + //m_log.Info("[INTER]: " + rdebugRegionName + ":Local BackEnd: Got Listener trigginering local event: " + agentData.firstname + " " + agentData.lastname); + + return true; + } + return false; + } + + public bool InformRegionOfPrimCrossing(ulong regionHandle, LLUUID primID, string objData) + { + if (m_regionListeners.ContainsKey(regionHandle)) + { + m_regionListeners[regionHandle].TriggerExpectPrim(regionHandle, primID, objData); + return true; + } + return false; + } + + /// + /// + /// + /// + /// + /// + /// + public bool ExpectAvatarCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying) + { + if (m_regionListeners.ContainsKey(regionHandle)) + { + // Console.WriteLine("CommsManager- Informing a region to expect avatar crossing"); + m_regionListeners[regionHandle].TriggerExpectAvatarCrossing(regionHandle, agentID, position, isFlying); + return true; + } + return false; + } + + public bool ExpectPrimCrossing(ulong regionHandle, LLUUID primID, LLVector3 position, bool isPhysical) + { + if (m_regionListeners.ContainsKey(regionHandle)) + { + m_regionListeners[regionHandle].TriggerExpectPrimCrossing(regionHandle, primID, position, isPhysical); + return true; + } + return false; + } + + + + public bool AcknowledgeAgentCrossed(ulong regionHandle, LLUUID agentId) + { + if (m_regionListeners.ContainsKey(regionHandle)) + { + return true; + } + return false; + } + + public bool AcknowledgePrimCrossed(ulong regionHandle, LLUUID primID) + { + if (m_regionListeners.ContainsKey(regionHandle)) + { + return true; + } + return false; + } + + /// + /// Is a Sandbox mode method, used by the local Login server to inform a region of a connection user/session + /// + /// + /// + /// + public void AddNewSession(ulong regionHandle, Login loginData) + { + AgentCircuitData agent = new AgentCircuitData(); + agent.AgentID = loginData.Agent; + agent.firstname = loginData.First; + agent.lastname = loginData.Last; + agent.SessionID = loginData.Session; + agent.SecureSessionID = loginData.SecureSession; + agent.circuitcode = loginData.CircuitCode; + agent.BaseFolder = loginData.BaseFolder; + agent.InventoryFolder = loginData.InventoryFolder; + agent.startpos = loginData.StartPos; + + agent.CapsPath = loginData.CapsPath; + + TriggerExpectUser(regionHandle, agent); + } + + public void TriggerExpectUser(ulong regionHandle, AgentCircuitData agent) + { + //m_log.Info("[INTER]: " + rdebugRegionName + ":Local BackEnd: Other region is sending child agent our way: " + agent.firstname + " " + agent.lastname); + + if (m_regionListeners.ContainsKey(regionHandle)) + { + //m_log.Info("[INTER]: " + rdebugRegionName + ":Local BackEnd: FoundLocalRegion To send it to: " + agent.firstname + " " + agent.lastname); + + m_regionListeners[regionHandle].TriggerExpectUser(regionHandle, agent); + } + } + + public void TriggerExpectPrim(ulong regionHandle, LLUUID primID, string objData) + { + if (m_regionListeners.ContainsKey(regionHandle)) + { + m_regionListeners[regionHandle].TriggerExpectPrim(regionHandle, primID, objData); + } + } + + public void PingCheckReply(Hashtable respData) + { + foreach (ulong region in m_regions.Keys) + { + Hashtable regData = new Hashtable(); + RegionInfo reg = m_regions[region]; + regData["status"] = "active"; + regData["handle"] = region.ToString(); + + respData[reg.RegionID.ToString()] = regData; + } + } + + public bool TriggerExpectAvatarCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying) + { + if (m_regionListeners.ContainsKey(regionHandle)) + { + return m_regionListeners[regionHandle].TriggerExpectAvatarCrossing(regionHandle, agentID, position, + isFlying); + } + + return false; + } + + public bool TriggerExpectPrimCrossing(ulong regionHandle, LLUUID primID, LLVector3 position, bool isPhysical) + { + if (m_regionListeners.ContainsKey(regionHandle)) + { + return + m_regionListeners[regionHandle].TriggerExpectPrimCrossing(regionHandle, primID, position, isPhysical); + } + return false; + } + + public bool IncomingChildAgent(ulong regionHandle, AgentCircuitData agentData) + { + // m_log.Info("[INTER]: " + rdebugRegionName + ":Local BackEnd: Other local region is sending child agent our way: " + agentData.firstname + " " + agentData.lastname); + + if (m_regionListeners.ContainsKey(regionHandle)) + { + //m_log.Info("[INTER]: " + rdebugRegionName + ":Local BackEnd: found local region to trigger event on: " + agentData.firstname + " " + agentData.lastname); + + TriggerExpectUser(regionHandle, agentData); + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Communications/Local/LocalInventoryService.cs b/trunk/OpenSim/Region/Communications/Local/LocalInventoryService.cs new file mode 100644 index 0000000000..77a2a6e405 --- /dev/null +++ b/trunk/OpenSim/Region/Communications/Local/LocalInventoryService.cs @@ -0,0 +1,142 @@ +/* +* 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.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; + +namespace OpenSim.Region.Communications.Local +{ + /// + /// An implementation of user inventory where the inventory is held locally (e.g. when OpenSim is + /// operating in standalone mode. + /// + public class LocalInventoryService : InventoryServiceBase + { + public override void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, + InventoryItemInfo itemCallBack) + { + List folders = RequestFirstLevelFolders(userID); + InventoryFolderImpl rootFolder = null; + + //need to make sure we send root folder first + foreach (InventoryFolderBase folder in folders) + { + if (folder.parentID == LLUUID.Zero) + { + rootFolder = RequestInventoryFolder(userID, folder, folderCallBack, itemCallBack); + } + } + + if (rootFolder != null) + { + foreach (InventoryFolderBase folder in folders) + { + if (folder.folderID != rootFolder.folderID) + { + RequestInventoryFolder(userID, folder, folderCallBack, itemCallBack); + } + } + } + } + + public override void AddNewInventoryFolder(LLUUID userID, InventoryFolderBase folder) + { + AddFolder(folder); + } + + public override void MoveExistingInventoryFolder(InventoryFolderBase folder) + { + MoveFolder(folder); + } + + public override void AddNewInventoryItem(LLUUID userID, InventoryItemBase item) + { + AddItem(item); + } + + public override void DeleteInventoryItem(LLUUID userID, InventoryItemBase item) + { + DeleteItem(item); + } + + public override bool HasInventoryForUser(LLUUID userID) + { + InventoryFolderBase root = RequestUsersRoot(userID); + if (root == null) + { + return false; + } + else + { + return true; + } + } + + public override InventoryFolderBase RequestNamedFolder(LLUUID userID, string folderName) + { + List folders = RequestFirstLevelFolders(userID); + InventoryFolderBase requestedFolder = null; + + //need to make sure we send root folder first + foreach (InventoryFolderBase folder in folders) + { + if (folder.name == folderName) + { + requestedFolder = folder; + break; + } + } + + return requestedFolder; + } + + /// + /// Send the given inventory folder and its item contents back to the requester. + /// + /// + /// + private InventoryFolderImpl RequestInventoryFolder(LLUUID userID, InventoryFolderBase folder, + InventoryFolderInfo folderCallBack, + InventoryItemInfo itemCallBack) + { + InventoryFolderImpl newFolder = new InventoryFolderImpl(folder); + folderCallBack(userID, newFolder); + + List items = RequestFolderItems(newFolder.folderID); + foreach (InventoryItemBase item in items) + { + itemCallBack(userID, item); + } + + return newFolder; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Communications/Local/LocalLoginService.cs b/trunk/OpenSim/Region/Communications/Local/LocalLoginService.cs new file mode 100644 index 0000000000..e6a9621972 --- /dev/null +++ b/trunk/OpenSim/Region/Communications/Local/LocalLoginService.cs @@ -0,0 +1,235 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using libsecondlife; + +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Statistics; +using OpenSim.Framework.UserManagement; +using InventoryFolder=OpenSim.Framework.InventoryFolder; + +namespace OpenSim.Region.Communications.Local +{ + public delegate void LoginToRegionEvent(ulong regionHandle, Login login); + + public class LocalLoginService : LoginService + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private CommunicationsLocal m_Parent; + + private NetworkServersInfo serversInfo; + private uint defaultHomeX; + private uint defaultHomeY; + private bool authUsers = false; + + public event LoginToRegionEvent OnLoginToRegion; + + public LocalLoginService(UserManagerBase userManager, string welcomeMess, + CommunicationsLocal parent, NetworkServersInfo serversInfo, + bool authenticate) + : base(userManager, parent.UserProfileCacheService.libraryRoot, welcomeMess) + { + m_Parent = parent; + this.serversInfo = serversInfo; + defaultHomeX = this.serversInfo.DefaultHomeLocX; + defaultHomeY = this.serversInfo.DefaultHomeLocY; + authUsers = authenticate; + } + + + public override UserProfileData GetTheUser(string firstname, string lastname) + { + UserProfileData profile = m_userManager.GetUserProfile(firstname, lastname); + if (profile != null) + { + return profile; + } + + if (!authUsers) + { + //no current user account so make one + m_log.Info("[LOGIN]: No user account found so creating a new one."); + + m_userManager.AddUserProfile(firstname, lastname, "test", defaultHomeX, defaultHomeY); + + profile = m_userManager.GetUserProfile(firstname, lastname); + if (profile != null) + { + m_Parent.InventoryService.CreateNewUserInventory(profile.UUID); + } + + return profile; + } + return null; + } + + public override bool AuthenticateUser(UserProfileData profile, string password) + { + if (!authUsers) + { + //for now we will accept any password in sandbox mode + m_log.Info("[LOGIN]: Authorising user (no actual password check)"); + + return true; + } + else + { + m_log.Info( + "[LOGIN]: Authenticating " + profile.username + " " + profile.surname); + + if (!password.StartsWith("$1$")) + password = "$1$" + Util.Md5Hash(password); + + password = password.Remove(0, 3); //remove $1$ + + string s = Util.Md5Hash(password + ":" + profile.passwordSalt); + + bool loginresult = (profile.passwordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase) + || profile.passwordHash.Equals(password, StringComparison.InvariantCultureIgnoreCase)); + return loginresult; + } + } + + public override void CustomiseResponse(LoginResponse response, UserProfileData theUser) + { + ulong currentRegion = theUser.currentAgent.currentHandle; + RegionInfo reg = m_Parent.GridService.RequestNeighbourInfo(currentRegion); + + if (reg != null) + { + response.Home = "{'region_handle':[r" + (reg.RegionLocX * Constants.RegionSize).ToString() + ",r" + + (reg.RegionLocY * Constants.RegionSize).ToString() + "], " + + "'position':[r" + theUser.homeLocation.X.ToString() + ",r" + + theUser.homeLocation.Y.ToString() + ",r" + theUser.homeLocation.Z.ToString() + "], " + + "'look_at':[r" + theUser.homeLocation.X.ToString() + ",r" + + theUser.homeLocation.Y.ToString() + ",r" + theUser.homeLocation.Z.ToString() + "]}"; + string capsPath = Util.GetRandomCapsPath(); + response.SimAddress = reg.ExternalEndPoint.Address.ToString(); + response.SimPort = (uint) reg.ExternalEndPoint.Port; + response.RegionX = reg.RegionLocX; + response.RegionY = reg.RegionLocY ; + + response.SeedCapability = "http://" + reg.ExternalHostName + ":" + + serversInfo.HttpListenerPort.ToString() + "/CAPS/" + capsPath + "0000/"; + // response.SeedCapability = "http://" + reg.ExternalHostName + ":" + this.serversInfo.HttpListenerPort.ToString() + "/CapsSeed/" + capsPath + "0000/"; + theUser.currentAgent.currentRegion = reg.RegionID; + theUser.currentAgent.currentHandle = reg.RegionHandle; + + LoginResponse.BuddyList buddyList = new LoginResponse.BuddyList(); + + response.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(theUser.UUID)); + + Login _login = new Login(); + //copy data to login object + _login.First = response.Firstname; + _login.Last = response.Lastname; + _login.Agent = response.AgentID; + _login.Session = response.SessionID; + _login.SecureSession = response.SecureSessionID; + _login.CircuitCode = (uint) response.CircuitCode; + _login.StartPos = new LLVector3(128, 128, 70); + _login.CapsPath = capsPath; + + if (OnLoginToRegion != null) + { + OnLoginToRegion(currentRegion, _login); + } + } + else + { + m_log.Warn("[LOGIN]: Not found region " + currentRegion); + } + } + private LoginResponse.BuddyList ConvertFriendListItem(List LFL) + { + LoginResponse.BuddyList buddylistreturn = new LoginResponse.BuddyList(); + foreach (FriendListItem fl in LFL) + { + LoginResponse.BuddyList.BuddyInfo buddyitem = new LoginResponse.BuddyList.BuddyInfo(fl.Friend); + buddyitem.BuddyID = fl.Friend; + buddyitem.BuddyRightsHave = (int)fl.FriendListOwnerPerms; + buddyitem.BuddyRightsGiven = (int)fl.FriendPerms; + buddylistreturn.AddNewBuddy(buddyitem); + + } + return buddylistreturn; + } + protected override InventoryData CreateInventoryData(LLUUID userID) + { + List folders = m_Parent.InventoryService.RequestFirstLevelFolders(userID); + if (folders.Count > 0) + { + LLUUID rootID = LLUUID.Zero; + ArrayList AgentInventoryArray = new ArrayList(); + Hashtable TempHash; + foreach (InventoryFolderBase InvFolder in folders) + { + if (InvFolder.parentID == LLUUID.Zero) + { + rootID = InvFolder.folderID; + } + TempHash = new Hashtable(); + TempHash["name"] = InvFolder.name; + TempHash["parent_id"] = InvFolder.parentID.ToString(); + TempHash["version"] = (Int32) InvFolder.version; + TempHash["type_default"] = (Int32) InvFolder.type; + TempHash["folder_id"] = InvFolder.folderID.ToString(); + AgentInventoryArray.Add(TempHash); + } + return new InventoryData(AgentInventoryArray, rootID); + } + else + { + AgentInventory userInventory = new AgentInventory(); + userInventory.CreateRootFolder(userID, false); + + ArrayList AgentInventoryArray = new ArrayList(); + Hashtable TempHash; + foreach (InventoryFolder InvFolder in userInventory.InventoryFolders.Values) + { + TempHash = new Hashtable(); + TempHash["name"] = InvFolder.FolderName; + TempHash["parent_id"] = InvFolder.ParentID.ToString(); + TempHash["version"] = (Int32) InvFolder.Version; + TempHash["type_default"] = (Int32) InvFolder.DefaultType; + TempHash["folder_id"] = InvFolder.FolderID.ToString(); + AgentInventoryArray.Add(TempHash); + } + + return new InventoryData(AgentInventoryArray, userInventory.InventoryRoot.FolderID); + } + + } + } +} diff --git a/trunk/OpenSim/Region/Communications/Local/LocalUserServices.cs b/trunk/OpenSim/Region/Communications/Local/LocalUserServices.cs new file mode 100644 index 0000000000..9811f8ae00 --- /dev/null +++ b/trunk/OpenSim/Region/Communications/Local/LocalUserServices.cs @@ -0,0 +1,105 @@ +/* +* 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; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Statistics; +using OpenSim.Framework.UserManagement; + +namespace OpenSim.Region.Communications.Local +{ + public class LocalUserServices : UserManagerBase + { + private readonly NetworkServersInfo m_serversInfo; + private readonly uint m_defaultHomeX; + private readonly uint m_defaultHomeY; + private IInventoryServices m_inventoryService; + + + /// + /// + /// + /// + /// + /// + /// + /// Can be null if stats collection is not required. + public LocalUserServices(NetworkServersInfo serversInfo, uint defaultHomeLocX, uint defaultHomeLocY, + IInventoryServices inventoryService) + { + m_serversInfo = serversInfo; + + m_defaultHomeX = defaultHomeLocX; + m_defaultHomeY = defaultHomeLocY; + + m_inventoryService = inventoryService; + } + + public override UserProfileData SetupMasterUser(string firstName, string lastName) + { + return SetupMasterUser(firstName, lastName, String.Empty); + } + + public override UserProfileData SetupMasterUser(string firstName, string lastName, string password) + { + UserProfileData profile = GetUserProfile(firstName, lastName); + if (profile != null) + { + return profile; + } + + Console.WriteLine("Unknown Master User. Sandbox Mode: Creating Account"); + AddUserProfile(firstName, lastName, password, m_defaultHomeX, m_defaultHomeY); + + profile = GetUserProfile(firstName, lastName); + + if (profile == null) + { + Console.WriteLine("Unknown Master User after creation attempt. No clue what to do here."); + } + else + { + m_inventoryService.CreateNewUserInventory(profile.UUID); + } + + return profile; + } + + public override UserProfileData SetupMasterUser(LLUUID uuid) + { + UserProfileData data = GetUserProfile(uuid); + if (data == null) + { + throw new Exception("Unknown master user UUID. Possible reason: UserServer is not running."); + } + return data; + } + } +} diff --git a/trunk/OpenSim/Region/Communications/Local/Properties/AssemblyInfo.cs b/trunk/OpenSim/Region/Communications/Local/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..1f73d1a3b1 --- /dev/null +++ b/trunk/OpenSim/Region/Communications/Local/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* 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.Communications.Local")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Region.Communications.Local")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("fb173926-bd0a-4cd0-bb45-185b2f72ddfb")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Region/Communications/OGS1/CommunicationsOGS1.cs b/trunk/OpenSim/Region/Communications/OGS1/CommunicationsOGS1.cs new file mode 100644 index 0000000000..5da36fcf9e --- /dev/null +++ b/trunk/OpenSim/Region/Communications/OGS1/CommunicationsOGS1.cs @@ -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 OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Servers; + +namespace OpenSim.Region.Communications.OGS1 +{ + public class CommunicationsOGS1 : CommunicationsManager + { + public CommunicationsOGS1(NetworkServersInfo serversInfo, BaseHttpServer httpServer, AssetCache assetCache) + : base(serversInfo, httpServer, assetCache, false) + { + OGS1GridServices gridInterComms = new OGS1GridServices(serversInfo, httpServer); + m_gridService = gridInterComms; + m_interRegion = gridInterComms; + + m_inventoryService = new OGS1InventoryService(serversInfo.InventoryURL); + m_userService = new OGS1UserServices(this); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Communications/OGS1/OGS1GridServices.cs b/trunk/OpenSim/Region/Communications/OGS1/OGS1GridServices.cs new file mode 100644 index 0000000000..5d38b83771 --- /dev/null +++ b/trunk/OpenSim/Region/Communications/OGS1/OGS1GridServices.cs @@ -0,0 +1,1365 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; +using System.Runtime.Remoting.Channels.Tcp; +using System.Security.Authentication; +using libsecondlife; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Region.Communications.Local; + +namespace OpenSim.Region.Communications.OGS1 +{ + public class OGS1GridServices : IGridServices, IInterRegionCommunications + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private LocalBackEndServices m_localBackend = new LocalBackEndServices(); + private Dictionary m_remoteRegionInfoCache = new Dictionary(); + private List m_knownRegions = new List(); + private Dictionary m_deadRegionCache = new Dictionary(); + private Dictionary m_queuedGridSettings = new Dictionary(); + + public BaseHttpServer httpListener; + public NetworkServersInfo serversInfo; + public BaseHttpServer httpServer; + public string _gdebugRegionName = String.Empty; + + public string gdebugRegionName + { + get { return _gdebugRegionName; } + set { _gdebugRegionName = value; } + } + + public string _rdebugRegionName = String.Empty; + + public string rdebugRegionName + { + get { return _rdebugRegionName; } + set { _rdebugRegionName = value; } + } + + /// + /// + /// + /// + /// + public OGS1GridServices(NetworkServersInfo servers_info, BaseHttpServer httpServe) + { + serversInfo = servers_info; + httpServer = httpServe; + //Respond to Grid Services requests + httpServer.AddXmlRPCHandler("expect_user", ExpectUser); + httpServer.AddXmlRPCHandler("check", PingCheckReply); + + StartRemoting(); + } + + /// + /// + /// + /// + /// + public RegionCommsListener RegisterRegion(RegionInfo regionInfo) + { + Hashtable GridParams = new Hashtable(); + // Login / Authentication + + GridParams["authkey"] = serversInfo.GridSendKey; + GridParams["recvkey"] = serversInfo.GridRecvKey; + GridParams["UUID"] = regionInfo.RegionID.ToString(); + GridParams["sim_ip"] = regionInfo.ExternalHostName; + GridParams["sim_port"] = regionInfo.InternalEndPoint.Port.ToString(); + GridParams["region_locx"] = regionInfo.RegionLocX.ToString(); + GridParams["region_locy"] = regionInfo.RegionLocY.ToString(); + GridParams["sim_name"] = regionInfo.RegionName; + GridParams["http_port"] = serversInfo.HttpListenerPort.ToString(); + GridParams["remoting_port"] = NetworkServersInfo.RemotingListenerPort.ToString(); + GridParams["map-image-id"] = regionInfo.EstateSettings.terrainImageID.ToString(); + + + // Added by daTwitch + // part of an initial brutish effort to provide accurate information (as per the xml region spec) + // wrt the ownership of a given region + // the (very bad) assumption is that this value is being read and handled inconsistently or + // not at all. Current strategy is to put the code in place to support the validity of this information + // and to roll forward debugging any issues from that point + // + // this particular section of the mod attempts to supply a value from the region's xml file to the grid + // server for the UUID of the region's owner (master avatar) + // + GridParams["master_avatar_uuid"] = regionInfo.MasterAvatarAssignedUUID.ToString(); + // end of daTwitch's addition to this file + + + // Package into an XMLRPC Request + ArrayList SendParams = new ArrayList(); + SendParams.Add(GridParams); + + // Send Request + XmlRpcRequest GridReq; + XmlRpcResponse GridResp; + try + { + GridReq = new XmlRpcRequest("simulator_login", SendParams); + GridResp = GridReq.Send(serversInfo.GridURL, 16000); + } catch (Exception ex) + { + m_log.Error("Unable to connect to grid. Grid server not running?"); + throw(ex); + } + Hashtable GridRespData = (Hashtable)GridResp.Value; + Hashtable griddatahash = GridRespData; + + // Process Response + if (GridRespData.ContainsKey("error")) + { + string errorstring = (string) GridRespData["error"]; + m_log.Error("Unable to connect to grid: " + errorstring); + return null; + } + else + { + m_knownRegions = RequestNeighbours(regionInfo.RegionLocX, regionInfo.RegionLocY); + if (GridRespData.ContainsKey("allow_forceful_banlines")) + { + if ((string) GridRespData["allow_forceful_banlines"] != "TRUE") + { + //m_localBackend.SetForcefulBanlistsDisallowed(regionInfo.RegionHandle); + m_queuedGridSettings.Add("allow_forceful_banlines", "FALSE"); + } + } + } + return m_localBackend.RegisterRegion(regionInfo); + } + + public bool DeregisterRegion(RegionInfo regionInfo) + { + return false; + } + + public virtual Dictionary GetGridSettings() + { + Dictionary returnGridSettings = new Dictionary(); + lock (m_queuedGridSettings) + { + foreach (string Dictkey in m_queuedGridSettings.Keys) + { + returnGridSettings.Add(Dictkey, m_queuedGridSettings[Dictkey]); + } + + + m_queuedGridSettings.Clear(); + } + + return returnGridSettings; + } + + /// + /// + /// + /// + /// + public List RequestNeighbours(uint x, uint y) + { + Hashtable respData = MapBlockQuery((int) x - 1, (int) y - 1, (int) x + 1, (int) y + 1); + + List neighbours = new List(); + + foreach (ArrayList neighboursList in respData.Values) + { + foreach (Hashtable neighbourData in neighboursList) + { + uint regX = Convert.ToUInt32(neighbourData["x"]); + uint regY = Convert.ToUInt32(neighbourData["y"]); + if ((x != regX) || (y != regY)) + { + string simIp = (string) neighbourData["sim_ip"]; + + uint port = Convert.ToUInt32(neighbourData["sim_port"]); + string externalUri = (string) neighbourData["sim_uri"]; + + string externalIpStr = Util.GetHostFromDNS(simIp).ToString(); + SimpleRegionInfo sri = new SimpleRegionInfo(regX, regY, simIp, port); + sri.RemotingPort = Convert.ToUInt32(neighbourData["remoting_port"]); + sri.RegionID = new LLUUID((string) neighbourData["uuid"]); + + neighbours.Add(sri); + } + } + } + + return neighbours; + } + + /// + /// + /// + /// + /// + public RegionInfo RequestNeighbourInfo(LLUUID Region_UUID) + { + RegionInfo regionInfo; + Hashtable requestData = new Hashtable(); + requestData["region_UUID"] = Region_UUID.ToString(); + requestData["authkey"] = serversInfo.GridSendKey; + ArrayList SendParams = new ArrayList(); + SendParams.Add(requestData); + XmlRpcRequest GridReq = new XmlRpcRequest("simulator_data_request", SendParams); + XmlRpcResponse GridResp = GridReq.Send(serversInfo.GridURL, 3000); + + Hashtable responseData = (Hashtable) GridResp.Value; + + if (responseData.ContainsKey("error")) + { + Console.WriteLine("error received from grid server" + responseData["error"]); + return null; + } + + uint regX = Convert.ToUInt32((string) responseData["region_locx"]); + uint regY = Convert.ToUInt32((string) responseData["region_locy"]); + string internalIpStr = (string) responseData["sim_ip"]; + uint port = Convert.ToUInt32(responseData["sim_port"]); + string externalUri = (string) responseData["sim_uri"]; + + IPEndPoint neighbourInternalEndPoint = new IPEndPoint(IPAddress.Parse(internalIpStr), (int) port); + string neighbourExternalUri = externalUri; + regionInfo = new RegionInfo(regX, regY, neighbourInternalEndPoint, internalIpStr); + + regionInfo.RemotingPort = Convert.ToUInt32((string) responseData["remoting_port"]); + regionInfo.RemotingAddress = internalIpStr; + + regionInfo.RegionID = new LLUUID((string) responseData["region_UUID"]); + regionInfo.RegionName = (string) responseData["region_name"]; + + if (requestData.ContainsKey("regionHandle")) + { + m_remoteRegionInfoCache.Add(Convert.ToUInt64((string) requestData["regionHandle"]), regionInfo); + } + + return regionInfo; + } + + /// + /// + /// + /// + /// + public RegionInfo RequestNeighbourInfo(ulong regionHandle) + { + RegionInfo regionInfo = m_localBackend.RequestNeighbourInfo(regionHandle); + + if (regionInfo != null) + { + return regionInfo; + } + + if (m_remoteRegionInfoCache.TryGetValue(regionHandle, out regionInfo)) + { + } + else + { + try + { + Hashtable requestData = new Hashtable(); + requestData["region_handle"] = regionHandle.ToString(); + requestData["authkey"] = serversInfo.GridSendKey; + ArrayList SendParams = new ArrayList(); + SendParams.Add(requestData); + XmlRpcRequest GridReq = new XmlRpcRequest("simulator_data_request", SendParams); + XmlRpcResponse GridResp = GridReq.Send(serversInfo.GridURL, 3000); + + Hashtable responseData = (Hashtable) GridResp.Value; + + if (responseData.ContainsKey("error")) + { + Console.WriteLine("error received from grid server" + responseData["error"]); + return null; + } + + uint regX = Convert.ToUInt32((string) responseData["region_locx"]); + uint regY = Convert.ToUInt32((string) responseData["region_locy"]); + string internalIpStr = (string) responseData["sim_ip"]; + uint port = Convert.ToUInt32(responseData["sim_port"]); + string externalUri = (string) responseData["sim_uri"]; + + IPEndPoint neighbourInternalEndPoint = new IPEndPoint(IPAddress.Parse(internalIpStr), (int) port); + string neighbourExternalUri = externalUri; + regionInfo = new RegionInfo(regX, regY, neighbourInternalEndPoint, internalIpStr); + + regionInfo.RemotingPort = Convert.ToUInt32((string) responseData["remoting_port"]); + regionInfo.RemotingAddress = internalIpStr; + + regionInfo.RegionID = new LLUUID((string) responseData["region_UUID"]); + regionInfo.RegionName = (string) responseData["region_name"]; + + m_remoteRegionInfoCache.Add(regionHandle, regionInfo); + } + catch (WebException) + { + m_log.Error("[GRID]: " + + "Region lookup failed for: " + regionHandle.ToString() + + " - Is the GridServer down?"); + return null; + } + } + + return regionInfo; + } + + /// + /// + /// + /// + /// + /// + /// + /// + public List RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY) + { + int temp = 0; + + if (minX > maxX) + { + temp = minX; + minX = maxX; + maxX = temp; + } + if (minY > maxY) + { + temp = minY; + minY = maxY; + maxY = temp; + } + + Hashtable respData = MapBlockQuery(minX, minY, maxX, maxY); + + List neighbours = new List(); + + foreach (ArrayList a in respData.Values) + { + foreach (Hashtable n in a) + { + MapBlockData neighbour = new MapBlockData(); + + neighbour.X = Convert.ToUInt16(n["x"]); + neighbour.Y = Convert.ToUInt16(n["y"]); + + neighbour.Name = (string) n["name"]; + neighbour.Access = Convert.ToByte(n["access"]); + neighbour.RegionFlags = Convert.ToUInt32(n["region-flags"]); + neighbour.WaterHeight = Convert.ToByte(n["water-height"]); + neighbour.MapImageId = new LLUUID((string) n["map-image-id"]); + + neighbours.Add(neighbour); + } + } + + return neighbours; + } + + + + + /// + /// Performs a XML-RPC query against the grid server returning mapblock information in the specified coordinates + /// + /// REDUNDANT - OGS1 is to be phased out in favour of OGS2 + /// Minimum X value + /// Minimum Y value + /// Maximum X value + /// Maximum Y value + /// Hashtable of hashtables containing map data elements + private Hashtable MapBlockQuery(int minX, int minY, int maxX, int maxY) + { + Hashtable param = new Hashtable(); + param["xmin"] = minX; + param["ymin"] = minY; + param["xmax"] = maxX; + param["ymax"] = maxY; + IList parameters = new ArrayList(); + parameters.Add(param); + try + { + XmlRpcRequest req = new XmlRpcRequest("map_block", parameters); + XmlRpcResponse resp = req.Send(serversInfo.GridURL, 10000); + Hashtable respData = (Hashtable) resp.Value; + return respData; + } + catch (Exception e) + { + m_log.Error("MapBlockQuery XMLRPC failure: " + e.ToString()); + return new Hashtable(); + } + } + + /// + /// A ping / version check + /// + /// + /// + public XmlRpcResponse PingCheckReply(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + + Hashtable respData = new Hashtable(); + respData["online"] = "true"; + + m_localBackend.PingCheckReply(respData); + + response.Value = respData; + + return response; + } + + + // Grid Request Processing + /// + /// + /// + /// + /// + public XmlRpcResponse ExpectUser(XmlRpcRequest request) + { + m_log.Debug("[CONNECTION DEBUGGING]: Expect User called, starting agent setup ... "); + Hashtable requestData = (Hashtable) request.Params[0]; + AgentCircuitData agentData = new AgentCircuitData(); + agentData.SessionID = new LLUUID((string) requestData["session_id"]); + agentData.SecureSessionID = new LLUUID((string) requestData["secure_session_id"]); + agentData.firstname = (string) requestData["firstname"]; + agentData.lastname = (string) requestData["lastname"]; + agentData.AgentID = new LLUUID((string) requestData["agent_id"]); + agentData.circuitcode = Convert.ToUInt32(requestData["circuit_code"]); + agentData.CapsPath = (string) requestData["caps_path"]; + + if (requestData.ContainsKey("child_agent") && requestData["child_agent"].Equals("1")) + { + m_log.Debug("[CONNECTION DEBUGGING]: Child agent detected"); + agentData.child = true; + } + else + { + m_log.Debug("[CONNECTION DEBUGGING]: Main agent detected"); + agentData.startpos = + new LLVector3(Convert.ToUInt32(requestData["startpos_x"]), + Convert.ToUInt32(requestData["startpos_y"]), + Convert.ToUInt32(requestData["startpos_z"])); + agentData.child = false; + } + + ulong regionHandle = Convert.ToUInt64((string) requestData["regionhandle"]); + + m_log.Debug("[CONNECTION DEBUGGING]: Triggering welcome for " + agentData.AgentID.ToString() + " into " + regionHandle.ToString()); + m_localBackend.TriggerExpectUser(regionHandle, agentData); + + m_log.Info("[GRID]: Welcoming new user..."); + + return new XmlRpcResponse(); + } + + #region m_interRegion Comms + + /// + /// + /// + private void StartRemoting() + { + TcpChannel ch; + try + { + ch = new TcpChannel((int)NetworkServersInfo.RemotingListenerPort); + ChannelServices.RegisterChannel(ch, false); // Disabled security as Mono doesnt support this. + } + catch (Exception ex) + { + m_log.Error("Exception while attempting to listen on TCP port " + (int)NetworkServersInfo.RemotingListenerPort + "."); + throw (ex); + } + + WellKnownServiceTypeEntry wellType = + new WellKnownServiceTypeEntry(typeof (OGS1InterRegionRemoting), "InterRegions", + WellKnownObjectMode.Singleton); + RemotingConfiguration.RegisterWellKnownServiceType(wellType); + InterRegionSingleton.Instance.OnArrival += TriggerExpectAvatarCrossing; + InterRegionSingleton.Instance.OnChildAgent += IncomingChildAgent; + InterRegionSingleton.Instance.OnPrimGroupArrival += IncomingPrim; + InterRegionSingleton.Instance.OnPrimGroupNear += TriggerExpectPrimCrossing; + InterRegionSingleton.Instance.OnRegionUp += TriggerRegionUp; + InterRegionSingleton.Instance.OnChildAgentUpdate += TriggerChildAgentUpdate; + InterRegionSingleton.Instance.OnTellRegionToCloseChildConnection += TriggerTellRegionToCloseChildConnection; + + } + + #region Methods called by regions in this instance + + public bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData) + { + int failures = 0; + lock (m_deadRegionCache) + { + if (m_deadRegionCache.ContainsKey(regionHandle)) + { + failures = m_deadRegionCache[regionHandle]; + } + } + if (failures <= 3) + { + RegionInfo regInfo = null; + try + { + if (m_localBackend.ChildAgentUpdate(regionHandle, cAgentData)) + { + return true; + } + + regInfo = RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + //don't want to be creating a new link to the remote instance every time like we are here + bool retValue = false; + + + OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject( + typeof(OGS1InterRegionRemoting), + "tcp://" + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions"); + + if (remObject != null) + { + retValue = remObject.ChildAgentUpdate(regionHandle, cAgentData); + } + else + { + Console.WriteLine("remoting object not found"); + } + remObject = null; + //m_log.Info("[INTER]: " + + //gdebugRegionName + + //": OGS1 tried to Update Child Agent data on outside region and got " + + //retValue.ToString()); + + return retValue; + } + NoteDeadRegion(regionHandle); + + return false; + } + catch (RemotingException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Remoting Error: Unable to connect to adjacent region: " + + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (SocketException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Socket Error: Unable to connect to adjacent region: " + " " + + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (InvalidCredentialException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Invalid Credentials: Unable to connect to adjacent region: " + + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (AuthenticationException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Authentication exception: Unable to connect to adjacent region: " + + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (Exception e) + { + NoteDeadRegion(regionHandle); + m_log.Debug(e.ToString()); + return false; + } + } + else + { + //m_log.Info("[INTERREGION]: Skipped Sending Child Update to a region because it failed too many times:" + regionHandle.ToString()); + return false; + } + } + + /// + /// + /// + /// + /// + /// + public bool InformRegionOfChildAgent(ulong regionHandle, AgentCircuitData agentData) + { + RegionInfo regInfo = null; + try + { + if (m_localBackend.InformRegionOfChildAgent(regionHandle, agentData)) + { + return true; + } + + regInfo = RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + //don't want to be creating a new link to the remote instance every time like we are here + bool retValue = false; + + + OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject( + typeof(OGS1InterRegionRemoting), + "tcp://" + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions"); + + if (remObject != null) + { + retValue = remObject.InformRegionOfChildAgent(regionHandle, new sAgentCircuitData(agentData)); + } + else + { + Console.WriteLine("remoting object not found"); + } + remObject = null; + m_log.Info("[INTER]: " + + gdebugRegionName + ": OGS1 tried to InformRegionOfChildAgent for " + + agentData.firstname + " " + agentData.lastname + " and got " + + retValue.ToString()); + + return retValue; + + } + NoteDeadRegion(regionHandle); + return false; + } + catch (RemotingException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Remoting Error: Unable to connect to adjacent region: " + regInfo.RegionName + + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (SocketException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Socket Error: Unable to connect to adjacent region: " + regInfo.RegionName + " " + + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (InvalidCredentialException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Invalid Credentials: Unable to connect to adjacent region: " + regInfo.RegionName + + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (AuthenticationException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Authentication exception: Unable to connect to adjacent region: " + + regInfo.RegionName + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (Exception e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Unknown exception: Unable to connect to adjacent region: " + regInfo.RegionName + + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + } + + // UGLY! + public bool RegionUp(SearializableRegionInfo region, ulong regionhandle) + { + SearializableRegionInfo regInfo = null; + try + { + // You may ask why this is in here... + // The region asking the grid services about itself.. + // And, surprisingly, the reason is.. it doesn't know + // it's own remoting port! How special. + region = new SearializableRegionInfo(RequestNeighbourInfo(region.RegionHandle)); + region.RemotingAddress = region.ExternalHostName; + region.RemotingPort = NetworkServersInfo.RemotingListenerPort; + if (m_localBackend.RegionUp(region, regionhandle)) + { + return true; + } + + regInfo = new SearializableRegionInfo(RequestNeighbourInfo(regionhandle)); + if (regInfo != null) + { + // If we're not trying to remote to ourselves. + if (regInfo.RemotingAddress != region.RemotingAddress && region.RemotingAddress != null) + { + //don't want to be creating a new link to the remote instance every time like we are here + bool retValue = false; + + + OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting) Activator.GetObject( + typeof ( + OGS1InterRegionRemoting), + "tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions"); + + if (remObject != null) + { + retValue = remObject.RegionUp(region, regionhandle); + } + else + { + Console.WriteLine("remoting object not found"); + } + remObject = null; + m_log.Info("[INTER]: " + gdebugRegionName + ": OGS1 tried to inform region I'm up"); + + return retValue; + } + else + { + // We're trying to inform ourselves via remoting. + // This is here because we're looping over the listeners before we get here. + // Odd but it should work. + return true; + } + } + + return false; + } + catch (RemotingException e) + { + m_log.Warn("Remoting Error: Unable to connect to adjacent region using tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY + + " - Is this neighbor up?"); + m_log.Debug(e.ToString()); + return false; + } + catch (SocketException e) + { + m_log.Warn("Socket Error: Unable to connect to adjacent region using tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY + + " - Is this neighbor up?"); + m_log.Debug(e.ToString()); + return false; + } + catch (InvalidCredentialException e) + { + m_log.Warn("Invalid Credentials: Unable to connect to adjacent region using tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (AuthenticationException e) + { + m_log.Warn("Authentication exception: Unable to connect to adjacent region using tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (Exception e) + { + // This line errors with a Null Reference Exception.. Why? @.@ + //m_log.Warn("Unknown exception: Unable to connect to adjacent region using tcp://" + regInfo.RemotingAddress + + // ":" + regInfo.RemotingPort + + //"/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY + " - This is likely caused by an incompatibility in the protocol between this sim and that one"); + m_log.Debug(e.ToString()); + return false; + } + } + + /// + /// + /// + /// + /// + /// + public bool InformRegionOfPrimCrossing(ulong regionHandle, LLUUID primID, string objData) + { + int failures = 0; + lock (m_deadRegionCache) + { + if (m_deadRegionCache.ContainsKey(regionHandle)) + { + failures = m_deadRegionCache[regionHandle]; + } + } + if (failures <= 1) + { + RegionInfo regInfo = null; + try + { + if (m_localBackend.InformRegionOfPrimCrossing(regionHandle, primID, objData)) + { + return true; + } + + regInfo = RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + //don't want to be creating a new link to the remote instance every time like we are here + bool retValue = false; + + + OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject( + typeof(OGS1InterRegionRemoting), + "tcp://" + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions"); + + if (remObject != null) + { + retValue = remObject.InformRegionOfPrimCrossing(regionHandle, primID.UUID, objData); + } + else + { + Console.WriteLine("remoting object not found"); + } + remObject = null; + + + return retValue; + } + NoteDeadRegion(regionHandle); + return false; + } + catch (RemotingException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Remoting Error: Unable to connect to adjacent region: " + regionHandle); + m_log.Debug(e.ToString()); + return false; + } + catch (SocketException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Remoting Error: Unable to connect to adjacent region: " + regionHandle); + m_log.Debug(e.ToString()); + return false; + } + catch (InvalidCredentialException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Invalid Credential Exception: Invalid Credentials : " + regionHandle); + m_log.Debug(e.ToString()); + return false; + } + catch (AuthenticationException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Authentication exception: Unable to connect to adjacent region: " + regionHandle); + + m_log.Debug(e.ToString()); + return false; + } + catch (Exception e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Unknown exception: Unable to connect to adjacent region: " + regionHandle); + m_log.Debug(e.ToString()); + return false; + } + } + else + { + return false; + } + } + + /// + /// + /// + /// + /// + /// + /// + public bool ExpectAvatarCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying) + { + RegionInfo regInfo = null; + try + { + if (m_localBackend.TriggerExpectAvatarCrossing(regionHandle, agentID, position, isFlying)) + { + return true; + } + + regInfo = RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + bool retValue = false; + OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting) Activator.GetObject( + typeof (OGS1InterRegionRemoting), + "tcp://" + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions"); + if (remObject != null) + { + retValue = + remObject.ExpectAvatarCrossing(regionHandle, agentID.UUID, new sLLVector3(position), + isFlying); + } + else + { + Console.WriteLine("remoting object not found"); + } + remObject = null; + + return retValue; + } + //TODO need to see if we know about where this region is and use .net remoting + // to inform it. + NoteDeadRegion(regionHandle); + return false; + } + catch (RemotingException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Remoting Error: Unable to connect to adjacent region: " + regInfo.RegionName + + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch + { + NoteDeadRegion(regionHandle); + return false; + } + } + + public bool ExpectPrimCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isPhysical) + { + RegionInfo regInfo = null; + try + { + if (m_localBackend.TriggerExpectPrimCrossing(regionHandle, agentID, position, isPhysical)) + { + return true; + } + + regInfo = RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + bool retValue = false; + OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting) Activator.GetObject( + typeof (OGS1InterRegionRemoting), + "tcp://" + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions"); + if (remObject != null) + { + retValue = + remObject.ExpectAvatarCrossing(regionHandle, agentID.UUID, new sLLVector3(position), + isPhysical); + } + else + { + Console.WriteLine("remoting object not found"); + } + remObject = null; + + return retValue; + } + //TODO need to see if we know about where this region is and use .net remoting + // to inform it. + NoteDeadRegion(regionHandle); + return false; + } + catch (RemotingException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Remoting Error: Unable to connect to adjacent region: " + regionHandle); + m_log.Debug(e.ToString()); + return false; + } + catch (SocketException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Remoting Error: Unable to connect to adjacent region: " + regionHandle); + m_log.Debug(e.ToString()); + return false; + } + catch (InvalidCredentialException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Invalid Credential Exception: Invalid Credentials : " + regionHandle); + m_log.Debug(e.ToString()); + return false; + } + catch (AuthenticationException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Authentication exception: Unable to connect to adjacent region: " + regionHandle); + + m_log.Debug(e.ToString()); + return false; + } + catch (Exception e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Unknown exception: Unable to connect to adjacent region: " + regionHandle); + m_log.Debug(e.ToString()); + return false; + } + } + + public bool TellRegionToCloseChildConnection(ulong regionHandle, LLUUID agentID) + { + RegionInfo regInfo = null; + try + { + if (m_localBackend.TriggerTellRegionToCloseChildConnection(regionHandle, agentID)) + { + return true; + } + + regInfo = RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + bool retValue = false; + OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject( + typeof(OGS1InterRegionRemoting), + "tcp://" + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions"); + if (remObject != null) + { + retValue = + remObject.TellRegionToCloseChildConnection(regionHandle, agentID.UUID); + } + else + { + Console.WriteLine("remoting object not found"); + } + remObject = null; + + return true; + } + //TODO need to see if we know about where this region is and use .net remoting + // to inform it. + NoteDeadRegion(regionHandle); + return false; + } + catch (RemotingException) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Remoting Error: Unable to connect to adjacent region to tell it to close child agents: " + regInfo.RegionName + + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + //m_log.Debug(e.ToString()); + return false; + } + + catch (SocketException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Socket Error: Unable to connect to adjacent region using tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY + + " - Is this neighbor up?"); + m_log.Debug(e.ToString()); + return false; + } + catch (InvalidCredentialException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Invalid Credentials: Unable to connect to adjacent region using tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (AuthenticationException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("Authentication exception: Unable to connect to adjacent region using tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (WebException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("WebException exception: Unable to connect to adjacent region using tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.Debug(e.ToString()); + return false; + } + catch (Exception e) + { + NoteDeadRegion(regionHandle); + // This line errors with a Null Reference Exception.. Why? @.@ + //m_log.Warn("Unknown exception: Unable to connect to adjacent region using tcp://" + regInfo.RemotingAddress + + // ":" + regInfo.RemotingPort + + //"/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY + " - This is likely caused by an incompatibility in the protocol between this sim and that one"); + m_log.Debug(e.ToString()); + return false; + } + } + + public bool AcknowledgeAgentCrossed(ulong regionHandle, LLUUID agentId) + { + return m_localBackend.AcknowledgeAgentCrossed(regionHandle, agentId); + } + + public bool AcknowledgePrimCrossed(ulong regionHandle, LLUUID primId) + { + return m_localBackend.AcknowledgePrimCrossed(regionHandle, primId); + } + + #endregion + + #region Methods triggered by calls from external instances + + /// + /// + /// + /// + /// + /// + public bool IncomingChildAgent(ulong regionHandle, AgentCircuitData agentData) + { + //m_log.Info("[INTER]: " + gdebugRegionName + ": Incoming OGS1 Agent " + agentData.firstname + " " + agentData.lastname); + + try + { + return m_localBackend.IncomingChildAgent(regionHandle, agentData); + } + catch (RemotingException) + { + //m_log.Error("Remoting Error: Unable to connect to adjacent region.\n" + e.ToString()); + return false; + } + } + + public bool TriggerRegionUp(SearializableRegionInfo regionData, ulong regionhandle) + { + m_log.Info("[INTER]: " + + gdebugRegionName + "Incoming OGS1 RegionUpReport: " + "(" + regionData.RegionLocX + + "," + regionData.RegionLocY + "). Giving this region a fresh set of 'dead' tries"); + + try + { + lock (m_deadRegionCache) + { + if (m_deadRegionCache.ContainsKey(regionData.RegionHandle)) + { + + m_deadRegionCache.Remove(regionData.RegionHandle); + } + } + + return m_localBackend.TriggerRegionUp(new RegionInfo(regionData), regionhandle); + + } + + catch (RemotingException e) + { + m_log.Error("Remoting Error: Unable to connect to adjacent region.\n" + e.ToString()); + return false; + } + } + + public bool TriggerChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData) + { + //m_log.Info("[INTER]: Incoming OGS1 Child Agent Data Update"); + + try + { + return m_localBackend.TriggerChildAgentUpdate(regionHandle, cAgentData); + } + catch (RemotingException e) + { + m_log.Error("Remoting Error: Unable to connect to adjacent region.\n" + e.ToString()); + return false; + } + } + + /// + /// + /// + /// + /// + /// + public bool IncomingPrim(ulong regionHandle, LLUUID primID, string objData) + { + // Is this necessary? + try + { + m_localBackend.TriggerExpectPrim(regionHandle, primID, objData); + return true; + //m_localBackend. + + } + catch (RemotingException e) + { + m_log.Error("Remoting Error: Unable to connect to adjacent region.\n" + e.ToString()); + return false; + } + return false; + } + + /// + /// + /// + /// + /// + /// + /// + public bool TriggerExpectAvatarCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying) + { + try + { + return m_localBackend.TriggerExpectAvatarCrossing(regionHandle, agentID, position, isFlying); + } + catch (RemotingException e) + { + m_log.Error("Remoting Error: Unable to connect to adjacent region.\n" + e.ToString()); + return false; + } + } + + public bool TriggerExpectPrimCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isPhysical) + { + try + { + return m_localBackend.TriggerExpectPrimCrossing(regionHandle, agentID, position, isPhysical); + } + catch (RemotingException e) + { + m_log.Error("Remoting Error: Unable to connect to adjacent region.\n" + e.ToString()); + return false; + } + } + + public bool TriggerTellRegionToCloseChildConnection(ulong regionHandle, LLUUID agentID) + { + try + { + return m_localBackend.TriggerTellRegionToCloseChildConnection(regionHandle, agentID); + } + catch (RemotingException) + { + m_log.Info("[INTERREGION]: Remoting Error: Unable to connect to neighbour to tell it to close a child connection"); + return false; + } + + } + + #endregion + + #endregion + + // helper to see if remote region is up + bool m_bAvailable = false; + int timeOut = 10; //10 seconds + + public void CheckRegion(string address, uint port) + { + m_bAvailable = false; + IPAddress ia = null; + IPAddress.TryParse(address, out ia); + IPEndPoint m_EndPoint = new IPEndPoint(ia, (int)port); + AsyncCallback ConnectedMethodCallback = new AsyncCallback(ConnectedMethod); + Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + IAsyncResult ar = socket.BeginConnect(m_EndPoint, ConnectedMethodCallback, socket); + ar.AsyncWaitHandle.WaitOne(timeOut*1000, false); + } + + public bool Available + { + get { return m_bAvailable; } + } + + void ConnectedMethod(IAsyncResult ar) + { + Socket socket = (Socket)ar.AsyncState; + try + { + socket.EndConnect(ar); + m_bAvailable = true; + } + catch (Exception) + { + } + socket.Close(); + } + public void NoteDeadRegion(ulong regionhandle) + { + lock (m_deadRegionCache) + { + if (m_deadRegionCache.ContainsKey(regionhandle)) + { + m_deadRegionCache[regionhandle] = m_deadRegionCache[regionhandle] + 1; + } + else + { + m_deadRegionCache.Add(regionhandle, 1); + } + } + } + } + +} diff --git a/trunk/OpenSim/Region/Communications/OGS1/OGS1InterSimComms.cs b/trunk/OpenSim/Region/Communications/OGS1/OGS1InterSimComms.cs new file mode 100644 index 0000000000..217bb81a82 --- /dev/null +++ b/trunk/OpenSim/Region/Communications/OGS1/OGS1InterSimComms.cs @@ -0,0 +1,249 @@ +/* +* 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; +using System.Runtime.Remoting; +using libsecondlife; +using OpenSim.Framework; + +namespace OpenSim.Region.Communications.OGS1 +{ + public delegate bool InformRegionChild(ulong regionHandle, AgentCircuitData agentData); + + public delegate bool ExpectArrival(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying); + + public delegate bool InformRegionPrimGroup(ulong regionHandle, LLUUID primID, LLVector3 Positon, bool isPhysical); + + public delegate bool PrimGroupArrival(ulong regionHandle, LLUUID primID, string objData); + + public delegate bool RegionUp(SearializableRegionInfo region, ulong regionhandle); + + public delegate bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate childUpdate); + + public delegate bool TellRegionToCloseChildConnection(ulong regionHandle, LLUUID agentID); + + public sealed class InterRegionSingleton + { + private static readonly InterRegionSingleton instance = new InterRegionSingleton(); + + public event InformRegionChild OnChildAgent; + public event ExpectArrival OnArrival; + public event InformRegionPrimGroup OnPrimGroupNear; + public event PrimGroupArrival OnPrimGroupArrival; + public event RegionUp OnRegionUp; + public event ChildAgentUpdate OnChildAgentUpdate; + public event TellRegionToCloseChildConnection OnTellRegionToCloseChildConnection; + + + + static InterRegionSingleton() + { + } + + private InterRegionSingleton() + { + } + + public static InterRegionSingleton Instance + { + get { return instance; } + } + + public bool InformRegionOfChildAgent(ulong regionHandle, AgentCircuitData agentData) + { + if (OnChildAgent != null) + { + return OnChildAgent(regionHandle, agentData); + } + return false; + } + + public bool RegionUp(SearializableRegionInfo sregion, ulong regionhandle) + { + if (OnRegionUp != null) + { + return OnRegionUp(sregion, regionhandle); + } + return false; + } + + public bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentUpdate) + { + if (OnChildAgentUpdate != null) + { + return OnChildAgentUpdate(regionHandle, cAgentUpdate); + } + return false; + } + + public bool ExpectAvatarCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying) + { + if (OnArrival != null) + { + return OnArrival(regionHandle, agentID, position, isFlying); + } + return false; + } + + public bool InformRegionPrim(ulong regionHandle, LLUUID primID, LLVector3 position, bool isPhysical) + { + if (OnPrimGroupNear != null) + { + return OnPrimGroupNear(regionHandle, primID, position, isPhysical); + } + return false; + } + + public bool ExpectPrimCrossing(ulong regionHandle, LLUUID primID, string objData) + { + if (OnPrimGroupArrival != null) + { + return OnPrimGroupArrival(regionHandle, primID, objData); + } + return false; + } + + public bool TellRegionToCloseChildConnection(ulong regionHandle, LLUUID agentID) + { + if (OnTellRegionToCloseChildConnection != null) + { + + return OnTellRegionToCloseChildConnection(regionHandle, agentID); + } + return false; + } + } + + public class OGS1InterRegionRemoting : MarshalByRefObject + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public OGS1InterRegionRemoting() + { + } + + public bool InformRegionOfChildAgent(ulong regionHandle, sAgentCircuitData agentData) + { + try + { + return + InterRegionSingleton.Instance.InformRegionOfChildAgent(regionHandle, new AgentCircuitData(agentData)); + } + catch (RemotingException e) + { + Console.WriteLine("Remoting Error: Unable to connect to remote region.\n" + e.ToString()); + return false; + } + } + + public bool RegionUp(SearializableRegionInfo region, ulong regionhandle) + { + try + { + return InterRegionSingleton.Instance.RegionUp(region, regionhandle); + } + catch (RemotingException e) + { + Console.WriteLine("Remoting Error: Unable to connect to remote region.\n" + e.ToString()); + return false; + } + } + + public bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData) + { + try + { + return InterRegionSingleton.Instance.ChildAgentUpdate(regionHandle, cAgentData); + } + catch (RemotingException e) + { + Console.WriteLine("Remoting Error: Unable to send Child agent update to remote region.\n" + e.ToString()); + return false; + } + } + + + public bool ExpectAvatarCrossing(ulong regionHandle, Guid agentID, sLLVector3 position, bool isFlying) + { + try + { + return + InterRegionSingleton.Instance.ExpectAvatarCrossing(regionHandle, new LLUUID(agentID), + new LLVector3(position.x, position.y, position.z), + isFlying); + } + catch (RemotingException e) + { + Console.WriteLine("Remoting Error: Unable to connect to remote region.\n" + e.ToString()); + return false; + } + } + + public bool InformRegionPrim(ulong regionHandle, Guid SceneObjectGroupID, sLLVector3 position, bool isPhysical) + { + try + { + return + InterRegionSingleton.Instance.InformRegionPrim(regionHandle, new LLUUID(SceneObjectGroupID), + new LLVector3(position.x, position.y, position.z), + isPhysical); + } + catch (RemotingException e) + { + Console.WriteLine("Remoting Error: Unable to connect to remote region.\n" + e.ToString()); + return false; + } + } + + public bool InformRegionOfPrimCrossing(ulong regionHandle, Guid primID, string objData) + { + try + { + return InterRegionSingleton.Instance.ExpectPrimCrossing(regionHandle, new LLUUID(primID), objData); + } + catch (RemotingException e) + { + Console.WriteLine("Remoting Error: Unable to connect to remote region.\n" + e.ToString()); + return false; + } + } + + public bool TellRegionToCloseChildConnection(ulong regionHandle, Guid agentID) + { + try + { + return InterRegionSingleton.Instance.TellRegionToCloseChildConnection(regionHandle, new LLUUID(agentID)); + } + catch (RemotingException) + { + m_log.Info("[INTERREGION]: Remoting Error: Unable to connect to remote region: " + regionHandle.ToString()); + return false; + } + } + } +} diff --git a/trunk/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs b/trunk/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs new file mode 100644 index 0000000000..8ff62d022c --- /dev/null +++ b/trunk/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs @@ -0,0 +1,208 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; + +namespace OpenSim.Region.Communications.OGS1 +{ + public class OGS1InventoryService : IInventoryServices + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private string _inventoryServerUrl; + private Dictionary m_RequestingInventory = new Dictionary(); + + public OGS1InventoryService(string inventoryServerUrl) + { + _inventoryServerUrl = inventoryServerUrl; + } + + #region IInventoryServices Members + + // See IInventoryServices + public void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, + InventoryItemInfo itemCallBack) + { + if (!m_RequestingInventory.ContainsKey(userID)) + { + InventoryRequest request = new InventoryRequest(userID, folderCallBack, itemCallBack); + m_RequestingInventory.Add(userID, request); + RequestInventory(userID); + } + } + + /// + /// Request the entire user's inventory (folders and items) from the inventory server. + /// + /// XXX May want to change this so that we don't end up shuffling over data which might prove + /// entirely unnecessary. + /// + /// + private void RequestInventory(LLUUID userID) + { + try + { + m_log.InfoFormat( + "[INVENTORY]: Requesting inventory from {0}/GetInventory/ for user {1}", + _inventoryServerUrl, userID); + + RestObjectPosterResponse requester + = new RestObjectPosterResponse(); + requester.ResponseCallback = InventoryResponse; + + requester.BeginPostObject(_inventoryServerUrl + "/GetInventory/", userID.UUID); + } + catch (Exception e) + { + m_log.Error("[INVENTORY]: " + e.ToString()); + } + } + + /// + /// Callback used by the inventory server GetInventory request + /// + /// + private void InventoryResponse(InventoryCollection response) + { + LLUUID userID = response.UserID; + if (m_RequestingInventory.ContainsKey(userID)) + { + m_log.InfoFormat("[INVENTORY]: " + + "Received inventory response for user {0} containing {1} folders and {2} items", + userID, response.Folders.Count, response.AllItems.Count); + + InventoryFolderImpl rootFolder = null; + InventoryRequest request = m_RequestingInventory[userID]; + foreach (InventoryFolderBase folder in response.Folders) + { + if (folder.parentID == LLUUID.Zero) + { + InventoryFolderImpl newfolder = new InventoryFolderImpl(folder); + rootFolder = newfolder; + request.FolderCallBack(userID, newfolder); + } + } + + if (rootFolder != null) + { + foreach (InventoryFolderBase folder in response.Folders) + { + if (folder.folderID != rootFolder.folderID) + { + InventoryFolderImpl newfolder = new InventoryFolderImpl(folder); + request.FolderCallBack(userID, newfolder); + } + } + + foreach (InventoryItemBase item in response.AllItems) + { + request.ItemCallBack(userID, item); + } + } + m_RequestingInventory.Remove(userID); + } + else + { + m_log.WarnFormat( + "[INVENTORY]: " + + "Received inventory response for {0} for which we do not have a record of requesting!", + userID); + } + } + + public void AddNewInventoryFolder(LLUUID userID, InventoryFolderBase folder) + { + SynchronousRestObjectPoster.BeginPostObject( + "POST", _inventoryServerUrl + "/NewFolder/", folder); + } + + public void MoveInventoryFolder(LLUUID userID, InventoryFolderBase folder) + { + SynchronousRestObjectPoster.BeginPostObject( + "POST", _inventoryServerUrl + "/MoveFolder/", folder); + } + + public void AddNewInventoryItem(LLUUID userID, InventoryItemBase item) + { + SynchronousRestObjectPoster.BeginPostObject( + "POST", _inventoryServerUrl + "/NewItem/", item); + } + + public void DeleteInventoryItem(LLUUID userID, InventoryItemBase item) + { + SynchronousRestObjectPoster.BeginPostObject( + "POST", _inventoryServerUrl + "/DeleteItem/", item); + } + + public bool HasInventoryForUser(LLUUID userID) + { + return false; + } + + public InventoryFolderBase RequestRootFolder(LLUUID userID) + { + return null; + } + + public virtual InventoryFolderBase RequestNamedFolder(LLUUID userID, string folderName) + { + return null; + } + + public void CreateNewUserInventory(LLUUID user) + { + } + + public List RequestFirstLevelFolders(LLUUID userID) + { + return new List(); + } + + #endregion + + public class InventoryRequest + { + public LLUUID UserID; + public InventoryFolderInfo FolderCallBack; + public InventoryItemInfo ItemCallBack; + + public InventoryRequest(LLUUID userId, InventoryFolderInfo folderCall, InventoryItemInfo itemCall) + { + UserID = userId; + FolderCallBack = folderCall; + ItemCallBack = itemCall; + } + } + } +} diff --git a/trunk/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs b/trunk/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs new file mode 100644 index 0000000000..9a22d14183 --- /dev/null +++ b/trunk/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs @@ -0,0 +1,465 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Text.RegularExpressions; +using libsecondlife; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Communications.OGS1 +{ + public class OGS1UserServices : IUserService + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private CommunicationsOGS1 m_parent; + + public OGS1UserServices(CommunicationsOGS1 parent) + { + m_parent = parent; + } + + public UserProfileData ConvertXMLRPCDataToUserProfile(Hashtable data) + { + if (data.Contains("error_type")) + { + m_log.Warn("[GRID]: " + + "Error sent by user server when trying to get user profile: (" + + data["error_type"] + + "): " + data["error_desc"]); + return null; + } + + UserProfileData userData = new UserProfileData(); + userData.username = (string) data["firstname"]; + userData.surname = (string) data["lastname"]; + userData.UUID = new LLUUID((string) data["uuid"]); + userData.userInventoryURI = (string) data["server_inventory"]; + userData.userAssetURI = (string) data["server_asset"]; + userData.profileFirstText = (string) data["profile_firstlife_about"]; + userData.profileFirstImage = new LLUUID((string) data["profile_firstlife_image"]); + userData.profileCanDoMask = Convert.ToUInt32((string) data["profile_can_do"]); + userData.profileWantDoMask = Convert.ToUInt32(data["profile_want_do"]); + userData.profileImage = new LLUUID((string) data["profile_image"]); + userData.lastLogin = Convert.ToInt32((string) data["profile_lastlogin"]); + userData.homeRegion = Convert.ToUInt64((string) data["home_region"]); + userData.homeLocation = + new LLVector3((float) Convert.ToDecimal((string) data["home_coordinates_x"]), + (float) Convert.ToDecimal((string) data["home_coordinates_y"]), + (float) Convert.ToDecimal((string) data["home_coordinates_z"])); + userData.homeLookAt = + new LLVector3((float) Convert.ToDecimal((string) data["home_look_x"]), + (float) Convert.ToDecimal((string) data["home_look_y"]), + (float) Convert.ToDecimal((string) data["home_look_z"])); + + return userData; + } + + public List ConvertXMLRPCDataToAvatarPickerList(LLUUID queryID, Hashtable data) + { + List pickerlist = new List(); + int pickercount = Convert.ToInt32((string) data["avcount"]); + LLUUID respqueryID = new LLUUID((string) data["queryid"]); + if (queryID == respqueryID) + { + for (int i = 0; i < pickercount; i++) + { + AvatarPickerAvatar apicker = new AvatarPickerAvatar(); + LLUUID avatarID = new LLUUID((string) data["avatarid" + i.ToString()]); + string firstname = (string) data["firstname" + i.ToString()]; + string lastname = (string) data["lastname" + i.ToString()]; + apicker.AvatarID = avatarID; + apicker.firstName = firstname; + apicker.lastName = lastname; + pickerlist.Add(apicker); + } + } + else + { + m_log.Warn("[INTERGRID]: Got invalid queryID from userServer"); + } + return pickerlist; + } + + public List ConvertXMLRPCDataToFriendListItemList(Hashtable data) + { + List buddylist = new List(); + int buddycount = Convert.ToInt32((string)data["avcount"]); + + + for (int i = 0; i < buddycount; i++) + { + FriendListItem buddylistitem = new FriendListItem(); + + buddylistitem.FriendListOwner = new LLUUID((string)data["ownerID" + i.ToString()]); + buddylistitem.Friend = new LLUUID((string)data["friendID" + i.ToString()]); + buddylistitem.FriendListOwnerPerms = (uint)Convert.ToInt32((string)data["ownerPerms" + i.ToString()]); + buddylistitem.FriendPerms = (uint)Convert.ToInt32((string)data["friendPerms" + i.ToString()]); + + buddylist.Add(buddylistitem); + } + + + return buddylist; + } + + /// + /// Logs off a user on the user server + /// + /// UUID of the user + /// UUID of the Region + /// final position x + /// final position y + /// final position z + public void LogOffUser(LLUUID userid, LLUUID regionid, ulong regionhandle, float posx, float posy, float posz) + { + Hashtable param = new Hashtable(); + param["avatar_uuid"] = userid.UUID.ToString(); + param["region_uuid"] = regionid.UUID.ToString(); + param["region_handle"] = regionhandle.ToString(); + param["region_pos_x"] = posx.ToString(); + param["region_pos_y"] = posy.ToString(); + param["region_pos_z"] = posz.ToString(); + + IList parameters = new ArrayList(); + parameters.Add(param); + XmlRpcRequest req = new XmlRpcRequest("logout_of_simulator", parameters); + try + { + XmlRpcResponse resp = req.Send(m_parent.NetworkServersInfo.UserURL, 3000); + } + catch (System.Net.WebException) + { + m_log.Warn("[LOGOFF]: Unable to notify grid server of user logoff"); + } + + + } + public UserProfileData GetUserProfile(string firstName, string lastName) + { + return GetUserProfile(firstName + " " + lastName); + } + + public List GenerateAgentPickerRequestResponse(LLUUID queryID, string query) + { + List pickerlist = new List(); + Regex objAlphaNumericPattern = new Regex("[^a-zA-Z0-9 ]"); + try + { + Hashtable param = new Hashtable(); + param["queryid"] = (string) queryID.ToString(); + param["avquery"] = objAlphaNumericPattern.Replace(query, String.Empty); + IList parameters = new ArrayList(); + parameters.Add(param); + XmlRpcRequest req = new XmlRpcRequest("get_avatar_picker_avatar", parameters); + XmlRpcResponse resp = req.Send(m_parent.NetworkServersInfo.UserURL, 3000); + Hashtable respData = (Hashtable) resp.Value; + pickerlist = ConvertXMLRPCDataToAvatarPickerList(queryID, respData); + } + catch (WebException e) + { + m_log.Warn("Error when trying to fetch Avatar Picker Response: " + + e.Message); + // Return Empty picker list (no results) + } + return pickerlist; + } + + public UserProfileData GetUserProfile(string name) + { + try + { + Hashtable param = new Hashtable(); + param["avatar_name"] = name; + IList parameters = new ArrayList(); + parameters.Add(param); + XmlRpcRequest req = new XmlRpcRequest("get_user_by_name", parameters); + XmlRpcResponse resp = req.Send(m_parent.NetworkServersInfo.UserURL, 3000); + Hashtable respData = (Hashtable) resp.Value; + + return ConvertXMLRPCDataToUserProfile(respData); + } + catch (WebException e) + { + m_log.Warn("Error when trying to fetch profile data by name from remote user server: " + + e.Message); + } + return null; + } + + public UserProfileData GetUserProfile(LLUUID avatarID) + { + try + { + Hashtable param = new Hashtable(); + param["avatar_uuid"] = avatarID.ToString(); + IList parameters = new ArrayList(); + parameters.Add(param); + XmlRpcRequest req = new XmlRpcRequest("get_user_by_uuid", parameters); + XmlRpcResponse resp = req.Send(m_parent.NetworkServersInfo.UserURL, 3000); + Hashtable respData = (Hashtable) resp.Value; + + return ConvertXMLRPCDataToUserProfile(respData); + } + catch (Exception e) + { + Console.WriteLine("Error when trying to fetch profile data by uuid from remote user server: " + + e.Message); + } + return null; + } + + public void clearUserAgent(LLUUID avatarID) + { + // TODO: implement + } + + public UserProfileData SetupMasterUser(string firstName, string lastName) + { + return SetupMasterUser(firstName, lastName, String.Empty); + } + + public UserProfileData SetupMasterUser(string firstName, string lastName, string password) + { + UserProfileData profile = GetUserProfile(firstName, lastName); + return profile; + } + + public UserProfileData SetupMasterUser(LLUUID uuid) + { + UserProfileData data = GetUserProfile(uuid); + if (data == null) + { + throw new Exception("Unknown master user UUID"); + } + return data; + } + + public LLUUID AddUserProfile(string firstName, string lastName, string pass, uint regX, uint regY) + { + throw new Exception("The method or operation is not implemented."); + } + + #region IUserServices Friend Methods + /// + /// Adds a new friend to the database for XUser + /// + /// The agent that who's friends list is being added to + /// The agent that being added to the friends list of the friends list owner + /// A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects + public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms) + { + try + { + Hashtable param = new Hashtable(); + param["ownerID"] = friendlistowner.UUID.ToString(); + param["friendID"] = friend.UUID.ToString(); + param["friendPerms"] = perms.ToString(); + IList parameters = new ArrayList(); + parameters.Add(param); + + XmlRpcRequest req = new XmlRpcRequest("add_new_user_friend", parameters); + XmlRpcResponse resp = req.Send(m_parent.NetworkServersInfo.UserURL, 3000); + Hashtable respData = (Hashtable)resp.Value; + if (respData != null) + { + if (respData.Contains("returnString")) + { + if ((string)respData["returnString"] == "TRUE") + { + + } + else + { + m_log.Warn("[GRID]: Unable to add new friend, User Server Reported an issue"); + } + } + else + { + m_log.Warn("[GRID]: Unable to add new friend, UserServer didn't understand me!"); + } + } + else + { + m_log.Warn("[GRID]: Unable to add new friend, UserServer didn't understand me!"); + + } + } + catch (WebException e) + { + m_log.Warn("[GRID]: Error when trying to AddNewUserFriend: " + + e.Message); + + } + + } + + /// + /// Delete friend on friendlistowner's friendlist. + /// + /// The agent that who's friends list is being updated + /// The Ex-friend agent + public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend) + { + try + { + Hashtable param = new Hashtable(); + param["ownerID"] = friendlistowner.UUID.ToString(); + param["friendID"] = friend.UUID.ToString(); + + + IList parameters = new ArrayList(); + parameters.Add(param); + + XmlRpcRequest req = new XmlRpcRequest("remove_user_friend", parameters); + XmlRpcResponse resp = req.Send(m_parent.NetworkServersInfo.UserURL, 3000); + Hashtable respData = (Hashtable)resp.Value; + if (respData != null) + { + if (respData.Contains("returnString")) + { + if ((string)respData["returnString"] == "TRUE") + { + + } + else + { + m_log.Warn("[GRID]: Unable to remove friend, User Server Reported an issue"); + } + } + else + { + m_log.Warn("[GRID]: Unable to remove friend, UserServer didn't understand me!"); + } + } + else + { + m_log.Warn("[GRID]: Unable to remove friend, UserServer didn't understand me!"); + + } + } + catch (WebException e) + { + m_log.Warn("[GRID]: Error when trying to RemoveUserFriend: " + + e.Message); + + } + } + + /// + /// Update permissions for friend on friendlistowner's friendlist. + /// + /// The agent that who's friends list is being updated + /// The agent that is getting or loosing permissions + /// A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects + public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms) + { + try + { + Hashtable param = new Hashtable(); + param["ownerID"] = friendlistowner.UUID.ToString(); + param["friendID"] = friend.UUID.ToString(); + param["friendPerms"] = perms.ToString(); + IList parameters = new ArrayList(); + parameters.Add(param); + + XmlRpcRequest req = new XmlRpcRequest("update_user_friend_perms", parameters); + XmlRpcResponse resp = req.Send(m_parent.NetworkServersInfo.UserURL, 3000); + Hashtable respData = (Hashtable)resp.Value; + if (respData != null) + { + if (respData.Contains("returnString")) + { + if ((string)respData["returnString"] == "TRUE") + { + + } + else + { + m_log.Warn("[GRID]: Unable to update_user_friend_perms, User Server Reported an issue"); + } + } + else + { + m_log.Warn("[GRID]: Unable to update_user_friend_perms, UserServer didn't understand me!"); + } + } + else + { + m_log.Warn("[GRID]: Unable to update_user_friend_perms, UserServer didn't understand me!"); + + } + } + catch (WebException e) + { + m_log.Warn("[GRID]: Error when trying to update_user_friend_perms: " + + e.Message); + } + } + /// + /// Returns a list of FriendsListItems that describe the friends and permissions in the friend relationship for LLUUID friendslistowner + /// + /// The agent that we're retreiving the friends Data. + public List GetUserFriendList(LLUUID friendlistowner) + { + List buddylist = new List(); + + try + { + Hashtable param = new Hashtable(); + param["ownerID"] = friendlistowner.UUID.ToString(); + + IList parameters = new ArrayList(); + parameters.Add(param); + XmlRpcRequest req = new XmlRpcRequest("get_user_friend_list", parameters); + XmlRpcResponse resp = req.Send(m_parent.NetworkServersInfo.UserURL, 3000); + Hashtable respData = (Hashtable) resp.Value; + + if (respData.Contains("avcount")) + { + buddylist = ConvertXMLRPCDataToFriendListItemList(respData); + } + + } + catch (WebException e) + { + m_log.Warn("Error when trying to fetch Avatar's friends list: " + + e.Message); + // Return Empty list (no friends) + } + return buddylist; + } + + #endregion + } +} diff --git a/trunk/OpenSim/Region/Communications/OGS1/Properties/AssemblyInfo.cs b/trunk/OpenSim/Region/Communications/OGS1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..2aa5739ab2 --- /dev/null +++ b/trunk/OpenSim/Region/Communications/OGS1/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* 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("OpenGrid.Framework.Communications.OGS1")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenGrid.Framework.Communications.OGS1")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("a8b2b39b-c83b-41e2-b0b5-7ccfc1fddae7")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/EstateManager.cs b/trunk/OpenSim/Region/Environment/EstateManager.cs new file mode 100644 index 0000000000..96baf21bd6 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/EstateManager.cs @@ -0,0 +1,674 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment +{ + /// + /// Processes requests regarding estates. Refer to EstateSettings.cs in OpenSim.Framework. Types for all of the core settings + /// + public class EstateManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + private RegionInfo m_regInfo; + + public enum EstateAccessCodex : uint + { + AccessOptions = 17, + AllowedGroups = 18, + EstateBans = 20, + EstateManagers = 24 + } + + + public EstateManager(Scene scene, RegionInfo reginfo) + { + m_scene = scene; + m_regInfo = reginfo; + } + + private bool convertParamStringToBool(byte[] field) + { + string s = Helpers.FieldToUTF8String(field); + if (s == "1" || s.ToLower() == "y" || s.ToLower() == "yes" || s.ToLower() == "t" || s.ToLower() == "true") + { + return true; + } + return false; + } + + /// + /// Sets terrain texture heights for each of the four corners of the region - textures are distributed as a linear range between the two heights. + /// + /// Which corner + /// Minimum height that texture range should cover + /// Maximum height that texture range should cover + public void setEstateTextureRange(Int16 corner, float lowValue, float highValue) + { + switch (corner) + { + case 0: + m_regInfo.EstateSettings.terrainStartHeight0 = lowValue; + m_regInfo.EstateSettings.terrainHeightRange0 = highValue; + break; + case 1: + m_regInfo.EstateSettings.terrainStartHeight1 = lowValue; + m_regInfo.EstateSettings.terrainHeightRange1 = highValue; + break; + case 2: + m_regInfo.EstateSettings.terrainStartHeight2 = lowValue; + m_regInfo.EstateSettings.terrainHeightRange2 = highValue; + break; + case 3: + m_regInfo.EstateSettings.terrainStartHeight3 = lowValue; + m_regInfo.EstateSettings.terrainHeightRange3 = highValue; + break; + } + } + + /// + /// Sets the 'detail' terrain texture on each of the bands. + /// + /// Which texture band + /// The UUID of the texture + public void setTerrainTexture(Int16 band, LLUUID textureUUID) + { + switch (band) + { + case 0: + m_regInfo.EstateSettings.terrainDetail0 = textureUUID; + break; + case 1: + m_regInfo.EstateSettings.terrainDetail1 = textureUUID; + break; + case 2: + m_regInfo.EstateSettings.terrainDetail2 = textureUUID; + break; + case 3: + m_regInfo.EstateSettings.terrainDetail3 = textureUUID; + break; + } + } + + /// + /// Sets common region settings + /// + /// Water height of the waterplane (may not nessecarily be one value) + /// Maximum amount terrain can be raised from previous baking + /// Minimum amount terrain can be lowered from previous baking + /// Use a fixed time of day on the sun? + /// The offset hour of the day + public void setRegionSettings(float WaterHeight, float TerrainRaiseLimit, float TerrainLowerLimit, + bool UseFixedSun, float SunHour) + { + // Water Height + m_regInfo.EstateSettings.waterHeight = WaterHeight; + m_scene.Terrain.watermap.Fill(WaterHeight); + + // Terraforming limits + m_regInfo.EstateSettings.terrainRaiseLimit = TerrainRaiseLimit; + m_regInfo.EstateSettings.terrainLowerLimit = TerrainLowerLimit; + m_scene.Terrain.maxRaise = TerrainRaiseLimit; + m_scene.Terrain.minLower = TerrainLowerLimit; + + // Time of day / fixed sun + m_regInfo.EstateSettings.useFixedSun = UseFixedSun; + m_regInfo.EstateSettings.sunHour = SunHour; + } + + #region Packet Handlers + + public void handleEstateOwnerMessage(EstateOwnerMessagePacket packet, IClientAPI remote_client) + { + switch (Helpers.FieldToUTF8String(packet.MethodData.Method)) + { + case "getinfo": + + //m_log.Info("[ESTATE]: CLIENT--->" + packet.ToString()); + sendRegionInfoPacketToAll(); + if (m_scene.PermissionsMngr.GenericEstatePermission(remote_client.AgentId)) + { + sendDetailedEstateData(remote_client, packet); + } + break; + case "setregioninfo": + if (m_scene.PermissionsMngr.CanEditEstateTerrain(remote_client.AgentId)) + estateSetRegionInfoHandler(packet); + break; + case "texturebase": + if (m_scene.PermissionsMngr.CanEditEstateTerrain(remote_client.AgentId)) + estateTextureBaseHandler(packet); + break; + case "texturedetail": + if (m_scene.PermissionsMngr.CanEditEstateTerrain(remote_client.AgentId)) + estateTextureDetailHandler(packet); + break; + case "textureheights": + if (m_scene.PermissionsMngr.CanEditEstateTerrain(remote_client.AgentId)) + estateTextureHeightsHandler(packet); + break; + case "texturecommit": + sendRegionHandshakeToAll(); + break; + case "setregionterrain": + if (m_scene.PermissionsMngr.CanEditEstateTerrain(remote_client.AgentId)) + estateSetRegionTerrainHandler(packet); + break; + case "restart": + if (m_scene.PermissionsMngr.CanRestartSim(remote_client.AgentId)) + { + estateRestartSim(packet); + } + break; + case "estatechangecovenantid": + if (m_scene.PermissionsMngr.CanEditEstateTerrain(remote_client.AgentId)) + { + EstateChangeCovenant(packet); + } + break; + case "estateaccessdelta": // Estate access delta manages the banlist and allow list too. + if (m_scene.PermissionsMngr.GenericEstatePermission(remote_client.AgentId)) + { + estateAccessDelta(remote_client, packet); + } + break; + case "simulatormessage": + if (m_scene.PermissionsMngr.GenericEstatePermission(remote_client.AgentId)) + { + SendSimulatorBlueBoxMessage(remote_client, packet); + } + break; + case "instantmessage": + if (m_scene.PermissionsMngr.GenericEstatePermission(remote_client.AgentId)) + { + SendEstateBlueBoxMessage(remote_client, packet); + } + break; + case "setregiondebug": + if (m_scene.PermissionsMngr.GenericEstatePermission(remote_client.AgentId)) + { + SetRegionDebug(remote_client, packet); + } + break; + default: + m_log.Error("EstateOwnerMessage: Unknown method requested\n" + packet.ToString()); + break; + } + } + + private void SetRegionDebug(IClientAPI remote_client, EstateOwnerMessagePacket packet) + { + LLUUID invoice = packet.MethodData.Invoice; + LLUUID SenderID = packet.AgentData.AgentID; + bool scripted = convertParamStringToBool(packet.ParamList[0].Parameter); + bool collisionEvents = convertParamStringToBool(packet.ParamList[1].Parameter); + bool physics = convertParamStringToBool(packet.ParamList[2].Parameter); + + if (physics) + { + m_scene.RegionInfo.EstateSettings.regionFlags |= Simulator.RegionFlags.SkipPhysics; + } + else + { + m_scene.RegionInfo.EstateSettings.regionFlags &= ~Simulator.RegionFlags.SkipPhysics; + } + + if (scripted) + { + m_scene.RegionInfo.EstateSettings.regionFlags |= Simulator.RegionFlags.SkipScripts; + } + else + { + m_scene.RegionInfo.EstateSettings.regionFlags &= ~Simulator.RegionFlags.SkipScripts; + } + + + m_scene.SetSceneCoreDebug(scripted, collisionEvents, physics); + } + + private void SendSimulatorBlueBoxMessage(IClientAPI remote_client, EstateOwnerMessagePacket packet) + { + LLUUID invoice = packet.MethodData.Invoice; + LLUUID SenderID = new LLUUID(Helpers.FieldToUTF8String(packet.ParamList[2].Parameter)); + string SenderName = Helpers.FieldToUTF8String(packet.ParamList[3].Parameter); + string Message = Helpers.FieldToUTF8String(packet.ParamList[4].Parameter); + m_scene.SendRegionMessageFromEstateTools(SenderID, packet.AgentData.SessionID, SenderName, Message); + + } + private void SendEstateBlueBoxMessage(IClientAPI remote_client, EstateOwnerMessagePacket packet) + { + LLUUID invoice = packet.MethodData.Invoice; + LLUUID SenderID = packet.AgentData.AgentID; + string SenderName = Helpers.FieldToUTF8String(packet.ParamList[0].Parameter); + string Message = Helpers.FieldToUTF8String(packet.ParamList[1].Parameter); + m_scene.SendEstateMessageFromEstateTools(SenderID, packet.AgentData.SessionID, SenderName, Message); + + } + private void sendDetailedEstateData(IClientAPI remote_client, EstateOwnerMessagePacket packet) + { + + LLUUID invoice = packet.MethodData.Invoice; + packet.AgentData.TransactionID = LLUUID.Random(); + packet.MethodData.Method = Helpers.StringToField("estateupdateinfo"); + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[9]; + + for (int i = 0; i < 9; i++) + { + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); + } + + //Sending Estate Settings + returnblock[0].Parameter = Helpers.StringToField(m_scene.RegionInfo.MasterAvatarFirstName + m_scene.RegionInfo.MasterAvatarLastName); + returnblock[1].Parameter = Helpers.StringToField(m_scene.RegionInfo.MasterAvatarAssignedUUID.ToString()); + returnblock[2].Parameter = Helpers.StringToField(m_scene.RegionInfo.EstateSettings.estateID.ToString()); + + // TODO: Resolve Magic numbers here + returnblock[3].Parameter = Helpers.StringToField("269516800"); + returnblock[4].Parameter = Helpers.StringToField("0"); + returnblock[5].Parameter = Helpers.StringToField("1"); + returnblock[6].Parameter = Helpers.StringToField(m_scene.RegionInfo.RegionID.ToString()); + returnblock[7].Parameter = Helpers.StringToField("1160895077"); + returnblock[8].Parameter = Helpers.StringToField("1"); + + packet.ParamList = returnblock; + //m_log.Info("[ESTATE]: SIM--->" + packet.ToString()); + remote_client.OutPacket(packet, ThrottleOutPacketType.Task); + + sendEstateManagerList(remote_client, packet); + + } + + private void sendEstateManagerList(IClientAPI remote_client, EstateOwnerMessagePacket packet) + { + LLUUID invoice = packet.MethodData.Invoice; + + //Sending Estate Managers + packet = new EstateOwnerMessagePacket(); + packet.AgentData.TransactionID = LLUUID.Random(); + packet.AgentData.AgentID = remote_client.AgentId; + packet.AgentData.SessionID = remote_client.SessionId; + packet.MethodData.Invoice = invoice; + packet.MethodData.Method = Helpers.StringToField("setaccess"); + + LLUUID[] EstateManagers = m_scene.RegionInfo.EstateSettings.estateManagers; + + EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + EstateManagers.Length]; + + for (int i = 0; i < (6 + EstateManagers.Length); i++) + { + returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); + } + int j = 0; + returnblock[j].Parameter = Helpers.StringToField(m_scene.RegionInfo.EstateSettings.estateID.ToString()); j++; + returnblock[j].Parameter = Helpers.StringToField(((int)EstateAccessCodex.EstateManagers).ToString()); j++; + returnblock[j].Parameter = Helpers.StringToField("0"); j++; + returnblock[j].Parameter = Helpers.StringToField("0"); j++; + returnblock[j].Parameter = Helpers.StringToField("0"); j++; + returnblock[j].Parameter = Helpers.StringToField(EstateManagers.Length.ToString()); j++; + for (int i = 0; i < EstateManagers.Length; i++) + { + returnblock[j].Parameter = EstateManagers[i].GetBytes(); j++; + } + packet.ParamList = returnblock; + //m_log.Info("[ESTATE]: SIM--->" + packet.ToString()); + remote_client.OutPacket(packet, ThrottleOutPacketType.Task); + } + + private void estateAccessDelta(IClientAPI remote_client, EstateOwnerMessagePacket packet) + { + // EstateAccessDelta handles Estate Managers, Sim Access, Sim Banlist, allowed Groups.. etc. + int estateAccessType = Convert.ToInt16(Helpers.FieldToUTF8String(packet.ParamList[1].Parameter)); + + switch (estateAccessType) + { + case 256: + + // This needs to be updated for SuperEstateOwnerUser.. a non existing user in the estatesettings.xml + // So make sure you really trust your region owners. because they can add other estate manaagers to your other estates + if (packet.AgentData.AgentID == m_scene.RegionInfo.MasterAvatarAssignedUUID || m_scene.PermissionsMngr.BypassPermissions) + { + m_scene.RegionInfo.EstateSettings.AddEstateManager(new LLUUID(Helpers.FieldToUTF8String(packet.ParamList[2].Parameter))); + sendEstateManagerList(remote_client, packet); + } + else + { + remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); + } + + break; + case 512: + // This needs to be updated for SuperEstateOwnerUser.. a non existing user in the estatesettings.xml + // So make sure you really trust your region owners. because they can add other estate manaagers to your other estates + if (packet.AgentData.AgentID == m_scene.RegionInfo.MasterAvatarAssignedUUID || m_scene.PermissionsMngr.BypassPermissions) + { + m_scene.RegionInfo.EstateSettings.RemoveEstateManager(new LLUUID(Helpers.FieldToUTF8String(packet.ParamList[2].Parameter))); + sendEstateManagerList(remote_client, packet); + } + else + { + remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); + } + break; + + default: + + m_log.Error("EstateOwnerMessage: Unknown EstateAccessType requested in estateAccessDelta\n" + packet.ToString()); + break; + } + //m_log.Error("EstateOwnerMessage: estateAccessDelta\n" + packet.ToString()); + + + } + private void estateSetRegionInfoHandler(EstateOwnerMessagePacket packet) + { + if (packet.ParamList.Length != 9) + { + m_log.Error("EstateOwnerMessage: SetRegionInfo method has a ParamList of invalid length"); + } + else + { + m_regInfo.EstateSettings.regionFlags = Simulator.RegionFlags.None; + + if (convertParamStringToBool(packet.ParamList[0].Parameter)) + { + m_regInfo.EstateSettings.regionFlags = m_regInfo.EstateSettings.regionFlags | + Simulator.RegionFlags.BlockTerraform; + } + + if (convertParamStringToBool(packet.ParamList[1].Parameter)) + { + m_regInfo.EstateSettings.regionFlags = m_regInfo.EstateSettings.regionFlags | + Simulator.RegionFlags.NoFly; + } + + if (convertParamStringToBool(packet.ParamList[2].Parameter)) + { + m_regInfo.EstateSettings.regionFlags = m_regInfo.EstateSettings.regionFlags | + Simulator.RegionFlags.AllowDamage; + } + + if (convertParamStringToBool(packet.ParamList[3].Parameter) == false) + { + m_regInfo.EstateSettings.regionFlags = m_regInfo.EstateSettings.regionFlags | + Simulator.RegionFlags.BlockLandResell; + } + + + int tempMaxAgents = + Convert.ToInt16(Convert.ToDecimal(Helpers.FieldToUTF8String(packet.ParamList[4].Parameter))); + m_regInfo.EstateSettings.maxAgents = (byte) tempMaxAgents; + + float tempObjectBonusFactor = + (float) Convert.ToDecimal(Helpers.FieldToUTF8String(packet.ParamList[5].Parameter)); + m_regInfo.EstateSettings.objectBonusFactor = tempObjectBonusFactor; + + int tempMatureLevel = Convert.ToInt16(Helpers.FieldToUTF8String(packet.ParamList[6].Parameter)); + m_regInfo.EstateSettings.simAccess = (Simulator.SimAccess) tempMatureLevel; + + + if (convertParamStringToBool(packet.ParamList[7].Parameter)) + { + m_regInfo.EstateSettings.regionFlags = m_regInfo.EstateSettings.regionFlags | + Simulator.RegionFlags.RestrictPushObject; + } + + if (convertParamStringToBool(packet.ParamList[8].Parameter)) + { + m_regInfo.EstateSettings.regionFlags = m_regInfo.EstateSettings.regionFlags | + Simulator.RegionFlags.AllowParcelChanges; + } + + sendRegionInfoPacketToAll(); + } + } + + private void estateSetRegionTerrainHandler(EstateOwnerMessagePacket packet) + { + if (packet.ParamList.Length != 9) + { + m_log.Error("EstateOwnerMessage: SetRegionTerrain method has a ParamList of invalid length"); + } + else + { + try + { + string tmp; + tmp = Helpers.FieldToUTF8String(packet.ParamList[0].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float WaterHeight = (float)Convert.ToDecimal(tmp); + tmp = Helpers.FieldToUTF8String(packet.ParamList[1].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float TerrainRaiseLimit = (float)Convert.ToDecimal(tmp); + tmp = Helpers.FieldToUTF8String(packet.ParamList[2].Parameter); + if (!tmp.Contains(".")) tmp += ".00"; + float TerrainLowerLimit = (float)Convert.ToDecimal(tmp); + bool UseFixedSun = convertParamStringToBool(packet.ParamList[4].Parameter); + float SunHour = (float)Convert.ToDecimal(Helpers.FieldToUTF8String(packet.ParamList[5].Parameter)); + + setRegionSettings(WaterHeight, TerrainRaiseLimit, TerrainLowerLimit, UseFixedSun, SunHour); + + sendRegionInfoPacketToAll(); + } + catch (Exception ex) + { + m_log.Error("EstateManager: Exception while setting terrain settings: \n" + packet.ToString() + "\n" + ex.ToString()); + } + } + } + + private void estateTextureHeightsHandler(EstateOwnerMessagePacket packet) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in packet.ParamList) + { + string s = Helpers.FieldToUTF8String(block.Parameter); + string[] splitField = s.Split(' '); + if (splitField.Length == 3) + { + Int16 corner = Convert.ToInt16(splitField[0]); + float lowValue = (float) Convert.ToDecimal(splitField[1]); + float highValue = (float) Convert.ToDecimal(splitField[2]); + + setEstateTextureRange(corner, lowValue, highValue); + } + } + } + + private void estateTextureDetailHandler(EstateOwnerMessagePacket packet) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in packet.ParamList) + { + string s = Helpers.FieldToUTF8String(block.Parameter); + string[] splitField = s.Split(' '); + if (splitField.Length == 2) + { + Int16 corner = Convert.ToInt16(splitField[0]); + LLUUID textureUUID = new LLUUID(splitField[1]); + + setTerrainTexture(corner, textureUUID); + } + } + } + + private void estateTextureBaseHandler(EstateOwnerMessagePacket packet) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in packet.ParamList) + { + string s = Helpers.FieldToUTF8String(block.Parameter); + string[] splitField = s.Split(' '); + if (splitField.Length == 2) + { + LLUUID tempUUID = new LLUUID(splitField[1]); + switch (Convert.ToInt16(splitField[0])) + { + case 0: + m_regInfo.EstateSettings.terrainBase0 = tempUUID; + break; + case 1: + m_regInfo.EstateSettings.terrainBase1 = tempUUID; + break; + case 2: + m_regInfo.EstateSettings.terrainBase2 = tempUUID; + break; + case 3: + m_regInfo.EstateSettings.terrainBase3 = tempUUID; + break; + } + } + } + } + + private void estateRestartSim(EstateOwnerMessagePacket packet) + { + // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart. + foreach (EstateOwnerMessagePacket.ParamListBlock block in packet.ParamList) + { + float timeSeconds = 0; + Helpers.TryParse(Helpers.FieldToUTF8String(block.Parameter), out timeSeconds); + timeSeconds = (int)timeSeconds; + m_scene.Restart(timeSeconds); + + } + } + + private void EstateChangeCovenant(EstateOwnerMessagePacket packet) + { + foreach (EstateOwnerMessagePacket.ParamListBlock block in packet.ParamList) + { + LLUUID newCovenantID = new LLUUID(Helpers.FieldToUTF8String(block.Parameter)); + m_regInfo.CovenantID = newCovenantID; + m_scene.RegionInfo.SaveEstatecovenantUUID(newCovenantID); + } + } + + public void HandleRegionInfoRequest(IClientAPI client, LLUUID sessionID) + { + RegionInfoPacket rinfopack = new RegionInfoPacket(); + RegionInfoPacket.RegionInfoBlock rinfoblk = new RegionInfoPacket.RegionInfoBlock(); + + rinfoblk.BillableFactor = 0; + rinfoblk.EstateID = 02; + rinfoblk.MaxAgents = 100; + rinfoblk.ObjectBonusFactor = 1.0f; + rinfoblk.ParentEstateID = 0; + rinfoblk.PricePerMeter = 0; + rinfoblk.RedirectGridX = 0; + rinfoblk.RedirectGridY = 0; + rinfoblk.RegionFlags = (uint) m_regInfo.EstateSettings.regionFlags; + rinfoblk.SimAccess = (byte) m_regInfo.EstateSettings.simAccess; + rinfoblk.SunHour = m_regInfo.EstateSettings.sunHour; + rinfoblk.TerrainLowerLimit = 20; + rinfoblk.TerrainRaiseLimit = 20; + rinfoblk.UseEstateSun = true; + rinfoblk.WaterHeight = m_regInfo.EstateSettings.waterHeight; + rinfoblk.SimName = Helpers.StringToField(m_regInfo.RegionName); + + rinfopack.RegionInfo = rinfoblk; + + client.OutPacket(rinfopack, ThrottleOutPacketType.Task); + } + + public void HandleEstateCovenantRequest(IClientAPI client, LLUUID sessionID) + { + EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); + EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); + edata.CovenantID = m_regInfo.CovenantID; + edata.CovenantTimestamp = 0; + edata.EstateOwnerID = m_regInfo.MasterAvatarAssignedUUID; + edata.EstateName = + Helpers.StringToField(m_regInfo.MasterAvatarFirstName + " " + m_regInfo.MasterAvatarLastName); + einfopack.Data = edata; + client.OutPacket(einfopack, ThrottleOutPacketType.Task); + } + + #endregion + + #region Outgoing Packets + + public void sendRegionInfoPacketToAll() + { + List avatars = m_scene.GetAvatars(); + + for (int i = 0; i < avatars.Count; i++) + { + sendRegionInfoPacket(avatars[i].ControllingClient); + } + } + + public void sendRegionHandshakeToAll() + { + m_scene.Broadcast( + sendRegionHandshake + ); + } + + public void sendRegionInfoPacket(IClientAPI remote_client) + { + Encoding _enc = Encoding.ASCII; + + AgentCircuitData circuitData = remote_client.RequestClientInfo(); + + RegionInfoPacket regionInfoPacket = new RegionInfoPacket(); + regionInfoPacket.AgentData.AgentID = circuitData.AgentID; + regionInfoPacket.AgentData.SessionID = circuitData.SessionID; + regionInfoPacket.RegionInfo.BillableFactor = m_regInfo.EstateSettings.billableFactor; + regionInfoPacket.RegionInfo.EstateID = m_regInfo.EstateSettings.estateID; + regionInfoPacket.RegionInfo.MaxAgents = m_regInfo.EstateSettings.maxAgents; + regionInfoPacket.RegionInfo.ObjectBonusFactor = m_regInfo.EstateSettings.objectBonusFactor; + regionInfoPacket.RegionInfo.ParentEstateID = m_regInfo.EstateSettings.parentEstateID; + regionInfoPacket.RegionInfo.PricePerMeter = m_regInfo.EstateSettings.pricePerMeter; + regionInfoPacket.RegionInfo.RedirectGridX = m_regInfo.EstateSettings.redirectGridX; + regionInfoPacket.RegionInfo.RedirectGridY = m_regInfo.EstateSettings.redirectGridY; + regionInfoPacket.RegionInfo.RegionFlags = (uint) m_regInfo.EstateSettings.regionFlags; + regionInfoPacket.RegionInfo.SimAccess = (byte) m_regInfo.EstateSettings.simAccess; + regionInfoPacket.RegionInfo.SimName = _enc.GetBytes(m_regInfo.RegionName); + regionInfoPacket.RegionInfo.SunHour = m_regInfo.EstateSettings.sunHour; + regionInfoPacket.RegionInfo.TerrainLowerLimit = m_regInfo.EstateSettings.terrainLowerLimit; + regionInfoPacket.RegionInfo.TerrainRaiseLimit = m_regInfo.EstateSettings.terrainRaiseLimit; + regionInfoPacket.RegionInfo.UseEstateSun = !m_regInfo.EstateSettings.useFixedSun; + regionInfoPacket.RegionInfo.WaterHeight = m_regInfo.EstateSettings.waterHeight; + + remote_client.OutPacket(regionInfoPacket, ThrottleOutPacketType.Task); + } + + public void sendRegionHandshake(IClientAPI remoteClient) + { + remoteClient.SendRegionHandshake(m_regInfo); + } + + #endregion + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/InstantMessageReceiver.cs b/trunk/OpenSim/Region/Environment/InstantMessageReceiver.cs new file mode 100644 index 0000000000..5bf6779736 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/InstantMessageReceiver.cs @@ -0,0 +1,56 @@ +/* +* 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; + +namespace OpenSim.Region.Environment +{ + /// + /// Bit Vector for Which Modules to send an instant message to from the Scene or an Associated Module + /// + + // This prevents the Modules from sending Instant messages to other modules through the scene + // and then receiving the same messages + + // This is mostly here because on LLSL and the SecondLife Client, IMs,Groups and friends are linked + // inseparably + + [Flags] + public enum InstantMessageReceiver : uint + { + /// None of them.. here for posterity and amusement + None = 0, + /// The IM Module + IMModule = 0x00000001, + /// The Friends Module + FriendsModule = 0x00000002, + /// The Groups Module + GroupsModule = 0x00000004 + + } +} diff --git a/trunk/OpenSim/Region/Environment/Interfaces/IAgentAssetTransactions.cs b/trunk/OpenSim/Region/Environment/Interfaces/IAgentAssetTransactions.cs new file mode 100644 index 0000000000..a764a88082 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Interfaces/IAgentAssetTransactions.cs @@ -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. +* +*/ + +using libsecondlife; +using OpenSim.Framework; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface IAgentAssetTransactions + { + void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID, + InventoryItemBase item); + + void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask); + + void RemoveAgentAssetTransactions(LLUUID userID); + } +} diff --git a/trunk/OpenSim/Region/Environment/Interfaces/IAvatarFactory.cs b/trunk/OpenSim/Region/Environment/Interfaces/IAvatarFactory.cs new file mode 100644 index 0000000000..1ed3418bef --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Interfaces/IAvatarFactory.cs @@ -0,0 +1,40 @@ +/* +* 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 libsecondlife; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface IAvatarFactory : IRegionModule + { + bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance); + void UpdateDatabase(LLUUID userID, AvatarAppearance avatAppearance); + + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Interfaces/IDynamicTextureManager.cs b/trunk/OpenSim/Region/Environment/Interfaces/IDynamicTextureManager.cs new file mode 100644 index 0000000000..daecf86f07 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Interfaces/IDynamicTextureManager.cs @@ -0,0 +1,56 @@ +/* +* 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.IO; +using libsecondlife; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface IDynamicTextureManager + { + void RegisterRender(string handleType, IDynamicTextureRender render); + void ReturnData(LLUUID id, byte[] data); + + LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url, string extraParams, + int updateTimer); + + LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data, string extraParams, + int updateTimer); + } + + public interface IDynamicTextureRender + { + string GetName(); + string GetContentType(); + bool SupportsAsynchronous(); + byte[] ConvertUrl(string url, string extraParams); + byte[] ConvertStream(Stream data, string extraParams); + bool AsyncConvertUrl(LLUUID id, string url, string extraParams); + bool AsyncConvertData(LLUUID id, string bodyData, string extraParams); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Interfaces/IHttpRequests.cs b/trunk/OpenSim/Region/Environment/Interfaces/IHttpRequests.cs new file mode 100644 index 0000000000..6aa8f357e7 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Interfaces/IHttpRequests.cs @@ -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 System.Collections.Generic; +using libsecondlife; +using OpenSim.Region.Environment.Modules; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface IHttpRequests + { + LLUUID MakeHttpRequest(string url, string parameters, string body); + LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List parameters, string body); + void StopHttpRequest(uint m_localID, LLUUID m_itemID); + HttpRequestClass GetNextCompletedRequest(); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Interfaces/IRegionDataStore.cs b/trunk/OpenSim/Region/Environment/Interfaces/IRegionDataStore.cs new file mode 100644 index 0000000000..d0b5680a53 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Interfaces/IRegionDataStore.cs @@ -0,0 +1,79 @@ +/* +* 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.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.LandManagement; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface IRegionDataStore + { + /// + /// Initialises the data storage engine + /// + /// The file to save the database to (may not be applicable). Alternatively, + /// a connection string for the database + /// Temporary switch while this option is immature + void Initialise(string filename, bool persistPrimInventories); + + /// + /// Stores all object's details apart from inventory + /// + /// + /// + void StoreObject(SceneObjectGroup obj, LLUUID regionUUID); + + /// + /// Entirely removes the object, including inventory + /// + /// + /// + /// + void RemoveObject(LLUUID uuid, LLUUID regionUUID); + + /// + /// Store a prim's inventory + /// + /// + void StorePrimInventory(LLUUID primID, ICollection items); + + List LoadObjects(LLUUID regionUUID); + + void StoreTerrain(double[,] terrain, LLUUID regionID); + double[,] LoadTerrain(LLUUID regionID); + + void StoreLandObject(Land Parcel, LLUUID regionUUID); + void RemoveLandObject(LLUUID globalID); + List LoadLandObjects(LLUUID regionUUID); + + void Shutdown(); + } +} diff --git a/trunk/OpenSim/Region/Environment/Interfaces/IRegionModule.cs b/trunk/OpenSim/Region/Environment/Interfaces/IRegionModule.cs new file mode 100644 index 0000000000..e5d0b264e0 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Interfaces/IRegionModule.cs @@ -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 Nini.Config; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface IRegionModule + { + void Initialise(Scene scene, IConfigSource source); + void PostInitialise(); + void Close(); + string Name { get; } + bool IsSharedModule { get; } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Interfaces/ISimChat.cs b/trunk/OpenSim/Region/Environment/Interfaces/ISimChat.cs new file mode 100644 index 0000000000..fb491cc09a --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Interfaces/ISimChat.cs @@ -0,0 +1,38 @@ +/* +* 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; +using OpenSim.Framework; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface ISimChat + { + void SimChat(Object sender, ChatFromViewerArgs e); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Interfaces/ITerrain.cs b/trunk/OpenSim/Region/Environment/Interfaces/ITerrain.cs new file mode 100644 index 0000000000..9171d09074 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Interfaces/ITerrain.cs @@ -0,0 +1,74 @@ +/* +* 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 OpenSim.Framework; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface ITerrain + { + bool Tainted(); + bool Tainted(int x, int y); + void ResetTaint(); + + void ModifyTerrain(float height, float seconds, byte brushsize, byte action, float north, float west, + IClientAPI remoteUser); + + void CheckHeightValues(); + float[] GetHeights1D(); + float[,] GetHeights2D(); + double[,] GetHeights2DD(); + void GetHeights1D(float[] heights); + void SetHeights2D(float[,] heights); + void SetHeights2D(double[,] heights); + void SwapRevertMaps(); + void SaveRevertMap(); + bool RunTerrainCmd(string[] args, ref string resultText, string simName); + void SetRange(float min, float max); + void LoadFromFileF64(string filename); + void LoadFromFileF32(string filename); + void LoadFromFileF32(string filename, int dimensionX, int dimensionY, int lowerboundX, int lowerboundY); + void LoadFromFileIMG(string filename, int dimensionX, int dimensionY, int lowerboundX, int lowerboundY); + void LoadFromFileSLRAW(string filename); + void WriteToFileF64(string filename); + void WriteToFileF32(string filename); + void WriteToFileRAW(string filename); + void WriteToFileHiRAW(string filename); + void SetSeed(int val); + void RaiseTerrain(double rx, double ry, double size, double amount); + void LowerTerrain(double rx, double ry, double size, double amount); + void FlattenTerrain(double rx, double ry, double size, double amount); + void NoiseTerrain(double rx, double ry, double size, double amount); + void RevertTerrain(double rx, double ry, double size, double amount); + void SmoothTerrain(double rx, double ry, double size, double amount); + void HillsGenerator(); + double GetHeight(int x, int y); + void ExportImage(string filename, string gradientmap); + byte[] ExportJpegImage(string gradientmap); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Interfaces/ITerrainChannel.cs b/trunk/OpenSim/Region/Environment/Interfaces/ITerrainChannel.cs new file mode 100644 index 0000000000..cc0226853b --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Interfaces/ITerrainChannel.cs @@ -0,0 +1,38 @@ +/* +* 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; +namespace OpenSim.Region.Environment.Interfaces +{ + public interface ITerrainChannel + { + int Height { get; } + double this[int x, int y] { get; set; } + int Width { get; } + } +} diff --git a/trunk/OpenSim/Region/Environment/Interfaces/IWorldComm.cs b/trunk/OpenSim/Region/Environment/Interfaces/IWorldComm.cs new file mode 100644 index 0000000000..7567bb2e06 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Interfaces/IWorldComm.cs @@ -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. +* +*/ + +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Modules; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface IWorldComm + { + int Listen(uint LocalID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg); + void DeliverMessage(string sourceItemID, ChatTypeEnum type, int channel, string name, string msg); + bool HasMessages(); + ListenerInfo GetNextMessage(); + void ListenControl(int handle, int active); + void ListenRemove(int handle); + void DeleteListener(LLUUID itemID); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Interfaces/IXMLRPC.cs b/trunk/OpenSim/Region/Environment/Interfaces/IXMLRPC.cs new file mode 100644 index 0000000000..82b692d40f --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Interfaces/IXMLRPC.cs @@ -0,0 +1,44 @@ +/* +* 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 libsecondlife; +using OpenSim.Region.Environment.Modules; + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface IXMLRPC + { + LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID); + void CloseXMLRPCChannel(LLUUID channelKey); + bool hasRequests(); + RPCRequestInfo GetNextRequest(); + void RemoteDataReply(string channel, string message_id, string sdata, int idata); + bool IsEnabled(); + void DeleteChannel(LLUUID itemID); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Interfaces/IXfer.cs b/trunk/OpenSim/Region/Environment/Interfaces/IXfer.cs new file mode 100644 index 0000000000..5e5ff1b37d --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Interfaces/IXfer.cs @@ -0,0 +1,35 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.Environment.Interfaces +{ + public interface IXfer + { + bool AddNewFile(string fileName, byte[] data); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/LandManagement/Land.cs b/trunk/OpenSim/Region/Environment/LandManagement/Land.cs new file mode 100644 index 0000000000..fec889909c --- /dev/null +++ b/trunk/OpenSim/Region/Environment/LandManagement/Land.cs @@ -0,0 +1,819 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.Environment.Interfaces; + +namespace OpenSim.Region.Environment.LandManagement +{ + + #region Parcel Class + + /// + /// Keeps track of a specific piece of land's information + /// + public class Land + { + #region Member Variables + + public LandData landData = new LandData(); + public List primsOverMe = new List(); + public Scene m_scene; + + private bool[,] landBitmap = new bool[64,64]; + + #endregion + + #region Constructors + + public Land(LLUUID owner_id, bool is_group_owned, Scene scene) + { + m_scene = scene; + landData.ownerID = owner_id; + landData.isGroupOwned = is_group_owned; + } + + #endregion + + #region Member Functions + + #region General Functions + + /// + /// Checks to see if this land object contains a point + /// + /// + /// + /// Returns true if the piece of land contains the specified point + public bool containsPoint(int x, int y) + { + if (x >= 0 && y >= 0 && x <= Constants.RegionSize && x <= Constants.RegionSize) + { + return (landBitmap[x/4, y/4] == true); + } + else + { + return false; + } + } + + public Land Copy() + { + Land newLand = new Land(landData.ownerID, landData.isGroupOwned, m_scene); + + //Place all new variables here! + newLand.landBitmap = (bool[,]) (landBitmap.Clone()); + newLand.landData = landData.Copy(); + + return newLand; + } + + #endregion + + #region Packet Request Handling + + /// + /// Sends land properties as requested + /// + /// ID sent by client for them to keep track of + /// Bool sent by client for them to use + /// Object representing the client + public void sendLandProperties(int sequence_id, bool snap_selection, int request_result, + IClientAPI remote_client) + { + ParcelPropertiesPacket updatePacket = (ParcelPropertiesPacket) PacketPool.Instance.GetPacket(PacketType.ParcelProperties); + // TODO: don't create new blocks if recycling an old packet + + updatePacket.ParcelData.AABBMax = landData.AABBMax; + updatePacket.ParcelData.AABBMin = landData.AABBMin; + updatePacket.ParcelData.Area = landData.area; + updatePacket.ParcelData.AuctionID = landData.auctionID; + updatePacket.ParcelData.AuthBuyerID = landData.authBuyerID; //unemplemented + + updatePacket.ParcelData.Bitmap = landData.landBitmapByteArray; + + updatePacket.ParcelData.Desc = Helpers.StringToField(landData.landDesc); + updatePacket.ParcelData.Category = (byte) landData.category; + updatePacket.ParcelData.ClaimDate = landData.claimDate; + updatePacket.ParcelData.ClaimPrice = landData.claimPrice; + updatePacket.ParcelData.GroupID = landData.groupID; + updatePacket.ParcelData.GroupPrims = landData.groupPrims; + updatePacket.ParcelData.IsGroupOwned = landData.isGroupOwned; + updatePacket.ParcelData.LandingType = (byte) landData.landingType; + updatePacket.ParcelData.LocalID = landData.localID; + if (landData.area > 0) + { + updatePacket.ParcelData.MaxPrims = + Convert.ToInt32( + Math.Round((Convert.ToDecimal(landData.area)/Convert.ToDecimal(65536))*15000* + Convert.ToDecimal(m_scene.RegionInfo.EstateSettings.objectBonusFactor))); + } + else + { + updatePacket.ParcelData.MaxPrims = 0; + } + updatePacket.ParcelData.MediaAutoScale = landData.mediaAutoScale; + updatePacket.ParcelData.MediaID = landData.mediaID; + updatePacket.ParcelData.MediaURL = Helpers.StringToField(landData.mediaURL); + updatePacket.ParcelData.MusicURL = Helpers.StringToField(landData.musicURL); + updatePacket.ParcelData.Name = Helpers.StringToField(landData.landName); + updatePacket.ParcelData.OtherCleanTime = 0; //unemplemented + updatePacket.ParcelData.OtherCount = 0; //unemplemented + updatePacket.ParcelData.OtherPrims = landData.otherPrims; + updatePacket.ParcelData.OwnerID = landData.ownerID; + updatePacket.ParcelData.OwnerPrims = landData.ownerPrims; + updatePacket.ParcelData.ParcelFlags = landData.landFlags; + updatePacket.ParcelData.ParcelPrimBonus = m_scene.RegionInfo.EstateSettings.objectBonusFactor; + updatePacket.ParcelData.PassHours = landData.passHours; + updatePacket.ParcelData.PassPrice = landData.passPrice; + updatePacket.ParcelData.PublicCount = 0; //unemplemented + + uint regionFlags = (uint) m_scene.RegionInfo.EstateSettings.regionFlags; + updatePacket.ParcelData.RegionDenyAnonymous = ((regionFlags & (uint) Simulator.RegionFlags.DenyAnonymous) > + 0); + updatePacket.ParcelData.RegionDenyIdentified = ((regionFlags & (uint) Simulator.RegionFlags.DenyIdentified) > + 0); + updatePacket.ParcelData.RegionDenyTransacted = ((regionFlags & (uint) Simulator.RegionFlags.DenyTransacted) > + 0); + updatePacket.ParcelData.RegionPushOverride = ((regionFlags & (uint) Simulator.RegionFlags.RestrictPushObject) > + 0); + + updatePacket.ParcelData.RentPrice = 0; + updatePacket.ParcelData.RequestResult = request_result; + updatePacket.ParcelData.SalePrice = landData.salePrice; + updatePacket.ParcelData.SelectedPrims = landData.selectedPrims; + updatePacket.ParcelData.SelfCount = 0; //unemplemented + updatePacket.ParcelData.SequenceID = sequence_id; + if (landData.simwideArea > 0) + { + updatePacket.ParcelData.SimWideMaxPrims = + Convert.ToInt32( + Math.Round((Convert.ToDecimal(landData.simwideArea)/Convert.ToDecimal(65536))*15000* + Convert.ToDecimal(m_scene.RegionInfo.EstateSettings.objectBonusFactor))); + } + else + { + updatePacket.ParcelData.SimWideMaxPrims = 0; + } + updatePacket.ParcelData.SimWideTotalPrims = landData.simwidePrims; + updatePacket.ParcelData.SnapSelection = snap_selection; + updatePacket.ParcelData.SnapshotID = landData.snapshotID; + updatePacket.ParcelData.Status = (byte) landData.landStatus; + updatePacket.ParcelData.TotalPrims = landData.ownerPrims + landData.groupPrims + landData.otherPrims + + landData.selectedPrims; + updatePacket.ParcelData.UserLocation = landData.userLocation; + updatePacket.ParcelData.UserLookAt = landData.userLookAt; + remote_client.OutPacket((Packet) updatePacket, ThrottleOutPacketType.Task); + } + + public void updateLandProperties(ParcelPropertiesUpdatePacket packet, IClientAPI remote_client) + { + if (remote_client.AgentId == landData.ownerID) + { + //Needs later group support + LandData newData = landData.Copy(); + newData.authBuyerID = packet.ParcelData.AuthBuyerID; + newData.category = (Parcel.ParcelCategory) packet.ParcelData.Category; + newData.landDesc = Helpers.FieldToUTF8String(packet.ParcelData.Desc); + newData.groupID = packet.ParcelData.GroupID; + newData.landingType = packet.ParcelData.LandingType; + newData.mediaAutoScale = packet.ParcelData.MediaAutoScale; + newData.mediaID = packet.ParcelData.MediaID; + newData.mediaURL = Helpers.FieldToUTF8String(packet.ParcelData.MediaURL); + newData.musicURL = Helpers.FieldToUTF8String(packet.ParcelData.MusicURL); + newData.landName = Helpers.FieldToUTF8String(packet.ParcelData.Name); + newData.landFlags = packet.ParcelData.ParcelFlags; + newData.passHours = packet.ParcelData.PassHours; + newData.passPrice = packet.ParcelData.PassPrice; + newData.salePrice = packet.ParcelData.SalePrice; + newData.snapshotID = packet.ParcelData.SnapshotID; + newData.userLocation = packet.ParcelData.UserLocation; + newData.userLookAt = packet.ParcelData.UserLookAt; + + m_scene.LandManager.updateLandObject(landData.localID, newData); + + sendLandUpdateToAvatarsOverMe(); + } + } + + public bool isEitherBannedOrRestricted(LLUUID avatar) + { + if (isBannedFromLand(avatar)) + { + return true; + } + else if (isRestrictedFromLand(avatar)) + { + return true; + } + return false; + } + + public bool isBannedFromLand(LLUUID avatar) + { + if ((landData.landFlags & (uint) Parcel.ParcelFlags.UseBanList) > 0) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = avatar; + entry.Flags = ParcelManager.AccessList.Ban; + entry.Time = new DateTime(); + if (landData.parcelAccessList.Contains(entry)) + { + //They are banned, so lets send them a notice about this parcel + return true; + } + } + return false; + } + + public bool isRestrictedFromLand(LLUUID avatar) + { + if ((landData.landFlags & (uint) Parcel.ParcelFlags.UseAccessList) > 0) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = avatar; + entry.Flags = ParcelManager.AccessList.Access; + entry.Time = new DateTime(); + if (!landData.parcelAccessList.Contains(entry)) + { + //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel + return true; + } + } + return false; + } + + public void sendLandUpdateToClient(IClientAPI remote_client) + { + sendLandProperties(0, false, 0, remote_client); + } + + public void sendLandUpdateToAvatarsOverMe() + { + List avatars = m_scene.GetAvatars(); + for (int i = 0; i < avatars.Count; i++) + { + Land over = + m_scene.LandManager.getLandObject((int) Math.Round(avatars[i].AbsolutePosition.X), + (int) Math.Round(avatars[i].AbsolutePosition.Y)); + if (over != null) + { + if (over.landData.localID == landData.localID) + { + sendLandUpdateToClient(avatars[i].ControllingClient); + } + } + } + } + + #endregion + + #region AccessList Functions + + public ParcelAccessListReplyPacket.ListBlock[] createAccessListArrayByFlag(ParcelManager.AccessList flag) + { + List list = new List(); + foreach (ParcelManager.ParcelAccessEntry entry in landData.parcelAccessList) + { + if (entry.Flags == flag) + { + ParcelAccessListReplyPacket.ListBlock listBlock = new ParcelAccessListReplyPacket.ListBlock(); + + listBlock.Flags = (uint) 0; + listBlock.ID = entry.AgentID; + listBlock.Time = 0; + + list.Add(listBlock); + } + } + + if (list.Count == 0) + { + ParcelAccessListReplyPacket.ListBlock listBlock = new ParcelAccessListReplyPacket.ListBlock(); + + listBlock.Flags = (uint) 0; + listBlock.ID = LLUUID.Zero; + listBlock.Time = 0; + + list.Add(listBlock); + } + return list.ToArray(); + } + + public void sendAccessList(LLUUID agentID, LLUUID sessionID, uint flags, int sequenceID, + IClientAPI remote_client) + { + ParcelAccessListReplyPacket replyPacket; + + if (flags == (uint) ParcelManager.AccessList.Access || flags == (uint) ParcelManager.AccessList.Both) + { + replyPacket = (ParcelAccessListReplyPacket) PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply); + replyPacket.Data.AgentID = agentID; + replyPacket.Data.Flags = (uint) ParcelManager.AccessList.Access; + replyPacket.Data.LocalID = landData.localID; + replyPacket.Data.SequenceID = 0; + + replyPacket.List = createAccessListArrayByFlag(ParcelManager.AccessList.Access); + remote_client.OutPacket((Packet) replyPacket, ThrottleOutPacketType.Task); + } + + if (flags == (uint) ParcelManager.AccessList.Ban || flags == (uint) ParcelManager.AccessList.Both) + { + replyPacket = (ParcelAccessListReplyPacket) PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply); + replyPacket.Data.AgentID = agentID; + replyPacket.Data.Flags = (uint) ParcelManager.AccessList.Ban; + replyPacket.Data.LocalID = landData.localID; + replyPacket.Data.SequenceID = 0; + + replyPacket.List = createAccessListArrayByFlag(ParcelManager.AccessList.Ban); + remote_client.OutPacket((Packet) replyPacket, ThrottleOutPacketType.Task); + } + } + + public void updateAccessList(uint flags, List entries, IClientAPI remote_client) + { + LandData newData = landData.Copy(); + + if (entries.Count == 1 && entries[0].AgentID == LLUUID.Zero) + { + entries.Clear(); + } + + List toRemove = new List(); + foreach (ParcelManager.ParcelAccessEntry entry in newData.parcelAccessList) + { + if (entry.Flags == (ParcelManager.AccessList) flags) + { + toRemove.Add(entry); + } + } + + foreach (ParcelManager.ParcelAccessEntry entry in toRemove) + { + newData.parcelAccessList.Remove(entry); + } + foreach (ParcelManager.ParcelAccessEntry entry in entries) + { + ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry(); + temp.AgentID = entry.AgentID; + temp.Time = new DateTime(); //Pointless? Yes. + temp.Flags = (ParcelManager.AccessList) flags; + + if (!newData.parcelAccessList.Contains(temp)) + { + newData.parcelAccessList.Add(temp); + } + } + + m_scene.LandManager.updateLandObject(landData.localID, newData); + } + + #endregion + + #region Update Functions + + /// + /// Updates the AABBMin and AABBMax values after area/shape modification of the land object + /// + private void updateAABBAndAreaValues() + { + int min_x = 64; + int min_y = 64; + int max_x = 0; + int max_y = 0; + int tempArea = 0; + int x, y; + for (x = 0; x < 64; x++) + { + for (y = 0; y < 64; y++) + { + if (landBitmap[x, y] == true) + { + if (min_x > x) min_x = x; + if (min_y > y) min_y = y; + if (max_x < x) max_x = x; + if (max_y < y) max_y = y; + tempArea += 16; //16sqm peice of land + } + } + } + landData.AABBMin = + new LLVector3((float) (min_x*4), (float) (min_y*4), + (float) m_scene.Terrain.GetHeight((min_x*4), (min_y*4))); + landData.AABBMax = + new LLVector3((float) (max_x*4), (float) (max_y*4), + (float) m_scene.Terrain.GetHeight((max_x*4), (max_y*4))); + landData.area = tempArea; + } + + public void updateLandBitmapByteArray() + { + landData.landBitmapByteArray = convertLandBitmapToBytes(); + } + + /// + /// Update all settings in land such as area, bitmap byte array, etc + /// + public void forceUpdateLandInfo() + { + updateAABBAndAreaValues(); + updateLandBitmapByteArray(); + } + + public void setLandBitmapFromByteArray() + { + landBitmap = convertBytesToLandBitmap(); + } + + #endregion + + #region Land Bitmap Functions + + /// + /// Sets the land's bitmap manually + /// + /// 64x64 block representing where this land is on a map + public void setLandBitmap(bool[,] bitmap) + { + if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + //throw new Exception("Error: Invalid Parcel Bitmap"); + } + else + { + //Valid: Lets set it + landBitmap = bitmap; + forceUpdateLandInfo(); + } + } + + /// + /// Gets the land's bitmap manually + /// + /// + public bool[,] getLandBitmap() + { + return landBitmap; + } + + /// + /// Converts the land bitmap to a packet friendly byte array + /// + /// + private byte[] convertLandBitmapToBytes() + { + byte[] tempConvertArr = new byte[512]; + byte tempByte = 0; + int x, y, i, byteNum = 0; + i = 0; + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + tempByte = Convert.ToByte(tempByte | Convert.ToByte(landBitmap[x, y]) << (i++%8)); + if (i%8 == 0) + { + tempConvertArr[byteNum] = tempByte; + tempByte = (byte) 0; + i = 0; + byteNum++; + } + } + } + return tempConvertArr; + } + + private bool[,] convertBytesToLandBitmap() + { + bool[,] tempConvertMap = new bool[64,64]; + tempConvertMap.Initialize(); + byte tempByte = 0; + int x = 0, y = 0, i = 0, bitNum = 0; + for (i = 0; i < 512; i++) + { + tempByte = landData.landBitmapByteArray[i]; + for (bitNum = 0; bitNum < 8; bitNum++) + { + bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1); + tempConvertMap[x, y] = bit; + x++; + if (x > 63) + { + x = 0; + y++; + } + } + } + return tempConvertMap; + } + + /// + /// Full sim land object creation + /// + /// + public static bool[,] basicFullRegionLandBitmap() + { + return getSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize); + } + + /// + /// Used to modify the bitmap between the x and y points. Points use 64 scale + /// + /// + /// + /// + /// + /// + public static bool[,] getSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) + { + bool[,] tempBitmap = new bool[64,64]; + tempBitmap.Initialize(); + + tempBitmap = modifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); + return tempBitmap; + } + + /// + /// Change a land bitmap at within a square and set those points to a specific value + /// + /// + /// + /// + /// + /// + /// + /// + public static bool[,] modifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, + bool set_value) + { + if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()"); + } + + int x, y; + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + if (x >= start_x/4 && x < end_x/4 + && y >= start_y/4 && y < end_y/4) + { + land_bitmap[x, y] = set_value; + } + } + } + return land_bitmap; + } + + /// + /// Join the true values of 2 bitmaps together + /// + /// + /// + /// + public static bool[,] mergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) + { + if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps"); + } + if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps"); + } + + int x, y; + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + if (bitmap_add[x, y]) + { + bitmap_base[x, y] = true; + } + } + } + return bitmap_base; + } + + #endregion + + #region Object Select and Object Owner Listing + + public void sendForceObjectSelect(int local_id, int request_type, IClientAPI remote_client) + { + List resultLocalIDs = new List(); + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.LocalId > 0) + { + if (request_type == LandManager.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == landData.ownerID) + { + resultLocalIDs.Add(obj.LocalId); + } + // else if (request_type == LandManager.LAND_SELECT_OBJECTS_GROUP && ...) // TODO: group support + // { + // } + else if (request_type == LandManager.LAND_SELECT_OBJECTS_OTHER && + obj.OwnerID != remote_client.AgentId) + { + resultLocalIDs.Add(obj.LocalId); + } + } + } + + + bool firstCall = true; + int MAX_OBJECTS_PER_PACKET = 251; + ForceObjectSelectPacket pack = (ForceObjectSelectPacket) PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); + // TODO: don't create new blocks if recycling an old packet + ForceObjectSelectPacket.DataBlock[] data; + while (resultLocalIDs.Count > 0) + { + if (firstCall) + { + pack._Header.ResetList = true; + firstCall = false; + } + else + { + pack._Header.ResetList = false; + } + + if (resultLocalIDs.Count > MAX_OBJECTS_PER_PACKET) + { + data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET]; + } + else + { + data = new ForceObjectSelectPacket.DataBlock[resultLocalIDs.Count]; + } + + int i; + for (i = 0; i < MAX_OBJECTS_PER_PACKET && resultLocalIDs.Count > 0; i++) + { + data[i] = new ForceObjectSelectPacket.DataBlock(); + data[i].LocalID = Convert.ToUInt32(resultLocalIDs[0]); + resultLocalIDs.RemoveAt(0); + } + pack.Data = data; + remote_client.OutPacket((Packet) pack, ThrottleOutPacketType.Task); + } + } + + public void sendLandObjectOwners(IClientAPI remote_client) + { + Dictionary ownersAndCount = new Dictionary(); + ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket) PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); + // TODO: don't create new blocks if recycling an old packet + + foreach (SceneObjectGroup obj in primsOverMe) + { + if (!ownersAndCount.ContainsKey(obj.OwnerID)) + { + ownersAndCount.Add(obj.OwnerID, 0); + } + ownersAndCount[obj.OwnerID] += obj.PrimCount; + } + if (ownersAndCount.Count > 0) + { + ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock = new ParcelObjectOwnersReplyPacket.DataBlock[32]; + + if (ownersAndCount.Count < 32) + { + dataBlock = new ParcelObjectOwnersReplyPacket.DataBlock[ownersAndCount.Count]; + } + + + int num = 0; + foreach (LLUUID owner in ownersAndCount.Keys) + { + dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock(); + dataBlock[num].Count = ownersAndCount[owner]; + dataBlock[num].IsGroupOwned = false; //TODO: fix me when group support is added + dataBlock[num].OnlineStatus = true; //TODO: fix me later + dataBlock[num].OwnerID = owner; + + num++; + } + pack.Data = dataBlock; + } + remote_client.OutPacket(pack, ThrottleOutPacketType.Task); + } + + #endregion + + #region Object Returning + + public void returnObject(SceneObjectGroup obj) + { + } + + public void returnLandObjects(int type, LLUUID owner) + { + } + + #endregion + + #region Object Adding/Removing from Parcel + + public void resetLandPrimCounts() + { + landData.groupPrims = 0; + landData.ownerPrims = 0; + landData.otherPrims = 0; + landData.selectedPrims = 0; + primsOverMe.Clear(); + } + + public void addPrimToCount(SceneObjectGroup obj) + { + LLUUID prim_owner = obj.OwnerID; + int prim_count = obj.PrimCount; + + if (obj.IsSelected) + { + landData.selectedPrims += prim_count; + } + else + { + if (prim_owner == landData.ownerID) + { + landData.ownerPrims += prim_count; + } + else + { + landData.otherPrims += prim_count; + } + } + + primsOverMe.Add(obj); + } + + public void removePrimFromCount(SceneObjectGroup obj) + { + if (primsOverMe.Contains(obj)) + { + LLUUID prim_owner = obj.OwnerID; + int prim_count = obj.PrimCount; + + if (prim_owner == landData.ownerID) + { + landData.ownerPrims -= prim_count; + } + else if (prim_owner == landData.groupID) + { + landData.groupPrims -= prim_count; + } + else + { + landData.otherPrims -= prim_count; + } + + primsOverMe.Remove(obj); + } + } + + #endregion + + #endregion + } + + #endregion +} diff --git a/trunk/OpenSim/Region/Environment/LandManagement/LandManager.cs b/trunk/OpenSim/Region/Environment/LandManagement/LandManager.cs new file mode 100644 index 0000000000..f5e2a3ef69 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/LandManagement/LandManager.cs @@ -0,0 +1,896 @@ +/* +* 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; +using System.Collections.Generic; +using Axiom.Math; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Environment.LandManagement +{ + #region LandManager Class + + /// + /// Handles Land objects and operations requiring information from other Land objects (divide, join, etc) + /// + public class LandManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #region Constants + + //Land types set with flags in ParcelOverlay. + //Only one of these can be used. + public const byte LAND_TYPE_PUBLIC = (byte) 0; //Equals 00000000 + public const byte LAND_TYPE_OWNED_BY_OTHER = (byte) 1; //Equals 00000001 + public const byte LAND_TYPE_OWNED_BY_GROUP = (byte) 2; //Equals 00000010 + public const byte LAND_TYPE_OWNED_BY_REQUESTER = (byte) 3; //Equals 00000011 + public const byte LAND_TYPE_IS_FOR_SALE = (byte) 4; //Equals 00000100 + public const byte LAND_TYPE_IS_BEING_AUCTIONED = (byte) 5; //Equals 00000101 + + //Flags that when set, a border on the given side will be placed + //NOTE: North and East is assumable by the west and south sides (if land to east has a west border, then I have an east border; etc) + //This took forever to figure out -- jeesh. /blame LL for even having to send these + public const byte LAND_FLAG_PROPERTY_BORDER_WEST = (byte) 64; //Equals 01000000 + public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = (byte) 128; //Equals 10000000 + + //RequestResults (I think these are right, they seem to work): + public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land + public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land + + //ParcelSelectObjects + public const int LAND_SELECT_OBJECTS_OWNER = 2; + public const int LAND_SELECT_OBJECTS_GROUP = 4; + public const int LAND_SELECT_OBJECTS_OTHER = 8; + + //These are other constants. Yay! + public const int START_LAND_LOCAL_ID = 1; + + public const float BAN_LINE_SAFETY_HIEGHT = 100; + + #endregion + + #region Member Variables + + public Dictionary landList = new Dictionary(); + private int lastLandLocalID = START_LAND_LOCAL_ID - 1; + private int[,] landIDList = new int[64,64]; + + /// + /// Set to true when a prim is moved, created, added. Performs a prim count update + /// + public bool landPrimCountTainted = false; + + private readonly Scene m_scene; + private readonly RegionInfo m_regInfo; + + public bool allowedForcefulBans = true; + + #endregion + + #region Constructors + + public LandManager(Scene scene, RegionInfo reginfo) + { + m_scene = scene; + m_regInfo = reginfo; + landIDList.Initialize(); + scene.EventManager.OnAvatarEnteringNewParcel += + new EventManager.AvatarEnteringNewParcel(handleAvatarChangingParcel); + scene.EventManager.OnClientMovement += new EventManager.ClientMovement(handleAnyClientMovement); + } + + #endregion + + #region Member Functions + + #region Land Object From Storage Functions + + public void IncomingLandObjectsFromStorage(List data) + { + for (int i = 0; i < data.Count; i++) + { + //try + //{ + IncomingLandObjectFromStorage(data[i]); + //} + //catch (Exception ex) + //{ + //m_log.Error("[LandManager]: IncomingLandObjectsFromStorage: Exception: " + ex.ToString()); + //throw ex; + //} + } + //foreach (LandData parcel in data) + //{ + // IncomingLandObjectFromStorage(parcel); + //} + } + + public void IncomingLandObjectFromStorage(LandData data) + { + Land new_land = new Land(data.ownerID, data.isGroupOwned, m_scene); + new_land.landData = data.Copy(); + new_land.setLandBitmapFromByteArray(); + addLandObject(new_land); + } + + public void NoLandDataFromStorage() + { + Console.WriteLine("No LandData in storage! Loading a single, flat parcel instead"); + resetSimLandObjects(); + } + + #endregion + + #region Parcel Add/Remove/Get/Create + + /// + /// Creates a basic Parcel object without an owner (a zeroed key) + /// + /// + public Land createBaseLand() + { + return new Land(LLUUID.Zero, false, m_scene); + } + + /// + /// Adds a land object to the stored list and adds them to the landIDList to what they own + /// + /// The land object being added + public Land addLandObject(Land new_land) + { + lastLandLocalID++; + new_land.landData.localID = lastLandLocalID; + landList.Add(lastLandLocalID, new_land.Copy()); + + + bool[,] landBitmap = new_land.getLandBitmap(); + int x, y; + for (x = 0; x < 64; x++) + { + for (y = 0; y < 64; y++) + { + if (landBitmap[x, y]) + { + landIDList[x, y] = lastLandLocalID; + } + } + } + landList[lastLandLocalID].forceUpdateLandInfo(); + m_scene.EventManager.TriggerLandObjectAdded(new_land, m_scene.RegionInfo.RegionID); + return new_land; + } + + /// + /// Removes a land object from the list. Will not remove if local_id is still owning an area in landIDList + /// + /// Land.localID of the peice of land to remove. + public void removeLandObject(int local_id) + { + int x, y; + for (x = 0; x < 64; x++) + { + for (y = 0; y < 64; y++) + { + if (landIDList[x, y] == local_id) + { + return; + //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y); + } + } + } + + m_scene.EventManager.TriggerLandObjectRemoved(landList[local_id].landData.globalID); + landList.Remove(local_id); + } + + public void updateLandObject(int local_id, LandData newData) + { + if (landList.ContainsKey(local_id)) + { + landList[local_id].landData = newData.Copy(); + m_scene.EventManager.TriggerLandObjectUpdated((uint) local_id, landList[local_id]); + } + else + { + //throw new Exception("Could not update land object. Local ID '" + local_id + "' does not exist"); + } + } + + private void performFinalLandJoin(Land master, Land slave) + { + int x, y; + bool[,] landBitmapSlave = slave.getLandBitmap(); + for (x = 0; x < 64; x++) + { + for (y = 0; y < 64; y++) + { + if (landBitmapSlave[x, y]) + { + landIDList[x, y] = master.landData.localID; + } + } + } + + removeLandObject(slave.landData.localID); + updateLandObject(master.landData.localID, master.landData); + } + + /// + /// Get the land object at the specified point + /// + /// Value between 0 - 256 on the x axis of the point + /// Value between 0 - 256 on the y axis of the point + /// Land object at the point supplied + public Land getLandObject(float x_float, float y_float) + { + int x; + int y; + + try + { + x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / Convert.ToDouble(4.0))); + y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / Convert.ToDouble(4.0))); + } + catch (System.OverflowException) + { + return null; + } + + if (x >= 64 || y >= 64 || x < 0 || y < 0) + { + return null; + } + else + { + // Console.WriteLine("Point (" + x + ", " + y + ") determined from point (" + x_float + ", " + y_float + ")"); + return landList[landIDList[x, y]]; + } + } + + public Land getLandObject(int x, int y) + { + if (x >= Constants.RegionSize || y >= Constants.RegionSize || x < 0 || y < 0) + { + // These exceptions here will cause a lot of complaints from the users specifically because + // they happen every time at border crossings + throw new Exception("Error: Parcel not found at point " + x + ", " + y); + } + else + { + return landList[landIDList[x/4, y/4]]; + } + } + + #endregion + + #region Parcel Modification + + /// + /// Subdivides a piece of land + /// + /// West Point + /// South Point + /// East Point + /// North Point + /// LLUUID of user who is trying to subdivide + /// Returns true if successful + private bool subdivide(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id) + { + //First, lets loop through the points and make sure they are all in the same peice of land + //Get the land object at start + Land startLandObject = getLandObject(start_x, start_y); + if (startLandObject == null) return false; //No such land object at the beginning + + //Loop through the points + try + { + int totalX = end_x - start_x; + int totalY = end_y - start_y; + int x, y; + for (y = 0; y < totalY; y++) + { + for (x = 0; x < totalX; x++) + { + Land tempLandObject = getLandObject(start_x + x, start_y + y); + if (tempLandObject == null) return false; //No such land object at that point + if (tempLandObject != startLandObject) return false; //Subdividing over 2 land objects; no-no + } + } + } + catch (Exception) + { + return false; //Exception. For now, lets skip subdivision + } + + //If we are still here, then they are subdividing within one piece of land + //Check owner + if (startLandObject.landData.ownerID != attempting_user_id) + { + return false; //They cant do this! + } + + //Lets create a new land object with bitmap activated at that point (keeping the old land objects info) + Land newLand = startLandObject.Copy(); + newLand.landData.landName = "Subdivision of " + newLand.landData.landName; + newLand.landData.globalID = LLUUID.Random(); + + newLand.setLandBitmap(Land.getSquareLandBitmap(start_x, start_y, end_x, end_y)); + + //Now, lets set the subdivision area of the original to false + int startLandObjectIndex = startLandObject.landData.localID; + landList[startLandObjectIndex].setLandBitmap( + Land.modifyLandBitmapSquare(startLandObject.getLandBitmap(), start_x, start_y, end_x, end_y, false)); + landList[startLandObjectIndex].forceUpdateLandInfo(); + + setPrimsTainted(); + + //Now add the new land object + Land result = addLandObject(newLand); + updateLandObject(startLandObject.landData.localID, startLandObject.landData); + result.sendLandUpdateToAvatarsOverMe(); + + + return true; + } + + /// + /// Join 2 land objects together + /// + /// x value in first piece of land + /// y value in first piece of land + /// x value in second peice of land + /// y value in second peice of land + /// LLUUID of the avatar trying to join the land objects + /// Returns true if successful + private bool join(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id) + { + end_x -= 4; + end_y -= 4; + + List selectedLandObjects = new List(); + int stepXSelected = 0; + int stepYSelected = 0; + for (stepYSelected = start_y; stepYSelected <= end_y; stepYSelected += 4) + { + for (stepXSelected = start_x; stepXSelected <= end_x; stepXSelected += 4) + { + Land p = getLandObject(stepXSelected, stepYSelected); + if (p != null) + { + if (!selectedLandObjects.Contains(p)) + { + selectedLandObjects.Add(p); + } + } + } + } + Land masterLandObject = selectedLandObjects[0]; + selectedLandObjects.RemoveAt(0); + + + if (selectedLandObjects.Count < 1) + { + return false; //Only one piece of land selected + } + if (masterLandObject.landData.ownerID != attempting_user_id) + { + return false; //Not the same owner + } + foreach (Land p in selectedLandObjects) + { + if (p.landData.ownerID != masterLandObject.landData.ownerID) + { + return false; //Over multiple users. TODO: make this just ignore this piece of land? + } + } + foreach (Land slaveLandObject in selectedLandObjects) + { + landList[masterLandObject.landData.localID].setLandBitmap( + Land.mergeLandBitmaps(masterLandObject.getLandBitmap(), slaveLandObject.getLandBitmap())); + performFinalLandJoin(masterLandObject, slaveLandObject); + } + + + setPrimsTainted(); + + masterLandObject.sendLandUpdateToAvatarsOverMe(); + + return true; + } + + #endregion + + #region Parcel Updating + + /// + /// Where we send the ParcelOverlay packet to the client + /// + /// The object representing the client + public void sendParcelOverlay(IClientAPI remote_client) + { + const int LAND_BLOCKS_PER_PACKET = 1024; + int x, y = 0; + byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; + int byteArrayCount = 0; + int sequenceID = 0; + ParcelOverlayPacket packet; + + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + byte tempByte = (byte) 0; //This represents the byte for the current 4x4 + Land currentParcelBlock = getLandObject(x*4, y*4); + if (currentParcelBlock != null) + { + if (currentParcelBlock.landData.ownerID == remote_client.AgentId) + { + //Owner Flag + tempByte = Convert.ToByte(tempByte | LAND_TYPE_OWNED_BY_REQUESTER); + } + else if (currentParcelBlock.landData.salePrice > 0 && + (currentParcelBlock.landData.authBuyerID == LLUUID.Zero || + currentParcelBlock.landData.authBuyerID == remote_client.AgentId)) + { + //Sale Flag + tempByte = Convert.ToByte(tempByte | LAND_TYPE_IS_FOR_SALE); + } + else if (currentParcelBlock.landData.ownerID == LLUUID.Zero) + { + //Public Flag + tempByte = Convert.ToByte(tempByte | LAND_TYPE_PUBLIC); + } + else + { + //Other Flag + tempByte = Convert.ToByte(tempByte | LAND_TYPE_OWNED_BY_OTHER); + } + + + //Now for border control + try + { + Land westParcel = null; + Land southParcel = null; + if (x > 0) + { + westParcel = getLandObject((x - 1)*4, y*4); + } + if (y > 0) + { + southParcel = getLandObject(x*4, (y - 1)*4); + } + + if (x == 0) + { + tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_WEST); + } + else if (westParcel != null && westParcel != currentParcelBlock) + { + tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_WEST); + } + + if (y == 0) + { + tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_SOUTH); + } + else if (southParcel != null && southParcel != currentParcelBlock) + { + tempByte = Convert.ToByte(tempByte | LAND_FLAG_PROPERTY_BORDER_SOUTH); + } + + byteArray[byteArrayCount] = tempByte; + byteArrayCount++; + if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) + { + byteArrayCount = 0; + packet = (ParcelOverlayPacket) PacketPool.Instance.GetPacket(PacketType.ParcelOverlay); + packet.ParcelData.Data = byteArray; + packet.ParcelData.SequenceID = sequenceID; + remote_client.OutPacket((Packet) packet, ThrottleOutPacketType.Task); + sequenceID++; + byteArray = new byte[LAND_BLOCKS_PER_PACKET]; + } + } + catch (Exception e) + { + m_log.Debug("[LAND]: Skipped Land checks because avatar is out of bounds: " + e.Message); + } + } + } + } + } + + public void handleParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, + bool snap_selection, IClientAPI remote_client) + { + //Get the land objects within the bounds + List temp = new List(); + int x, y, i; + int inc_x = end_x - start_x; + int inc_y = end_y - start_y; + for (x = 0; x < inc_x; x++) + { + for (y = 0; y < inc_y; y++) + { + Land currentParcel = getLandObject(start_x + x, start_y + y); + if (currentParcel != null) + { + if (!temp.Contains(currentParcel)) + { + currentParcel.forceUpdateLandInfo(); + temp.Add(currentParcel); + } + } + } + } + + int requestResult = LAND_RESULT_SINGLE; + if (temp.Count > 1) + { + requestResult = LAND_RESULT_MULTIPLE; + } + + for (i = 0; i < temp.Count; i++) + { + temp[i].sendLandProperties(sequence_id, snap_selection, requestResult, remote_client); + } + + + sendParcelOverlay(remote_client); + } + + public void handleParcelPropertiesUpdateRequest(ParcelPropertiesUpdatePacket packet, IClientAPI remote_client) + { + if (landList.ContainsKey(packet.ParcelData.LocalID)) + { + landList[packet.ParcelData.LocalID].updateLandProperties(packet, remote_client); + } + } + + public void handleParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client) + { + subdivide(west, south, east, north, remote_client.AgentId); + } + + public void handleParcelJoinRequest(int west, int south, int east, int north, IClientAPI remote_client) + { + join(west, south, east, north, remote_client.AgentId); + } + + public void handleParcelSelectObjectsRequest(int local_id, int request_type, IClientAPI remote_client) + { + landList[local_id].sendForceObjectSelect(local_id, request_type, remote_client); + } + + public void handleParcelObjectOwnersRequest(int local_id, IClientAPI remote_client) + { + landList[local_id].sendLandObjectOwners(remote_client); + } + + #endregion + + /// + /// Resets the sim to the default land object (full sim piece of land owned by the default user) + /// + public void resetSimLandObjects() + { + //Remove all the land objects in the sim and add a blank, full sim land object set to public + landList.Clear(); + lastLandLocalID = START_LAND_LOCAL_ID - 1; + landIDList.Initialize(); + + Land fullSimParcel = new Land(LLUUID.Zero, false, m_scene); + + fullSimParcel.setLandBitmap(Land.getSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); + fullSimParcel.landData.ownerID = m_regInfo.MasterAvatarAssignedUUID; + + addLandObject(fullSimParcel); + } + + public List parcelsNearPoint(LLVector3 position) + { + List parcelsNear = new List(); + int x, y; + for (x = -4; x <= 4; x += 4) + { + for (y = -4; y <= 4; y += 4) + { + Land check = getLandObject(position.X + x, position.Y + y); + if (check != null) + { + if (!parcelsNear.Contains(check)) + { + parcelsNear.Add(check); + } + } + } + } + + return parcelsNear; + } + + public void sendYouAreBannedNotice(ScenePresence avatar) + { + if (allowedForcefulBans) + { + avatar.ControllingClient.SendAlertMessage( + "You are not allowed on this parcel because you are banned. Please go away. <3 OpenSim Developers"); + + avatar.PhysicsActor.Position = + new PhysicsVector(avatar.lastKnownAllowedPosition.x, avatar.lastKnownAllowedPosition.y, + avatar.lastKnownAllowedPosition.z); + avatar.PhysicsActor.Velocity = new PhysicsVector(0, 0, 0); + } + else + { + avatar.ControllingClient.SendAlertMessage( + "You are not allowed on this parcel because you are banned; however, the grid administrator has disabled ban lines globally. Please obey the land owner's requests or you can be banned from the entire sim! <3 OpenSim Developers"); + } + } + + public void handleAvatarChangingParcel(ScenePresence avatar, int localLandID, LLUUID regionID) + { + if (m_scene.RegionInfo.RegionID == regionID) + { + if (landList[localLandID] != null) + { + Land parcelAvatarIsEntering = landList[localLandID]; + if (avatar.AbsolutePosition.Z < BAN_LINE_SAFETY_HIEGHT) + { + if (parcelAvatarIsEntering.isBannedFromLand(avatar.UUID)) + { + sendYouAreBannedNotice(avatar); + } + else if (parcelAvatarIsEntering.isRestrictedFromLand(avatar.UUID)) + { + avatar.ControllingClient.SendAlertMessage( + "You are not allowed on this parcel because the land owner has restricted access. For now, you can enter, but please respect the land owner's decisions (or he can ban you!). <3 OpenSim Developers"); + } + else + { + avatar.sentMessageAboutRestrictedParcelFlyingDown = true; + } + } + else + { + avatar.sentMessageAboutRestrictedParcelFlyingDown = true; + } + } + } + } + + public void sendOutNearestBanLine(IClientAPI avatar) + { + List avatars = m_scene.GetAvatars(); + foreach (ScenePresence presence in avatars) + { + if (presence.UUID == avatar.AgentId) + { + List checkLandParcels = parcelsNearPoint(presence.AbsolutePosition); + foreach (Land checkBan in checkLandParcels) + { + if (checkBan.isBannedFromLand(avatar.AgentId)) + { + checkBan.sendLandProperties(-30000, false, (int) ParcelManager.ParcelResult.Single, avatar); + return; //Only send one + } + else if (checkBan.isRestrictedFromLand(avatar.AgentId)) + { + checkBan.sendLandProperties(-40000, false, (int) ParcelManager.ParcelResult.Single, avatar); + return; //Only send one + } + } + return; + } + } + } + + public void sendLandUpdate(ScenePresence avatar, bool force) + { + Land over = getLandObject((int) Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), + (int) Math.Min(255, Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); + + if (over != null) + { + if (force) + { + if (!avatar.IsChildAgent) + { + over.sendLandUpdateToClient(avatar.ControllingClient); + } + } + + if (avatar.currentParcelUUID != over.landData.globalID) + { + if (!avatar.IsChildAgent) + { + over.sendLandUpdateToClient(avatar.ControllingClient); + avatar.currentParcelUUID = over.landData.globalID; + m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.landData.localID, + m_scene.RegionInfo.RegionID); + } + } + } + } + public void sendLandUpdate(ScenePresence avatar) + { + sendLandUpdate(avatar, false); + + } + public void handleSignificantClientMovement(IClientAPI remote_client) + { + ScenePresence clientAvatar = m_scene.GetScenePresence(remote_client.AgentId); + + if (clientAvatar != null) + { + sendLandUpdate(clientAvatar); + sendOutNearestBanLine(remote_client); + Land parcel = getLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y); + if (parcel != null) + { + if (clientAvatar.AbsolutePosition.Z < BAN_LINE_SAFETY_HIEGHT && + clientAvatar.sentMessageAboutRestrictedParcelFlyingDown) + { + handleAvatarChangingParcel(clientAvatar, parcel.landData.localID, m_scene.RegionInfo.RegionID); + //They are going below the safety line! + if (!parcel.isBannedFromLand(clientAvatar.UUID)) + { + clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false; + } + } + else if (clientAvatar.AbsolutePosition.Z < BAN_LINE_SAFETY_HIEGHT && + parcel.isBannedFromLand(clientAvatar.UUID)) + { + sendYouAreBannedNotice(clientAvatar); + } + } + } + } + + public void handleAnyClientMovement(ScenePresence avatar) + //Like handleSignificantClientMovement, but called with an AgentUpdate regardless of distance. + { + Land over = getLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + if (over != null) + { + if (!over.isBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= BAN_LINE_SAFETY_HIEGHT) + { + avatar.lastKnownAllowedPosition = + new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); + } + } + } + + + public void handleParcelAccessRequest(LLUUID agentID, LLUUID sessionID, uint flags, int sequenceID, + int landLocalID, IClientAPI remote_client) + { + if (landList.ContainsKey(landLocalID)) + { + landList[landLocalID].sendAccessList(agentID, sessionID, flags, sequenceID, remote_client); + } + } + + public void handleParcelAccessUpdateRequest(LLUUID agentID, LLUUID sessionID, uint flags, int landLocalID, + List entries, + IClientAPI remote_client) + { + if (landList.ContainsKey(landLocalID)) + { + if (agentID == landList[landLocalID].landData.ownerID) + { + landList[landLocalID].updateAccessList(flags, entries, remote_client); + } + } + else + { + Console.WriteLine("INVALID LOCAL LAND ID"); + } + } + + public void resetAllLandPrimCounts() + { + foreach (Land p in landList.Values) + { + p.resetLandPrimCounts(); + } + } + + public void setPrimsTainted() + { + landPrimCountTainted = true; + } + + public void addPrimToLandPrimCounts(SceneObjectGroup obj) + { + LLVector3 position = obj.AbsolutePosition; + Land landUnderPrim = getLandObject(position.X, position.Y); + if (landUnderPrim != null) + { + landUnderPrim.addPrimToCount(obj); + } + } + + public void removePrimFromLandPrimCounts(SceneObjectGroup obj) + { + foreach (Land p in landList.Values) + { + p.removePrimFromCount(obj); + } + } + + public void finalizeLandPrimCountUpdate() + { + //Get Simwide prim count for owner + Dictionary> landOwnersAndParcels = new Dictionary>(); + foreach (Land p in landList.Values) + { + if (!landOwnersAndParcels.ContainsKey(p.landData.ownerID)) + { + List tempList = new List(); + tempList.Add(p); + landOwnersAndParcels.Add(p.landData.ownerID, tempList); + } + else + { + landOwnersAndParcels[p.landData.ownerID].Add(p); + } + } + + foreach (LLUUID owner in landOwnersAndParcels.Keys) + { + int simArea = 0; + int simPrims = 0; + foreach (Land p in landOwnersAndParcels[owner]) + { + simArea += p.landData.area; + simPrims += p.landData.ownerPrims + p.landData.otherPrims + p.landData.groupPrims + + p.landData.selectedPrims; + } + + foreach (Land p in landOwnersAndParcels[owner]) + { + p.landData.simwideArea = simArea; + p.landData.simwidePrims = simPrims; + } + } + } + + #endregion + } + + #endregion +} diff --git a/trunk/OpenSim/Region/Environment/ModuleLoader.cs b/trunk/OpenSim/Region/Environment/ModuleLoader.cs new file mode 100644 index 0000000000..1200c8df39 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/ModuleLoader.cs @@ -0,0 +1,305 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Modules; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment +{ + public class ModuleLoader + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public Dictionary LoadedAssemblys = new Dictionary(); + + private readonly List m_loadedModules = new List(); + private readonly Dictionary m_loadedSharedModules = new Dictionary(); + private readonly IConfigSource m_config; + + public ModuleLoader(IConfigSource config) + { + m_config = config; + } + + public IRegionModule[] GetLoadedSharedModules + { + get + { + IRegionModule[] regionModules = new IRegionModule[m_loadedSharedModules.Count]; + m_loadedSharedModules.Values.CopyTo(regionModules, 0); + return regionModules; + } + } + + public void PickupModules(Scene scene, string moduleDir) + { + DirectoryInfo dir = new DirectoryInfo(moduleDir); + + foreach (FileInfo fileInfo in dir.GetFiles("*.dll")) + { + LoadRegionModules(fileInfo.FullName, scene); + } + } + + public void LoadDefaultSharedModules() + { + DynamicTextureModule dynamicModule = new DynamicTextureModule(); + if (m_loadedSharedModules.ContainsKey(dynamicModule.Name)) + { + m_log.ErrorFormat("[MODULES]: Module name \"{0}\" already exists in module list. Module type {1} not added!", dynamicModule.Name, "DynamicTextureModule"); + } + else + { + m_loadedSharedModules.Add(dynamicModule.Name, dynamicModule); + } + + ChatModule chat = new ChatModule(); + if (m_loadedSharedModules.ContainsKey(chat.Name)) + { + m_log.ErrorFormat("[MODULES]: Module name \"{0}\" already exists in module list. Module type {1} not added!", chat.Name, "ChatModule"); + } + else + { + m_loadedSharedModules.Add(chat.Name, chat); + } + + InstantMessageModule imMod = new InstantMessageModule(); + if (m_loadedSharedModules.ContainsKey(imMod.Name)) + { + m_log.ErrorFormat("[MODULES]: Module name \"{0}\" already exists in module list. Module type {1} not added!", imMod.Name, "InstantMessageModule"); + } + else + { + m_loadedSharedModules.Add(imMod.Name, imMod); + } + + LoadImageURLModule loadMod = new LoadImageURLModule(); + if (m_loadedSharedModules.ContainsKey(loadMod.Name)) + { + m_log.ErrorFormat("[MODULES]: Module name \"{0}\" already exists in module list. Module type {1} not added!", loadMod.Name, "LoadImageURLModule"); + } + else + { + m_loadedSharedModules.Add(loadMod.Name, loadMod); + } + + AvatarFactoryModule avatarFactory = new AvatarFactoryModule(); + if (m_loadedSharedModules.ContainsKey(avatarFactory.Name)) + { + m_log.ErrorFormat("[MODULES]: Module name \"{0}\" already exists in module list. Module type {1} not added!", avatarFactory.Name, "AvarFactoryModule"); + } + else + { + m_loadedSharedModules.Add(avatarFactory.Name, avatarFactory); + } + + XMLRPCModule xmlRpcMod = new XMLRPCModule(); + if (m_loadedSharedModules.ContainsKey(xmlRpcMod.Name)) + { + m_log.ErrorFormat("[MODULES]: Module name \"{0}\" already exists in module list. Module type {1} not added!", xmlRpcMod.Name, "XMLRPCModule"); + } + else + { + m_loadedSharedModules.Add(xmlRpcMod.Name, xmlRpcMod); + } + //TextureDownloadModule textureModule = new TextureDownloadModule(); + + //LoadedSharedModules.Add(textureModule.Name, textureModule); + } + + public void InitialiseSharedModules(Scene scene) + { + foreach (IRegionModule module in m_loadedSharedModules.Values) + { + module.Initialise(scene, m_config); + scene.AddModule(module.Name, module); //should be doing this? + } + } + + public void InitializeModule(IRegionModule module, Scene scene) + { + module.Initialise(scene, m_config); + scene.AddModule(module.Name, module); + m_loadedModules.Add(module); + } + + /// + /// Loads/initialises a Module instance that can be used by multiple Regions + /// + /// + /// + public void LoadSharedModule(string dllName, string moduleName) + { + IRegionModule module = LoadModule(dllName, moduleName); + + if (module != null) + LoadSharedModule(module); + } + + /// + /// Loads/initialises a Module instance that can be used by multiple Regions + /// + /// + public void LoadSharedModule(IRegionModule module) + { + if (!m_loadedSharedModules.ContainsKey(module.Name)) + { + m_loadedSharedModules.Add(module.Name, module); + } + } + + public void LoadRegionModules(string dllName, Scene scene) + { + IRegionModule[] modules = LoadModules(dllName); + + if (modules.Length > 0) + { + m_log.InfoFormat("[MODULES]: Found Module Library [{0}]", dllName); + foreach (IRegionModule module in modules) + { + if (!module.IsSharedModule) + { + m_log.InfoFormat("[MODULES]: [{0}]: Initializing.", module.Name); + InitializeModule(module, scene); + } + else + { + m_log.InfoFormat("[MODULES]: [{0}]: Loading Shared Module.", module.Name); + LoadSharedModule(module); + } + } + } + } + + public void LoadRegionModule(string dllName, string moduleName, Scene scene) + { + IRegionModule module = LoadModule(dllName, moduleName); + if (module != null) + { + InitializeModule(module, scene); + } + } + + /// + /// Loads a external Module (if not already loaded) and creates a new instance of it. + /// + /// + /// + public IRegionModule LoadModule(string dllName, string moduleName) + { + IRegionModule[] modules = LoadModules(dllName); + + foreach (IRegionModule module in modules) + { + if ((module != null) && (module.Name == moduleName)) + { + return module; + } + } + + return null; + } + + public IRegionModule[] LoadModules(string dllName) + { + List modules = new List(); + + Assembly pluginAssembly; + if (!LoadedAssemblys.TryGetValue(dllName, out pluginAssembly)) + { + try + { + pluginAssembly = Assembly.LoadFrom(dllName); + LoadedAssemblys.Add(dllName, pluginAssembly); + } + catch (BadImageFormatException) + { + //m_log.InfoFormat("[MODULES]: The file [{0}] is not a module assembly.", e.FileName); + } + } + + if (pluginAssembly != null) + { + try + { + foreach (Type pluginType in pluginAssembly.GetTypes()) + { + if (pluginType.IsPublic) + { + if (!pluginType.IsAbstract) + { + if (pluginType.GetInterface("IRegionModule") != null) + { + modules.Add((IRegionModule)Activator.CreateInstance(pluginType)); + } + } + } + } + } + catch (ReflectionTypeLoadException) + { + m_log.InfoFormat("[MODULES]: Could not load types for [{0}].", pluginAssembly.FullName); + } + } + + return modules.ToArray(); + } + + public void PostInitialise() + { + foreach (IRegionModule module in m_loadedSharedModules.Values) + { + module.PostInitialise(); + } + + foreach (IRegionModule module in m_loadedModules) + { + module.PostInitialise(); + } + } + + public void ClearCache() + { + LoadedAssemblys.Clear(); + } + + public void UnloadModule(IRegionModule rm) + { + rm.Close(); + + m_loadedModules.Remove(rm); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Modules/AgentAssetTransactionModule.cs b/trunk/OpenSim/Region/Environment/Modules/AgentAssetTransactionModule.cs new file mode 100644 index 0000000000..f29c20e741 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/AgentAssetTransactionModule.cs @@ -0,0 +1,272 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class AgentAssetTransactionModule : IRegionModule, IAgentAssetTransactions + { + private Dictionary RegisteredScenes = new Dictionary(); + private Scene m_scene = null; + private bool m_dumpAssetsToFile = false; + + private AgentAssetTransactionsManager m_transactionManager; + + public void Initialise(Scene scene, IConfigSource config) + { + if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) + { + RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); + scene.RegisterModuleInterface(this); + + scene.EventManager.OnNewClient += NewClient; + + try + { + m_dumpAssetsToFile = config.Configs["StandAlone"].GetBoolean("dump_assets_to_file", false); + } + catch (Exception) + { + } + } + + if (m_scene == null) + { + m_scene = scene; + m_transactionManager = new AgentAssetTransactionsManager(m_scene, m_dumpAssetsToFile); + } + } + + public void PostInitialise() + { + + } + + public void Close() + { + } + + public string Name + { + get { return "AgentTransactionModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public void NewClient(IClientAPI client) + { + client.OnAssetUploadRequest += m_transactionManager.HandleUDPUploadRequest; + client.OnXferReceive += m_transactionManager.HandleXfer; + } + + public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + m_transactionManager.HandleItemCreationFromTransaction(remoteClient, transactionID, folderID, callbackID, description, name, invType, type, wearableType, nextOwnerMask); + } + + public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID, + InventoryItemBase item) + { + m_transactionManager.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); + } + + public void RemoveAgentAssetTransactions(LLUUID userID) + { + m_transactionManager.RemoveAgentAssetTransactions(userID); + } + } + + //should merge this classes and clean up + public class AgentAssetTransactionsManager + { + private static readonly log4net.ILog m_log + = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Fields + public Scene MyScene; + + /// + /// Each agent has its own singleton collection of transactions + /// + private Dictionary AgentTransactions = + new Dictionary(); + + /// + /// Should we dump uploaded assets to the filesystem? + /// + private bool m_dumpAssetsToFile; + + public AgentAssetTransactionsManager(Scene scene, bool dumpAssetsToFile) + { + MyScene = scene; + m_dumpAssetsToFile = dumpAssetsToFile; + } + + /// + /// Get the collection of asset transactions for the given user. If one does not already exist, it + /// is created. + /// + /// + /// + private AgentAssetTransactions GetUserTransactions(LLUUID userID) + { + lock (AgentTransactions) + { + if (!AgentTransactions.ContainsKey(userID)) + { + AgentAssetTransactions transactions + = new AgentAssetTransactions(userID, this, m_dumpAssetsToFile); + AgentTransactions.Add(userID, transactions); + } + + return AgentTransactions[userID]; + } + } + + /// + /// Remove the given agent asset transactions. This should be called when a client is departing + /// from a scene (and hence won't be making any more transactions here). + /// + /// + public void RemoveAgentAssetTransactions(LLUUID userID) + { + // m_log.DebugFormat("Removing agent asset transactions structure for agent {0}", userID); + + lock (AgentTransactions) + { + AgentTransactions.Remove(userID); + } + } + + /// + /// Create an inventory item from data that has been received through a transaction. + /// + /// This is called when new clothing or body parts are created. It may also be called in other + /// situations. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public void HandleItemCreationFromTransaction(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + m_log.DebugFormat( + "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name); + + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.RequestCreateInventoryItem( + remoteClient, transactionID, folderID, callbackID, description, + name, invType, type, wearableType, nextOwnerMask); + } + + /// + /// Update an inventory item with data that has been received through a transaction. + /// + /// This is called when clothing or body parts are updated (for instance, with new textures or + /// colours). It may also be called in other situations. + /// + /// + /// + /// + public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, LLUUID transactionID, + InventoryItemBase item) + { + m_log.DebugFormat( + "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", + item.inventoryName); + + AgentAssetTransactions transactions + = GetUserTransactions(remoteClient.AgentId); + + transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item); + } + + /// + /// Request that a client (agent) begin an asset transfer. + /// + /// + /// + /// + /// + /// + /// + public void HandleUDPUploadRequest(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, + byte[] data, bool storeLocal, bool tempFile) + { + // Console.WriteLine("asset upload of " + assetID); + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + AgentAssetTransactions.AssetXferUploader uploader = transactions.RequestXferUploader(transaction); + if (uploader != null) + { + + if (uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile)) + { + + } + } + } + + /// + /// Handle asset transfer data packets received in response to the asset upload request in + /// HandleUDPUploadRequest() + /// + /// + /// + /// + /// + public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) + { + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.HandleXfer(xferID, packetID, data); + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/AgentAssetsTransactions.cs b/trunk/OpenSim/Region/Environment/Modules/AgentAssetsTransactions.cs new file mode 100644 index 0000000000..f0fe6cf97d --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/AgentAssetsTransactions.cs @@ -0,0 +1,408 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using System.IO; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework.Servers; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; + +namespace OpenSim.Region.Environment.Modules +{ + + /// + /// Manage asset transactions for a single agent. + /// + public class AgentAssetTransactions + { + //private static readonly log4net.ILog m_log + // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Fields + public LLUUID UserID; + public Dictionary XferUploaders = new Dictionary(); + public AgentAssetTransactionsManager Manager; + private bool m_dumpAssetsToFile; + + // Methods + public AgentAssetTransactions(LLUUID agentID, AgentAssetTransactionsManager manager, bool dumpAssetsToFile) + { + UserID = agentID; + Manager = manager; + m_dumpAssetsToFile = dumpAssetsToFile; + } + + public AssetXferUploader RequestXferUploader(LLUUID transactionID) + { + if (!XferUploaders.ContainsKey(transactionID)) + { + AssetXferUploader uploader = new AssetXferUploader(this, m_dumpAssetsToFile); + + lock (XferUploaders) + { + XferUploaders.Add(transactionID, uploader); + } + + return uploader; + } + return null; + } + + public void HandleXfer(ulong xferID, uint packetID, byte[] data) + { + AssetXferUploader uploaderFound = null; + + lock (XferUploaders) + { + foreach (AssetXferUploader uploader in XferUploaders.Values) + { + if (uploader.XferID == xferID) + { + break; + } + } + + } + } + + public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + if (XferUploaders.ContainsKey(transactionID)) + { + XferUploaders[transactionID].RequestCreateInventoryItem(remoteClient, transactionID, folderID, + callbackID, description, name, invType, type, + wearableType, nextOwnerMask); + } + } + + public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, + InventoryItemBase item) + { + if (XferUploaders.ContainsKey(transactionID)) + { + XferUploaders[transactionID].RequestUpdateInventoryItem(remoteClient, transactionID, item); + } + } + + /// + /// Get an uploaded asset. If the data is successfully retrieved, the transaction will be removed. + /// + /// + /// The asset if the upload has completed, null if it has not. + public AssetBase GetTransactionAsset(LLUUID transactionID) + { + if (XferUploaders.ContainsKey(transactionID)) + { + AssetXferUploader uploader = XferUploaders[transactionID]; + AssetBase asset = uploader.GetAssetData(); + + lock (XferUploaders) + { + XferUploaders.Remove(transactionID); + } + + return asset; + } + + return null; + } + + // Nested Types + public class AssetXferUploader + { + // Fields + public bool AddToInventory; + public AssetBase Asset; + public LLUUID InventFolder = LLUUID.Zero; + private IClientAPI ourClient; + public LLUUID TransactionID = LLUUID.Zero; + public bool UploadComplete; + public ulong XferID; + private string m_name = String.Empty; + private string m_description = String.Empty; + private sbyte type = 0; + private sbyte invType = 0; + private uint nextPerm = 0; + private bool m_finished = false; + private bool m_createItem = false; + private AgentAssetTransactions m_userTransactions; + private bool m_storeLocal; + private bool m_dumpAssetToFile; + + public AssetXferUploader(AgentAssetTransactions transactions, bool dumpAssetToFile) + { + m_userTransactions = transactions; + m_dumpAssetToFile = dumpAssetToFile; + } + + /// + /// Process transfer data received from the client. + /// + /// + /// + /// + /// True if the transfer is complete, false otherwise or if the xferID was not valid + public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) + { + if (XferID == xferID) + { + if (Asset.Data.Length > 1) + { + byte[] destinationArray = new byte[Asset.Data.Length + data.Length]; + Array.Copy(Asset.Data, 0, destinationArray, 0, Asset.Data.Length); + Array.Copy(data, 0, destinationArray, Asset.Data.Length, data.Length); + Asset.Data = destinationArray; + } + else + { + byte[] buffer2 = new byte[data.Length - 4]; + Array.Copy(data, 4, buffer2, 0, data.Length - 4); + Asset.Data = buffer2; + } + ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket(); + newPack.XferID.ID = xferID; + newPack.XferID.Packet = packetID; + ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); + if ((packetID & 0x80000000) != 0) + { + SendCompleteMessage(); + return true; + } + } + + return false; + } + + /// + /// Initialise asset transfer from the client + /// + /// + /// + /// + /// True if the transfer is complete, false otherwise + public bool Initialise(IClientAPI remoteClient, LLUUID assetID, LLUUID transaction, sbyte type, byte[] data, + bool storeLocal, bool tempFile) + { + ourClient = remoteClient; + Asset = new AssetBase(); + Asset.FullID = assetID; + Asset.InvType = type; + Asset.Type = type; + Asset.Data = data; + Asset.Name = "blank"; + Asset.Description = "empty"; + Asset.Local = storeLocal; + Asset.Temporary = tempFile; + + TransactionID = transaction; + m_storeLocal = storeLocal; + if (Asset.Data.Length > 2) + { + SendCompleteMessage(); + return true; + } + else + { + RequestStartXfer(); + } + + return false; + } + + protected void RequestStartXfer() + { + UploadComplete = false; + XferID = Util.GetNextXferID(); + RequestXferPacket newPack = new RequestXferPacket(); + newPack.XferID.ID = XferID; + newPack.XferID.VFileType = Asset.Type; + newPack.XferID.VFileID = Asset.FullID; + newPack.XferID.FilePath = 0; + newPack.XferID.Filename = new byte[0]; + ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); + } + + protected void SendCompleteMessage() + { + UploadComplete = true; + AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); + newPack.AssetBlock.Type = Asset.Type; + newPack.AssetBlock.Success = true; + newPack.AssetBlock.UUID = Asset.FullID; + ourClient.OutPacket(newPack, ThrottleOutPacketType.Asset); + m_finished = true; + if (m_createItem) + { + DoCreateItem(); + } + else if (m_storeLocal) + { + m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset); + } + + // Console.WriteLine("upload complete "+ this.TransactionID); + + if (m_dumpAssetToFile) + { + DateTime now = DateTime.Now; + string filename = + String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", now.Year, now.Month, now.Day, + now.Hour, now.Minute, now.Second, Asset.Name, Asset.Type); + SaveAssetToFile(filename, Asset.Data); + } + } + + ///Left this in and commented in case there are unforseen issues + //private void SaveAssetToFile(string filename, byte[] data) + //{ + // FileStream fs = File.Create(filename); + // BinaryWriter bw = new BinaryWriter(fs); + // bw.Write(data); + // bw.Close(); + // fs.Close(); + //} + private void SaveAssetToFile(string filename, byte[] data) + { + string assetPath = "UserAssets"; + if (!Directory.Exists(assetPath)) + { + Directory.CreateDirectory(assetPath); + } + FileStream fs = File.Create(Path.Combine(assetPath, filename)); + BinaryWriter bw = new BinaryWriter(fs); + bw.Write(data); + bw.Close(); + fs.Close(); + } + + public void RequestCreateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + if (TransactionID == transactionID) + { + InventFolder = folderID; + m_name = name; + m_description = description; + this.type = type; + this.invType = invType; + nextPerm = nextOwnerMask; + Asset.Name = name; + Asset.Description = description; + Asset.Type = type; + Asset.InvType = invType; + m_createItem = true; + if (m_finished) + { + DoCreateItem(); + } + } + } + + public void RequestUpdateInventoryItem(IClientAPI remoteClient, LLUUID transactionID, + InventoryItemBase item) + { + if (TransactionID == transactionID) + { + CachedUserInfo userInfo = + m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails( + remoteClient.AgentId); + + if (userInfo != null) + { + LLUUID assetID = LLUUID.Combine(transactionID, remoteClient.SecureSessionId); + + AssetBase asset + = m_userTransactions.Manager.MyScene.CommsManager.AssetCache.GetAsset( + assetID, (item.assetType == (int) AssetType.Texture ? true : false)); + + if (asset == null) + { + asset = m_userTransactions.GetTransactionAsset(transactionID); + } + + if (asset != null && asset.FullID == assetID) + { + asset.Name = item.inventoryName; + asset.Description = item.inventoryDescription; + asset.InvType = (sbyte) item.invType; + asset.Type = (sbyte) item.assetType; + item.assetID = asset.FullID; + + m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset); + } + + userInfo.UpdateItem(remoteClient.AgentId, item); + } + } + } + + private void DoCreateItem() + { + //really need to fix this call, if lbsa71 saw this he would die. + m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(Asset); + CachedUserInfo userInfo = + m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(ourClient.AgentId); + if (userInfo != null) + { + InventoryItemBase item = new InventoryItemBase(); + item.avatarID = ourClient.AgentId; + item.creatorsID = ourClient.AgentId; + item.inventoryID = LLUUID.Random(); + item.assetID = Asset.FullID; + item.inventoryDescription = m_description; + item.inventoryName = m_name; + item.assetType = type; + item.invType = invType; + item.parentFolderID = InventFolder; + item.inventoryBasePermissions = 2147483647; + item.inventoryCurrentPermissions = 2147483647; + item.inventoryNextPermissions = nextPerm; + + userInfo.AddItem(ourClient.AgentId, item); + ourClient.SendInventoryItemCreateUpdate(item); + } + } + + public AssetBase GetAssetData() + { + if (m_finished) + { + return Asset; + } + return null; + } + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/AppearanceTableMapper.cs b/trunk/OpenSim/Region/Environment/Modules/AppearanceTableMapper.cs new file mode 100644 index 0000000000..6a0eef19e2 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/AppearanceTableMapper.cs @@ -0,0 +1,244 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Framework; +using TribalMedia.Framework.Data; + +namespace OpenSim.Region.Environment.Modules +{ + public class AppearanceRowMapper : BaseRowMapper + { + + public AppearanceRowMapper(BaseSchema schema, AvatarAppearance obj) + : base(schema, obj) + { + } + } + + public class AppearanceTableMapper : BaseTableMapper + { + public AppearanceTableMapper(BaseDatabaseConnector database, string tableName) + : base(database, tableName) + { + BaseSchema rowMapperSchema = new BaseSchema(this); + m_schema = rowMapperSchema; + + m_keyFieldMapper = rowMapperSchema.AddMapping("UUID", + delegate(AppearanceRowMapper mapper) { return mapper.Object.ScenePresenceID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.ScenePresenceID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("Serial", + delegate(AppearanceRowMapper mapper) { return (uint)mapper.Object.WearablesSerial; }, + delegate(AppearanceRowMapper mapper, uint value) { mapper.Object.WearablesSerial = (int)value; }); + + rowMapperSchema.AddMapping("WearableItem0", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[0].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { + if (mapper.Object.Wearables == null) + { + mapper.Object.Wearables = new OpenSim.Framework.AvatarWearable[13]; + for (int i = 0; i < 13; i++) + { + mapper.Object.Wearables[i] = new AvatarWearable(); + } + } + mapper.Object.Wearables[0].ItemID = new libsecondlife.LLUUID(value.ToString()); + }); + + rowMapperSchema.AddMapping("WearableAsset0", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[0].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[0].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableItem1", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[1].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[1].ItemID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableAsset1", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[1].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[1].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableItem2", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[2].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[2].ItemID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableAsset2", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[2].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[2].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableItem3", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[3].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[3].ItemID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableAsset3", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[3].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[3].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableItem4", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[4].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[4].ItemID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableAsset4", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[4].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[4].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableItem5", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[5].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[5].ItemID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableAsset5", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[5].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[5].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableItem6", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[6].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[6].ItemID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableAsset6", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[6].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[6].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableItem7", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[7].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[7].ItemID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableAsset7", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[7].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[7].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableItem8", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[8].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[8].ItemID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableAsset8", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[8].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[8].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableItem9", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[9].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[9].ItemID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableAsset9", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[9].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[9].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableItem10", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[10].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[10].ItemID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableAsset10", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[10].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[10].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableItem11", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[11].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[11].ItemID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableAsset11", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[11].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[11].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableItem12", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[12].ItemID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) { mapper.Object.Wearables[12].ItemID = new libsecondlife.LLUUID(value.ToString()); }); + + rowMapperSchema.AddMapping("WearableAsset12", + delegate(AppearanceRowMapper mapper) { return mapper.Object.Wearables[12].AssetID.UUID; }, + delegate(AppearanceRowMapper mapper, Guid value) + { mapper.Object.Wearables[12].AssetID = new libsecondlife.LLUUID(value.ToString()); }); + + } + + public bool Add(Guid userID, AvatarAppearance appearance) + { + AppearanceRowMapper mapper = CreateRowMapper(appearance); + return Add(mapper); + } + + public bool Update(Guid userID, AvatarAppearance appearance) + { + AppearanceRowMapper mapper = CreateRowMapper(appearance); + return Update(appearance.ScenePresenceID.UUID, mapper); + } + + protected AppearanceRowMapper CreateRowMapper(AvatarAppearance appearance) + { + return new AppearanceRowMapper(m_schema, appearance); + } + + protected AppearanceRowMapper CreateRowMapper() + { + return CreateRowMapper(new AvatarAppearance()); + } + + protected AppearanceRowMapper FromReader(BaseDataReader reader, AvatarAppearance appearance) + { + AppearanceRowMapper mapper = CreateRowMapper(appearance); + mapper.FillObject(reader); + return mapper; + } + + public override AppearanceRowMapper FromReader(BaseDataReader reader) + { + AppearanceRowMapper mapper = CreateRowMapper(); + mapper.FillObject(reader); + return mapper; + } + + public bool TryGetValue(Guid presenceID, out AvatarAppearance val) + { + AppearanceRowMapper mapper; + if (TryGetValue(presenceID, out mapper)) + { + val = mapper.Object; + return true; + } + else + { + val = null; + return false; + } + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/AssetDownloadModule.cs b/trunk/OpenSim/Region/Environment/Modules/AssetDownloadModule.cs new file mode 100644 index 0000000000..54d5ad8215 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/AssetDownloadModule.cs @@ -0,0 +1,72 @@ +/* +* 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 Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class AssetDownloadModule : IRegionModule + { + private Scene m_scene; + + public AssetDownloadModule() + { + } + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_scene.EventManager.OnNewClient += NewClient; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "AssetDownloadModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public void NewClient(IClientAPI client) + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs b/trunk/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs new file mode 100644 index 0000000000..24afdb4dc7 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/AvatarFactoryModule.cs @@ -0,0 +1,339 @@ +/* +* 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; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Framework.Data; +using TribalMedia.Framework.Data; + +namespace OpenSim.Region.Environment.Modules +{ + public class AvatarFactoryModule : IAvatarFactory + { + private Scene m_scene = null; + private readonly Dictionary m_avatarsAppearance = new Dictionary(); + + private bool m_enablePersist = false; + private string m_connectionString; + private bool m_configured = false; + private BaseDatabaseConnector m_databaseMapper; + private AppearanceTableMapper m_appearanceMapper; + + private Dictionary m_fetchesInProgress = new Dictionary(); + private object m_syncLock = new object(); + + public bool TryGetAvatarAppearance(LLUUID avatarId, out AvatarAppearance appearance) + { + + //should only let one thread at a time do this part + EventWaitHandle waitHandle = null; + bool fetchInProgress = false; + lock (m_syncLock) + { + appearance = CheckCache(avatarId); + if (appearance != null) + { + return true; + } + + //not in cache so check to see if another thread is already fetching it + if (m_fetchesInProgress.TryGetValue(avatarId, out waitHandle)) + { + fetchInProgress = true; + } + else + { + fetchInProgress = false; + + //no thread already fetching this appearance, so add a wait handle to list + //for any following threads that want the same appearance + waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset); + m_fetchesInProgress.Add(avatarId, waitHandle); + } + } + + if (fetchInProgress) + { + waitHandle.WaitOne(); + appearance = CheckCache(avatarId); + if (appearance != null) + { + waitHandle = null; + return true; + } + else + { + waitHandle = null; + return false; + } + } + else + { + Thread.Sleep(5000); + + //this is the first thread to request this appearance + //so let it check the db and if not found then create a default appearance + //and add that to the cache + appearance = CheckDatabase(avatarId); + if (appearance != null) + { + //appearance has now been added to cache so lets pulse any waiting threads + lock (m_syncLock) + { + m_fetchesInProgress.Remove(avatarId); + waitHandle.Set(); + } + // waitHandle.Close(); + waitHandle = null; + return true; + } + + //not found a appearance for the user, so create a new default one + appearance = CreateDefault(avatarId); + if (appearance != null) + { + //update database + if (m_enablePersist) + { + m_appearanceMapper.Add(avatarId.UUID, appearance); + } + + //add appearance to dictionary cache + lock (m_avatarsAppearance) + { + m_avatarsAppearance[avatarId] = appearance; + } + + //appearance has now been added to cache so lets pulse any waiting threads + lock (m_syncLock) + { + m_fetchesInProgress.Remove(avatarId); + waitHandle.Set(); + } + // waitHandle.Close(); + waitHandle = null; + return true; + } + else + { + //something went wrong, so release the wait handle and remove it + //all waiting threads will fail to find cached appearance + //but its better for them to fail than wait for ever + lock (m_syncLock) + { + m_fetchesInProgress.Remove(avatarId); + waitHandle.Set(); + } + //waitHandle.Close(); + waitHandle = null; + return false; + } + } + } + + private AvatarAppearance CreateDefault(LLUUID avatarId) + { + AvatarAppearance appearance = null; + AvatarWearable[] wearables; + byte[] visualParams; + GetDefaultAvatarAppearance(out wearables, out visualParams); + appearance = new AvatarAppearance(avatarId, wearables, visualParams); + + return appearance; + } + + private AvatarAppearance CheckDatabase(LLUUID avatarId) + { + AvatarAppearance appearance = null; + if (m_enablePersist) + { + if (m_appearanceMapper.TryGetValue(avatarId.UUID, out appearance)) + { + appearance.VisualParams = GetDefaultVisualParams(); + appearance.TextureEntry = AvatarAppearance.GetDefaultTextureEntry(); + lock (m_avatarsAppearance) + { + m_avatarsAppearance[avatarId] = appearance; + } + } + } + return appearance; + } + + private AvatarAppearance CheckCache(LLUUID avatarId) + { + AvatarAppearance appearance = null; + lock (m_avatarsAppearance) + { + if (m_avatarsAppearance.ContainsKey(avatarId)) + { + appearance = m_avatarsAppearance[avatarId]; + } + } + return appearance; + } + + public void Initialise(Scene scene, IConfigSource source) + { + scene.RegisterModuleInterface(this); + scene.EventManager.OnNewClient += NewClient; + + if (m_scene == null) + { + m_scene = scene; + } + + if (!m_configured) + { + m_configured = true; + try + { + m_enablePersist = source.Configs["Startup"].GetBoolean("appearance_persist", false); + m_connectionString = source.Configs["Startup"].GetString("appearance_connection_string", ""); + } + catch (Exception) + { + } + if (m_enablePersist) + { + m_databaseMapper = new MySQLDatabaseMapper(m_connectionString); + m_appearanceMapper = new AppearanceTableMapper(m_databaseMapper, "AvatarAppearance"); + } + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "Default Avatar Factory"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public void NewClient(IClientAPI client) + { + client.OnAvatarNowWearing += AvatarIsWearing; + } + + public void RemoveClient(IClientAPI client) + { + // client.OnAvatarNowWearing -= AvatarIsWearing; + } + + public void AvatarIsWearing(Object sender, AvatarWearingArgs e) + { + IClientAPI clientView = (IClientAPI)sender; + CachedUserInfo profile = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(clientView.AgentId); + if (profile != null) + { + if (profile.RootFolder != null) + { + if (m_avatarsAppearance.ContainsKey(clientView.AgentId)) + { + AvatarAppearance avatAppearance = null; + lock (m_avatarsAppearance) + { + avatAppearance = m_avatarsAppearance[clientView.AgentId]; + } + + foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) + { + if (wear.Type < 13) + { + if (wear.ItemID == LLUUID.Zero) + { + avatAppearance.Wearables[wear.Type].ItemID = LLUUID.Zero; + avatAppearance.Wearables[wear.Type].AssetID = LLUUID.Zero; + + UpdateDatabase(clientView.AgentId, avatAppearance); + } + else + { + LLUUID assetId; + + InventoryItemBase baseItem = profile.RootFolder.HasItem(wear.ItemID); + if (baseItem != null) + { + assetId = baseItem.assetID; + avatAppearance.Wearables[wear.Type].AssetID = assetId; + avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID; + + UpdateDatabase(clientView.AgentId, avatAppearance); + } + } + } + } + } + } + } + } + + public void UpdateDatabase(LLUUID userID, AvatarAppearance avatAppearance) + { + if (m_enablePersist) + { + m_appearanceMapper.Update(userID.UUID, avatAppearance); + } + } + + public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams) + { + visualParams = GetDefaultVisualParams(); + wearables = AvatarWearable.DefaultWearables; + } + + private static byte[] GetDefaultVisualParams() + { + byte[] visualParams; + visualParams = new byte[218]; + for (int i = 0; i < 218; i++) + { + visualParams[i] = 100; + } + return visualParams; + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/AvatarProfilesModule.cs b/trunk/OpenSim/Region/Environment/Modules/AvatarProfilesModule.cs new file mode 100644 index 0000000000..66c9fd5563 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/AvatarProfilesModule.cs @@ -0,0 +1,94 @@ +/* +* 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 libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class AvatarProfilesModule : IRegionModule + { + private Scene m_scene; + + public AvatarProfilesModule() + { + } + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_scene.EventManager.OnNewClient += NewClient; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "AvatarProfilesModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public void NewClient(IClientAPI client) + { + client.OnRequestAvatarProperties += RequestAvatarProperty; + } + + public void RemoveClient(IClientAPI client) + { + client.OnRequestAvatarProperties -= RequestAvatarProperty; + } + + /// + /// + /// + /// + /// + public void RequestAvatarProperty(IClientAPI remoteClient, LLUUID avatarID) + { + string about = "OpenSim crash test dummy"; + string bornOn = "Before now"; + string flAbout = "First life? What is one of those? OpenSim is my life!"; + LLUUID partner = new LLUUID("11111111-1111-0000-0000-000100bba000"); + remoteClient.SendAvatarProperties(avatarID, about, bornOn, System.String.Empty, flAbout, 0, LLUUID.Zero, LLUUID.Zero, System.String.Empty, + partner); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs b/trunk/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs new file mode 100644 index 0000000000..d51936b223 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/BetaGridLikeMoneyModule.cs @@ -0,0 +1,318 @@ +/* +* 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 Nini.Config; +using System; +using System.Collections; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using libsecondlife; +using MoneyTransferArgs = OpenSim.Region.Environment.Scenes.EventManager.MoneyTransferArgs; + +namespace OpenSim.Region.Environment.Modules +{ + public class BetaGridLikeMoneyModule: IRegionModule + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private Dictionary m_scenel = new Dictionary(); + + private IConfigSource m_gConfig; + + private bool m_keepMoneyAcrossLogins = true; + + private int m_minFundsBeforeRefresh = 100; + + private int m_stipend = 1000; + + private bool m_enabled = true; + + + + private Dictionary m_KnownClientFunds = new Dictionary(); + + + + private bool gridmode = false; + + public void Initialise(Scene scene, IConfigSource config) + { + m_gConfig = config; + ReadConfigAndPopulate(); + + if (m_enabled) + { + lock (m_scenel) + { + + if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle)) + { + m_scenel[scene.RegionInfo.RegionHandle] = scene; + } + else + { + m_scenel.Add(scene.RegionInfo.RegionHandle, scene); + } + } + + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnMoneyTransfer += MoneyTransferAction; + scene.EventManager.OnClientClosed += ClientClosed; + } + } + private void ReadConfigAndPopulate() + { + IConfig startupConfig = m_gConfig.Configs["Startup"]; + gridmode = startupConfig.GetBoolean("gridmode", false); + m_enabled = (startupConfig.GetString("moneymodule", "BetaGridLikeMoneyModule") == "BetaGridLikeMoneyModule"); + + } + + private void OnNewClient(IClientAPI client) + { + // Here we check if we're in grid mode + // I imagine that the 'check balance' + // function for the client should be here or shortly after + + if (gridmode) + { + CheckExistAndRefreshFunds(client.AgentId); + } + else + { + CheckExistAndRefreshFunds(client.AgentId); + } + + // Subscribe to Money messages + client.OnMoneyBalanceRequest += SendMoneyBalance; + client.OnLogout += ClientClosed; + + } + + public void ClientClosed(LLUUID AgentID) + { + lock (m_KnownClientFunds) + { + if (!m_keepMoneyAcrossLogins) + m_KnownClientFunds.Remove(AgentID); + } + + } + + private void MoneyTransferAction (Object osender, MoneyTransferArgs e) + { + IClientAPI sender = null; + IClientAPI receiver = null; + + sender = LocateClientObject(e.sender); + if (sender != null) + { + + + receiver = LocateClientObject(e.reciever); + bool transactionresult = doMoneyTranfer(e.sender, e.reciever, e.amount); + + if (e.sender != e.reciever) + { + if (sender != null) + { + sender.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.sender)); + } + } + + if (receiver != null) + { + receiver.SendMoneyBalance(LLUUID.Random(), transactionresult, Helpers.StringToField(e.description), GetFundsForAgentID(e.reciever)); + } + + + } + else + { + m_log.Warn("[MONEY]: Potential Fraud Warning, got money transfer request for avatar that isn't in this simulator - Details; Sender:" + e.sender.ToString() + " Reciver: " + e.reciever.ToString() + " Amount: " + e.amount.ToString()); + } + } + + private bool doMoneyTranfer(LLUUID Sender, LLUUID Receiver, int amount) + { + bool result = false; + if (amount >= 0) + { + lock (m_KnownClientFunds) + { + // If we don't know about the sender, then the sender can't + // actually be here and therefore this is likely fraud or outdated. + if (m_KnownClientFunds.ContainsKey(Sender)) + { + // Does the sender have enough funds to give? + if (m_KnownClientFunds[Sender] >= amount) + { + // Subtract the funds from the senders account + m_KnownClientFunds[Sender] -= amount; + + // do we know about the receiver? + if (!m_KnownClientFunds.ContainsKey(Receiver)) + { + // Make a record for them so they get the updated balance when they login + CheckExistAndRefreshFunds(Receiver); + } + + //Add the amount to the Receiver's funds + m_KnownClientFunds[Receiver] += amount; + result = true; + } + else + { + // These below are redundant to make this clearer to read + result = false; + } + } + else + { + result = false; + } + } + } + return result; + } + + private IClientAPI LocateClientObject(LLUUID AgentID) + { + ScenePresence tPresence = null; + IClientAPI rclient = null; + + lock (m_scenel) + { + foreach (Scene _scene in m_scenel.Values) + { + tPresence = _scene.GetScenePresence(AgentID); + if (tPresence != null) + { + if (!tPresence.IsChildAgent) + { + rclient = tPresence.ControllingClient; + } + } + if (rclient != null) + { + return rclient; + } + } + + } + return null; + } + + public void ClientClosed(IClientAPI client) + { + ClientClosed(client.AgentId); + } + + public void SendMoneyBalance(IClientAPI client, LLUUID agentID, LLUUID SessionID, LLUUID TransactionID) + { + if (client.AgentId == agentID && client.SessionId == SessionID) + { + + int returnfunds = 0; + + try + { + returnfunds = GetFundsForAgentID(agentID); + } + catch (System.Exception e) + { + client.SendAlertMessage(e.Message + " "); + } + + client.SendMoneyBalance(TransactionID, true, new byte[0], returnfunds); + } + else + { + client.SendAlertMessage("Unable to send your money balance to you!"); + } + } + + private void CheckExistAndRefreshFunds(LLUUID agentID) + { + lock (m_KnownClientFunds) + { + if (!m_KnownClientFunds.ContainsKey(agentID)) + { + m_KnownClientFunds.Add(agentID, m_stipend); + } + else + { + if (m_KnownClientFunds[agentID] <= m_minFundsBeforeRefresh) + { + m_KnownClientFunds[agentID] = m_stipend; + } + } + } + } + private int GetFundsForAgentID(LLUUID AgentID) + { + int returnfunds = 0; + lock (m_KnownClientFunds) + { + if (m_KnownClientFunds.ContainsKey(AgentID)) + { + returnfunds = m_KnownClientFunds[AgentID]; + } + else + { + throw new Exception("Unable to get funds."); + } + } + return returnfunds; + } + + public void PostInitialise() + { + } + + + + public void Close() + { + } + + public string Name + { + get { return "BetaGridLikeMoneyModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + } + +} diff --git a/trunk/OpenSim/Region/Environment/Modules/ChatModule.cs b/trunk/OpenSim/Region/Environment/Modules/ChatModule.cs new file mode 100644 index 0000000000..a34bd96f1e --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/ChatModule.cs @@ -0,0 +1,815 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Net.Sockets; +using System.Text.RegularExpressions; +using System.Threading; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class ChatModule : IRegionModule, ISimChat + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private List m_scenes = new List(); + + private int m_whisperdistance = 10; + private int m_saydistance = 30; + private int m_shoutdistance = 100; + + private IRCChatModule m_irc = null; + + private string m_last_new_user = null; + private string m_last_leaving_user = null; + private string m_defaultzone = null; + internal object m_syncInit = new object(); + internal object m_syncLogout = new object(); + private Thread m_irc_connector=null; + + public void Initialise(Scene scene, IConfigSource config) + { + lock (m_syncInit) + { + // wrap this in a try block so that defaults will work if + // the config file doesn't specify otherwise. + try + { + m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); + m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); + m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); + } + catch (Exception) + { + } + try + { + m_defaultzone = config.Configs["IRC"].GetString("nick","Sim"); + } + catch (Exception) + { + } + + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + scene.EventManager.OnNewClient += NewClient; + scene.RegisterModuleInterface(this); + } + + // setup IRC Relay + if (m_irc == null) { m_irc = new IRCChatModule(config); } + if (m_irc_connector == null) { m_irc_connector = new Thread(IRCConnectRun); } + + } + } + + public void PostInitialise() + { + if (m_irc.Enabled) + { + try + { + //m_irc.Connect(m_scenes); + if (m_irc_connector == null) { m_irc_connector = new Thread(IRCConnectRun); } + if (!m_irc_connector.IsAlive) { m_irc_connector.Start(); } + } + catch (Exception ex) + { + } + + } + } + + public void Close() + { + m_irc.Close(); + } + + public string Name + { + get { return "ChatModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public void NewClient(IClientAPI client) + { + try + { + client.OnChatFromViewer += SimChat; + + if ((m_irc.Enabled) && (m_irc.Connected)) + { + string clientName = client.FirstName + " " + client.LastName; + // handles simple case. May not work for hundred connecting in per second. + // and the NewClients calles getting interleved + // but filters out multiple reports + if (clientName != m_last_new_user) + { + m_last_new_user = clientName; + string clientRegion = FindClientRegion(client.FirstName, client.LastName); + m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " in "+clientRegion); + } + } + client.OnLogout += ClientLoggedOut; + client.OnConnectionClosed += ClientLoggedOut; + //client.OnDisconnectUser += ClientLoggedOut; + client.OnLogout += ClientLoggedOut; + } + catch (Exception ex) + { + m_log.Error("[IRC]: NewClient exception trap:" + ex.ToString()); + } + } + + public void ClientLoggedOut(IClientAPI client) + { + lock (m_syncLogout) + { + try + { + if ((m_irc.Enabled) && (m_irc.Connected)) + { + string clientName = client.FirstName + " " + client.LastName; + string clientRegion = FindClientRegion(client.FirstName, client.LastName); + // handles simple case. May not work for hundred connecting in per second. + // and the NewClients calles getting interleved + // but filters out multiple reports + if (clientName != m_last_leaving_user) + { + m_last_leaving_user = clientName; + m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " left " + clientRegion); + m_log.Info("[IRC]: IRC watcher notices " + clientName + " left " + clientRegion); + } + } + } + catch (Exception ex) + { + m_log.Error("[IRC]: ClientLoggedOut exception trap:" + ex.ToString()); + } + } + + } + private void TrySendChatMessage(ScenePresence presence, LLVector3 fromPos, LLVector3 regionPos, + LLUUID fromAgentID, string fromName, ChatTypeEnum type, string message) + { + if (!presence.IsChildAgent) + { + LLVector3 fromRegionPos = fromPos + regionPos; + LLVector3 toRegionPos = presence.AbsolutePosition + regionPos; + int dis = Math.Abs((int) Util.GetDistanceTo(toRegionPos, fromRegionPos)); + + if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || + type == ChatTypeEnum.Say && dis > m_saydistance || + type == ChatTypeEnum.Shout && dis > m_shoutdistance) + { + return; + } + + // TODO: should change so the message is sent through the avatar rather than direct to the ClientView + presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, fromAgentID); + } + } + + public void SimChat(Object sender, ChatFromViewerArgs e) + { + // FROM: Sim TO: IRC + + ScenePresence avatar = null; + + //TODO: Move ForEachScenePresence and others into IScene. + Scene scene = (Scene) e.Scene; + + //TODO: Remove the need for this check + if (scene == null) + scene = m_scenes[0]; + + // Filled in since it's easier than rewriting right now. + LLVector3 fromPos = e.Position; + LLVector3 regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); + + string fromName = e.From; + string message = e.Message; + LLUUID fromAgentID = LLUUID.Zero; + + if (e.Sender != null) + { + avatar = scene.GetScenePresence(e.Sender.AgentId); + } + + if (avatar != null) + { + fromPos = avatar.AbsolutePosition; + regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); + fromName = avatar.Firstname + " " + avatar.Lastname; + fromAgentID = e.Sender.AgentId; + } + + // Try to reconnect to server if not connected + if ((m_irc.Enabled)&&(!m_irc.Connected)) + { + // In a non-blocking way. Eventually the connector will get it started + try + { + if (m_irc_connector == null) { m_irc_connector = new Thread(IRCConnectRun); } + if (!m_irc_connector.IsAlive) { m_irc_connector.Start(); } + } + catch (Exception ex) + { + } + } + + if (e.Message.Length > 0) + { + if (m_irc.Connected && (avatar != null)) // this is to keep objects from talking to IRC + { + m_irc.PrivMsg(fromName, scene.RegionInfo.RegionName, e.Message); + } + } + + if (e.Channel == 0) + { + foreach (Scene s in m_scenes) + { + s.ForEachScenePresence(delegate(ScenePresence presence) + { + TrySendChatMessage(presence, fromPos, regionPos, + fromAgentID, fromName, e.Type, message); + }); + } + } + } + + // if IRC is enabled then just keep trying using a monitor thread + public void IRCConnectRun() + { + while(true) + { + if ((m_irc.Enabled)&&(!m_irc.Connected)) + { + m_irc.Connect(m_scenes); + + } + Thread.Sleep(15000); + } + } + + public string FindClientRegion(string client_FirstName,string client_LastName) + { + string sourceRegion = null; + foreach (Scene s in m_scenes) + { + s.ForEachScenePresence(delegate(ScenePresence presence) + { + if ((presence.IsChildAgent==false) + &&(presence.Firstname==client_FirstName) + &&(presence.Lastname==client_LastName)) + { + sourceRegion = presence.Scene.RegionInfo.RegionName; + //sourceRegion= s.RegionInfo.RegionName; + } + }); + if (sourceRegion != null) return sourceRegion; + } + if (m_defaultzone == null) { m_defaultzone = "Sim"; } + return m_defaultzone; + } + } + + internal class IRCChatModule + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private string m_server = null; + private uint m_port = 6668; + private string m_user = "USER OpenSimBot 8 * :I'm a OpenSim to irc bot"; + private string m_nick = null; + private string m_basenick = null; + private string m_channel = null; + private string m_privmsgformat = "PRIVMSG {0} :<{1} in {2}>: {3}"; + + private NetworkStream m_stream; + private TcpClient m_tcp; + private StreamWriter m_writer; + private StreamReader m_reader; + + private Thread pingSender; + private Thread listener; + internal object m_syncConnect = new object(); + + private bool m_enabled = false; + private bool m_connected = false; + + private List m_scenes = null; + private List m_last_scenes = null; + + public IRCChatModule(IConfigSource config) + { + m_nick = "OSimBot" + Util.RandomClass.Next(1, 99); + m_tcp = null; + m_writer = null; + m_reader = null; + + // configuration in OpenSim.ini + // [IRC] + // server = chat.freenode.net + // nick = OSimBot_mysim + // ;username = USER OpenSimBot 8 * :I'm a OpenSim to irc bot + // ; username is the IRC command line sent + // ; USER * : + // channel = #opensim-regions + // port = 6667 + // ;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message + // ;for : : + // ;msgformat = "PRIVMSG {0} :<{1} in {2}>: {3}" + // ;for : - : + // ;msgformat = "PRIVMSG {0} : {3} - {1} of {2}" + // ;for : - from : + // ;msgformat = "PRIVMSG {0} : {3} - from {1}" + // Traps I/O disconnects so it does not crash the sim + // Trys to reconnect if disconnected and someone says something + // Tells IRC server "QUIT" when doing a close (just to be nice) + // Default port back to 6667 + + try + { + m_server = config.Configs["IRC"].GetString("server"); + m_nick = config.Configs["IRC"].GetString("nick"); + m_basenick = m_nick; + m_channel = config.Configs["IRC"].GetString("channel"); + m_port = (uint) config.Configs["IRC"].GetInt("port", (int) m_port); + m_user = config.Configs["IRC"].GetString("username", m_user); + m_privmsgformat = config.Configs["IRC"].GetString("msgformat", m_privmsgformat); + if (m_server != null && m_nick != null && m_channel != null) + { + m_nick = m_nick + Util.RandomClass.Next(1, 99); + m_enabled = true; + } + } + catch (Exception) + { + m_log.Info("[CHAT]: No IRC config information, skipping IRC bridge configuration"); + } + } + + public bool Connect(List scenes) + { + lock (m_syncConnect) + { + try + { + if (m_connected) return true; + m_scenes = scenes; + if (m_last_scenes == null) { m_last_scenes = scenes; } + + m_tcp = new TcpClient(m_server, (int)m_port); + m_log.Info("[IRC]: Connecting..."); + m_stream = m_tcp.GetStream(); + m_log.Info("[IRC]: Connected to " + m_server); + m_reader = new StreamReader(m_stream); + m_writer = new StreamWriter(m_stream); + + pingSender = new Thread(new ThreadStart(PingRun)); + pingSender.Start(); + + listener = new Thread(new ThreadStart(ListenerRun)); + listener.Start(); + + m_writer.WriteLine(m_user); + m_writer.Flush(); + m_writer.WriteLine("NICK " + m_nick); + m_writer.Flush(); + m_writer.WriteLine("JOIN " + m_channel); + m_writer.Flush(); + m_log.Info("[IRC]: Connection fully established"); + m_connected = true; + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + } + return m_connected; + } + } + + public bool Enabled + { + get { return m_enabled; } + } + + public bool Connected + { + get { return m_connected; } + } + + public string Nick + { + get { return m_nick; } + } + + public void Reconnect() + { + m_connected = false; + listener.Abort(); + pingSender.Abort(); + m_writer.Close(); + m_reader.Close(); + m_tcp.Close(); + if (m_enabled) { Connect(m_last_scenes); } + + } + + public void PrivMsg(string from, string region, string msg) + { + // One message to the IRC server + + try + { + if (m_privmsgformat == null) + { + m_writer.WriteLine("PRIVMSG {0} :<{1} in {2}>: {3}", m_channel, from, region, msg); + } + else + { + m_writer.WriteLine(m_privmsgformat, m_channel, from, region, msg); + } + m_writer.Flush(); + m_log.Info("[IRC]: PrivMsg " + from + " in " + region + " :" + msg); + } + catch (IOException) + { + m_log.Error("[IRC]: Disconnected from IRC server.(PrivMsg)"); + Reconnect(); + } + catch (Exception ex) + { + m_log.Error("[IRC]: PrivMsg exception trap:" + ex.ToString()); + } + } + + private Dictionary ExtractMsg(string input) + { + //examines IRC commands and extracts any private messages + // which will then be reboadcast in the Sim + + m_log.Info("[IRC]: ExtractMsg: " + input); + Dictionary result = null; + //string regex = @":(?\w*)!~(?\S*) PRIVMSG (?\S+) :(?.*)"; + string regex = @":(?\w*)!(?\S*) PRIVMSG (?\S+) :(?.*)"; + Regex RE = new Regex(regex, RegexOptions.Multiline); + MatchCollection matches = RE.Matches(input); + // Get some direct matches $1 $4 is a + if ((matches.Count == 1) && (matches[0].Groups.Count == 5)) + { + result = new Dictionary(); + result.Add("nick", matches[0].Groups[1].Value); + result.Add("user", matches[0].Groups[2].Value); + result.Add("channel", matches[0].Groups[3].Value); + result.Add("msg", matches[0].Groups[4].Value); + } + else + { + m_log.Info("[IRC]: Number of matches: " + matches.Count); + if (matches.Count > 0) + { + m_log.Info("[IRC]: Number of groups: " + matches[0].Groups.Count); + } + } + return result; + } + + public void PingRun() + { + // IRC keep alive thread + // send PING ever 15 seconds + while (true) + { + try + { + if (m_connected == true) + { + m_writer.WriteLine("PING :" + m_server); + m_writer.Flush(); + Thread.Sleep(15000); + } + } + catch (IOException) + { + m_log.Error("[IRC]: Disconnected from IRC server.(PingRun)"); + Reconnect(); + } + catch (Exception ex) + { + m_log.Error("[IRC]: PingRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace); + } + } + } + + public void ListenerRun() + { + string inputLine; + LLVector3 pos = new LLVector3(128, 128, 20); + while (true) + { + try + { + while ((m_connected == true) && ((inputLine = m_reader.ReadLine()) != null)) + { + // Console.WriteLine(inputLine); + if (inputLine.Contains(m_channel)) + { + Dictionary data = ExtractMsg(inputLine); + // Any chat ??? + if (data != null) + { + foreach (Scene m_scene in m_scenes) + { + m_scene.ForEachScenePresence(delegate(ScenePresence avatar) + { + if (!avatar.IsChildAgent) + { + avatar.ControllingClient.SendChatMessage( + Helpers.StringToField(data["msg"]), 255, + pos, data["nick"], + LLUUID.Zero); + } + }); + } + + + } + else + { + // Was an command from the IRC server + ProcessIRCCommand(inputLine); + } + } + else + { + // Was an command from the IRC server + ProcessIRCCommand(inputLine); + } + Thread.Sleep(150); + } + } + catch (IOException) + { + m_log.Error("[IRC]: ListenerRun IOException. Disconnected from IRC server ??? (ListenerRun)"); + Reconnect(); + } + catch (Exception ex) + { + m_log.Error("[IRC]: ListenerRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace); + } + } + } + + public void BroadcastSim(string message,string sender) + { + LLVector3 pos = new LLVector3(128, 128, 20); + try + { + foreach (Scene m_scene in m_scenes) + { + m_scene.ForEachScenePresence(delegate(ScenePresence avatar) + { + if (!avatar.IsChildAgent) + { + avatar.ControllingClient.SendChatMessage( + Helpers.StringToField(message), 255, + pos, sender, + LLUUID.Zero); + } + }); + } + } + catch (Exception ex) // IRC gate should not crash Sim + { + m_log.Error("[IRC]: BroadcastSim Exception Trap:" + ex.ToString() + "\n" + ex.StackTrace); + + } + } + + public enum ErrorReplies + { + NotRegistered = 451, // ":You have not registered" + NicknameInUse = 433 // " :Nickname is already in use" + } + + public enum Replies + { + MotdStart = 375, // ":- Message of the day - " + Motd = 372, // ":- " + EndOfMotd = 376 // ":End of /MOTD command" + } + + public void ProcessIRCCommand(string command) + { + //m_log.Info("[IRC]: ProcessIRCCommand:" + command); + + string[] commArgs = new string[command.Split(' ').Length]; + string c_server = m_server; + + commArgs = command.Split(' '); + if (commArgs[0].Substring(0, 1) == ":") + { + commArgs[0] = commArgs[0].Remove(0, 1); + } + + if (commArgs[1] == "002") + { + // fetch the correct servername + // ex: irc.freenode.net -> brown.freenode.net/kornbluth.freenode.net/... + // irc.bluewin.ch -> irc1.bluewin.ch/irc2.bluewin.ch + + c_server = (commArgs[6].Split('['))[0]; + m_server = c_server; + } + + if (commArgs[0] == "ERROR") + { + m_log.Error("[IRC]: IRC SERVER ERROR:" + command); + } + + if (commArgs[0] == "PING") + { + string p_reply = ""; + + for (int i = 1; i < commArgs.Length; i++) + { + p_reply += commArgs[i] + " "; + } + + m_writer.WriteLine("PONG " + p_reply); + m_writer.Flush(); + + } + else if (commArgs[0] == c_server) + { + // server message + try + { + Int32 commandCode = Int32.Parse(commArgs[1]); + switch (commandCode) + { + case (int)ErrorReplies.NicknameInUse: + // Gen a new name + m_nick = m_basenick + Util.RandomClass.Next(1, 99); + m_log.Error("[IRC]: IRC SERVER reports NicknameInUse, trying " + m_nick); + // Retry + m_writer.WriteLine("NICK " + m_nick); + m_writer.Flush(); + m_writer.WriteLine("JOIN " + m_channel); + m_writer.Flush(); + break; + case (int)ErrorReplies.NotRegistered: + break; + case (int)Replies.EndOfMotd: + break; + } + } + catch (Exception ex) + { + } + + } + else + { + // Normal message + string commAct = commArgs[1]; + switch (commAct) + { + case "JOIN": eventIrcJoin(commArgs); break; + case "PART": eventIrcPart(commArgs); break; + case "MODE": eventIrcMode(commArgs); break; + case "NICK": eventIrcNickChange(commArgs); break; + case "KICK": eventIrcKick(commArgs); break; + case "QUIT": eventIrcQuit(commArgs); break; + case "PONG": break; // that's nice + } + + + } + } + + public void eventIrcJoin(string[] commArgs) + { + string IrcChannel = commArgs[2]; + string IrcUser = commArgs[0].Split('!')[0]; + BroadcastSim(IrcUser + " is joining " + IrcChannel, m_nick); + + } + + public void eventIrcPart(string[] commArgs) + { + string IrcChannel = commArgs[2]; + string IrcUser = commArgs[0].Split('!')[0]; + BroadcastSim(IrcUser + " is parting " + IrcChannel, m_nick); + + } + public void eventIrcMode(string[] commArgs) + { + string IrcChannel = commArgs[2]; + string IrcUser = commArgs[0].Split('!')[0]; + string UserMode = ""; + for (int i = 3; i < commArgs.Length; i++) + { + UserMode += commArgs[i] + " "; + } + + if (UserMode.Substring(0, 1) == ":") + { + UserMode = UserMode.Remove(0, 1); + } + + } + public void eventIrcNickChange(string[] commArgs) + { + string UserOldNick = commArgs[0].Split('!')[0]; + string UserNewNick = commArgs[2].Remove(0, 1); + BroadcastSim(UserOldNick + " changed their nick to " + UserNewNick, m_nick); + + } + + public void eventIrcKick(string[] commArgs) + { + string UserKicker = commArgs[0].Split('!')[0]; + string UserKicked = commArgs[3]; + string IrcChannel = commArgs[2]; + string KickMessage = ""; + for (int i = 4; i < commArgs.Length; i++) + { + KickMessage += commArgs[i] + " "; + } + BroadcastSim(UserKicker + " kicked " + UserKicked +" on "+IrcChannel+" saying "+KickMessage, m_nick); + if (UserKicked == m_nick) + { + BroadcastSim("Hey, that was me!!!", m_nick); + + } + } + + public void eventIrcQuit(string[] commArgs) + { + string IrcUser = commArgs[0].Split('!')[0]; + string QuitMessage = ""; + + for (int i = 2; i < commArgs.Length; i++) + { + QuitMessage += commArgs[i] + " "; + } + BroadcastSim(IrcUser + " quits saying " + QuitMessage, m_nick); + + } + + + public void Close() + { + m_connected = false; + m_writer.WriteLine("QUIT :" + m_nick + " to " + m_channel + " wormhole with " + m_server + " closing"); + m_writer.Flush(); + listener.Abort(); + pingSender.Abort(); + m_writer.Close(); + m_reader.Close(); + m_tcp.Close(); + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/DynamicTextureModule.cs b/trunk/OpenSim/Region/Environment/Modules/DynamicTextureModule.cs new file mode 100644 index 0000000000..4b747acf5e --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/DynamicTextureModule.cs @@ -0,0 +1,190 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class DynamicTextureModule : IRegionModule, IDynamicTextureManager + { + private Dictionary RegisteredScenes = new Dictionary(); + + private Dictionary RenderPlugins = + new Dictionary(); + + private Dictionary Updaters = new Dictionary(); + + public void Initialise(Scene scene, IConfigSource config) + { + if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) + { + RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); + scene.RegisterModuleInterface(this); + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "DynamicTextureModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public void RegisterRender(string handleType, IDynamicTextureRender render) + { + if (!RenderPlugins.ContainsKey(handleType)) + { + RenderPlugins.Add(handleType, render); + } + } + + public void ReturnData(LLUUID id, byte[] data) + { + if (Updaters.ContainsKey(id)) + { + DynamicTextureUpdater updater = Updaters[id]; + if (RegisteredScenes.ContainsKey(updater.SimUUID)) + { + Scene scene = RegisteredScenes[updater.SimUUID]; + updater.DataReceived(data, scene); + } + } + } + + public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url, + string extraParams, int updateTimer) + { + if (RenderPlugins.ContainsKey(contentType)) + { + //Console.WriteLine("dynamic texture being created: " + url + " of type " + contentType); + + DynamicTextureUpdater updater = new DynamicTextureUpdater(); + updater.SimUUID = simID; + updater.PrimID = primID; + updater.ContentType = contentType; + updater.Url = url; + updater.UpdateTimer = updateTimer; + updater.UpdaterID = LLUUID.Random(); + updater.Params = extraParams; + + if (!Updaters.ContainsKey(updater.UpdaterID)) + { + Updaters.Add(updater.UpdaterID, updater); + } + + RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams); + return updater.UpdaterID; + } + return LLUUID.Zero; + } + + public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data, + string extraParams, int updateTimer) + { + if (RenderPlugins.ContainsKey(contentType)) + { + DynamicTextureUpdater updater = new DynamicTextureUpdater(); + updater.SimUUID = simID; + updater.PrimID = primID; + updater.ContentType = contentType; + updater.BodyData = data; + updater.UpdateTimer = updateTimer; + updater.UpdaterID = LLUUID.Random(); + updater.Params = extraParams; + + if (!Updaters.ContainsKey(updater.UpdaterID)) + { + Updaters.Add(updater.UpdaterID, updater); + } + + RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); + return updater.UpdaterID; + } + return LLUUID.Zero; + } + + public class DynamicTextureUpdater + { + public LLUUID SimUUID; + public LLUUID UpdaterID; + public string ContentType; + public string Url; + public string BodyData; + public LLUUID PrimID; + public int UpdateTimer; + public LLUUID LastAssetID; + public string Params; + + public DynamicTextureUpdater() + { + LastAssetID = LLUUID.Zero; + UpdateTimer = 0; + BodyData = null; + } + + public void DataReceived(byte[] data, Scene scene) + { + //TODO delete the last asset(data), if it was a dynamic texture + byte[] assetData = new byte[data.Length]; + Array.Copy(data, assetData, data.Length); + AssetBase asset = new AssetBase(); + asset.FullID = LLUUID.Random(); + asset.Data = assetData; + asset.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000); + asset.Type = 0; + asset.Description = "dynamic image"; + asset.Local = false; + asset.Temporary = true; + scene.AssetCache.AddAsset(asset); + + LastAssetID = asset.FullID; + + SceneObjectPart part = scene.GetSceneObjectPart(PrimID); + part.Shape.Textures = new LLObject.TextureEntry(asset.FullID); + part.ScheduleFullUpdate(); + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Modules/EmailModule.cs b/trunk/OpenSim/Region/Environment/Modules/EmailModule.cs new file mode 100644 index 0000000000..046a46cb51 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/EmailModule.cs @@ -0,0 +1,34 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.Environment.Modules +{ + internal class EmailModule + { + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Modules/FriendsModule.cs b/trunk/OpenSim/Region/Environment/Modules/FriendsModule.cs new file mode 100644 index 0000000000..3c324a42d5 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/FriendsModule.cs @@ -0,0 +1,222 @@ +/* +* 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 Nini.Config; +using System; +using System.Collections; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using libsecondlife; + +namespace OpenSim.Region.Environment.Modules +{ + public class FriendsModule : IRegionModule + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + + Dictionary m_pendingFriendRequests = new Dictionary(); + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnGridInstantMessageToFriendsModule += OnGridInstantMessage; + } + + private void OnNewClient(IClientAPI client) + { + // All friends establishment protocol goes over instant message + // There's no way to send a message from the sim + // to a user to 'add a friend' without causing dialog box spam + // + // The base set of friends are added when the user signs on in their XMLRPC response + // Generated by LoginService. The friends are retreived from the database by the UserManager + + // Subscribe to instant messages + client.OnInstantMessage += OnInstantMessage; + client.OnApproveFriendRequest += OnApprovedFriendRequest; + client.OnDenyFriendRequest += OnDenyFriendRequest; + client.OnTerminateFriendship += OnTerminateFriendship; + + + } + + private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID, + LLUUID fromAgentSession, LLUUID toAgentID, + LLUUID imSessionID, uint timestamp, string fromAgentName, + string message, byte dialog, bool fromGroup, byte offline, + uint ParentEstateID, LLVector3 Position, LLUUID RegionID, + byte[] binaryBucket) + { + // Friend Requests go by Instant Message.. using the dialog param + // https://wiki.secondlife.com/wiki/ImprovedInstantMessage + + // 38 == Offer friendship + if (dialog == (byte)38) + { + LLUUID friendTransactionID = LLUUID.Random(); + + m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); + + m_log.Info("[FRIEND]: 38 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message); + GridInstantMessage msg = new GridInstantMessage(); + msg.fromAgentID = fromAgentID.UUID; + msg.fromAgentSession = fromAgentSession.UUID; + msg.toAgentID = toAgentID.UUID; + msg.imSessionID = friendTransactionID.UUID; // This is the item we're mucking with here + m_log.Info("[FRIEND]: Filling Session: " + msg.imSessionID.ToString()); + msg.timestamp = timestamp; + if (client != null) + { + msg.fromAgentName = client.FirstName + " " + client.LastName;// fromAgentName; + } + else + { + msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it + } + msg.message = message; + msg.dialog = dialog; + msg.fromGroup = fromGroup; + msg.offline = offline; + msg.ParentEstateID = ParentEstateID; + msg.Position = new sLLVector3(Position); + msg.RegionID = RegionID.UUID; + msg.binaryBucket = binaryBucket; + m_scene.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); + } + + // 39 == Accept Friendship + if (dialog == (byte)39) + { + m_log.Info("[FRIEND]: 39 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message); + } + + // 40 == Decline Friendship + if (dialog == (byte)40) + { + m_log.Info("[FRIEND]: 40 - From:" + fromAgentID.ToString() + " To: " + toAgentID.ToString() + " Session:" + imSessionID.ToString() + " Message:" + message); + } + } + + private void OnApprovedFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List callingCardFolders) + { + if (m_pendingFriendRequests.ContainsKey(transactionID)) + { + // Found Pending Friend Request with that Transaction.. + + // Compose response to other agent. + GridInstantMessage msg = new GridInstantMessage(); + msg.toAgentID = m_pendingFriendRequests[transactionID].UUID; + msg.fromAgentID = agentID.UUID; + msg.fromAgentName = client.FirstName + " " + client.LastName; + msg.fromAgentSession = client.SessionId.UUID; + msg.fromGroup = false; + msg.imSessionID = transactionID.UUID; + msg.message = agentID.UUID.ToString(); + msg.ParentEstateID = 0; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.RegionID = m_scene.RegionInfo.RegionID.UUID; + msg.dialog = (byte)39;// Approved friend request + msg.Position = new sLLVector3(); + msg.offline = (byte)0; + msg.binaryBucket = new byte[0]; + m_scene.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); + m_scene.StoreAddFriendship(m_pendingFriendRequests[transactionID], agentID, (uint)1); + m_pendingFriendRequests.Remove(transactionID); + + // TODO: Inform agent that the friend is online + } + } + + private void OnDenyFriendRequest(IClientAPI client, LLUUID agentID, LLUUID transactionID, List callingCardFolders) + { + if (m_pendingFriendRequests.ContainsKey(transactionID)) + { + // Found Pending Friend Request with that Transaction.. + + // Compose response to other agent. + GridInstantMessage msg = new GridInstantMessage(); + msg.toAgentID = m_pendingFriendRequests[transactionID].UUID; + msg.fromAgentID = agentID.UUID; + msg.fromAgentName = client.FirstName + " " + client.LastName; + msg.fromAgentSession = client.SessionId.UUID; + msg.fromGroup = false; + msg.imSessionID = transactionID.UUID; + msg.message = agentID.UUID.ToString(); + msg.ParentEstateID = 0; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.RegionID = m_scene.RegionInfo.RegionID.UUID; + msg.dialog = (byte)40;// Deny friend request + msg.Position = new sLLVector3(); + msg.offline = (byte)0; + msg.binaryBucket = new byte[0]; + m_scene.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); + m_pendingFriendRequests.Remove(transactionID); + } + } + + private void OnTerminateFriendship(IClientAPI client, LLUUID agent, LLUUID exfriendID) + { + m_scene.StoreRemoveFriendship(agent, exfriendID); + // TODO: Inform the client that the ExFriend is offline + } + + private void OnGridInstantMessage(GridInstantMessage msg) + { + // Trigger the above event handler + OnInstantMessage(null,new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession), + new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName, + msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID, + new LLVector3(msg.Position.x, msg.Position.y, msg.Position.z), new LLUUID(msg.RegionID), + msg.binaryBucket); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "FriendsModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/GroupsModule.cs b/trunk/OpenSim/Region/Environment/Modules/GroupsModule.cs new file mode 100644 index 0000000000..50e9a39aef --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/GroupsModule.cs @@ -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 Nini.Config; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class GroupsModule : IRegionModule + { + private Scene m_scene; + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "GroupsModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Modules/InstantMessageModule.cs b/trunk/OpenSim/Region/Environment/Modules/InstantMessageModule.cs new file mode 100644 index 0000000000..e0b31386e4 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/InstantMessageModule.cs @@ -0,0 +1,127 @@ +/* +* 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.Collections.Generic; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class InstantMessageModule : IRegionModule + { + private List m_scenes = new List(); + + public void Initialise(Scene scene, IConfigSource config) + { + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnGridInstantMessageToIMModule += OnGridInstantMessage; + } + } + + private void OnNewClient(IClientAPI client) + { + client.OnInstantMessage += OnInstantMessage; + } + + private void OnInstantMessage(IClientAPI client,LLUUID fromAgentID, + LLUUID fromAgentSession, LLUUID toAgentID, + LLUUID imSessionID, uint timestamp, string fromAgentName, + string message, byte dialog, bool fromGroup, byte offline, + uint ParentEstateID, LLVector3 Position, LLUUID RegionID, + byte[] binaryBucket) + { + bool FriendDialog = ((dialog == (byte)38) || (dialog == (byte)39) || (dialog == (byte)40)); + + // IM dialogs need to be pre-processed and have their sessionID filled by the server + // so the sim can match the transaction on the return packet. + + // Don't send a Friend Dialog IM with a LLUUID.Zero session. + if (!(FriendDialog && imSessionID == LLUUID.Zero)) + { + foreach (Scene scene in m_scenes) + { + if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) + { + // Local message + ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; + if (!user.IsChildAgent) + { + user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message, + toAgentID, imSessionID, fromAgentName, dialog, + timestamp); + // Message sent + return; + } + } + } + } + + // Still here, try send via Grid + // TODO + } + + // Trusty OSG1 called method. This method also gets called from the FriendsModule + // Turns out the sim has to send an instant message to the user to get it to show an accepted friend. + + private void OnGridInstantMessage(GridInstantMessage msg) + { + // Trigger the above event handler + OnInstantMessage(null,new LLUUID(msg.fromAgentID), new LLUUID(msg.fromAgentSession), + new LLUUID(msg.toAgentID), new LLUUID(msg.imSessionID), msg.timestamp, msg.fromAgentName, + msg.message, msg.dialog, msg.fromGroup, msg.offline, msg.ParentEstateID, + new LLVector3(msg.Position.x,msg.Position.y,msg.Position.z), new LLUUID(msg.RegionID), + msg.binaryBucket); + + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "InstantMessageModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/InventoryModule.cs b/trunk/OpenSim/Region/Environment/Modules/InventoryModule.cs new file mode 100644 index 0000000000..e2ad0d5b43 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/InventoryModule.cs @@ -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 Nini.Config; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class InventoryModule : IRegionModule + { + private Scene m_scene; + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "InventoryModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Modules/LoadImageURLModule.cs b/trunk/OpenSim/Region/Environment/Modules/LoadImageURLModule.cs new file mode 100644 index 0000000000..0548b9d2d2 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/LoadImageURLModule.cs @@ -0,0 +1,177 @@ +/* +* 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; +using System.Drawing; +using System.IO; +using System.Net; +using libsecondlife; +using Nini.Config; +using OpenJPEGNet; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class LoadImageURLModule : IRegionModule, IDynamicTextureRender + { + private string m_name = "LoadImageURL"; + private IDynamicTextureManager m_textureManager; + private Scene m_scene; + + public void Initialise(Scene scene, IConfigSource config) + { + if (m_scene == null) + { + m_scene = scene; + } + } + + public void PostInitialise() + { + m_textureManager = m_scene.RequestModuleInterface(); + m_textureManager.RegisterRender(GetContentType(), this); + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public string GetName() + { + return m_name; + } + + public string GetContentType() + { + return ("image"); + } + + public bool SupportsAsynchronous() + { + return true; + } + + public byte[] ConvertUrl(string url, string extraParams) + { + return null; + } + + public byte[] ConvertStream(Stream data, string extraParams) + { + return null; + } + + public bool AsyncConvertUrl(LLUUID id, string url, string extraParams) + { + MakeHttpRequest(url, id); + return true; + } + + public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams) + { + return false; + } + + private void MakeHttpRequest(string url, LLUUID requestID) + { + WebRequest request = HttpWebRequest.Create(url); + RequestState state = new RequestState((HttpWebRequest) request, requestID); + IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state); + + TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1)); + state.TimeOfRequest = (int) t.TotalSeconds; + } + + private void HttpRequestReturn(IAsyncResult result) + { + RequestState state = (RequestState) result.AsyncState; + WebRequest request = (WebRequest) state.Request; + HttpWebResponse response = (HttpWebResponse) request.EndGetResponse(result); + if (response.StatusCode == HttpStatusCode.OK) + { + Bitmap image = new Bitmap(response.GetResponseStream()); + Size newsize; + + // TODO: make this a bit less hard coded + if ((image.Height < 64) && (image.Width < 64)) + { + newsize = new Size(32, 32); + } + else if ((image.Height < 128) && (image.Width < 128)) + { + newsize = new Size(64, 64); + } + else if ((image.Height <256) && (image.Width < 256)) + { + newsize = new Size(128, 128); + } + else if ((image.Height < 512 && image.Width < 512)) + { + newsize = new Size(256, 256); + } + else if ((image.Height < 1024 && image.Width < 1024)) + { + newsize = new Size(512, 512); + } + else + { + newsize = new Size(1024,1024); + } + + Bitmap resize = new Bitmap(image, newsize); + byte[] imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); + + m_textureManager.ReturnData(state.RequestID, imageJ2000); + } + } + + public class RequestState + { + public HttpWebRequest Request = null; + public LLUUID RequestID = LLUUID.Zero; + public int TimeOfRequest = 0; + + public RequestState(HttpWebRequest request, LLUUID requestID) + { + Request = request; + RequestID = requestID; + } + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs b/trunk/OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs new file mode 100644 index 0000000000..e3de13b82b --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs @@ -0,0 +1,343 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text; +using System.Threading; +using libsecondlife; +using Nini.Config; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +/***************************************************** + * + * ScriptsHttpRequests + * + * Implements the llHttpRequest and http_response + * callback. + * + * Some stuff was already in LSLLongCmdHandler, and then + * there was this file with a stub class in it. So, + * I am moving some of the objects and functions out of + * LSLLongCmdHandler, such as the HttpRequestClass, the + * start and stop methods, and setting up pending and + * completed queues. These are processed in the + * LSLLongCmdHandler polling loop. Similiar to the + * XMLRPCModule, since that seems to work. + * + * //TODO + * + * This probably needs some throttling mechanism but + * its wide open right now. This applies to both + * number of requests and data volume. + * + * Linden puts all kinds of header fields in the requests. + * Not doing any of that: + * User-Agent + * X-SecondLife-Shard + * X-SecondLife-Object-Name + * X-SecondLife-Object-Key + * X-SecondLife-Region + * X-SecondLife-Local-Position + * X-SecondLife-Local-Velocity + * X-SecondLife-Local-Rotation + * X-SecondLife-Owner-Name + * X-SecondLife-Owner-Key + * + * HTTPS support + * + * Configurable timeout? + * Configurable max repsonse size? + * Configurable + * + * **************************************************/ + +namespace OpenSim.Region.Environment.Modules +{ + public class ScriptHTTPRequests : IRegionModule, IHttpRequests + { + private Scene m_scene; + private Queue rpcQueue = new Queue(); + private object HttpListLock = new object(); + private string m_name = "HttpScriptRequests"; + private int httpTimeout = 30000; + + // + private Dictionary m_pendingRequests; + + public ScriptHTTPRequests() + { + } + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + + m_scene.RegisterModuleInterface(this); + + m_pendingRequests = new Dictionary(); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public LLUUID MakeHttpRequest(string url, string parameters, string body) + { + return LLUUID.Zero; + } + + public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List parameters, string body) + { + LLUUID reqID = LLUUID.Random(); + HttpRequestClass htc = new HttpRequestClass(); + + // Parameters are expected in {key, value, ... , key, value} + if (parameters != null) + { + string[] parms = parameters.ToArray(); + for (int i = 0; i < parms.Length/2; i += 2) + { + switch (Int32.Parse(parms[i])) + { + case HttpRequestClass.HTTP_METHOD: + + htc.httpMethod = parms[i + 1]; + break; + + case HttpRequestClass.HTTP_MIMETYPE: + + htc.httpMIMEType = parms[i + 1]; + break; + + case HttpRequestClass.HTTP_BODY_MAXLENGTH: + + // TODO implement me + break; + + case HttpRequestClass.HTTP_VERIFY_CERT: + + // TODO implement me + break; + } + } + } + + htc.localID = localID; + htc.itemID = itemID; + htc.url = url; + htc.reqID = reqID; + htc.httpTimeout = httpTimeout; + htc.outbound_body = body; + + lock (HttpListLock) + { + m_pendingRequests.Add(reqID, htc); + } + + htc.process(); + + return reqID; + } + + public void StopHttpRequest(uint m_localID, LLUUID m_itemID) + { + lock (HttpListLock) + { + HttpRequestClass tmpReq; + if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) + { + tmpReq.Stop(); + m_pendingRequests.Remove(m_itemID); + } + } + } + + /* + * TODO + * Not sure how important ordering is is here - the next first + * one completed in the list is returned, based soley on its list + * position, not the order in which the request was started or + * finsihed. I thought about setting up a queue for this, but + * it will need some refactoring and this works 'enough' right now + */ + + public HttpRequestClass GetNextCompletedRequest() + { + lock (HttpListLock) + { + foreach (LLUUID luid in m_pendingRequests.Keys) + { + HttpRequestClass tmpReq; + + if (m_pendingRequests.TryGetValue(luid, out tmpReq)) + { + if (tmpReq.finished) + { + m_pendingRequests.Remove(luid); + return tmpReq; + } + } + } + } + return null; + } + } + + // + // HTTP REAQUEST + // This class was originally in LSLLongCmdHandler + // + // TODO: setter/getter methods, maybe pass some in + // constructor + // + + public class HttpRequestClass + { + // Constants for parameters + public const int HTTP_METHOD = 0; + public const int HTTP_MIMETYPE = 1; + public const int HTTP_BODY_MAXLENGTH = 2; + public const int HTTP_VERIFY_CERT = 3; + + // Parameter members and default values + public string httpMethod = "GET"; + public string httpMIMEType = "text/plain;charset=utf-8"; + public int httpBodyMaxLen = 2048; // not implemented + public bool httpVerifyCert = true; // not implemented + + // Request info + public uint localID; + public LLUUID itemID; + public LLUUID reqID; + public int httpTimeout; + public string url; + public string outbound_body; + public DateTime next; + public int status; + public bool finished; + public List response_metadata; + public string response_body; + public HttpWebRequest request; + private Thread httpThread; + + public void process() + { + httpThread = new Thread(SendRequest); + httpThread.Name = "HttpRequestThread"; + httpThread.Priority = ThreadPriority.BelowNormal; + httpThread.IsBackground = true; + httpThread.Start(); + } + + /* + * TODO: More work on the response codes. Right now + * returning 200 for success or 499 for exception + */ + + public void SendRequest() + { + HttpWebResponse response = null; + StringBuilder sb = new StringBuilder(); + byte[] buf = new byte[8192]; + string tempString = null; + int count = 0; + + try + { + request = (HttpWebRequest) + WebRequest.Create(url); + request.Method = httpMethod; + request.ContentType = httpMIMEType; + + request.Timeout = httpTimeout; + // execute the request + response = (HttpWebResponse) + request.GetResponse(); + + Stream resStream = response.GetResponseStream(); + + do + { + // fill the buffer with data + count = resStream.Read(buf, 0, buf.Length); + + // make sure we read some data + if (count != 0) + { + // translate from bytes to ASCII text + tempString = Encoding.ASCII.GetString(buf, 0, count); + + // continue building the string + sb.Append(tempString); + } + } while (count > 0); // any more data to read? + + response_body = sb.ToString(); + } + catch (Exception e) + { + status = 499; + response_body = e.Message; + finished = true; + return; + } + + status = 200; + finished = true; + } + + public void Stop() + { + try + { + httpThread.Abort(); + } + catch (Exception) + { + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Modules/SunModule.cs b/trunk/OpenSim/Region/Environment/Modules/SunModule.cs new file mode 100644 index 0000000000..d2572c00fc --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/SunModule.cs @@ -0,0 +1,194 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class SunModule : IRegionModule + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private const double m_real_day = 24.0; + private const int m_default_frame = 100; + private int m_frame_mod; + private double m_day_length; + private int m_dilation; + private int m_frame; + private long m_start; + + private Scene m_scene; + + public void Initialise(Scene scene, IConfigSource config) + { + m_start = DateTime.Now.Ticks; + m_frame = 0; + + // Just in case they don't have the stanzas + try + { + m_day_length = config.Configs["Sun"].GetDouble("day_length", m_real_day); + m_frame_mod = config.Configs["Sun"].GetInt("frame_rate", m_default_frame); + } + catch (Exception) + { + m_day_length = m_real_day; + m_frame_mod = m_default_frame; + } + + m_dilation = (int) (m_real_day/m_day_length); + m_scene = scene; + scene.EventManager.OnFrame += SunUpdate; + scene.EventManager.OnNewClient += SunToClient; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "SunModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public void SunToClient(IClientAPI client) + { + client.SendSunPos(SunPos(HourOfTheDay()), new LLVector3(0, 0.0f, 10.0f)); + } + + public void SunUpdate() + { + if (m_frame < m_frame_mod) + { + m_frame++; + return; + } + // m_log.Info("[SUN]: I've got an update {0} => {1}", m_scene.RegionsInfo.RegionName, HourOfTheDay()); + List avatars = m_scene.GetAvatars(); + foreach (ScenePresence avatar in avatars) + { + avatar.ControllingClient.SendSunPos(SunPos(HourOfTheDay()), new LLVector3(0, 0.0f, 10.0f)); + } + m_frame = 0; + } + + // Hour of the Day figures out the hour of the day as a float. + // The intent here is that we seed hour of the day with real + // time when the simulator starts, then run time forward + // faster based on time dilation factor. This means that + // ticks don't get out of hand + private double HourOfTheDay() + { + long m_addticks = (DateTime.Now.Ticks - m_start)*m_dilation; + DateTime dt = new DateTime(m_start + m_addticks); + return (double) dt.Hour + ((double) dt.Minute/60.0); + } + + private LLVector3 SunPos(double hour) + { + // now we have our radian position + double rad = (hour/m_real_day)*2*Math.PI - (Math.PI/2.0); + double z = Math.Sin(rad); + double x = Math.Cos(rad); + return new LLVector3((float) x, 0f, (float) z); + } + + // TODO: clear this out. This is here so that I remember to + // figure out if we need those other packet fields that I've + // left out so far + // + // public void SendViewerTime(int phase) + // { + // Console.WriteLine("SunPhase: {0}", phase); + // SimulatorViewerTimeMessagePacket viewertime = new SimulatorViewerTimeMessagePacket(); + // //viewertime.TimeInfo.SecPerDay = 86400; + // // viewertime.TimeInfo.SecPerYear = 31536000; + // viewertime.TimeInfo.SecPerDay = 1000; + // viewertime.TimeInfo.SecPerYear = 365000; + // viewertime.TimeInfo.SunPhase = 1; + // int sunPhase = (phase + 2)/2; + // if ((sunPhase < 6) || (sunPhase > 36)) + // { + // viewertime.TimeInfo.SunDirection = new LLVector3(0f, 0.8f, -0.8f); + // Console.WriteLine("sending night"); + // } + // else + // { + // if (sunPhase < 12) + // { + // sunPhase = 12; + // } + // sunPhase = sunPhase - 12; + // + // float yValue = 0.1f*(sunPhase); + // Console.WriteLine("Computed SunPhase: {0}, yValue: {1}", sunPhase, yValue); + // if (yValue > 1.2f) + // { + // yValue = yValue - 1.2f; + // } + // if (yValue > 1) + // { + // yValue = 1; + // } + // if (yValue < 0) + // { + // yValue = 0; + // } + // if (sunPhase < 14) + // { + // yValue = 1 - yValue; + // } + // if (sunPhase < 12) + // { + // yValue *= -1; + // } + // viewertime.TimeInfo.SunDirection = new LLVector3(0f, yValue, 0.3f); + // Console.WriteLine("sending sun update " + yValue); + // } + // viewertime.TimeInfo.SunAngVelocity = new LLVector3(0, 0.0f, 10.0f); + // viewertime.TimeInfo.UsecSinceStart = (ulong) Util.UnixTimeSinceEpoch(); + // // OutPacket(viewertime); + // } + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/TeleportModule.cs b/trunk/OpenSim/Region/Environment/Modules/TeleportModule.cs new file mode 100644 index 0000000000..77f8db2f97 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/TeleportModule.cs @@ -0,0 +1,34 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.Environment.Modules +{ + internal class TeleportModule + { + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs b/trunk/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs new file mode 100644 index 0000000000..4e937bb87a --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/Terrain/TerrainModule.cs @@ -0,0 +1,132 @@ +/* +* 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 Nini.Config; +using System; +using System.Collections; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Modules; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using libsecondlife; + +namespace OpenSim.Region.Environment.Modules.Terrain +{ + /// + /// A new version of the old Channel class, simplified + /// + public class TerrainChannel : ITerrainChannel + { + private double[,] map; + + public int Width + { + get { return map.GetLength(0); } + } + + public int Height + { + get { return map.GetLength(1); } + } + + public TerrainChannel Copy() + { + TerrainChannel copy = new TerrainChannel(false); + copy.map = (double[,])this.map.Clone(); + + return copy; + } + + public double this[int x, int y] + { + get + { + return map[x, y]; + } + set + { + map[x, y] = value; + } + } + + public TerrainChannel() + { + map = new double[Constants.RegionSize, Constants.RegionSize]; + } + + public TerrainChannel(bool createMap) + { + if (createMap) + map = new double[Constants.RegionSize, Constants.RegionSize]; + } + + public TerrainChannel(int w, int h) + { + map = new double[w, h]; + } + } + + public class TerrainModule : IRegionModule + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + Scene m_scene; + + private IConfigSource m_gConfig; + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_gConfig = config; + } + + public void Close() + { + + } + + public string Name + { + get { return "TerrainModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public void PostInitialise() + { + + } + + } + +} diff --git a/trunk/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs b/trunk/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs new file mode 100644 index 0000000000..cf558e009e --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs @@ -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 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; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using libsecondlife.Packets; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + //this is a first attempt, to start breaking the mess thats called the assetcache up. + // basically this should be the texture sending (to clients) code moved out of assetcache + //and some small clean up + public class TextureDownloadModule : IRegionModule + { + private static readonly log4net.ILog m_log + = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + private List m_scenes = new List(); + + private readonly BlockingQueue m_queueSenders = new BlockingQueue(); + + private readonly Dictionary m_userTextureServices = + new Dictionary(); + + private Thread m_thread; + + public TextureDownloadModule() + { + } + + public void Initialise(Scene scene, IConfigSource config) + { + if (m_scene == null) + { + //Console.WriteLine("Creating Texture download module"); + m_thread = new Thread(new ThreadStart(ProcessTextureSenders)); + m_thread.IsBackground = true; + m_thread.Start(); + } + + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + m_scene = scene; + m_scene.EventManager.OnNewClient += NewClient; + m_scene.EventManager.OnRemovePresence += EventManager_OnRemovePresence; + } + } + + private void EventManager_OnRemovePresence(LLUUID agentId) + { + UserTextureDownloadService textureService; + + lock (m_userTextureServices) + { + if( m_userTextureServices.TryGetValue( agentId, out textureService )) + { + textureService.Close(); + + m_userTextureServices.Remove(agentId); + } + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "TextureDownloadModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public void NewClient(IClientAPI client) + { + client.OnRequestTexture += TextureRequest; + } + + private bool TryGetUserTextureService(LLUUID userID, out UserTextureDownloadService textureService) + { + lock (m_userTextureServices) + { + if (m_userTextureServices.TryGetValue(userID, out textureService)) + { + return true; + } + + textureService = new UserTextureDownloadService(m_scene, m_queueSenders); + m_userTextureServices.Add(userID, textureService); + return true; + } + } + + public void TextureRequest(Object sender, TextureRequestArgs e) + { + IClientAPI client = (IClientAPI) sender; + UserTextureDownloadService textureService; + if (TryGetUserTextureService(client.AgentId, out textureService)) + { + textureService.HandleTextureRequest(client, e); + m_scene.AddPendingDownloads(1); + } + + } + + public void ProcessTextureSenders() + { + TextureSender sender = null; + + while (true) + { + sender = m_queueSenders.Dequeue(); + + if (sender.Cancel) + { + TextureSent(sender); + + sender.Cancel = false; + } + else + { + bool finished = sender.SendTexturePacket(); + if (finished) + { + TextureSent(sender); + } + else + { + m_queueSenders.Enqueue(sender); + } + } + + // Make sure that any sender we currently have can get garbage collected + sender = null; + + //m_log.InfoFormat("[TEXTURE DOWNLOAD] Texture sender queue size: {0}", m_queueSenders.Count()); + } + } + + private void TextureSent(TextureSender sender) + { + sender.Sending = false; + m_scene.AddPendingDownloads(-1); + } + + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/TextureSender.cs b/trunk/OpenSim/Region/Environment/Modules/TextureSender.cs new file mode 100644 index 0000000000..08da59130c --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/TextureSender.cs @@ -0,0 +1,166 @@ +/* +* 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; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Environment.Modules +{ + public class TextureSender + { + private static readonly log4net.ILog m_log + = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public int counter = 0; + private AssetBase m_asset; + public long DataPointer = 0; + public int NumPackets = 0; + public int PacketCounter = 0; + public bool Cancel = false; + public bool ImageLoaded = false; + + public bool Sending = false; + + public IClientAPI RequestUser; + public LLUUID RequestedAssetID; + public int RequestedDiscardLevel = -1; + public uint StartPacketNumber = 0; + + // private int m_sentDiscardLevel = -1; + + public TextureSender(IClientAPI client, LLUUID textureID, int discardLevel, uint packetNumber) + { + RequestUser = client; + RequestedAssetID = textureID; + RequestedDiscardLevel = discardLevel; + StartPacketNumber = packetNumber; + } + + public void TextureReceived(AssetBase asset) + { + m_asset = asset; + NumPackets = CalculateNumPackets(asset.Data.Length); + PacketCounter = (int) StartPacketNumber; + ImageLoaded = true; + } + + public void UpdateRequest(int discardLevel, uint packetNumber) + { + RequestedDiscardLevel = discardLevel; + StartPacketNumber = packetNumber; + PacketCounter = (int) StartPacketNumber; + } + + public bool SendTexturePacket() + { + SendPacket(); + counter++; + if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) || + ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets/(RequestedDiscardLevel + 1))))) + { + return true; + } + return false; + } + + private void SendPacket() + { + if (PacketCounter <= NumPackets) + { + if (PacketCounter == 0) + { + if (NumPackets == 0) + { + ImageDataPacket im = new ImageDataPacket(); + im.Header.Reliable = false; + im.ImageID.Packets = 1; + im.ImageID.ID = m_asset.FullID; + im.ImageID.Size = (uint) m_asset.Data.Length; + im.ImageData.Data = m_asset.Data; + im.ImageID.Codec = 2; + RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); + PacketCounter++; + } + else + { + ImageDataPacket im = new ImageDataPacket(); + im.Header.Reliable = false; + im.ImageID.Packets = (ushort) (NumPackets); + im.ImageID.ID = m_asset.FullID; + im.ImageID.Size = (uint) m_asset.Data.Length; + im.ImageData.Data = new byte[600]; + Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600); + im.ImageID.Codec = 2; + RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); + PacketCounter++; + } + } + else + { + ImagePacketPacket im = new ImagePacketPacket(); + im.Header.Reliable = false; + im.ImageID.Packet = (ushort) (PacketCounter); + im.ImageID.ID = m_asset.FullID; + int size = m_asset.Data.Length - 600 - (1000*(PacketCounter - 1)); + if (size > 1000) size = 1000; + im.ImageData.Data = new byte[size]; + try + { + Array.Copy(m_asset.Data, 600 + (1000*(PacketCounter - 1)), im.ImageData.Data, 0, size); + } + catch (ArgumentOutOfRangeException) + { + m_log.Error("[TEXTURE]: Unable to separate texture into multiple packets: Array bounds failure on asset:" + + m_asset.FullID.ToString() ); + return; + } + RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); + PacketCounter++; + } + } + } + + private int CalculateNumPackets(int length) + { + int numPackets = 0; + + if (length > 600) + { + //over 600 bytes so split up file + int restData = (length - 600); + int restPackets = ((restData + 999)/1000); + numPackets = restPackets; + } + + return numPackets; + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/TreePopulatorModule.cs b/trunk/OpenSim/Region/Environment/Modules/TreePopulatorModule.cs new file mode 100644 index 0000000000..725ce0d6b4 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/TreePopulatorModule.cs @@ -0,0 +1,246 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + /// + /// Version 2.0 - Very hacky compared to the original. Will fix original and release as 0.3 later. + /// + public class TreePopulatorModule : IRegionModule + { + private Scene m_scene; + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private List m_trees; + + public double m_tree_density = 50.0; // Aim for this many per region + public double m_tree_updates = 1000.0; // MS between updates + + public void Initialise(Scene scene, IConfigSource config) + { + try + { + m_tree_density = config.Configs["Trees"].GetDouble("tree_density", m_tree_density); + } + catch (Exception) + { } + + m_trees = new List(); + m_scene = scene; + + m_scene.EventManager.OnPluginConsole += new EventManager.OnPluginConsoleDelegate(EventManager_OnPluginConsole); + + System.Timers.Timer CalculateTrees = new System.Timers.Timer(m_tree_updates); + CalculateTrees.Elapsed += new System.Timers.ElapsedEventHandler(CalculateTrees_Elapsed); + CalculateTrees.Start(); + m_log.Debug("[TREES]: Initialised tree module"); + } + + void EventManager_OnPluginConsole(string[] args) + { + if (args[0] == "tree") + { + m_log.Debug("[TREES]: New tree planting"); + CreateTree(new LLVector3(128.0f, 128.0f, 0.0f)); + } + } + + void growTrees() + { + foreach (LLUUID tree in m_trees) + { + if (m_scene.Entities.ContainsKey(tree)) + { + SceneObjectPart s_tree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; + + // 100 seconds to grow 1m + s_tree.Scale += new LLVector3(0.1f, 0.1f, 0.1f); + s_tree.SendFullUpdateToAllClients(); + //s_tree.ScheduleTerseUpdate(); + } + else + { + m_trees.Remove(tree); + } + } + } + + void seedTrees() + { + foreach (LLUUID tree in m_trees) + { + if (m_scene.Entities.ContainsKey(tree)) + { + SceneObjectPart s_tree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; + + if (s_tree.Scale.X > 0.5) + { + if (Util.RandomClass.NextDouble() > 0.75) + { + SpawnChild(s_tree); + } + } + + } + else + { + m_trees.Remove(tree); + } + } + } + + void killTrees() + { + foreach (LLUUID tree in m_trees) + { + double killLikelyhood = 0.0; + + if (m_scene.Entities.ContainsKey(tree)) + { + SceneObjectPart selectedTree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; + double selectedTreeScale = Math.Sqrt(Math.Pow(selectedTree.Scale.X, 2) + + Math.Pow(selectedTree.Scale.Y, 2) + + Math.Pow(selectedTree.Scale.Z, 2)); + + foreach (LLUUID picktree in m_trees) + { + if (picktree != tree) + { + SceneObjectPart pickedTree = ((SceneObjectGroup)m_scene.Entities[picktree]).RootPart; + + double pickedTreeScale = Math.Sqrt(Math.Pow(pickedTree.Scale.X, 2) + + Math.Pow(pickedTree.Scale.Y, 2) + + Math.Pow(pickedTree.Scale.Z, 2)); + + double pickedTreeDistance = Math.Sqrt(Math.Pow(Math.Abs(pickedTree.AbsolutePosition.X - selectedTree.AbsolutePosition.X), 2) + + Math.Pow(Math.Abs(pickedTree.AbsolutePosition.Y - selectedTree.AbsolutePosition.Y), 2) + + Math.Pow(Math.Abs(pickedTree.AbsolutePosition.Z - selectedTree.AbsolutePosition.Z), 2)); + + killLikelyhood += (selectedTreeScale / (pickedTreeScale * pickedTreeDistance)) * 0.1; + } + } + + if (Util.RandomClass.NextDouble() < killLikelyhood) + { + m_scene.RemoveEntity(selectedTree.ParentGroup); + m_trees.Remove(selectedTree.ParentGroup.UUID); + + m_scene.ForEachClient(delegate(IClientAPI controller) + { + controller.SendKillObject(m_scene.RegionInfo.RegionHandle, + selectedTree.LocalID); + }); + + break; + } + else + { + selectedTree.SetText(killLikelyhood.ToString(), new Axiom.Math.Vector3(1.0f, 1.0f, 1.0f), 1.0); + } + } + else + { + m_trees.Remove(tree); + } + } + } + + private void SpawnChild(SceneObjectPart s_tree) + { + LLVector3 position = new LLVector3(); + + position.X = s_tree.AbsolutePosition.X + (1 * (-1 * Util.RandomClass.Next(1))); + if (position.X > 255) + position.X = 255; + if (position.X < 0) + position.X = 0; + position.Y = s_tree.AbsolutePosition.Y + (1 * (-1 * Util.RandomClass.Next(1))); + if (position.Y > 255) + position.Y = 255; + if (position.Y < 0) + position.Y = 0; + + double randX = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); + double randY = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); + + position.X += (float)randX; + position.Y += (float)randY; + + CreateTree(position); + } + + private void CreateTree(LLVector3 position) + { + position.Z = (float)m_scene.Terrain.heightmap.Get((int)position.X, (int)position.Y); + + SceneObjectGroup tree = + m_scene.AddTree(new LLVector3(0.1f, 0.1f, 0.1f), + LLQuaternion.Identity, + position, + Tree.Cypress1, + false); + + m_trees.Add(tree.UUID); + tree.SendGroupFullUpdate(); + } + + void CalculateTrees_Elapsed(object sender, System.Timers.ElapsedEventArgs e) + { + growTrees(); + seedTrees(); + killTrees(); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "TreePopulatorModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs b/trunk/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs new file mode 100644 index 0000000000..32bc7c3f13 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs @@ -0,0 +1,143 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class UserTextureDownloadService + { + private static readonly log4net.ILog m_log + = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private readonly Dictionary m_textureSenders = new Dictionary(); + private readonly BlockingQueue m_sharedSendersQueue; + private readonly Scene m_scene; + + public UserTextureDownloadService(Scene scene, BlockingQueue sharedQueue) + { + m_scene = scene; + m_sharedSendersQueue = sharedQueue; + } + + public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e) + { + TextureSender textureSender; + + //TODO: should be working out the data size/ number of packets to be sent for each discard level + if ((e.DiscardLevel >= 0) || (e.Priority != 0)) + { + lock (m_textureSenders) + { + if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) + { + textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber); + + if ((textureSender.ImageLoaded) && + (textureSender.Sending == false)) + { + EnqueueTextureSender(textureSender); + } + } + else + { + TextureSender requestHandler = + new TextureSender(client, e.RequestedAssetID, e.DiscardLevel, e.PacketNumber); + m_textureSenders.Add(e.RequestedAssetID, requestHandler); + m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback); + } + } + } + else + { + lock (m_textureSenders) + { + if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) + { + textureSender.Cancel = true; + } + } + } + } + + public void TextureCallback(LLUUID textureID, AssetBase asset) + { + lock (m_textureSenders) + { + TextureSender textureSender; + + if (m_textureSenders.TryGetValue(textureID, out textureSender)) + { + if (!textureSender.ImageLoaded) + { + textureSender.TextureReceived(asset); + EnqueueTextureSender(textureSender); + } + + //m_log.InfoFormat("[TEXTURE SENDER] Removing texture sender with uuid {0}", textureID); + m_textureSenders.Remove(textureID); + //m_log.InfoFormat("[TEXTURE SENDER] Current texture senders in dictionary: {0}", m_textureSenders.Count); + } + else + { + throw new Exception("Got a texture with no sender object to handle it, this shouldn't happen"); + } + } + } + + private void EnqueueTextureSender(TextureSender textureSender) + { + textureSender.Cancel = false; + textureSender.Sending = true; + textureSender.counter = 0; + + if (!m_sharedSendersQueue.Contains(textureSender)) + { + m_sharedSendersQueue.Enqueue(textureSender); + } + } + + internal void Close() + { + lock (m_textureSenders) + { + foreach( TextureSender textureSender in m_textureSenders.Values ) + { + textureSender.Cancel = true; + } + + m_textureSenders.Clear(); + } + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/WorldCommModule.cs b/trunk/OpenSim/Region/Environment/Modules/WorldCommModule.cs new file mode 100644 index 0000000000..a426eda580 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/WorldCommModule.cs @@ -0,0 +1,515 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +/***************************************************** + * + * WorldCommModule + * + * + * Holding place for world comms - basically llListen + * function implementation. + * + * lLListen(integer channel, string name, key id, string msg) + * The name, id, and msg arguments specify the filtering + * criteria. You can pass the empty string + * (or NULL_KEY for id) for these to set a completely + * open filter; this causes the listen() event handler to be + * invoked for all chat on the channel. To listen only + * for chat spoken by a specific object or avatar, + * specify the name and/or id arguments. To listen + * only for a specific command, specify the + * (case-sensitive) msg argument. If msg is not empty, + * listener will only hear strings which are exactly equal + * to msg. You can also use all the arguments to establish + * the most restrictive filtering criteria. + * + * It might be useful for each listener to maintain a message + * digest, with a list of recent messages by UUID. This can + * be used to prevent in-world repeater loops. However, the + * linden functions do not have this capability, so for now + * thats the way it works. + * + * **************************************************/ + +namespace OpenSim.Region.Environment.Modules +{ + public class WorldCommModule : IRegionModule, IWorldComm + { + private Scene m_scene; + private object CommListLock = new object(); + private object ListLock = new object(); + private string m_name = "WorldCommModule"; + private ListenerManager m_listenerManager; + private Queue m_pending; + + public WorldCommModule() + { + } + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_scene.RegisterModuleInterface(this); + m_listenerManager = new ListenerManager(); + m_pending = new Queue(); + m_scene.EventManager.OnNewClient += NewClient; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public void NewClient(IClientAPI client) + { + client.OnChatFromViewer += DeliverClientMessage; + } + + private void DeliverClientMessage(Object sender, ChatFromViewerArgs e) + { + DeliverMessage(e.Sender.AgentId.ToString(), + e.Type, e.Channel, + e.Sender.FirstName + " " + e.Sender.LastName, + e.Message); + } + + public int Listen(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) + { + return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); + } + + public void ListenControl(int handle, int active) + { + if (active == 1) + m_listenerManager.Activate(handle); + else if (active == 0) + m_listenerManager.Dectivate(handle); + } + + public void ListenRemove(int handle) + { + m_listenerManager.Remove(handle); + } + + public void DeleteListener(LLUUID itemID) + { + lock (ListLock) + { + m_listenerManager.DeleteListener(itemID); + } + + } + + // This method scans nearby objects and determines if they are listeners, + // and if so if this message fits the filter. If it does, then + // enqueue the message for delivery to the objects listen event handler. + // Objects that do an llSay have their messages delivered here, and for + // nearby avatars, the SimChat function is used. + public void DeliverMessage(string sourceItemID, ChatTypeEnum type, int channel, string name, string msg) + { + SceneObjectPart source = null; + ScenePresence avatar = null; + + source = m_scene.GetSceneObjectPart(new LLUUID(sourceItemID)); + if (source == null) + { + avatar = m_scene.GetScenePresence(new LLUUID(sourceItemID)); + } + if ((avatar != null) || (source != null)) + { + // Loop through the objects in the scene + // If they are in proximity, then if they are + // listeners, if so add them to the pending queue + + foreach (LLUUID eb in m_scene.Entities.Keys) + { + EntityBase sPart; + + m_scene.Entities.TryGetValue(eb, out sPart); + + // Dont process if this message is from itself! + if (eb.ToString().Equals(sourceItemID) || + sPart.UUID.ToString().Equals(sourceItemID)) + continue; + + double dis = 0; + + if (source != null) + dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition); + else + dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition); + + switch (type) + { + case ChatTypeEnum.Whisper: + + if ((dis < 10) && (dis > -10)) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + m_pending.Enqueue(isListener); + } + } + break; + + case ChatTypeEnum.Say: + + if ((dis < 30) && (dis > -30)) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + m_pending.Enqueue(isListener); + } + } + break; + + case ChatTypeEnum.Shout: + if ((dis < 100) && (dis > -100)) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + m_pending.Enqueue(isListener); + } + } + break; + + case ChatTypeEnum.Broadcast: + ListenerInfo isListen = + m_listenerManager.IsListenerMatch(sourceItemID, eb, channel, name, msg); + if (isListen != null) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + m_pending.Enqueue(isListener); + } + } + break; + } + } + ; + } + } + + public bool HasMessages() + { + return (m_pending.Count > 0); + } + + public ListenerInfo GetNextMessage() + { + ListenerInfo li = null; + + lock (CommListLock) + { + li = m_pending.Dequeue(); + } + + return li; + } + } + + // hostID: the ID of the ScenePart + // itemID: the ID of the script host engine + // localID: local ID of host engine + public class ListenerManager + { + private Dictionary m_listeners; + private object ListenersLock = new object(); + private int m_MaxListeners = 100; + + public ListenerManager() + { + m_listeners = new Dictionary(); + } + + public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, + string msg) + { + if (m_listeners.Count < m_MaxListeners) + { + ListenerInfo isListener = IsListenerMatch(LLUUID.Zero.ToString(), itemID, channel, name, msg); + + if (isListener == null) + { + int newHandle = GetNewHandle(); + + if (newHandle > -1) + { + ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg); + + lock (ListenersLock) + { + m_listeners.Add(newHandle, li); + } + + return newHandle; + } + } + } + + return -1; + } + + public void Remove(int handle) + { + m_listeners.Remove(handle); + } + + public void DeleteListener(LLUUID itemID) + { + foreach (ListenerInfo li in m_listeners.Values) + { + if (li.GetItemID().Equals(itemID)) + { + Remove(li.GetHandle()); + return; + } + } + } + + private int GetNewHandle() + { + for (int i = 0; i < int.MaxValue - 1; i++) + { + if (!m_listeners.ContainsKey(i)) + return i; + } + + return -1; + } + + public bool IsListener(LLUUID hostID) + { + foreach (ListenerInfo li in m_listeners.Values) + { + if (li.GetHostID().Equals(hostID)) + return true; + } + + return false; + } + + public void Activate(int handle) + { + ListenerInfo li; + + if (m_listeners.TryGetValue(handle, out li)) + { + li.Activate(); + } + } + + public void Dectivate(int handle) + { + ListenerInfo li; + + if (m_listeners.TryGetValue(handle, out li)) + { + li.Deactivate(); + } + } + + // Theres probably a more clever and efficient way to + // do this, maybe with regex. + public ListenerInfo IsListenerMatch(string sourceItemID, LLUUID listenerKey, int channel, string name, + string msg) + { + bool isMatch = true; + + foreach (ListenerInfo li in m_listeners.Values) + { + if (li.GetHostID().Equals(listenerKey)) + { + if (li.IsActive()) + { + if (channel == li.GetChannel()) + { + if ((li.GetID().ToString().Length > 0) && + (!li.GetID().Equals(LLUUID.Zero))) + { + if (!li.GetID().ToString().Equals(sourceItemID)) + { + isMatch = false; + } + } + if (isMatch && (li.GetName().Length > 0)) + { + if (li.GetName().Equals(name)) + { + isMatch = false; + } + } + if (isMatch) + { + return new ListenerInfo( + li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(), + li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID) + ); + } + } + } + } + } + return null; + } + } + + public class ListenerInfo + { + private LLUUID m_itemID; // ID of the host script engine + private LLUUID m_hostID; // ID of the host/scene part + private LLUUID m_sourceItemID; // ID of the scenePart or avatar source of the message + private int m_channel; // Channel + private int m_handle; // Assigned handle of this listener + private uint m_localID; // Local ID from script engine + private string m_name; // Object name to filter messages from + private LLUUID m_id; // ID to filter messages from + private string m_message; // The message + private bool m_active; // Listener is active or not + + public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, + string message) + { + Initialise(localID, handle, ItemID, hostID, channel, name, id, message); + } + + public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, + string message, LLUUID sourceItemID) + { + Initialise(localID, handle, ItemID, hostID, channel, name, id, message); + m_sourceItemID = sourceItemID; + } + + private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, + LLUUID id, string message) + { + m_handle = handle; + m_channel = channel; + m_itemID = ItemID; + m_hostID = hostID; + m_name = name; + m_id = id; + m_message = message; + m_active = true; + m_localID = localID; + } + + public LLUUID GetItemID() + { + return m_itemID; + } + + public LLUUID GetHostID() + { + return m_hostID; + } + + public LLUUID GetSourceItemID() + { + return m_sourceItemID; + } + + public int GetChannel() + { + return m_channel; + } + + public uint GetLocalID() + { + return m_localID; + } + + public int GetHandle() + { + return m_handle; + } + + public string GetMessage() + { + return m_message; + } + + public string GetName() + { + return m_name; + } + + public bool IsActive() + { + return m_active; + } + + public void Deactivate() + { + m_active = false; + } + + public void Activate() + { + m_active = true; + } + + public LLUUID GetID() + { + return m_id; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Modules/XMLRPCModule.cs b/trunk/OpenSim/Region/Environment/Modules/XMLRPCModule.cs new file mode 100644 index 0000000000..edd1df80e2 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/XMLRPCModule.cs @@ -0,0 +1,431 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +/***************************************************** + * + * XMLRPCModule + * + * Module for accepting incoming communications from + * external XMLRPC client and calling a remote data + * procedure for a registered data channel/prim. + * + * + * 1. On module load, open a listener port + * 2. Attach an XMLRPC handler + * 3. When a request is received: + * 3.1 Parse into components: channel key, int, string + * 3.2 Look up registered channel listeners + * 3.3 Call the channel (prim) remote data method + * 3.4 Capture the response (llRemoteDataReply) + * 3.5 Return response to client caller + * 3.6 If no response from llRemoteDataReply within + * RemoteReplyScriptTimeout, generate script timeout fault + * + * Prims in script must: + * 1. Open a remote data channel + * 1.1 Generate a channel ID + * 1.2 Register primid,channelid pair with module + * 2. Implement the remote data procedure handler + * + * llOpenRemoteDataChannel + * llRemoteDataReply + * remote_data(integer type, key channel, key messageid, string sender, integer ival, string sval) + * llCloseRemoteDataChannel + * + * **************************************************/ + +namespace OpenSim.Region.Environment.Modules +{ + public class XMLRPCModule : IRegionModule, IXMLRPC + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + private Queue rpcQueue = new Queue(); + private object XMLRPCListLock = new object(); + private string m_name = "XMLRPCModule"; + private int RemoteReplyScriptWait = 300; + private int RemoteReplyScriptTimeout = 900; + private int m_remoteDataPort = 0; + private List m_scenes = new List(); + + // + private Dictionary m_openChannels; + + // + private Dictionary m_pendingResponse; + + public void Initialise(Scene scene, IConfigSource config) + { + try + { + m_remoteDataPort = config.Configs["Network"].GetInt("remoteDataPort", m_remoteDataPort); + } + catch (Exception) + { + } + + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + + scene.RegisterModuleInterface(this); + } + } + + public void PostInitialise() + { + if (IsEnabled()) + { + m_openChannels = new Dictionary(); + m_pendingResponse = new Dictionary(); + + // Start http server + // Attach xmlrpc handlers + m_log.Info("[REMOTE_DATA]: " + + "Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands."); + BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort); + httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); + httpServer.Start(); + } + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + public bool IsEnabled() + { + return (m_remoteDataPort > 0); + } + + /********************************************** + * OpenXMLRPCChannel + * + * Generate a LLUUID channel key and add it and + * the prim id to dictionary + * + * First check if there is a channel assigned for + * this itemID. If there is, then someone called + * llOpenRemoteDataChannel twice. Just return the + * original channel. Other option is to delete the + * current channel and assign a new one. + * + * ********************************************/ + + public LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID) + { + LLUUID channel = null; + + //Is a dupe? + foreach (RPCChannelInfo ci in m_openChannels.Values) + { + if (ci.GetItemID().Equals(itemID)) + { + // return the original channel ID for this item + channel = ci.GetChannelID(); + break; + } + } + + if ((channel.Equals(null)) || (channel.Equals(LLUUID.Zero))) + { + channel = LLUUID.Random(); + RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, channel); + lock (XMLRPCListLock) + { + m_openChannels.Add(channel, rpcChanInfo); + } + } + + return channel; + } + + public void DeleteChannel(LLUUID itemID) + { + + foreach (RPCChannelInfo li in m_openChannels.Values) + { + + if (li.GetItemID().Equals(itemID)) + { + + m_openChannels.Remove(li.GetChannelID()); + return; + + } + + } + + } + + /********************************************** + * Remote Data Reply + * + * Response to RPC message + * + *********************************************/ + + public void RemoteDataReply(string channel, string message_id, string sdata, int idata) + { + RPCRequestInfo rpcInfo; + LLUUID message_key = new LLUUID(message_id); + + if (m_pendingResponse.TryGetValue(message_key, out rpcInfo)) + { + rpcInfo.SetRetval(sdata); + rpcInfo.SetProcessed(true); + + lock (XMLRPCListLock) + { + m_pendingResponse.Remove(message_key); + } + } + } + + /********************************************** + * CloseXMLRPCChannel + * + * Remove channel from dictionary + * + *********************************************/ + + public void CloseXMLRPCChannel(LLUUID channelKey) + { + if (m_openChannels.ContainsKey(channelKey)) + m_openChannels.Remove(channelKey); + } + + + public XmlRpcResponse XmlRpcRemoteData(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + + Hashtable requestData = (Hashtable) request.Params[0]; + bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") && + requestData.Contains("StringValue")); + + if (GoodXML) + { + LLUUID channel = new LLUUID((string) requestData["Channel"]); + RPCChannelInfo rpcChanInfo; + if (m_openChannels.TryGetValue(channel, out rpcChanInfo)) + { + string intVal = (string) requestData["IntValue"]; + string strVal = (string) requestData["StringValue"]; + + RPCRequestInfo rpcInfo; + + lock (XMLRPCListLock) + { + rpcInfo = + new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal, + intVal); + rpcQueue.Enqueue(rpcInfo); + } + + int timeoutCtr = 0; + + while (!rpcInfo.IsProcessed() && (timeoutCtr < RemoteReplyScriptTimeout)) + { + Thread.Sleep(RemoteReplyScriptWait); + timeoutCtr += RemoteReplyScriptWait; + } + if (rpcInfo.IsProcessed()) + { + response.Value = rpcInfo.GetRetval(); + rpcInfo = null; + } + else + { + response.SetFault(-1, "Script timeout"); + lock (XMLRPCListLock) + { + m_pendingResponse.Remove(rpcInfo.GetMessageID()); + } + } + } + else + { + response.SetFault(-1, "Invalid channel"); + } + } + + return response; + } + + public bool hasRequests() + { + return (rpcQueue.Count > 0); + } + + public RPCRequestInfo GetNextRequest() + { + lock (XMLRPCListLock) + { + RPCRequestInfo rpcInfo = rpcQueue.Dequeue(); + m_pendingResponse.Add(rpcInfo.GetMessageID(), rpcInfo); + return rpcInfo; + } + } + } + + /************************************************************** + * + * Class RPCRequestInfo + * + * Holds details about incoming requests until they are picked + * from the queue by LSLLongCmdHandler + * ***********************************************************/ + + public class RPCRequestInfo + { + private string m_StrVal; + private string m_IntVal; + private bool m_processed; + private string m_resp; + private uint m_localID; + private LLUUID m_ItemID; + private LLUUID m_MessageID; + private LLUUID m_ChannelKey; + + public RPCRequestInfo(uint localID, LLUUID itemID, LLUUID channelKey, string strVal, string intVal) + { + m_localID = localID; + m_StrVal = strVal; + m_IntVal = intVal; + m_ItemID = itemID; + m_ChannelKey = channelKey; + m_MessageID = LLUUID.Random(); + m_processed = false; + m_resp = String.Empty; + } + + public bool IsProcessed() + { + return m_processed; + } + + public LLUUID GetChannelKey() + { + return m_ChannelKey; + } + + public void SetProcessed(bool processed) + { + m_processed = processed; + } + + public void SetRetval(string resp) + { + m_resp = resp; + } + + public string GetRetval() + { + return m_resp; + } + + public uint GetLocalID() + { + return m_localID; + } + + public LLUUID GetItemID() + { + return m_ItemID; + } + + public string GetStrVal() + { + return m_StrVal; + } + + public int GetIntValue() + { + return int.Parse(m_IntVal); + } + + public LLUUID GetMessageID() + { + return m_MessageID; + } + } + + public class RPCChannelInfo + { + private LLUUID m_itemID; + private uint m_localID; + private LLUUID m_ChannelKey; + + public RPCChannelInfo(uint localID, LLUUID itemID, LLUUID channelID) + { + m_ChannelKey = channelID; + m_localID = localID; + m_itemID = itemID; + } + + public LLUUID GetItemID() + { + return m_itemID; + } + + public LLUUID GetChannelID() + { + return m_ChannelKey; + } + + public uint GetLocalID() + { + return m_localID; + } + + } +} diff --git a/trunk/OpenSim/Region/Environment/Modules/XferModule.cs b/trunk/OpenSim/Region/Environment/Modules/XferModule.cs new file mode 100644 index 0000000000..131e2b02fe --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Modules/XferModule.cs @@ -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 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; +using System.Collections.Generic; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class XferModule : IRegionModule, IXfer + { + public Dictionary NewFiles = new Dictionary(); + public Dictionary Transfers = new Dictionary(); + + private Scene m_scene; + + public XferModule() + { + } + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_scene.EventManager.OnNewClient += NewClient; + + m_scene.RegisterModuleInterface(this); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "XferModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public void NewClient(IClientAPI client) + { + client.OnRequestXfer += RequestXfer; + client.OnConfirmXfer += AckPacket; + } + + /// + /// + /// + /// + /// + /// + public void RequestXfer(IClientAPI remoteClient, ulong xferID, string fileName) + { + lock (NewFiles) + { + if (NewFiles.ContainsKey(fileName)) + { + if (!Transfers.ContainsKey(xferID)) + { + byte[] fileData = NewFiles[fileName]; + XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient); + Transfers.Add(xferID, transaction); + NewFiles.Remove(fileName); + + if (transaction.StartSend()) + { + Transfers.Remove(xferID); + } + } + } + } + } + + public void AckPacket(IClientAPI remoteClient, ulong xferID, uint packet) + { + if (Transfers.ContainsKey(xferID)) + { + if (Transfers[xferID].AckPacket(packet)) + { + { + Transfers.Remove(xferID); + } + } + } + } + + public bool AddNewFile(string fileName, byte[] data) + { + lock (NewFiles) + { + if (NewFiles.ContainsKey(fileName)) + { + NewFiles[fileName] = data; + } + else + { + NewFiles.Add(fileName, data); + } + } + return true; + } + + + public class XferDownLoad + { + public byte[] Data = new byte[0]; + public string FileName = String.Empty; + public ulong XferID = 0; + public int DataPointer = 0; + public uint Packet = 0; + public IClientAPI Client; + public uint Serial = 1; + private bool complete; + + public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client) + { + FileName = fileName; + Data = data; + XferID = xferID; + Client = client; + } + + public XferDownLoad() + { + } + + /// + /// Start a transfer + /// + /// True if the transfer is complete, false if not + public bool StartSend() + { + if (Data.Length < 1000) + { + // for now (testing ) we only support files under 1000 bytes + byte[] transferData = new byte[Data.Length + 4]; + Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4); + Array.Copy(Data, 0, transferData, 4, Data.Length); + Client.SendXferPacket(XferID, 0 + 0x80000000, transferData); + + complete = true; + } + else + { + byte[] transferData = new byte[1000 + 4]; + Array.Copy(Helpers.IntToBytes(Data.Length), 0, transferData, 0, 4); + Array.Copy(Data, 0, transferData, 4, 1000); + Client.SendXferPacket(XferID, 0, transferData); + Packet++; + DataPointer = 1000; + } + + return complete; + } + + /// + /// Respond to an ack packet from the client + /// + /// + /// True if the transfer is complete, false otherwise + public bool AckPacket(uint packet) + { + if (!complete) + { + if ((Data.Length - DataPointer) > 1000) + { + byte[] transferData = new byte[1000]; + Array.Copy(Data, DataPointer, transferData, 0, 1000); + Client.SendXferPacket(XferID, Packet, transferData); + Packet++; + DataPointer += 1000; + } + else + { + byte[] transferData = new byte[Data.Length - DataPointer]; + Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer); + uint endPacket = Packet |= (uint) 0x80000000; + Client.SendXferPacket(XferID, endPacket, transferData); + Packet++; + DataPointer += (Data.Length - DataPointer); + + complete = true; + } + } + + return complete; + } + } + } +} diff --git a/trunk/OpenSim/Region/Environment/PermissionManager.cs b/trunk/OpenSim/Region/Environment/PermissionManager.cs new file mode 100644 index 0000000000..5958249279 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/PermissionManager.cs @@ -0,0 +1,620 @@ +/* +* 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 libsecondlife; +using OpenSim.Region.Environment.LandManagement; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment +{ + public class PermissionManager + { + protected Scene m_scene; + + // These are here for testing. They will be taken out + private uint PERM_ALL = (uint)2147483647; + private uint PERM_COPY = (uint)32768; + private uint PERM_MODIFY = (uint)16384; + private uint PERM_MOVE = (uint)524288; + private uint PERM_TRANS = (uint)8192; + private uint PERM_LOCKED = (uint)540672; + // Bypasses the permissions engine (always returns OK) + // disable in any production environment + // TODO: Change this to false when permissions are a desired default + // TODO: Move to configuration option. + private bool m_bypassPermissions = true; + + public bool BypassPermissions + { + get { return m_bypassPermissions; } + set { m_bypassPermissions = value; } + } + + public PermissionManager() + { + } + + public PermissionManager(Scene scene) + { + m_scene = scene; + } + + public void Initialise(Scene scene) + { + m_scene = scene; + } + + protected virtual void SendPermissionError(LLUUID user, string reason) + { + m_scene.EventManager.TriggerPermissionError(user, reason); + } + + protected virtual bool IsAdministrator(LLUUID user) + { + if (m_bypassPermissions) + { + return true; + } + + // If there is no master avatar, return false + if (m_scene.RegionInfo.MasterAvatarAssignedUUID != null) + { + return m_scene.RegionInfo.MasterAvatarAssignedUUID == user; + } + + return false; + } + + public virtual bool IsEstateManager(LLUUID user) + { + if (m_bypassPermissions) + { + return true; + } + if (user != null) + { + LLUUID[] estatemanagers = m_scene.RegionInfo.EstateSettings.estateManagers; + for (int i = 0; i < estatemanagers.Length; i++) + { + if (estatemanagers[i] == user) + return true; + } + } + // The below is commented out because logically it happens anyway. It's left in for readability + //else + //{ + //return false; + //} + + return false; + } + + protected virtual bool IsGridUser(LLUUID user) + { + return true; + } + + protected virtual bool IsGuest(LLUUID user) + { + return false; + } + + public virtual bool CanRezObject(LLUUID user, LLVector3 position) + { + bool permission = false; + + string reason = "Insufficient permission"; + + Land land = m_scene.LandManager.getLandObject(position.X, position.Y); + if (land == null) return false; + + if ((land.landData.landFlags & ((int)Parcel.ParcelFlags.CreateObjects)) == + (int)Parcel.ParcelFlags.CreateObjects) + permission = true; + + //TODO: check for group rights + + if (IsAdministrator(user)) + { + permission = true; + } + else + { + reason = "Not an administrator"; + } + + if (GenericParcelPermission(user, position)) + { + permission = true; + } + else + { + reason = "Not the parcel owner"; + } + + if (!permission) + SendPermissionError(user, reason); + + return permission; + } + + #region Object Permissions + + public virtual uint GenerateClientFlags(LLUUID user, LLUUID objID) + { + + // Here's the way this works, + // ObjectFlags and Permission flags are two different enumerations + // ObjectFlags, however, tells the client to change what it will allow the user to do. + // So, that means that all of the permissions type ObjectFlags are /temporary/ and only + // supposed to be set when customizing the objectflags for the client. + + // These temporary objectflags get computed and added in this function based on the + // Permission mask that's appropriate! + // Outside of this method, they should never be added to objectflags! + // -teravus + + if (!m_scene.Entities.ContainsKey(objID)) + { + return 0; + } + + // If it's not an object, we cant edit it. + if (!(m_scene.Entities[objID] is SceneObjectGroup)) + { + return 0; + } + + SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objID]; + LLUUID objectOwner = task.OwnerID; + + uint objflags = task.RootPart.ObjectFlags; + + + // Remove any of the objectFlags that are temporary. These will get added back if appropriate + // in the next bit of code + + objflags &= (uint) + ~(LLObject.ObjectFlags.ObjectCopy | // Tells client you can copy the object + LLObject.ObjectFlags.ObjectModify | // tells client you can modify the object + LLObject.ObjectFlags.ObjectMove | // tells client that you can move the object (only, no mod) + LLObject.ObjectFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it + LLObject.ObjectFlags.ObjectYouOwner | // Tells client that you're the owner of the object + LLObject.ObjectFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set + ); + + // Creating the three ObjectFlags options for this method to choose from. + // Customize the OwnerMask + uint objectOwnerMask = ApplyObjectModifyMasks(task.RootPart.OwnerMask, objflags); + objectOwnerMask |= (uint)LLObject.ObjectFlags.ObjectYouOwner; + + // Customize the GroupMask + uint objectGroupMask = ApplyObjectModifyMasks(task.RootPart.GroupMask, objflags); + + // Customize the EveryoneMask + uint objectEveryoneMask = ApplyObjectModifyMasks(task.RootPart.EveryoneMask, objflags); + + + // Hack to allow collaboration until Groups and Group Permissions are implemented + if ((objectEveryoneMask & (uint)LLObject.ObjectFlags.ObjectMove) != 0) + objectEveryoneMask |= (uint)LLObject.ObjectFlags.ObjectModify; + + if (m_bypassPermissions) + return objectOwnerMask; + + // Object owners should be able to edit their own content + if (user == objectOwner) + { + return objectOwnerMask; + } + + // Users should be able to edit what is over their land. + Land parcel = m_scene.LandManager.getLandObject(task.AbsolutePosition.X, task.AbsolutePosition.Y); + if (parcel != null && parcel.landData.ownerID == user) + return objectOwnerMask; + + // Admin objects should not be editable by the above + if (IsAdministrator(objectOwner)) + return objectEveryoneMask; + + // Estate users should be able to edit anything in the sim + if (IsEstateManager(user)) + return objectOwnerMask; + + + + // Admin should be able to edit anything in the sim (including admin objects) + if (IsAdministrator(user)) + return objectOwnerMask; + + + return objectEveryoneMask; + } + + + + private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) + { + // We are adding the temporary objectflags to the object's objectflags based on the + // permission flag given. These change the F flags on the client. + + if ((setPermissionMask & (uint)PermissionMask.Copy) != 0) + { + objectFlagsMask |= (uint)LLObject.ObjectFlags.ObjectCopy; + } + + if ((setPermissionMask & (uint)PermissionMask.Move) != 0) + { + objectFlagsMask |= (uint)LLObject.ObjectFlags.ObjectMove; + } + + if ((setPermissionMask & (uint)PermissionMask.Modify) != 0) + { + objectFlagsMask |= (uint)LLObject.ObjectFlags.ObjectModify; + } + + if ((setPermissionMask & (uint)PermissionMask.Transfer) != 0) + { + objectFlagsMask |= (uint)LLObject.ObjectFlags.ObjectTransfer; + } + + return objectFlagsMask; + } + + protected virtual bool GenericObjectPermission(LLUUID currentUser, LLUUID objId) + { + // Default: deny + bool permission = false; + bool locked = false; + + if (!m_scene.Entities.ContainsKey(objId)) + { + return false; + } + + // If it's not an object, we cant edit it. + if ((!(m_scene.Entities[objId] is SceneObjectGroup))) + { + return false; + } + + + SceneObjectGroup group = (SceneObjectGroup)m_scene.Entities[objId]; + + LLUUID objectOwner = group.OwnerID; + locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0); + + // People shouldn't be able to do anything with locked objects, except the Administrator + // The 'set permissions' runs through a different permission check, so when an object owner + // sets an object locked, the only thing that they can do is unlock it. + // + // Nobody but the object owner can set permissions on an object + // + + if (locked && (!IsAdministrator(currentUser))) + { + return false; + } + + // Object owners should be able to edit their own content + if (currentUser == objectOwner) + { + permission = true; + } + + // Users should be able to edit what is over their land. + Land parcel = m_scene.LandManager.getLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y); + if ((parcel != null) && (parcel.landData.ownerID == currentUser)) + { + permission = true; + } + + // Estate users should be able to edit anything in the sim + if (IsEstateManager(currentUser)) + { + permission = true; + } + + // Admin objects should not be editable by the above + if (IsAdministrator(objectOwner)) + { + permission = false; + } + + // Admin should be able to edit anything in the sim (including admin objects) + if (IsAdministrator(currentUser)) + { + permission = true; + } + + return permission; + } + + /// + /// Permissions check - can user delete an object? + /// + /// User attempting the delete + /// Target object + /// Has permission? + public virtual bool CanDeRezObject(LLUUID user, LLUUID obj) + { + return GenericObjectPermission(user, obj); + } + + public virtual bool CanEditObject(LLUUID user, LLUUID obj) + { + return GenericObjectPermission(user, obj); + } + + public virtual bool CanEditObjectPosition(LLUUID user, LLUUID obj) + { + bool permission = GenericObjectPermission(user, obj); + if (!permission) + { + if (!m_scene.Entities.ContainsKey(obj)) + { + return false; + } + + // The client + // may request to edit linked parts, and therefore, it needs + // to also check for SceneObjectPart + + // If it's not an object, we cant edit it. + if ((!(m_scene.Entities[obj] is SceneObjectGroup))) + { + return false; + } + + + SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[obj]; + + + LLUUID taskOwner = null; + // Added this because at this point in time it wouldn't be wise for + // the administrator object permissions to take effect. + LLUUID objectOwner = task.OwnerID; + + // Anyone can move + if ((task.RootPart.EveryoneMask & PERM_MOVE) != 0) + permission = true; + + // Locked + if ((task.RootPart.OwnerMask & PERM_LOCKED) != 0) + permission = false; + + } + return permission; + } + + public virtual bool CanCopyObject(LLUUID user, LLUUID obj) + { + bool permission = GenericObjectPermission(user, obj); + if (!permission) + { + if (!m_scene.Entities.ContainsKey(obj)) + { + return false; + } + + // If it's not an object, we cant edit it. + if (!(m_scene.Entities[obj] is SceneObjectGroup)) + { + return false; + } + + SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[obj]; + LLUUID taskOwner = null; + // Added this because at this point in time it wouldn't be wise for + // the administrator object permissions to take effect. + LLUUID objectOwner = task.OwnerID; + if ((task.RootPart.EveryoneMask & PERM_COPY) != 0) + permission = true; + } + return permission; + } + + public virtual bool CanReturnObject(LLUUID user, LLUUID obj) + { + return GenericObjectPermission(user, obj); + } + + #endregion + + #region Communication Permissions + + public virtual bool GenericCommunicationPermission(LLUUID user, LLUUID target) + { + bool permission = false; + string reason = "Only registered users may communicate with another account."; + + if (IsGridUser(user)) + permission = true; + + if (!IsGridUser(user)) + { + permission = false; + reason = "The person that you are messaging is not a registered user."; + } + if (IsAdministrator(user)) + permission = true; + + if (IsEstateManager(user)) + permission = true; + + if (!permission) + SendPermissionError(user, reason); + + return permission; + } + + public virtual bool CanInstantMessage(LLUUID user, LLUUID target) + { + return GenericCommunicationPermission(user, target); + } + + public virtual bool CanInventoryTransfer(LLUUID user, LLUUID target) + { + return GenericCommunicationPermission(user, target); + } + + #endregion + + public virtual bool CanEditScript(LLUUID user, LLUUID script) + { + return IsAdministrator(user); + } + + public virtual bool CanRunScript(LLUUID user, LLUUID script) + { + return IsAdministrator(user); + } + + public virtual bool CanRunConsoleCommand(LLUUID user) + { + return IsAdministrator(user); + } + + public virtual bool CanTerraform(LLUUID user, LLVector3 position) + { + bool permission = false; + + // Estate override + if (GenericEstatePermission(user)) + permission = true; + + float X = position.X; + float Y = position.Y; + + if (X > 255) + X = 255; + if (Y > 255) + Y = 255; + if (X < 0) + X = 0; + if (Y < 0) + Y = 0; + + // Land owner can terraform too + Land parcel = m_scene.LandManager.getLandObject(X, Y); + if (parcel != null && GenericParcelPermission(user, parcel)) + permission = true; + + if (!permission) + SendPermissionError(user, "Not authorized to terraform at this location."); + + return permission; + } + + #region Estate Permissions + + public virtual bool GenericEstatePermission(LLUUID user) + { + // Default: deny + bool permission = false; + + // Estate admins should be able to use estate tools + if (IsEstateManager(user)) + permission = true; + + // Administrators always have permission + if (IsAdministrator(user)) + permission = true; + + return permission; + } + + public virtual bool CanEditEstateTerrain(LLUUID user) + { + return GenericEstatePermission(user); + } + + public virtual bool CanRestartSim(LLUUID user) + { + // Since this is potentially going on a grid... + + return GenericEstatePermission(user); + //return m_scene.RegionInfo.MasterAvatarAssignedUUID == user; + } + + #endregion + + #region Parcel Permissions + + protected virtual bool GenericParcelPermission(LLUUID user, Land parcel) + { + bool permission = false; + + if (parcel.landData.ownerID == user) + { + permission = true; + } + + if (parcel.landData.isGroupOwned) + { + // TODO: Need to do some extra checks here. Requires group code. + } + + if (IsEstateManager(user)) + { + permission = true; + } + + if (IsAdministrator(user)) + { + permission = true; + } + + return permission; + } + + protected virtual bool GenericParcelPermission(LLUUID user, LLVector3 pos) + { + Land parcel = m_scene.LandManager.getLandObject(pos.X, pos.Y); + if (parcel == null) return false; + return GenericParcelPermission(user, parcel); + } + + public virtual bool CanEditParcel(LLUUID user, Land parcel) + { + return GenericParcelPermission(user, parcel); + } + + public virtual bool CanSellParcel(LLUUID user, Land parcel) + { + return GenericParcelPermission(user, parcel); + } + + public virtual bool CanAbandonParcel(LLUUID user, Land parcel) + { + return GenericParcelPermission(user, parcel); + } + + #endregion + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/AvatarAnimations.cs b/trunk/OpenSim/Region/Environment/Scenes/AvatarAnimations.cs new file mode 100644 index 0000000000..be882e077f --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/AvatarAnimations.cs @@ -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; +using System.Collections.Generic; +using System.Xml; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Environment.Scenes +{ + public class AvatarAnimations + { + public Dictionary AnimsLLUUID = new Dictionary(); + public Dictionary AnimsNames = new Dictionary(); + + public AvatarAnimations() + { + using (XmlTextReader reader = new XmlTextReader("data/avataranimations.xml")) + { + XmlDocument doc = new XmlDocument(); + doc.Load(reader); + foreach (XmlNode nod in doc.DocumentElement.ChildNodes) + { + if (nod.Attributes["name"] != null) + { + string name = (string)nod.Attributes["name"].Value; + LLUUID id = (LLUUID)nod.InnerText; + + AnimsLLUUID.Add(name, id); + AnimsNames.Add(id, name); + } + } + } + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/AvatarAppearance.cs b/trunk/OpenSim/Region/Environment/Scenes/AvatarAppearance.cs new file mode 100644 index 0000000000..b54f777404 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/AvatarAppearance.cs @@ -0,0 +1,153 @@ +/* +* 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 libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; + +namespace OpenSim.Region.Environment.Scenes +{ + public class AvatarAppearance + { + protected LLUUID m_scenePresenceID; + + public LLUUID ScenePresenceID + { + get { return m_scenePresenceID; } + set { m_scenePresenceID = value; } + } + protected int m_wearablesSerial = 1; + + public int WearablesSerial + { + get { return m_wearablesSerial; } + set { m_wearablesSerial = value; } + } + + protected byte[] m_visualParams; + + public byte[] VisualParams + { + get { return m_visualParams; } + set { m_visualParams = value; } + } + + protected AvatarWearable[] m_wearables; + + public AvatarWearable[] Wearables + { + get { return m_wearables; } + set { m_wearables = value; } + } + + protected LLObject.TextureEntry m_textureEntry; + + public LLObject.TextureEntry TextureEntry + { + get { return m_textureEntry; } + set { m_textureEntry = value; } + } + + protected float m_avatarHeight = 0; + + public float AvatarHeight + { + get { return m_avatarHeight; } + set { m_avatarHeight = value; } + } + + public AvatarAppearance() + { + } + + public AvatarAppearance(LLUUID avatarID, AvatarWearable[] wearables, byte[] visualParams) + { + m_scenePresenceID = avatarID; + m_wearablesSerial = 1; + m_wearables = wearables; + m_visualParams = visualParams; + m_textureEntry = GetDefaultTextureEntry(); + } + + /// + /// + /// + /// + /// + public void SetAppearance(byte[] texture, AgentSetAppearancePacket.VisualParamBlock[] visualParam) + { + LLObject.TextureEntry textureEnt = new LLObject.TextureEntry(texture, 0, texture.Length); + m_textureEntry = textureEnt; + + for (int i = 0; i < visualParam.Length; i++) + { + m_visualParams[i] = visualParam[i].ParamValue; + } + + // Teravus : Nifty AV Height Getting Maaaaagical formula. Oh how we love turning 0-255 into meters. + // (float)m_visualParams[25] = Height + // (float)m_visualParams[125] = LegLength + m_avatarHeight = (1.50856f + (((float) m_visualParams[25]/255.0f)*(2.525506f - 1.50856f))) + + (((float) m_visualParams[125]/255.0f)/1.5f); + } + + /// + /// + /// + /// + public void SendAppearanceToOtherAgent(ScenePresence avatar) + { + avatar.ControllingClient.SendAppearance(m_scenePresenceID, m_visualParams, + m_textureEntry.ToBytes()); + } + + public void SetWearable(IClientAPI client, int wearableId, AvatarWearable wearable) + { + m_wearables[wearableId] = wearable; + SendOwnWearables(client); + } + + public void SendOwnWearables(IClientAPI ourClient) + { + ourClient.SendWearables(m_wearables, m_wearablesSerial++); + } + + public static LLObject.TextureEntry GetDefaultTextureEntry() + { + LLObject.TextureEntry textu = new LLObject.TextureEntry(new LLUUID("C228D1CF-4B5D-4BA8-84F4-899A0796AA97")); + textu.CreateFace(0).TextureID = new LLUUID("00000000-0000-1111-9999-000000000012"); + textu.CreateFace(1).TextureID = new LLUUID("5748decc-f629-461c-9a36-a35a221fe21f"); + textu.CreateFace(2).TextureID = new LLUUID("5748decc-f629-461c-9a36-a35a221fe21f"); + textu.CreateFace(3).TextureID = new LLUUID("6522E74D-1660-4E7F-B601-6F48C1659A77"); + textu.CreateFace(4).TextureID = new LLUUID("7CA39B4C-BD19-4699-AFF7-F93FD03D3E7B"); + textu.CreateFace(5).TextureID = new LLUUID("00000000-0000-1111-9999-000000000010"); + textu.CreateFace(6).TextureID = new LLUUID("00000000-0000-1111-9999-000000000011"); + return textu; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Scenes/EntityBase.cs b/trunk/OpenSim/Region/Environment/Scenes/EntityBase.cs new file mode 100644 index 0000000000..ffcc44bf5e --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/EntityBase.cs @@ -0,0 +1,159 @@ +/* +* 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.Collections.Generic; +using Axiom.Math; +using libsecondlife; + +namespace OpenSim.Region.Environment.Scenes +{ + public abstract class EntityBase + { + protected Scene m_scene; + + public Scene Scene + { + get { return m_scene; } + } + + public LLUUID m_uuid; + + public virtual LLUUID UUID + { + get { return m_uuid; } + set { m_uuid = value; } + } + + protected string m_name; + + /// + /// + /// + public virtual string Name + { + get { return m_name; } + set { m_name = value; } + } + + protected LLVector3 m_pos; + + /// + /// + /// + public virtual LLVector3 AbsolutePosition + { + get { return m_pos; } + set { m_pos = value; } + } + + protected LLVector3 m_velocity; + protected LLVector3 m_rotationalvelocity; + + /// + /// + /// + public virtual LLVector3 Velocity + { + get { return m_velocity; } + set { m_velocity = value; } + } + + protected Quaternion m_rotation = new Quaternion(0, 0, 1, 0); + + public virtual Quaternion Rotation + { + get { return m_rotation; } + set { m_rotation = value; } + } + + protected uint m_localId; + + public virtual uint LocalId + { + get { return m_localId; } + set { m_localId = value; } + } + + /// + /// Creates a new Entity (should not occur on it's own) + /// + public EntityBase() + { + m_uuid = LLUUID.Zero; + + m_pos = new LLVector3(); + m_velocity = new LLVector3(); + Rotation = new Quaternion(); + m_name = "(basic entity)"; + m_rotationalvelocity = new LLVector3(0, 0, 0); + } + + /// + /// + /// + public abstract void UpdateMovement(); + + /// + /// Performs any updates that need to be done at each frame. + /// + public abstract void Update(); + + /// + /// Copies the entity + /// + /// + public virtual EntityBase Copy() + { + return (EntityBase) MemberwiseClone(); + } + + + public abstract void SetText(string text, Vector3 color, double alpha); + } + + //Nested Classes + public class EntityIntersection + { + public Vector3 ipoint = new Vector3(0, 0, 0); + public float normal = 0; + public bool HitTF = false; + public SceneObjectPart obj; + public float distance = 0; + + public EntityIntersection() + { + } + + public EntityIntersection(Vector3 _ipoint, float _normal, bool _HitTF) + { + ipoint = _ipoint; + normal = _normal; + HitTF = _HitTF; + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/IScenePresenceBody.cs b/trunk/OpenSim/Region/Environment/Scenes/IScenePresenceBody.cs new file mode 100644 index 0000000000..3e87981999 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/IScenePresenceBody.cs @@ -0,0 +1,38 @@ +/* +* 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 libsecondlife; +using OpenSim.Framework; + +namespace OpenSim.Region.Environment.Scenes +{ + public interface IScenePresenceBody + { + void processMovement(IClientAPI remoteClient, uint flags, LLQuaternion bodyRotation); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Scenes/InnerScene.cs b/trunk/OpenSim/Region/Environment/Scenes/InnerScene.cs new file mode 100644 index 0000000000..57b8ae768f --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/InnerScene.cs @@ -0,0 +1,1173 @@ +/* +* 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; +using System.Collections.Generic; +using Axiom.Math; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Types; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Environment.Scenes +{ + public delegate void PhysicsCrash(); + + public class InnerScene + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #region Events + + public event PhysicsCrash UnRecoverableError; + + #endregion + + #region Fields + + public Dictionary ScenePresences; + // SceneObjects is not currently populated or used. + //public Dictionary SceneObjects; + public Dictionary Entities; + + public BasicQuadTreeNode QuadTree; + + protected RegionInfo m_regInfo; + protected Scene m_parentScene; + protected PermissionManager PermissionsMngr; + protected int m_numRootAgents = 0; + protected int m_numPrim = 0; + protected int m_numChildAgents = 0; + protected int m_physicalPrim = 0; + + protected int m_activeScripts = 0; + protected int m_scriptLPS = 0; + + internal object m_syncRoot = new object(); + + public PhysicsScene _PhyScene; + + #endregion + + public InnerScene(Scene parent, RegionInfo regInfo, PermissionManager permissionsMngr) + { + m_parentScene = parent; + m_regInfo = regInfo; + PermissionsMngr = permissionsMngr; + QuadTree = new BasicQuadTreeNode(null, "/0/", 0, 0, (short)Constants.RegionSize, (short)Constants.RegionSize); + QuadTree.Subdivide(); + QuadTree.Subdivide(); + } + + public PhysicsScene PhysicsScene + { + get { return _PhyScene; } + set + { + // If we're not doing the initial set + // Then we've got to remove the previous + // event handler + try + { + _PhyScene.OnPhysicsCrash -= physicsBasedCrash; + } + catch (NullReferenceException) + { + // This occurs when storing to _PhyScene the first time. + // Is there a better way to check the event handler before + // getting here + // This can be safely ignored. We're setting the first inital + // there are no event handler's registered. + } + + _PhyScene = value; + + _PhyScene.OnPhysicsCrash += physicsBasedCrash; + } + } + + public void Close() + { + ScenePresences.Clear(); + //SceneObjects.Clear(); + Entities.Clear(); + } + + #region Update Methods + + internal void UpdatePreparePhysics() + { + // If we are using a threaded physics engine + // grab the latest scene from the engine before + // trying to process it. + + // PhysX does this (runs in the background). + + if (_PhyScene.IsThreaded) + { + _PhyScene.GetResults(); + } + } + + internal void UpdateEntities() + { + List updateEntities = GetEntities(); + + foreach (EntityBase entity in updateEntities) + { + entity.Update(); + } + } + + internal float UpdatePhysics(double elapsed) + { + lock (m_syncRoot) + { + return _PhyScene.Simulate((float)elapsed); + } + } + + internal void UpdateEntityMovement() + { + List moveEntities = GetEntities(); + + foreach (EntityBase entity in moveEntities) + { + entity.UpdateMovement(); + } + } + + #endregion + + #region Entity Methods + + public void AddEntityFromStorage(SceneObjectGroup sceneObject) + { + sceneObject.RegionHandle = m_regInfo.RegionHandle; + sceneObject.SetScene(m_parentScene); + foreach (SceneObjectPart part in sceneObject.Children.Values) + { + part.LocalID = m_parentScene.PrimIDAllocate(); + + } + sceneObject.UpdateParentIDs(); + AddEntity(sceneObject); + } + + public void AddEntity(SceneObjectGroup sceneObject) + { + if (!Entities.ContainsKey(sceneObject.UUID)) + { + // QuadTree.AddObject(sceneObject); + lock (Entities) + { + Entities.Add(sceneObject.UUID, sceneObject); + } + m_numPrim++; + } + } + + public void AddPhysicalPrim(int number) + { + m_physicalPrim++; + } + + public void RemovePhysicalPrim(int number) + { + m_physicalPrim--; + } + + public void AddToScriptLPS(int number) + { + m_scriptLPS += number; + } + + public void AddActiveScripts(int number) + { + m_activeScripts += number; + } + + public void RemovePrim(uint localID, LLUUID avatar_deleter) + { + List EntityList = GetEntities(); + + foreach (EntityBase obj in EntityList) + { + if (obj is SceneObjectGroup) + { + if (((SceneObjectGroup)obj).LocalId == localID) + { + m_parentScene.RemoveEntity((SceneObjectGroup)obj); + m_numPrim--; + return; + } + } + } + } + + public void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, LLQuaternion rot) + { + System.Console.WriteLine("Attaching object " + objectLocalID + " to " + AttachmentPt); + SceneObjectPart p = GetSceneObjectPart(objectLocalID); + ScenePresence av = null; + if (TryGetAvatar(remoteClient.AgentId, out av)) + { + ObjectUpdatePacket objupdate = new ObjectUpdatePacket(); + objupdate.RegionData.RegionHandle = m_regInfo.RegionHandle; + objupdate.RegionData.TimeDilation = ushort.MaxValue; + objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[2]; + // avatar stuff - horrible group copypaste + + objupdate.ObjectData[0] = new ObjectUpdatePacket.ObjectDataBlock(); + objupdate.ObjectData[0].PSBlock = new byte[0]; + objupdate.ObjectData[0].ExtraParams = new byte[1]; + objupdate.ObjectData[0].MediaURL = new byte[0]; + objupdate.ObjectData[0].NameValue = new byte[0]; + objupdate.ObjectData[0].Text = new byte[0]; + objupdate.ObjectData[0].TextColor = new byte[4]; + objupdate.ObjectData[0].JointAxisOrAnchor = new LLVector3(0, 0, 0); + objupdate.ObjectData[0].JointPivot = new LLVector3(0, 0, 0); + objupdate.ObjectData[0].Material = 4; + objupdate.ObjectData[0].TextureAnim = new byte[0]; + objupdate.ObjectData[0].Sound = LLUUID.Zero; + + objupdate.ObjectData[0].State = 0; + objupdate.ObjectData[0].Data = new byte[0]; + + objupdate.ObjectData[0].ObjectData = new byte[76]; + objupdate.ObjectData[0].ObjectData[15] = 128; + objupdate.ObjectData[0].ObjectData[16] = 63; + objupdate.ObjectData[0].ObjectData[56] = 128; + objupdate.ObjectData[0].ObjectData[61] = 102; + objupdate.ObjectData[0].ObjectData[62] = 40; + objupdate.ObjectData[0].ObjectData[63] = 61; + objupdate.ObjectData[0].ObjectData[64] = 189; + + + objupdate.ObjectData[0].UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); + objupdate.ObjectData[0].PathCurve = 16; + objupdate.ObjectData[0].ProfileCurve = 1; + objupdate.ObjectData[0].PathScaleX = 100; + objupdate.ObjectData[0].PathScaleY = 100; + objupdate.ObjectData[0].ParentID = 0; + objupdate.ObjectData[0].OwnerID = LLUUID.Zero; + objupdate.ObjectData[0].Scale = new LLVector3(1, 1, 1); + objupdate.ObjectData[0].PCode = 47; + objupdate.ObjectData[0].TextureEntry = ScenePresence.DefaultTexture; + + objupdate.ObjectData[0].ID = av.LocalId; + objupdate.ObjectData[0].FullID = remoteClient.AgentId; + objupdate.ObjectData[0].ParentID = 0; + objupdate.ObjectData[0].NameValue = + Helpers.StringToField("FirstName STRING RW SV " + av.Firstname + "\nLastName STRING RW SV " + av.Lastname); + LLVector3 pos2 = av.AbsolutePosition; + // new LLVector3((float) Pos.X, (float) Pos.Y, (float) Pos.Z); + byte[] pb = pos2.GetBytes(); + Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); + + + // primitive part + objupdate.ObjectData[1] = new ObjectUpdatePacket.ObjectDataBlock(); + // SetDefaultPrimPacketValues + objupdate.ObjectData[1].PSBlock = new byte[0]; + objupdate.ObjectData[1].ExtraParams = new byte[1]; + objupdate.ObjectData[1].MediaURL = new byte[0]; + objupdate.ObjectData[1].NameValue = new byte[0]; + objupdate.ObjectData[1].Text = new byte[0]; + objupdate.ObjectData[1].TextColor = new byte[4]; + objupdate.ObjectData[1].JointAxisOrAnchor = new LLVector3(0, 0, 0); + objupdate.ObjectData[1].JointPivot = new LLVector3(0, 0, 0); + objupdate.ObjectData[1].Material = 3; + objupdate.ObjectData[1].TextureAnim = new byte[0]; + objupdate.ObjectData[1].Sound = LLUUID.Zero; + objupdate.ObjectData[1].State = 0; + objupdate.ObjectData[1].Data = new byte[0]; + + objupdate.ObjectData[1].ObjectData = new byte[60]; + objupdate.ObjectData[1].ObjectData[46] = 128; + objupdate.ObjectData[1].ObjectData[47] = 63; + + // SetPrimPacketShapeData + PrimitiveBaseShape primData = p.Shape; + + objupdate.ObjectData[1].TextureEntry = primData.TextureEntry; + objupdate.ObjectData[1].PCode = primData.PCode; + objupdate.ObjectData[1].State = (byte)(((byte)AttachmentPt) << 4); + objupdate.ObjectData[1].PathBegin = primData.PathBegin; + objupdate.ObjectData[1].PathEnd = primData.PathEnd; + objupdate.ObjectData[1].PathScaleX = primData.PathScaleX; + objupdate.ObjectData[1].PathScaleY = primData.PathScaleY; + objupdate.ObjectData[1].PathShearX = primData.PathShearX; + objupdate.ObjectData[1].PathShearY = primData.PathShearY; + objupdate.ObjectData[1].PathSkew = primData.PathSkew; + objupdate.ObjectData[1].ProfileBegin = primData.ProfileBegin; + objupdate.ObjectData[1].ProfileEnd = primData.ProfileEnd; + objupdate.ObjectData[1].Scale = primData.Scale; + objupdate.ObjectData[1].PathCurve = primData.PathCurve; + objupdate.ObjectData[1].ProfileCurve = primData.ProfileCurve; + objupdate.ObjectData[1].ProfileHollow = primData.ProfileHollow; + objupdate.ObjectData[1].PathRadiusOffset = primData.PathRadiusOffset; + objupdate.ObjectData[1].PathRevolutions = primData.PathRevolutions; + objupdate.ObjectData[1].PathTaperX = primData.PathTaperX; + objupdate.ObjectData[1].PathTaperY = primData.PathTaperY; + objupdate.ObjectData[1].PathTwist = primData.PathTwist; + objupdate.ObjectData[1].PathTwistBegin = primData.PathTwistBegin; + objupdate.ObjectData[1].ExtraParams = primData.ExtraParams; + + + objupdate.ObjectData[1].UpdateFlags = 276957500; // flags; // ?? + objupdate.ObjectData[1].ID = p.LocalID; + objupdate.ObjectData[1].FullID = p.UUID; + objupdate.ObjectData[1].OwnerID = p.OwnerID; + objupdate.ObjectData[1].Text = Helpers.StringToField(p.Text); + objupdate.ObjectData[1].TextColor[0] = 255; + objupdate.ObjectData[1].TextColor[1] = 255; + objupdate.ObjectData[1].TextColor[2] = 255; + objupdate.ObjectData[1].TextColor[3] = 128; + objupdate.ObjectData[1].ParentID = objupdate.ObjectData[0].ID; + //objupdate.ObjectData[1].PSBlock = particleSystem; + //objupdate.ObjectData[1].ClickAction = clickAction; + objupdate.ObjectData[1].Radius = 20; + objupdate.ObjectData[1].NameValue = + Helpers.StringToField("AttachItemID STRING RW SV " + p.UUID); + LLVector3 pos = new LLVector3((float)0.0, (float)0.0, (float)0.0); + + pb = pos.GetBytes(); + Array.Copy(pb, 0, objupdate.ObjectData[1].ObjectData, 0, pb.Length); + + byte[] brot = rot.GetBytes(); + Array.Copy(brot, 0, objupdate.ObjectData[1].ObjectData, 36, brot.Length); + + remoteClient.OutPacket(objupdate, ThrottleOutPacketType.Task); + } + else + { + m_log.Info("[SCENE]: Avatar " + remoteClient.AgentId + " not found"); + } + } + + + public ScenePresence CreateAndAddScenePresence(IClientAPI client, bool child, AvatarAppearance appearance) + { + ScenePresence newAvatar = null; + + newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, appearance); + newAvatar.IsChildAgent = child; + + if (child) + { + m_numChildAgents++; + m_log.Info("[SCENE]: " + m_regInfo.RegionName + ": Creating new child agent."); + } + else + { + m_numRootAgents++; + m_log.Info("[SCENE]: " + m_regInfo.RegionName + ": Creating new root agent."); + m_log.Info("[SCENE]: " + m_regInfo.RegionName + ": Adding Physical agent."); + + newAvatar.AddToPhysicalScene(); + } + + lock (Entities) + { + if (!Entities.ContainsKey(client.AgentId)) + { + Entities.Add(client.AgentId, newAvatar); + } + else + { + Entities[client.AgentId] = newAvatar; + } + } + lock (ScenePresences) + { + if (ScenePresences.ContainsKey(client.AgentId)) + { + ScenePresences[client.AgentId] = newAvatar; + } + else + { + ScenePresences.Add(client.AgentId, newAvatar); + } + } + + return newAvatar; + } + + public void SwapRootChildAgent(bool direction_RC_CR_T_F) + { + if (direction_RC_CR_T_F) + { + m_numRootAgents--; + m_numChildAgents++; + } + else + { + m_numChildAgents--; + m_numRootAgents++; + } + } + + public void removeUserCount(bool TypeRCTF) + { + if (TypeRCTF) + { + m_numRootAgents--; + } + else + { + m_numChildAgents--; + } + } + + public void RemoveAPrimCount() + { + m_numPrim--; + } + + public void AddAPrimCount() + { + m_numPrim++; + } + + public int GetChildAgentCount() + { + // some network situations come in where child agents get closed twice. + if (m_numChildAgents < 0) + { + m_numChildAgents = 0; + } + + return m_numChildAgents; + } + + public int GetRootAgentCount() + { + return m_numRootAgents; + } + + public int GetTotalObjects() + { + return m_numPrim; + } + + public int GetActiveObjects() + { + return m_physicalPrim; + } + + public int GetActiveScripts() + { + return m_activeScripts; + } + + public int GetScriptLPS() + { + int returnval = m_scriptLPS; + m_scriptLPS = 0; + return returnval; + } + #endregion + + #region Get Methods + + /// + /// Request a List of all m_scenePresences in this World + /// + /// + public List GetScenePresences() + { + List result; + + lock (ScenePresences) + { + result = new List(ScenePresences.Values); + } + + return result; + } + + public List GetAvatars() + { + List result = + GetScenePresences(delegate(ScenePresence scenePresence) { return !scenePresence.IsChildAgent; }); + + return result; + } + + /// + /// Request a filtered list of m_scenePresences in this World + /// + /// + public List GetScenePresences(FilterAvatarList filter) + { + List result = new List(); + List ScenePresencesList = GetScenePresences(); + + foreach (ScenePresence avatar in ScenePresencesList) + { + if (filter(avatar)) + { + result.Add(avatar); + } + } + + return result; + } + + /// + /// Request a Avatar by UUID + /// + /// + /// + public ScenePresence GetScenePresence(LLUUID avatarID) + { + if (ScenePresences.ContainsKey(avatarID)) + { + return ScenePresences[avatarID]; + } + return null; + } + + private SceneObjectGroup GetGroupByPrim(uint localID) + { + List EntityList = GetEntities(); + + foreach (EntityBase ent in EntityList) + { + if (ent is SceneObjectGroup) + { + if (((SceneObjectGroup)ent).HasChildPrim(localID)) + return (SceneObjectGroup)ent; + } + } + return null; + } + + private SceneObjectGroup GetGroupByPrim(LLUUID fullID) + { + List EntityList = GetEntities(); + + foreach (EntityBase ent in EntityList) + { + if (ent is SceneObjectGroup) + { + if (((SceneObjectGroup)ent).HasChildPrim(fullID)) + return (SceneObjectGroup)ent; + } + } + return null; + } + + public EntityIntersection GetClosestIntersectingPrim(Ray hray) + { + // Primitive Ray Tracing + float closestDistance = 280f; + EntityIntersection returnResult = new EntityIntersection(); + foreach (EntityBase ent in Entities.Values) + { + if (ent is SceneObjectGroup) + { + SceneObjectGroup reportingG = (SceneObjectGroup)ent; + EntityIntersection result = reportingG.TestIntersection(hray); + if (result.HitTF) + { + if (result.distance < closestDistance) + { + closestDistance = result.distance; + returnResult = result; + } + } + } + } + return returnResult; + } + + public SceneObjectPart GetSceneObjectPart(uint localID) + { + SceneObjectGroup group = GetGroupByPrim(localID); + if (group != null) + return group.GetChildPart(localID); + else + return null; + } + + public SceneObjectPart GetSceneObjectPart(LLUUID fullID) + { + SceneObjectGroup group = GetGroupByPrim(fullID); + if (group != null) + return group.GetChildPart(fullID); + else + return null; + } + + internal bool TryGetAvatar(LLUUID avatarId, out ScenePresence avatar) + { + ScenePresence presence; + if (ScenePresences.TryGetValue(avatarId, out presence)) + { + if (!presence.IsChildAgent) + { + avatar = presence; + return true; + } + } + + avatar = null; + return false; + } + + internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) + { + foreach (ScenePresence presence in ScenePresences.Values) + { + if (!presence.IsChildAgent) + { + string name = presence.ControllingClient.FirstName + " " + presence.ControllingClient.LastName; + + if (String.Compare(avatarName, name, true) == 0) + { + avatar = presence; + return true; + } + } + } + + avatar = null; + return false; + } + + public List GetEntities() + { + List result; + + lock (Entities) + { + result = new List(Entities.Values); + } + + return result; + } + + #endregion + + #region Other Methods + + public void physicsBasedCrash() + { + if (UnRecoverableError != null) + { + UnRecoverableError(); + } + } + + public LLUUID ConvertLocalIDToFullID(uint localID) + { + SceneObjectGroup group = GetGroupByPrim(localID); + if (group != null) + return group.GetPartsFullID(localID); + else + return LLUUID.Zero; + } + + public void SendAllSceneObjectsToClient(ScenePresence presence) + { + List EntityList = GetEntities(); + + foreach (EntityBase ent in EntityList) + { + if (ent is SceneObjectGroup) + { + // Only send child agents stuff in their draw distance. + // This will need to be done for every agent once we figure out + // what we're going to use to store prim that agents already got + // the initial update for and what we'll use to limit the + // space we check for new objects on movement. + + if (presence.IsChildAgent && m_parentScene.m_seeIntoRegionFromNeighbor) + { + LLVector3 oLoc = ((SceneObjectGroup)ent).AbsolutePosition; + float distResult = (float)Util.GetDistanceTo(presence.AbsolutePosition, oLoc); + + //m_log.Info("[DISTANCE]: " + distResult.ToString()); + + if (distResult < presence.DrawDistance) + { + // Send Only if we don't already know about it. + // KnownPrim also makes the prim known when called. + if (!presence.KnownPrim(((SceneObjectGroup)ent).UUID)) + ((SceneObjectGroup)ent).ScheduleFullUpdateToAvatar(presence); + } + } + else + { + ((SceneObjectGroup)ent).ScheduleFullUpdateToAvatar(presence); + } + } + } + } + + internal void ForEachClient(Action action) + { + foreach (ScenePresence presence in ScenePresences.Values) + { + action(presence.ControllingClient); + } + } + + #endregion + + #region Client Event handlers + + /// + /// + /// + /// + /// + /// + public void UpdatePrimScale(uint localID, LLVector3 scale, IClientAPI remoteClient) + { + SceneObjectGroup group = GetGroupByPrim(localID); + if (group != null) + { + if (PermissionsMngr.CanEditObjectPosition(remoteClient.AgentId, group.UUID)) + { + group.Resize(scale, localID); + } + } + } + + /// + /// This handles the nifty little tool tip that you get when you drag your mouse over an object + /// Send to the Object Group to process. We don't know enough to service the request + /// + /// + /// + /// + /// + public void RequestObjectPropertiesFamily(IClientAPI remoteClient, LLUUID AgentID, uint RequestFlags, + LLUUID ObjectID) + { + SceneObjectGroup group = GetGroupByPrim(ObjectID); + if (group != null) + { + group.ServiceObjectPropertiesFamilyRequest(remoteClient, AgentID, RequestFlags); + } + } + + /// + /// + /// + /// + /// + /// + public void UpdatePrimSingleRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient) + { + SceneObjectGroup group = GetGroupByPrim(localID); + if (group != null) + { + if (PermissionsMngr.CanEditObjectPosition(remoteClient.AgentId, group.UUID)) + { + group.UpdateSingleRotation(rot, localID); + } + } + } + + /// + /// + /// + /// + /// + /// + public void UpdatePrimRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient) + { + SceneObjectGroup group = GetGroupByPrim(localID); + if (group != null) + { + if (PermissionsMngr.CanEditObjectPosition(remoteClient.AgentId, group.UUID)) + { + group.UpdateGroupRotation(rot); + } + } + } + + /// + /// + /// + /// + /// + /// + /// + public void UpdatePrimRotation(uint localID, LLVector3 pos, LLQuaternion rot, IClientAPI remoteClient) + { + SceneObjectGroup group = GetGroupByPrim(localID); + if (group != null) + { + if (PermissionsMngr.CanEditObjectPosition(remoteClient.AgentId, group.UUID)) + { + group.UpdateGroupRotation(pos, rot); + } + } + } + + public void UpdatePrimSinglePosition(uint localID, LLVector3 pos, IClientAPI remoteClient) + { + SceneObjectGroup group = GetGroupByPrim(localID); + if (group != null) + { + if (PermissionsMngr.CanEditObjectPosition(remoteClient.AgentId, group.UUID)) + { + group.UpdateSinglePosition(pos, localID); + } + } + } + + /// + /// + /// + /// + /// + /// + public void UpdatePrimPosition(uint localID, LLVector3 pos, IClientAPI remoteClient) + { + SceneObjectGroup group = GetGroupByPrim(localID); + if (group != null) + { + if (PermissionsMngr.CanEditObjectPosition(remoteClient.AgentId, group.UUID)) + { + group.UpdateGroupPosition(pos); + } + } + } + + /// + /// + /// + /// + /// + /// + public void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient) + { + SceneObjectGroup group = GetGroupByPrim(localID); + if (group != null) + { + if (PermissionsMngr.CanEditObjectPosition(remoteClient.AgentId, group.UUID)) + { + group.UpdateTextureEntry(localID, texture); + } + } + } + + /// + /// + /// + /// + /// + /// + public void UpdatePrimFlags(uint localID, Packet packet, IClientAPI remoteClient) + { + SceneObjectGroup group = GetGroupByPrim(localID); + if (group != null) + { + if (PermissionsMngr.CanEditObject(remoteClient.AgentId, group.UUID)) + { + group.UpdatePrimFlags(localID, (ushort)packet.Type, true, packet.ToBytes()); + } + } + } + + public void MoveObject(LLUUID objectID, LLVector3 offset, LLVector3 pos, IClientAPI remoteClient) + { + SceneObjectGroup group = GetGroupByPrim(objectID); + if (group != null) + { + if (PermissionsMngr.CanEditObjectPosition(remoteClient.AgentId, group.UUID)) + { + group.GrabMovement(offset, pos, remoteClient); + } + // This is outside the above permissions condition + // so that if the object is locked the client moving the object + // get's it's position on the simulator even if it was the same as before + // This keeps the moving user's client in sync with the rest of the world. + group.SendGroupTerseUpdate(); + } + } + + /// + /// + /// + /// + /// + public void PrimName(IClientAPI remoteClient, uint primLocalID, string name) + { + SceneObjectGroup group = GetGroupByPrim(primLocalID); + if (group != null) + { + if (PermissionsMngr.CanEditObject(remoteClient.AgentId, group.UUID)) + { + group.SetPartName(Util.CleanString(name), primLocalID); + } + } + } + + /// + /// + /// + /// + /// + public void PrimDescription(IClientAPI remoteClient, uint primLocalID, string description) + { + SceneObjectGroup group = GetGroupByPrim(primLocalID); + if (group != null) + { + if (PermissionsMngr.CanEditObject(remoteClient.AgentId, group.UUID)) + { + group.SetPartDescription(Util.CleanString(description), primLocalID); + } + } + } + + public void UpdateExtraParam(LLUUID agentID, uint primLocalID, ushort type, bool inUse, byte[] data) + { + SceneObjectGroup group = GetGroupByPrim(primLocalID); + + if (group != null) + { + if (PermissionsMngr.CanEditObject(agentID, group.UUID)) + { + group.UpdateExtraParam(primLocalID, type, inUse, data); + } + } + } + + /// + /// + /// + /// + /// + public void UpdatePrimShape(LLUUID agentID, uint primLocalID, ObjectShapePacket.ObjectDataBlock shapeBlock) + { + SceneObjectGroup group = GetGroupByPrim(primLocalID); + if (group != null) + { + if (PermissionsMngr.CanEditObjectPosition(agentID, group.GetPartsFullID(primLocalID))) + { + group.UpdateShape(shapeBlock, primLocalID); + } + } + } + + /// + /// + /// + /// + /// + public void LinkObjects(uint parentPrim, List childPrims) + { + List EntityList = GetEntities(); + + SceneObjectGroup parenPrim = null; + foreach (EntityBase ent in EntityList) + { + if (ent is SceneObjectGroup) + { + if (((SceneObjectGroup)ent).LocalId == parentPrim) + { + parenPrim = (SceneObjectGroup)ent; + break; + } + } + } + + List children = new List(); + if (parenPrim != null) + { + for (int i = 0; i < childPrims.Count; i++) + { + foreach (EntityBase ent in EntityList) + { + if (ent is SceneObjectGroup) + { + if (((SceneObjectGroup)ent).LocalId == childPrims[i]) + { + children.Add((SceneObjectGroup)ent); + } + } + } + } + } + + foreach (SceneObjectGroup sceneObj in children) + { + parenPrim.LinkToGroup(sceneObj); + } + } + + /// + /// Delink a linkset + /// + /// + public void DelinkObjects(List primIds) + { + SceneObjectGroup parenPrim = null; + + // Need a list of the SceneObjectGroup local ids + // XXX I'm anticipating that building this dictionary once is more efficient than + // repeated scanning of the Entity.Values for a large number of primIds. However, it might + // be more efficient yet to keep this dictionary permanently on hand. + + Dictionary sceneObjects = new Dictionary(); + + List EntitieList = GetEntities(); + foreach (EntityBase ent in EntitieList) + { + if (ent is SceneObjectGroup) + { + SceneObjectGroup obj = (SceneObjectGroup)ent; + sceneObjects.Add(obj.LocalId, obj); + + } + } + + // Find the root prim among the prim ids we've been given + for (int i = 0; i < primIds.Count; i++) + { + + if (sceneObjects.ContainsKey(primIds[i])) + { + + parenPrim = sceneObjects[primIds[i]]; + primIds.RemoveAt(i); + break; + } + } + + if (parenPrim != null) + { + foreach (uint childPrimId in primIds) + { + parenPrim.DelinkFromGroup(childPrimId); + } + } + else + { + // If the first scan failed, we need to do a /deep/ scan of the linkages. This is /really/ slow + // We know that this is not the root prim now essentially, so we don't have to worry about remapping + // which one is the root prim + bool delinkedSomething = false; + for (int i = 0; i < primIds.Count; i++) + { + foreach (SceneObjectGroup grp in sceneObjects.Values) + { + SceneObjectPart gPart = grp.GetChildPart(primIds[i]); + if (gPart != null) + { + grp.DelinkFromGroup(primIds[i]); + delinkedSomething = true; + } + + } + } + if (!delinkedSomething) + { + m_log.InfoFormat("[SCENE]: " + + "DelinkObjects(): Could not find a root prim out of {0} as given to a delink request!", + primIds); + } + } + } + + /// + /// + /// + /// + /// + /// + public void DuplicateObject(uint originalPrim, LLVector3 offset, uint flags, LLUUID AgentID, LLUUID GroupID) + { + List EntityList = GetEntities(); + + SceneObjectGroup originPrim = null; + foreach (EntityBase ent in EntityList) + { + if (ent is SceneObjectGroup) + { + if (((SceneObjectGroup)ent).LocalId == originalPrim) + { + originPrim = (SceneObjectGroup)ent; + break; + } + } + } + + if (originPrim != null) + { + if (PermissionsMngr.CanCopyObject(AgentID, originPrim.UUID)) + { + SceneObjectGroup copy = originPrim.Copy(AgentID, GroupID); + copy.AbsolutePosition = copy.AbsolutePosition + offset; + copy.ResetIDs(); + + lock (Entities) + { + Entities.Add(copy.UUID, copy); + } + + m_numPrim++; + + copy.StartScripts(); + copy.ScheduleGroupForFullUpdate(); + } + } + else + { + m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID); + } + } + + /// + /// Calculates the distance between two Vector3s + /// + /// + /// + /// + public float Vector3Distance(Vector3 v1, Vector3 v2) + { + // We don't really need the double floating point precision... + // so casting it to a single + + return + (float) + Math.Sqrt((v1.x - v2.x) * (v1.x - v2.x) + (v1.y - v2.y) * (v1.y - v2.y) + (v1.z - v2.z) * (v1.z - v2.z)); + } + + #endregion + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs b/trunk/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs new file mode 100644 index 0000000000..13fa0095dd --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs @@ -0,0 +1,865 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using System.IO; +using System.Text; +using System.Xml; +using OpenSim.Region.Environment.Interfaces; + + +namespace OpenSim.Region.Environment.Scenes +{ + public partial class Scene + { + private static readonly log4net.ILog m_log + = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Start all the scripts in the scene which should be started. + /// + public void StartScripts() + { + m_log.Info("[PRIMINVENTORY]: Starting scripts in scene"); + + foreach (SceneObjectGroup group in Entities.Values) + { + group.StartScripts(); + } + } + + /// + /// Add an inventory item to an avatar's inventory. + /// + /// The remote client controlling the avatar + /// The item. This structure contains all the item metadata, including the folder + /// in which the item is to be placed. + public void AddInventoryItem(IClientAPI remoteClient, InventoryItemBase item) + { + CachedUserInfo userInfo + = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); + + if (userInfo != null) + { + userInfo.AddItem(remoteClient.AgentId, item); + remoteClient.SendInventoryItemCreateUpdate(item); + } + } + + /// + /// AddInventoryItem(LLUUID, InventoryItemBase) + /// + /// The ID of the avatar + /// The item. This structure contains all the item metadata, including the folder + /// in which the item is to be placed. + public void AddInventoryItem(LLUUID avatarId, InventoryItemBase item) + { + ScenePresence avatar; + + if (!TryGetAvatar(avatarId, out avatar)) + { + m_log.ErrorFormat( + "[AGENTINVENTORY]: Could not find avatar {0} to add inventory item", avatarId); + return; + } + + AddInventoryItem(avatar.ControllingClient, item); + } + + /// + /// Capability originating call to update the asset of an item in an agent's inventory + /// + /// + /// + /// + /// + public LLUUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, LLUUID itemID, byte[] data) + { + CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); + if (userInfo != null) + { + if (userInfo.RootFolder != null) + { + InventoryItemBase item = userInfo.RootFolder.HasItem(itemID); + if (item != null) + { + AssetBase asset = + CreateAsset(item.inventoryName, item.inventoryDescription, (sbyte) item.invType, + (sbyte) item.assetType, data); + AssetCache.AddAsset(asset); + + item.assetID = asset.FullID; + userInfo.UpdateItem(remoteClient.AgentId, item); + + // remoteClient.SendInventoryItemCreateUpdate(item); + if ((InventoryType) item.invType == InventoryType.Notecard) + { + //do we want to know about updated note cards? + } + else if ((InventoryType) item.invType == InventoryType.LSL) + { + // do we want to know about updated scripts + } + + return (asset.FullID); + } + } + } + return LLUUID.Zero; + } + + /// + /// CapsUpdatedInventoryItemAsset(IClientAPI, LLUUID, byte[]) + /// + private LLUUID CapsUpdateInventoryItemAsset(LLUUID avatarId, LLUUID itemID, byte[] data) + { + ScenePresence avatar; + + if (TryGetAvatar(avatarId, out avatar)) + { + return CapsUpdateInventoryItemAsset(avatar.ControllingClient, itemID, data); + } + else + { + m_log.ErrorFormat( + "[AGENTINVENTORY]: " + + "Avatar {0} cannot be found to update its inventory item asset", + avatarId); + } + + return LLUUID.Zero; + } + + /// + /// Capability originating call to update the asset of a script in a prim's (task's) inventory + /// + /// + /// + /// The prim which contains the item to update + /// Indicates whether the script to update is currently running + /// + public void CapsUpdateTaskInventoryScriptAsset(IClientAPI remoteClient, LLUUID itemId, + LLUUID primId, bool isScriptRunning, byte[] data) + { + // Retrieve group + SceneObjectPart part = GetSceneObjectPart(primId); + SceneObjectGroup group = part.ParentGroup; + if (null == group) + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Prim inventory update requested for item ID {0} in prim ID {1} but this prim does not exist", + itemId, primId); + + return; + } + + // Retrieve item + TaskInventoryItem item = group.GetInventoryItem(part.LocalID, itemId); + if (null == item) + { + return; + } + + // Create new asset + // XXX Hardcoding the numbers is a temporary measure - need an enumeration for this + // There may well be one in libsecondlife + AssetBase asset = CreateAsset(item.Name, item.Description, 10, 10, data); + AssetCache.AddAsset(asset); + + // Update item with new asset + item.AssetID = asset.FullID; + group.UpdateInventoryItem(item); + group.GetProperties(remoteClient); + + // Trigger rerunning of script (use TriggerRezScript event, see RezScript) + if (isScriptRunning) + { + group.StopScript(part.LocalID, item.ItemID); + group.StartScript(part.LocalID, item.ItemID); + } + } + + /// + /// CapsUpdateTaskInventoryScriptAsset(IClientAPI, LLUUID, LLUUID, bool, byte[]) + /// + private void CapsUpdateTaskInventoryScriptAsset(LLUUID avatarId, LLUUID itemId, + LLUUID primId, bool isScriptRunning, byte[] data) + { + ScenePresence avatar; + + if (TryGetAvatar(avatarId, out avatar)) + { + CapsUpdateTaskInventoryScriptAsset( + avatar.ControllingClient, itemId, primId, isScriptRunning, data); + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Avatar {0} cannot be found to update its prim item asset", + avatarId); + } + } + + /// + /// Update an item which is either already in the client's inventory or is within + /// a transaction + /// + /// + /// The transaction ID. If this is LLUUID.Zero we will + /// assume that we are not in a transaction + /// The ID of the updated item + /// The name of the updated item + /// The description of the updated item + /// The permissions of the updated item + public void UpdateInventoryItemAsset(IClientAPI remoteClient, LLUUID transactionID, + LLUUID itemID, string name, string description, + uint nextOwnerMask) + { + CachedUserInfo userInfo + = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); + + if (userInfo != null && userInfo.RootFolder != null) + { + InventoryItemBase item = userInfo.RootFolder.HasItem(itemID); + + if (item != null) + { + if (LLUUID.Zero == transactionID) + { + item.inventoryName = name; + item.inventoryDescription = description; + item.inventoryNextPermissions = nextOwnerMask; + + userInfo.UpdateItem(remoteClient.AgentId, item); + } + else + { + IAgentAssetTransactions agentTransactions = this.RequestModuleInterface(); + if (agentTransactions != null) + { + agentTransactions.HandleItemUpdateFromTransaction( + remoteClient, transactionID, item); + } + } + } + else + { + m_log.Error( + "[AGENTINVENTORY]: Item ID " + itemID + " not found for an inventory item update."); + } + } + else + { + m_log.Error( + "[AGENTINVENTORY]: Agent ID " + remoteClient.AgentId + " not found for an inventory item update."); + } + } + + public void CopyInventoryItem(IClientAPI remoteClient, uint callbackID, LLUUID oldAgentID, LLUUID oldItemID, + LLUUID newFolderID, string newName) + { + InventoryItemBase item = CommsManager.UserProfileCacheService.libraryRoot.HasItem(oldItemID); + if (item == null) + { + CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(oldAgentID); + if (userInfo == null) + { + m_log.Error("[AGENTINVENTORY]: Failed to find user " + oldAgentID.ToString()); + return; + } + + if (userInfo.RootFolder != null) + { + item = userInfo.RootFolder.HasItem(oldItemID); + if (item == null) + { + m_log.Error("[AGENTINVENTORY]: Failed to find item " + oldItemID.ToString()); + return; + } + } + else + { + m_log.Error("[AGENTINVENTORY]: Failed to find item " + oldItemID.ToString()); + return; + } + } + + + AssetBase asset = AssetCache.CopyAsset(item.assetID); + if (asset == null) + { + m_log.Warn("[AGENTINVENTORY]: Failed to find asset " + item.assetID.ToString()); + return; + } + + asset.Name = (newName.Length == 0) ? item.inventoryName : newName; + + // TODO: preserve current permissions? + CreateNewInventoryItem(remoteClient, newFolderID, callbackID, asset, item.inventoryNextPermissions); + } + + private AssetBase CreateAsset(string name, string description, sbyte invType, sbyte assetType, byte[] data) + { + AssetBase asset = new AssetBase(); + asset.Name = name; + asset.Description = description; + asset.InvType = invType; + asset.Type = assetType; + asset.FullID = LLUUID.Random(); // TODO: check for conflicts + asset.Data = (data == null) ? new byte[1] : data; + return asset; + } + + public void MoveInventoryItem(IClientAPI remoteClient, LLUUID folderID, LLUUID itemID, int length, + string newName) + { + m_log.Info( + "[AGENTINVENTORY]: " + + "Moving item for " + remoteClient.AgentId.ToString()); + + CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); + if (userInfo == null) + { + m_log.Error("[AGENTINVENTORY]: Failed to find user " + remoteClient.AgentId.ToString()); + return; + } + + if (userInfo.RootFolder != null) + { + InventoryItemBase item = userInfo.RootFolder.HasItem(itemID); + if (item != null) + { + if (newName != System.String.Empty) + { + item.inventoryName = newName; + } + item.parentFolderID = folderID; + userInfo.DeleteItem(remoteClient.AgentId, item); + + // TODO: preserve current permissions? + AddInventoryItem(remoteClient, item); + } + else + { + m_log.Error("[AGENTINVENTORY]: Failed to find item " + itemID.ToString()); + return; + } + } + else + { + m_log.Error("[AGENTINVENTORY]: Failed to find item " + itemID.ToString() + ", no root folder"); + return; + } + } + + /// + /// Create a new inventory item. + /// + /// + /// + /// + /// + /// + private void CreateNewInventoryItem(IClientAPI remoteClient, LLUUID folderID, uint callbackID, + AssetBase asset, uint nextOwnerMask) + { + CachedUserInfo userInfo + = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); + + if (userInfo != null) + { + InventoryItemBase item = new InventoryItemBase(); + item.avatarID = remoteClient.AgentId; + item.creatorsID = remoteClient.AgentId; + item.inventoryID = LLUUID.Random(); + item.assetID = asset.FullID; + item.inventoryDescription = asset.Description; + item.inventoryName = asset.Name; + item.assetType = asset.Type; + item.invType = asset.InvType; + item.parentFolderID = folderID; + item.inventoryCurrentPermissions = 2147483647; + item.inventoryNextPermissions = nextOwnerMask; + + userInfo.AddItem(remoteClient.AgentId, item); + remoteClient.SendInventoryItemCreateUpdate(item); + } + else + { + m_log.WarnFormat( + "No user details associated with client {0} uuid {1} in CreateNewInventoryItem!", + remoteClient.Name, remoteClient.AgentId); + } + } + + /// + /// Create a new inventory item. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public void CreateNewInventoryItem(IClientAPI remoteClient, LLUUID transactionID, LLUUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte assetType, + byte wearableType, uint nextOwnerMask) + { + if (transactionID == LLUUID.Zero) + { + CachedUserInfo userInfo + = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); + + if (userInfo != null) + { + AssetBase asset = CreateAsset(name, description, invType, assetType, null); + AssetCache.AddAsset(asset); + + CreateNewInventoryItem(remoteClient, folderID, callbackID, asset, nextOwnerMask); + } + else + { + m_log.ErrorFormat( + "userInfo for agent uuid {0} unexpectedly null in CreateNewInventoryItem", + remoteClient.AgentId); + } + } + else + { + IAgentAssetTransactions agentTransactions = this.RequestModuleInterface(); + if (agentTransactions != null) + { + agentTransactions.HandleItemCreationFromTransaction( + remoteClient, transactionID, folderID, callbackID, description, + name, invType, assetType, wearableType, nextOwnerMask); + } + + + } + } + + private void RemoveInventoryItem(IClientAPI remoteClient, LLUUID itemID) + { + CachedUserInfo userInfo + = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); + if (userInfo == null) + { + m_log.Error("[AGENTINVENTORY]: Failed to find user " + remoteClient.AgentId.ToString()); + return; + } + + // is going through the root folder really the best way? + // this triggers a tree walk to find and remove the item. 8-( + // since this only happens in Trash (in theory) shouldn't we grab + // the trash folder directly instead of RootFolder? + if (userInfo.RootFolder != null) + { + InventoryItemBase item = userInfo.RootFolder.HasItem(itemID); + if (item != null) + { + userInfo.DeleteItem(remoteClient.AgentId, item); + } + } + } + + private void RemoveInventoryFolder(IClientAPI remoteClient, LLUUID folderID) + { + CachedUserInfo userInfo + = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); + if (userInfo == null) + { + m_log.Error("[AGENTINVENTORY]: Failed to find user " + remoteClient.AgentId.ToString()); + return; + } + + if (userInfo.RootFolder != null) + { + InventoryItemBase folder = userInfo.RootFolder.HasItem(folderID); + if (folder != null) + { + // doesn't work just yet, commented out. WIll fix in next patch. + // userInfo.DeleteItem(remoteClient.AgentId, folder); + } + } + } + + private SceneObjectGroup GetGroupByPrim(uint localID) + { + List EntitieList = GetEntities(); + + foreach (EntityBase ent in EntitieList) + { + if (ent is SceneObjectGroup) + { + if (((SceneObjectGroup) ent).HasChildPrim(localID)) + return (SceneObjectGroup) ent; + } + } + return null; + } + + /// + /// Request a prim (task) inventory + /// + /// + /// + public void RequestTaskInventory(IClientAPI remoteClient, uint primLocalID) + { + SceneObjectGroup group = GetGroupByPrim(primLocalID); + if (group != null) + { + bool fileChange = group.GetPartInventoryFileName(remoteClient, primLocalID); + if (fileChange) + { + if (XferManager != null) + { + group.RequestInventoryFile(primLocalID, XferManager); + } + } + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: Inventory requested of prim {0} which doesn't exist", primLocalID); + } + } + + /// + /// Remove an item from a prim (task) inventory + /// + /// Unused at the moment but retained since the avatar ID might + /// be necessary for a permissions check at some stage. + /// + /// + public void RemoveTaskInventory(IClientAPI remoteClient, LLUUID itemID, uint localID) + { + SceneObjectGroup group = GetGroupByPrim(localID); + if (group != null) + { + int type = group.RemoveInventoryItem(localID, itemID); + group.GetProperties(remoteClient); + if (type == 10) + { + EventManager.TriggerRemoveScript(localID, itemID); + } + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Removal of item {0} requested of prim {1} but this prim does not exist", + itemID, + localID); + } + } + + /// + /// Update an item in a prim (task) inventory. + /// This method does not handle scripts, RezScript(IClientAPI, LLUUID, unit) + /// + /// + /// + /// + /// + public void UpdateTaskInventory(IClientAPI remoteClient, LLUUID itemID, LLUUID folderID, + uint primLocalID) + { + SceneObjectGroup group = GetGroupByPrim(primLocalID); + if (group != null) + { + // TODO Retrieve itemID from client's inventory to pass on + //group.AddInventoryItem(remoteClient, primLocalID, null); + m_log.InfoFormat( + "[PRIMINVENTORY]: " + + "Non script prim inventory not yet implemented!" + + "\nUpdateTaskInventory called with item {0}, folder {1}, primLocalID {2}, user {3}", + itemID, folderID, primLocalID, remoteClient.Name); + } + else + { + m_log.WarnFormat( + "[PRIMINVENTORY]: " + + "Update with item {0} requested of prim {1} for {2} but this prim does not exist", + itemID, primLocalID, remoteClient.Name); + } + } + + /// + /// Rez a script into a prim's inventory + /// + /// + /// + /// + public void RezScript(IClientAPI remoteClient, LLUUID itemID, uint localID) + { + LLUUID copyID = LLUUID.Random(); + + if (itemID != LLUUID.Zero) + { + CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); + + if (userInfo != null && userInfo.RootFolder != null) + { + InventoryItemBase item = userInfo.RootFolder.HasItem(itemID); + + // Try library + // XXX clumsy, possibly should be one call + if (null == item) + { + item = CommsManager.UserProfileCacheService.libraryRoot.HasItem(itemID); + } + + if (item != null) + { + SceneObjectGroup group = GetGroupByPrim(localID); + if (group != null) + { + group.AddInventoryItem(remoteClient, localID, item, copyID); + group.StartScript(localID, copyID); + group.GetProperties(remoteClient); + + // m_log.InfoFormat("[PRIMINVENTORY]: " + + // "Rezzed script {0} into prim local ID {1} for user {2}", + // item.inventoryName, localID, remoteClient.Name); + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Could not rez script {0} into prim local ID {1} for user {2}" + + " because the prim could not be found in the region!", + item.inventoryName, localID, remoteClient.Name); + } + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: Could not find script inventory item {0} to rez for {1}!", + itemID, remoteClient.Name); + } + } + } + else // If the itemID is zero then the script has been rezzed directly in an object's inventory + { + // not yet implemented + // TODO Need to get more details from original RezScript packet + // XXX jc tmp +// AssetBase asset = CreateAsset("chimney sweep", "sailor.lsl", 10, 10, null); +// AssetCache.AddAsset(asset); + } + } + + /// + /// + /// + /// + /// + public virtual void DeRezObject(Packet packet, IClientAPI remoteClient) + { + DeRezObjectPacket DeRezPacket = (DeRezObjectPacket) packet; + + if (DeRezPacket.AgentBlock.DestinationID == LLUUID.Zero) + { + //currently following code not used (or don't know of any case of destination being zero + } + else + { + foreach (DeRezObjectPacket.ObjectDataBlock Data in DeRezPacket.ObjectData) + { + EntityBase selectedEnt = null; + //m_log.Info("[CLIENT]: LocalID:" + Data.ObjectLocalID.ToString()); + + List EntitieList = GetEntities(); + + foreach (EntityBase ent in EntitieList) + { + if (ent.LocalId == Data.ObjectLocalID) + { + selectedEnt = ent; + break; + } + } + if (selectedEnt != null) + { + if (PermissionsMngr.CanDeRezObject(remoteClient.AgentId, ((SceneObjectGroup) selectedEnt).UUID)) + { + string sceneObjectXml = ((SceneObjectGroup) selectedEnt).ToXmlString(); + CachedUserInfo userInfo = + CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); + if (userInfo != null) + { + AssetBase asset = CreateAsset( + ((SceneObjectGroup) selectedEnt).GetPartName(selectedEnt.LocalId), + ((SceneObjectGroup) selectedEnt).GetPartDescription(selectedEnt.LocalId), + (sbyte) InventoryType.Object, + (sbyte) AssetType.Primitive, + Helpers.StringToField(sceneObjectXml)); + AssetCache.AddAsset(asset); + + InventoryItemBase item = new InventoryItemBase(); + item.avatarID = remoteClient.AgentId; + item.creatorsID = remoteClient.AgentId; + item.inventoryID = LLUUID.Random(); // TODO: check for conflicts + item.assetID = asset.FullID; + item.inventoryDescription = asset.Description; + item.inventoryName = asset.Name; + item.assetType = asset.Type; + item.invType = asset.InvType; + item.parentFolderID = DeRezPacket.AgentBlock.DestinationID; + item.inventoryCurrentPermissions = 2147483647; + item.inventoryNextPermissions = 2147483647; + item.inventoryEveryOnePermissions = + ((SceneObjectGroup) selectedEnt).RootPart.EveryoneMask; + item.inventoryBasePermissions = ((SceneObjectGroup) selectedEnt).RootPart.BaseMask; + item.inventoryCurrentPermissions = ((SceneObjectGroup) selectedEnt).RootPart.OwnerMask; + + userInfo.AddItem(remoteClient.AgentId, item); + remoteClient.SendInventoryItemCreateUpdate(item); + } + + DeleteSceneObjectGroup((SceneObjectGroup) selectedEnt); + } + } + } + } + } + + public void DeleteSceneObjectGroup(SceneObjectGroup group) + { + SceneObjectPart rootPart = (group).GetChildPart(group.UUID); + if (rootPart.PhysActor != null) + { + PhysicsScene.RemovePrim(rootPart.PhysActor); + rootPart.PhysActor = null; + } + + m_storageManager.DataStore.RemoveObject(group.UUID, m_regInfo.RegionID); + group.DeleteGroup(); + + lock (Entities) + { + Entities.Remove(group.UUID); + m_innerScene.RemoveAPrimCount(); + } + group.DeleteParts(); + } + + public virtual void RezObject(IClientAPI remoteClient, LLUUID itemID, LLVector3 RayEnd, LLVector3 RayStart, + LLUUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, + uint EveryoneMask, uint GroupMask, uint NextOwnerMask, uint ItemFlags, + bool RezSelected, bool RemoveItem, LLUUID fromTaskID) + { + byte bRayEndIsIntersection = (byte)0; + + if (RayEndIsIntersection) + { + bRayEndIsIntersection = (byte)1; + } + else + { + bRayEndIsIntersection = (byte)0; + } + + LLVector3 pos = GetNewRezLocation(RayStart, RayEnd, RayTargetID, new LLQuaternion(0, 0, 0, 1), BypassRayCast, bRayEndIsIntersection); + RezObject(remoteClient, itemID, pos); + } + + public virtual void RezObject(IClientAPI remoteClient, LLUUID itemID, LLVector3 pos) + { + CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); + if (userInfo != null) + { + if (userInfo.RootFolder != null) + { + InventoryItemBase item = userInfo.RootFolder.HasItem(itemID); + if (item != null) + { + AssetBase rezAsset = AssetCache.GetAsset(item.assetID, false); + + if (rezAsset != null) + { + AddRezObject(Helpers.FieldToUTF8String(rezAsset.Data), pos); + //userInfo.DeleteItem(remoteClient.AgentId, item); + //remoteClient.SendRemoveInventoryItem(itemID); + } + } + } + } + } + public void RezSingleAttachment(IClientAPI remoteClient, LLUUID itemID, uint AttachmentPt, + uint ItemFlags, uint NextOwnerMask) + { + System.Console.WriteLine("RezSingleAttachment: unimplemented yet"); + } + + + private void AddRezObject(string xmlData, LLVector3 pos) + { + SceneObjectGroup group = new SceneObjectGroup(this, m_regionHandle, xmlData); + group.ResetIDs(); + AddEntity(group); + group.AbsolutePosition = pos; + SceneObjectPart rootPart = group.GetChildPart(group.UUID); + rootPart.TrimPermissions(); + group.ApplyPhysics(m_physicalPrim); + group.StartScripts(); + + //bool UsePhysics = (((rootPart.ObjectFlags & (uint)LLObject.ObjectFlags.Physics) > 0)&& m_physicalPrim); + //if ((rootPart.ObjectFlags & (uint) LLObject.ObjectFlags.Phantom) == 0) + //{ + //PrimitiveBaseShape pbs = rootPart.Shape; + //rootPart.PhysActor = PhysicsScene.AddPrimShape( + //rootPart.Name, + //pbs, + //new PhysicsVector(rootPart.AbsolutePosition.X, rootPart.AbsolutePosition.Y, + // rootPart.AbsolutePosition.Z), + //new PhysicsVector(rootPart.Scale.X, rootPart.Scale.Y, rootPart.Scale.Z), + //new Quaternion(rootPart.RotationOffset.W, rootPart.RotationOffset.X, + // rootPart.RotationOffset.Y, rootPart.RotationOffset.Z), UsePhysics); + + // rootPart.DoPhysicsPropertyUpdate(UsePhysics, true); + + // } + // + rootPart.ScheduleFullUpdate(); + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs b/trunk/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs new file mode 100644 index 0000000000..7c0cd77f28 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs @@ -0,0 +1,218 @@ +/* +* 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.Collections.Generic; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.UserManagement; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Environment.Scenes +{ + public partial class Scene + { + /// + /// Modifies terrain using the specified information + /// + /// The height at which the user started modifying the terrain + /// The number of seconds the modify button was pressed + /// The size of the brush used + /// The action to be performed + /// Distance from the north border where the cursor is located + /// Distance from the west border where the cursor is located + public void ModifyTerrain(float height, float seconds, byte brushsize, byte action, float north, float west, + float south, float east, + IClientAPI remoteUser) + { + // Do a permissions check before allowing terraforming. + // random users are now no longer allowed to terraform + // if permissions are enabled. + if (!PermissionsMngr.CanTerraform(remoteUser.AgentId, new LLVector3(north, west, 0))) + return; + + //if it wasn't for the permission checking we could have the terrain module directly subscribe to the OnModifyTerrain event + Terrain.ModifyTerrain(height, seconds, brushsize, action, north, west, south, east, remoteUser); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public void SimChat(byte[] message, ChatTypeEnum type, int channel, LLVector3 fromPos, string fromName, + LLUUID fromAgentID) + { + if (m_simChatModule != null) + { + ChatFromViewerArgs args = new ChatFromViewerArgs(); + + args.Message = Helpers.FieldToUTF8String(message); + args.Channel = channel; + args.Type = type; + args.Position = fromPos; + + ScenePresence user = GetScenePresence(fromAgentID); + if (user != null) + args.Sender = user.ControllingClient; + else + args.Sender = null; + + args.From = fromName; + + m_simChatModule.SimChat(this, args); + } + } + + /// + /// + /// + /// + /// + public void SelectPrim(uint primLocalID, IClientAPI remoteClient) + { + List EntitieList = GetEntities(); + + foreach (EntityBase ent in EntitieList) + { + if (ent is SceneObjectGroup) + { + if (((SceneObjectGroup) ent).LocalId == primLocalID) + { + ((SceneObjectGroup) ent).GetProperties(remoteClient); + ((SceneObjectGroup) ent).IsSelected = true; + LandManager.setPrimsTainted(); + break; + } + } + } + } + + /// + /// + /// + /// + /// + public void DeselectPrim(uint primLocalID, IClientAPI remoteClient) + { + List EntitieList = GetEntities(); + + foreach (EntityBase ent in EntitieList) + { + if (ent is SceneObjectGroup) + { + if (((SceneObjectGroup) ent).LocalId == primLocalID) + { + ((SceneObjectGroup) ent).IsSelected = false; + LandManager.setPrimsTainted(); + break; + } + } + } + } + + public virtual void ProcessMoneyTransferRequest(LLUUID source, LLUUID destination, int amount, int transactiontype, string description) + { + EventManager.MoneyTransferArgs args = new EventManager.MoneyTransferArgs( + source, destination, amount, transactiontype, description); + + EventManager.TriggerMoneyTransfer(this, args); + } + + public virtual void ProcessObjectGrab(uint localID, LLVector3 offsetPos, IClientAPI remoteClient) + { + + List EntitieList = GetEntities(); + + foreach (EntityBase ent in EntitieList) + { + if (ent is SceneObjectGroup) + { + SceneObjectGroup obj = ent as SceneObjectGroup; + + // Is this prim part of the group + if (obj.HasChildPrim(localID)) + { + // Currently only grab/touch for the single prim + // the client handles rez correctly + obj.ObjectGrabHandler(localID, offsetPos, remoteClient); + + // trigger event, one for each prim part in the group + // so that a touch to a non-root prim in a group will still + // trigger a touch_start for a script in the root prim + foreach (SceneObjectPart part in obj.Children.Values) + { + EventManager.TriggerObjectGrab(part.LocalID, part.OffsetPosition, remoteClient); + } + + return; + } + } + } + } + + public void ProcessAvatarPickerRequest(IClientAPI client, LLUUID avatarID, LLUUID RequestID, string query) + { + //EventManager.TriggerAvatarPickerRequest(); + + List AvatarResponses = new List(); + AvatarResponses = m_sceneGridService.GenerateAgentPickerRequestResponse(RequestID, query); + + AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); + // TODO: don't create new blocks if recycling an old packet + + AvatarPickerReplyPacket.DataBlock[] searchData = + new AvatarPickerReplyPacket.DataBlock[AvatarResponses.Count]; + AvatarPickerReplyPacket.AgentDataBlock agentData = new AvatarPickerReplyPacket.AgentDataBlock(); + + agentData.AgentID = avatarID; + agentData.QueryID = RequestID; + replyPacket.AgentData = agentData; + //byte[] bytes = new byte[AvatarResponses.Count*32]; + + int i = 0; + foreach (AvatarPickerAvatar item in AvatarResponses) + { + LLUUID translatedIDtem = item.AvatarID; + searchData[i] = new AvatarPickerReplyPacket.DataBlock(); + searchData[i].AvatarID = translatedIDtem; + searchData[i].FirstName = Helpers.StringToField((string) item.firstName); + searchData[i].LastName = Helpers.StringToField((string) item.lastName); + i++; + } + if (AvatarResponses.Count == 0) + { + searchData = new AvatarPickerReplyPacket.DataBlock[0]; + } + replyPacket.Data = searchData; + client.SendAvatarPickerReply(replyPacket); + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/Scene.cs b/trunk/OpenSim/Region/Environment/Scenes/Scene.cs new file mode 100644 index 0000000000..7af3f5bd99 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/Scene.cs @@ -0,0 +1,2637 @@ +/* +* 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; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.Threading; +using System.Timers; +using Axiom.Math; +using libsecondlife; +using libsecondlife.Packets; +using OpenJPEGNet; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.LandManagement; +using OpenSim.Region.Environment.Modules; +using OpenSim.Region.Environment.Scenes.Scripting; +using OpenSim.Region.Physics.Manager; +using OpenSim.Region.Terrain; +using Caps = OpenSim.Region.Capabilities.Caps; +using Image = System.Drawing.Image; +using Timer = System.Timers.Timer; + +namespace OpenSim.Region.Environment.Scenes +{ + public delegate bool FilterAvatarList(ScenePresence avatar); + + public partial class Scene : SceneBase + { + #region Fields + + protected Timer m_heartbeatTimer = new Timer(); + protected Timer m_restartWaitTimer = new Timer(); + + protected SimStatsReporter m_statsReporter; + + protected List m_regionRestartNotifyList = new List(); + protected List m_neighbours = new List(); + + public InnerScene m_innerScene; + + private Random Rand = new Random(); + private uint _primCount = 720000; + private readonly Mutex _primAllocateMutex = new Mutex(false); + + private int m_timePhase = 24; + private int m_timeUpdateCount; + + private readonly Mutex updateLock; + public bool m_physicalPrim; + public bool m_seeIntoRegionFromNeighbor; + private int m_RestartTimerCounter; + private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing + private int m_incrementsof15seconds = 0; + + public string m_simulatorVersion = "OpenSimulator 0.5"; + + protected ModuleLoader m_moduleLoader; + protected StorageManager m_storageManager; + protected AgentCircuitManager m_authenticateHandler; + public CommunicationsManager CommsManager; + // protected XferManager xferManager; + protected SceneCommunicationService m_sceneGridService; + protected SceneXmlLoader m_sceneXmlLoader; + + protected Dictionary m_capsHandlers = new Dictionary(); + protected BaseHttpServer m_httpListener; + + protected Dictionary Modules = new Dictionary(); + public Dictionary ModuleInterfaces = new Dictionary(); + protected Dictionary ModuleAPIMethods = new Dictionary(); + + //API module interfaces + + public IXfer XferManager; + + protected IHttpRequests m_httpRequestModule; + protected ISimChat m_simChatModule; + protected IXMLRPC m_xmlrpcModule; + protected IWorldComm m_worldCommModule; + protected IAvatarFactory m_AvatarFactory; + + // Central Update Loop + + protected int m_fps = 10; + protected int m_frame = 0; + protected float m_timespan = 0.089f; + protected DateTime m_lastupdate = DateTime.Now; + + protected float m_timedilation = 1.0f; + + private int m_update_physics = 1; + private int m_update_entitymovement = 1; + private int m_update_entities = 1; + private int m_update_events = 1; + private int m_update_backup = 200; + private int m_update_terrain = 50; + private int m_update_land = 1; + private int m_update_avatars = 1; + + private int frameMS = 0; + private int physicsMS2 = 0; + private int physicsMS = 0; + private int otherMS = 0; + + private bool m_physics_enabled = true; + private bool m_physics_collisions_enabled = true; + private bool m_scripts_enabled = true; + + + + #endregion + + #region Properties + + public AgentCircuitManager AuthenticateHandler + { + get { return m_authenticateHandler; } + } + + protected readonly LandManager m_LandManager; + // LandManager object instance that manages land related things. Parcel, primcounts etc.. + public LandManager LandManager + { + get { return m_LandManager; } + } + + protected readonly EstateManager m_estateManager; + // an instance to the physics plugin's Scene object. + public PhysicsScene PhysicsScene + { + set { m_innerScene.PhysicsScene = value; } + get { return (m_innerScene.PhysicsScene); } + } + + // This gets locked so things stay thread safe. + public object SyncRoot + { + get { return m_innerScene.m_syncRoot; } + } + + public EstateManager EstateManager + { + get { return m_estateManager; } + } + + public float TimeDilation + { + get { return m_timedilation; } + } + + protected readonly PermissionManager m_permissionManager; + // This is the instance to the permissions manager. + // This manages permissions to clients on in world objects + + public PermissionManager PermissionsMngr + { + get { return m_permissionManager; } + } + + public int TimePhase + { + get { return m_timePhase; } + } + + // Local reference to the objects in the scene (which are held in innerScene) + // public Dictionary Objects + // { + // get { return m_innerScene.SceneObjects; } + // } + + // Reference to all of the agents in the scene (root and child) + protected Dictionary m_scenePresences + { + get { return m_innerScene.ScenePresences; } + set { m_innerScene.ScenePresences = value; } + } + + // protected Dictionary m_sceneObjects + // { + // get { return m_innerScene.SceneObjects; } + // set { m_innerScene.SceneObjects = value; } + // } + + public Dictionary Entities + { + get { return m_innerScene.Entities; } + set { m_innerScene.Entities = value; } + } + + #endregion + + #region Constructors + + public Scene(RegionInfo regInfo, AgentCircuitManager authen, PermissionManager permissionManager, + CommunicationsManager commsMan, SceneCommunicationService sceneGridService, + AssetCache assetCach, StorageManager storeManager, BaseHttpServer httpServer, + ModuleLoader moduleLoader, bool dumpAssetsToFile, bool physicalPrim, bool SeeIntoRegionFromNeighbor) + { + updateLock = new Mutex(false); + + m_moduleLoader = moduleLoader; + m_authenticateHandler = authen; + CommsManager = commsMan; + m_sceneGridService = sceneGridService; + m_sceneGridService.debugRegionName = regInfo.RegionName; + m_storageManager = storeManager; + AssetCache = assetCach; + m_regInfo = regInfo; + m_regionHandle = m_regInfo.RegionHandle; + m_regionName = m_regInfo.RegionName; + m_datastore = m_regInfo.DataStore; + + m_physicalPrim = physicalPrim; + m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor; + + m_eventManager = new EventManager(); + + m_LandManager = new LandManager(this, m_regInfo); + + //Bind Storage Manager functions to some land manager functions for this scene + EventManager.OnLandObjectAdded += + new EventManager.LandObjectAdded(m_storageManager.DataStore.StoreLandObject); + EventManager.OnLandObjectRemoved += + new EventManager.LandObjectRemoved(m_storageManager.DataStore.RemoveLandObject); + + m_estateManager = new EstateManager(this, m_regInfo); + + m_permissionManager = permissionManager; + m_permissionManager.Initialise(this); + + m_innerScene = new InnerScene(this, m_regInfo, m_permissionManager); + + // If the Inner scene has an Unrecoverable error, restart this sim. + // Currently the only thing that causes it to happen is two kinds of specific + // Physics based crashes. + // + // Out of memory + // Operating system has killed the plugin + m_innerScene.UnRecoverableError += RestartNow; + + m_sceneXmlLoader = new SceneXmlLoader(this, m_innerScene, m_regInfo); + + RegisterDefaultSceneEvents(); + + m_log.Info("[SCENE]: Creating new entitities instance"); + Entities = new Dictionary(); + m_scenePresences = new Dictionary(); + //m_sceneObjects = new Dictionary(); + + m_log.Info("[SCENE]: Creating LandMap"); + Terrain = new TerrainEngine((int)RegionInfo.RegionLocX, (int)RegionInfo.RegionLocY); + + m_httpListener = httpServer; + m_dumpAssetsToFile = dumpAssetsToFile; + + if ((RegionInfo.EstateSettings.regionFlags & Simulator.RegionFlags.SkipScripts) == Simulator.RegionFlags.SkipScripts) + { + m_scripts_enabled = false; + } + else + { + m_scripts_enabled = true; + } + if ((RegionInfo.EstateSettings.regionFlags & Simulator.RegionFlags.SkipPhysics) == Simulator.RegionFlags.SkipPhysics) + { + m_physics_enabled = false; + } + else + { + m_physics_enabled = true; + } + + m_statsReporter = new SimStatsReporter(regInfo); + m_statsReporter.OnSendStatsResult += SendSimStatsPackets; + string OSString = ""; + + if (System.Environment.OSVersion.Platform != PlatformID.Unix) + { + OSString = System.Environment.OSVersion.ToString(); + } + else + { + OSString = Util.ReadEtcIssue(); + } + if (OSString.Length > 45) + { + OSString = OSString.Substring(0, 45); + } + + m_simulatorVersion = "OpenSimulator v0.5-SVN on " + OSString + " ChilTasks:" + m_seeIntoRegionFromNeighbor.ToString() + " PhysPrim:" + m_physicalPrim.ToString(); + } + + #endregion + + #region Startup / Close Methods + + protected virtual void RegisterDefaultSceneEvents() + { + m_eventManager.OnParcelPrimCountAdd += m_LandManager.addPrimToLandPrimCounts; + m_eventManager.OnParcelPrimCountUpdate += addPrimsToParcelCounts; + m_eventManager.OnPermissionError += SendPermissionAlert; + } + + public override string GetSimulatorVersion() + { + return m_simulatorVersion; + } + + public override bool OtherRegionUp(RegionInfo otherRegion) + { + // Another region is up. + // Gets called from Grid Comms (SceneCommunicationService<---RegionListener<----LocalBackEnd<----OGS1) + // We have to tell all our ScenePresences about it.. + // and add it to the neighbor list. + + // We only add it to the neighbor list if it's within 1 region from here. + // Agents may have draw distance values that cross two regions though, so + // we add it to the notify list regardless of distance. + // We'll check the agent's draw distance before notifying them though. + + + if (RegionInfo.RegionHandle != otherRegion.RegionHandle) + { + for (int i = 0; i < m_neighbours.Count; i++) + { + // The purpose of this loop is to re-update the known neighbors + // when another region comes up on top of another one. + // The latest region in that location ends up in the + // 'known neighbors list' + // Additionally, the commFailTF property gets reset to false. + if (m_neighbours[i].RegionHandle == otherRegion.RegionHandle) + { + lock (m_neighbours) + { + m_neighbours[i] = otherRegion; + } + } + } + + // If the value isn't in the neighbours, add it. + // If the RegionInfo isn't exact but is for the same XY World location, + // then the above loop will fix that. + + if (!(m_neighbours.Contains(otherRegion))) + { + lock (m_neighbours) + { + m_neighbours.Add(otherRegion); + } + } + // If these are cast to INT because long + negative values + abs returns invalid data + + int resultX = Math.Abs((int)otherRegion.RegionLocX - (int)RegionInfo.RegionLocX); + int resultY = Math.Abs((int)otherRegion.RegionLocY - (int)RegionInfo.RegionLocY); + if ((resultX <= 1) && + (resultY <= 1)) + { + try + { + ForEachScenePresence(delegate(ScenePresence agent) + { + // If agent is a root agent. + if (!agent.IsChildAgent) + { + //agent.ControllingClient.new + //this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo()); + InformClientOfNeighbor(agent, otherRegion); + } + } + ); + } + catch (NullReferenceException) + { + // This means that we're not booted up completely yet. + // This shouldn't happen too often anymore. + m_log.Error("[SCENE]: Couldn't inform client of regionup because we got a null reference exception"); + } + } + else + { + m_log.Info("[INTERGRID]: Got notice about far away Region: " + otherRegion.RegionName.ToString() + + " at (" + otherRegion.RegionLocX.ToString() + ", " + + otherRegion.RegionLocY.ToString() + ")"); + } + } + return true; + } + + // Given float seconds, this will restart the region. + + public virtual void Restart(float seconds) + { + // notifications are done in 15 second increments + // so .. if the number of seconds is less then 15 seconds, it's not really a restart request + // It's a 'Cancel restart' request. + + // RestartNow() does immediate restarting. + if (seconds < 15) + { + m_restartTimer.Stop(); + SendGeneralAlert("Restart Aborted"); + } + else + { + // Now we figure out what to set the timer to that does the notifications and calls, RestartNow() + m_restartTimer.Interval = 15000; + m_incrementsof15seconds = (int)seconds / 15; + m_RestartTimerCounter = 0; + m_restartTimer.AutoReset = true; + m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); + m_log.Error("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); + m_restartTimer.Start(); + SendRegionMessageFromEstateTools(LLUUID.Random(), LLUUID.Random(), String.Empty, RegionInfo.RegionName + ": Restarting in 2 Minutes"); + //SendGeneralAlert(RegionInfo.RegionName + ": Restarting in 2 Minutes"); + } + } + + // The Restart timer has occured. + // We have to figure out if this is a notification or if the number of seconds specified in Restart + // have elapsed. + // If they have elapsed, call RestartNow() + public void RestartTimer_Elapsed(object sender, ElapsedEventArgs e) + { + m_RestartTimerCounter++; + if (m_RestartTimerCounter <= m_incrementsof15seconds) + { + if (m_RestartTimerCounter == 4 || m_RestartTimerCounter == 6 || m_RestartTimerCounter == 7) + SendRegionMessageFromEstateTools(LLUUID.Random(), LLUUID.Random(), String.Empty, RegionInfo.RegionName + ": Restarting in " + + ((8 - m_RestartTimerCounter) * 15) + " seconds"); + + // SendGeneralAlert(RegionInfo.RegionName + ": Restarting in " + ((8 - m_RestartTimerCounter)*15) + + //" seconds"); + } + else + { + m_restartTimer.Stop(); + m_restartTimer.AutoReset = false; + RestartNow(); + } + } + + // This causes the region to restart immediatley. + public void RestartNow() + { + if (PhysicsScene != null) + { + PhysicsScene.Dispose(); + } + + m_log.Error("[REGION]: Closing"); + Close(); + m_log.Error("[REGION]: Firing Region Restart Message"); + base.Restart(0); + } + + // This is a helper function that notifies root agents in this region that a new sim near them has come up + // This is in the form of a timer because when an instance of OpenSim.exe is started, + // Even though the sims initialize, they don't listen until 'all of the sims are initialized' + // If we tell an agent about a sim that's not listening yet, the agent will not be able to connect to it. + // subsequently the agent will never see the region come back online. + public void RestartNotifyWaitElapsed(object sender, ElapsedEventArgs e) + { + m_restartWaitTimer.Stop(); + lock (m_regionRestartNotifyList) + { + foreach (RegionInfo region in m_regionRestartNotifyList) + { + try + { + ForEachScenePresence(delegate(ScenePresence agent) + { + // If agent is a root agent. + if (!agent.IsChildAgent) + { + //agent.ControllingClient.new + //this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo()); + InformClientOfNeighbor(agent, region); + } + } + ); + } + catch (NullReferenceException) + { + // This means that we're not booted up completely yet. + // This shouldn't happen too often anymore. + } + } + + // Reset list to nothing. + m_regionRestartNotifyList.Clear(); + } + } + + public void SetSceneCoreDebug(bool ScriptEngine, bool CollisionEvents, bool PhysicsEngine) + { + if (m_scripts_enabled != !ScriptEngine) + { + // Tedd! Here's the method to disable the scripting engine! + if (ScriptEngine) + { + m_log.Info("Stopping all Scripts in Scene"); + lock (Entities) + { + foreach (EntityBase ent in Entities.Values) + { + if (ent is SceneObjectGroup) + { + ((SceneObjectGroup)ent).StopScripts(); + } + } + } + } + else + { + m_log.Info("Starting all Scripts in Scene"); + lock (Entities) + { + foreach (EntityBase ent in Entities.Values) + { + if (ent is SceneObjectGroup) + { + ((SceneObjectGroup)ent).StartScripts(); + } + } + } + + + } + m_scripts_enabled = !ScriptEngine; + m_log.Info("[TOTEDD]: Here is the method to trigger disabling of the scripting engine"); + } + if (m_physics_enabled != !PhysicsEngine) + { + m_physics_enabled = !PhysicsEngine; + + } + + } + + // This is the method that shuts down the scene. + public override void Close() + { + m_log.Warn("[SCENE]: Closing down the single simulator: " + RegionInfo.RegionName); + // Kick all ROOT agents with the message, 'The simulator is going down' + ForEachScenePresence(delegate(ScenePresence avatar) + { + if (avatar.KnownChildRegions.Contains(RegionInfo.RegionHandle)) + avatar.KnownChildRegions.Remove(RegionInfo.RegionHandle); + + if (!avatar.IsChildAgent) + avatar.ControllingClient.Kick("The simulator is going down."); + + avatar.ControllingClient.OutPacket(PacketPool.Instance.GetPacket(libsecondlife.Packets.PacketType.DisableSimulator), + ThrottleOutPacketType.Task); + }); + + // Wait here, or the kick messages won't actually get to the agents before the scene terminates. + Thread.Sleep(500); + + // Stop all client threads. + ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(true); }); + // Stop updating the scene objects and agents. + m_heartbeatTimer.Close(); + // close the inner scene + m_innerScene.Close(); + // De-register with region communications (events cleanup) + UnRegisterReginWithComms(); + + // Shut down all non shared modules. + foreach (IRegionModule module in Modules.Values) + { + if (!module.IsSharedModule) + { + module.Close(); + } + } + Modules.Clear(); + + // call the base class Close method. + base.Close(); + } + + /// + /// + /// + public void StartTimer() + { + m_log.Debug("[SCENE]: Starting timer"); + m_heartbeatTimer.Enabled = true; + m_heartbeatTimer.Interval = (int)(m_timespan * 1000); + m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); + } + + public void SetModuleInterfaces() + { + m_simChatModule = RequestModuleInterface(); + m_httpRequestModule = RequestModuleInterface(); + m_xmlrpcModule = RequestModuleInterface(); + m_worldCommModule = RequestModuleInterface(); + XferManager = RequestModuleInterface(); + m_AvatarFactory = RequestModuleInterface(); + } + + #endregion + + #region Update Methods + + /// + /// Performs per-frame updates regularly + /// + /// + /// + private void Heartbeat(object sender, EventArgs e) + { + Update(); + } + + /// + /// Performs per-frame updates on the scene, this should be the central scene loop + /// + public override void Update() + { + TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate; + // Aquire a lock so only one update call happens at once + updateLock.WaitOne(); + float physicsFPS = 0; + int agentsInScene = m_innerScene.GetRootAgentCount() + m_innerScene.GetChildAgentCount(); + + + if (agentsInScene > 21) + { + if (m_update_entities == 1) + { + m_update_avatars = 5; + m_update_entities = 5; + m_statsReporter.SetUpdateMS(6000); + } + } + else + { + if (m_update_entities == 5) + { + m_update_avatars = 1; + m_update_entities = 1; + m_statsReporter.SetUpdateMS(3000); + } + } + + + frameMS = System.Environment.TickCount; + try + { + // Increment the frame counter + m_frame++; + + // Loop it + if (m_frame == Int32.MaxValue) + m_frame = 0; + + + physicsMS2 = System.Environment.TickCount; + if ((m_frame % m_update_physics == 0) && m_physics_enabled) + m_innerScene.UpdatePreparePhysics(); + physicsMS2 = System.Environment.TickCount - physicsMS2; + + if (m_frame % m_update_entitymovement == 0) + m_innerScene.UpdateEntityMovement(); + + physicsMS = System.Environment.TickCount; + if ((m_frame % m_update_physics == 0) && m_physics_enabled) + physicsFPS = m_innerScene.UpdatePhysics( + Math.Max(SinceLastFrame.TotalSeconds, m_timespan) + ); + + physicsMS = System.Environment.TickCount - physicsMS; + physicsMS += physicsMS2; + + otherMS = System.Environment.TickCount; + if (m_frame % m_update_entities == 0) + m_innerScene.UpdateEntities(); + + if (m_frame % m_update_events == 0) + UpdateEvents(); + + if (m_frame % m_update_backup == 0) + UpdateStorageBackup(); + + if (m_frame % m_update_terrain == 0) + UpdateTerrain(); + + if (m_frame % m_update_land == 0) + UpdateLand(); + otherMS = System.Environment.TickCount - otherMS; + // if (m_frame%m_update_avatars == 0) + // UpdateInWorldTime(); + m_statsReporter.AddPhysicsFPS(physicsFPS); + m_statsReporter.AddTimeDilation(m_timedilation); + m_statsReporter.AddFPS(1); + m_statsReporter.AddInPackets(0); + m_statsReporter.SetRootAgents(m_innerScene.GetRootAgentCount()); + m_statsReporter.SetChildAgents(m_innerScene.GetChildAgentCount()); + m_statsReporter.SetObjects(m_innerScene.GetTotalObjects()); + m_statsReporter.SetActiveObjects(m_innerScene.GetActiveObjects()); + frameMS = System.Environment.TickCount - frameMS; + m_statsReporter.addFrameMS(frameMS); + m_statsReporter.addPhysicsMS(physicsMS); + m_statsReporter.addOtherMS(otherMS); + m_statsReporter.SetActiveScripts(m_innerScene.GetActiveScripts()); + m_statsReporter.addScriptLines(m_innerScene.GetScriptLPS()); + + } + catch (NotImplementedException) + { + throw; + } + catch (System.AccessViolationException e) + { + m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); + + } + catch (System.NullReferenceException e) + { + m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); + + } + catch (System.InvalidOperationException e) + { + m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); + + } + catch (Exception e) + { + m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); + } + finally + { + updateLock.ReleaseMutex(); + // Get actual time dilation + float tmpval = (m_timespan / (float)SinceLastFrame.TotalSeconds); + + // If actual time dilation is greater then one, we're catching up, so subtract + // the amount that's greater then 1 from the time dilation + if (tmpval > 1.0) + { + tmpval = tmpval - (tmpval - 1.0f); + } + m_timedilation = tmpval; + + m_lastupdate = DateTime.Now; + } + } + + //Updates the time in the viewer. + private void UpdateInWorldTime() + { + m_timeUpdateCount++; + if (m_timeUpdateCount > 600) + { + List avatars = GetAvatars(); + foreach (ScenePresence avatar in avatars) + { + avatar.ControllingClient.SendViewerTime(m_timePhase); + } + + m_timeUpdateCount = 0; + m_timePhase++; + if (m_timePhase > 94) + { + m_timePhase = 0; + } + } + } + + private void SendSimStatsPackets(SimStatsPacket pack) + { + List StatSendAgents = GetScenePresences(); + foreach (ScenePresence agent in StatSendAgents) + { + if (!agent.IsChildAgent) + { + pack.Header.Reliable = false; + agent.ControllingClient.OutPacket(pack, ThrottleOutPacketType.Task); + } + } + } + + private void UpdateLand() + { + if (m_LandManager.landPrimCountTainted) + { + //Perform land update of prim count + performParcelPrimCountUpdate(); + } + } + + private void UpdateTerrain() + { + if (Terrain.IsTainted() && !Terrain.IsUserStillEditing()) + { + CreateTerrainTexture(true); + + lock (Terrain.heightmap) + { + lock (SyncRoot) + { + PhysicsScene.SetTerrain(Terrain.GetHeights1D()); + } + + m_storageManager.DataStore.StoreTerrain(Terrain.GetHeights2DD(), RegionInfo.RegionID); + + SendTerrainUpdate(true); + + Terrain.ResetTaint(); + } + } + } + + public void SendTerrainUpdate(bool checkForTainted) + { + float[] terData = Terrain.GetHeights1D(); + + Broadcast(delegate(IClientAPI client) + { + for (int x = 0; x < 16; x++) + { + for (int y = 0; y < 16; y++) + { + if ((!checkForTainted) || (Terrain.IsTainted(x * 16, y * 16))) + { + client.SendLayerData(x, y, terData); + } + } + } + }); + } + + private void UpdateStorageBackup() + { + Backup(); + } + + private void UpdateEvents() + { + m_eventManager.TriggerOnFrame(); + } + + /// + /// Perform delegate action on all clients subscribing to updates from this region. + /// + /// + internal void Broadcast(Action whatToDo) + { + ForEachScenePresence(delegate(ScenePresence presence) { whatToDo(presence.ControllingClient); }); + } + + /// + /// + /// + /// + public bool Backup() + { + EventManager.TriggerOnBackup(m_storageManager.DataStore); + return true; + } + + #endregion + + #region Load Terrain + + public void ExportWorldMap(string fileName) + { + List mapBlocks = + m_sceneGridService.RequestNeighbourMapBlocks((int)(RegionInfo.RegionLocX - 9), + (int)(RegionInfo.RegionLocY - 9), + (int)(RegionInfo.RegionLocX + 9), + (int)(RegionInfo.RegionLocY + 9)); + List textures = new List(); + List bitImages = new List(); + + foreach (MapBlockData mapBlock in mapBlocks) + { + AssetBase texAsset = AssetCache.GetAsset(mapBlock.MapImageId, true); + + if (texAsset != null) + { + textures.Add(texAsset); + } + else + { + texAsset = AssetCache.GetAsset(mapBlock.MapImageId, true); + if (texAsset != null) + { + textures.Add(texAsset); + } + } + } + + foreach (AssetBase asset in textures) + { + Image image = OpenJPEG.DecodeToImage(asset.Data); + bitImages.Add(image); + } + + Bitmap mapTexture = new Bitmap(2560, 2560); + Graphics g = Graphics.FromImage(mapTexture); + SolidBrush sea = new SolidBrush(Color.DarkBlue); + g.FillRectangle(sea, 0, 0, 2560, 2560); + + for (int i = 0; i < mapBlocks.Count; i++) + { + ushort x = (ushort)((mapBlocks[i].X - RegionInfo.RegionLocX) + 10); + ushort y = (ushort)((mapBlocks[i].Y - RegionInfo.RegionLocY) + 10); + g.DrawImage(bitImages[i], (x * 128), (y * 128), 128, 128); + } + mapTexture.Save(fileName, ImageFormat.Jpeg); + } + + /// + /// Loads a world map from a specified R32 file + /// + /// A working R32 file + public void LoadWorldMap(string filename) + { + Terrain.LoadFromFileF32(filename); + Terrain.SaveRevertMap(); + } + + /// + /// Loads the World heightmap + /// + /// + public override void LoadWorldMap() + { + try + { + double[,] map = m_storageManager.DataStore.LoadTerrain(RegionInfo.RegionID); + if (map == null) + { + if (string.IsNullOrEmpty(m_regInfo.EstateSettings.terrainFile)) + { + m_log.Info("[TERRAIN]: No default terrain. Generating a new terrain."); + Terrain.SetDefaultTerrain(); + + m_storageManager.DataStore.StoreTerrain(Terrain.GetHeights2DD(), RegionInfo.RegionID); + } + else + { + try + { + Terrain.LoadFromFileF32(m_regInfo.EstateSettings.terrainFile); + Terrain *= m_regInfo.EstateSettings.terrainMultiplier; + } + catch + { + m_log.Info("[TERRAIN]: No terrain found in database or default. Generating a new terrain."); + Terrain.SetDefaultTerrain(); + } + m_storageManager.DataStore.StoreTerrain(Terrain.GetHeights2DD(), RegionInfo.RegionID); + } + } + else + { + Terrain.SetHeights2D(map); + } + + CreateTerrainTexture(true); + //CommsManager.GridService.RegisterRegion(RegionInfo); //hack to update the terrain texture in grid mode so it shows on world map + } + catch (Exception e) + { + m_log.Warn("[terrain]: Scene.cs: LoadWorldMap() - Failed with exception " + e.ToString()); + } + } + + public void RegisterRegionWithGrid() + { + RegisterCommsEvents(); + // These two 'commands' *must be* next to each other or sim rebooting fails. + m_sceneGridService.RegisterRegion(RegionInfo); + m_sceneGridService.InformNeighborsThatRegionisUp(RegionInfo); + Dictionary dGridSettings = m_sceneGridService.GetGridSettings(); + if (dGridSettings.ContainsKey("allow_forceful_banlines")) + { + if (dGridSettings["allow_forceful_banlines"] != "TRUE") + { + m_log.Info("[GRID]: Grid is disabling forceful parcel banlists"); + m_LandManager.allowedForcefulBans = false; + } + else + { + m_log.Info("[GRID]: Grid is allowing forceful parcel banlists"); + m_LandManager.allowedForcefulBans = true; + } + } + } + + /// + /// + /// + public void CreateTerrainTexture(bool temporary) + { + //create a texture asset of the terrain + byte[] data = Terrain.WriteJpegImage("defaultstripe.png"); + m_regInfo.EstateSettings.terrainImageID = LLUUID.Random(); + AssetBase asset = new AssetBase(); + asset.FullID = m_regInfo.EstateSettings.terrainImageID; + asset.Data = data; + asset.Name = "terrainImage"; + asset.Description = RegionInfo.RegionName; + asset.Type = 0; + asset.Temporary = temporary; + AssetCache.AddAsset(asset); + } + + #endregion + + #region Load Land + + public void loadAllLandObjectsFromStorage() + { + m_log.Info("[SCENE]: Loading land objects from storage"); + List landData = m_storageManager.DataStore.LoadLandObjects(RegionInfo.RegionID); + + if (landData.Count == 0) + { + m_LandManager.NoLandDataFromStorage(); + } + else + { + m_LandManager.IncomingLandObjectsFromStorage(landData); + } + } + + #endregion + + #region Primitives Methods + + /// + /// Loads the World's objects + /// + public virtual void LoadPrimsFromStorage(bool m_permissions) + { + m_log.Info("[SCENE]: Loading objects from datastore"); + + List PrimsFromDB = m_storageManager.DataStore.LoadObjects(m_regInfo.RegionID); + foreach (SceneObjectGroup group in PrimsFromDB) + { + AddEntityFromStorage(group); + SceneObjectPart rootPart = group.GetChildPart(group.UUID); + rootPart.ObjectFlags &= ~(uint)LLObject.ObjectFlags.Scripted; + rootPart.TrimPermissions(); + + group.ApplyPhysics(m_physicalPrim); + //rootPart.DoPhysicsPropertyUpdate(UsePhysics, true); + } + + m_log.Info("[SCENE]: Loaded " + PrimsFromDB.Count.ToString() + " SceneObject(s)"); + } + + + /// + /// Returns a new unallocated primitive ID + /// + /// A brand new primitive ID + public uint PrimIDAllocate() + { + uint myID; + + _primAllocateMutex.WaitOne(); + ++_primCount; + myID = _primCount; + _primAllocateMutex.ReleaseMutex(); + + return myID; + } + + public LLVector3 GetNewRezLocation(LLVector3 RayStart, LLVector3 RayEnd, LLUUID RayTargetID, LLQuaternion rot, byte bypassRayCast, byte RayEndIsIntersection) + { + LLVector3 pos = LLVector3.Zero; + if (RayEndIsIntersection == (byte)1) + { + pos = RayEnd; + return pos; + } + if (RayTargetID != LLUUID.Zero) + { + SceneObjectPart target = GetSceneObjectPart(RayTargetID); + if (target != null) + { + pos = target.AbsolutePosition; + // TODO: Raytrace here + return pos; + } + else + { + // fall back to our stupid functionality + pos = RayEnd; + return pos; + } + } + else + { + // fall back to our stupid functionality + pos = RayEnd; + return pos; + } + } + + public virtual void AddNewPrim(LLUUID ownerID, LLVector3 RayEnd, LLQuaternion rot, PrimitiveBaseShape shape, + byte bypassRaycast, LLVector3 RayStart, LLUUID RayTargetID, + byte RayEndIsIntersection) + { + LLVector3 pos = GetNewRezLocation(RayStart, RayEnd, RayTargetID, rot, bypassRaycast, RayEndIsIntersection); + + if (PermissionsMngr.CanRezObject(ownerID, pos)) + { + // rez ON the ground, not IN the ground + pos.Z += 0.25F; + + + AddNewPrim(ownerID, pos, rot, shape); + } + } + + public virtual SceneObjectGroup AddNewPrim(LLUUID ownerID, LLVector3 pos, LLQuaternion rot, PrimitiveBaseShape shape) + { + SceneObjectGroup sceneOb = + new SceneObjectGroup(this, m_regionHandle, ownerID, PrimIDAllocate(), pos, rot, shape); + AddEntity(sceneOb); + SceneObjectPart rootPart = sceneOb.GetChildPart(sceneOb.UUID); + // if grass or tree, make phantom + //rootPart.TrimPermissions(); + if ((rootPart.Shape.PCode == 95) || (rootPart.Shape.PCode == 255) || (rootPart.Shape.PCode == 111)) + { + rootPart.AddFlag(LLObject.ObjectFlags.Phantom); + //rootPart.ObjectFlags += (uint)LLObject.ObjectFlags.Phantom; + } + // if not phantom, add to physics + sceneOb.ApplyPhysics(m_physicalPrim); + + return sceneOb; + } + + public SceneObjectGroup AddTree(LLVector3 scale, LLQuaternion rotation, LLVector3 position, + Tree treeType, bool newTree) + { + LLUUID uuid = this.RegionInfo.MasterAvatarAssignedUUID; + PrimitiveBaseShape treeShape = new PrimitiveBaseShape(); + treeShape.PathCurve = 16; + treeShape.PathEnd = 49900; + treeShape.PCode = newTree ? (byte)PCode.NewTree : (byte)PCode.Tree; + treeShape.Scale = scale; + treeShape.State = (byte)treeType; + return AddNewPrim(uuid, position, rotation, treeShape); + } + + public void RemovePrim(uint localID, LLUUID avatar_deleter) + { + m_innerScene.RemovePrim(localID, avatar_deleter); + } + + public void AddEntityFromStorage(SceneObjectGroup sceneObject) + { + m_innerScene.AddEntityFromStorage(sceneObject); + } + + public void AddEntity(SceneObjectGroup sceneObject) + { + m_innerScene.AddEntity(sceneObject); + } + + public void RemoveEntity(SceneObjectGroup sceneObject) + { + if (Entities.ContainsKey(sceneObject.UUID)) + { + m_LandManager.removePrimFromLandPrimCounts(sceneObject); + Entities.Remove(sceneObject.UUID); + m_LandManager.setPrimsTainted(); + m_innerScene.RemoveAPrimCount(); + } + } + + /// + /// Called by a prim when it has been created/cloned, so that its events can be subscribed to + /// + /// + public void AcknowledgeNewPrim(SceneObjectGroup prim) + { + prim.OnPrimCountTainted += m_LandManager.setPrimsTainted; + } + + public void LoadPrimsFromXml(string fileName, bool newIdsFlag, LLVector3 loadOffset) + { + m_sceneXmlLoader.LoadPrimsFromXml(fileName, newIdsFlag, loadOffset); + } + + public void SavePrimsToXml(string fileName) + { + m_sceneXmlLoader.SavePrimsToXml(fileName); + } + + public void LoadPrimsFromXml2(string fileName) + { + m_sceneXmlLoader.LoadPrimsFromXml2(fileName); + } + + public void SavePrimsToXml2(string fileName) + { + m_sceneXmlLoader.SavePrimsToXml2(fileName); + } + + public void CrossPrimGroupIntoNewRegion(LLVector3 position, SceneObjectGroup grp) + { + m_log.Warn("Prim crossing: " + grp.UUID.ToString()); + int thisx = (int)RegionInfo.RegionLocX; + int thisy = (int)RegionInfo.RegionLocY; + ulong newRegionHandle = 0; + LLVector3 pos = position; + + if (position.X > Constants.RegionSize + 0.1f) + { + pos.X = ((pos.X - Constants.RegionSize)); + + newRegionHandle = Util.UIntsToLong((uint)((thisx + 1) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize)); + + // x + 1 + } + else if (position.X < -0.1f) + { + pos.X = ((pos.X + Constants.RegionSize)); + newRegionHandle = Util.UIntsToLong((uint)((thisx - 1) * Constants.RegionSize), (uint)(thisy * Constants.RegionSize)); + // x - 1 + } + + if (position.Y > Constants.RegionSize + 0.1f) + { + pos.Y = ((pos.Y - Constants.RegionSize)); + newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + 1) * Constants.RegionSize)); + // y + 1 + } + else if (position.Y < -1f) + { + pos.Y = ((pos.Y + Constants.RegionSize)); + newRegionHandle = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - 1) * Constants.RegionSize)); + // y - 1 + } + + // Offset the positions for the new region across the border + grp.OffsetForNewRegion(pos); + + if (newRegionHandle != 0) + { + bool successYN = false; + successYN = m_sceneGridService.PrimCrossToNeighboringRegion(newRegionHandle, grp.UUID, m_sceneXmlLoader.SavePrimGroupToXML2String(grp)); + if (successYN) + { + // We remove the object here + try + { + DeleteSceneObjectGroup(grp); + } + catch (System.Exception) + { + m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border."); + } + } + else + { + m_log.Warn("[INTERREGION]: Prim Crossing Failed!"); + if (grp.RootPart != null) + { + if (grp.RootPart.PhysActor != null) + { + grp.RootPart.PhysActor.CrossingFailure(); + } + } + } + } + } + public void IncomingInterRegionPrimGroup(ulong regionHandle, LLUUID primID, string objXMLData) + { + m_log.Warn("{[INTERREGION]: A new prim arrived from a neighbor"); + m_sceneXmlLoader.LoadGroupFromXml2String(objXMLData); + + } + #endregion + + #region Add/Remove Avatar Methods + + /// + /// + /// + /// + public override void AddNewClient(IClientAPI client, bool child) + { + m_log.Warn("[CONNECTION DEBUGGING]: Creating new client for " + client.AgentId.ToString()); + SubscribeToClientEvents(client); + + m_estateManager.sendRegionHandshake(client); + + CreateAndAddScenePresence(client, child); + + m_LandManager.sendParcelOverlay(client); + CommsManager.UserProfileCacheService.AddNewUser(client.AgentId); + } + + protected virtual void SubscribeToClientEvents(IClientAPI client) + { + client.OnRegionHandShakeReply += SendLayerData; + //remoteClient.OnRequestWearables += new GenericCall(this.GetInitialPrims); + client.OnModifyTerrain += ModifyTerrain; + // client.OnRequestWearables += InformClientOfNeighbours; + client.OnAddPrim += AddNewPrim; + client.OnUpdatePrimGroupPosition += m_innerScene.UpdatePrimPosition; + client.OnUpdatePrimSinglePosition += m_innerScene.UpdatePrimSinglePosition; + client.OnUpdatePrimGroupRotation += m_innerScene.UpdatePrimRotation; + client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; + client.OnUpdatePrimSingleRotation += m_innerScene.UpdatePrimSingleRotation; + client.OnUpdatePrimScale += m_innerScene.UpdatePrimScale; + client.OnUpdateExtraParams += m_innerScene.UpdateExtraParam; + client.OnUpdatePrimShape += m_innerScene.UpdatePrimShape; + client.OnRequestMapBlocks += RequestMapBlocks; + client.OnUpdatePrimTexture += m_innerScene.UpdatePrimTexture; + client.OnTeleportLocationRequest += RequestTeleportLocation; + client.OnObjectSelect += SelectPrim; + client.OnObjectDeselect += DeselectPrim; + client.OnGrabUpdate += m_innerScene.MoveObject; + client.OnDeRezObject += DeRezObject; + client.OnRezObject += RezObject; + client.OnRezSingleAttachmentFromInv += RezSingleAttachment; + client.OnObjectAttach += m_innerScene.AttachObject; + client.OnNameFromUUIDRequest += CommsManager.HandleUUIDNameRequest; + client.OnObjectDescription += m_innerScene.PrimDescription; + client.OnObjectName += m_innerScene.PrimName; + client.OnLinkObjects += m_innerScene.LinkObjects; + client.OnDelinkObjects += m_innerScene.DelinkObjects; + client.OnObjectDuplicate += m_innerScene.DuplicateObject; + client.OnUpdatePrimFlags += m_innerScene.UpdatePrimFlags; + client.OnRequestObjectPropertiesFamily += m_innerScene.RequestObjectPropertiesFamily; + client.OnParcelPropertiesRequest += new ParcelPropertiesRequest(m_LandManager.handleParcelPropertiesRequest); + client.OnParcelDivideRequest += new ParcelDivideRequest(m_LandManager.handleParcelDivideRequest); + client.OnParcelJoinRequest += new ParcelJoinRequest(m_LandManager.handleParcelJoinRequest); + client.OnParcelPropertiesUpdateRequest += + new ParcelPropertiesUpdateRequest(m_LandManager.handleParcelPropertiesUpdateRequest); + client.OnParcelSelectObjects += new ParcelSelectObjects(m_LandManager.handleParcelSelectObjectsRequest); + client.OnParcelObjectOwnerRequest += + new ParcelObjectOwnerRequest(m_LandManager.handleParcelObjectOwnersRequest); + client.OnParcelAccessListRequest += new ParcelAccessListRequest(m_LandManager.handleParcelAccessRequest); + client.OnParcelAccessListUpdateRequest += + new ParcelAccessListUpdateRequest(m_LandManager.handleParcelAccessUpdateRequest); + + client.OnEstateOwnerMessage += new EstateOwnerMessageRequest(m_estateManager.handleEstateOwnerMessage); + client.OnRegionInfoRequest += m_estateManager.HandleRegionInfoRequest; + client.OnEstateCovenantRequest += m_estateManager.HandleEstateCovenantRequest; + client.OnRequestGodlikePowers += handleRequestGodlikePowers; + client.OnGodKickUser += handleGodlikeKickUser; + client.OnObjectPermissions += HandleObjectPermissionsUpdate; + + client.OnCreateNewInventoryItem += CreateNewInventoryItem; + client.OnCreateNewInventoryFolder += CommsManager.UserProfileCacheService.HandleCreateInventoryFolder; + client.OnUpdateInventoryFolder += CommsManager.UserProfileCacheService.HandleUpdateInventoryFolder; + client.OnMoveInventoryFolder += CommsManager.UserProfileCacheService.HandleMoveInventoryFolder; + client.OnFetchInventoryDescendents += CommsManager.UserProfileCacheService.HandleFetchInventoryDescendents; + client.OnPurgeInventoryDescendents += CommsManager.UserProfileCacheService.HandlePurgeInventoryDescendents; + client.OnFetchInventory += CommsManager.UserProfileCacheService.HandleFetchInventory; + client.OnUpdateInventoryItem += UpdateInventoryItemAsset; + client.OnCopyInventoryItem += CopyInventoryItem; + client.OnMoveInventoryItem += MoveInventoryItem; + client.OnRemoveInventoryItem += RemoveInventoryItem; + client.OnRemoveInventoryFolder += RemoveInventoryFolder; + // client.OnAssetUploadRequest += CommsManager.TransactionsManager.HandleUDPUploadRequest; + // client.OnXferReceive += CommsManager.TransactionsManager.HandleXfer; + client.OnRezScript += RezScript; + + client.OnRequestTaskInventory += RequestTaskInventory; + client.OnRemoveTaskItem += RemoveTaskInventory; + client.OnUpdateTaskInventory += UpdateTaskInventory; + + client.OnGrabObject += ProcessObjectGrab; + client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; + client.OnAvatarPickerRequest += ProcessAvatarPickerRequest; + client.OnPacketStats += AddPacketStats; + + EventManager.TriggerOnNewClient(client); + } + + protected virtual ScenePresence CreateAndAddScenePresence(IClientAPI client, bool child) + { + ScenePresence avatar = null; + + AvatarAppearance appearance; + GetAvatarAppearance(client, out appearance); + + avatar = m_innerScene.CreateAndAddScenePresence(client, child, appearance); + + if (avatar.IsChildAgent) + { + avatar.OnSignificantClientMovement += m_LandManager.handleSignificantClientMovement; + } + + return avatar; + } + + + protected void GetAvatarAppearance(IClientAPI client, out AvatarAppearance appearance) + { + if (m_AvatarFactory == null || + !m_AvatarFactory.TryGetAvatarAppearance(client.AgentId, out appearance)) + { + //not found Appearance + m_log.Warn("[AVATAR DEBUGGING]: Couldn't fetch avatar appearance from factory, please report this to the opensim mantis"); + byte[] visualParams; + AvatarWearable[] wearables; + AvatarFactoryModule.GetDefaultAvatarAppearance(out wearables, out visualParams); + appearance = new AvatarAppearance(client.AgentId, wearables, visualParams); + } + } + + /// + /// + /// + /// + public override void RemoveClient(LLUUID agentID) + { + ScenePresence avatar = GetScenePresence(agentID); + try + { + if (avatar.IsChildAgent) + { + m_innerScene.removeUserCount(false); + } + else + { + m_innerScene.removeUserCount(true); + m_sceneGridService.LogOffUser(agentID, RegionInfo.RegionID, RegionInfo.RegionHandle, + avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, + avatar.AbsolutePosition.Z); + m_sceneGridService.SendCloseChildAgentConnections(avatar); + } + + m_eventManager.TriggerClientClosed(agentID); + } + catch (NullReferenceException) + { + // We don't know which count to remove it from + // Avatar is already disposed :/ + } + m_eventManager.TriggerOnRemovePresence(agentID); + Broadcast(delegate(IClientAPI client) + { + try + { + client.SendKillObject(avatar.RegionHandle, avatar.LocalId); + } + catch (System.NullReferenceException) + { + //We can safely ignore null reference exceptions. It means the avatar are dead and cleaned up anyway. + } + }); + + ForEachScenePresence( + delegate(ScenePresence presence) { presence.CoarseLocationChange(); }); + + IAgentAssetTransactions agentTransactions = this.RequestModuleInterface(); + if (agentTransactions != null) + { + agentTransactions.RemoveAgentAssetTransactions(agentID); + } + + lock (m_scenePresences) + { + if (m_scenePresences.Remove(agentID)) + { + //m_log.InfoFormat("[SCENE] Removed scene presence {0}", agentID); + } + else + { + m_log.WarnFormat("[SCENE] Tried to remove non-existent scene prescence with agent ID {0} from scene ScenePresences list", agentID); + } + } + + lock (Entities) + { + if (Entities.Remove(agentID)) + { + //m_log.InfoFormat("[SCENE] Removed scene presence {0} from entities list", agentID); + } + else + { + m_log.WarnFormat("[SCENE] Tried to remove non-existent scene prescence with agent ID {0} from scene Entities list", agentID); + } + } + + try + { + avatar.Close(); + } + catch (NullReferenceException) + { + //We can safely ignore null reference exceptions. It means the avatar are dead and cleaned up anyway. + } + catch (Exception e) + { + m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); + } + + // Remove client agent from profile, so new logins will work + m_sceneGridService.ClearUserAgent(agentID); + + //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); + //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); + } + + public override void CloseAllAgents(uint circuitcode) + { + // Called by ClientView to kill all circuit codes + ClientManager.CloseAllAgents(circuitcode); + } + + public void NotifyMyCoarseLocationChange() + { + ForEachScenePresence(delegate(ScenePresence presence) { presence.CoarseLocationChange(); }); + } + + #endregion + + #region Entities + + /// + /// + /// + /// + /// + public bool DeleteEntity(LLUUID entID) + { + if (Entities.ContainsKey(entID)) + { + Entities.Remove(entID); + m_storageManager.DataStore.RemoveObject(entID, m_regInfo.RegionID); + m_innerScene.RemoveAPrimCount(); + return true; + } + return false; + } + + public void SendKillObject(uint localID) + { + Broadcast(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); + } + + #endregion + + #region RegionComms + + /// + /// + /// + public void RegisterCommsEvents() + { + m_sceneGridService.OnExpectUser += NewUserConnection; + m_sceneGridService.OnAvatarCrossingIntoRegion += AgentCrossing; + m_sceneGridService.OnCloseAgentConnection += CloseConnection; + m_sceneGridService.OnRegionUp += OtherRegionUp; + m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; + m_sceneGridService.OnExpectPrim += IncomingInterRegionPrimGroup; + + + + + + m_sceneGridService.KillObject = SendKillObject; + } + + /// + /// + /// + public void UnRegisterReginWithComms() + { + m_sceneGridService.OnExpectPrim -= IncomingInterRegionPrimGroup; + m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; + m_sceneGridService.OnRegionUp -= OtherRegionUp; + m_sceneGridService.OnExpectUser -= NewUserConnection; + m_sceneGridService.OnAvatarCrossingIntoRegion -= AgentCrossing; + m_sceneGridService.OnCloseAgentConnection -= CloseConnection; + + m_sceneGridService.Close(); + } + + + /// + /// + /// + /// + /// + public void NewUserConnection(ulong regionHandle, AgentCircuitData agent) + { + if (regionHandle == m_regInfo.RegionHandle) + { + if (agent.CapsPath != String.Empty) + { + m_log.Debug("[CONNECTION DEBUGGING]: Setting up CAPS handler for " + agent.AgentID.ToString() + " at " + agent.CapsPath.ToString()); + Caps cap = + new Caps(AssetCache, m_httpListener, m_regInfo.ExternalHostName, m_httpListener.Port, + agent.CapsPath, agent.AgentID, m_dumpAssetsToFile); + + Util.SetCapsURL(agent.AgentID, + "http://" + m_regInfo.ExternalHostName + ":" + m_httpListener.Port.ToString() + + "/CAPS/" + agent.CapsPath + "0000/"); + cap.RegisterHandlers(); + if (agent.child) + { + + } + cap.AddNewInventoryItem = AddInventoryItem; + cap.ItemUpdatedCall = CapsUpdateInventoryItemAsset; + cap.TaskScriptUpdatedCall = CapsUpdateTaskInventoryScriptAsset; + + if (m_capsHandlers.ContainsKey(agent.AgentID)) + { + m_log.Debug("[CONNECTION DEBUGGING]: Caps path already in use for " + agent.AgentID.ToString()); + try + { + m_capsHandlers[agent.AgentID] = cap; + } + catch (KeyNotFoundException) + { + m_log.Debug("[CONNECTION DEBUGGING]: Caught exception adding handler for " + agent.AgentID.ToString()); + // Fix for a potential race condition. + m_capsHandlers.Add(agent.AgentID, cap); + } + } + else + { + m_capsHandlers.Add(agent.AgentID, cap); + } + } + else + { + m_log.Warn("[CONNECTION DEBUGGING]: Skipped setting up CAPS handler for " + agent.AgentID.ToString()); + } + m_log.Debug("[CONNECTION DEBUGGING]: Creating new circuit code (" + agent.circuitcode.ToString() + ") for " + agent.AgentID.ToString()); + m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); + } + else + { + m_log.Warn("[CONNECTION DEBUGGING]: Skipping this region for welcoming " + agent.AgentID.ToString() + " [" + regionHandle.ToString() + "]"); + } + } + + /// + /// + /// + /// + /// + /// + /// + public virtual void AgentCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying) + { + if (regionHandle == m_regInfo.RegionHandle) + { + if (m_scenePresences.ContainsKey(agentID)) + { + try + { + m_scenePresences[agentID].MakeRootAgent(position, isFlying); + } + catch (Exception e) + { + m_log.Info("[SCENE]: Unable to do Agent Crossing."); + m_log.Debug("[SCENE]: " + e.ToString()); + } + //m_innerScene.SwapRootChildAgent(false); + } + } + } + + public virtual bool IncomingChildAgentDataUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData) + { + ScenePresence childAgentUpdate = GetScenePresence(new LLUUID(cAgentData.AgentID)); + if (childAgentUpdate != null) + { + // I can't imagine *yet* why we would get an update if the agent is a root agent.. + // however to avoid a race condition crossing borders.. + if (childAgentUpdate.IsChildAgent) + { + uint rRegionX = (uint)(cAgentData.regionHandle >> 40); + uint rRegionY = (((uint)(cAgentData.regionHandle)) >> 8); + uint tRegionX = RegionInfo.RegionLocX; + uint tRegionY = RegionInfo.RegionLocY; + //Send Data to ScenePresence + childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); + // Not Implemented: + //TODO: Do we need to pass the message on to one of our neighbors? + + } + return true; + } + return false; + } + + /// + /// Tell a single agent to disconnect from the region. + /// + /// + /// + public bool CloseConnection(ulong regionHandle, LLUUID agentID) + { + if (regionHandle == m_regionHandle) + { + ScenePresence presence = m_innerScene.GetScenePresence(agentID); + if (presence != null) + { + if (presence.IsChildAgent) + { + m_innerScene.removeUserCount(false); + } + else + { + m_innerScene.removeUserCount(true); + } + // Tell a single agent to disconnect from the region. + libsecondlife.Packets.DisableSimulatorPacket disable = (libsecondlife.Packets.DisableSimulatorPacket)PacketPool.Instance.GetPacket(libsecondlife.Packets.PacketType.DisableSimulator); + presence.ControllingClient.OutPacket(disable, ThrottleOutPacketType.Task); + presence.ControllingClient.Close(true); + } + } + return true; + } + + /// + /// Tell neighboring regions about this agent + /// When the regions respond with a true value, + /// tell the agents about the region. + /// + /// We have to tell the regions about the agents first otherwise it'll deny them access + /// + /// + /// + public void InformClientOfNeighbours(ScenePresence presence) + { + m_sceneGridService.EnableNeighbourChildAgents(presence, m_neighbours); + } + + /// + /// Tell a neighboring region about this agent + /// + /// + /// + public void InformClientOfNeighbor(ScenePresence presence, RegionInfo region) + { + m_sceneGridService.InformNeighborChildAgent(presence, region, m_neighbours); + } + + /// + /// Requests information about this region from gridcomms + /// + /// + /// + public RegionInfo RequestNeighbouringRegionInfo(ulong regionHandle) + { + return m_sceneGridService.RequestNeighbouringRegionInfo(regionHandle); + } + + /// + /// Requests textures for map from minimum region to maximum region in world cordinates + /// + /// + /// + /// + /// + /// + public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY) + { + m_sceneGridService.RequestMapBlocks(remoteClient, minX, minY, maxX, maxX); + } + + /// + /// Tries to teleport agent to other region. + /// + /// + /// + /// + /// + /// + public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, LLVector3 position, + LLVector3 lookAt, uint flags) + { + if (m_scenePresences.ContainsKey(remoteClient.AgentId)) + { + m_sceneGridService.RequestTeleportToLocation(m_scenePresences[remoteClient.AgentId], regionHandle, + position, lookAt, flags); + } + } + + /// + /// Agent is crossing the border into a neighbouring region. Tell the neighbour about it! + /// + /// + /// + /// + /// + /// + public bool InformNeighbourOfCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying) + { + return m_sceneGridService.CrossToNeighbouringRegion(regionHandle, agentID, position, isFlying); + } + + public void SendOutChildAgentUpdates(ChildAgentDataUpdate cadu, ScenePresence presence) + { + m_sceneGridService.SendChildAgentDataUpdate(cadu, presence); + } + + #endregion + + #region Module Methods + + /// + /// + /// + /// + /// + public void AddModule(string name, IRegionModule module) + { + if (!Modules.ContainsKey(name)) + { + Modules.Add(name, module); + } + } + + /// + /// + /// + /// + public void RegisterModuleInterface(M mod) + { + if (!ModuleInterfaces.ContainsKey(typeof(M))) + { + ModuleInterfaces.Add(typeof(M), mod); + } + } + + /// + /// + /// + /// + public T RequestModuleInterface() + { + if (ModuleInterfaces.ContainsKey(typeof(T))) + { + return (T)ModuleInterfaces[typeof(T)]; + } + else + { + return default(T); + } + } + + + + #endregion + + #region Other Methods + + /// + /// + /// + /// + public void SetTimePhase(int phase) + { + m_timePhase = phase; + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public void SendUrlToUser(LLUUID avatarID, string objectName, LLUUID objectID, LLUUID ownerID, bool groupOwned, + string message, string url) + { + if (m_scenePresences.ContainsKey(avatarID)) + { + m_scenePresences[avatarID].ControllingClient.SendLoadURL(objectName, objectID, ownerID, groupOwned, + message, url); + } + } + + public void SendDialogToUser(LLUUID avatarID, string objectName, LLUUID objectID, LLUUID ownerID, string message, LLUUID TextureID, int ch, string[] buttonlabels) + { + if (m_scenePresences.ContainsKey(avatarID)) + { + m_scenePresences[avatarID].ControllingClient.SendDialog(objectName, objectID, ownerID, message, TextureID, ch, buttonlabels); + } + } + + /// + /// + /// + /// + /// + /// + /// + public LLUUID MakeHttpRequest(string url, string type, string body) + { + if (m_httpRequestModule != null) + { + return m_httpRequestModule.MakeHttpRequest(url, type, body); + } + return LLUUID.Zero; + } + + /// + /// + /// + public void performParcelPrimCountUpdate() + { + m_LandManager.resetAllLandPrimCounts(); + m_eventManager.TriggerParcelPrimCountUpdate(); + m_LandManager.finalizeLandPrimCountUpdate(); + m_LandManager.landPrimCountTainted = false; + } + + /// + /// + /// + public void addPrimsToParcelCounts() + { + foreach (EntityBase obj in Entities.Values) + { + if (obj is SceneObjectGroup) + { + m_eventManager.TriggerParcelPrimCountAdd((SceneObjectGroup)obj); + } + } + } + + /// + /// This method is a way for the Friends Module to create an instant + /// message to the avatar and for Instant Messages that travel across + /// gridcomms to make it to the Instant Message Module. + /// + /// Friendship establishment and groups are unfortunately tied with instant messaging and + /// there's no way to separate them completely. + /// + /// object containing the instant message data + /// void + public void TriggerGridInstantMessage(GridInstantMessage message, InstantMessageReceiver options) + { + m_eventManager.TriggerGridInstantMessage(message, options); + } + + + public virtual void StoreAddFriendship(LLUUID ownerID, LLUUID friendID, uint perms) + { + // TODO: m_sceneGridService.DoStuff; + m_sceneGridService.AddNewUserFriend(ownerID, friendID, perms); + } + + public virtual void StoreUpdateFriendship(LLUUID ownerID, LLUUID friendID, uint perms) + { + // TODO: m_sceneGridService.DoStuff; + m_sceneGridService.UpdateUserFriendPerms(ownerID, friendID, perms); + } + + public virtual void StoreRemoveFriendship(LLUUID ownerID, LLUUID ExfriendID) + { + // TODO: m_sceneGridService.DoStuff; + m_sceneGridService.RemoveUserFriend(ownerID, ExfriendID); + } + public virtual List StoreGetFriendsForUser(LLUUID ownerID) + { + // TODO: m_sceneGridService.DoStuff; + return m_sceneGridService.GetUserFriendList(ownerID); + } + + public void AddPacketStats(int inPackets, int outPackets, int unAckedBytes) + { + m_statsReporter.AddInPackets(inPackets); + m_statsReporter.AddOutPackets(outPackets); + m_statsReporter.AddunAckedBytes(unAckedBytes); + } + public void AddAgentTime(int ms) + { + m_statsReporter.addFrameMS(ms); + m_statsReporter.addAgentMS(ms); + } + public void AddAgentUpdates(int count) + { + m_statsReporter.AddAgentUpdates(count); + } + + public void AddPendingDownloads(int count) + { + m_statsReporter.addPendingDownload(count); + } + + #endregion + + #region Console Commands + + #region Alert Methods + + private void SendPermissionAlert(LLUUID user, string reason) + { + SendAlertToUser(user, reason, false); + } + + /// + /// + /// + /// + public void SendGeneralAlert(string message) + { + List presenceList = GetScenePresences(); + + foreach (ScenePresence presence in presenceList) + { + presence.ControllingClient.SendAlertMessage(message); + } + } + + /// + /// + /// + /// + /// + /// + public void SendAlertToUser(LLUUID agentID, string message, bool modal) + { + if (m_scenePresences.ContainsKey(agentID)) + { + m_scenePresences[agentID].ControllingClient.SendAgentAlertMessage(message, modal); + } + } + + /// + /// + /// + /// + /// + /// + /// + public void handleRequestGodlikePowers(LLUUID agentID, LLUUID sessionID, LLUUID token, + IClientAPI controllingClient) + { + // First check that this is the sim owner + if (m_permissionManager.GenericEstatePermission(agentID)) + { + // User needs to be logged into this sim + if (m_scenePresences.ContainsKey(agentID)) + { + // Next we check for spoofing..... + LLUUID testSessionID = m_scenePresences[agentID].ControllingClient.SessionId; + if (sessionID == testSessionID) + { + if (sessionID == controllingClient.SessionId) + { + m_scenePresences[agentID].GrantGodlikePowers(agentID, testSessionID, token); + } + } + } + } + else + { + m_scenePresences[agentID].ControllingClient.SendAgentAlertMessage("Request for god powers denied", false); + } + } + + /// + /// Sends a Big Blue Box message on the upper right of the screen to the client + /// for all agents in the region + /// + /// The person sending the message + /// The session of the person sending the message + /// The name of the person doing the sending + /// The Message being sent to the user + public void SendRegionMessageFromEstateTools(LLUUID FromAvatarID, LLUUID fromSessionID, String FromAvatarName, String Message) + { + + List presenceList = GetScenePresences(); + + foreach (ScenePresence presence in presenceList) + { + if (!presence.IsChildAgent) + presence.ControllingClient.SendBlueBoxMessage(FromAvatarID, fromSessionID, FromAvatarName, Message); + } + } + + /// + /// Sends a Big Blue Box message on the upper right of the screen to the client + /// for all agents in the estate + /// + /// The person sending the message + /// The session of the person sending the message + /// The name of the person doing the sending + /// The Message being sent to the user + public void SendEstateMessageFromEstateTools(LLUUID FromAvatarID, LLUUID fromSessionID, String FromAvatarName, String Message) + { + + ClientManager.ForEachClient(delegate(IClientAPI controller) + { + controller.SendBlueBoxMessage(FromAvatarID, fromSessionID, FromAvatarName, Message); + } + ); + } + + /// + /// Kicks User specified from the simulator. This logs them off of the grid + /// If the client gets the UUID: 44e87126e7944ded05b37c42da3d5cdb it assumes + /// that you're kicking it even if the avatar's UUID isn't the UUID that the + /// agent is assigned + /// + /// The person doing the kicking + /// The session of the person doing the kicking + /// the person that is being kicked + /// This isn't used apparently + /// The message to send to the user after it's been turned into a field + public void handleGodlikeKickUser(LLUUID godID, LLUUID sessionID, LLUUID agentID, uint kickflags, byte[] reason) + { + // For some reason the client sends this seemingly hard coded UUID for kicking everyone. Dun-know. + LLUUID kickUserID = new LLUUID("44e87126e7944ded05b37c42da3d5cdb"); + if (m_scenePresences.ContainsKey(agentID) || agentID == kickUserID) + { + if (m_permissionManager.GenericEstatePermission(godID)) + { + if (agentID == kickUserID) + { + ClientManager.ForEachClient(delegate(IClientAPI controller) + { + if (controller.AgentId != godID) + controller.Kick(Helpers.FieldToUTF8String(reason)); + + + + } + ); + // This is a bit crude. It seems the client will be null before it actually stops the thread + // The thread will kill itself eventually :/ + // Is there another way to make sure *all* clients get this 'inter region' message? + ClientManager.ForEachClient(delegate(IClientAPI controller) + { + ScenePresence p = GetScenePresence(controller.AgentId); + bool childagent = !p.Equals(null) && p.IsChildAgent; + if (controller.AgentId != godID && !childagent) + // Do we really want to kick the initiator of this madness? + { + controller.Close(true); + } + } + ); + } + else + { + if (m_scenePresences[agentID].IsChildAgent) + { + m_innerScene.removeUserCount(false); + } + else + { + m_innerScene.removeUserCount(true); + } + + m_scenePresences[agentID].ControllingClient.Kick(Helpers.FieldToUTF8String(reason)); + m_scenePresences[agentID].ControllingClient.Close(true); + } + } + else + { + if (m_scenePresences.ContainsKey(godID)) + m_scenePresences[godID].ControllingClient.SendAgentAlertMessage("Kick request denied", false); + } + } + } + + public void HandleObjectPermissionsUpdate(IClientAPI controller, LLUUID agentID, LLUUID sessionID, byte field, uint localId, uint mask, byte set) + { + // Check for spoofing.. since this is permissions we're talking about here! + if ((controller.SessionId == sessionID) && (controller.AgentId == agentID)) + { + + // Tell the object to do permission update + SceneObjectGroup chObjectGroup = GetGroupByPrim(localId); + chObjectGroup.UpdatePermissions(agentID, field, localId, mask, set); + + } + } + + /// + /// + /// + /// + /// + /// + /// + public void SendAlertToUser(string firstName, string lastName, string message, bool modal) + { + List presenceList = GetScenePresences(); + + foreach (ScenePresence presence in presenceList) + { + if ((presence.Firstname == firstName) && (presence.Lastname == lastName)) + { + presence.ControllingClient.SendAgentAlertMessage(message, modal); + break; + } + } + } + + /// + /// + /// + /// + public void HandleAlertCommand(string[] commandParams) + { + if (commandParams[0] == "general") + { + string message = CombineParams(commandParams, 1); + SendGeneralAlert(message); + } + else + { + string message = CombineParams(commandParams, 2); + SendAlertToUser(commandParams[0], commandParams[1], message, false); + } + } + + private string CombineParams(string[] commandParams, int pos) + { + string result = String.Empty; + for (int i = pos; i < commandParams.Length; i++) + { + result += commandParams[i] + " "; + } + return result; + } + + #endregion + + /// + /// Causes all clients to get a full object update on all of the objects in the scene. + /// + public void ForceClientUpdate() + { + List EntitieList = GetEntities(); + + foreach (EntityBase ent in EntitieList) + { + if (ent is SceneObjectGroup) + { + ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); + } + } + } + + /// + /// This is currently only used for scale (to scale to MegaPrim size) + /// There is a console command that calls this in OpenSimMain + /// + /// + public void HandleEditCommand(string[] cmdparams) + { + Console.WriteLine("Searching for Primitive: '" + cmdparams[0] + "'"); + + List EntitieList = GetEntities(); + + foreach (EntityBase ent in EntitieList) + { + if (ent is SceneObjectGroup) + { + SceneObjectPart part = ((SceneObjectGroup)ent).GetChildPart(((SceneObjectGroup)ent).UUID); + if (part != null) + { + if (part.Name == cmdparams[0]) + { + part.Resize( + new LLVector3(Convert.ToSingle(cmdparams[1]), Convert.ToSingle(cmdparams[2]), + Convert.ToSingle(cmdparams[3]))); + + Console.WriteLine("Edited scale of Primitive: " + part.Name); + } + } + } + } + } + + /// + /// Shows various details about the sim based on the parameters supplied by the console command in openSimMain. + /// + /// + public void Show(string showWhat) + { + switch (showWhat) + { + case "users": + m_log.Error("Current Region: " + RegionInfo.RegionName); + m_log.ErrorFormat("{0,-16}{1,-16}{2,-25}{3,-25}{4,-16}{5,-16}{6,-16}", "Firstname", "Lastname", + "Agent ID", "Session ID", "Circuit", "IP", "World"); + + foreach (ScenePresence scenePrescence in GetAvatars()) + { + m_log.ErrorFormat("{0,-16}{1,-16}{2,-25}{3,-25}{4,-16},{5,-16}{6,-16}", + scenePrescence.Firstname, + scenePrescence.Lastname, + scenePrescence.UUID, + scenePrescence.ControllingClient.AgentId, + "Unknown", + "Unknown", + RegionInfo.RegionName); + } + break; + case "modules": + m_log.Error("The currently loaded modules in " + RegionInfo.RegionName + " are:"); + foreach (IRegionModule module in Modules.Values) + { + if (!module.IsSharedModule) + { + m_log.Error("Region Module: " + module.Name); + } + } + break; + } + } + + #endregion + + #region Script Handling Methods + + /// + /// Console command handler to send script command to script engine. + /// + /// + public void SendCommandToPlugins(string[] args) + { + m_eventManager.TriggerOnPluginConsole(args); + } + + public double GetLandHeight(int x, int y) + { + return Terrain.GetHeight(x, y); + } + + public LLUUID GetLandOwner(float x, float y) + { + Land land = LandManager.getLandObject(x, y); + if (land == null) + { + return LLUUID.Zero; + } + else + { + return land.landData.ownerID; + } + } + + public LandData GetLandData(float x, float y) + { + return LandManager.getLandObject(x, y).landData; + } + + public void SetLandMusicURL(float x, float y, string url) + { + Land land = LandManager.getLandObject(x, y); + if (land == null) + { + return; + } + else + { + land.landData.musicURL = url; + return; + } + } + + #endregion + + #region Script Engine + + private List ScriptEngines = new List(); + private bool m_dumpAssetsToFile; + + /// + /// + /// + /// + public void AddScriptEngine(ScriptEngineInterface scriptEngine) + { + ScriptEngines.Add(scriptEngine); + scriptEngine.InitializeEngine(this); + } + + public void TriggerObjectChanged(uint localID, uint change) + { + + m_eventManager.TriggerOnScriptChangedEvent(localID, change); + } + + #endregion + + #region InnerScene wrapper methods + + /// + /// + /// + /// + /// + public LLUUID ConvertLocalIDToFullID(uint localID) + { + return m_innerScene.ConvertLocalIDToFullID(localID); + } + + public void SwapRootAgentCount(bool rootChildChildRootTF) + { + m_innerScene.SwapRootChildAgent(rootChildChildRootTF); + } + + public void AddPhysicalPrim(int num) + { + m_innerScene.AddPhysicalPrim(num); + } + + public void RemovePhysicalPrim(int num) + { + m_innerScene.RemovePhysicalPrim(num); + } + + /// + /// + /// + /// + public void SendAllSceneObjectsToClient(ScenePresence presence) + { + m_innerScene.SendAllSceneObjectsToClient(presence); + } + + //The idea is to have a group of method that return a list of avatars meeting some requirement + // ie it could be all m_scenePresences within a certain range of the calling prim/avatar. + + /// + /// + /// + /// + public List GetAvatars() + { + return m_innerScene.GetAvatars(); + } + + /// + /// Request a List of all m_scenePresences in this World + /// + /// + public List GetScenePresences() + { + return m_innerScene.GetScenePresences(); + } + + /// + /// Request a filtered list of m_scenePresences in this World + /// + /// + /// + public List GetScenePresences(FilterAvatarList filter) + { + return m_innerScene.GetScenePresences(filter); + } + + /// + /// Request a Avatar by UUID + /// + /// + /// + public ScenePresence GetScenePresence(LLUUID avatarID) + { + return m_innerScene.GetScenePresence(avatarID); + } + + /// + /// Request an Avatar's Child Status - used by ClientView when a 'kick everyone' or 'estate message' occurs + /// + /// AvatarID to lookup + /// + public override bool PresenceChildStatus(LLUUID avatarID) + { + ScenePresence cp = GetScenePresence(avatarID); + return cp.IsChildAgent; + } + + /// + /// + /// + /// + public void ForEachScenePresence(Action action) + { + // We don't want to try to send messages if there are no avatar. + if (!(m_scenePresences.Equals(null))) + { + try + { + List presenceList = GetScenePresences(); + foreach (ScenePresence presence in presenceList) + { + action(presence); + } + } + catch (Exception e) + { + m_log.Info("[BUG]: " + e.ToString()); + } + } + } + + /// + /// + /// + /// + // public void ForEachObject(Action action) + // { + // List presenceList; + // + // lock (m_sceneObjects) + // { + // presenceList = new List(m_sceneObjects.Values); + // } + // + // foreach (SceneObjectGroup presence in presenceList) + // { + // action(presence); + // } + // } + + /// + /// + /// + /// + /// + public SceneObjectPart GetSceneObjectPart(uint localID) + { + return m_innerScene.GetSceneObjectPart(localID); + } + + /// + /// + /// + /// + /// + public SceneObjectPart GetSceneObjectPart(LLUUID fullID) + { + return m_innerScene.GetSceneObjectPart(fullID); + } + + internal bool TryGetAvatar(LLUUID avatarId, out ScenePresence avatar) + { + return m_innerScene.TryGetAvatar(avatarId, out avatar); + } + + internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) + { + return m_innerScene.TryGetAvatarByName(avatarName, out avatar); + } + + internal void ForEachClient(Action action) + { + m_innerScene.ForEachClient(action); + } + + public List GetEntities() + { + return m_innerScene.GetEntities(); + } + + #endregion + + #region BaseHTTPServer wrapper methods + + public bool AddHTTPHandler(string method, GenericHTTPMethod handler) + { + return m_httpListener.AddHTTPHandler(method, handler); + } + + public bool AddXmlRPCHandler(string method, XmlRpcMethod handler) + { + return m_httpListener.AddXmlRPCHandler(method, handler); + } + + public void AddStreamHandler(IRequestHandler handler) + { + m_httpListener.AddStreamHandler(handler); + } + + public void RemoveStreamHandler(string httpMethod, string path) + { + m_httpListener.RemoveStreamHandler(httpMethod, path); + } + + public void RemoveHTTPHandler(string httpMethod, string path) + { + m_httpListener.RemoveHTTPHandler(httpMethod, path); + } + + #endregion + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/SceneBase.cs b/trunk/OpenSim/Region/Environment/Scenes/SceneBase.cs new file mode 100644 index 0000000000..4e05682899 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/SceneBase.cs @@ -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 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; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Region.Terrain; +using OpenSim.Region.Environment.Interfaces; + +namespace OpenSim.Region.Environment.Scenes +{ + public abstract class SceneBase : IScene + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #region Events + + public event restart OnRestart; + + #endregion + + #region Fields + + private readonly ClientManager m_clientManager = new ClientManager(); + + public ClientManager ClientManager + { + get { return m_clientManager; } + } + + protected ulong m_regionHandle; + protected string m_regionName; + protected RegionInfo m_regInfo; + + public TerrainEngine Terrain; + public ITerrainChannel Heightmap; + + protected EventManager m_eventManager; + + public EventManager EventManager + { + get { return m_eventManager; } + } + + protected string m_datastore; + + private uint m_nextLocalId = 8880000; + + private AssetCache m_assetCache; + + public AssetCache AssetCache + { + get { return m_assetCache; } + set { m_assetCache = value; } + } + + protected RegionStatus m_regStatus; + + public RegionStatus Region_Status + { + get { return m_regStatus; } + set { m_regStatus = value; } + } + + #endregion + + #region Update Methods + + /// + /// Normally called once every frame/tick to let the world preform anything required (like running the physics simulation) + /// + public abstract void Update(); + + #endregion + + #region Terrain Methods + + /// + /// Loads the World heightmap + /// + public abstract void LoadWorldMap(); + + /// + /// Send the region heightmap to the client + /// + /// Client to send to + public virtual void SendLayerData(IClientAPI RemoteClient) + { + RemoteClient.SendLayerData(Terrain.GetHeights1D()); + } + + #endregion + + #region Add/Remove Agent/Avatar + + /// + /// + /// + /// + /// + /// + public abstract void AddNewClient(IClientAPI client, bool child); + + /// + /// + /// + /// + public abstract void RemoveClient(LLUUID agentID); + + public abstract void CloseAllAgents(uint circuitcode); + + #endregion + + /// + /// + /// + /// + public virtual RegionInfo RegionInfo + { + get { return m_regInfo; } + } + + public uint NextLocalId + { + get { return m_nextLocalId++; } + } + + #region admin stuff + + /// + /// Region Restart - Seconds till restart. + /// + /// + public virtual void Restart(int seconds) + { + m_log.Error("[REGION]: passing Restart Message up the namespace"); + OnRestart(RegionInfo); + } + + public virtual bool PresenceChildStatus(LLUUID avatarID) + { + return false; + } + public abstract bool OtherRegionUp(RegionInfo thisRegion); + + public virtual string GetSimulatorVersion() + { + return "OpenSimulator v0.5 SVN"; + } + + #endregion + + #region Shutdown + + /// + /// Tidy before shutdown + /// + public virtual void Close() + { + try + { + EventManager.TriggerShutdown(); + } + catch (Exception e) + { + m_log.Error("[SCENE]: SceneBase.cs: Close() - Failed with exception " + e.ToString()); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs b/trunk/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs new file mode 100644 index 0000000000..4cf93ed167 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs @@ -0,0 +1,598 @@ +/* +* 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; +using System.Collections.Generic; +using System.Net; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Environment.Scenes +{ + public delegate void KillObjectDelegate(uint localID); + + public class SceneCommunicationService //one instance per region + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected CommunicationsManager m_commsProvider; + protected RegionInfo m_regionInfo; + + protected RegionCommsListener regionCommsHost; + + public event AgentCrossing OnAvatarCrossingIntoRegion; + public event ExpectUserDelegate OnExpectUser; + public event ExpectPrimDelegate OnExpectPrim; + public event CloseAgentConnection OnCloseAgentConnection; + public event PrimCrossing OnPrimCrossingIntoRegion; + public event RegionUp OnRegionUp; + public event ChildAgentUpdate OnChildAgentUpdate; + + + + public KillObjectDelegate KillObject; + public string _debugRegionName = String.Empty; + + public string debugRegionName + { + get { return _debugRegionName; } + set { _debugRegionName = value; } + } + + public SceneCommunicationService(CommunicationsManager commsMan) + { + m_commsProvider = commsMan; + m_commsProvider.GridService.gdebugRegionName = _debugRegionName; + m_commsProvider.InterRegion.rdebugRegionName = _debugRegionName; + } + + public void RegisterRegion(RegionInfo regionInfos) + { + m_regionInfo = regionInfos; + regionCommsHost = m_commsProvider.GridService.RegisterRegion(m_regionInfo); + + if (regionCommsHost != null) + { + //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got" + regionCommsHost.ToString()); + + regionCommsHost.debugRegionName = _debugRegionName; + regionCommsHost.OnExpectPrim += IncomingPrimCrossing; + regionCommsHost.OnExpectUser += NewUserConnection; + regionCommsHost.OnAvatarCrossingIntoRegion += AgentCrossing; + regionCommsHost.OnCloseAgentConnection += CloseConnection; + regionCommsHost.OnRegionUp += newRegionUp; + regionCommsHost.OnChildAgentUpdate += ChildAgentUpdate; + + } + else + { + //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got null"); + } + } + + public void Close() + { + if (regionCommsHost != null) + { + regionCommsHost.OnChildAgentUpdate -= ChildAgentUpdate; + regionCommsHost.OnRegionUp -= newRegionUp; + regionCommsHost.OnExpectUser -= NewUserConnection; + regionCommsHost.OnExpectPrim -= IncomingPrimCrossing; + regionCommsHost.OnAvatarCrossingIntoRegion -= AgentCrossing; + regionCommsHost.OnCloseAgentConnection -= CloseConnection; + m_commsProvider.GridService.DeregisterRegion(m_regionInfo); + regionCommsHost = null; + } + } + + #region CommsManager Event handlers + + /// + /// + /// + /// + /// + /// + protected void NewUserConnection(ulong regionHandle, AgentCircuitData agent) + { + if (OnExpectUser != null) + { + //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: OnExpectUser Fired for User:" + agent.firstname + " " + agent.lastname); + OnExpectUser(regionHandle, agent); + } + } + + protected bool newRegionUp(RegionInfo region) + { + if (OnRegionUp != null) + { + //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: newRegionUp Fired for User:" + region.RegionName); + OnRegionUp(region); + } + return true; + } + + protected bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData) + { + if (OnChildAgentUpdate != null) + OnChildAgentUpdate(regionHandle, cAgentData); + + + return true; + } + + protected void AgentCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position, bool isFlying) + { + if (OnAvatarCrossingIntoRegion != null) + { + OnAvatarCrossingIntoRegion(regionHandle, agentID, position, isFlying); + } + } + + protected void IncomingPrimCrossing(ulong regionHandle, LLUUID primID, String objXMLData) + { + if (OnExpectPrim != null) + { + OnExpectPrim(regionHandle, primID, objXMLData); + } + + } + + protected void PrimCrossing(ulong regionHandle, LLUUID primID, LLVector3 position, bool isPhysical) + { + if (OnPrimCrossingIntoRegion != null) + { + OnPrimCrossingIntoRegion(regionHandle, primID, position, isPhysical); + } + } + + protected bool CloseConnection(ulong regionHandle, LLUUID agentID) + { + m_log.Info("[INTERREGION]: Incoming Agent Close Request for agent: " + agentID.ToString()); + + if (OnCloseAgentConnection != null) + { + return OnCloseAgentConnection(regionHandle, agentID); + } + return false; + } + + #endregion + + #region Inform Client of Neighbours + + private delegate void InformClientOfNeighbourDelegate( + ScenePresence avatar, AgentCircuitData a, ulong regionHandle, IPEndPoint endPoint); + + private void InformClientOfNeighbourCompleted(IAsyncResult iar) + { + InformClientOfNeighbourDelegate icon = (InformClientOfNeighbourDelegate) iar.AsyncState; + icon.EndInvoke(iar); + } + + /// + /// Async compnent for informing client of which neighbours exists + /// + /// + /// This needs to run asynchronesously, as a network timeout may block the thread for a long while + /// + /// + /// + /// + /// + private void InformClientOfNeighbourAsync(ScenePresence avatar, AgentCircuitData a, ulong regionHandle, + IPEndPoint endPoint) + { + m_log.Info("[INTERGRID]: Starting to inform client about neighbours"); + bool regionAccepted = m_commsProvider.InterRegion.InformRegionOfChildAgent(regionHandle, a); + + if (regionAccepted) + { + avatar.ControllingClient.InformClientOfNeighbour(regionHandle, endPoint); + avatar.AddNeighbourRegion(regionHandle); + m_log.Info("[INTERGRID]: Completed inform client about neighbours"); + } + } + + public void RequestNeighbors(RegionInfo region) + { + List neighbours = + m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); + //IPEndPoint blah = new IPEndPoint(); + + //blah.Address = region.RemotingAddress; + //blah.Port = region.RemotingPort; + } + + /// + /// This informs all neighboring regions about agent "avatar". + /// Calls an asynchronous method to do so.. so it doesn't lag the sim. + /// + public void EnableNeighbourChildAgents(ScenePresence avatar, List lstneighbours) + { + List neighbours = new List(); + + //m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); + for (int i = 0; i < lstneighbours.Count; i++) + { + // We don't want to keep sending to regions that consistently fail on comms. + if (!(lstneighbours[i].commFailTF)) + { + neighbours.Add(new SimpleRegionInfo(lstneighbours[i])); + } + } + // we're going to be using the above code once neighbour cache is correct. Currently it doesn't appear to be + // So we're temporarily going back to the old method of grabbing it from the Grid Server Every time :/ + neighbours = + m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); + + if (neighbours != null) + { + for (int i = 0; i < neighbours.Count; i++) + { + AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo(); + agent.BaseFolder = LLUUID.Zero; + agent.InventoryFolder = LLUUID.Zero; + agent.startpos = new LLVector3(128, 128, 70); + agent.child = true; + + InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; + d.BeginInvoke(avatar, agent, neighbours[i].RegionHandle, neighbours[i].ExternalEndPoint, + InformClientOfNeighbourCompleted, + d); + } + } + } + + /// + /// This informs a single neighboring region about agent "avatar". + /// Calls an asynchronous method to do so.. so it doesn't lag the sim. + /// + public void InformNeighborChildAgent(ScenePresence avatar, RegionInfo region, List neighbours) + { + AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo(); + agent.BaseFolder = LLUUID.Zero; + agent.InventoryFolder = LLUUID.Zero; + agent.startpos = new LLVector3(128, 128, 70); + agent.child = true; + + InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; + d.BeginInvoke(avatar, agent, region.RegionHandle, region.ExternalEndPoint, + InformClientOfNeighbourCompleted, + d); + } + + #endregion + + public delegate void InformNeighbourThatRegionUpDelegate(RegionInfo region, ulong regionhandle); + + private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar) + { + InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate) iar.AsyncState; + icon.EndInvoke(iar); + } + + + private void InformNeighboursThatRegionIsUpAsync(RegionInfo region, ulong regionhandle) + { + m_log.Info("[INTERGRID]: Starting to inform neighbors that I'm here"); + bool regionAccepted = + m_commsProvider.InterRegion.RegionUp((new SearializableRegionInfo(region)), regionhandle); + + if (regionAccepted) + { + m_log.Info("[INTERGRID]: Completed informing neighbors that I'm here"); + } + else + { + m_log.Info("[INTERGRID]: Failed to inform neighbors that I'm here"); + } + } + + /// + /// Called by scene when region is initialized (not always when it's listening for agents) + /// This is an inter-region message that informs the surrounding neighbors that the sim is up. + /// + public void InformNeighborsThatRegionisUp(RegionInfo region) + { + //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); + + + List neighbours = new List(); + // This stays uncached because we don't already know about our neighbors at this point. + neighbours = m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); + if (neighbours != null) + { + for (int i = 0; i < neighbours.Count; i++) + { + InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; + + d.BeginInvoke(region, neighbours[i].RegionHandle, + InformNeighborsThatRegionisUpCompleted, + d); + } + } + + //bool val = m_commsProvider.InterRegion.RegionUp(new SearializableRegionInfo(region)); + } + + public delegate void SendChildAgentDataUpdateDelegate(ChildAgentDataUpdate cAgentData, ScenePresence presence); + + /// + /// This informs all neighboring regions about the settings of it's child agent. + /// Calls an asynchronous method to do so.. so it doesn't lag the sim. + /// + /// This contains information, such as, Draw Distance, Camera location, Current Position, Current throttle settings, etc. + /// + /// + private void SendChildAgentDataUpdateAsync(ChildAgentDataUpdate cAgentData, ScenePresence presence) + { + //m_log.Info("[INTERGRID]: Informing neighbors about my agent."); + try + { + foreach (ulong regionHandle in presence.KnownChildRegions) + { + bool regionAccepted = m_commsProvider.InterRegion.ChildAgentUpdate(regionHandle, cAgentData); + + if (regionAccepted) + { + //m_log.Info("[INTERGRID]: Completed sending a neighbor an update about my agent"); + } + else + { + //m_log.Info("[INTERGRID]: Failed sending a neighbor an update about my agent"); + } + } + } + catch (System.InvalidOperationException) + { + // We're ignoring a collection was modified error because this data gets old and outdated fast. + } + + } + + private void SendChildAgentDataUpdateCompleted(IAsyncResult iar) + { + SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate) iar.AsyncState; + icon.EndInvoke(iar); + } + + public void SendChildAgentDataUpdate(ChildAgentDataUpdate cAgentData, ScenePresence presence) + { + // This assumes that we know what our neighbors are. + SendChildAgentDataUpdateDelegate d = SendChildAgentDataUpdateAsync; + d.BeginInvoke(cAgentData,presence, + SendChildAgentDataUpdateCompleted, + d); + } + + public delegate void SendCloseChildAgentDelegate( ScenePresence presence); + + /// + /// This Closes child agents on neighboring regions + /// Calls an asynchronous method to do so.. so it doesn't lag the sim. + /// + private void SendCloseChildAgentAsync(ScenePresence presence) + { + + foreach (ulong regionHandle in presence.KnownChildRegions) + { + bool regionAccepted = m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, presence.ControllingClient.AgentId); + + if (regionAccepted) + { + m_log.Info("[INTERGRID]: Completed sending agent Close agent Request to neighbor"); + presence.RemoveNeighbourRegion(regionHandle); + } + else + { + m_log.Info("[INTERGRID]: Failed sending agent Close agent Request to neighbor"); + + } + + } + } + + private void SendCloseChildAgentCompleted(IAsyncResult iar) + { + SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState; + icon.EndInvoke(iar); + } + + public void SendCloseChildAgentConnections(ScenePresence presence) + { + // This assumes that we know what our neighbors are. + SendCloseChildAgentDelegate d = SendCloseChildAgentAsync; + d.BeginInvoke(presence, + SendCloseChildAgentCompleted, + d); + } + + /// + /// Helper function to request neighbors from grid-comms + /// + /// + /// + public virtual RegionInfo RequestNeighbouringRegionInfo(ulong regionHandle) + { + //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionHandle.ToString()); + return m_commsProvider.GridService.RequestNeighbourInfo(regionHandle); + } + + /// + /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates + /// + /// + /// + /// + /// + public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY) + { + List mapBlocks; + mapBlocks = m_commsProvider.GridService.RequestNeighbourMapBlocks(minX - 4, minY - 4, minX + 4, minY + 4); + remoteClient.SendMapBlock(mapBlocks); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public virtual void RequestTeleportToLocation(ScenePresence avatar, ulong regionHandle, LLVector3 position, + LLVector3 lookAt, uint flags) + { + bool destRegionUp = false; + if (regionHandle == m_regionInfo.RegionHandle) + { + avatar.ControllingClient.SendTeleportLocationStart(); + avatar.ControllingClient.SendLocalTeleport(position, lookAt, flags); + avatar.Teleport(position); + } + else + { + RegionInfo reg = RequestNeighbouringRegionInfo(regionHandle); + if (reg != null) + { + avatar.ControllingClient.SendTeleportLocationStart(); + AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo(); + agent.BaseFolder = LLUUID.Zero; + agent.InventoryFolder = LLUUID.Zero; + agent.startpos = position; + agent.child = true; + + if (reg.RemotingAddress != "" && reg.RemotingPort != 0) + { + // region is remote. see if it is up + m_commsProvider.InterRegion.CheckRegion(reg.RemotingAddress, reg.RemotingPort); + destRegionUp = m_commsProvider.InterRegion.Available; + } + else + { + // assume local regions are always up + destRegionUp = true; + } + if(destRegionUp) + { + avatar.Close(); + m_commsProvider.InterRegion.InformRegionOfChildAgent(regionHandle, agent); + m_commsProvider.InterRegion.ExpectAvatarCrossing(regionHandle, avatar.ControllingClient.AgentId, + position, false); + AgentCircuitData circuitdata = avatar.ControllingClient.RequestClientInfo(); + string capsPath = Util.GetCapsURL(avatar.ControllingClient.AgentId); + avatar.ControllingClient.SendRegionTeleport(regionHandle, 13, reg.ExternalEndPoint, 4, (1 << 4), + capsPath); + avatar.MakeChildAgent(); + if (KillObject != null) + { + KillObject(avatar.LocalId); + } + uint newRegionX = (uint)(regionHandle >> 40); + uint newRegionY = (((uint)(regionHandle)) >> 8); + uint oldRegionX = (uint)(m_regionInfo.RegionHandle >> 40); + uint oldRegionY = (((uint)(m_regionInfo.RegionHandle)) >> 8); + if (Util.fast_distance2d((int)(newRegionX - oldRegionX), (int)(newRegionY - oldRegionY)) > 3) + { + SendCloseChildAgentConnections(avatar); + } + } + else + { + avatar.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); + } + } + } + } + + /// + /// + /// + /// + /// + /// + public bool CrossToNeighbouringRegion(ulong regionhandle, LLUUID agentID, LLVector3 position, bool isFlying) + { + return m_commsProvider.InterRegion.ExpectAvatarCrossing(regionhandle, agentID, position, isFlying); + } + + public bool PrimCrossToNeighboringRegion(ulong regionhandle, LLUUID primID, string objData) + { + return m_commsProvider.InterRegion.InformRegionOfPrimCrossing(regionhandle, primID, objData); + } + + + public Dictionary GetGridSettings() + { + return m_commsProvider.GridService.GetGridSettings(); + } + + public void LogOffUser(LLUUID userid, LLUUID regionid, ulong regionhandle, float posx, float posy, float posz) + { + m_commsProvider.LogOffUser(userid, regionid, regionhandle, posx, posy, posz); + } + + public void ClearUserAgent(LLUUID avatarID) + { + m_commsProvider.UserService.clearUserAgent(avatarID); + } + + public void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms) + { + m_commsProvider.AddNewUserFriend(friendlistowner, friend, perms); + } + + public void UpdateUserFriendPerms(LLUUID friendlistowner, LLUUID friend, uint perms) + { + m_commsProvider.UpdateUserFriendPerms(friendlistowner, friend, perms); + } + + public void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend) + { + m_commsProvider.RemoveUserFriend(friendlistowner, friend); + } + + public List GetUserFriendList(LLUUID friendlistowner) + { + return m_commsProvider.GetUserFriendList(friendlistowner); + } + + public List RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY) + { + return m_commsProvider.GridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY); + } + + public List GenerateAgentPickerRequestResponse(LLUUID queryID, string query) + { + return m_commsProvider.GenerateAgentPickerRequestResponse(queryID, query); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Scenes/SceneEvents.cs b/trunk/OpenSim/Region/Environment/Scenes/SceneEvents.cs new file mode 100644 index 0000000000..cada9916b7 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/SceneEvents.cs @@ -0,0 +1,355 @@ +/* +* 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 libsecondlife; +using System; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.LandManagement; + +namespace OpenSim.Region.Environment.Scenes +{ + + /// + /// A class for triggering remote scene events. + /// + public class EventManager + { + public delegate void OnFrameDelegate(); + + public event OnFrameDelegate OnFrame; + + public delegate void ClientMovement(ScenePresence client); + + public event ClientMovement OnClientMovement; + + public delegate void OnBackupDelegate(IRegionDataStore datastore); + + public event OnBackupDelegate OnBackup; + + public delegate void OnNewClientDelegate(IClientAPI client); + + public event OnNewClientDelegate OnNewClient; + + public delegate void OnNewPresenceDelegate(ScenePresence presence); + + public event OnNewPresenceDelegate OnNewPresence; + + public delegate void OnRemovePresenceDelegate(LLUUID agentId); + + public event OnRemovePresenceDelegate OnRemovePresence; + + public delegate void OnParcelPrimCountUpdateDelegate(); + + public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate; + + public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj); + + public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd; + + public delegate void OnPluginConsoleDelegate(string[] args); + + public event OnPluginConsoleDelegate OnPluginConsole; + + public delegate void OnShutdownDelegate(); + + public event OnShutdownDelegate OnShutdown; + + public delegate void ObjectGrabDelegate(uint localID, LLVector3 offsetPos, IClientAPI remoteClient); + + public delegate void OnPermissionErrorDelegate(LLUUID user, string reason); + + public event ObjectGrabDelegate OnObjectGrab; + + public event OnPermissionErrorDelegate OnPermissionError; + + public delegate void NewRezScript(uint localID, LLUUID itemID, string script); + + public event NewRezScript OnRezScript; + + public delegate void RemoveScript(uint localID, LLUUID itemID); + + public event RemoveScript OnRemoveScript; + + public delegate bool SceneGroupMoved(LLUUID groupID, LLVector3 delta); + + public event SceneGroupMoved OnSceneGroupMove; + + public delegate void SceneGroupGrabed(LLUUID groupID, LLVector3 offset, LLUUID userID); + + public event SceneGroupGrabed OnSceneGroupGrab; + + public delegate void LandObjectAdded(Land newParcel, LLUUID regionUUID); + + public event LandObjectAdded OnLandObjectAdded; + + public delegate void LandObjectRemoved(LLUUID globalID); + + public event LandObjectRemoved OnLandObjectRemoved; + + public delegate void AvatarEnteringNewParcel(ScenePresence avatar, int localLandID, LLUUID regionID); + + public event AvatarEnteringNewParcel OnAvatarEnteringNewParcel; + + + public delegate void NewGridInstantMessage(GridInstantMessage message); + + public event NewGridInstantMessage OnGridInstantMessageToIMModule; + + public event NewGridInstantMessage OnGridInstantMessageToFriendsModule; + + public event NewGridInstantMessage OnGridInstantMessageToGroupsModule; + + public delegate void ClientClosed(LLUUID clientID); + + public event ClientClosed OnClientClosed; + + public delegate void ScriptChangedEvent(uint localID, uint change); + + public event ScriptChangedEvent OnScriptChangedEvent; + + public class MoneyTransferArgs : System.EventArgs + { + public LLUUID sender; + public LLUUID reciever; + + // Always false. The SL protocol sucks. + public bool authenticated = false; + + public int amount; + public int transactiontype; + public string description; + + public MoneyTransferArgs(LLUUID asender, LLUUID areciever, int aamount, int atransactiontype, string adescription) { + sender = asender; + reciever = areciever; + amount = aamount; + transactiontype = atransactiontype; + description = adescription; + } + } + + public delegate void MoneyTransferEvent(Object sender, MoneyTransferArgs e); + + public event MoneyTransferEvent OnMoneyTransfer; + + public void TriggerOnScriptChangedEvent(uint localID, uint change) + { + if (OnScriptChangedEvent != null) + OnScriptChangedEvent(localID,change); + } + + public void TriggerOnClientMovement(ScenePresence avatar) + { + if (OnClientMovement != null) + OnClientMovement(avatar); + } + + public void TriggerPermissionError(LLUUID user, string reason) + { + if (OnPermissionError != null) + OnPermissionError(user, reason); + } + + public void TriggerOnPluginConsole(string[] args) + { + if (OnPluginConsole != null) + OnPluginConsole(args); + } + + public void TriggerOnFrame() + { + if (OnFrame != null) + { + OnFrame(); + } + } + + public void TriggerOnNewClient(IClientAPI client) + { + if (OnNewClient != null) + OnNewClient(client); + } + + public void TriggerOnNewPresence(ScenePresence presence) + { + if (OnNewPresence != null) + OnNewPresence(presence); + } + + public void TriggerOnRemovePresence(LLUUID agentId) + { + if (OnRemovePresence != null) + { + OnRemovePresence(agentId); + } + } + + public void TriggerOnBackup(IRegionDataStore dstore) + { + if (OnBackup != null) + { + OnBackup(dstore); + } + } + + public void TriggerParcelPrimCountUpdate() + { + if (OnParcelPrimCountUpdate != null) + { + OnParcelPrimCountUpdate(); + } + } + + public void TriggerMoneyTransfer(Object sender, MoneyTransferArgs e) + { + if (OnMoneyTransfer != null) + { + OnMoneyTransfer(sender, e); + } + } + + + public void TriggerParcelPrimCountAdd(SceneObjectGroup obj) + { + if (OnParcelPrimCountAdd != null) + { + OnParcelPrimCountAdd(obj); + } + } + + public void TriggerShutdown() + { + if (OnShutdown != null) + OnShutdown(); + } + + public void TriggerObjectGrab(uint localID, LLVector3 offsetPos, IClientAPI remoteClient) + { + if (OnObjectGrab != null) + { + OnObjectGrab(localID, offsetPos, remoteClient); + } + } + + public void TriggerRezScript(uint localID, LLUUID itemID, string script) + { + if (OnRezScript != null) + { + OnRezScript(localID, itemID, script); + } + } + + public void TriggerRemoveScript(uint localID, LLUUID itemID) + { + if (OnRemoveScript != null) + { + OnRemoveScript(localID, itemID); + } + } + + public bool TriggerGroupMove(LLUUID groupID, LLVector3 delta) + { + if (OnSceneGroupMove != null) + { + return OnSceneGroupMove(groupID, delta); + } + return true; + } + + public void TriggerGroupGrab(LLUUID groupID, LLVector3 offset, LLUUID userID) + { + if (OnSceneGroupGrab != null) + { + OnSceneGroupGrab(groupID, offset, userID); + } + } + + public void TriggerLandObjectAdded(Land newParcel, LLUUID regionID) + { + if (OnLandObjectAdded != null) + { + OnLandObjectAdded(newParcel, regionID); + } + } + + public void TriggerLandObjectRemoved(LLUUID globalID) + { + if (OnLandObjectRemoved != null) + { + OnLandObjectRemoved(globalID); + } + } + + public void TriggerLandObjectUpdated(uint localParcelID, Land newParcel) + { + //triggerLandObjectRemoved(localParcelID); + TriggerLandObjectAdded(newParcel, newParcel.m_scene.RegionInfo.RegionID); + } + + public void TriggerAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, LLUUID regionID) + { + if (OnAvatarEnteringNewParcel != null) + { + OnAvatarEnteringNewParcel(avatar, localLandID, regionID); + } + } + + ///Used to pass instnat messages around between the Scene, the Friends Module and the Instant Messsage Module + ///Object containing the Instant Message Data + ///A bit vector containing the modules to send the message to + public void TriggerGridInstantMessage(GridInstantMessage message, InstantMessageReceiver whichModule) + { + if ((whichModule & InstantMessageReceiver.IMModule) != 0) + { + + if (OnGridInstantMessageToIMModule != null) + { + OnGridInstantMessageToIMModule(message); + } + } + if ((whichModule & InstantMessageReceiver.FriendsModule) != 0) + { + if (OnGridInstantMessageToFriendsModule != null) + { + OnGridInstantMessageToFriendsModule(message); + } + + } + } + + public void TriggerClientClosed(LLUUID ClientID) + { + if (OnClientClosed != null) + { + OnClientClosed(ClientID); + } + } + + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Scenes/SceneManager.cs b/trunk/OpenSim/Region/Environment/Scenes/SceneManager.cs new file mode 100644 index 0000000000..01c9232841 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/SceneManager.cs @@ -0,0 +1,429 @@ +/* +* 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; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Environment.Scenes +{ + public delegate void RestartSim(RegionInfo thisregion); + + public class SceneManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public event RestartSim OnRestartSim; + + private readonly List m_localScenes; + private Scene m_currentScene = null; + + public List Scenes + { + get { return m_localScenes; } + } + + public Scene CurrentScene + { + get { return m_currentScene; } + } + + public Scene CurrentOrFirstScene + { + get + { + if (m_currentScene == null) + { + return m_localScenes[0]; + } + else + { + return m_currentScene; + } + } + } + + public SceneManager() + { + m_localScenes = new List(); + } + + public void Close() + { + for (int i = 0; i < m_localScenes.Count; i++) + { + m_localScenes[i].Close(); + } + } + + public void Close(Scene cscene) + { + if (m_localScenes.Contains(cscene)) + { + for (int i = 0; i < m_localScenes.Count; i++) + { + if (m_localScenes[i].Equals(cscene)) + { + m_localScenes[i].Close(); + } + } + } + } + + public void Add(Scene scene) + { + scene.OnRestart += HandleRestart; + m_localScenes.Add(scene); + } + + public void HandleRestart(RegionInfo rdata) + { + m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main"); + int RegionSceneElement = -1; + for (int i = 0; i < m_localScenes.Count; i++) + { + if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName) + { + RegionSceneElement = i; + } + } + + // Now we make sure the region is no longer known about by the SceneManager + // Prevents duplicates. + + if (RegionSceneElement >= 0) + { + m_localScenes.RemoveAt(RegionSceneElement); + } + + // Send signal to main that we're restarting this sim. + OnRestartSim(rdata); + } + + public void SendSimOnlineNotification(ulong regionHandle) + { + RegionInfo Result = null; + + for (int i = 0; i < m_localScenes.Count; i++) + { + if (m_localScenes[i].RegionInfo.RegionHandle == regionHandle) + { + // Inform other regions to tell their avatar about me + Result = m_localScenes[i].RegionInfo; + } + } + if (!(Result.Equals(null))) + { + for (int i = 0; i < m_localScenes.Count; i++) + { + if (m_localScenes[i].RegionInfo.RegionHandle != regionHandle) + { + // Inform other regions to tell their avatar about me + //m_localScenes[i].OtherRegionUp(Result); + } + } + } + else + { + m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up"); + } + } + + public void SaveCurrentSceneToXml(string filename) + { + CurrentOrFirstScene.SavePrimsToXml(filename); + } + + public void LoadCurrentSceneFromXml(string filename, bool generateNewIDs, LLVector3 loadOffset) + { + CurrentOrFirstScene.LoadPrimsFromXml(filename, generateNewIDs, loadOffset); + } + + public void SaveCurrentSceneToXml2(string filename) + { + CurrentOrFirstScene.SavePrimsToXml2(filename); + } + + public void LoadCurrentSceneFromXml2(string filename) + { + CurrentOrFirstScene.LoadPrimsFromXml2(filename); + } + + public bool RunTerrainCmdOnCurrentScene(string[] cmdparams, ref string result) + { + if (m_currentScene == null) + { + bool success = true; + foreach (Scene scene in m_localScenes) + { + if (!scene.Terrain.RunTerrainCmd(cmdparams, ref result, scene.RegionInfo.RegionName)) + { + success = false; + } + + // Messy way of preventing us printing out the same help text for each scene + if (cmdparams.Length <= 0 || cmdparams[0] == "help") + { + break; + } + } + + return success; + } + else + { + return m_currentScene.Terrain.RunTerrainCmd(cmdparams, ref result, m_currentScene.RegionInfo.RegionName); + } + } + + public void SendCommandToCurrentSceneScripts(string[] cmdparams) + { + ForEachCurrentScene(delegate(Scene scene) { scene.SendCommandToPlugins(cmdparams); }); + } + + public void SetBypassPermissionsOnCurrentScene(bool bypassPermissions) + { + ForEachCurrentScene(delegate(Scene scene) { scene.PermissionsMngr.BypassPermissions = bypassPermissions; }); + } + + private void ForEachCurrentScene(Action func) + { + if (m_currentScene == null) + { + m_localScenes.ForEach(func); + } + else + { + func(m_currentScene); + } + } + + public void RestartCurrentScene() + { + ForEachCurrentScene(delegate(Scene scene) { scene.RestartNow(); }); + } + + public void BackupCurrentScene() + { + ForEachCurrentScene(delegate(Scene scene) { scene.Backup(); }); + } + + public void HandleAlertCommandOnCurrentScene(string[] cmdparams) + { + ForEachCurrentScene(delegate(Scene scene) { scene.HandleAlertCommand(cmdparams); }); + } + + public void SendGeneralMessage(string msg) + { + ForEachCurrentScene(delegate(Scene scene) { scene.SendGeneralAlert(msg); }); + } + + public bool TrySetCurrentScene(string regionName) + { + if ((String.Compare(regionName, "root") == 0) || (String.Compare(regionName, "..") == 0)) + { + m_currentScene = null; + return true; + } + else + { + Console.WriteLine("Searching for Region: '" + regionName + "'"); + + foreach (Scene scene in m_localScenes) + { + if (String.Compare(scene.RegionInfo.RegionName, regionName, true) == 0) + { + m_currentScene = scene; + return true; + } + } + + return false; + } + } + + public bool TryGetScene(string regionName, out Scene scene) + { + foreach (Scene mscene in m_localScenes) + { + if (String.Compare(mscene.RegionInfo.RegionName, regionName, true) == 0) + { + scene = mscene; + return true; + } + } + scene = null; + return false; + } + + public bool TryGetScene(LLUUID regionID, out Scene scene) + { + foreach (Scene mscene in m_localScenes) + { + if (mscene.RegionInfo.RegionID == regionID) + { + scene = mscene; + return true; + } + } + scene = null; + return false; + } + + public void SetDebugPacketOnCurrentScene(int newDebug) + { + ForEachCurrentScene(delegate(Scene scene) + { + List scenePresences = scene.GetScenePresences(); + + foreach (ScenePresence scenePresence in scenePresences) + { + if (!scenePresence.IsChildAgent) + { + m_log.ErrorFormat("Packet debug for {0} {1} set to {2}", + scenePresence.Firstname, + scenePresence.Lastname, + newDebug); + + scenePresence.ControllingClient.SetDebug(newDebug); + } + } + }); + } + + public List GetCurrentSceneAvatars() + { + List avatars = new List(); + + ForEachCurrentScene(delegate(Scene scene) + { + List scenePrescences = scene.GetScenePresences(); + + foreach (ScenePresence scenePrescence in scenePrescences) + { + if (!scenePrescence.IsChildAgent) + { + avatars.Add(scenePrescence); + } + } + }); + + return avatars; + } + + public RegionInfo GetRegionInfo(ulong regionHandle) + { + foreach (Scene scene in m_localScenes) + { + if (scene.RegionInfo.RegionHandle == regionHandle) + { + return scene.RegionInfo; + } + } + + return null; + } + + public void SetCurrentSceneTimePhase(int timePhase) + { + ForEachCurrentScene(delegate(Scene scene) + { + scene.SetTimePhase( + timePhase) + ; + }); + } + + public void ForceCurrentSceneClientUpdate() + { + ForEachCurrentScene(delegate(Scene scene) { scene.ForceClientUpdate(); }); + } + + public void HandleEditCommandOnCurrentScene(string[] cmdparams) + { + ForEachCurrentScene(delegate(Scene scene) { scene.HandleEditCommand(cmdparams); }); + } + + public bool TryGetAvatar(LLUUID avatarId, out ScenePresence avatar) + { + foreach (Scene scene in m_localScenes) + { + if (scene.TryGetAvatar(avatarId, out avatar)) + { + return true; + } + } + + avatar = null; + return false; + } + + public bool TryGetAvatarsScene(LLUUID avatarId, out Scene scene) + { + ScenePresence avatar = null; + foreach (Scene mScene in m_localScenes) + { + if (mScene.TryGetAvatar(avatarId, out avatar)) + { + scene = mScene; + return true; + } + } + + scene = null; + return false; + } + + public void CloseScene(Scene scene) + { + m_localScenes.Remove(scene); + scene.Close(); + } + + public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) + { + foreach (Scene scene in m_localScenes) + { + if (scene.TryGetAvatarByName(avatarName, out avatar)) + { + return true; + } + } + + avatar = null; + return false; + } + + public void ForEachScene(Action action) + { + m_localScenes.ForEach(action); + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs b/trunk/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs new file mode 100644 index 0000000000..e26ed5c0a5 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs @@ -0,0 +1,275 @@ +/* +* 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; + +using libsecondlife; + +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; + +namespace OpenSim.Region.Environment.Scenes +{ + public partial class SceneObjectGroup : EntityBase + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Start a given script. + /// + /// + /// A + /// + public void StartScript(uint localID, LLUUID itemID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + part.StartScript(itemID); + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Couldn't find part {0} in object group {1}, {2} to start script with ID {3}", + localID, Name, UUID, itemID); + } + } + +// /// Start a given script. +// /// +// /// +// /// A +// /// +// public void StartScript(LLUUID partID, LLUUID itemID) +// { +// SceneObjectPart part = GetChildPart(partID); +// if (part != null) +// { +// part.StartScript(itemID); +// } +// else +// { +// m_log.ErrorFormat( +// "[PRIMINVENTORY]: " + +// "Couldn't find part {0} in object group {1}, {2} to start script with ID {3}", +// localID, Name, UUID, itemID); +// } +// } + + /// + /// Start the scripts contained in all the prims in this group. + /// + public void StartScripts() + { + // Don't start scripts if they're turned off in the region! + if (!((m_scene.RegionInfo.EstateSettings.regionFlags & Simulator.RegionFlags.SkipScripts) == Simulator.RegionFlags.SkipScripts)) + { + foreach (SceneObjectPart part in m_parts.Values) + { + part.StartScripts(); + } + } + } + + public void StopScripts() + { + lock (m_parts) + { + foreach (SceneObjectPart part in m_parts.Values) + { + part.StopScripts(); + } + } + } + + /// Start a given script. + /// + /// + /// A + /// + public void StopScript(uint partID, LLUUID itemID) + { + SceneObjectPart part = GetChildPart(partID); + if (part != null) + { + part.StopScript(itemID); + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Couldn't find part {0} in object group {1}, {2} to stop script with ID {3}", + partID, Name, UUID, itemID); + } + } + + /// + /// + /// + /// + /// + public bool GetPartInventoryFileName(IClientAPI remoteClient, uint localID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + return part.GetInventoryFileName(remoteClient, localID); + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Couldn't find part {0} in object group {1}, {2} to retreive prim inventory", + localID, Name, UUID); + } + return false; + } + + public void RequestInventoryFile(uint localID, IXfer xferManager) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + part.RequestInventoryFile(xferManager); + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Couldn't find part {0} in object group {1}, {2} to request inventory data", + localID, Name, UUID); + } + } + + /// + /// Add an inventory item to a prim in this group. + /// + /// + /// + /// + /// The item UUID that should be used by the new item. + /// + public bool AddInventoryItem(IClientAPI remoteClient, uint localID, + InventoryItemBase item, LLUUID copyItemID) + { + LLUUID newItemId = (!copyItemID.Equals(null)) ? copyItemID : item.inventoryID; + + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ItemID = newItemId; + taskItem.AssetID = item.assetID; + taskItem.Name = item.inventoryName; + taskItem.Description = item.inventoryDescription; + taskItem.OwnerID = item.avatarID; + taskItem.CreatorID = item.creatorsID; + taskItem.Type = item.assetType; + taskItem.InvType = item.invType; + part.AddInventoryItem(taskItem); + + return true; + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Couldn't find prim local ID {0} in group {1}, {2} to add inventory item ID {3}", + localID, Name, UUID, newItemId); + } + + return false; + } + + /// + /// Returns an existing inventory item. Returns the original, so any changes will be live. + /// + /// + /// + /// null if the item does not exist + public TaskInventoryItem GetInventoryItem(uint primID, LLUUID itemID) + { + SceneObjectPart part = GetChildPart(primID); + if (part != null) + { + return part.GetInventoryItem(itemID); + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Couldn't find prim local ID {0} in prim {1}, {2} to get inventory item ID {3}", + primID, part.Name, part.UUID, itemID); + } + + return null; + } + + /// + /// Update an existing inventory item. + /// + /// The updated item. An item with the same id must already exist + /// in this prim's inventory + /// false if the item did not exist, true if the update occurred succesfully + public bool UpdateInventoryItem(TaskInventoryItem item) + { + SceneObjectPart part = GetChildPart(item.ParentPartID); + if (part != null) + { + part.UpdateInventoryItem(item); + + return true; + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Couldn't find prim ID {0} to update item {1}, {2}", + item.ParentPartID, item.Name, item.ItemID); + } + + return false; + } + + public int RemoveInventoryItem(uint localID, LLUUID itemID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + int type = part.RemoveInventoryItem(itemID); + + return type; + } + + return -1; + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/trunk/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs new file mode 100644 index 0000000000..519858b30b --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs @@ -0,0 +1,1781 @@ +/* +* 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; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Text; +using System.Xml; +using Axiom.Math; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Environment.Scenes +{ + public delegate void PrimCountTaintedDelegate(); + + public partial class SceneObjectGroup : EntityBase + { + private Encoding enc = Encoding.ASCII; + + protected SceneObjectPart m_rootPart; + protected Dictionary m_parts = new Dictionary(); + + protected ulong m_regionHandle; + + public event PrimCountTaintedDelegate OnPrimCountTainted; + + /// + /// Signal whether the non-inventory attributes of any prims in the group have changed + /// since the group's last persistent backup + /// + public bool HasGroupChanged = false; + + + private LLVector3 lastPhysGroupPos; + private LLQuaternion lastPhysGroupRot; + + #region Properties + + /// + /// + /// + public int PrimCount + { + get { return m_parts.Count; } + } + + public LLQuaternion GroupRotation + { + get { return m_rootPart.RotationOffset; } + } + public LLUUID GroupID + { + get { return m_rootPart.GroupID; } + set { m_rootPart.GroupID = value; } + } + /// + /// + /// + public LLVector3 GroupCentrePoint + { + get { return new LLVector3(0, 0, 0); } + } + + public Dictionary Children + { + get { return m_parts; } + set { m_parts = value; } + } + + public SceneObjectPart RootPart + { + get { return m_rootPart; } + set { m_rootPart = value; } + } + + public ulong RegionHandle + { + get { return m_regionHandle; } + set + { + m_regionHandle = value; + lock (m_parts) + { + foreach (SceneObjectPart part in m_parts.Values) + { + part.RegionHandle = m_regionHandle; + } + } + } + } + + public override LLVector3 AbsolutePosition + { + get { return m_rootPart.GroupPosition; } + set + { + LLVector3 val = value; + if (val.X > 257f || val.X < -1f || val.Y > 257f || val.Y < -1f) + { + m_scene.CrossPrimGroupIntoNewRegion(val, this); + } + + + lock (m_parts) + { + foreach (SceneObjectPart part in m_parts.Values) + { + part.GroupPosition = val; + } + } + //if (m_rootPart.PhysActor != null) + //{ + //m_rootPart.PhysActor.Position = + //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y, + //m_rootPart.GroupPosition.Z); + //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); + //} + } + } + + public override uint LocalId + { + get { return m_rootPart.LocalID; } + set { m_rootPart.LocalID = value; } + } + + public override LLUUID UUID + { + get { return m_rootPart.UUID; } + set { m_rootPart.UUID = value; } + } + + public LLUUID OwnerID + { + get { return m_rootPart.OwnerID; } + set { m_rootPart.OwnerID = value; } + } + + public Color Color + { + get { return m_rootPart.Color; } + set { m_rootPart.Color = value; } + } + + public string Text + { + get { return m_rootPart.Text; } + set { m_rootPart.Text = value; } + } + + /// + /// Added because the Parcel code seems to use it + /// but not sure a object should have this + /// as what does it tell us? that some avatar has selected it (but not what Avatar/user) + /// think really there should be a list (or whatever) in each scenepresence + /// saying what prim(s) that user has selected. + /// + protected bool m_isSelected = false; + + protected virtual bool InSceneBackup + { + get { return true; } + } + + public bool IsSelected + { + get { return m_isSelected; } + set { + m_isSelected = value; + // Tell physics engine that group is selected + if (m_rootPart.PhysActor != null) + { + m_rootPart.PhysActor.Selected = value; + } + } + } + + // The UUID for the Region this Object is in. + public LLUUID RegionUUID + { + get + { + if (m_scene != null) + { + return m_scene.RegionInfo.RegionID; + } + return LLUUID.Zero; + } + } + + #endregion + + #region Constructors + + /// + /// + /// + public SceneObjectGroup() + { + } + + /// + /// This constructor creates a SceneObjectGroup using a pre-existing SceneObjectPart. + /// The original SceneObjectPart will be used rather than a copy, preserving + /// its existing localID and UUID. + /// + public SceneObjectGroup(Scene scene, ulong regionHandle, SceneObjectPart part) + { + m_scene = scene; + part.SetParent(this); + part.ParentID = 0; + part.LinkNum = 0; + m_parts.Add(part.UUID, part); + + SetPartAsRoot(part); + + RegionHandle = regionHandle; + + AttachToBackup(); + + ApplyPhysics(scene.m_physicalPrim); + + ScheduleGroupForFullUpdate(); + } + + /// + /// + /// + public SceneObjectGroup(Scene scene, ulong regionHandle, string xmlData) + { + m_scene = scene; + m_regionHandle = regionHandle; + + StringReader sr = new StringReader(xmlData); + XmlTextReader reader = new XmlTextReader(sr); + reader.Read(); + reader.ReadStartElement("SceneObjectGroup"); + reader.ReadStartElement("RootPart"); + m_rootPart = SceneObjectPart.FromXml(reader); + AddPart(m_rootPart); + reader.ReadEndElement(); + + while (reader.Read()) + { + switch (reader.NodeType) + { + case XmlNodeType.Element: + if (reader.Name == "Part") + { + reader.Read(); + SceneObjectPart part = SceneObjectPart.FromXml(reader); + part.LocalID = m_scene.PrimIDAllocate(); + AddPart(part); + part.RegionHandle = m_regionHandle; + + part.TrimPermissions(); + } + break; + case XmlNodeType.EndElement: + break; + } + } + reader.Close(); + sr.Close(); + + + m_rootPart.LocalID = m_scene.PrimIDAllocate(); + m_rootPart.ParentID = 0; + m_rootPart.RegionHandle = m_regionHandle; + UpdateParentIDs(); + + AttachToBackup(); + + ApplyPhysics(scene.m_physicalPrim); + + ScheduleGroupForFullUpdate(); + } + + /// + /// + /// + public SceneObjectGroup(string xmlData) + { + StringReader sr = new StringReader(xmlData); + XmlTextReader reader = new XmlTextReader(sr); + reader.Read(); + + reader.ReadStartElement("SceneObjectGroup"); + m_rootPart = SceneObjectPart.FromXml(reader); + m_rootPart.SetParent(this); + m_parts.Add(m_rootPart.UUID, m_rootPart); + m_rootPart.ParentID = 0; + m_rootPart.LinkNum = 0; + + reader.Read(); + bool more = true; + + while (more) + { + switch (reader.NodeType) + { + case XmlNodeType.Element: + if (reader.Name == "SceneObjectPart") + { + SceneObjectPart Part = SceneObjectPart.FromXml(reader); + AddPart(Part); + } + else + { + Console.WriteLine("found unexpected element: " + reader.Name); + reader.Read(); + } + break; + case XmlNodeType.EndElement: + reader.Read(); + break; + } + more = !reader.EOF; + } + reader.Close(); + sr.Close(); + + UpdateParentIDs(); + + ScheduleGroupForFullUpdate(); + } + + private void AttachToBackup() + { + if (InSceneBackup) + { + m_scene.EventManager.OnBackup += ProcessBackup; + } + } + + public EntityIntersection TestIntersection(Ray hRay) + { + // We got a request from the inner_scene to raytrace along the Ray hRay + // We're going to check all of the prim in this group for intersection with the ray + // If we get a result, we're going to find the closest result to the origin of the ray + // and send back the intersection information back to the innerscene. + + EntityIntersection returnresult = new EntityIntersection(); + + foreach (SceneObjectPart part in m_parts.Values) + { + // Temporary commented to stop compiler warning + //Vector3 partPosition = + // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); + Quaternion parentrotation = + new Quaternion(GroupRotation.W, GroupRotation.X, GroupRotation.Y, GroupRotation.Z); + + // Telling the prim to raytrace. + EntityIntersection inter = part.TestIntersection(hRay, parentrotation); + + // This may need to be updated to the maximum draw distance possible.. + // We might (and probably will) be checking for prim creation from other sims + // when the camera crosses the border. + float idist = (float)Constants.RegionSize; + + + if (inter.HitTF) + { + // We need to find the closest prim to return to the testcaller along the ray + if (inter.distance < idist) + { + idist = inter.distance; + returnresult.HitTF = true; + returnresult.ipoint = inter.ipoint; + returnresult.obj = part; + returnresult.normal = inter.normal; + returnresult.distance = inter.distance; + } + } + } + return returnresult; + } + + /// + /// + /// + public SceneObjectGroup(Scene scene, ulong regionHandle, LLUUID ownerID, uint localID, LLVector3 pos, + LLQuaternion rot, PrimitiveBaseShape shape) + { + m_regionHandle = regionHandle; + m_scene = scene; + + // this.Pos = pos; + LLVector3 rootOffset = new LLVector3(0, 0, 0); + SceneObjectPart newPart = + new SceneObjectPart(m_regionHandle, this, ownerID, localID, shape, pos, rot, rootOffset); + newPart.LinkNum = m_parts.Count; + m_parts.Add(newPart.UUID, newPart); + SetPartAsRoot(newPart); + + AttachToBackup(); + + //ApplyPhysics(scene.m_physicalPrim); + } + + /// + /// + /// + public SceneObjectGroup(Scene scene, ulong regionHandle, LLUUID ownerID, uint localID, LLVector3 pos, + PrimitiveBaseShape shape) + : this(scene, regionHandle, ownerID, localID, pos, LLQuaternion.Identity, shape) + { + } + + #endregion + + public string ToXmlString() + { + using (StringWriter sw = new StringWriter()) + { + using (XmlTextWriter writer = new XmlTextWriter(sw)) + { + ToXml(writer); + } + + return sw.ToString(); + } + } + + public void ToXml(XmlTextWriter writer) + { + writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty); + writer.WriteStartElement(String.Empty, "RootPart", String.Empty); + m_rootPart.ToXml(writer); + writer.WriteEndElement(); + writer.WriteStartElement(String.Empty, "OtherParts", String.Empty); + foreach (SceneObjectPart part in m_parts.Values) + { + if (part.UUID != m_rootPart.UUID) + { + writer.WriteStartElement(String.Empty, "Part", String.Empty); + part.ToXml(writer); + writer.WriteEndElement(); + } + } + writer.WriteEndElement(); + writer.WriteEndElement(); + } + + public string ToXmlString2() + { + using (StringWriter sw = new StringWriter()) + { + using (XmlTextWriter writer = new XmlTextWriter(sw)) + { + ToXml2(writer); + } + + return sw.ToString(); + } + } + + public void ToXml2(XmlTextWriter writer) + { + writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty); + m_rootPart.ToXml(writer); + writer.WriteStartElement(String.Empty, "OtherParts", String.Empty); + foreach (SceneObjectPart part in m_parts.Values) + { + if (part.UUID != m_rootPart.UUID) + { + part.ToXml(writer); + } + } + writer.WriteEndElement(); + writer.WriteEndElement(); + } + + #region Copying + + /// + /// + /// + /// + public SceneObjectGroup Copy(LLUUID cAgentID, LLUUID cGroupID) + { + SceneObjectGroup dupe = (SceneObjectGroup) MemberwiseClone(); + dupe.m_parts = new Dictionary(); + dupe.m_parts.Clear(); + //dupe.OwnerID = AgentID; + //dupe.GroupID = GroupID; + dupe.AbsolutePosition = new LLVector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); + dupe.m_scene = m_scene; + dupe.m_regionHandle = m_regionHandle; + + dupe.CopyRootPart(m_rootPart, OwnerID, GroupID); + dupe.m_rootPart.TrimPermissions(); + + /// may need to create a new Physics actor. + if (dupe.RootPart.PhysActor != null) + { + PrimitiveBaseShape pbs = dupe.RootPart.Shape; + + dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( + dupe.RootPart.Name, + pbs, + new PhysicsVector(dupe.RootPart.AbsolutePosition.X, dupe.RootPart.AbsolutePosition.Y, + dupe.RootPart.AbsolutePosition.Z), + new PhysicsVector(dupe.RootPart.Scale.X, dupe.RootPart.Scale.Y, dupe.RootPart.Scale.Z), + new Quaternion(dupe.RootPart.RotationOffset.W, dupe.RootPart.RotationOffset.X, + dupe.RootPart.RotationOffset.Y, dupe.RootPart.RotationOffset.Z), + dupe.RootPart.PhysActor.IsPhysical); + dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); + } + // Now we've made a copy that replaces this one, we need to + // switch the owner to the person who did the copying + // Second Life copies an object and duplicates the first one in it's place + // So, we have to make a copy of this one, set it in it's place then set the owner on this one + + SetRootPartOwner(m_rootPart, cAgentID, cGroupID); + + + m_rootPart.ScheduleFullUpdate(); + + List partList = new List(m_parts.Values); + foreach (SceneObjectPart part in partList) + { + if (part.UUID != m_rootPart.UUID) + { + dupe.CopyPart(part, OwnerID, GroupID); + SetPartOwner(part, cAgentID, cGroupID); + part.ScheduleFullUpdate(); + } + } + dupe.UpdateParentIDs(); + + dupe.AttachToBackup(); + ScheduleGroupForFullUpdate(); + + return dupe; + } + + /// + /// + /// + /// + public void CopyRootPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID) + { + SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count); + newPart.SetParent(this); + m_parts.Add(newPart.UUID, newPart); + SetPartAsRoot(newPart); + } + + public void applyImpulse(PhysicsVector impulse) + { + // We check if rootpart is null here because scripts don't delete if you delete the host. + // This means that unfortunately, we can pass a null physics actor to Simulate! + // Make sure we don't do that! + SceneObjectPart rootpart = m_rootPart; + if (rootpart != null) + { + if (rootpart.PhysActor != null) + { + rootpart.PhysActor.AddForce(impulse); + m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor); + } + } + } + + public void SetRootPartOwner(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID) + { + part.LastOwnerID = part.OwnerID; + part.OwnerID = cAgentID; + part.GroupID = cGroupID; + + + if (part.OwnerID != cAgentID) + { + // Apply Next Owner Permissions if we're not bypassing permissions + if (!m_scene.PermissionsMngr.BypassPermissions) + m_rootPart.ApplyNextOwnerPermissions(); + } + + part.ScheduleFullUpdate(); + } + + /// + /// + /// + /// + public void CopyPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID) + { + SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count); + newPart.SetParent(this); + m_parts.Add(newPart.UUID, newPart); + SetPartAsNonRoot(newPart); + } + + /// + /// Reset the LLUUIDs for all the prims that make up this group. + /// + /// This is called by methods which want to add a new group to an existing scene, in order + /// to ensure that there are no clashes with groups already present. + /// + public void ResetIDs() + { + List partsList = new List(m_parts.Values); + m_parts.Clear(); + foreach (SceneObjectPart part in partsList) + { + part.ResetIDs(m_parts.Count); + m_parts.Add(part.UUID, part); + } + } + + /// + /// + /// + /// + public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, LLUUID AgentID, uint RequestFlags) + { + //RootPart.ServiceObjectPropertiesFamilyRequest(remoteClient, AgentID, RequestFlags); + ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket) PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); + // TODO: don't create new blocks if recycling an old packet + + ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); + objPropDB.RequestFlags = RequestFlags; + objPropDB.ObjectID = RootPart.UUID; + objPropDB.OwnerID = RootPart.ObjectOwner; + objPropDB.GroupID = RootPart.GroupID; + objPropDB.BaseMask = RootPart.BaseMask; + objPropDB.OwnerMask = RootPart.OwnerMask; + objPropDB.GroupMask = RootPart.GroupMask; + objPropDB.EveryoneMask = RootPart.EveryoneMask; + objPropDB.NextOwnerMask = RootPart.NextOwnerMask; + + // TODO: More properties are needed in SceneObjectPart! + objPropDB.OwnershipCost = RootPart.OwnershipCost; + objPropDB.SaleType = RootPart.ObjectSaleType; + objPropDB.SalePrice = RootPart.SalePrice; + objPropDB.Category = RootPart.Category; + objPropDB.LastOwnerID = RootPart.CreatorID; + objPropDB.Name = Helpers.StringToField(RootPart.Name); + objPropDB.Description = Helpers.StringToField(RootPart.Description); + objPropFamilyPack.ObjectData = objPropDB; + remoteClient.OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task); + } + + public void SetPartOwner(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID) + { + part.OwnerID = cAgentID; + part.GroupID = cGroupID; + } + + #endregion + + #region Scheduling + + /// + /// + /// + public override void Update() + { + if (Util.GetDistanceTo(lastPhysGroupPos, AbsolutePosition) > 0.02) + { + foreach (SceneObjectPart part in m_parts.Values) + { + if (part.UpdateFlag == 0) part.UpdateFlag = 1; + } + lastPhysGroupPos = AbsolutePosition; + } + if ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1) + || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1) + || (Math.Abs(lastPhysGroupRot.Y - GroupRotation.Y) > 0.1) + || (Math.Abs(lastPhysGroupRot.Z - GroupRotation.Z) > 0.1)) + { + foreach (SceneObjectPart part in m_parts.Values) + { + if (part.UpdateFlag == 0) part.UpdateFlag = 1; + } + lastPhysGroupRot = GroupRotation; + } + foreach (SceneObjectPart part in m_parts.Values) + { + part.SendScheduledUpdates(); + } + } + + public void ScheduleFullUpdateToAvatar(ScenePresence presence) + { + foreach (SceneObjectPart part in m_parts.Values) + { + part.AddFullUpdateToAvatar(presence); + } + } + + public void ScheduleTerseUpdateToAvatar(ScenePresence presence) + { + foreach (SceneObjectPart part in m_parts.Values) + { + part.AddTerseUpdateToAvatar(presence); + } + } + + /// + /// + /// + public void ScheduleGroupForFullUpdate() + { + HasGroupChanged = true; + foreach (SceneObjectPart part in m_parts.Values) + { + part.ScheduleFullUpdate(); + } + } + + /// + /// + /// + public void ScheduleGroupForTerseUpdate() + { + HasGroupChanged = true; + foreach (SceneObjectPart part in m_parts.Values) + { + part.ScheduleTerseUpdate(); + } + } + + /// + /// + /// + public void SendGroupFullUpdate() + { + HasGroupChanged = true; + foreach (SceneObjectPart part in m_parts.Values) + { + part.SendFullUpdateToAllClients(); + } + } + + /// + /// + /// + public void SendGroupTerseUpdate() + { + HasGroupChanged = true; + foreach (SceneObjectPart part in m_parts.Values) + { + part.SendTerseUpdateToAllClients(); + } + } + + #endregion + + #region SceneGroupPart Methods + + /// + /// Get the child part by LinkNum + /// + /// + /// null if no child part with that linknum or child part + public SceneObjectPart GetLinkNumPart(int linknum) + { + foreach (SceneObjectPart part in m_parts.Values) + { + if (part.LinkNum == linknum) + { + return part; + } + } + return null; + } + + /// + /// Get a child part with a given UUID + /// + /// + /// null if a child part with the primID was not found + public SceneObjectPart GetChildPart(LLUUID primID) + { + SceneObjectPart childPart = null; + if (m_parts.ContainsKey(primID)) + { + childPart = m_parts[primID]; + } + return childPart; + } + + /// + /// Get a child part with a given local ID + /// + /// + /// null if a child part with the local ID was not found + public SceneObjectPart GetChildPart(uint localID) + { + foreach (SceneObjectPart part in m_parts.Values) + { + if (part.LocalID == localID) + { + return part; + } + } + return null; + } + + /// + /// Does this group contain the child prim + /// should be able to remove these methods once we have a entity index in scene + /// + /// + /// + public bool HasChildPrim(LLUUID primID) + { + if (m_parts.ContainsKey(primID)) + { + return true; + } + return false; + } + + /// + /// Does this group contain the child prim + /// should be able to remove these methods once we have a entity index in scene + /// + /// + /// + public bool HasChildPrim(uint localID) + { + foreach (SceneObjectPart part in m_parts.Values) + { + if (part.LocalID == localID) + { + return true; + } + } + return false; + } + + #endregion + + #region Packet Handlers + + /// + /// Link the prims in a given group to this group + /// + /// The group of prims which should be linked to this group + public void LinkToGroup(SceneObjectGroup objectGroup) + { + SceneObjectPart linkPart = objectGroup.m_rootPart; + + Vector3 oldGroupPosition = + new Vector3(linkPart.GroupPosition.X, linkPart.GroupPosition.Y, linkPart.GroupPosition.Z); + Quaternion oldRootRotation = + new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X, linkPart.RotationOffset.Y, + linkPart.RotationOffset.Z); + + linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; + linkPart.GroupPosition = AbsolutePosition; + Vector3 axPos = new Vector3(linkPart.OffsetPosition.X, linkPart.OffsetPosition.Y, linkPart.OffsetPosition.Z); + + Quaternion parentRot = + new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y, + m_rootPart.RotationOffset.Z); + axPos = parentRot.Inverse()*axPos; + + linkPart.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z); + Quaternion oldRot = + new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X, linkPart.RotationOffset.Y, + linkPart.RotationOffset.Z); + Quaternion newRot = parentRot.Inverse()*oldRot; + linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w); + + linkPart.ParentID = m_rootPart.LocalID; + linkPart.LinkNum = m_parts.Count; + + m_parts.Add(linkPart.UUID, linkPart); + linkPart.SetParent(this); + + //if (linkPart.PhysActor != null) + //{ + // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); + + //linkPart.PhysActor = null; + //} + + //TODO: rest of parts + foreach (SceneObjectPart part in objectGroup.Children.Values) + { + if (part.UUID != objectGroup.m_rootPart.UUID) + { + LinkNonRootPart(part, oldGroupPosition, oldRootRotation); + } + } + + DetachFromBackup(objectGroup); + + m_scene.DeleteEntity(objectGroup.UUID); + + objectGroup.DeleteParts(); + AbsolutePosition = AbsolutePosition; + ScheduleGroupForFullUpdate(); + } + + /// + /// Delink the given prim from this group. The delinked prim is established as + /// an independent SceneObjectGroup. + /// + /// + public void DelinkFromGroup(uint partID) + { + SceneObjectPart linkPart = GetChildPart(partID); + + if (null != linkPart) + { + LLQuaternion worldRot = linkPart.GetWorldRotation(); + + // Remove the part from this object + m_parts.Remove(linkPart.UUID); + linkPart.ParentID = 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 + = new Quaternion( + m_rootPart.RotationOffset.W, + m_rootPart.RotationOffset.X, + m_rootPart.RotationOffset.Y, + m_rootPart.RotationOffset.Z); + + Vector3 axPos + = new Vector3( + linkPart.OffsetPosition.X, + linkPart.OffsetPosition.Y, + linkPart.OffsetPosition.Z); + + axPos = parentRot*axPos; + linkPart.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z); + linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; + linkPart.OffsetPosition = new LLVector3(0, 0, 0); + + linkPart.RotationOffset = worldRot; + + // This chunk is probably unnecesary now - delete later on + /* + Quaternion oldRot + = new Quaternion( + linkPart.RotationOffset.W, + linkPart.RotationOffset.X, + linkPart.RotationOffset.Y, + linkPart.RotationOffset.Z); + Quaternion newRot = parentRot*oldRot; + linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w); + */ + + // Add physics information back to delinked part if appropriate + // XXX This is messy and should be refactorable with the similar section in + // SceneObjectPart.UpdatePrimFlags() + //if (m_rootPart.PhysActor != null) + //{ + //linkPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( + //linkPart.Name, + //linkPart.Shape, + //new PhysicsVector(linkPart.AbsolutePosition.X, linkPart.AbsolutePosition.Y, + //linkPart.AbsolutePosition.Z), + //new PhysicsVector(linkPart.Scale.X, linkPart.Scale.Y, linkPart.Scale.Z), + //new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X, + //linkPart.RotationOffset.Y, linkPart.RotationOffset.Z), + //m_rootPart.PhysActor.IsPhysical); + //m_rootPart.DoPhysicsPropertyUpdate(m_rootPart.PhysActor.IsPhysical, true); + //} + + SceneObjectGroup objectGroup = new SceneObjectGroup(m_scene, m_regionHandle, linkPart); + + m_scene.AddEntity(objectGroup); + + ScheduleGroupForFullUpdate(); + } + else + { + m_log.InfoFormat("[SCENE]: " + + "DelinkFromGroup(): Child prim local id {0} not found in object with root prim id {1}", + partID, LocalId); + } + } + + private void DetachFromBackup(SceneObjectGroup objectGroup) + { + m_scene.EventManager.OnBackup -= objectGroup.ProcessBackup; + } + + private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation) + { + part.SetParent(this); + part.ParentID = m_rootPart.LocalID; + part.LinkNum = m_parts.Count; + m_parts.Add(part.UUID, part); + + Vector3 axiomOldPos = new Vector3(part.OffsetPosition.X, part.OffsetPosition.Y, part.OffsetPosition.Z); + axiomOldPos = oldGroupRotation*axiomOldPos; + axiomOldPos += oldGroupPosition; + LLVector3 oldAbsolutePosition = new LLVector3(axiomOldPos.x, axiomOldPos.y, axiomOldPos.z); + part.OffsetPosition = oldAbsolutePosition - AbsolutePosition; + + Quaternion axiomRootRotation = + new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y, + m_rootPart.RotationOffset.Z); + + Vector3 axiomPos = new Vector3(part.OffsetPosition.X, part.OffsetPosition.Y, part.OffsetPosition.Z); + axiomPos = axiomRootRotation.Inverse()*axiomPos; + part.OffsetPosition = new LLVector3(axiomPos.x, axiomPos.y, axiomPos.z); + + Quaternion axiomPartRotation = + new Quaternion(part.RotationOffset.W, part.RotationOffset.X, part.RotationOffset.Y, + part.RotationOffset.Z); + + axiomPartRotation = oldGroupRotation*axiomPartRotation; + axiomPartRotation = axiomRootRotation.Inverse()*axiomPartRotation; + part.RotationOffset = + new LLQuaternion(axiomPartRotation.x, axiomPartRotation.y, axiomPartRotation.z, axiomPartRotation.w); + } + + /// + /// If object is physical, apply force to move it around + /// If object is not physical, just put it at the resulting location + /// + /// Always seems to be 0,0,0, so ignoring + /// New position. We do the math here to turn it into a force + /// + public void GrabMovement(LLVector3 offset, LLVector3 pos, IClientAPI remoteClient) + { + + if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) + { + + if (m_rootPart.PhysActor != null) + { + if (m_rootPart.PhysActor.IsPhysical) + { + LLVector3 llmoveforce = pos - AbsolutePosition; + PhysicsVector grabforce = new PhysicsVector(llmoveforce.X, llmoveforce.Y, llmoveforce.Z); + grabforce = (grabforce / 10) * m_rootPart.PhysActor.Mass; + m_rootPart.PhysActor.AddForce(grabforce); + m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); + } + else + { + NonPhysicalGrabMovement(pos); + } + } + else + { + NonPhysicalGrabMovement(pos); + } + } + } + public void NonPhysicalGrabMovement(LLVector3 pos) + { + AbsolutePosition = pos; + m_rootPart.SendTerseUpdateToAllClients(); + + } + /// + /// + /// + /// + public void GetProperties(IClientAPI client) + { + ObjectPropertiesPacket proper = (ObjectPropertiesPacket) PacketPool.Instance.GetPacket(PacketType.ObjectProperties); + // TODO: don't create new blocks if recycling an old packet + + proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1]; + proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock(); + proper.ObjectData[0].ItemID = LLUUID.Zero; + proper.ObjectData[0].CreationDate = (ulong) m_rootPart.CreationDate; + proper.ObjectData[0].CreatorID = m_rootPart.CreatorID; + proper.ObjectData[0].FolderID = LLUUID.Zero; + proper.ObjectData[0].FromTaskID = LLUUID.Zero; + proper.ObjectData[0].GroupID = LLUUID.Zero; + proper.ObjectData[0].InventorySerial = (short) m_rootPart.InventorySerial; + proper.ObjectData[0].LastOwnerID = m_rootPart.LastOwnerID; + proper.ObjectData[0].ObjectID = UUID; + proper.ObjectData[0].OwnerID = m_rootPart.OwnerID; + proper.ObjectData[0].TouchName = Helpers.StringToField(m_rootPart.TouchName); + proper.ObjectData[0].TextureID = new byte[0]; + proper.ObjectData[0].SitName = Helpers.StringToField(m_rootPart.SitName); + proper.ObjectData[0].Name = Helpers.StringToField(m_rootPart.Name); + proper.ObjectData[0].Description = Helpers.StringToField(m_rootPart.Description); + proper.ObjectData[0].OwnerMask = m_rootPart.OwnerMask; + proper.ObjectData[0].NextOwnerMask = m_rootPart.NextOwnerMask; + proper.ObjectData[0].GroupMask = m_rootPart.GroupMask; + proper.ObjectData[0].EveryoneMask = m_rootPart.EveryoneMask; + proper.ObjectData[0].BaseMask = m_rootPart.BaseMask; + + client.OutPacket(proper, ThrottleOutPacketType.Task); + } + + /// + /// Set the name of a prim + /// + /// + /// + public void SetPartName(string name, uint localID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + part.Name = name; + } + } + + public void SetPartDescription(string des, uint localID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + part.Description = des; + } + } + + public void SetPartText(string text, uint localID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + part.Text = text; + } + } + + public void SetPartText(string text, LLUUID partID) + { + SceneObjectPart part = GetChildPart(partID); + if (part != null) + { + part.Text = text; + } + } + + public string GetPartName(uint localID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + return part.Name; + } + return String.Empty; + } + + public string GetPartDescription(uint localID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + return part.Description; + } + return String.Empty; + } + + /// + /// + /// + /// + /// + /// + /// + /// + public void UpdatePrimFlags(uint localID, ushort type, bool inUse, byte[] data) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + // If we have children + if (m_parts.Count > 1) + { + foreach (SceneObjectPart parts in m_parts.Values) + { + parts.UpdatePrimFlags(type, inUse, data); + } + } + else + { + part.UpdatePrimFlags(type, inUse, data); + } + } + } + + public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + part.UpdateExtraParam(type, inUse, data); + } + } + public SceneObjectPart[] GetParts() + { + int numParts = Children.Count; + SceneObjectPart[] partArray = new SceneObjectPart[numParts]; + Children.Values.CopyTo(partArray, 0); + return partArray; + } + + /// + /// + /// + /// + /// + public void UpdateTextureEntry(uint localID, byte[] textureEntry) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + part.UpdateTextureEntry(textureEntry); + } + } + + public void UpdatePermissions(LLUUID AgentID, byte field, uint localID, uint mask, byte addRemTF) + { + SceneObjectPart updatePart = GetChildPart(localID); + updatePart.UpdatePermissions(AgentID, field, localID, mask, addRemTF); + } + + #endregion + + #region Shape + + /// + /// + /// + /// + public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock, uint localID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + part.UpdateShape(shapeBlock); + + if (part.PhysActor != null) + m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); + } + + } + + #endregion + + #region Resize + + /// + /// + /// + /// + /// + public void Resize(LLVector3 scale, uint localID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + part.Resize(scale); + if (part.PhysActor != null) + { + part.PhysActor.Size = + new PhysicsVector(scale.X, scale.Y, scale.Z); + m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); + } + if (part.UUID != m_rootPart.UUID) + ScheduleGroupForFullUpdate(); + + //if (part.UUID == m_rootPart.UUID) + //{ + //if (m_rootPart.PhysActor != null) + //{ + //m_rootPart.PhysActor.Size = + //new PhysicsVector(m_rootPart.Scale.X, m_rootPart.Scale.Y, m_rootPart.Scale.Z); + //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); + //} + //} + } + } + + #endregion + + #region Position + + /// + /// + /// + /// + public void UpdateGroupPosition(LLVector3 pos) + { + if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) + { + AbsolutePosition = pos; + } + //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(); + } + + /// + /// + /// + /// + /// + public void UpdateSinglePosition(LLVector3 pos, uint localID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + if (part.UUID == m_rootPart.UUID) + { + UpdateRootPosition(pos); + } + else + { + part.UpdateOffSet(pos); + } + } + } + + /// + /// + /// + /// + private void UpdateRootPosition(LLVector3 pos) + { + LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z); + LLVector3 oldPos = + new LLVector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, + AbsolutePosition.Y + m_rootPart.OffsetPosition.Y, + AbsolutePosition.Z + m_rootPart.OffsetPosition.Z); + LLVector3 diff = oldPos - newPos; + Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z); + Quaternion partRotation = + new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y, + m_rootPart.RotationOffset.Z); + axDiff = partRotation.Inverse()*axDiff; + diff.X = axDiff.x; + diff.Y = axDiff.y; + diff.Z = axDiff.z; + + foreach (SceneObjectPart obPart in m_parts.Values) + { + if (obPart.UUID != m_rootPart.UUID) + { + obPart.OffsetPosition = obPart.OffsetPosition + diff; + } + } + AbsolutePosition = newPos; + ScheduleGroupForTerseUpdate(); + } + + public void OffsetForNewRegion(LLVector3 offset) + { + m_rootPart.GroupPosition = offset; + } + + #endregion + + #region Rotation + + /// + /// + /// + /// + public void UpdateGroupRotation(LLQuaternion rot) + { + m_rootPart.UpdateRotation(rot); + if (m_rootPart.PhysActor != null) + { + m_rootPart.PhysActor.Orientation = + new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y, + m_rootPart.RotationOffset.Z); + m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); + } + ScheduleGroupForTerseUpdate(); + } + + /// + /// + /// + /// + /// + public void UpdateGroupRotation(LLVector3 pos, LLQuaternion rot) + { + m_rootPart.UpdateRotation(rot); + if (m_rootPart.PhysActor != null) + { + m_rootPart.PhysActor.Orientation = + new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y, + m_rootPart.RotationOffset.Z); + m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); + } + AbsolutePosition = pos; + ScheduleGroupForTerseUpdate(); + } + + /// + /// + /// + /// + /// + public void UpdateSingleRotation(LLQuaternion rot, uint localID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + if (part.UUID == m_rootPart.UUID) + { + UpdateRootRotation(rot); + } + else + { + part.UpdateRotation(rot); + } + } + } + + /// + /// + /// + /// + private void UpdateRootRotation(LLQuaternion rot) + { + Quaternion axRot = new Quaternion(rot.W, rot.X, rot.Y, rot.Z); + Quaternion oldParentRot = + new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y, + m_rootPart.RotationOffset.Z); + + m_rootPart.UpdateRotation(rot); + if (m_rootPart.PhysActor != null) + { + m_rootPart.PhysActor.Orientation = + new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y, + m_rootPart.RotationOffset.Z); + m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); + } + + foreach (SceneObjectPart prim in m_parts.Values) + { + if (prim.UUID != m_rootPart.UUID) + { + Vector3 axPos = new Vector3(prim.OffsetPosition.X, prim.OffsetPosition.Y, prim.OffsetPosition.Z); + axPos = oldParentRot*axPos; + axPos = axRot.Inverse()*axPos; + prim.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z); + Quaternion primsRot = + new Quaternion(prim.RotationOffset.W, prim.RotationOffset.X, prim.RotationOffset.Y, + prim.RotationOffset.Z); + Quaternion newRot = oldParentRot*primsRot; + newRot = axRot.Inverse()*newRot; + prim.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w); + prim.ScheduleTerseUpdate(); + } + } + m_rootPart.ScheduleTerseUpdate(); + } + + #endregion + + /// + /// + /// + /// + private void SetPartAsRoot(SceneObjectPart part) + { + m_rootPart = part; + } + + /// + /// + /// + /// + private void SetPartAsNonRoot(SceneObjectPart part) + { + part.ParentID = m_rootPart.LocalID; + } + + /// + /// + /// + /// + public List GetScenePresences() + { + return m_scene.GetScenePresences(); + } + + #region Events + + /// + /// + /// + public void TriggerTainted() + { + if (OnPrimCountTainted != null) + { + OnPrimCountTainted(); + } + } + + /// + /// Processes backup + /// + /// + public void ProcessBackup(IRegionDataStore datastore) + { + if (HasGroupChanged) + { + datastore.StoreObject(this, m_scene.RegionInfo.RegionID); + HasGroupChanged = false; + } + + ForEachPart(delegate(SceneObjectPart part) { part.ProcessInventoryBackup(datastore); }); + } + + #endregion + + #region Client Updating + + public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientFlags) + { + lock (m_parts) + { + foreach (SceneObjectPart part in m_parts.Values) + { + SendPartFullUpdate(remoteClient, part, clientFlags); + } + } + } + + /// + /// + /// + /// + /// + internal void SendPartFullUpdate(IClientAPI remoteClient, SceneObjectPart part, uint clientFlags) + { + if (m_rootPart.UUID == part.UUID) + { + part.SendFullUpdateToClient(remoteClient, AbsolutePosition, clientFlags); + } + else + { + part.SendFullUpdateToClient(remoteClient, clientFlags); + } + } + + /// + /// + /// + /// + /// + internal void SendPartTerseUpdate(IClientAPI remoteClient, SceneObjectPart part) + { + if (m_rootPart.UUID == part.UUID) + { + part.SendTerseUpdateToClient(remoteClient, AbsolutePosition); + } + else + { + part.SendTerseUpdateToClient(remoteClient); + } + } + + #endregion + + public override void UpdateMovement() + { + foreach (SceneObjectPart part in m_parts.Values) + { + part.UpdateMovement(); + } + } + public float GetTimeDilation() + { + return m_scene.TimeDilation; + } + /// + /// Added as a way for the storage provider to reset the scene, + /// most likely a better way to do this sort of thing but for now... + /// + /// + public void SetScene(Scene scene) + { + m_scene = scene; + AttachToBackup(); + } + + /// + /// + /// + /// + public void AddPart(SceneObjectPart part) + { + part.SetParent(this); + part.LinkNum = m_parts.Count; + m_parts.Add(part.UUID, part); + } + + /// + /// + /// + public void UpdateParentIDs() + { + foreach (SceneObjectPart part in m_parts.Values) + { + if (part.UUID != m_rootPart.UUID) + { + part.ParentID = m_rootPart.LocalID; + } + } + } + + public void RegenerateFullIDs() + { + foreach (SceneObjectPart part in m_parts.Values) + { + part.UUID = LLUUID.Random(); + } + } + + public void ResetChildPrimPhysicsPositions() + { + AbsolutePosition = AbsolutePosition; + HasGroupChanged = false; + } + + public LLUUID GetPartsFullID(uint localID) + { + SceneObjectPart part = GetChildPart(localID); + if (part != null) + { + return part.UUID; + } + return null; + } + + public void UpdateText(string text) + { + m_rootPart.Text = text; + m_rootPart.ScheduleTerseUpdate(); + } + + public void ObjectGrabHandler(uint localId, LLVector3 offsetPos, IClientAPI remoteClient) + { + if (m_rootPart.LocalID == localId) + { + OnGrabGroup(offsetPos, remoteClient); + } + else + { + SceneObjectPart part = GetChildPart(localId); + OnGrabPart(part, offsetPos, remoteClient); + } + } + + public virtual void OnGrabPart(SceneObjectPart part, LLVector3 offsetPos, IClientAPI remoteClient) + { + part.OnGrab(offsetPos, remoteClient); + } + + public virtual void OnGrabGroup(LLVector3 offsetPos, IClientAPI remoteClient) + { + m_scene.EventManager.TriggerGroupGrab(UUID, offsetPos, remoteClient.AgentId); + } + + public void DeleteGroup() + { + DetachFromBackup(this); + foreach (SceneObjectPart part in m_parts.Values) + { + List avatars = GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) + { + if (avatars[i].ParentID == LocalId) + { + avatars[i].StandUp(); + } + + avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalID); + } + } + } + + public void DeleteParts() + { + m_rootPart = null; + m_parts.Clear(); + } + + public void AddScriptLPS(int count) + { + InnerScene d = m_scene.m_innerScene; + d.AddToScriptLPS(count); + } + + public void AddActiveScriptCount(int count) + { + InnerScene d = m_scene.m_innerScene; + d.AddActiveScripts(count); + } + + public override void SetText(string text, Vector3 color, double alpha) + { + Color = Color.FromArgb(0xff - (int) (alpha*0xff), + (int) (color.x*0xff), + (int) (color.y*0xff), + (int) (color.z*0xff)); + Text = text; + } + + public void ApplyPhysics(bool m_physicalPrim) + { + if (m_parts.Count > 1) + { + lock (m_parts) + { + foreach (SceneObjectPart part in m_parts.Values) + { + part.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim); + + // Hack to get the physics scene geometries in the right spot + ResetChildPrimPhysicsPositions(); + + } + } + } + else + { + m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim); + } + } + + public void SetOwnerId(LLUUID userId) + { + ForEachPart(delegate(SceneObjectPart part) + { part.OwnerID = userId; }); + } + + public void ForEachPart(Action whatToDo) + { + lock (m_parts) + { + foreach (SceneObjectPart part in m_parts.Values) + { + whatToDo(part); + } + } + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/SceneObjectPart.Inventory.cs b/trunk/OpenSim/Region/Environment/Scenes/SceneObjectPart.Inventory.cs new file mode 100644 index 0000000000..a27432d091 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/SceneObjectPart.Inventory.cs @@ -0,0 +1,510 @@ +/* +* 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; +using System.Collections.Generic; +using System.Xml.Serialization; + +using libsecondlife; + +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes.Scripting; + +namespace OpenSim.Region.Environment.Scenes +{ + public partial class SceneObjectPart : IScriptHost + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private string m_inventoryFileName = String.Empty; + + /// + /// The inventory folder for this prim + /// + private LLUUID m_folderID = LLUUID.Zero; + + /// + /// Exposing this is not particularly good, but it's one of the least evils at the moment to see + /// folder id from prim inventory item data, since it's not (yet) actually stored with the prim. + /// + public LLUUID FolderID + { + get { return m_folderID; } + set { m_folderID = value; } + } + + /// + /// Serial count for inventory file , used to tell if inventory has changed + /// no need for this to be part of Database backup + /// + protected uint m_inventorySerial = 0; + + public uint InventorySerial + { + get { return m_inventorySerial; } + set { m_inventorySerial = value; } + } + + /// + /// Holds in memory prim inventory + /// + protected TaskInventoryDictionary m_taskInventory = new TaskInventoryDictionary(); + + public TaskInventoryDictionary TaskInventory + { + get { return m_taskInventory; } + set { m_taskInventory = value; } + } + + /// + /// Tracks whether inventory has changed since the last persistent backup + /// + private bool HasInventoryChanged; + + /// + /// Reset LLUUIDs for all the items in the prim's inventory. This involves either generating + /// new ones or setting existing UUIDs to the correct parent UUIDs + /// + /// + /// + public void StartScript(TaskInventoryItem item) + { +// m_log.InfoFormat( +// "[PRIMINVENTORY]: " + +// "Starting script {0}, {1} in prim {2}, {3}", +// item.Name, item.ItemID, Name, UUID); + AddFlag(LLObject.ObjectFlags.Scripted); + + if (!((m_parentGroup.Scene.RegionInfo.EstateSettings.regionFlags & Simulator.RegionFlags.SkipScripts) == Simulator.RegionFlags.SkipScripts)) + { + AssetBase rezAsset = m_parentGroup.Scene.AssetCache.GetAsset(item.AssetID, false); + + if (rezAsset != null) + { + + string script = Helpers.FieldToUTF8String(rezAsset.Data); + m_parentGroup.Scene.EventManager.TriggerRezScript(LocalID, item.ItemID, script); + m_parentGroup.AddActiveScriptCount(1); + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Couldn't start script {0}, {1} since asset ID {2} could not be found", + item.Name, item.ItemID, item.AssetID); + } + } + ScheduleFullUpdate(); + } + + /// + /// Start a script which is in this prim's inventory. + /// + /// + /// A + /// + public void StartScript(LLUUID itemId) + { + lock (m_taskInventory) + { + if (m_taskInventory.ContainsKey(itemId)) + { + StartScript(m_taskInventory[itemId]); + + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}", + itemId, Name, UUID); + } + } + } + + /// + /// Stop a script which is in this prim's inventory. + /// + /// + public void StopScript(LLUUID itemId) + { + if (m_taskInventory.ContainsKey(itemId)) + { + m_parentGroup.Scene.EventManager.TriggerRemoveScript(LocalID, itemId); + m_parentGroup.AddActiveScriptCount(-1); + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2}", + itemId, Name, UUID); + } + } + + /// + /// Add an item to this prim's inventory. + /// + /// + public void AddInventoryItem(TaskInventoryItem item) + { + item.ParentID = m_folderID; + item.CreationDate = 1000; + item.ParentPartID = UUID; + + lock (m_taskInventory) + { + m_taskInventory.Add(item.ItemID, item); + TriggerScriptChangedEvent(Changed.INVENTORY); + } + + m_inventorySerial++; + HasInventoryChanged = true; + } + + /// + /// Restore a whole collection of items to the prim's inventory at once. + /// We assume that the items already have all their fields correctly filled out. + /// The items are not flagged for persistence to the database, since they are being restored + /// from persistence rather than being newly added. + /// + /// + public void RestoreInventoryItems(ICollection items) + { + lock (m_taskInventory) + { + foreach (TaskInventoryItem item in items) + { + m_taskInventory.Add(item.ItemID, item); + TriggerScriptChangedEvent(Changed.INVENTORY); + } + } + + m_inventorySerial++; + } + + /// + /// Returns an existing inventory item. Returns the original, so any changes will be live. + /// + /// + /// null if the item does not exist + public TaskInventoryItem GetInventoryItem(LLUUID itemID) + { + lock (m_taskInventory) + { + if (m_taskInventory.ContainsKey(itemID)) + { + return m_taskInventory[itemID]; + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory", + itemID, Name, UUID); + } + } + + return null; + } + + /// + /// Update an existing inventory item. + /// + /// The updated item. An item with the same id must already exist + /// in this prim's inventory. + /// false if the item did not exist, true if the update occurred succesfully + public bool UpdateInventoryItem(TaskInventoryItem item) + { + lock (m_taskInventory) + { + if (m_taskInventory.ContainsKey(item.ItemID)) + { + m_taskInventory[item.ItemID] = item; + m_inventorySerial++; + TriggerScriptChangedEvent(Changed.INVENTORY); + + HasInventoryChanged = true; + + return true; + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory", + item.ItemID, Name, UUID); + } + } + + return false; + } + + public void AddScriptLPS(int count) + { + m_parentGroup.AddScriptLPS(count); + } + + /// + /// Remove an item from this prim's inventory + /// + /// + /// Numeric asset type of the item removed. Returns -1 if the item did not exist + /// in this prim's inventory. + public int RemoveInventoryItem(LLUUID itemID) + { + lock (m_taskInventory) + { + if (m_taskInventory.ContainsKey(itemID)) + { + int type = m_taskInventory[itemID].InvType; + m_taskInventory.Remove(itemID); + m_inventorySerial++; + TriggerScriptChangedEvent(Changed.INVENTORY); + + HasInventoryChanged = true; + + int scriptcount = 0; + lock (m_taskInventory) + { + foreach (TaskInventoryItem item in m_taskInventory.Values) + { + if (item.Type == 10) + { + scriptcount++; + } + } + + } + if (scriptcount <= 0) + { + RemFlag(LLObject.ObjectFlags.Scripted); + ScheduleFullUpdate(); + } + ScheduleFullUpdate(); + + return type; + } + else + { + m_log.ErrorFormat( + "[PRIMINVENTORY]: " + + "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory", + itemID, Name, UUID); + } + } + + return -1; + } + + /// + /// + /// + /// + /// + public bool GetInventoryFileName(IClientAPI client, uint localID) + { + if (m_inventorySerial > 0) + { + client.SendTaskInventory(m_uuid, (short) m_inventorySerial, + Helpers.StringToField(m_inventoryFileName)); + return true; + } + else + { + client.SendTaskInventory(m_uuid, 0, new byte[0]); + return false; + } + } + + public void RequestInventoryFile(IXfer xferManager) + { + byte[] fileData = new byte[0]; + InventoryStringBuilder invString = new InventoryStringBuilder(m_folderID, UUID); + + lock (m_taskInventory) + { + foreach (TaskInventoryItem item in m_taskInventory.Values) + { + invString.AddItemStart(); + invString.AddNameValueLine("item_id", item.ItemID.ToString()); + invString.AddNameValueLine("parent_id", item.ParentID.ToString()); + + invString.AddPermissionsStart(); + invString.AddNameValueLine("base_mask", "0x7FFFFFFF"); + invString.AddNameValueLine("owner_mask", "0x7FFFFFFF"); + invString.AddNameValueLine("group_mask", "0x7FFFFFFF"); + invString.AddNameValueLine("everyone_mask", "0x7FFFFFFF"); + invString.AddNameValueLine("next_owner_mask", "0x7FFFFFFF"); + invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); + invString.AddNameValueLine("owner_id", item.OwnerID.ToString()); + invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); + invString.AddNameValueLine("group_id", item.GroupID.ToString()); + invString.AddSectionEnd(); + + invString.AddNameValueLine("asset_id", item.AssetID.ToString()); + invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); + invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); + invString.AddNameValueLine("flags", "0x00"); + invString.AddNameValueLine("name", item.Name + "|"); + invString.AddNameValueLine("desc", item.Description + "|"); + invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); + invString.AddSectionEnd(); + } + } + + fileData = Helpers.StringToField(invString.BuildString); + +// m_log.InfoFormat( +// "[PRIMINVENTORY]: RequestInventoryFile fileData: {0}", Helpers.FieldToUTF8String(fileData)); + + if (fileData.Length > 2) + { + xferManager.AddNewFile(m_inventoryFileName, fileData); + } + } + + /// + /// Process inventory backup + /// + /// + public void ProcessInventoryBackup(IRegionDataStore datastore) + { + if (HasInventoryChanged) + { + lock (TaskInventory) + { + datastore.StorePrimInventory(UUID, TaskInventory.Values); + } + + HasInventoryChanged = false; + } + } + + public class InventoryStringBuilder + { + public string BuildString = String.Empty; + + public InventoryStringBuilder(LLUUID folderID, LLUUID parentID) + { + BuildString += "\tinv_object\t0\n\t{\n"; + AddNameValueLine("obj_id", folderID.ToString()); + AddNameValueLine("parent_id", parentID.ToString()); + AddNameValueLine("type", "category"); + AddNameValueLine("name", "Contents"); + AddSectionEnd(); + } + + public void AddItemStart() + { + BuildString += "\tinv_item\t0\n"; + BuildString += "\t{\n"; + } + + public void AddPermissionsStart() + { + BuildString += "\tpermissions 0\n"; + BuildString += "\t{\n"; + } + + public void AddSectionEnd() + { + BuildString += "\t}\n"; + } + + public void AddLine(string addLine) + { + BuildString += addLine; + } + + public void AddNameValueLine(string name, string value) + { + BuildString += "\t\t"; + BuildString += name + "\t"; + BuildString += value + "\n"; + } + + public void Close() + { + } + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/trunk/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs new file mode 100644 index 0000000000..00cabf81b0 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs @@ -0,0 +1,1850 @@ +/* +* 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; +using System.Collections.Generic; +using System.Drawing; +using System.Xml; +using System.Xml.Serialization; +using Axiom.Math; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes.Scripting; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Environment.Scenes +{ + // I don't really know where to put this except here. + // Can't access the OpenSim.Region.ScriptEngine.Common.LSL_BaseClass.Changed constants + [Flags] + public enum ExtraParamType + { + Something1 = 1, + Something2 = 2, + Something3 = 4, + Something4 = 8, + Flexible = 16, + Light = 32, + Sculpt = 48, + Something5 = 64, + Something6 = 128 + } + [Flags] + public enum Changed : uint + { + INVENTORY = 1, + COLOR = 2, + SHAPE = 4, + SCALE = 8, + TEXTURE = 16, + LINK = 32, + ALLOWED_DROP = 64, + OWNER = 128 + } + [Flags] + public enum TextureAnimFlags : byte + { + NONE = 0x00, + ANIM_ON = 0x01, + LOOP = 0x02, + REVERSE = 0x04, + PING_PONG = 0x08, + SMOOTH = 0x10, + ROTATE = 0x20, + SCALE = 0x40 + } + + public partial class SceneObjectPart : IScriptHost + { + + [XmlIgnore] public PhysicsActor PhysActor = null; + + public LLUUID LastOwnerID; + public LLUUID OwnerID; + public LLUUID GroupID; + public int OwnershipCost; + public byte ObjectSaleType; + public int SalePrice; + public uint Category; + + + public Int32 CreationDate; + public uint ParentID = 0; + + private PhysicsVector m_lastRotationalVelocity = PhysicsVector.Zero; + private Vector3 m_sitTargetPosition = new Vector3(0, 0, 0); + private Quaternion m_sitTargetOrientation = new Quaternion(0, 0, 0, 1); + private LLUUID m_sitTargetAvatar = LLUUID.Zero; + + #region Permissions + + public uint BaseMask = (uint)PermissionMask.All; + public uint OwnerMask = (uint)PermissionMask.All; + public uint GroupMask = (uint)PermissionMask.None; + public uint EveryoneMask = (uint)PermissionMask.None; + public uint NextOwnerMask = (uint)PermissionMask.All; + + public LLObject.ObjectFlags Flags = LLObject.ObjectFlags.None; + + public uint ObjectFlags + { + get { return (uint)Flags; } + set { Flags = (LLObject.ObjectFlags)value; } + } + + #endregion + + protected byte[] m_particleSystem = new byte[0]; + + [XmlIgnore] public uint TimeStampFull = 0; + [XmlIgnore] public uint TimeStampTerse = 0; + [XmlIgnore] public uint TimeStampLastActivity = 0; // Will be used for AutoReturn + + /// + /// Only used internally to schedule client updates + /// + private byte m_updateFlag; + + #region Properties + + public LLUUID CreatorID; + + public LLUUID ObjectCreator + { + get { return CreatorID; } + } + + protected LLUUID m_uuid; + + public LLUUID UUID + { + get { return m_uuid; } + set { m_uuid = value; } + } + + protected uint m_localID; + + public uint LocalID + { + get { return m_localID; } + set { m_localID = value; } + } + + protected string m_name; + + public virtual string Name + { + get { return m_name; } + set { m_name = value; } + } + + + + protected LLObject.MaterialType m_material = 0; + + public byte Material + { + get { return (byte) m_material; } + set { m_material = (LLObject.MaterialType) value; } + } + + protected ulong m_regionHandle; + + public ulong RegionHandle + { + get { return m_regionHandle; } + set { m_regionHandle = value; } + } + + //unkown if this will be kept, added as a way of removing the group position from the group class + protected LLVector3 m_groupPosition; + + /// + /// Method for a prim to get it's world position from the group. + /// Remember, the Group Position simply gives the position of the group itself + /// + /// A Linked Child Prim objects position in world + public LLVector3 GetWorldPosition() + { + + Quaternion parentRot = new Quaternion( + ParentGroup.RootPart.RotationOffset.W, + ParentGroup.RootPart.RotationOffset.X, + ParentGroup.RootPart.RotationOffset.Y, + ParentGroup.RootPart.RotationOffset.Z); + + Vector3 axPos + = new Vector3( + OffsetPosition.X, + OffsetPosition.Y, + OffsetPosition.Z); + + axPos = parentRot * axPos; + LLVector3 translationOffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z); + return GroupPosition + translationOffsetPosition; + + //return (new LLVector3(axiomPos.x, axiomPos.y, axiomPos.z) + AbsolutePosition); + } + + /// + /// Gets the rotation of this prim offset by the group rotation + /// + /// + public LLQuaternion GetWorldRotation() + { + + Quaternion newRot; + + if (this.LinkNum == 0) + { + newRot = new Quaternion(RotationOffset.W,RotationOffset.X,RotationOffset.Y,RotationOffset.Z); + + } + else + { + Quaternion parentRot = new Quaternion( + ParentGroup.RootPart.RotationOffset.W, + ParentGroup.RootPart.RotationOffset.X, + ParentGroup.RootPart.RotationOffset.Y, + ParentGroup.RootPart.RotationOffset.Z); + + Quaternion oldRot + = new Quaternion( + RotationOffset.W, + RotationOffset.X, + RotationOffset.Y, + RotationOffset.Z); + + newRot = parentRot * oldRot; + } + return new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w); + + //return new LLQuaternion(axiomPartRotation.x, axiomPartRotation.y, axiomPartRotation.z, axiomPartRotation.w); + + } + + public LLVector3 GroupPosition + { + get + { + // If this is a linkset, we don't want the physics engine mucking up our group position here. + if (PhysActor != null && ParentID == 0) + { + m_groupPosition.X = PhysActor.Position.X; + m_groupPosition.Y = PhysActor.Position.Y; + m_groupPosition.Z = PhysActor.Position.Z; + } + return m_groupPosition; + } + set + { + m_groupPosition = value; + + if (PhysActor != null) + { + try + { + + // Root prim actually goes at Position + if (ParentID == 0) + { + PhysActor.Position = new PhysicsVector(value.X, value.Y, value.Z); + + } + else + { + + // To move the child prim in respect to the group position and rotation we have to calculate + + LLVector3 resultingposition = GetWorldPosition(); + PhysActor.Position = new PhysicsVector(resultingposition.X, resultingposition.Y, resultingposition.Z); + LLQuaternion resultingrot = GetWorldRotation(); + PhysActor.Orientation = new Quaternion(resultingrot.W, resultingrot.X, resultingrot.Y, resultingrot.Z); + } + + // Tell the physics engines that this prim changed. + m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + } + + } + } + + private byte[] m_TextureAnimation; + + protected LLVector3 m_offsetPosition; + + public LLVector3 OffsetPosition + { + get { return m_offsetPosition; } + set { m_offsetPosition = value; + try + { + // Hack to get the child prim to update world positions in the physics engine + ParentGroup.ResetChildPrimPhysicsPositions(); + + } + catch (System.NullReferenceException) + { + // Ignore, and skip over. + } + //m_log.Info("[PART]: OFFSET:" + m_offsetPosition.ToString()); + } + } + + public LLVector3 AbsolutePosition + { + get { return m_offsetPosition + m_groupPosition; } + } + + protected LLQuaternion m_rotationOffset; + + public LLQuaternion RotationOffset + { + get + { + // We don't want the physics engine mucking up the rotations in a linkset + if (PhysActor != null && ParentID == 0) + { + if (PhysActor.Orientation.x != 0 || PhysActor.Orientation.y != 0 + || PhysActor.Orientation.z != 0 || PhysActor.Orientation.w != 0) + { + m_rotationOffset.X = PhysActor.Orientation.x; + m_rotationOffset.Y = PhysActor.Orientation.y; + m_rotationOffset.Z = PhysActor.Orientation.z; + m_rotationOffset.W = PhysActor.Orientation.w; + } + } + return m_rotationOffset; + } + set + { + m_rotationOffset = value; + + if (PhysActor != null) + { + try + { + // Root prim gets value directly + if (ParentID == 0) + { + PhysActor.Orientation = new Quaternion(value.W, value.X, value.Y, value.Z); + //m_log.Info("[PART]: RO1:" + PhysActor.Orientation.ToString()); + } + else + { + // Child prim we have to calculate it's world rotationwel + LLQuaternion resultingrotation = GetWorldRotation(); + PhysActor.Orientation = new Quaternion(resultingrotation.W, resultingrotation.X, resultingrotation.Y, resultingrotation.Z); + //m_log.Info("[PART]: RO2:" + PhysActor.Orientation.ToString()); + } + m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + //} + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + } + } + + protected LLVector3 m_velocity; + protected LLVector3 m_rotationalvelocity; + + /// + public LLVector3 Velocity + { + get + { + //if (PhysActor.Velocity.x != 0 || PhysActor.Velocity.y != 0 + //|| PhysActor.Velocity.z != 0) + //{ + if (PhysActor != null) + { + if (PhysActor.IsPhysical) + { + m_velocity.X = PhysActor.Velocity.X; + m_velocity.Y = PhysActor.Velocity.Y; + m_velocity.Z = PhysActor.Velocity.Z; + } + } + + return m_velocity; + } + set { + + m_velocity = value; + if (PhysActor != null) + { + if (PhysActor.IsPhysical) + { + PhysActor.Velocity = new PhysicsVector(value.X, value.Y, value.Z); + m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + } + } + + } + } + + public LLVector3 RotationalVelocity + { + get + { + //if (PhysActor.Velocity.x != 0 || PhysActor.Velocity.y != 0 + //|| PhysActor.Velocity.z != 0) + //{ + if (PhysActor != null) + { + if (PhysActor.IsPhysical) + { + m_rotationalvelocity.FromBytes(PhysActor.RotationalVelocity.GetBytes(),0); + } + } + + return m_rotationalvelocity; + } + set { m_rotationalvelocity = value; } + } + + + protected LLVector3 m_angularVelocity; + + /// + public LLVector3 AngularVelocity + { + get { return m_angularVelocity; } + set { m_angularVelocity = value; } + } + + protected LLVector3 m_acceleration; + + /// + public LLVector3 Acceleration + { + get { return m_acceleration; } + set { m_acceleration = value; } + } + + private string m_description = String.Empty; + + public string Description + { + get { return m_description; } + set { m_description = value; } + } + + private Color m_color = Color.Black; + + public Color Color + { + get { return m_color; } + set + { + m_color = value; + TriggerScriptChangedEvent(Changed.COLOR); + + /* ScheduleFullUpdate() need not be called b/c after + * setting the color, the text will be set, so then + * ScheduleFullUpdate() will be called. */ + //ScheduleFullUpdate(); + } + } + + private string m_text = String.Empty; + + public Vector3 SitTargetPosition + { + get { return m_sitTargetPosition; } + } + + public Quaternion SitTargetOrientation + { + get { return m_sitTargetOrientation; } + } + + public string Text + { + get { return m_text; } + set + { + m_text = value; + ScheduleFullUpdate(); + } + } + + private string m_sitName = String.Empty; + + public string SitName + { + get { return m_sitName; } + set { m_sitName = value; } + } + + private string m_touchName = String.Empty; + + public string TouchName + { + get { return m_touchName; } + set { m_touchName = value; } + } + + private int m_linkNum = 0; + + public int LinkNum + { + get { return m_linkNum; } + set + { + m_linkNum = value; + TriggerScriptChangedEvent(Changed.LINK); + + } + } + + private byte m_clickAction = 0; + + public byte ClickAction + { + get { return m_clickAction; } + set + { + m_clickAction = value; + ScheduleFullUpdate(); + } + } + + protected PrimitiveBaseShape m_shape; + + /// + /// hook to the physics scene to apply impulse + /// This is sent up to the group, which then finds the root prim + /// and applies the force on the root prim of the group + /// + /// Vector force + public void ApplyImpulse(LLVector3 impulsei) + { + PhysicsVector impulse = new PhysicsVector(impulsei.X, impulsei.Y, impulsei.Z); + if (m_parentGroup != null) + { + m_parentGroup.applyImpulse(impulse); + } + } + + public void TriggerScriptChangedEvent(Changed val) + { + if (m_parentGroup != null) + { + if (m_parentGroup.Scene != null) + m_parentGroup.Scene.TriggerObjectChanged(LocalID, (uint)val); + } + + } + + public PrimitiveBaseShape Shape + { + get { return m_shape; } + set + { + + m_shape = value; + TriggerScriptChangedEvent(Changed.SHAPE); + } + } + + public LLVector3 Scale + { + get { return m_shape.Scale; } + set + { + m_shape.Scale = value; + TriggerScriptChangedEvent(Changed.SCALE); + } + } + + public bool Stopped + { + get { + double threshold = 0.02; + return (Math.Abs(Velocity.X) < threshold && + Math.Abs(Velocity.Y) < threshold && + Math.Abs(Velocity.Z) < threshold && + Math.Abs(AngularVelocity.X) < threshold && + Math.Abs(AngularVelocity.Y) < threshold && + Math.Abs(AngularVelocity.Z) < threshold); + } + } + + #endregion + + public LLUUID ObjectOwner + { + get { return OwnerID; } + } + + // FIXME, TODO, ERROR: 'ParentGroup' can't be in here, move it out. + protected SceneObjectGroup m_parentGroup; + + public SceneObjectGroup ParentGroup + { + get { return m_parentGroup; } + } + + public byte UpdateFlag + { + get { return m_updateFlag; } + set { m_updateFlag = value; } + } + + #region Constructors + + /// + /// No arg constructor called by region restore db code + /// + public SceneObjectPart() + { + // It's not necessary to persist this + m_inventoryFileName = "taskinventory" + LLUUID.Random().ToString(); + m_TextureAnimation = new byte[0]; + } + + public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, LLUUID ownerID, uint localID, + PrimitiveBaseShape shape, LLVector3 groupPosition, LLVector3 offsetPosition) + : this(regionHandle, parent, ownerID, localID, shape, groupPosition, LLQuaternion.Identity, offsetPosition) + { + } + + /// + /// Create a completely new SceneObjectPart (prim) + /// + /// + /// + /// + /// + /// + /// + public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, LLUUID ownerID, uint localID, + PrimitiveBaseShape shape, LLVector3 groupPosition, LLQuaternion rotationOffset, + LLVector3 offsetPosition) + { + m_name = "Primitive"; + m_regionHandle = regionHandle; + m_parentGroup = parent; + + CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; + OwnerID = ownerID; + CreatorID = OwnerID; + LastOwnerID = LLUUID.Zero; + UUID = LLUUID.Random(); + LocalID = (uint) (localID); + Shape = shape; + // Todo: Add More Object Parameter from above! + OwnershipCost = 0; + ObjectSaleType = (byte) 0; + SalePrice = 0; + Category = (uint) 0; + LastOwnerID = CreatorID; + // End Todo: /// + GroupPosition = groupPosition; + OffsetPosition = offsetPosition; + RotationOffset = rotationOffset; + Velocity = new LLVector3(0, 0, 0); + m_rotationalvelocity = new LLVector3(0, 0, 0); + AngularVelocity = new LLVector3(0, 0, 0); + Acceleration = new LLVector3(0, 0, 0); + m_TextureAnimation = new byte[0]; + m_inventoryFileName = "taskinventory" + LLUUID.Random().ToString(); + m_folderID = LLUUID.Random(); + + Flags = 0; + Flags |= LLObject.ObjectFlags.Touch | + LLObject.ObjectFlags.AllowInventoryDrop | + LLObject.ObjectFlags.CreateSelected; + + + TrimPermissions(); + + ScheduleFullUpdate(); + } + + /// + /// Re/create a SceneObjectPart (prim) + /// currently not used, and maybe won't be + /// + /// + /// + /// + /// + /// + /// + public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, int creationDate, LLUUID ownerID, + LLUUID creatorID, LLUUID lastOwnerID, uint localID, PrimitiveBaseShape shape, + LLVector3 position, LLQuaternion rotation, uint flags) + { + m_regionHandle = regionHandle; + m_parentGroup = parent; + TimeStampTerse = (uint) Util.UnixTimeSinceEpoch(); + CreationDate = creationDate; + OwnerID = ownerID; + CreatorID = creatorID; + LastOwnerID = lastOwnerID; + UUID = LLUUID.Random(); + LocalID = (uint) (localID); + Shape = shape; + OwnershipCost = 0; + ObjectSaleType = (byte) 0; + SalePrice = 0; + Category = (uint) 0; + LastOwnerID = CreatorID; + OffsetPosition = position; + RotationOffset = rotation; + ObjectFlags = flags; + + // Since we don't store script state, this is only a 'temporary' objectflag now + // If the object is scripted, the script will get loaded and this will be set again + ObjectFlags &= ~(uint)LLObject.ObjectFlags.Scripted; + + TrimPermissions(); + // ApplyPhysics(); + + ScheduleFullUpdate(); + } + + #endregion + + /// + /// + /// + /// + /// + public static SceneObjectPart FromXml(XmlReader xmlReader) + { + XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart)); + SceneObjectPart newobject = (SceneObjectPart) serializer.Deserialize(xmlReader); + + return newobject; + } + + public void ApplyPhysics(uint rootObjectFlags, bool m_physicalPrim) + { + + bool isPhysical = (((rootObjectFlags & (uint) LLObject.ObjectFlags.Physics) != 0) && m_physicalPrim); + bool isPhantom = ((rootObjectFlags & (uint) LLObject.ObjectFlags.Phantom) != 0); + + // Added clarification.. since A rigid body is an object that you can kick around, etc. + bool RigidBody = isPhysical && !isPhantom; + + // The only time the physics scene shouldn't know about the prim is if it's phantom + if (!isPhantom) + { + PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( + Name, + Shape, + new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, + AbsolutePosition.Z), + new PhysicsVector(Scale.X, Scale.Y, Scale.Z), + new Quaternion(RotationOffset.W, RotationOffset.X, + RotationOffset.Y, RotationOffset.Z), RigidBody); + + + DoPhysicsPropertyUpdate(RigidBody, true); + } + } + + public void ApplyNextOwnerPermissions() + { + BaseMask = NextOwnerMask; + OwnerMask = NextOwnerMask; + + TriggerScriptChangedEvent(Changed.OWNER); + + } + + public void TrimPermissions() + { + + BaseMask &= (uint)PermissionMask.All; + OwnerMask &= (uint)PermissionMask.All; + GroupMask &= (uint)PermissionMask.All; + EveryoneMask &= (uint)PermissionMask.All; + NextOwnerMask &= (uint)PermissionMask.All; + + } + + /// + /// + /// + /// + public void ToXml(XmlWriter xmlWriter) + { + XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart)); + serializer.Serialize(xmlWriter, this); + } + + public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot) + { + // In this case we're using a sphere with a radius of the largest dimention of the prim + // TODO: Change to take shape into account + + + EntityIntersection returnresult = new EntityIntersection(); + Vector3 vAbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); + + Vector3 vScale = new Vector3(Scale.X, Scale.Y, Scale.Z); + Quaternion qRotation = + new Quaternion(RotationOffset.W, RotationOffset.X, RotationOffset.Y, RotationOffset.Z); + + + //Quaternion worldRotation = (qRotation*parentrot); + //Matrix3 worldRotM = worldRotation.ToRotationMatrix(); + + + Vector3 rOrigin = iray.Origin; + Vector3 rDirection = iray.Direction; + + + + //rDirection = rDirection.Normalize(); + // Buidling the first part of the Quadratic equation + Vector3 r2ndDirection = rDirection*rDirection; + float itestPart1 = r2ndDirection.x + r2ndDirection.y + r2ndDirection.z; + + // Buidling the second part of the Quadratic equation + Vector3 tmVal2 = rOrigin - vAbsolutePosition; + Vector3 r2Direction = rDirection*2.0f; + Vector3 tmVal3 = r2Direction*tmVal2; + + float itestPart2 = tmVal3.x + tmVal3.y + tmVal3.z; + + // Buidling the third part of the Quadratic equation + Vector3 tmVal4 = rOrigin*rOrigin; + Vector3 tmVal5 = vAbsolutePosition*vAbsolutePosition; + + Vector3 tmVal6 = vAbsolutePosition*rOrigin; + + + // Set Radius to the largest dimention of the prim + float radius = 0f; + if (vScale.x > radius) + radius = vScale.x; + if (vScale.y > radius) + radius = vScale.y; + if (vScale.z > radius) + radius = vScale.z; + + //radius = radius; + + float itestPart3 = tmVal4.x + tmVal4.y + tmVal4.z + tmVal5.x + tmVal5.y + tmVal5.z - + (2.0f*(tmVal6.x + tmVal6.y + tmVal6.z + (radius*radius))); + + // Yuk Quadradrics.. Solve first + float rootsqr = (itestPart2*itestPart2) - (4.0f*itestPart1*itestPart3); + if (rootsqr < 0.0f) + { + // No intersection + return returnresult; + } + float root = ((-itestPart2) - (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f); + + if (root < 0.0f) + { + // perform second quadratic root solution + root = ((-itestPart2) + (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f); + + // is there any intersection? + if (root < 0.0f) + { + // nope, no intersection + return returnresult; + } + } + + // We got an intersection. putting together an EntityIntersection object with the + // intersection information + Vector3 ipoint = + new Vector3(iray.Origin.x + (iray.Direction.x*root), iray.Origin.y + (iray.Direction.y*root), + iray.Origin.z + (iray.Direction.z*root)); + + returnresult.HitTF = true; + returnresult.ipoint = ipoint; + + // Normal is calculated by the difference and then normalizing the result + Vector3 normalpart = ipoint - vAbsolutePosition; + returnresult.normal = normalpart.Normalize(); + + // It's funny how the LLVector3 object has a Distance function, but the Axiom.Math object doesnt. + // I can write a function to do it.. but I like the fact that this one is Static. + + LLVector3 distanceConvert1 = new LLVector3(iray.Origin.x, iray.Origin.y, iray.Origin.z); + LLVector3 distanceConvert2 = new LLVector3(ipoint.x, ipoint.y, ipoint.z); + float distance = (float) Util.GetDistanceTo(distanceConvert1, distanceConvert2); + + returnresult.distance = distance; + + return returnresult; + } + + + /// + /// + /// + public void SetParent(SceneObjectGroup parent) + { + m_parentGroup = parent; + } + + public void SetSitTarget(Vector3 offset, Quaternion orientation) + { + m_sitTargetPosition = offset; + m_sitTargetOrientation = orientation; + } + + public LLVector3 GetSitTargetPositionLL() + { + return new LLVector3(m_sitTargetPosition.x, m_sitTargetPosition.y, m_sitTargetPosition.z); + } + + public LLQuaternion GetSitTargetOrientationLL() + { + return + new LLQuaternion(m_sitTargetOrientation.x, m_sitTargetOrientation.y, m_sitTargetOrientation.z, + m_sitTargetOrientation.w); + } + + // Utility function so the databases don't have to reference axiom.math + public void SetSitTargetLL(LLVector3 offset, LLQuaternion orientation) + { + if ( + !(offset.X == 0 && offset.Y == 0 && offset.Z == 0 && (orientation.W == 0 || orientation.W == 1) && + orientation.X == 0 && orientation.Y == 0 && orientation.Z == 0)) + { + m_sitTargetPosition = new Vector3(offset.X, offset.Y, offset.Z); + m_sitTargetOrientation = new Quaternion(orientation.W, orientation.X, orientation.Y, orientation.Z); + } + } + + public Vector3 GetSitTargetPosition() + { + return m_sitTargetPosition; + } + + public Quaternion GetSitTargetOrientation() + { + return m_sitTargetOrientation; + } + + public void SetAvatarOnSitTarget(LLUUID avatarID) + { + m_sitTargetAvatar = avatarID; + TriggerScriptChangedEvent(Changed.LINK); + } + + public LLUUID GetAvatarOnSitTarget() + { + return m_sitTargetAvatar; + } + + + public LLUUID GetRootPartUUID() + { + if (m_parentGroup != null) + { + return m_parentGroup.UUID; + } + return LLUUID.Zero; + } + + public static SceneObjectPart Create() + { + SceneObjectPart part = new SceneObjectPart(); + part.UUID = LLUUID.Random(); + + PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); + part.Shape = shape; + + part.Name = "Primitive"; + part.OwnerID = LLUUID.Random(); + + return part; + } + + #region Copying + + /// + /// Duplicates this part. + /// + /// + public SceneObjectPart Copy(uint localID, LLUUID AgentID, LLUUID GroupID, int linkNum) + { + SceneObjectPart dupe = (SceneObjectPart) MemberwiseClone(); + dupe.m_shape = m_shape.Copy(); + dupe.m_regionHandle = m_regionHandle; + dupe.UUID = LLUUID.Random(); + dupe.LocalID = localID; + dupe.OwnerID = AgentID; + dupe.GroupID = GroupID; + dupe.GroupPosition = new LLVector3(GroupPosition.X, GroupPosition.Y, GroupPosition.Z); + dupe.OffsetPosition = new LLVector3(OffsetPosition.X, OffsetPosition.Y, OffsetPosition.Z); + dupe.RotationOffset = + new LLQuaternion(RotationOffset.X, RotationOffset.Y, RotationOffset.Z, RotationOffset.W); + dupe.Velocity = new LLVector3(0, 0, 0); + dupe.Acceleration = new LLVector3(0, 0, 0); + dupe.AngularVelocity = new LLVector3(0, 0, 0); + dupe.ObjectFlags = ObjectFlags; + + dupe.OwnershipCost = OwnershipCost; + dupe.ObjectSaleType = ObjectSaleType; + dupe.SalePrice = SalePrice; + dupe.Category = Category; + + dupe.TaskInventory = (TaskInventoryDictionary)dupe.TaskInventory.Clone(); + + dupe.ResetIDs(linkNum); + + // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. + dupe.LastOwnerID = ObjectOwner; + + byte[] extraP = new byte[Shape.ExtraParams.Length]; + Array.Copy(Shape.ExtraParams, extraP, extraP.Length); + dupe.Shape.ExtraParams = extraP; + bool UsePhysics = ((dupe.ObjectFlags & (uint) LLObject.ObjectFlags.Physics) != 0); + dupe.DoPhysicsPropertyUpdate(UsePhysics, true); + + return dupe; + } + + #endregion + + /// + /// Reset LLUUIDs for this part. This involves generate this part's own LLUUID and + /// generating new LLUUIDs for all the items in the inventory. + /// + /// + /// + /// + public void ScheduleTerseUpdate() + { + if (m_updateFlag < 1) + { + if (m_parentGroup != null) + { + m_parentGroup.HasGroupChanged = true; + } + TimeStampTerse = (uint) Util.UnixTimeSinceEpoch(); + m_updateFlag = 1; + } + } + + /// + /// + /// + public void SendScheduledUpdates() + { + if (m_updateFlag == 1) //some change has been made so update the clients + { + AddTerseUpdateToAllAvatars(); + ClearUpdateSchedule(); + + // This causes the Scene to 'poll' physical objects every couple of frames + // bad, so it's been replaced by an event driven method. + //if ((ObjectFlags & (uint)LLObject.ObjectFlags.Physics) != 0) + //{ + // Only send the constant terse updates on physical objects! + //ScheduleTerseUpdate(); + //} + } + else + { + if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes + { + AddFullUpdateToAllAvatars(); + ClearUpdateSchedule(); + } + } + } + + #endregion + + #region Shape + + /// + /// + /// + /// + public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock) + { + m_shape.PathBegin = shapeBlock.PathBegin; + m_shape.PathEnd = shapeBlock.PathEnd; + m_shape.PathScaleX = shapeBlock.PathScaleX; + m_shape.PathScaleY = shapeBlock.PathScaleY; + m_shape.PathShearX = shapeBlock.PathShearX; + m_shape.PathShearY = shapeBlock.PathShearY; + m_shape.PathSkew = shapeBlock.PathSkew; + m_shape.ProfileBegin = shapeBlock.ProfileBegin; + m_shape.ProfileEnd = shapeBlock.ProfileEnd; + m_shape.PathCurve = shapeBlock.PathCurve; + m_shape.ProfileCurve = shapeBlock.ProfileCurve; + m_shape.ProfileHollow = shapeBlock.ProfileHollow; + m_shape.PathRadiusOffset = shapeBlock.PathRadiusOffset; + m_shape.PathRevolutions = shapeBlock.PathRevolutions; + m_shape.PathTaperX = shapeBlock.PathTaperX; + m_shape.PathTaperY = shapeBlock.PathTaperY; + m_shape.PathTwist = shapeBlock.PathTwist; + m_shape.PathTwistBegin = shapeBlock.PathTwistBegin; + if (PhysActor != null) + { + PhysActor.Shape = m_shape; + } + ScheduleFullUpdate(); + } + + #endregion + + #region ExtraParams + + public void UpdatePrimFlags(ushort type, bool inUse, byte[] data) + { + + + //m_log.Info("TSomething1:" + ((type & (ushort)ExtraParamType.Something1) == (ushort)ExtraParamType.Something1)); + //m_log.Info("TSomething2:" + ((type & (ushort)ExtraParamType.Something2) == (ushort)ExtraParamType.Something2)); + //m_log.Info("TSomething3:" + ((type & (ushort)ExtraParamType.Something3) == (ushort)ExtraParamType.Something3)); + //m_log.Info("TSomething4:" + ((type & (ushort)ExtraParamType.Something4) == (ushort)ExtraParamType.Something4)); + //m_log.Info("TSomething5:" + ((type & (ushort)ExtraParamType.Something5) == (ushort)ExtraParamType.Something5)); + //m_log.Info("TSomething6:" + ((type & (ushort)ExtraParamType.Something6) == (ushort)ExtraParamType.Something6)); + + bool usePhysics = false; + bool IsTemporary = false; + bool IsPhantom = false; + bool castsShadows = false; + bool wasUsingPhysics = ((ObjectFlags & (uint) LLObject.ObjectFlags.Physics) != 0); + //bool IsLocked = false; + int i = 0; + + + try + { + i += 46; + //IsLocked = (data[i++] != 0) ? true : false; + usePhysics = ((data[i++] != 0) && m_parentGroup.Scene.m_physicalPrim) ? true : false; + //System.Console.WriteLine("U" + packet.ToBytes().Length.ToString()); + IsTemporary = (data[i++] != 0) ? true : false; + IsPhantom = (data[i++] != 0) ? true : false; + castsShadows = (data[i++] != 0) ? true : false; + } + catch (Exception) + { + Console.WriteLine("Ignoring invalid Packet:"); + //Silently ignore it - TODO: FIXME Quick + } + + if (usePhysics) + { + AddFlag(LLObject.ObjectFlags.Physics); + if (!wasUsingPhysics) + { + DoPhysicsPropertyUpdate(usePhysics, false); + } + } + else + { + RemFlag(LLObject.ObjectFlags.Physics); + if (wasUsingPhysics) + { + DoPhysicsPropertyUpdate(usePhysics, false); + } + } + + + if (IsPhantom) + { + AddFlag(LLObject.ObjectFlags.Phantom); + if (PhysActor != null) + { + m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); + /// that's not wholesome. Had to make Scene public + PhysActor = null; + } + } + else + { + RemFlag(LLObject.ObjectFlags.Phantom); + if (PhysActor == null) + { + PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( + Name, + Shape, + new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, + AbsolutePosition.Z), + new PhysicsVector(Scale.X, Scale.Y, Scale.Z), + new Quaternion(RotationOffset.W, RotationOffset.X, + RotationOffset.Y, RotationOffset.Z), usePhysics); + DoPhysicsPropertyUpdate(usePhysics, true); + } + else + { + PhysActor.IsPhysical = usePhysics; + DoPhysicsPropertyUpdate(usePhysics, false); + } + } + + if (IsTemporary) + { + AddFlag(LLObject.ObjectFlags.TemporaryOnRez); + } + else + { + RemFlag(LLObject.ObjectFlags.TemporaryOnRez); + } + // System.Console.WriteLine("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); + ScheduleFullUpdate(); + } + + public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew) + { + if (PhysActor != null) + { + if (UsePhysics != PhysActor.IsPhysical || isNew) + { + if (PhysActor.IsPhysical) + { + if (!isNew) + ParentGroup.Scene.RemovePhysicalPrim(1); + + PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; + PhysActor.OnOutOfBounds -= PhysicsOutOfBounds; + } + + PhysActor.IsPhysical = UsePhysics; + // If we're not what we're supposed to be in the physics scene, recreate ourselves. + //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); + /// that's not wholesome. Had to make Scene public + //PhysActor = null; + + + if ((ObjectFlags & (uint) LLObject.ObjectFlags.Phantom) == 0) + { + //PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( + //Name, + //Shape, + //new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, + //AbsolutePosition.Z), + //new PhysicsVector(Scale.X, Scale.Y, Scale.Z), + //new Quaternion(RotationOffset.W, RotationOffset.X, + //RotationOffset.Y, RotationOffset.Z), UsePhysics); + if (UsePhysics) + { + ParentGroup.Scene.AddPhysicalPrim(1); + + PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; + PhysActor.OnOutOfBounds += PhysicsOutOfBounds; + } + } + } + m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + } + } + + public void UpdateExtraParam(ushort type, bool inUse, byte[] data) + { + m_shape.ExtraParams = new byte[data.Length + 7]; + int i = 0; + uint length = (uint) data.Length; + m_shape.ExtraParams[i++] = 1; + m_shape.ExtraParams[i++] = (byte) (type%256); + m_shape.ExtraParams[i++] = (byte) ((type >> 8)%256); + + m_shape.ExtraParams[i++] = (byte) (length%256); + m_shape.ExtraParams[i++] = (byte) ((length >> 8)%256); + m_shape.ExtraParams[i++] = (byte) ((length >> 16)%256); + m_shape.ExtraParams[i++] = (byte) ((length >> 24)%256); + Array.Copy(data, 0, m_shape.ExtraParams, i, data.Length); + + ScheduleFullUpdate(); + } + + #endregion + + #region Physics + + public float GetMass() + { + if (PhysActor != null) + { + return PhysActor.Mass; + } + else + { + return 0; + } + } + + public LLVector3 GetGeometricCenter() + { + if (PhysActor != null) + { + return new LLVector3(PhysActor.CenterOfMass.X, PhysActor.CenterOfMass.Y, PhysActor.CenterOfMass.Z); + } + else + { + return new LLVector3(0, 0, 0); + } + } + + #endregion + + #region Texture + + /// + /// + /// + /// + public void UpdateTextureEntry(byte[] textureEntry) + { + m_shape.TextureEntry = textureEntry; + TriggerScriptChangedEvent(Changed.TEXTURE); + ScheduleFullUpdate(); + } + + // Added to handle bug in libsecondlife's TextureEntry.ToBytes() + // not handling RGBA properly. Cycles through, and "fixes" the color + // info + public void UpdateTexture(LLObject.TextureEntry tex) + { + //LLColor tmpcolor; + //for (uint i = 0; i < 32; i++) + //{ + // if (tex.FaceTextures[i] != null) + // { + // tmpcolor = tex.GetFace((uint) i).RGBA; + // tmpcolor.A = tmpcolor.A*255; + // tmpcolor.R = tmpcolor.R*255; + // tmpcolor.G = tmpcolor.G*255; + // tmpcolor.B = tmpcolor.B*255; + // tex.FaceTextures[i].RGBA = tmpcolor; + // } + //} + //tmpcolor = tex.DefaultTexture.RGBA; + //tmpcolor.A = tmpcolor.A*255; + //tmpcolor.R = tmpcolor.R*255; + //tmpcolor.G = tmpcolor.G*255; + //tmpcolor.B = tmpcolor.B*255; + //tex.DefaultTexture.RGBA = tmpcolor; + UpdateTextureEntry(tex.ToBytes()); + } + + public byte ConvertScriptUintToByte(uint indata) + { + byte outdata = (byte)TextureAnimFlags.NONE; + if ((indata & 1) != 0) outdata |= (byte)TextureAnimFlags.ANIM_ON; + if ((indata & 2) != 0) outdata |= (byte)TextureAnimFlags.LOOP; + if ((indata & 4) != 0) outdata |= (byte)TextureAnimFlags.REVERSE; + if ((indata & 8) != 0) outdata |= (byte)TextureAnimFlags.PING_PONG; + if ((indata & 16) != 0) outdata |= (byte)TextureAnimFlags.SMOOTH; + if ((indata & 32) != 0) outdata |= (byte)TextureAnimFlags.ROTATE; + if ((indata & 64) != 0) outdata |= (byte)TextureAnimFlags.SCALE; + return outdata; + } + + public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim) + { + byte[] data = new byte[16]; + int pos = 0; + + // The flags don't like conversion from uint to byte, so we have to do + // it the crappy way. See the above function :( + + data[pos] = ConvertScriptUintToByte(pTexAnim.Flags); pos++; + data[pos] = (byte)pTexAnim.Face; pos++; + data[pos] = (byte)pTexAnim.SizeX; pos++; + data[pos] = (byte)pTexAnim.SizeX; pos++; + + Helpers.FloatToBytes(pTexAnim.Start).CopyTo(data, pos); + Helpers.FloatToBytes(pTexAnim.Length ).CopyTo(data, pos + 4); + Helpers.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8); + + m_TextureAnimation = data; + } + + #endregion + + #region ParticleSystem + + public void AddNewParticleSystem(Primitive.ParticleSystem pSystem) + { + m_particleSystem = pSystem.GetBytes(); + } + + #endregion + + #region Position + + /// + /// + /// + /// + public void UpdateOffSet(LLVector3 pos) + { + LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z); + OffsetPosition = newPos; + ScheduleTerseUpdate(); + } + + public void UpdateGroupPosition(LLVector3 pos) + { + LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z); + GroupPosition = newPos; + ScheduleTerseUpdate(); + } + + #endregion + + #region rotation + + public void UpdateRotation(LLQuaternion rot) + { + RotationOffset = new LLQuaternion(rot.X, rot.Y, rot.Z, rot.W); + ScheduleTerseUpdate(); + } + + #endregion + + #region Sound + public void PreloadSound(string sound) + { + LLUUID ownerID = OwnerID; + LLUUID objectID = UUID; + LLUUID soundID = LLUUID.Zero; + + if (!LLUUID.TryParse(sound, out soundID)) + { + //Trys to fetch sound id from prim's inventory. + //Prim's inventory doesn't support non script items yet + SceneObjectPart op = this; + foreach (KeyValuePair item in op.TaskInventory) + { + if (item.Value.Name == sound) + { + soundID = item.Value.ItemID; + break; + } + } + } + + List avatarts = m_parentGroup.Scene.GetAvatars(); + foreach (ScenePresence p in avatarts) + { + // TODO: some filtering by distance of avatar + + p.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); + } + } + + public void SendSound(string sound, double volume, bool triggered) + { + if (volume > 1) + volume = 1; + if (volume < 0) + volume = 0; + + LLUUID ownerID = OwnerID; + LLUUID objectID = UUID; + LLUUID parentID = GetRootPartUUID(); + LLUUID soundID = LLUUID.Zero; + LLVector3 position = AbsolutePosition; // region local + ulong regionHandle = m_parentGroup.Scene.RegionInfo.RegionHandle; + + byte flags = 0; + + if (!LLUUID.TryParse(sound, out soundID)) + { + // search sound file from inventory + SceneObjectPart op = this; + foreach (KeyValuePair item in op.TaskInventory) + { + if (item.Value.Name == sound) + { + soundID = item.Value.ItemID; + break; + } + } + } + + List avatarts = m_parentGroup.Scene.GetAvatars(); + foreach (ScenePresence p in avatarts) + { + // TODO: some filtering by distance of avatar + if (triggered) + { + p.ControllingClient.SendTriggeredSound(soundID, ownerID, objectID, parentID, regionHandle, position, (float)volume); + } + else + { + p.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)volume, flags); + } + } + } + + #endregion + + #region Resizing/Scale + + /// + /// + /// + /// + public void Resize(LLVector3 scale) + { + m_shape.Scale = scale; + + ScheduleFullUpdate(); + } + + #endregion + + public void UpdatePermissions(LLUUID AgentID, byte field, uint localID, uint mask, byte addRemTF) + { + bool set = addRemTF == 1; + + // Are we the owner? + if (AgentID == OwnerID) + { + switch (field) + { + case 2: + OwnerMask = ApplyMask(OwnerMask, set, mask); + break; + case 4: + GroupMask = ApplyMask(GroupMask, set, mask); + break; + case 8: + EveryoneMask = ApplyMask(EveryoneMask, set, mask); + break; + case 16: + NextOwnerMask = ApplyMask(NextOwnerMask, set, mask); + break; + } + SendFullUpdateToAllClients(); + + SendObjectPropertiesToClient(AgentID); + + } + } + + private void SendObjectPropertiesToClient(LLUUID AgentID) + { + List avatars = m_parentGroup.GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) + { + // Ugly reference :( + if (avatars[i].UUID == AgentID) + { + m_parentGroup.GetProperties(avatars[i].ControllingClient); + } + } + } + + private uint ApplyMask(uint val, bool set, uint mask) + { + if (set) + { + return val |= mask; + } + else + { + return val &= ~mask; + } + } + + #region Client Update Methods + + public void AddFullUpdateToAllAvatars() + { + List avatars = m_parentGroup.GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) + { + avatars[i].QueuePartForUpdate(this); + } + } + public void SendFullUpdateToAllClientsExcept(LLUUID agentID) + { + List avatars = m_parentGroup.GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) + { + // Ugly reference :( + if (avatars[i].UUID != agentID) + { + m_parentGroup.SendPartFullUpdate(avatars[i].ControllingClient, this, + avatars[i].GenerateClientFlags(UUID)); + } + } + } + public void AddFullUpdateToAvatar(ScenePresence presence) + { + presence.QueuePartForUpdate(this); + } + + /// + /// + /// + public void SendFullUpdateToAllClients() + { + List avatars = m_parentGroup.GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) + { + // Ugly reference :( + m_parentGroup.SendPartFullUpdate(avatars[i].ControllingClient, this, + avatars[i].GenerateClientFlags(UUID)); + } + } + + /// + /// + /// + /// + public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags) + { + m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags); + } + + /// + /// + /// + /// + public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientflags) + { + LLVector3 lPos; + lPos = OffsetPosition; + SendFullUpdateToClient(remoteClient, lPos, clientflags); + } + + public void SendFullUpdateToClient(IClientAPI remoteClient, LLVector3 lPos, uint clientFlags) + { + LLQuaternion lRot; + lRot = RotationOffset; + clientFlags &= ~(uint) LLObject.ObjectFlags.CreateSelected; + + if (remoteClient.AgentId == OwnerID) + { + if ((uint) (Flags & LLObject.ObjectFlags.CreateSelected) != 0) + { + clientFlags |= (uint) LLObject.ObjectFlags.CreateSelected; + Flags &= ~LLObject.ObjectFlags.CreateSelected; + } + } + + + byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A}; + remoteClient.SendPrimitiveToClient(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalID, m_shape, lPos, clientFlags, m_uuid, + OwnerID, + m_text, color, ParentID, m_particleSystem, lRot, m_clickAction, m_TextureAnimation); + } + + /// Terse updates + public void AddTerseUpdateToAllAvatars() + { + List avatars = m_parentGroup.GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) + { + avatars[i].QueuePartForUpdate(this); + } + } + + public void AddTerseUpdateToAvatar(ScenePresence presence) + { + presence.QueuePartForUpdate(this); + } + + /// + /// + /// + public void SendTerseUpdateToAllClients() + { + List avatars = m_parentGroup.GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) + { + m_parentGroup.SendPartTerseUpdate(avatars[i].ControllingClient, this); + } + } + + /// + /// + /// + /// + public void SendTerseUpdate(IClientAPI remoteClient) + { + m_parentGroup.SendPartTerseUpdate(remoteClient, this); + } + + public void SendTerseUpdateToClient(IClientAPI remoteClient) + { + LLVector3 lPos; + lPos = OffsetPosition; + LLQuaternion mRot = RotationOffset; + if ((ObjectFlags & (uint) LLObject.ObjectFlags.Physics) == 0) + { + remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalID, lPos, mRot); + } + else + { + remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalID, lPos, mRot, Velocity, + RotationalVelocity); + //System.Console.WriteLine("LID: " + LocalID + " RVel:" + RotationalVelocity.ToString() + " TD: " + ((ushort)(m_parentGroup.Scene.TimeDilation * 500000f)).ToString() + ":" + m_parentGroup.Scene.TimeDilation.ToString()); + } + } + + public void SendTerseUpdateToClient(IClientAPI remoteClient, LLVector3 lPos) + { + LLQuaternion mRot = RotationOffset; + if ((ObjectFlags & (uint) LLObject.ObjectFlags.Physics) == 0) + { + remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalID, lPos, mRot); + } + else + { + remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalID, lPos, mRot, Velocity, + RotationalVelocity); + //System.Console.WriteLine("LID: " + LocalID + "RVel:" + RotationalVelocity.ToString() + " TD: " + ((ushort)(m_parentGroup.Scene.TimeDilation * 500000f)).ToString() + ":" + m_parentGroup.Scene.TimeDilation.ToString()); + } + } + + #endregion + + public virtual void UpdateMovement() + { + } + + #region Events + + public void PhysicsRequestingTerseUpdate() + { + if (PhysActor != null) + { + LLVector3 newpos = new LLVector3(PhysActor.Position.GetBytes(), 0); + if (newpos.X > 257f || newpos.X < -1f || newpos.Y > 257f || newpos.Y < -1f) + { + m_parentGroup.AbsolutePosition = newpos; + return; + } + + } + ScheduleTerseUpdate(); + + //SendTerseUpdateToAllClients(); + } + + #endregion + + public void PhysicsOutOfBounds(PhysicsVector pos) + { + m_log.Info("[PHYSICS]: Physical Object went out of bounds."); + RemFlag(LLObject.ObjectFlags.Physics); + DoPhysicsPropertyUpdate(false, true); + m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + } + + public virtual void OnGrab(LLVector3 offsetPos, IClientAPI remoteClient) + { + } + + public void SetText(string text, Vector3 color, double alpha) + { + Color = Color.FromArgb(0xff - (int) (alpha*0xff), + (int) (color.x*0xff), + (int) (color.y*0xff), + (int) (color.z*0xff)); + Text = text; + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/trunk/OpenSim/Region/Environment/Scenes/ScenePresence.cs new file mode 100644 index 0000000000..8e5907c8ac --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/ScenePresence.cs @@ -0,0 +1,1767 @@ +/* +* 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; +using System.Collections.Generic; +using Axiom.Math; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Types; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Environment.Scenes +{ + public class ScenePresence : EntityBase + { +// ~ScenePresence() +// { +// System.Console.WriteLine("[ScenePresence] Destructor called"); +// } + + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public static AvatarAnimations Animations = new AvatarAnimations(); + public static byte[] DefaultTexture; + + public LLUUID currentParcelUUID = LLUUID.Zero; + private List m_animations = new List(); + private List m_animationSeqs = new List(); + public Vector3 lastKnownAllowedPosition = new Vector3(); + public bool sentMessageAboutRestrictedParcelFlyingDown = false; + + private bool m_updateflag = false; + private byte m_movementflag = 0; + private readonly List m_forcesList = new List(); + private short m_updateCount = 0; + private uint m_requestedSitTargetID = 0; + private LLVector3 m_requestedSitOffset = new LLVector3(); + private float m_sitAvatarHeight = 2.0f; + private float m_godlevel = 0; + private LLVector3 m_LastChildAgentUpdatePosition = new LLVector3(); + + private int m_perfMonMS = 0; + + private bool m_setAlwaysRun = false; + + private Quaternion m_bodyRot; + + public bool IsRestrictedToRegion = false; + + // Agent moves with a PID controller causing a force to be exerted. + private bool m_newForce = false; + private bool m_newCoarseLocations = true; + private bool m_gotAllObjectsInScene = false; + + private bool m_lastPhysicsStoppedStatus = false; + + private LLVector3 m_lastVelocity = LLVector3.Zero; + + // Default AV Height + private float m_avHeight = 127.0f; + + protected RegionInfo m_regionInfo; + protected ulong crossingFromRegion = 0; + + private readonly Vector3[] Dir_Vectors = new Vector3[6]; + private LLVector3 lastPhysPos = new LLVector3(); + + // Position of agent's camera in world (region cordinates) + protected Vector3 m_CameraCenter = new Vector3(0, 0, 0); + + // Use these three vectors to figure out what the agent is looking at + // Convert it to a Matrix and/or Quaternion + protected Vector3 m_CameraAtAxis = new Vector3(0, 0, 0); + protected Vector3 m_CameraLeftAxis = new Vector3(0, 0, 0); + protected Vector3 m_CameraUpAxis = new Vector3(0, 0, 0); + private uint m_AgentControlFlags = (uint) 0; + private LLQuaternion m_headrotation = new LLQuaternion(); + private byte m_state = (byte) 0; + + //Reuse the LLVector3 instead of creating a new one on the UpdateMovement method + private LLVector3 movementvector = new LLVector3(); + + private List m_knownPrimUUID = new List(); + + // Agent's Draw distance. + protected float m_DrawDistance = 0f; + + protected AvatarAppearance m_appearance; + + private readonly List m_knownChildRegions = new List(); + //neighbouring regions we have enabled a child agent in + + + /// + /// Implemented Control Flags + /// + private enum Dir_ControlFlags + { + DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, + DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, + DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, + DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, + DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, + DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, + DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG + } + + /// + /// Position at which a significant movement was made + /// + private LLVector3 posLastSignificantMove = new LLVector3(); + + public delegate void SignificantClientMovement(IClientAPI remote_client); + + public event SignificantClientMovement OnSignificantClientMovement; + + private UpdateQueue m_partsUpdateQueue = new UpdateQueue(); + private Dictionary m_updateTimes = new Dictionary(); + + #region Properties + + /// + /// Physical scene representation of this Avatar. + /// + public PhysicsActor PhysicsActor + { + set { m_physicsActor = value; } + get { return m_physicsActor; } + } + + public bool KnownPrim(LLUUID primID) + { + if (m_knownPrimUUID.Contains(primID)) + { + return true; + } + m_knownPrimUUID.Add(primID); + return false; + } + + + public bool Updated + { + set { m_updateflag = value; } + get { return m_updateflag; } + } + + private readonly ulong m_regionHandle; + + public ulong RegionHandle + { + get { return m_regionHandle; } + } + + public Vector3 CameraPosition + { + get { return m_CameraCenter; } + } + + private readonly string m_firstname; + + public string Firstname + { + get { return m_firstname; } + } + + private readonly string m_lastname; + + public string Lastname + { + get { return m_lastname; } + } + + public float DrawDistance + { + get { return m_DrawDistance; } + } + + protected bool m_allowMovement = true; + + public bool AllowMovement + { + get { return m_allowMovement; } + set { m_allowMovement = value; } + } + + /// + /// This works out to be the ClientView object associated with this avatar, or it's UDP connection manager + /// + private readonly IClientAPI m_controllingClient; + + protected PhysicsActor m_physicsActor; + + public IClientAPI ControllingClient + { + get { return m_controllingClient; } + } + + protected LLVector3 m_parentPosition = new LLVector3(); + + /// + /// Absolute position of this avatar in 'region cordinates' + /// + public override LLVector3 AbsolutePosition + { + get + { + if (m_physicsActor != null) + { + m_pos.X = m_physicsActor.Position.X; + m_pos.Y = m_physicsActor.Position.Y; + m_pos.Z = m_physicsActor.Position.Z; + } + + return m_parentPosition + m_pos; + } + set + { + if (m_physicsActor != null) + { + try + { + lock (m_scene.SyncRoot) + { + m_physicsActor.Position = new PhysicsVector(value.X, value.Y, value.Z); + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + } + + m_pos = value; + } + } + + /// + /// Current Velocity of the avatar. + /// + public override LLVector3 Velocity + { + get + { + if (m_physicsActor != null) + { + m_velocity.X = m_physicsActor.Velocity.X; + m_velocity.Y = m_physicsActor.Velocity.Y; + m_velocity.Z = m_physicsActor.Velocity.Z; + } + + return m_velocity; + } + set + { + if (m_physicsActor != null) + { + try + { + lock (m_scene.SyncRoot) + { + m_physicsActor.Velocity = new PhysicsVector(value.X, value.Y, value.Z); + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + } + + m_velocity = value; + } + } + + /// + /// If this is true, agent doesn't have a representation in this scene. + /// this is an agent 'looking into' this scene from a nearby scene(region) + /// + /// if False, this agent has a representation in this scene + /// + private bool m_isChildAgent = true; + + public bool IsChildAgent + { + get { return m_isChildAgent; } + set { m_isChildAgent = value; } + } + + private uint m_parentID = 0; + + public uint ParentID + { + get { return m_parentID; } + set { m_parentID = value; } + } + + /// + /// These are the region handles known by the avatar. + /// + public List KnownChildRegions + { + get { return m_knownChildRegions; } + } + + #endregion + + #region Constructor(s) + + private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) + { + m_regionHandle = reginfo.RegionHandle; + m_controllingClient = client; + m_firstname = m_controllingClient.FirstName; + m_lastname = m_controllingClient.LastName; + + m_scene = world; + m_uuid = client.AgentId; + m_regionInfo = reginfo; + m_localId = m_scene.NextLocalId; + + AbsolutePosition = m_controllingClient.StartPos; + + // TODO: m_animations and m_animationSeqs should always be of the same length. + // Move them into an object to (hopefully) avoid threading issues. + try + { + m_animations.Add(Animations.AnimsLLUUID["STAND"]); + } + catch (KeyNotFoundException) + { + m_log.Warn("[AVATAR]: KeyNotFound Exception playing avatar stand animation"); + } + m_animationSeqs.Add(1); + + RegisterToEvents(); + SetDirectionVectors(); + + m_scene.LandManager.sendLandUpdate(this, true); + } + + public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams, + AvatarWearable[] wearables) + : this(client, world, reginfo) + { + m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams); + } + + public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance) + : this(client, world, reginfo) + { + m_appearance = appearance; + } + + private void RegisterToEvents() + { + m_controllingClient.OnRequestWearables += SendOwnAppearance; + m_controllingClient.OnSetAppearance += SetAppearance; + m_controllingClient.OnCompleteMovementToRegion += CompleteMovement; + m_controllingClient.OnCompleteMovementToRegion += SendInitialData; + m_controllingClient.OnAgentUpdate += HandleAgentUpdate; + m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit; + m_controllingClient.OnAgentSit += HandleAgentSit; + m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; + m_controllingClient.OnStartAnim += HandleStartAnim; + m_controllingClient.OnStopAnim += HandleStopAnim; + + // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); + // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); + } + + private void SetDirectionVectors() + { + Dir_Vectors[0] = new Vector3(1, 0, 0); //FORWARD + Dir_Vectors[1] = new Vector3(-1, 0, 0); //BACK + Dir_Vectors[2] = new Vector3(0, 1, 0); //LEFT + Dir_Vectors[3] = new Vector3(0, -1, 0); //RIGHT + Dir_Vectors[4] = new Vector3(0, 0, 1); //UP + Dir_Vectors[5] = new Vector3(0, 0, -1); //DOWN + Dir_Vectors[5] = new Vector3(0, 0, -0.5f); //DOWN_Nudge + } + + #endregion + + public void QueuePartForUpdate(SceneObjectPart part) + { + //if (InterestList.Contains(part.ParentGroup)) + //{ + lock (m_partsUpdateQueue) + { + m_partsUpdateQueue.Enqueue(part); + } + // } + } + + public uint GenerateClientFlags(LLUUID ObjectID) + { + return m_scene.PermissionsMngr.GenerateClientFlags(m_uuid, ObjectID); + } + + public void SendPrimUpdates() + { + // if (m_scene.QuadTree.GetNodeID(this.AbsolutePosition.X, this.AbsolutePosition.Y) != m_currentQuadNode) + //{ + // this.UpdateQuadTreeNode(); + //this.RefreshQuadObject(); + //} + m_perfMonMS = System.Environment.TickCount; + + if (!m_gotAllObjectsInScene) + { + if (!m_isChildAgent || m_scene.m_seeIntoRegionFromNeighbor) + { + + m_scene.SendAllSceneObjectsToClient(this); + m_gotAllObjectsInScene = true; + + } + } + if (m_partsUpdateQueue.Count > 0) + { + bool runUpdate = true; + int updateCount = 0; + while (runUpdate) + { + SceneObjectPart part = m_partsUpdateQueue.Dequeue(); + if (m_updateTimes.ContainsKey(part.UUID)) + { + ScenePartUpdate update = m_updateTimes[part.UUID]; + + // Two updates can occur with the same timestamp (especially + // since our timestamp resolution is to the nearest second). The first + // could have been sent in the last update - we still need to send the + // second here. + + if (update.LastFullUpdateTime < part.TimeStampFull) + { + //need to do a full update + part.SendFullUpdate(ControllingClient, GenerateClientFlags(part.UUID)); + + // We'll update to the part's timestamp rather than the current to + // avoid the race condition whereby the next tick occurs while we are + // doing this update. If this happened, then subsequent updates which occurred + // on the same tick or the next tick of the last update would be ignored. + update.LastFullUpdateTime = part.TimeStampFull; + + updateCount++; + } + else if (update.LastTerseUpdateTime <= part.TimeStampTerse) + { + part.SendTerseUpdate(ControllingClient); + + update.LastTerseUpdateTime = part.TimeStampTerse; + updateCount++; + } + } + else + { + //never been sent to client before so do full update + part.SendFullUpdate(ControllingClient, GenerateClientFlags(part.UUID)); + ScenePartUpdate update = new ScenePartUpdate(); + update.FullID = part.UUID; + update.LastFullUpdateTime = part.TimeStampFull; + m_updateTimes.Add(part.UUID, update); + updateCount++; + } + + if (m_partsUpdateQueue.Count < 1 || updateCount > 60) + { + runUpdate = false; + } + } + } + + m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS); + } + + public void forceAvatarMovement(Vector3 position, Quaternion rotation) + { + AddNewMovement(position, rotation); + } + + #region Status Methods + + /// + /// This turns a child agent, into a root agent + /// This is called when an agent teleports into a region, or if an + /// agent crosses into this region from a neighbor over the border + /// + public void MakeRootAgent(LLVector3 pos, bool isFlying) + { + m_isChildAgent = false; + + AbsolutePosition = pos; + + AddToPhysicalScene(); + m_physicsActor.Flying = isFlying; + + m_scene.SwapRootAgentCount(false); + m_scene.CommsManager.UserProfileCacheService.UpdateUserInventory(m_uuid); + //if (!m_gotAllObjectsInScene) + //{ + m_scene.SendAllSceneObjectsToClient(this); + m_scene.LandManager.sendLandUpdate(this, true); + + //m_gotAllObjectsInScene = true; + //} + } + + /// + /// This turns a root agent into a child agent + /// when an agent departs this region for a neighbor, this gets called. + /// + /// It doesn't get called for a teleport. Reason being, an agent that + /// teleports out may not be anywhere near this region + /// + public void MakeChildAgent() + { + Velocity = new LLVector3(0, 0, 0); + m_isChildAgent = true; + m_scene.SwapRootAgentCount(true); + RemoveFromPhysicalScene(); + + //this.Pos = new LLVector3(128, 128, 70); + } + + /// + /// Removes physics plugin scene representation of this agent if it exists. + /// + private void RemoveFromPhysicalScene() + { + if (PhysicsActor != null) + { + m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); + m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; + m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; + PhysicsActor = null; + } + } + + /// + /// + /// + /// + public void Teleport(LLVector3 pos) + { + AbsolutePosition = pos; + SendTerseUpdateToAllClients(); + } + + /// + /// + /// + public void StopMovement() + { + } + + public void StopFlying() + { + // It turns out to get the agent to stop flying, you have to feed it stop flying velocities + // and send a full object update. + // There's no message to send the client to tell it to stop flying + + // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air + // when the avatar stands up + + if (m_avHeight != 127.0f) + { + AbsolutePosition = AbsolutePosition + new LLVector3(0, 0, (m_avHeight / 6)); + } + else + { + AbsolutePosition = AbsolutePosition + new LLVector3(0, 0, (1.56f / 6)); + } + SetMovementAnimation(Animations.AnimsLLUUID["LAND"], 2); + SendFullUpdateToAllClients(); + } + + public void AddNeighbourRegion(ulong regionHandle) + { + if (!m_knownChildRegions.Contains(regionHandle)) + { + m_knownChildRegions.Add(regionHandle); + } + } + + public void RemoveNeighbourRegion(ulong regionHandle) + { + if (!m_knownChildRegions.Contains(regionHandle)) + { + m_knownChildRegions.Remove(regionHandle); + } + } + + #endregion + + #region Event Handlers + + /// + /// Sets avatar height in the phyiscs plugin + /// + internal void SetHeight(float height) + { + m_avHeight = height; + if (PhysicsActor != null) + { + PhysicsVector SetSize = new PhysicsVector(0.45f, 0.6f, m_avHeight); + PhysicsActor.Size = SetSize; + } + } + + /// + /// Complete Avatar's movement into the region + /// + public void CompleteMovement() + { + LLVector3 look = Velocity; + if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) + { + look = new LLVector3(0.99f, 0.042f, 0); + } + + m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look); + + if (m_isChildAgent) + { + m_isChildAgent = false; + + //this.m_scene.SendAllSceneObjectsToClient(this.ControllingClient); + MakeRootAgent(AbsolutePosition, false); + } + } + + /// + /// This is the event handler for client movement. If a client is moving, this event is triggering. + /// + public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdatePacket agentData) + { + //if (m_isChildAgent) + //{ + // // Console.WriteLine("DEBUG: HandleAgentUpdate: child agent"); + // return; + //} + + // Must check for standing up even when PhysicsActor is null, + // since sitting currently removes avatar from physical scene + + m_perfMonMS = System.Environment.TickCount; + + uint flags = agentData.AgentData.ControlFlags; + LLQuaternion bodyRotation = agentData.AgentData.BodyRotation; + + // Camera location in world. We'll need to raytrace + // from this location from time to time. + m_CameraCenter.x = agentData.AgentData.CameraCenter.X; + m_CameraCenter.y = agentData.AgentData.CameraCenter.Y; + m_CameraCenter.z = agentData.AgentData.CameraCenter.Z; + + // Use these three vectors to figure out what the agent is looking at + // Convert it to a Matrix and/or Quaternion + m_CameraAtAxis.x = agentData.AgentData.CameraAtAxis.X; + m_CameraAtAxis.y = agentData.AgentData.CameraAtAxis.Y; + m_CameraAtAxis.z = agentData.AgentData.CameraAtAxis.Z; + + m_CameraLeftAxis.x = agentData.AgentData.CameraLeftAxis.X; + m_CameraLeftAxis.y = agentData.AgentData.CameraLeftAxis.Y; + m_CameraLeftAxis.z = agentData.AgentData.CameraLeftAxis.Z; + + m_CameraUpAxis.x = agentData.AgentData.CameraUpAxis.X; + m_CameraUpAxis.y = agentData.AgentData.CameraUpAxis.Y; + m_CameraUpAxis.z = agentData.AgentData.CameraUpAxis.Z; + + // The Agent's Draw distance setting + m_DrawDistance = agentData.AgentData.Far; + + if ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) + { + StandUp(); + } + + if (PhysicsActor == null) + { + return; + } + + if ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) + { + // TODO: This doesn't quite work yet -- probably a parent ID problem + // m_parentID = (what should this be?) + SetMovementAnimation(Animations.AnimsLLUUID["SIT_GROUND"], 1); + } + // In the future, these values might need to go global. + // Here's where you get them. + + // m_AgentControlFlags = flags; + // m_headrotation = agentData.AgentData.HeadRotation; + // m_state = agentData.AgentData.State; + + if (m_allowMovement) + { + int i = 0; + bool update_movementflag = false; + bool update_rotation = false; + bool DCFlagKeyPressed = false; + Vector3 agent_control_v3 = new Vector3(0, 0, 0); + Quaternion q = new Quaternion(bodyRotation.W, bodyRotation.X, bodyRotation.Y, bodyRotation.Z); + bool oldflying = PhysicsActor.Flying; + + PhysicsActor.Flying = ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); + if (PhysicsActor.Flying != oldflying) + { + update_movementflag = true; + } + + if (q != m_bodyRot) + { + m_bodyRot = q; + update_rotation = true; + } + + if (m_parentID == 0) + { + foreach (Dir_ControlFlags DCF in Enum.GetValues(typeof (Dir_ControlFlags))) + { + if ((flags & (uint) DCF) != 0) + { + DCFlagKeyPressed = true; + try + { + agent_control_v3 += Dir_Vectors[i]; + } + catch (IndexOutOfRangeException) + { + // Why did I get this? + } + if ((m_movementflag & (uint) DCF) == 0) + { + m_movementflag += (byte) (uint) DCF; + update_movementflag = true; + } + } + else + { + if ((m_movementflag & (uint) DCF) != 0) + { + m_movementflag -= (byte) (uint) DCF; + update_movementflag = true; + } + } + i++; + } + } + // Cause the avatar to stop flying if it's colliding + // with something with the down arrow pressed. + + // Skip if there's no physicsactor + if (m_physicsActor != null) + { + // Only do this if we're flying + if (m_physicsActor.Flying) + { + // Are the landing controls requirements filled? + bool controlland = (((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || + ((flags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); + + // Are the collision requirements fulfilled? + bool colliding = (m_physicsActor.IsColliding == true); + + + + if (m_physicsActor.Flying && colliding && controlland) + { + StopFlying(); + } + } + } + if ((update_movementflag) || (update_rotation && DCFlagKeyPressed)) + { + AddNewMovement(agent_control_v3, q); + UpdateMovementAnimations(update_movementflag); + } + } + + m_scene.EventManager.TriggerOnClientMovement(this); + + m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS); + } + + /// + /// Perform the logic necessary to stand the client up. This method also executes + /// the stand animation. + /// + public void StandUp() + { + if (m_parentID != 0) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); + if (part != null) + { + // Reset sit target. + if (part.GetAvatarOnSitTarget() == UUID) + part.SetAvatarOnSitTarget(LLUUID.Zero); + + m_parentPosition = part.GetWorldPosition(); + } + + if (m_physicsActor == null) + { + AddToPhysicalScene(); + + } + + m_pos += m_parentPosition + new LLVector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); + m_parentPosition = new LLVector3(); + + + m_parentID = 0; + SendFullUpdateToAllClients(); + + if (m_physicsActor != null) + { + SetHeight(m_avHeight); + + } + } + + SetMovementAnimation(Animations.AnimsLLUUID["STAND"], 1); + } + + private void SendSitResponse(IClientAPI remoteClient, LLUUID targetID, LLVector3 offset) + { + AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); + + avatarSitResponse.SitObject.ID = targetID; + + bool autopilot = true; + LLVector3 pos = new LLVector3(); + LLQuaternion sitOrientation = new LLQuaternion(0, 0, 0, 1); + + SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); + if (part != null) + { + // TODO: determine position to sit at based on scene geometry; don't trust offset from client + // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it + + + // Is a sit target available? + Vector3 avSitOffSet = part.GetSitTargetPosition(); + Quaternion avSitOrientation = part.GetSitTargetOrientation(); + LLUUID avOnTargetAlready = part.GetAvatarOnSitTarget(); + + bool SitTargetUnOccupied = (!(avOnTargetAlready != LLUUID.Zero)); + bool SitTargetisSet = + (!(avSitOffSet.x == 0 && avSitOffSet.y == 0 && avSitOffSet.z == 0 && avSitOrientation.w == 0 && + avSitOrientation.x == 0 && avSitOrientation.y == 0 && avSitOrientation.z == 1)); + + if (SitTargetisSet && SitTargetUnOccupied) + { + part.SetAvatarOnSitTarget(UUID); + offset = new LLVector3(avSitOffSet.x, avSitOffSet.y, avSitOffSet.z); + sitOrientation = + new LLQuaternion(avSitOrientation.w, avSitOrientation.x, avSitOrientation.y, avSitOrientation.z); + autopilot = false; + } + + + pos = part.AbsolutePosition + offset; + + if (m_physicsActor != null) + { + // + // If we're not using the client autopilot, we're immediately warping the avatar to the location + // We can remove the physicsActor until they stand up. + // + m_sitAvatarHeight = m_physicsActor.Size.Z; + + if (autopilot) + { + if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) + { + autopilot = false; + + RemoveFromPhysicalScene(); + AbsolutePosition = pos + new LLVector3(0.0f, 0.0f, m_sitAvatarHeight); + } + else + { + } + } + else + { + RemoveFromPhysicalScene(); + } + } // Physactor != null + } // part != null + + + avatarSitResponse.SitTransform.AutoPilot = autopilot; + avatarSitResponse.SitTransform.SitPosition = offset; + avatarSitResponse.SitTransform.SitRotation = sitOrientation; + + remoteClient.OutPacket(avatarSitResponse, ThrottleOutPacketType.Task); + + // This calls HandleAgentSit twice, once from here, and the client calls + // HandleAgentSit itself after it gets to the location + // It doesn't get to the location until we've moved them there though + // which happens in HandleAgentSit :P + if (!autopilot) + HandleAgentSit(remoteClient, UUID); + } + + public void HandleAgentRequestSit(IClientAPI remoteClient, LLUUID agentID, LLUUID targetID, LLVector3 offset) + { + if (m_parentID != 0) + { + StandUp(); + } + + + SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); + + if (part != null) + { + m_requestedSitTargetID = part.LocalID; + m_requestedSitOffset = offset; + } + else + { + m_log.Warn("Sit requested on unknown object: " + targetID.ToString()); + } + SendSitResponse(remoteClient, targetID, offset); + } + + public void HandleAgentSit(IClientAPI remoteClient, LLUUID agentID) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); + + if (part != null) + { + if (part.GetAvatarOnSitTarget() == UUID) + { + Vector3 sitTargetPos = part.GetSitTargetPosition(); + Quaternion sitTargetOrient = part.GetSitTargetOrientation(); + + //Quaternion vq = new Quaternion(sitTargetPos.x, sitTargetPos.y+0.2f, sitTargetPos.z+0.2f, 0); + //Quaternion nq = new Quaternion(sitTargetOrient.w, -sitTargetOrient.x, -sitTargetOrient.y, -sitTargetOrient.z); + + //Quaternion result = (sitTargetOrient * vq) * nq; + + m_pos = new LLVector3(sitTargetPos.x, sitTargetPos.y, sitTargetPos.z); + m_bodyRot = sitTargetOrient; + //Rotation = sitTargetOrient; + m_parentPosition = part.AbsolutePosition; + + //SendTerseUpdateToAllClients(); + } + else + { + m_pos -= part.AbsolutePosition; + m_parentPosition = part.AbsolutePosition; + } + } + + m_parentID = m_requestedSitTargetID; + + Velocity = new LLVector3(0, 0, 0); + RemoveFromPhysicalScene(); + + SetMovementAnimation(Animations.AnimsLLUUID["SIT"], 1); + SendFullUpdateToAllClients(); + // This may seem stupid, but Our Full updates don't send avatar rotation :P + // So we're also sending a terse update (which has avatar rotation) + SendTerseUpdateToAllClients(); + } + + /// + /// Event handler for the 'Always run' setting on the client + /// Tells the physics plugin to increase speed of movement. + /// + public void HandleSetAlwaysRun(IClientAPI remoteClient, bool SetAlwaysRun) + { + m_setAlwaysRun = SetAlwaysRun; + if (PhysicsActor != null) + { + PhysicsActor.SetAlwaysRun = SetAlwaysRun; + } + } + + public void AddAnimation(LLUUID animID, int seq) + { + if (!m_animations.Contains(animID)) + { + m_animations.Add(animID); + m_animationSeqs.Add(seq); + SendAnimPack(); + } + } + + public void RemoveAnimation(LLUUID animID) + { + if (m_animations.Contains(animID)) + { + if (m_animations[0] == animID) + { + SetMovementAnimation(Animations.AnimsLLUUID["STAND"], 1); + } + else + { + m_animations.Remove(animID); + SendAnimPack(); + } + } + } + + public void HandleStartAnim(IClientAPI remoteClient, LLUUID animID, int seq) + { + AddAnimation(animID, seq); + } + + public void HandleStopAnim(IClientAPI remoteClient, LLUUID animID) + { + RemoveAnimation(animID); + } + + /// + /// The movement animation is the first element of the animation list, + /// reserved for "main" animations that are mutually exclusive, + /// like flying and sitting, for example. + /// + protected void SetMovementAnimation(LLUUID anim, int seq) + { + try + { + if (m_animations[0] != anim) + { + m_animations[0] = anim; + m_animationSeqs[0] = seq; + SendAnimPack(); + } + } + catch + { + m_log.Warn("[AVATAR]: SetMovementAnimation for avatar failed. Attempting recovery..."); + m_animations[0] = anim; + m_animationSeqs[0] = seq; + SendAnimPack(); + } + } + + /// + /// This method handles agent movement related animations + /// + protected void UpdateMovementAnimations(bool update_movementflag) + { + + + if (update_movementflag) + { + // Are we moving? + if (m_movementflag != 0) + { + // We are moving + + if (m_physicsActor.Flying) + { + // We are flying + SetMovementAnimation(Animations.AnimsLLUUID["FLY"], 1); + } + else if (((m_movementflag & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) && + PhysicsActor.IsColliding) + { + // Client is pressing the page down button and moving and is colliding with something + SetMovementAnimation(Animations.AnimsLLUUID["CROUCHWALK"], 1); + } + else if (!PhysicsActor.IsColliding && m_physicsActor.Velocity.Z < -6) + { + // Client is moving and falling at a velocity greater then 6 meters per unit + SetMovementAnimation(Animations.AnimsLLUUID["FALLDOWN"], 1); + } + else if (!PhysicsActor.IsColliding && Velocity.Z > 0 && + (m_movementflag & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0) + { + // Client is moving, and colliding and pressing the page up button but isn't flying + try + { + SetMovementAnimation(Animations.AnimsLLUUID["JUMP"], 1); + } + catch (KeyNotFoundException) + { } + } + else if (m_setAlwaysRun) + { + // We are running + try + { + SetMovementAnimation(Animations.AnimsLLUUID["RUN"], 1); + } + catch (KeyNotFoundException) + { } + } + else + { + // We're moving, but we're not doing anything else.. so play the stand animation + try + { + SetMovementAnimation(Animations.AnimsLLUUID["WALK"], 1); + } + catch (KeyNotFoundException) + { } + + } + } + else + { + // Not moving + + if (((m_movementflag & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) && + PhysicsActor.IsColliding) + { + // Client pressing the page down button + SetMovementAnimation(Animations.AnimsLLUUID["CROUCH"], 1); + } + else if (!PhysicsActor.IsColliding && m_physicsActor.Velocity.Z < -6 && !m_physicsActor.Flying) + { + // Not colliding and not flying, and we're falling at high speed + SetMovementAnimation(Animations.AnimsLLUUID["FALLDOWN"], 1); + } + else if (!PhysicsActor.IsColliding && Velocity.Z > 0 && !m_physicsActor.Flying && + (m_movementflag & (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0) + { + // This is the standing jump + SetMovementAnimation(Animations.AnimsLLUUID["JUMP"], 1); + } + else if (m_physicsActor.Flying) + { + // We're flying but not moving + SetMovementAnimation(Animations.AnimsLLUUID["HOVER"], 1); + } + else + { + // We're not moving.. and we're not doing anything.. so play the stand animation + try + { + + SetMovementAnimation(Animations.AnimsLLUUID["STAND"], 1); + } + catch (KeyNotFoundException) + { } + } + } + } + + } + + /// + /// Adds a new movement + /// + protected void AddNewMovement(Vector3 vec, Quaternion rotation) + { + if (m_isChildAgent) + { + Console.WriteLine("DEBUG: AddNewMovement: child agent"); + return; + } + + m_perfMonMS = System.Environment.TickCount; + + m_rotation = rotation; + NewForce newVelocity = new NewForce(); + Vector3 direc = rotation*vec; + direc.Normalize(); + + direc *= 0.03f*128f; + if (m_physicsActor.Flying) + { + direc *= 4; + //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); + //bool colliding = (m_physicsActor.IsColliding==true); + //if (controlland) + // m_log.Info("[AGENT]: landCommand"); + //if (colliding ) + // m_log.Info("[AGENT]: colliding"); + //if (m_physicsActor.Flying && colliding && controlland) + //{ + // StopFlying(); + // m_log.Info("[AGENT]: Stop FLying"); + //} + } + else + { + if (!m_physicsActor.Flying && m_physicsActor.IsColliding) + { + //direc.z *= 40; + if (direc.z > 2.0f) + { + direc.z *= 3; + //System.Console.WriteLine("Jump"); + // PreJump and jump happen too quickly. Many times prejump gets ignored. + try + { + SetMovementAnimation(Animations.AnimsLLUUID["PREJUMP"], 1); + SetMovementAnimation(Animations.AnimsLLUUID["JUMP"], 1); + } + catch (KeyNotFoundException) + { } + } + } + } + + newVelocity.X = direc.x; + newVelocity.Y = direc.y; + newVelocity.Z = direc.z; + m_forcesList.Add(newVelocity); + + m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS); + } + + #endregion + + #region Overridden Methods + + /// + /// + /// + public override void Update() + { + SendPrimUpdates(); + + if (m_newCoarseLocations) + { + SendCoarseLocations(); + m_newCoarseLocations = false; + } + + if (m_isChildAgent == false) + { + if (m_newForce) // user movement 'forces' (ie commands to move) + { + SendTerseUpdateToAllClients(); + m_updateCount = 0; + } + else if (m_movementflag != 0) // scripted movement (?) + { + m_updateCount++; + if (m_updateCount > 3) + { + SendTerseUpdateToAllClients(); + m_updateCount = 0; + } + } + else if ((Util.GetDistanceTo(lastPhysPos, AbsolutePosition) > 0.02) || (Util.GetDistanceTo(m_lastVelocity, m_velocity) > 0.02)) // physics-related movement + { + + + // Send Terse Update to all clients updates lastPhysPos and m_lastVelocity + // doing the above assures us that we know what we sent the clients last + SendTerseUpdateToAllClients(); + m_updateCount = 0; + + + + } + + // followed suggestion from mic bowman. reversed the two lines below. + CheckForBorderCrossing(); + CheckForSignificantMovement(); // sends update to the modules. + + } + } + + #endregion + + #region Update Client(s) + + /// + /// Sends a location update to the client connected to this scenePresence + /// + /// + public void SendTerseUpdateToClient(IClientAPI remoteClient) + { + m_perfMonMS = System.Environment.TickCount; + + LLVector3 pos = m_pos; + LLVector3 vel = Velocity; + LLQuaternion rot = new LLQuaternion(m_bodyRot.x, m_bodyRot.y, m_bodyRot.z, m_bodyRot.w); + remoteClient.SendAvatarTerseUpdate(m_regionHandle, (ushort)(m_scene.TimeDilation * (float)ushort.MaxValue), LocalId, new LLVector3(pos.X, pos.Y, pos.Z), + new LLVector3(vel.X, vel.Y, vel.Z), rot); + + m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS); + m_scene.AddAgentUpdates(1); + } + + /// + /// Send a location/velocity/accelleration update to all agents in scene + /// + public void SendTerseUpdateToAllClients() + { + m_perfMonMS = System.Environment.TickCount; + + m_scene.Broadcast(SendTerseUpdateToClient); + + m_lastVelocity = m_velocity; + lastPhysPos = AbsolutePosition; + + m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS); + + } + + public void SendCoarseLocations() + { + m_perfMonMS = System.Environment.TickCount; + + List CoarseLocations = new List(); + List avatars = m_scene.GetAvatars(); + for (int i = 0; i < avatars.Count; i++) + { + if (avatars[i] != this) + { + CoarseLocations.Add(avatars[i].m_pos); + } + } + + m_controllingClient.SendCoarseLocationUpdate(CoarseLocations); + + m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS); + } + + public void CoarseLocationChange() + { + m_newCoarseLocations = true; + } + + /// + /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar) + /// + /// + public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar) + { + remoteAvatar.m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_uuid, + LocalId, m_pos, m_appearance.TextureEntry.ToBytes(), + m_parentID); + m_scene.AddAgentUpdates(1); + } + + /// + /// Tell *ALL* agents about this agent + /// + public void SendFullUpdateToAllClients() + { + m_perfMonMS = System.Environment.TickCount; + + List avatars = m_scene.GetScenePresences(); + foreach (ScenePresence avatar in avatars) + { + SendFullUpdateToOtherClient(avatar); + if (avatar.LocalId != LocalId) + { + if (!avatar.m_isChildAgent || m_scene.m_seeIntoRegionFromNeighbor) + { + avatar.SendFullUpdateToOtherClient(this); + avatar.SendAppearanceToOtherAgent(this); + } + } + } + m_scene.AddAgentUpdates(avatars.Count); + m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS); + } + + /// + /// + /// + public void SendInitialData() + { + m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_uuid, LocalId, + m_pos, m_appearance.TextureEntry.ToBytes(), m_parentID); + if (!m_isChildAgent) + { + m_scene.InformClientOfNeighbours(this); + } + + SendFullUpdateToAllClients(); + SendAppearanceToAllOtherAgents(); + } + + /// + /// + /// + /// + public void SendOwnAppearance() + { + m_appearance.SendOwnWearables(ControllingClient); + + // TODO: remove this once the SunModule is slightly more tested + // m_controllingClient.SendViewerTime(m_scene.TimePhase); + } + + /// + /// + /// + public void SendAppearanceToAllOtherAgents() + { + m_perfMonMS=System.Environment.TickCount; + + m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) + { + if (scenePresence.UUID != UUID) + { + m_appearance.SendAppearanceToOtherAgent(scenePresence); + } + }); + m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS); + } + + public void SendAppearanceToOtherAgent(ScenePresence avatar) + { + m_appearance.SendAppearanceToOtherAgent(avatar); + } + + public void SetAppearance(byte[] texture, AgentSetAppearancePacket.VisualParamBlock[] visualParam) + { + m_appearance.SetAppearance(texture, visualParam); + SetHeight(m_appearance.AvatarHeight); + + SendAppearanceToAllOtherAgents(); + } + + public void SetWearable(int wearableId, AvatarWearable wearable) + { + m_appearance.SetWearable(ControllingClient, wearableId, wearable); + } + + /// + /// + /// + /// + /// + public void SendAnimPack(LLUUID[] animations, int[] seqs) + { + m_scene.Broadcast( + delegate(IClientAPI client) { client.SendAnimations(animations, seqs, m_controllingClient.AgentId); }); + } + + /// + /// + /// + public void SendAnimPack() + { + SendAnimPack(m_animations.ToArray(), m_animationSeqs.ToArray()); + } + + #endregion + + #region Significant Movement Method + + /// + /// This checks for a significant movement and sends a courselocationchange update + /// + protected void CheckForSignificantMovement() + { + if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > 0.5) + { + posLastSignificantMove = AbsolutePosition; + if (OnSignificantClientMovement != null) + { + OnSignificantClientMovement(m_controllingClient); + m_scene.NotifyMyCoarseLocationChange(); + } + } + + // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m + if (Util.GetDistanceTo(AbsolutePosition,m_LastChildAgentUpdatePosition) > 32) + { + ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); + cadu.ActiveGroupID=LLUUID.Zero.UUID; + cadu.AgentID = UUID.UUID; + cadu.alwaysrun = m_setAlwaysRun; + cadu.AVHeight = m_avHeight; + LLVector3 tempCameraCenter = new LLVector3(m_CameraCenter.x, m_CameraCenter.y, m_CameraCenter.z); + cadu.cameraPosition = new sLLVector3(tempCameraCenter); + cadu.drawdistance = m_DrawDistance; + cadu.godlevel = m_godlevel; + cadu.GroupAccess = 0; + cadu.Position = new sLLVector3(AbsolutePosition); + cadu.regionHandle = m_scene.RegionInfo.RegionHandle; + cadu.throttles = ControllingClient.GetThrottlesPacked(1f); + cadu.Velocity = new sLLVector3(Velocity); + m_scene.SendOutChildAgentUpdates(cadu,this); + m_LastChildAgentUpdatePosition.X = AbsolutePosition.X; + m_LastChildAgentUpdatePosition.Y = AbsolutePosition.Y; + m_LastChildAgentUpdatePosition.Z = AbsolutePosition.Z; + } + } + + #endregion + + #region Border Crossing Methods + + /// + /// Checks to see if the avatar is in range of a border and calls CrossToNewRegion + /// + protected void CheckForBorderCrossing() + { + LLVector3 pos2 = AbsolutePosition; + LLVector3 vel = Velocity; + + float timeStep = 0.1f; + pos2.X = pos2.X + (vel.X*timeStep); + pos2.Y = pos2.Y + (vel.Y*timeStep); + pos2.Z = pos2.Z + (vel.Z*timeStep); + + if ((pos2.X < 0) || (pos2.X > Constants.RegionSize)) + { + CrossToNewRegion(); + } + + if ((pos2.Y < 0) || (pos2.Y > Constants.RegionSize)) + { + CrossToNewRegion(); + } + } + + /// + /// Moves the agent outside the region bounds + /// Tells neighbor region that we're crossing to it + /// If the neighbor accepts, remove the agent's viewable avatar from this scene + /// set them to a child agent. + /// + protected void CrossToNewRegion() + { + LLVector3 pos = AbsolutePosition; + LLVector3 newpos = new LLVector3(pos.X, pos.Y, pos.Z); + uint neighbourx = m_regionInfo.RegionLocX; + uint neighboury = m_regionInfo.RegionLocY; + + // distance to edge that will trigger crossing + const float boundaryDistance = 1.7f; + + // distance into new region to place avatar + const float enterDistance = 0.1f; + + if (pos.X < boundaryDistance) + { + neighbourx--; + newpos.X = Constants.RegionSize - enterDistance; + } + else if (pos.X > Constants.RegionSize - boundaryDistance) + { + neighbourx++; + newpos.X = enterDistance; + } + + if (pos.Y < boundaryDistance) + { + neighboury--; + newpos.Y = Constants.RegionSize - enterDistance; + } + else if (pos.Y > Constants.RegionSize - boundaryDistance) + { + neighboury++; + newpos.Y = enterDistance; + } + + LLVector3 vel = m_velocity; + ulong neighbourHandle = Helpers.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); + SimpleRegionInfo neighbourRegion = m_scene.RequestNeighbouringRegionInfo(neighbourHandle); + if (neighbourRegion != null) + { + bool res = + m_scene.InformNeighbourOfCrossing(neighbourHandle, m_controllingClient.AgentId, newpos, + m_physicsActor.Flying); + if (res) + { + AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo(); + string capsPath = Util.GetCapsURL(m_controllingClient.AgentId); + m_controllingClient.CrossRegion(neighbourHandle, newpos, vel, neighbourRegion.ExternalEndPoint, + capsPath); + MakeChildAgent(); + m_scene.SendKillObject(m_localId); + m_scene.NotifyMyCoarseLocationChange(); + } + } + } + + #endregion + + /// + /// This allows the Sim owner the abiility to kick users from their sim currently. + /// It tells the client that the agent has permission to do so. + /// + public void GrantGodlikePowers(LLUUID agentID, LLUUID sessionID, LLUUID token) + { + GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket(); + GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock(); + GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock(); + + adb.AgentID = agentID; + adb.SessionID = sessionID; // More security + + gdb.GodLevel = (byte) 250; + gdb.Token = token; + //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock; + respondPacket.GrantData = gdb; + respondPacket.AgentData = adb; + ControllingClient.OutPacket(respondPacket, ThrottleOutPacketType.Task); + } + + /// + /// This updates important decision making data about a child agent + /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region + /// + public void ChildAgentDataUpdate(ChildAgentDataUpdate cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) + { + // + int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; + int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; + + m_DrawDistance = cAgentData.drawdistance; + m_pos = new LLVector3(cAgentData.Position.x + shiftx, cAgentData.Position.y + shifty, cAgentData.Position.z); + + // It's hard to say here.. We can't really tell where the camera position is unless it's in world cordinates from the sending region + m_CameraCenter = + new Vector3(cAgentData.cameraPosition.x, cAgentData.cameraPosition.y, cAgentData.cameraPosition.z); + + + m_godlevel = cAgentData.godlevel; + SetHeight(cAgentData.AVHeight); + + ControllingClient.SetChildAgentThrottle(cAgentData.throttles); + + + + // Sends out the objects in the user's draw distance if m_sendTasksToChild is true. + if (m_scene.m_seeIntoRegionFromNeighbor) + m_scene.SendAllSceneObjectsToClient(this); + //cAgentData.AVHeight; + //cAgentData.regionHandle; + //m_velocity = cAgentData.Velocity; + } + + /// + /// Handles part of the PID controller function for moving an avatar. + /// + public override void UpdateMovement() + { + m_newForce = false; + lock (m_forcesList) + { + if (m_forcesList.Count > 0) + { + for (int i = 0; i < m_forcesList.Count; i++) + { + NewForce force = m_forcesList[i]; + + m_updateflag = true; + try + { + movementvector.X = force.X; + movementvector.Y = force.Y; + movementvector.Z = force.Z; + Velocity = movementvector; + } + catch (System.NullReferenceException) + { + // Under extreme load, this returns a NullReference Exception that we can ignore. + // Ignoring this causes no movement to be sent to the physics engine... + // which when the scene is moving at 1 frame every 10 seconds, it doesn't really matter! + } + m_newForce = true; + } + for (int i = 0; i < m_forcesList.Count; i++) + { + m_forcesList.RemoveAt(0); + } + } + } + } + + static ScenePresence() + { + LLObject.TextureEntry textu = AvatarAppearance.GetDefaultTextureEntry(); + DefaultTexture = textu.ToBytes(); + } + + public class NewForce + { + public float X; + public float Y; + public float Z; + + public NewForce() + { + } + } + + public class ScenePartUpdate + { + public LLUUID FullID; + public uint LastFullUpdateTime; + public uint LastTerseUpdateTime; + + public ScenePartUpdate() + { + FullID = LLUUID.Zero; + LastFullUpdateTime = 0; + LastTerseUpdateTime = 0; + } + } + + public override void SetText(string text, Vector3 color, double alpha) + { + throw new Exception("Can't set Text on avatar."); + } + + /// + /// Adds a physical representation of the avatar to the Physics plugin + /// + public void AddToPhysicalScene() + { + PhysicsScene scene = m_scene.PhysicsScene; + + PhysicsVector pVec = + new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, + AbsolutePosition.Z); + + m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,new PhysicsVector(0,0,m_avHeight)); + //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; + m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; + } + + // Event called by the physics plugin to tell the avatar about a collision. + private void PhysicsCollisionUpdate(EventArgs e) + { + bool isUserMoving = Velocity.X > 0 || Velocity.Y > 0; + UpdateMovementAnimations(isUserMoving); + } + + internal void Close() + { + RemoveFromPhysicalScene(); + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/SceneXmlLoader.cs b/trunk/OpenSim/Region/Environment/Scenes/SceneXmlLoader.cs new file mode 100644 index 0000000000..498261374c --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/SceneXmlLoader.cs @@ -0,0 +1,223 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using Axiom.Math; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Environment.Scenes +{ + public class SceneXmlLoader // can move to a module? + { + protected InnerScene m_innerScene; + protected RegionInfo m_regInfo; + protected Scene m_parentScene; + + public SceneXmlLoader(Scene parentScene, InnerScene innerScene, RegionInfo regionInfo) + { + m_parentScene = parentScene; + m_innerScene = innerScene; + m_regInfo = regionInfo; + } + + public void LoadPrimsFromXml(string fileName, bool newIDS, LLVector3 loadOffset) + { + XmlDocument doc = new XmlDocument(); + XmlNode rootNode; + int primCount = 0; + if (fileName.StartsWith("http:") || File.Exists(fileName)) + { + XmlTextReader reader = new XmlTextReader(fileName); + reader.WhitespaceHandling = WhitespaceHandling.None; + doc.Load(reader); + reader.Close(); + rootNode = doc.FirstChild; + foreach (XmlNode aPrimNode in rootNode.ChildNodes) + { + SceneObjectGroup obj = new SceneObjectGroup(m_parentScene, + m_regInfo.RegionHandle, aPrimNode.OuterXml); + if (newIDS) + { + obj.ResetIDs(); + } + //if we want this to be a import method then we need new uuids for the object to avoid any clashes + //obj.RegenerateFullIDs(); + m_innerScene.AddEntity(obj); + + SceneObjectPart rootPart = obj.GetChildPart(obj.UUID); + // Apply loadOffsets for load/import and move combinations + rootPart.GroupPosition = rootPart.AbsolutePosition + loadOffset; + bool UsePhysics = (((rootPart.ObjectFlags & (uint) LLObject.ObjectFlags.Physics) > 0) && + m_parentScene.m_physicalPrim); + if ((rootPart.ObjectFlags & (uint) LLObject.ObjectFlags.Phantom) == 0) + { + rootPart.PhysActor = m_innerScene.PhysicsScene.AddPrimShape( + rootPart.Name, + rootPart.Shape, + new PhysicsVector(rootPart.AbsolutePosition.X + loadOffset.X, + rootPart.AbsolutePosition.Y + loadOffset.Y, + rootPart.AbsolutePosition.Z + loadOffset.Z), + new PhysicsVector(rootPart.Scale.X, rootPart.Scale.Y, rootPart.Scale.Z), + new Quaternion(rootPart.RotationOffset.W, rootPart.RotationOffset.X, + rootPart.RotationOffset.Y, rootPart.RotationOffset.Z), UsePhysics); + rootPart.DoPhysicsPropertyUpdate(UsePhysics, true); + } + primCount++; + } + } + else + { + throw new Exception("Could not open file " + fileName + " for reading"); + } + } + + public void SavePrimsToXml(string fileName) + { + FileStream file = new FileStream(fileName, FileMode.Create); + StreamWriter stream = new StreamWriter(file); + int primCount = 0; + stream.WriteLine("\n"); + + List EntityList = m_innerScene.GetEntities(); + + foreach (EntityBase ent in EntityList) + { + if (ent is SceneObjectGroup) + { + stream.WriteLine(((SceneObjectGroup) ent).ToXmlString()); + primCount++; + } + } + stream.WriteLine("\n"); + stream.Close(); + file.Close(); + } + + public string SavePrimGroupToXML2String(SceneObjectGroup grp) + { + string returnstring = ""; + returnstring += "\n"; + returnstring += grp.ToXmlString2(); + returnstring += "\n"; + return returnstring; + + } + + public void LoadGroupFromXml2String(string xmlString) + { + XmlDocument doc = new XmlDocument(); + XmlNode rootNode; + + XmlTextReader reader = new XmlTextReader(new StringReader(xmlString)); + reader.WhitespaceHandling = WhitespaceHandling.None; + doc.Load(reader); + reader.Close(); + rootNode = doc.FirstChild; + foreach (XmlNode aPrimNode in rootNode.ChildNodes) + { + CreatePrimFromXml(aPrimNode.OuterXml); + } + + } + + public void LoadPrimsFromXml2(string fileName) + { + XmlDocument doc = new XmlDocument(); + XmlNode rootNode; + if (fileName.StartsWith("http:") || File.Exists(fileName)) + { + XmlTextReader reader = new XmlTextReader(fileName); + reader.WhitespaceHandling = WhitespaceHandling.None; + doc.Load(reader); + reader.Close(); + rootNode = doc.FirstChild; + foreach (XmlNode aPrimNode in rootNode.ChildNodes) + { + CreatePrimFromXml(aPrimNode.OuterXml); + } + } + else + { + throw new Exception("Could not open file " + fileName + " for reading"); + } + } + + public void CreatePrimFromXml(string xmlData) + { + SceneObjectGroup obj = new SceneObjectGroup(xmlData); + LLVector3 receivedVelocity = obj.RootPart.Velocity; + //System.Console.WriteLine(obj.RootPart.Velocity.ToString()); + m_innerScene.AddEntityFromStorage(obj); + + SceneObjectPart rootPart = obj.GetChildPart(obj.UUID); + bool UsePhysics = (((rootPart.ObjectFlags & (uint) LLObject.ObjectFlags.Physics) > 0) && + m_parentScene.m_physicalPrim); + if ((rootPart.ObjectFlags & (uint) LLObject.ObjectFlags.Phantom) == 0) + { + rootPart.PhysActor = m_innerScene.PhysicsScene.AddPrimShape( + rootPart.Name, + rootPart.Shape, + new PhysicsVector(rootPart.AbsolutePosition.X, rootPart.AbsolutePosition.Y, + rootPart.AbsolutePosition.Z), + new PhysicsVector(rootPart.Scale.X, rootPart.Scale.Y, rootPart.Scale.Z), + new Quaternion(rootPart.RotationOffset.W, rootPart.RotationOffset.X, + rootPart.RotationOffset.Y, rootPart.RotationOffset.Z), UsePhysics); + rootPart.DoPhysicsPropertyUpdate(UsePhysics, true); + rootPart.Velocity = receivedVelocity; + + } + } + + public void SavePrimsToXml2(string fileName) + { + FileStream file = new FileStream(fileName, FileMode.Create); + StreamWriter stream = new StreamWriter(file); + int primCount = 0; + stream.WriteLine("\n"); + + List EntityList = m_innerScene.GetEntities(); + + foreach (EntityBase ent in EntityList) + { + if (ent is SceneObjectGroup) + { + stream.WriteLine(((SceneObjectGroup) ent).ToXmlString2()); + primCount++; + } + } + stream.WriteLine("\n"); + stream.Close(); + file.Close(); + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Scenes/Scripting/IScriptHost.cs b/trunk/OpenSim/Region/Environment/Scenes/Scripting/IScriptHost.cs new file mode 100644 index 0000000000..cb000c4f6a --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/Scripting/IScriptHost.cs @@ -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. +* +*/ + +using Axiom.Math; +using libsecondlife; + +namespace OpenSim.Region.Environment.Scenes.Scripting +{ + public interface IScriptHost + { + string Name { get; set; } + string SitName { get; set; } + string TouchName { get; set; } + string Description { get; set; } + LLUUID UUID { get; } + LLUUID ObjectOwner { get; } + LLUUID ObjectCreator { get; } + LLVector3 AbsolutePosition { get; } + void SetText(string text, Vector3 color, double alpha); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Scenes/Scripting/NullScriptHost.cs b/trunk/OpenSim/Region/Environment/Scenes/Scripting/NullScriptHost.cs new file mode 100644 index 0000000000..58cf4c6564 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/Scripting/NullScriptHost.cs @@ -0,0 +1,88 @@ +/* +* 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; +using Axiom.Math; +using libsecondlife; + +namespace OpenSim.Region.Environment.Scenes.Scripting +{ + public class NullScriptHost : IScriptHost + { + private LLVector3 m_pos = new LLVector3(128, 128, 30); + + public string Name + { + get { return "Object"; } + set { } + } + + public string SitName + { + get { return String.Empty; } + set { } + } + + public string TouchName + { + get { return String.Empty; } + set { } + } + + public string Description + { + get { return String.Empty; } + set { } + } + + public LLUUID UUID + { + get { return LLUUID.Zero; } + } + + public LLUUID ObjectOwner + { + get { return LLUUID.Zero; } + } + + public LLUUID ObjectCreator + { + get { return LLUUID.Zero; } + } + + public LLVector3 AbsolutePosition + { + get { return m_pos; } + } + + public void SetText(string text, Vector3 color, double alpha) + { + Console.WriteLine("Tried to SetText [{0}] on NullScriptHost", text); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineInterface.cs b/trunk/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineInterface.cs new file mode 100644 index 0000000000..5d432f558f --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineInterface.cs @@ -0,0 +1,40 @@ +/* +* 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 OpenSim.Framework.Console; + +//TODO: WHERE TO PLACE THIS? + +namespace OpenSim.Region.Environment.Scenes.Scripting +{ + public interface ScriptEngineInterface + { + void InitializeEngine(Scene Sceneworld); + void Shutdown(); +// void StartScript(string ScriptID, IScriptHost ObjectID); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineLoader.cs b/trunk/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineLoader.cs new file mode 100644 index 0000000000..b52b2e9cf3 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/Scripting/ScriptEngineLoader.cs @@ -0,0 +1,119 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.IO; +using System.Reflection; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Environment.Scenes.Scripting +{ + public class ScriptEngineLoader + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public ScriptEngineInterface LoadScriptEngine(string EngineName) + { + ScriptEngineInterface ret = null; + try + { + ret = + LoadAndInitAssembly( + Path.Combine("ScriptEngines", "OpenSim.Region.ScriptEngine." + EngineName + ".dll"), + "OpenSim.Region.ScriptEngine." + EngineName + ".ScriptEngine"); + } + catch (Exception e) + { + m_log.Error("[ScriptEngine]: " + + "Error loading assembly \"" + EngineName + "\": " + e.Message + ", " + + e.StackTrace.ToString()); + } + return ret; + } + + /// + /// Does actual loading and initialization of script Assembly + /// + /// AppDomain to load script into + /// FileName of script assembly (.dll) + /// + private ScriptEngineInterface LoadAndInitAssembly(string FileName, string NameSpace) + { + //Common.SendToDebug("Loading ScriptEngine Assembly " + FileName); + // Load .Net Assembly (.dll) + // Initialize and return it + + // TODO: Add error handling + + Assembly a; + //try + //{ + + + // Load to default appdomain (temporary) + a = Assembly.LoadFrom(FileName); + // Load to specified appdomain + // TODO: Insert security + //a = FreeAppDomain.Load(FileName); + //} + //catch (Exception e) + //{ + // m_log.Error("[ScriptEngine]: Error loading assembly \String.Empty + FileName + "\": " + e.ToString()); + //} + + + //Console.WriteLine("Loading: " + FileName); + //foreach (Type _t in a.GetTypes()) + //{ + // Console.WriteLine("Type: " + _t.ToString()); + //} + + Type t; + //try + //{ + t = a.GetType(NameSpace, true); + //} + //catch (Exception e) + //{ + // m_log.Error("[ScriptEngine]: Error initializing type \String.Empty + NameSpace + "\" from \String.Empty + FileName + "\": " + e.ToString()); + //} + + ScriptEngineInterface ret; + //try + //{ + ret = (ScriptEngineInterface) Activator.CreateInstance(t); + //} + //catch (Exception e) + //{ + // m_log.Error("[ScriptEngine]: Error initializing type \String.Empty + NameSpace + "\" from \String.Empty + FileName + "\": " + e.ToString()); + //} + + return ret; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs b/trunk/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs new file mode 100644 index 0000000000..a0539f0a8f --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs @@ -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 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; +using System.Timers; +using libsecondlife.Packets; +using OpenSim.Framework; + +namespace OpenSim.Region.Environment.Scenes +{ + public class SimStatsReporter + { + public delegate void SendStatResult(SimStatsPacket pack); + + public event SendStatResult OnSendStatsResult; + + private enum Stats : uint + { + TimeDilation = 0, + SimFPS = 1, + PhysicsFPS = 2, + AgentUpdates = 3, + FrameMS = 4, + NetMS = 5, + OtherMS = 6, + PhysicsMS = 7, + AgentMS = 8, + ImageMS = 9, + ScriptMS = 10, + TotalPrim = 11, + ActivePrim = 12, + Agents = 13, + ChildAgents = 14, + ActiveScripts = 15, + ScriptLinesPerSecond = 16, + InPacketsPerSecond = 17, + OutPacketsPerSecond = 18, + PendingDownloads = 19, + PendingUploads = 20, + UnAckedBytes = 24, + + // Havok4 related... May or may not be in upcoming LLclients + // (kelly added them sometime late in January 2008) + NumRCCSLODReduced = 25, + NumRCCSFixed = 26 + } + + // Sending a stats update every 3 seconds + private int statsUpdatesEveryMS = 3000; + private float statsUpdateFactor = 0; + private float m_timeDilation = 0; + private int m_fps = 0; + private float m_pfps = 0; + private int m_agentUpdates = 0; + + private int m_frameMS = 0; + private int m_netMS = 0; + private int m_agentMS = 0; + private int m_physicsMS = 0; + private int m_imageMS = 0; + private int m_otherMS = 0; + private int m_scriptMS = 0; + + private int m_rootAgents = 0; + private int m_childAgents = 0; + private int m_numPrim = 0; + private int m_inPacketsPerSecond = 0; + private int m_outPacketsPerSecond = 0; + private int m_activePrim = 0; + private int m_unAckedBytes = 0; + private int m_pendingDownloads = 0; + private int m_pendingUploads = 0; + private int m_activeScripts = 0; + private int m_scriptLinesPerSecond = 0; + + + SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[21]; + SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); + SimStatsPacket statpack = (SimStatsPacket)PacketPool.Instance.GetPacket(PacketType.SimStats); + + + private RegionInfo ReportingRegion; + + private Timer m_report = new Timer(); + + + public SimStatsReporter(RegionInfo regionData) + { + + statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000); + ReportingRegion = regionData; + for (int i = 0; i<21;i++) + { + sb[i] = new SimStatsPacket.StatBlock(); + } + m_report.AutoReset = true; + m_report.Interval = statsUpdatesEveryMS; + m_report.Elapsed += new ElapsedEventHandler(statsHeartBeat); + m_report.Enabled = true; + } + + public void SetUpdateMS(int ms) + { + statsUpdatesEveryMS = ms; + statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000); + m_report.Interval = statsUpdatesEveryMS; + } + + private void statsHeartBeat(object sender, EventArgs e) + { + m_report.Enabled = false; + + // Packet is already initialized and ready for data insert + + + statpack.Region = rb; + statpack.Region.RegionX = ReportingRegion.RegionLocX; + statpack.Region.RegionY = ReportingRegion.RegionLocY; + try + { + statpack.Region.RegionFlags = (uint) ReportingRegion.EstateSettings.regionFlags; + } + catch (Exception) + { + statpack.Region.RegionFlags = (uint) 0; + } + statpack.Region.ObjectCapacity = (uint) 15000; + + #region various statistic googly moogly + + // Our FPS is actually 10fps, so multiplying by 5 to get the amount that people expect there + // 0-50 is pretty close to 0-45 + float simfps = (int) ((m_fps * 5)); + + //if (simfps > 45) + //simfps = simfps - (simfps - 45); + //if (simfps < 0) + //simfps = 0; + + // + float physfps = ((m_pfps / 1000)); + + //if (physfps > 600) + //physfps = physfps - (physfps - 600); + + if (physfps < 0) + physfps = 0; + + #endregion + + //Our time dilation is 0.91 when we're running a full speed, + // therefore to make sure we get an appropriate range, + // we have to factor in our error. (0.10f * statsUpdateFactor) + // multiplies the fix for the error times the amount of times it'll occur a second + // / 10 divides the value by the number of times the sim heartbeat runs (10fps) + // Then we divide the whole amount by the amount of seconds pass in between stats updates. + + sb[0].StatID = (uint) Stats.TimeDilation; + sb[0].StatValue = m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); + + sb[1].StatID = (uint) Stats.SimFPS; + sb[1].StatValue = simfps/statsUpdateFactor; + + sb[2].StatID = (uint) Stats.PhysicsFPS; + sb[2].StatValue = physfps / statsUpdateFactor; + + sb[3].StatID = (uint) Stats.AgentUpdates; + sb[3].StatValue = (m_agentUpdates / statsUpdateFactor); + + sb[4].StatID = (uint) Stats.Agents; + sb[4].StatValue = m_rootAgents; + + sb[5].StatID = (uint) Stats.ChildAgents; + sb[5].StatValue = m_childAgents; + + sb[6].StatID = (uint) Stats.TotalPrim; + sb[6].StatValue = m_numPrim; + + sb[7].StatID = (uint) Stats.ActivePrim; + sb[7].StatValue = m_activePrim; + + sb[8].StatID = (uint)Stats.FrameMS; + sb[8].StatValue = m_frameMS / statsUpdateFactor; + + sb[9].StatID = (uint)Stats.NetMS; + sb[9].StatValue = m_netMS / statsUpdateFactor; + + sb[10].StatID = (uint)Stats.PhysicsMS; + sb[10].StatValue = m_physicsMS / statsUpdateFactor; + + sb[11].StatID = (uint)Stats.ImageMS ; + sb[11].StatValue = m_imageMS / statsUpdateFactor; + + sb[12].StatID = (uint)Stats.OtherMS; + sb[12].StatValue = m_otherMS / statsUpdateFactor; + + sb[13].StatID = (uint)Stats.InPacketsPerSecond; + sb[13].StatValue = (m_inPacketsPerSecond); + + sb[14].StatID = (uint)Stats.OutPacketsPerSecond; + sb[14].StatValue = (m_outPacketsPerSecond / statsUpdateFactor); + + sb[15].StatID = (uint)Stats.UnAckedBytes; + sb[15].StatValue = m_unAckedBytes; + + sb[16].StatID = (uint)Stats.AgentMS; + sb[16].StatValue = m_agentMS / statsUpdateFactor; + + sb[17].StatID = (uint)Stats.PendingDownloads; + sb[17].StatValue = m_pendingDownloads; + + sb[18].StatID = (uint)Stats.PendingUploads; + sb[18].StatValue = m_pendingUploads; + + sb[19].StatID = (uint)Stats.ActiveScripts; + sb[19].StatValue = m_activeScripts; + + sb[20].StatID = (uint)Stats.ScriptLinesPerSecond; + sb[20].StatValue = m_scriptLinesPerSecond / statsUpdateFactor; + + statpack.Stat = sb; + + if (OnSendStatsResult != null) + { + OnSendStatsResult(statpack); + } + resetvalues(); + m_report.Enabled = true; + } + + private void resetvalues() + { + m_timeDilation = 0; + m_fps = 0; + m_pfps = 0; + m_agentUpdates = 0; + m_inPacketsPerSecond = 0; + m_outPacketsPerSecond = 0; + m_unAckedBytes = 0; + m_scriptLinesPerSecond = 0; + + m_frameMS = 0; + m_agentMS = 0; + m_netMS = 0; + m_physicsMS = 0; + m_imageMS = 0; + m_otherMS = 0; + m_scriptMS = 0; + } + + # region methods called from Scene + // The majority of these functions are additive + // so that you can easily change the amount of + // seconds in between sim stats updates + + public void AddTimeDilation(float td) + { + //float tdsetting = td; + //if (tdsetting > 1.0f) + //tdsetting = (tdsetting - (tdsetting - 0.91f)); + + //if (tdsetting < 0) + //tdsetting = 0.0f; + m_timeDilation = td; + } + + public void SetRootAgents(int rootAgents) + { + m_rootAgents = rootAgents; + } + + public void SetChildAgents(int childAgents) + { + m_childAgents = childAgents; + } + + public void SetObjects(int objects) + { + m_numPrim = objects; + } + + public void SetActiveObjects(int objects) + { + m_activePrim = objects; + } + + public void AddFPS(int frames) + { + m_fps += frames; + } + + public void AddPhysicsFPS(float frames) + { + m_pfps += frames; + } + + public void AddAgentUpdates(int numUpdates) + { + m_agentUpdates += numUpdates; + } + + public void AddInPackets(int numPackets) + { + m_inPacketsPerSecond += numPackets; + } + + public void AddOutPackets(int numPackets) + { + m_outPacketsPerSecond += numPackets; + } + + public void AddunAckedBytes(int numBytes) + { + m_unAckedBytes += numBytes; + } + + public void addFrameMS(int ms) + { + m_frameMS += ms; + } + public void addNetMS(int ms) + { + m_netMS += ms; + } + public void addAgentMS(int ms) + { + m_agentMS += ms; + } + public void addPhysicsMS(int ms) + { + m_physicsMS += ms; + } + public void addImageMS(int ms) + { + m_imageMS += ms; + } + public void addOtherMS(int ms) + { + m_otherMS += ms; + } + public void addPendingDownload(int count) + { + m_pendingDownloads += count; + } + + public void addScriptLines(int count) + { + m_scriptLinesPerSecond += count; + } + + public void SetActiveScripts(int count) + { + m_activeScripts = count; + } + + #endregion + + } +} diff --git a/trunk/OpenSim/Region/Environment/StorageManager.cs b/trunk/OpenSim/Region/Environment/StorageManager.cs new file mode 100644 index 0000000000..f15bbdbfab --- /dev/null +++ b/trunk/OpenSim/Region/Environment/StorageManager.cs @@ -0,0 +1,79 @@ +/* +* 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; +using System.Reflection; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; + +namespace OpenSim.Region.Environment +{ + public class StorageManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private IRegionDataStore m_dataStore; + + public IRegionDataStore DataStore + { + get { return m_dataStore; } + } + + public StorageManager(IRegionDataStore storage) + { + m_dataStore = storage; + } + + public StorageManager(string dllName, string connectionstring, bool persistPrimInventories) + { + m_log.Info("[DATASTORE]: Attempting to load " + dllName); + Assembly pluginAssembly = Assembly.LoadFrom(dllName); + + foreach (Type pluginType in pluginAssembly.GetTypes()) + { + if (pluginType.IsPublic) + { + Type typeInterface = pluginType.GetInterface("IRegionDataStore", true); + + if (typeInterface != null) + { + IRegionDataStore plug = + (IRegionDataStore) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + plug.Initialise(connectionstring, persistPrimInventories); + + m_dataStore = plug; + + m_log.Info("[DATASTORE]: Added IRegionDataStore Interface"); + } + } + } + + //TODO: Add checking and warning to make sure it initialised. + } + } +} diff --git a/trunk/OpenSim/Region/Environment/Types/BasicQuadTreeNode.cs b/trunk/OpenSim/Region/Environment/Types/BasicQuadTreeNode.cs new file mode 100644 index 0000000000..e654d2dfbb --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Types/BasicQuadTreeNode.cs @@ -0,0 +1,269 @@ +/* +* 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.Collections.Generic; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Types +{ + public class BasicQuadTreeNode + { + private List m_objects = new List(); + private BasicQuadTreeNode[] m_childNodes = null; + private BasicQuadTreeNode m_parent = null; + + private short m_leftX; + private short m_leftY; + private short m_width; + private short m_height; + //private int m_quadNumber; + private string m_quadID; + + public BasicQuadTreeNode(BasicQuadTreeNode parent, string quadID, short leftX, short leftY, short width, + short height) + { + m_parent = parent; + m_quadID = quadID; + m_leftX = leftX; + m_leftY = leftY; + m_width = width; + m_height = height; + // Console.WriteLine("creating quadtree node " + m_quadID); + } + + public void AddObject(SceneObjectGroup obj) + { + if (m_childNodes == null) + { + if (!m_objects.Contains(obj)) + { + m_objects.Add(obj); + } + } + else + { + if (obj.AbsolutePosition.X < (m_leftX + (m_width/2))) + { + if (obj.AbsolutePosition.Y < (m_leftY + (m_height/2))) + { + m_childNodes[0].AddObject(obj); + } + else + { + m_childNodes[2].AddObject(obj); + } + } + else + { + if (obj.AbsolutePosition.Y < (m_leftY + (m_height/2))) + { + m_childNodes[1].AddObject(obj); + } + else + { + m_childNodes[3].AddObject(obj); + } + } + } + } + + public void Subdivide() + { + if (m_childNodes == null) + { + m_childNodes = new BasicQuadTreeNode[4]; + m_childNodes[0] = + new BasicQuadTreeNode(this, m_quadID + "1/", m_leftX, m_leftY, (short) (m_width/2), + (short) (m_height/2)); + m_childNodes[1] = + new BasicQuadTreeNode(this, m_quadID + "2/", (short) (m_leftX + (m_width/2)), m_leftY, + (short) (m_width/2), (short) (m_height/2)); + m_childNodes[2] = + new BasicQuadTreeNode(this, m_quadID + "3/", m_leftX, (short) (m_leftY + (m_height/2)), + (short) (m_width/2), (short) (m_height/2)); + m_childNodes[3] = + new BasicQuadTreeNode(this, m_quadID + "4/", (short) (m_leftX + (m_width/2)), + (short) (m_height + (m_height/2)), (short) (m_width/2), (short) (m_height/2)); + } + else + { + for (int i = 0; i < m_childNodes.Length; i++) + { + m_childNodes[i].Subdivide(); + } + } + } + + public List GetObjectsFrom(float x, float y) + { + if (m_childNodes == null) + { + return new List(m_objects); + } + else + { + if (x < m_leftX + (m_width/2)) + { + if (y < m_leftY + (m_height/2)) + { + return m_childNodes[0].GetObjectsFrom(x, y); + } + else + { + return m_childNodes[2].GetObjectsFrom(x, y); + } + } + else + { + if (y < m_leftY + (m_height/2)) + { + return m_childNodes[1].GetObjectsFrom(x, y); + } + else + { + return m_childNodes[3].GetObjectsFrom(x, y); + } + } + } + } + + public List GetObjectsFrom(string nodeName) + { + if (nodeName == m_quadID) + { + return new List(m_objects); + } + else if (m_childNodes != null) + { + for (int i = 0; i < 4; i++) + { + List retVal; + retVal = m_childNodes[i].GetObjectsFrom(nodeName); + if (retVal != null) + { + return retVal; + } + } + } + return null; + } + + public string GetNodeID(float x, float y) + { + if (m_childNodes == null) + { + return m_quadID; + } + else + { + if (x < m_leftX + (m_width/2)) + { + if (y < m_leftY + (m_height/2)) + { + return m_childNodes[0].GetNodeID(x, y); + } + else + { + return m_childNodes[2].GetNodeID(x, y); + } + } + else + { + if (y < m_leftY + (m_height/2)) + { + return m_childNodes[1].GetNodeID(x, y); + } + else + { + return m_childNodes[3].GetNodeID(x, y); + } + } + } + } + + public void Update() + { + if (m_childNodes != null) + { + for (int i = 0; i < 4; i++) + { + m_childNodes[i].Update(); + } + } + else + { + List outBounds = new List(); + foreach (SceneObjectGroup group in m_objects) + { + if (((group.AbsolutePosition.X > m_leftX) && (group.AbsolutePosition.X < (m_leftX + m_width))) && + ((group.AbsolutePosition.Y > m_leftY) && (group.AbsolutePosition.Y < (m_leftY + m_height)))) + { + //still in bounds + } + else + { + outBounds.Add(group); + } + } + + foreach (SceneObjectGroup removee in outBounds) + { + m_objects.Remove(removee); + if (m_parent != null) + { + m_parent.PassUp(removee); + } + } + outBounds.Clear(); + } + } + + public void PassUp(SceneObjectGroup group) + { + if (((group.AbsolutePosition.X > m_leftX) && (group.AbsolutePosition.X < (m_leftX + m_width))) && + ((group.AbsolutePosition.Y > m_leftY) && (group.AbsolutePosition.Y < (m_leftY + m_height)))) + { + AddObject(group); + } + else + { + if (m_parent != null) + { + m_parent.PassUp(group); + } + } + } + + public string[] GetNeighbours(string nodeName) + { + string[] retVal = new string[1]; + retVal[0] = System.String.Empty; + return retVal; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Environment/Types/UpdateQueue.cs b/trunk/OpenSim/Region/Environment/Types/UpdateQueue.cs new file mode 100644 index 0000000000..0648476be2 --- /dev/null +++ b/trunk/OpenSim/Region/Environment/Types/UpdateQueue.cs @@ -0,0 +1,79 @@ +/* +* 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.Collections.Generic; +using libsecondlife; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Types +{ + public class UpdateQueue + { + private Queue m_queue; + + private List m_ids; + + public int Count + { + get { return m_queue.Count; } + } + + public UpdateQueue() + { + m_queue = new Queue(); + m_ids = new List(); + } + + public void Enqueue(SceneObjectPart part) + { + lock (m_ids) + { + if (!m_ids.Contains(part.UUID)) + { + m_ids.Add(part.UUID); + m_queue.Enqueue(part); + } + } + } + + public SceneObjectPart Dequeue() + { + SceneObjectPart part = null; + if (m_queue.Count > 0) + { + part = m_queue.Dequeue(); + lock (m_ids) + { + m_ids.Remove(part.UUID); + } + } + + return part; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Examples/SimpleApp/ComplexObject.cs b/trunk/OpenSim/Region/Examples/SimpleApp/ComplexObject.cs new file mode 100644 index 0000000000..06bcdec6e3 --- /dev/null +++ b/trunk/OpenSim/Region/Examples/SimpleApp/ComplexObject.cs @@ -0,0 +1,115 @@ +/* +* 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 libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes; + +namespace SimpleApp +{ + public class ComplexObject : SceneObjectGroup + { + private LLQuaternion m_rotationDirection; + + private class RotatingWheel : SceneObjectPart + { + private LLQuaternion m_rotationDirection; + + public RotatingWheel(ulong regionHandle, SceneObjectGroup parent, LLUUID ownerID, uint localID, + LLVector3 groupPosition, LLVector3 offsetPosition, LLQuaternion rotationDirection) + : base( + regionHandle, parent, ownerID, localID, PrimitiveBaseShape.CreateCylinder(0.5f, 0.2f), groupPosition, offsetPosition + ) + { + m_rotationDirection = rotationDirection; + } + + public override void UpdateMovement() + { + UpdateRotation(RotationOffset*m_rotationDirection); + } + } + + public override void UpdateMovement() + { + UpdateGroupRotation(GroupRotation*m_rotationDirection); + + base.UpdateMovement(); + } + + + public ComplexObject(Scene scene, ulong regionHandle, LLUUID ownerID, uint localID, LLVector3 pos) + : base(scene, regionHandle, ownerID, localID, pos, PrimitiveBaseShape.Default) + { + m_rotationDirection = new LLQuaternion(0.05f, 0.1f, 0.15f); + + AddPart( + new RotatingWheel(regionHandle, this, ownerID, scene.PrimIDAllocate(), pos, new LLVector3(0, 0, 0.75f), + new LLQuaternion(0.05f, 0, 0))); + AddPart( + new RotatingWheel(regionHandle, this, ownerID, scene.PrimIDAllocate(), pos, new LLVector3(0, 0, -0.75f), + new LLQuaternion(-0.05f, 0, 0))); + + AddPart( + new RotatingWheel(regionHandle, this, ownerID, scene.PrimIDAllocate(), pos, new LLVector3(0, 0.75f, 0), + new LLQuaternion(0.5f, 0, 0.05f))); + AddPart( + new RotatingWheel(regionHandle, this, ownerID, scene.PrimIDAllocate(), pos, new LLVector3(0, -0.75f, 0), + new LLQuaternion(-0.5f, 0, -0.05f))); + + AddPart( + new RotatingWheel(regionHandle, this, ownerID, scene.PrimIDAllocate(), pos, new LLVector3(0.75f, 0, 0), + new LLQuaternion(0, 0.5f, 0.05f))); + AddPart( + new RotatingWheel(regionHandle, this, ownerID, scene.PrimIDAllocate(), pos, new LLVector3(-0.75f, 0, 0), + new LLQuaternion(0, -0.5f, -0.05f))); + + UpdateParentIDs(); + } + + public override void OnGrabPart(SceneObjectPart part, LLVector3 offsetPos, IClientAPI remoteClient) + { + m_parts.Remove(part.UUID); + remoteClient.SendKillObject(m_regionHandle, part.LocalID); + remoteClient.AddMoney(1); + remoteClient.SendChatMessage("Poof!", 1, AbsolutePosition, "Party Party", LLUUID.Zero); + } + + public override void OnGrabGroup(LLVector3 offsetPos, IClientAPI remoteClient) + { + if (m_parts.Count == 1) + { + m_parts.Remove(m_rootPart.UUID); + m_scene.RemoveEntity(this); + remoteClient.SendKillObject(m_regionHandle, m_rootPart.LocalID); + remoteClient.AddMoney(50); + remoteClient.SendChatMessage("KABLAM!!!", 1, AbsolutePosition, "Groupie Groupie", LLUUID.Zero); + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Examples/SimpleApp/CpuCounterObject.cs b/trunk/OpenSim/Region/Examples/SimpleApp/CpuCounterObject.cs new file mode 100644 index 0000000000..041050d3c7 --- /dev/null +++ b/trunk/OpenSim/Region/Examples/SimpleApp/CpuCounterObject.cs @@ -0,0 +1,60 @@ +/* +* 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; +using System.Diagnostics; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes; + +namespace SimpleApp +{ + public class CpuCounterObject : SceneObjectGroup + { + private PerformanceCounter m_counter; + + public CpuCounterObject(Scene world, ulong regionHandle, LLUUID ownerID, uint localID, LLVector3 pos) + : base(world, regionHandle, ownerID, localID, pos, PrimitiveBaseShape.Default) + { + String objectName = "Processor"; + String counterName = "% Processor Time"; + String instanceName = "_Total"; + + m_counter = new PerformanceCounter(objectName, counterName, instanceName); + } + + public override void UpdateMovement() + { + float cpu = m_counter.NextValue()/40f; + LLVector3 size = new LLVector3(cpu, cpu, cpu); + //rootPrimitive.ResizeGoup( size ); + + base.UpdateMovement(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Examples/SimpleApp/FileSystemObject.cs b/trunk/OpenSim/Region/Examples/SimpleApp/FileSystemObject.cs new file mode 100644 index 0000000000..3fe15ff543 --- /dev/null +++ b/trunk/OpenSim/Region/Examples/SimpleApp/FileSystemObject.cs @@ -0,0 +1,52 @@ +/* +* 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.IO; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes; + +namespace SimpleApp +{ + public class FileSystemObject : SceneObjectGroup + { + public FileSystemObject(Scene world, FileInfo fileInfo, LLVector3 pos) + : base(world, world.RegionInfo.RegionHandle, LLUUID.Zero, world.NextLocalId, pos, PrimitiveBaseShape.Default) + { + //float size = (float) Math.Pow((double) fileInfo.Length, (double) 1/3)/5; + // rootPrimitive.ResizeGoup(new LLVector3(size, size, size)); + Text = fileInfo.Name; + ScheduleGroupForFullUpdate(); + } + + public override void Update() + { + base.Update(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs b/trunk/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs new file mode 100644 index 0000000000..0258c61c2a --- /dev/null +++ b/trunk/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs @@ -0,0 +1,531 @@ +/* +* 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; +using System.Collections.Generic; +using System.Net; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes; + +namespace SimpleApp +{ + public class MyNpcCharacter : IClientAPI + { + private uint movementFlag = 0; + private short flyState = 0; + private LLQuaternion bodyDirection = LLQuaternion.Identity; + private short count = 0; + +#pragma warning disable 67 + + public event Action OnLogout; + public event ObjectPermissions OnObjectPermissions; + + public event MoneyTransferRequest OnMoneyTransferRequest; + public event Action OnConnectionClosed; + + public event ImprovedInstantMessage OnInstantMessage; + public event ChatFromViewer OnChatFromViewer; + public event TextureRequest OnRequestTexture; + public event RezObject OnRezObject; + public event ModifyTerrain OnModifyTerrain; + public event SetAppearance OnSetAppearance; + public event AvatarNowWearing OnAvatarNowWearing; + public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; + public event ObjectAttach OnObjectAttach; + public event StartAnim OnStartAnim; + public event StopAnim OnStopAnim; + public event LinkObjects OnLinkObjects; + public event DelinkObjects OnDelinkObjects; + public event RequestMapBlocks OnRequestMapBlocks; + public event RequestMapName OnMapNameRequest; + public event TeleportLocationRequest OnTeleportLocationRequest; + public event DisconnectUser OnDisconnectUser; + public event RequestAvatarProperties OnRequestAvatarProperties; + public event SetAlwaysRun OnSetAlwaysRun; + + public event GenericCall4 OnDeRezObject; + public event Action OnRegionHandShakeReply; + public event GenericCall2 OnRequestWearables; + public event GenericCall2 OnCompleteMovementToRegion; + public event UpdateAgent OnAgentUpdate; + public event AgentRequestSit OnAgentRequestSit; + public event AgentSit OnAgentSit; + public event AvatarPickerRequest OnAvatarPickerRequest; + public event Action OnRequestAvatarsData; + public event AddNewPrim OnAddPrim; + public event RequestGodlikePowers OnRequestGodlikePowers; + public event GodKickUser OnGodKickUser; + public event ObjectDuplicate OnObjectDuplicate; + public event UpdateVector OnGrabObject; + public event ObjectSelect OnDeGrabObject; + public event MoveObject OnGrabUpdate; + public event ViewerEffectEventHandler OnViewerEffect; + + + public event UpdateShape OnUpdatePrimShape; + public event ObjectExtraParams OnUpdateExtraParams; + public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; + public event ObjectSelect OnObjectSelect; + public event GenericCall7 OnObjectDescription; + public event GenericCall7 OnObjectName; + public event UpdatePrimFlags OnUpdatePrimFlags; + public event UpdatePrimTexture OnUpdatePrimTexture; + public event UpdateVector OnUpdatePrimGroupPosition; + public event UpdateVector OnUpdatePrimSinglePosition; + public event UpdatePrimRotation OnUpdatePrimGroupRotation; + public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation; + public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; + public event UpdateVector OnUpdatePrimScale; + public event StatusChange OnChildAgentStatus; + public event GenericCall2 OnStopMovement; + public event Action OnRemoveAvatar; + + public event CreateNewInventoryItem OnCreateNewInventoryItem; + public event CreateInventoryFolder OnCreateNewInventoryFolder; + public event UpdateInventoryFolder OnUpdateInventoryFolder; + public event MoveInventoryFolder OnMoveInventoryFolder; + public event RemoveInventoryFolder OnRemoveInventoryFolder; + public event RemoveInventoryItem OnRemoveInventoryItem; + public event FetchInventoryDescendents OnFetchInventoryDescendents; + public event PurgeInventoryDescendents OnPurgeInventoryDescendents; + public event FetchInventory OnFetchInventory; + public event RequestTaskInventory OnRequestTaskInventory; + public event UpdateInventoryItem OnUpdateInventoryItem; + public event CopyInventoryItem OnCopyInventoryItem; + public event MoveInventoryItem OnMoveInventoryItem; + public event UDPAssetUploadRequest OnAssetUploadRequest; + public event XferReceive OnXferReceive; + public event RequestXfer OnRequestXfer; + public event ConfirmXfer OnConfirmXfer; + public event RezScript OnRezScript; + public event UpdateTaskInventory OnUpdateTaskInventory; + public event RemoveTaskInventory OnRemoveTaskItem; + + public event UUIDNameRequest OnNameFromUUIDRequest; + + public event ParcelPropertiesRequest OnParcelPropertiesRequest; + public event ParcelDivideRequest OnParcelDivideRequest; + public event ParcelJoinRequest OnParcelJoinRequest; + public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; + + public event ParcelAccessListRequest OnParcelAccessListRequest; + public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest; + public event ParcelSelectObjects OnParcelSelectObjects; + public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest; + public event ObjectDeselect OnObjectDeselect; + public event EstateOwnerMessageRequest OnEstateOwnerMessage; + public event RegionInfoRequest OnRegionInfoRequest; + public event EstateCovenantRequest OnEstateCovenantRequest; + + public event FriendActionDelegate OnApproveFriendRequest; + public event FriendActionDelegate OnDenyFriendRequest; + public event FriendshipTermination OnTerminateFriendship; + public event PacketStats OnPacketStats; + public event MoneyBalanceRequest OnMoneyBalanceRequest; + +#pragma warning restore 67 + + private LLUUID myID = LLUUID.Random(); + + public MyNpcCharacter(EventManager eventManager) + { + // startPos = new LLVector3(128, (float)(Util.RandomClass.NextDouble()*100), 2); + eventManager.OnFrame += Update; + } + + private LLVector3 startPos = new LLVector3(128, 128, 2); + + public virtual LLVector3 StartPos + { + get { return startPos; } + set { } + } + + public virtual LLUUID AgentId + { + get { return myID; } + } + + public LLUUID SessionId + { + get { return LLUUID.Zero; } + } + + public LLUUID SecureSessionId + { + get { return LLUUID.Zero; } + } + + public virtual string FirstName + { + get { return "Annoying"; } + } + + private string lastName = "NPC" + Util.RandomClass.Next(1, 1000); + + public virtual string LastName + { + get { return lastName; } + } + + public virtual String Name + { + get { return FirstName + LastName; } + } + + + public virtual void OutPacket(Packet newPack, ThrottleOutPacketType packType) + { + } + + public virtual void SendWearables(AvatarWearable[] wearables, int serial) + { + } + + public virtual void SendAppearance(LLUUID agentID, byte[] visualParams, byte[] textureEntry) + { + } + + public virtual void Kick(string message) + { + } + + public virtual void SendStartPingCheck(byte seq) + { + } + + public virtual void SendAvatarPickerReply(AvatarPickerReplyPacket response) + { + } + + public virtual void SendKillObject(ulong regionHandle, uint localID) + { + } + + public virtual void SetChildAgentThrottle(byte[] throttle) + { + } + public byte[] GetThrottlesPacked(float multiplier) + { + return new byte[0]; + } + + + public virtual void SendAnimations(LLUUID[] animations, int[] seqs, LLUUID sourceAgentId) + { + } + + public virtual void SendChatMessage(string message, byte type, LLVector3 fromPos, string fromName, + LLUUID fromAgentID) + { + } + + public virtual void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, + LLUUID fromAgentID) + { + } + + public virtual void SendInstantMessage(LLUUID fromAgent, LLUUID fromAgentSession, string message, LLUUID toAgent, + LLUUID imSessionID, string fromName, byte dialog, uint timeStamp) + { + } + + public virtual void SendLayerData(float[] map) + { + } + + public virtual void SendLayerData(int px, int py, float[] map) + { + } + + public virtual void MoveAgentIntoRegion(RegionInfo regInfo, LLVector3 pos, LLVector3 look) + { + } + + public virtual void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourExternalEndPoint) + { + } + + public virtual AgentCircuitData RequestClientInfo() + { + return new AgentCircuitData(); + } + + public virtual void CrossRegion(ulong newRegionHandle, LLVector3 pos, LLVector3 lookAt, + IPEndPoint newRegionExternalEndPoint, string capsURL) + { + } + + public virtual void SendMapBlock(List mapBlocks) + { + } + + public virtual void SendLocalTeleport(LLVector3 position, LLVector3 lookAt, uint flags) + { + } + + public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, + uint locationID, uint flags, string capsURL) + { + } + + public virtual void SendTeleportFailed(string reason) + { + } + + public virtual void SendTeleportLocationStart() + { + } + + public virtual void SendMoneyBalance(LLUUID transaction, bool success, byte[] description, int balance) + { + } + + public virtual void SendAvatarData(ulong regionHandle, string firstName, string lastName, LLUUID avatarID, + uint avatarLocalID, LLVector3 Pos, byte[] textureEntry, uint parentID) + { + } + + public virtual void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, + LLVector3 position, LLVector3 velocity, LLQuaternion rotation) + { + } + + public virtual void SendCoarseLocationUpdate(List CoarseLocations) + { + } + + public virtual void AttachObject(uint localID, LLQuaternion rotation, byte attachPoint) + { + } + + public virtual void SendDialog(string objectname, LLUUID objectID, LLUUID ownerID, string msg, LLUUID textureID, int ch, string[] buttonlabels) + { + } + + public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, + PrimitiveBaseShape primShape, LLVector3 pos, uint flags, + LLUUID objectID, LLUUID ownerID, string text, byte[] color, + uint parentID, + byte[] particleSystem, LLQuaternion rotation, byte clickAction) + { + } + public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, + PrimitiveBaseShape primShape, LLVector3 pos, uint flags, + LLUUID objectID, LLUUID ownerID, string text, byte[] color, + uint parentID, + byte[] particleSystem, LLQuaternion rotation, byte clickAction, byte[] textureanimation) + { + } + public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, + LLVector3 position, LLQuaternion rotation) + { + } + + public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, + LLVector3 position, LLQuaternion rotation, LLVector3 velocity, + LLVector3 rotationalvelocity) + { + } + + public virtual void SendInventoryFolderDetails(LLUUID ownerID, LLUUID folderID, + List items, + List folders, + bool fetchFolders, + bool fetchItems) + { + } + + public virtual void SendInventoryItemDetails(LLUUID ownerID, InventoryItemBase item) + { + } + + public virtual void SendInventoryItemCreateUpdate(InventoryItemBase Item) + { + } + + public virtual void SendRemoveInventoryItem(LLUUID itemID) + { + } + + public virtual void SendTaskInventory(LLUUID taskID, short serial, byte[] fileName) + { + } + + public virtual void SendXferPacket(ulong xferID, uint packet, byte[] data) + { + } + + public virtual void SendNameReply(LLUUID profileId, string firstname, string lastname) + { + } + + public virtual void SendPreLoadSound(LLUUID objectID, LLUUID ownerID, LLUUID soundID) + { + } + + public virtual void SendPlayAttachedSound(LLUUID soundID, LLUUID objectID, LLUUID ownerID, float gain, + byte flags) + { + } + + public void SendTriggeredSound(LLUUID soundID, LLUUID ownerID, LLUUID objectID, LLUUID parentID, ulong handle, LLVector3 position, float gain) + { + } + + public void SendAlertMessage(string message) + { + } + + public void SendAgentAlertMessage(string message, bool modal) + { + } + + public void SendSystemAlertMessage(string message) + { + } + + public void SendLoadURL(string objectname, LLUUID objectID, LLUUID ownerID, bool groupOwned, string message, + string url) + { + } + + public virtual void SendRegionHandshake(RegionInfo regionInfo) + { + if (OnRegionHandShakeReply != null) + { + OnRegionHandShakeReply(this); + } + + if (OnCompleteMovementToRegion != null) + { + OnCompleteMovementToRegion(); + } + } + + private void Update() + { + if (OnAgentUpdate != null) + { + AgentUpdatePacket pack = new AgentUpdatePacket(); + pack.AgentData.ControlFlags = movementFlag; + pack.AgentData.BodyRotation = bodyDirection; + OnAgentUpdate(this, pack); + } + if (flyState == 0) + { + movementFlag = (uint) AgentManager.ControlFlags.AGENT_CONTROL_FLY | + (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG; + flyState = 1; + } + else if (flyState == 1) + { + movementFlag = (uint) AgentManager.ControlFlags.AGENT_CONTROL_FLY | + (uint) AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; + flyState = 2; + } + else + { + movementFlag = (uint) AgentManager.ControlFlags.AGENT_CONTROL_FLY; + flyState = 0; + } + + if (count >= 200) + { + if (OnChatFromViewer != null) + { + ChatFromViewerArgs args = new ChatFromViewerArgs(); + args.Message = "Kinda quiet around here, isn't it?"; + args.Channel = 0; + args.From = FirstName + " " + LastName; + args.Position = new LLVector3(128, 128, 26); + args.Sender = this; + args.Type = ChatTypeEnum.Shout; + + OnChatFromViewer(this, args); + } + count = -1; + } + + count++; + } + + public bool AddMoney(int debit) + { + return false; + } + + public void SendSunPos(LLVector3 sunPos, LLVector3 sunVel) + { + } + + public void SendViewerTime(int phase) + { + } + + public void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember, + string flAbout, uint flags, LLUUID flImageID, LLUUID imageID, string profileURL, + LLUUID partnerID) + { + } + + public void SetDebug(int newDebug) + { + } + + public void InPacket(Packet NewPack) + { + } + + public void Close(bool ShutdownCircuit) + { + } + + public void Stop() + { + } + + private uint m_circuitCode; + + public uint CircuitCode + { + get { return m_circuitCode; } + set { m_circuitCode = value; } + } + public void SendBlueBoxMessage(LLUUID FromAvatarID, LLUUID fromSessionID, String FromAvatarName, String Message) + { + + } + public void SendLogoutPacket() + { + } + } +} diff --git a/trunk/OpenSim/Region/Examples/SimpleApp/MyWorld.cs b/trunk/OpenSim/Region/Examples/SimpleApp/MyWorld.cs new file mode 100644 index 0000000000..4c12b3f730 --- /dev/null +++ b/trunk/OpenSim/Region/Examples/SimpleApp/MyWorld.cs @@ -0,0 +1,83 @@ +/* +* 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.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Servers; +using OpenSim.Region.Environment; +using OpenSim.Region.Environment.Scenes; + +namespace SimpleApp +{ + public class MyWorld : Scene + { + private List m_avatars; + + public MyWorld(RegionInfo regionInfo, AgentCircuitManager authen, PermissionManager permissionManager, + CommunicationsManager commsMan, SceneCommunicationService sceneGridService, + AssetCache assetCach, StorageManager storeMan, BaseHttpServer httpServer, + ModuleLoader moduleLoader, bool physicalPrim, bool ChildGetTasks) + : base( + regionInfo, authen, permissionManager, commsMan, sceneGridService, assetCach, storeMan, httpServer, + moduleLoader, false, true, false) + { + m_avatars = new List(); + } + + public override void LoadWorldMap() + { + float[] map = new float[65536]; + + for (int i = 0; i < 65536; i++) + { + map[i] = 25f; + } + + Terrain.GetHeights1D(map); + CreateTerrainTexture(true); + } + + public override void AddNewClient(IClientAPI client, bool child) + { + SubscribeToClientEvents(client); + + ScenePresence avatar = CreateAndAddScenePresence(client, child); + avatar.AbsolutePosition = new LLVector3(128, 128, 26); + + LLVector3 pos = new LLVector3(128, 128, 128); + + client.OnCompleteMovementToRegion += + delegate() { client.SendChatMessage("Welcome to My World.", 1, pos, "System", LLUUID.Zero); }; + + client.SendRegionHandshake(m_regInfo); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Examples/SimpleApp/Program.cs b/trunk/OpenSim/Region/Examples/SimpleApp/Program.cs new file mode 100644 index 0000000000..f919276610 --- /dev/null +++ b/trunk/OpenSim/Region/Examples/SimpleApp/Program.cs @@ -0,0 +1,221 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Net; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Region.ClientStack; +using OpenSim.Region.Communications.Local; +using OpenSim.Region.Environment; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.Physics.Manager; + +namespace SimpleApp +{ + internal class Program : RegionApplicationBase, conscmd_callback + { + private ModuleLoader m_moduleLoader; + private IConfigSource m_config = null; + + private string m_userPlugin = "OpenSim.Framework.Data.SQLite.dll"; + private string m_inventoryPlugin = "OpenSim.Framework.Data.SQLite.dll"; + + protected override ConsoleBase CreateConsole() + { + return new ConsoleBase("SimpleApp", this); + } + + protected override void Initialize() + { + m_networkServersInfo = new NetworkServersInfo(1000, 1000); + + m_httpServerPort = m_networkServersInfo.HttpListenerPort; + + LocalAssetServer assetServer = new LocalAssetServer(); + + m_assetCache = new AssetCache(assetServer); + } + + public void Run() + { + StartConsole(); + StartUp(); + + LocalInventoryService inventoryService = new LocalInventoryService(); + inventoryService.AddPlugin(m_inventoryPlugin); + + LocalUserServices userService = + new LocalUserServices(m_networkServersInfo, m_networkServersInfo.DefaultHomeLocX, + m_networkServersInfo.DefaultHomeLocY, inventoryService); + userService.AddPlugin(m_userPlugin); + + LocalBackEndServices backendService = new LocalBackEndServices(); + + CommunicationsLocal localComms = + new CommunicationsLocal(m_networkServersInfo, m_httpServer, m_assetCache, userService, inventoryService, + backendService, backendService, false); + m_commsManager = localComms; + + LocalLoginService loginService = + new LocalLoginService( + userService, String.Empty, localComms, m_networkServersInfo, false); + loginService.OnLoginToRegion += backendService.AddNewSession; + + m_httpServer.AddXmlRPCHandler("login_to_simulator", loginService.XmlRpcLoginMethod); + + m_console.Notice(m_console.LineInfo); + + IPEndPoint internalEndPoint = + new IPEndPoint(IPAddress.Parse("127.0.0.1"), (int) m_networkServersInfo.HttpListenerPort); + + RegionInfo regionInfo = new RegionInfo(1000, 1000, internalEndPoint, "localhost"); + regionInfo.DataStore = "simpleapp_datastore.yap"; + + UDPServer udpServer; + + m_moduleLoader = new ModuleLoader(m_config); + m_moduleLoader.LoadDefaultSharedModules(); + + Scene scene = SetupScene(regionInfo, out udpServer, false); + + m_moduleLoader.InitialiseSharedModules(scene); + + scene.SetModuleInterfaces(); + + scene.StartTimer(); + + m_sceneManager.Add(scene); + + m_moduleLoader.PostInitialise(); + m_moduleLoader.ClearCache(); + + udpServer.ServerListener(); + + LLVector3 pos = new LLVector3(110, 129, 27); + + SceneObjectGroup sceneObject = + new CpuCounterObject(scene, regionInfo.RegionHandle, LLUUID.Zero, scene.PrimIDAllocate(), + pos + new LLVector3(1f, 1f, 1f)); + scene.AddEntity(sceneObject); + + for (int i = 0; i < 27; i++) + { + LLVector3 posOffset = new LLVector3((i%3)*4, (i%9)/3*4, (i/9)*4); + ComplexObject complexObject = + new ComplexObject(scene, regionInfo.RegionHandle, LLUUID.Zero, scene.PrimIDAllocate(), + pos + posOffset); + scene.AddEntity(complexObject); + } + + for (int i = 0; i < 2; i++) + { + MyNpcCharacter m_character = new MyNpcCharacter(scene.EventManager); + scene.AddNewClient(m_character, false); + } + + List avatars = scene.GetAvatars(); + foreach (ScenePresence avatar in avatars) + { + avatar.AbsolutePosition = + new LLVector3((float) Util.RandomClass.Next(100, 200), (float) Util.RandomClass.Next(30, 200), 2); + } + + DirectoryInfo dirInfo = new DirectoryInfo("."); + + float x = 0; + float z = 0; + + foreach (FileInfo fileInfo in dirInfo.GetFiles()) + { + LLVector3 filePos = new LLVector3(100 + x, 129, 27 + z); + x = x + 2; + if (x > 50) + { + x = 0; + z = z + 2; + } + + FileSystemObject fileObject = new FileSystemObject(scene, fileInfo, filePos); + scene.AddEntity(fileObject); + } + + m_console.Notice("Press enter to quit."); + m_console.ReadLine(); + } + + protected override Scene CreateScene(RegionInfo regionInfo, StorageManager storageManager, + AgentCircuitManager circuitManager) + { + PermissionManager permissionManager = new PermissionManager(); + SceneCommunicationService sceneGridService = new SceneCommunicationService(m_commsManager); + return + new MyWorld(regionInfo, circuitManager, permissionManager, m_commsManager, sceneGridService, + m_assetCache, storageManager, m_httpServer, + new ModuleLoader(m_config), true, false); + } + + protected override StorageManager CreateStorageManager(string connectionstring) + { + return new StorageManager("OpenSim.DataStore.NullStorage.dll", "simpleapp.yap", false); + } + + protected override PhysicsScene GetPhysicsScene() + { + return GetPhysicsScene("basicphysics", "Meshmerizer"); + } + + #region conscmd_callback Members + + public void RunCmd(string cmd, string[] cmdparams) + { + throw new Exception("The method or operation is not implemented."); + } + + public void Show(string ShowWhat) + { + throw new Exception("The method or operation is not implemented."); + } + + #endregion + + private static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + Program app = new Program(); + + app.Run(); + } + } +} diff --git a/trunk/OpenSim/Region/Examples/SimpleApp/Properties/AssemblyInfo.cs b/trunk/OpenSim/Region/Examples/SimpleApp/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..564dfeea5e --- /dev/null +++ b/trunk/OpenSim/Region/Examples/SimpleApp/Properties/AssemblyInfo.cs @@ -0,0 +1,64 @@ +/* +* 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("SimpleApp")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("OpenSimulator.org")] +[assembly : AssemblyProduct("SimpleApp")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator Developers 2007-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("a5cfa45f-5acf-4b2e-9c50-1dd1fd7608ee")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/CSharp/CSharpScriptEngine.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/CSharp/CSharpScriptEngine.cs new file mode 100644 index 0000000000..03d478ffa6 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/CSharp/CSharpScriptEngine.cs @@ -0,0 +1,106 @@ +/* +* 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; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using Microsoft.CSharp; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.ExtensionsScriptModule.CSharp +{ + public class CSharpScriptEngine : IScriptCompiler + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public string FileExt() + { + return ".cs"; + } + + private Dictionary LoadDotNetScript(CodeDomProvider compiler, string filename) + { + CompilerParameters compilerParams = new CompilerParameters(); + CompilerResults compilerResults; + compilerParams.GenerateExecutable = false; + compilerParams.GenerateInMemory = true; + compilerParams.IncludeDebugInformation = false; + compilerParams.ReferencedAssemblies.Add("OpenSim.Region.ClientStack.dll"); + compilerParams.ReferencedAssemblies.Add("OpenSim.Region.Environment.dll"); + compilerParams.ReferencedAssemblies.Add("OpenSim.Region.ExtensionsScriptModule.dll"); + compilerParams.ReferencedAssemblies.Add("OpenSim.Framework.dll"); + compilerParams.ReferencedAssemblies.Add("libsecondlife.dll"); + compilerParams.ReferencedAssemblies.Add("System.dll"); + + compilerResults = compiler.CompileAssemblyFromFile(compilerParams, filename); + + if (compilerResults.Errors.Count > 0) + { + m_log.Error("Compile errors"); + foreach (CompilerError error in compilerResults.Errors) + { + m_log.Error(error.Line.ToString() + ": " + error.ErrorText.ToString()); + } + } + else + { + Dictionary scripts = new Dictionary(); + + foreach (Type pluginType in compilerResults.CompiledAssembly.GetExportedTypes()) + { + Type testInterface = pluginType.GetInterface("IScript", true); + + if (testInterface != null) + { + IScript script = + (IScript) compilerResults.CompiledAssembly.CreateInstance(pluginType.ToString()); + + string scriptName = "C#/" + script.Name; + Console.WriteLine("Script: " + scriptName + " loaded."); + + if (!scripts.ContainsKey(scriptName)) + { + scripts.Add(scriptName, script); + } + else + { + scripts[scriptName] = script; + } + } + } + return scripts; + } + return null; + } + + public Dictionary compile(string filename) + { + CSharpCodeProvider csharpProvider = new CSharpCodeProvider(); + return LoadDotNetScript(csharpProvider, filename); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/CSharp/Examples/ExportRegionToLSL.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/CSharp/Examples/ExportRegionToLSL.cs new file mode 100644 index 0000000000..6b1f29149e --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/CSharp/Examples/ExportRegionToLSL.cs @@ -0,0 +1,94 @@ +/* +* 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 OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.ExtensionsScriptModule.CSharp.Examples +{ + public class LSLExportScript : IScript + { + private ScriptInfo script; + + public string Name + { + get { return "LSL Export Script 0.1"; } + } + + public void Initialise(ScriptInfo scriptInfo) + { + script = scriptInfo; + + script.events.OnPluginConsole += new EventManager.OnPluginConsoleDelegate(ProcessConsoleMsg); + } + + private void ProcessConsoleMsg(string[] args) + { + /*if (args[0].ToLower() == "lslexport") + { + string sequence = String.Empty; + + foreach (KeyValuePair obj in script.world.Objects) + { + SceneObject root = obj.Value; + + sequence += "NEWOBJ::" + obj.Key.ToString() + "\n"; + + string rootPrim = processPrimitiveToString(root.rootPrimitive); + + sequence += "ROOT:" + rootPrim; + + foreach (KeyValuePair prim in root.Children) + { + string child = processPrimitiveToString(prim.Value); + sequence += "CHILD:" + child; + } + } + + System.Console.WriteLine(sequence); + }*/ + } + + private string processPrimitiveToString(SceneObjectPart prim) + { + /*string desc = prim.Description; + string name = prim.Name; + LLVector3 pos = prim.Pos; + LLQuaternion rot = new LLQuaternion(prim.Rotation.x, prim.Rotation.y, prim.Rotation.z, prim.Rotation.w); + LLVector3 scale = prim.Scale; + LLVector3 rootPos = prim.WorldPos; + + string setPrimParams = String.Empty; + + setPrimParams += "[PRIM_SCALE, " + scale.ToString() + ", PRIM_POS, " + rootPos.ToString() + ", PRIM_ROTATION, " + rot.ToString() + "]\n"; + + return setPrimParams; + */ + return System.String.Empty; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JScript/JScriptEngine.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JScript/JScriptEngine.cs new file mode 100644 index 0000000000..dbe0dca5c9 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JScript/JScriptEngine.cs @@ -0,0 +1,106 @@ +/* +* 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; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using Microsoft.JScript; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.ExtensionsScriptModule.JScript +{ + public class JScriptEngine : IScriptCompiler + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public string FileExt() + { + return ".js"; + } + + private Dictionary LoadDotNetScript(CodeDomProvider compiler, string filename) + { + CompilerParameters compilerParams = new CompilerParameters(); + CompilerResults compilerResults; + compilerParams.GenerateExecutable = false; + compilerParams.GenerateInMemory = true; + compilerParams.IncludeDebugInformation = false; + compilerParams.ReferencedAssemblies.Add("OpenSim.Region.ClientStack.dll"); + compilerParams.ReferencedAssemblies.Add("OpenSim.Region.Environment.dll"); + compilerParams.ReferencedAssemblies.Add("OpenSim.Region.ExtensionsScriptModule.dll"); + compilerParams.ReferencedAssemblies.Add("OpenSim.Framework.dll"); + compilerParams.ReferencedAssemblies.Add("libsecondlife.dll"); + compilerParams.ReferencedAssemblies.Add("System.dll"); + + compilerResults = compiler.CompileAssemblyFromFile(compilerParams, filename); + + if (compilerResults.Errors.Count > 0) + { + m_log.Error("Compile errors"); + foreach (CompilerError error in compilerResults.Errors) + { + m_log.Error(error.Line.ToString() + ": " + error.ErrorText.ToString()); + } + } + else + { + Dictionary scripts = new Dictionary(); + + foreach (Type pluginType in compilerResults.CompiledAssembly.GetExportedTypes()) + { + Type testInterface = pluginType.GetInterface("IScript", true); + + if (testInterface != null) + { + IScript script = + (IScript) compilerResults.CompiledAssembly.CreateInstance(pluginType.ToString()); + + string scriptName = "JS.NET/" + script.Name; + Console.WriteLine("Script: " + scriptName + " loaded."); + + if (!scripts.ContainsKey(scriptName)) + { + scripts.Add(scriptName, script); + } + else + { + scripts[scriptName] = script; + } + } + } + return scripts; + } + return null; + } + + public Dictionary compile(string filename) + { + JScriptCodeProvider jscriptProvider = new JScriptCodeProvider(); + return LoadDotNetScript(jscriptProvider, filename); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/ClassInstance.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/ClassInstance.cs new file mode 100644 index 0000000000..c12fda5728 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/ClassInstance.cs @@ -0,0 +1,43 @@ +/* +* 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.Collections.Generic; +using OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types; + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + public class ClassInstance : Object + { + public int Size; + public ClassRecord ClassRec; + public Dictionary Fields = new Dictionary(); + + public ClassInstance() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/ClassRecord.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/ClassRecord.cs new file mode 100644 index 0000000000..3e5ae5a797 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/ClassRecord.cs @@ -0,0 +1,648 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types; +using OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types.PrimitiveTypes; + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + public class ClassRecord + { + private ushort m_majorVersion; + private ushort m_minorVersion; + private ushort m_constantPoolCount; + private ushort m_accessFlags; + private ushort m_thisClass; + private ushort m_supperClass; + private ushort m_interfaceCount; + private ushort m_fieldCount; + private ushort m_methodCount; + //private ushort _attributeCount; + //private string _name; + public Dictionary StaticFields = new Dictionary(); + public PoolClass MClass; + + public List m_constantsPool = new List(); + private List m_methodsList = new List(); + private List m_fieldList = new List(); + + public ClassRecord() + { + } + + public ClassInstance CreateNewInstance() + { + ClassInstance classInst = new ClassInstance(); + classInst.ClassRec = this; + //TODO: set fields + + return classInst; + } + + public void LoadClassFromFile(string fileName) + { + Console.WriteLine("loading script " + fileName); + FileStream fs = File.OpenRead(fileName); + LoadClassFromBytes(ReadFully(fs)); + fs.Close(); + } + + public void LoadClassFromBytes(byte[] data) + { + int i = 0; + i += 4; + m_minorVersion = (ushort) ((data[i++] << 8) + data[i++]); + m_majorVersion = (ushort) ((data[i++] << 8) + data[i++]); + m_constantPoolCount = (ushort) ((data[i++] << 8) + data[i++]); + Console.WriteLine("there should be " + m_constantPoolCount + " items in the pool"); + for (int count = 0; count < (m_constantPoolCount - 1); count++) + { + //read in the constant pool + byte pooltype = data[i++]; + Console.WriteLine("#" + count + ": new constant type = " + pooltype); + //Console.WriteLine("start position is: " + i); + switch (pooltype) + { + case 1: //Utf8 + ushort uLength = (ushort) ((data[i++] << 8) + data[i++]); + + // Console.WriteLine("new utf8 type, length is " + uLength); + PoolUtf8 utf8 = new PoolUtf8(); + utf8.readValue(data, ref i, uLength); + m_constantsPool.Add(utf8); + break; + case 3: //Int + break; + case 4: //Float + break; + case 7: //Class + PoolClass pClass = new PoolClass(this); + pClass.readValue(data, ref i); + m_constantsPool.Add(pClass); + break; + case 9: //FieldRef + PoolFieldRef pField = new PoolFieldRef(this); + pField.readValue(data, ref i); + m_constantsPool.Add(pField); + break; + case 10: //Method + PoolMethodRef pMeth = new PoolMethodRef(this); + pMeth.readValue(data, ref i); + m_constantsPool.Add(pMeth); + break; + case 12: //NamedType + PoolNamedType pNamed = new PoolNamedType(this); + pNamed.readValue(data, ref i); + m_constantsPool.Add(pNamed); + break; + } + } + + m_accessFlags = (ushort) ((data[i++] << 8) + data[i++]); + m_thisClass = (ushort) ((data[i++] << 8) + data[i++]); + m_supperClass = (ushort) ((data[i++] << 8) + data[i++]); + + if (m_constantsPool[m_thisClass - 1] is PoolClass) + { + MClass = ((PoolClass) m_constantsPool[m_thisClass - 1]); + } + + m_interfaceCount = (ushort) ((data[i++] << 8) + data[i++]); + //should now read in the info for each interface + + m_fieldCount = (ushort) ((data[i++] << 8) + data[i++]); + //should now read in the info for each field + for (int count = 0; count < m_fieldCount; count++) + { + FieldInfo fieldInf = new FieldInfo(this); + fieldInf.ReadData(data, ref i); + m_fieldList.Add(fieldInf); + } + + m_methodCount = (ushort) ((data[i++] << 8) + data[i++]); + for (int count = 0; count < m_methodCount; count++) + { + MethodInfo methInf = new MethodInfo(this); + methInf.ReadData(data, ref i); + m_methodsList.Add(methInf); + } + } + + public void AddMethodsToMemory(MethodMemory memory) + { + for (int count = 0; count < m_methodCount; count++) + { + m_methodsList[count].AddMethodCode(memory); + } + } + + public bool StartMethod(Thread thread, string methodName) + { + for (int count = 0; count < m_methodCount; count++) + { + if (m_constantsPool[m_methodsList[count].NameIndex - 1] is PoolUtf8) + { + if (((PoolUtf8) m_constantsPool[m_methodsList[count].NameIndex - 1]).Value == methodName) + { + //Console.WriteLine("found method: " + ((PoolUtf8)this._constantsPool[this._methodsList[count].NameIndex - 1]).Value); + thread.SetPC(m_methodsList[count].CodePointer); + return true; + } + } + } + return false; + } + + public void PrintToConsole() + { + Console.WriteLine("Class File:"); + Console.WriteLine("Major version: " + m_majorVersion); + Console.WriteLine("Minor version: " + m_minorVersion); + Console.WriteLine("Pool size: " + m_constantPoolCount); + + for (int i = 0; i < m_constantsPool.Count; i++) + { + m_constantsPool[i].Print(); + } + + Console.WriteLine("Access flags: " + m_accessFlags); + Console.WriteLine("This class: " + m_thisClass); + Console.WriteLine("Super class: " + m_supperClass); + + for (int count = 0; count < m_fieldCount; count++) + { + Console.WriteLine(); + m_fieldList[count].Print(); + } + + for (int count = 0; count < m_methodCount; count++) + { + Console.WriteLine(); + m_methodsList[count].Print(); + } + + Console.WriteLine("class name is " + MClass.Name.Value); + } + + public static byte[] ReadFully(Stream stream) + { + byte[] buffer = new byte[1024]; + using (MemoryStream ms = new MemoryStream()) + { + while (true) + { + int read = stream.Read(buffer, 0, buffer.Length); + if (read <= 0) + return ms.ToArray(); + ms.Write(buffer, 0, read); + } + } + } + + #region nested classes + + public class PoolItem + { + public virtual void Print() + { + } + } + + public class PoolUtf8 : PoolItem + { + public string Value = String.Empty; + + public void readValue(byte[] data, ref int pointer, int length) + { + for (int i = 0; i < length; i++) + { + int a = (int) data[pointer++]; + if ((a & 0x80) == 0) + { + Value = Value + (char) a; + } + else if ((a & 0x20) == 0) + { + int b = (int) data[pointer++]; + Value = Value + (char) (((a & 0x1f) << 6) + (b & 0x3f)); + } + else + { + int b = (int) data[pointer++]; + int c = (int) data[pointer++]; + Value = Value + (char) (((a & 0xf) << 12) + ((b & 0x3f) << 6) + (c & 0x3f)); + } + } + } + + public override void Print() + { + Console.WriteLine("Utf8 type: " + Value); + } + } + + private class PoolInt : PoolItem + { + } + + public class PoolClass : PoolItem + { + //public string name = String.Empty; + public ushort namePointer = 0; + private ClassRecord parent; + public PoolUtf8 Name; + + public PoolClass(ClassRecord paren) + { + parent = paren; + } + + public void readValue(byte[] data, ref int pointer) + { + namePointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); + } + + public override void Print() + { + Name = ((PoolUtf8) parent.m_constantsPool[namePointer - 1]); + Console.Write("Class type: " + namePointer); + Console.WriteLine(" // " + ((PoolUtf8) parent.m_constantsPool[namePointer - 1]).Value); + } + } + + public class PoolFieldRef : PoolItem + { + public ushort classPointer = 0; + public ushort nameTypePointer = 0; + public PoolNamedType mNameType; + public PoolClass mClass; + private ClassRecord parent; + + public PoolFieldRef(ClassRecord paren) + { + parent = paren; + } + + public void readValue(byte[] data, ref int pointer) + { + classPointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); + nameTypePointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); + } + + public override void Print() + { + mNameType = ((PoolNamedType) parent.m_constantsPool[nameTypePointer - 1]); + mClass = ((PoolClass) parent.m_constantsPool[classPointer - 1]); + Console.WriteLine("FieldRef type: " + classPointer + " , " + nameTypePointer); + } + } + + public class PoolMethodRef : PoolItem + { + public ushort classPointer = 0; + public ushort nameTypePointer = 0; + public PoolNamedType mNameType; + public PoolClass mClass; + private ClassRecord parent; + + public PoolMethodRef(ClassRecord paren) + { + parent = paren; + } + + public void readValue(byte[] data, ref int pointer) + { + classPointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); + nameTypePointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); + } + + public override void Print() + { + mNameType = ((PoolNamedType) parent.m_constantsPool[nameTypePointer - 1]); + mClass = ((PoolClass) parent.m_constantsPool[classPointer - 1]); + Console.WriteLine("MethodRef type: " + classPointer + " , " + nameTypePointer); + } + } + + public class PoolNamedType : PoolItem + { + public ushort namePointer = 0; + public ushort typePointer = 0; + private ClassRecord parent; + public PoolUtf8 Name; + public PoolUtf8 Type; + + public PoolNamedType(ClassRecord paren) + { + parent = paren; + } + + public void readValue(byte[] data, ref int pointer) + { + namePointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); + typePointer = (ushort) ((data[pointer++] << 8) + data[pointer++]); + } + + public override void Print() + { + Name = ((PoolUtf8) parent.m_constantsPool[namePointer - 1]); + Type = ((PoolUtf8) parent.m_constantsPool[typePointer - 1]); + Console.Write("Named type: " + namePointer + " , " + typePointer); + Console.WriteLine(" // " + ((PoolUtf8) parent.m_constantsPool[namePointer - 1]).Value); + } + } + + //*********************** + public class MethodInfo + { + public ushort AccessFlags = 0; + public ushort NameIndex = 0; + public string Name = String.Empty; + public ushort DescriptorIndex = 0; + public ushort AttributeCount = 0; + public List Attributes = new List(); + private ClassRecord parent; + public int CodePointer = 0; + + public MethodInfo(ClassRecord paren) + { + parent = paren; + } + + public void AddMethodCode(MethodMemory memory) + { + Array.Copy(Attributes[0].Code, 0, memory.MethodBuffer, memory.NextMethodPC, Attributes[0].Code.Length); + memory.Methodcount++; + CodePointer = memory.NextMethodPC; + memory.NextMethodPC += Attributes[0].Code.Length; + } + + public void ReadData(byte[] data, ref int pointer) + { + AccessFlags = (ushort) ((data[pointer++] << 8) + data[pointer++]); + NameIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); + DescriptorIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); + AttributeCount = (ushort) ((data[pointer++] << 8) + data[pointer++]); + for (int i = 0; i < AttributeCount; i++) + { + MethodAttribute attri = new MethodAttribute(parent); + attri.ReadData(data, ref pointer); + Attributes.Add(attri); + } + } + + public void Print() + { + Console.WriteLine("Method Info Struct: "); + Console.WriteLine("AccessFlags: " + AccessFlags); + Console.WriteLine("NameIndex: " + NameIndex + " // " + + ((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value); + Console.WriteLine("DescriptorIndex: " + DescriptorIndex + " // " + + ((PoolUtf8) parent.m_constantsPool[DescriptorIndex - 1]).Value); + Console.WriteLine("Attribute Count:" + AttributeCount); + for (int i = 0; i < AttributeCount; i++) + { + Attributes[i].Print(); + } + } + + public class MethodAttribute + { + public ushort NameIndex = 0; + public string Name = String.Empty; + public Int32 Length = 0; + //for now only support code attribute + public ushort MaxStack = 0; + public ushort MaxLocals = 0; + public Int32 CodeLength = 0; + public byte[] Code; + public ushort ExceptionTableLength = 0; + public ushort SubAttributeCount = 0; + public List SubAttributes = new List(); + private ClassRecord parent; + + public MethodAttribute(ClassRecord paren) + { + parent = paren; + } + + public void ReadData(byte[] data, ref int pointer) + { + NameIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); + Length = + (Int32) + ((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]); + MaxStack = (ushort) ((data[pointer++] << 8) + data[pointer++]); + MaxLocals = (ushort) ((data[pointer++] << 8) + data[pointer++]); + CodeLength = + (Int32) + ((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]); + Code = new byte[CodeLength]; + for (int i = 0; i < CodeLength; i++) + { + Code[i] = data[pointer++]; + } + ExceptionTableLength = (ushort) ((data[pointer++] << 8) + data[pointer++]); + SubAttributeCount = (ushort) ((data[pointer++] << 8) + data[pointer++]); + for (int i = 0; i < SubAttributeCount; i++) + { + SubAttribute subAttri = new SubAttribute(parent); + subAttri.ReadData(data, ref pointer); + SubAttributes.Add(subAttri); + } + } + + public void Print() + { + Console.WriteLine("Method Attribute: "); + Console.WriteLine("Name Index: " + NameIndex + " // " + + ((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value); + Console.WriteLine("Length: " + Length); + Console.WriteLine("MaxStack: " + MaxStack); + Console.WriteLine("MaxLocals: " + MaxLocals); + Console.WriteLine("CodeLength: " + CodeLength); + for (int i = 0; i < Code.Length; i++) + { + Console.WriteLine("OpCode #" + i + " is: " + Code[i]); + } + Console.WriteLine("SubAttributes: " + SubAttributeCount); + for (int i = 0; i < SubAttributeCount; i++) + { + SubAttributes[i].Print(); + } + } + + public class SubAttribute + { + public ushort NameIndex = 0; + public string Name = String.Empty; + public Int32 Length = 0; + public byte[] Data; + private ClassRecord parent; + + public SubAttribute(ClassRecord paren) + { + parent = paren; + } + + public void ReadData(byte[] data, ref int pointer) + { + NameIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); + Length = + (Int32) + ((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + + data[pointer++]); + Data = new byte[Length]; + for (int i = 0; i < Length; i++) + { + Data[i] = data[pointer++]; + } + } + + public void Print() + { + Console.WriteLine("SubAttribute: NameIndex: " + NameIndex + " // " + + ((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value); + } + } + } + } + + private class InterfaceInfo + { + public void ReadData(byte[] data, ref int i) + { + } + } + + public class FieldInfo + { + public ushort AccessFlags = 0; + public ushort NameIndex = 0; + public string Name = String.Empty; + public ushort DescriptorIndex = 0; + public ushort AttributeCount = 0; + public List Attributes = new List(); + private ClassRecord parent; + + public FieldInfo(ClassRecord paren) + { + parent = paren; + } + + public void ReadData(byte[] data, ref int pointer) + { + AccessFlags = (ushort) ((data[pointer++] << 8) + data[pointer++]); + NameIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); + DescriptorIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); + AttributeCount = (ushort) ((data[pointer++] << 8) + data[pointer++]); + for (int i = 0; i < AttributeCount; i++) + { + FieldAttribute attri = new FieldAttribute(parent); + attri.ReadData(data, ref pointer); + Attributes.Add(attri); + } + } + + public void Print() + { + Console.WriteLine("Field Info Struct: "); + Console.WriteLine("AccessFlags: " + AccessFlags); + Console.WriteLine("NameIndex: " + NameIndex + " // " + + ((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value); + Console.WriteLine("DescriptorIndex: " + DescriptorIndex + " // " + + ((PoolUtf8) parent.m_constantsPool[DescriptorIndex - 1]).Value); + Console.WriteLine("Attribute Count:" + AttributeCount); + //if static, add to static field list + // if (this.AccessFlags == 9) //public and static + if ((AccessFlags & 0x08) != 0) + { + switch (((PoolUtf8) parent.m_constantsPool[DescriptorIndex - 1]).Value) + { + case "I": + Int newin = new Int(); + parent.StaticFields.Add(((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value, newin); + break; + case "F": + Float newfl = new Float(); + parent.StaticFields.Add(((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value, newfl); + break; + } + } + for (int i = 0; i < AttributeCount; i++) + { + Attributes[i].Print(); + } + } + + public class FieldAttribute + { + public ushort NameIndex = 0; + public string Name = String.Empty; + public Int32 Length = 0; + public byte[] Data; + private ClassRecord parent; + + public FieldAttribute(ClassRecord paren) + { + parent = paren; + } + + public void ReadData(byte[] data, ref int pointer) + { + NameIndex = (ushort) ((data[pointer++] << 8) + data[pointer++]); + Length = + (Int32) + ((data[pointer++] << 24) + (data[pointer++] << 16) + (data[pointer++] << 8) + data[pointer++]); + Data = new byte[Length]; + for (int i = 0; i < Length; i++) + { + Data[i] = data[pointer++]; + } + } + + public void Print() + { + Console.WriteLine("FieldAttribute: NameIndex: " + NameIndex + " // " + + ((PoolUtf8) parent.m_constantsPool[NameIndex - 1]).Value); + } + } + } + + private class AttributeInfo + { + public void ReadData(byte[] data, ref int i) + { + } + } + + #endregion + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Heap.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Heap.cs new file mode 100644 index 0000000000..4308a1962f --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Heap.cs @@ -0,0 +1,40 @@ +/* +* 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.Collections.Generic; + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + public class Heap + { + public List ClassObjects = new List(); + + public Heap() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.Logic.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.Logic.cs new file mode 100644 index 0000000000..d9f5ce12e1 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.Logic.cs @@ -0,0 +1,619 @@ +/* +* 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 OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types; +using OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types.PrimitiveTypes; + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + partial class Thread + { + private partial class Interpreter + { + private bool IsLogicOpCode(byte opcode) + { + bool result = false; + switch (opcode) + { + case (byte) (byte) OpCode.iconst_m1: + Int m_int = new Int(); + m_int.mValue = -1; + m_thread.m_currentFrame.OpStack.Push(m_int); + result = true; + break; + case (byte) (byte) OpCode.iconst_0: + m_int = new Int(); + m_int.mValue = 0; + m_thread.m_currentFrame.OpStack.Push(m_int); + result = true; + break; + case (byte) (byte) OpCode.iconst_1: + m_int = new Int(); + m_int.mValue = 1; + m_thread.m_currentFrame.OpStack.Push(m_int); + result = true; + break; + case (byte) (byte) OpCode.iconst_2: + m_int = new Int(); + m_int.mValue = 2; + m_thread.m_currentFrame.OpStack.Push(m_int); + result = true; + break; + case (byte) (byte) OpCode.iconst_3: + m_int = new Int(); + m_int.mValue = 3; + m_thread.m_currentFrame.OpStack.Push(m_int); + break; + case (byte) (byte) OpCode.iconst_4: + m_int = new Int(); + m_int.mValue = 4; + m_thread.m_currentFrame.OpStack.Push(m_int); + result = true; + break; + case (byte) OpCode.iconst_5: + m_int = new Int(); + m_int.mValue = 5; + m_thread.m_currentFrame.OpStack.Push(m_int); + result = true; + break; + case (byte) OpCode.fconst_0: + Float m_float = new Float(); + m_float.mValue = 0.0f; + m_thread.m_currentFrame.OpStack.Push(m_float); + result = true; + break; + case (byte) OpCode.fconst_1: + m_float = new Float(); + m_float.mValue = 1.0f; + m_thread.m_currentFrame.OpStack.Push(m_float); + result = true; + break; + case (byte) OpCode.fconst_2: + m_float = new Float(); + m_float.mValue = 2.0f; + m_thread.m_currentFrame.OpStack.Push(m_float); + result = true; + break; + case (byte) OpCode.bipush: //is this right? this should be pushing a byte onto stack not int? + int pushvalue = (int) GlobalMemory.MethodArea.MethodBuffer[m_thread.PC]; + Int pushInt = new Int(); + pushInt.mValue = pushvalue; + m_thread.m_currentFrame.OpStack.Push(pushInt); + m_thread.PC++; + result = true; + break; + case (byte) OpCode.sipush: + short pushvalue2 = + (short) + ((GlobalMemory.MethodArea.MethodBuffer[m_thread.PC] << 8) + + GlobalMemory.MethodArea.MethodBuffer[m_thread.PC + 1]); + Int pushInt2 = new Int(); + pushInt2.mValue = pushvalue2; + m_thread.m_currentFrame.OpStack.Push(pushInt2); + m_thread.PC += 2; + result = true; + break; + case (byte) OpCode.fload: + short findex1 = (short) ((GlobalMemory.MethodArea.MethodBuffer[m_thread.PC])); + Float fload = new Float(); + if (m_thread.m_currentFrame.LocalVariables[findex1] != null) + { + if (m_thread.m_currentFrame.LocalVariables[findex1] is Float) + { + fload.mValue = ((Float) m_thread.m_currentFrame.LocalVariables[findex1]).mValue; + m_thread.m_currentFrame.OpStack.Push(fload); + } + } + m_thread.PC++; + result = true; + break; + case (byte) OpCode.iload_0: + if (m_thread.m_currentFrame.LocalVariables[0] != null) + { + if (m_thread.m_currentFrame.LocalVariables[0] is Int) + { + Int newInt = new Int(); + newInt.mValue = ((Int) m_thread.m_currentFrame.LocalVariables[0]).mValue; + m_thread.m_currentFrame.OpStack.Push(newInt); + } + } + result = true; + break; + case (byte) OpCode.iload_1: + if (m_thread.m_currentFrame.LocalVariables[1] != null) + { + if (m_thread.m_currentFrame.LocalVariables[1] is Int) + { + Int newInt = new Int(); + newInt.mValue = ((Int) m_thread.m_currentFrame.LocalVariables[1]).mValue; + m_thread.m_currentFrame.OpStack.Push(newInt); + } + } + result = true; + break; + case (byte) OpCode.fload_0: + if (m_thread.m_currentFrame.LocalVariables[0] != null) + { + if (m_thread.m_currentFrame.LocalVariables[0] is Float) + { + Float newfloat = new Float(); + newfloat.mValue = ((Float) m_thread.m_currentFrame.LocalVariables[0]).mValue; + m_thread.m_currentFrame.OpStack.Push(newfloat); + } + } + result = true; + break; + case (byte) OpCode.fload_1: + if (m_thread.m_currentFrame.LocalVariables[1] != null) + { + if (m_thread.m_currentFrame.LocalVariables[1] is Float) + { + Float newfloat = new Float(); + newfloat.mValue = ((Float) m_thread.m_currentFrame.LocalVariables[1]).mValue; + m_thread.m_currentFrame.OpStack.Push(newfloat); + } + } + result = true; + break; + case (byte) OpCode.fload_2: + if (m_thread.m_currentFrame.LocalVariables[2] != null) + { + if (m_thread.m_currentFrame.LocalVariables[2] is Float) + { + Float newfloat = new Float(); + newfloat.mValue = ((Float) m_thread.m_currentFrame.LocalVariables[2]).mValue; + m_thread.m_currentFrame.OpStack.Push(newfloat); + } + } + result = true; + break; + case (byte) OpCode.fload_3: + if (m_thread.m_currentFrame.LocalVariables[3] != null) + { + if (m_thread.m_currentFrame.LocalVariables[3] is Float) + { + Float newfloat = new Float(); + newfloat.mValue = ((Float) m_thread.m_currentFrame.LocalVariables[3]).mValue; + m_thread.m_currentFrame.OpStack.Push(newfloat); + } + } + result = true; + break; + case (byte) OpCode.istore: + short findex3 = (short) ((GlobalMemory.MethodArea.MethodBuffer[m_thread.PC])); + BaseType istor = m_thread.m_currentFrame.OpStack.Pop(); + if (istor is Int) + { + m_thread.m_currentFrame.LocalVariables[findex3] = (Int) istor; + } + m_thread.PC++; + result = true; + break; + case (byte) OpCode.fstore: + short findex = (short) ((GlobalMemory.MethodArea.MethodBuffer[m_thread.PC])); + BaseType fstor = m_thread.m_currentFrame.OpStack.Pop(); + if (fstor is Float) + { + m_thread.m_currentFrame.LocalVariables[findex] = (Float) fstor; + } + m_thread.PC++; + result = true; + break; + case (byte) OpCode.istore_0: + BaseType baset = m_thread.m_currentFrame.OpStack.Pop(); + if (baset is Int) + { + m_thread.m_currentFrame.LocalVariables[0] = (Int) baset; + } + result = true; + break; + case (byte) OpCode.istore_1: + baset = m_thread.m_currentFrame.OpStack.Pop(); + if (baset is Int) + { + m_thread.m_currentFrame.LocalVariables[1] = (Int) baset; + } + result = true; + break; + case (byte) OpCode.fstore_0: + baset = m_thread.m_currentFrame.OpStack.Pop(); + if (baset is Float) + { + m_thread.m_currentFrame.LocalVariables[0] = (Float) baset; + } + result = true; + break; + case (byte) OpCode.fstore_1: + baset = m_thread.m_currentFrame.OpStack.Pop(); + if (baset is Float) + { + m_thread.m_currentFrame.LocalVariables[1] = (Float) baset; + } + result = true; + break; + case (byte) OpCode.fstore_2: + baset = m_thread.m_currentFrame.OpStack.Pop(); + if (baset is Float) + { + m_thread.m_currentFrame.LocalVariables[2] = (Float) baset; + } + result = true; + break; + case (byte) OpCode.fstore_3: + baset = m_thread.m_currentFrame.OpStack.Pop(); + if (baset is Float) + { + m_thread.m_currentFrame.LocalVariables[3] = (Float) baset; + } + result = true; + break; + case (byte) OpCode.pop: + m_thread.m_currentFrame.OpStack.Pop(); + result = true; + break; + case (byte) OpCode.fadd: + BaseType bf2 = m_thread.m_currentFrame.OpStack.Pop(); + BaseType bf1 = m_thread.m_currentFrame.OpStack.Pop(); + if (bf1 is Float && bf2 is Float) + { + Float nflt = new Float(); + nflt.mValue = ((Float) bf1).mValue + ((Float) bf2).mValue; + m_thread.m_currentFrame.OpStack.Push(nflt); + } + result = true; + break; + case (byte) OpCode.fsub: + BaseType bsf2 = m_thread.m_currentFrame.OpStack.Pop(); + BaseType bsf1 = m_thread.m_currentFrame.OpStack.Pop(); + if (bsf1 is Float && bsf2 is Float) + { + Float resf = new Float(); + resf.mValue = ((Float) bsf1).mValue - ((Float) bsf2).mValue; + m_thread.m_currentFrame.OpStack.Push(resf); + } + result = true; + break; + case (byte) OpCode.imul: //check the order of the two values off the stack is correct + BaseType bs2 = m_thread.m_currentFrame.OpStack.Pop(); + BaseType bs1 = m_thread.m_currentFrame.OpStack.Pop(); + if (bs1 is Int && bs2 is Int) + { + Int nInt = new Int(); + nInt.mValue = ((Int) bs1).mValue*((Int) bs2).mValue; + m_thread.m_currentFrame.OpStack.Push(nInt); + } + result = true; + break; + case (byte) OpCode.iinc: + if (m_thread.m_currentFrame.LocalVariables[GlobalMemory.MethodArea.MethodBuffer[m_thread.PC]] != + null) + { + if ( + m_thread.m_currentFrame.LocalVariables[GlobalMemory.MethodArea.MethodBuffer[m_thread.PC] + ] is Int) + { + ((Int) + m_thread.m_currentFrame.LocalVariables[ + GlobalMemory.MethodArea.MethodBuffer[m_thread.PC]]).mValue += + (sbyte) GlobalMemory.MethodArea.MethodBuffer[m_thread.PC + 1]; + } + } + m_thread.PC += 2; + result = true; + break; + case (byte) OpCode.f2i: + BaseType conv1 = m_thread.m_currentFrame.OpStack.Pop(); + if (conv1 is Float) + { + Int newconv = new Int(); + newconv.mValue = (int) ((Float) conv1).mValue; + m_thread.m_currentFrame.OpStack.Push(newconv); + } + result = true; + break; + case (byte) OpCode.fcmpl: + BaseType flcom2 = m_thread.m_currentFrame.OpStack.Pop(); + BaseType flcom1 = m_thread.m_currentFrame.OpStack.Pop(); + if (flcom1 is Float && flcom2 is Float) + { + Int compres = new Int(); + if (((Float) flcom1).mValue < ((Float) flcom2).mValue) + { + compres.mValue = -1; + } + else if (((Float) flcom1).mValue > ((Float) flcom2).mValue) + { + compres.mValue = 1; + } + else + { + compres.mValue = 0; + } + m_thread.m_currentFrame.OpStack.Push(compres); + } + result = true; + break; + case (byte) OpCode.fcmpg: + flcom2 = m_thread.m_currentFrame.OpStack.Pop(); + flcom1 = m_thread.m_currentFrame.OpStack.Pop(); + if (flcom1 is Float && flcom2 is Float) + { + Int compres = new Int(); + if (((Float) flcom1).mValue < ((Float) flcom2).mValue) + { + compres.mValue = -1; + } + else if (((Float) flcom1).mValue > ((Float) flcom2).mValue) + { + compres.mValue = 1; + } + else + { + compres.mValue = 0; + } + m_thread.m_currentFrame.OpStack.Push(compres); + } + result = true; + break; + case (byte) OpCode.ifge: + short compareoffset2 = + (short) + ((GlobalMemory.MethodArea.MethodBuffer[m_thread.PC] << 8) + + GlobalMemory.MethodArea.MethodBuffer[m_thread.PC + 1]); + BaseType compe1 = m_thread.m_currentFrame.OpStack.Pop(); + if (compe1 is Int) + { + if (((Int) compe1).mValue >= 0) + { + m_thread.PC += -1 + compareoffset2; + } + else + { + m_thread.PC += 2; + } + } + else + { + m_thread.PC += 2; + } + result = true; + break; + case (byte) OpCode.ifle: + short compareoffset1 = + (short) + ((GlobalMemory.MethodArea.MethodBuffer[m_thread.PC] << 8) + + GlobalMemory.MethodArea.MethodBuffer[m_thread.PC + 1]); + BaseType comp1 = m_thread.m_currentFrame.OpStack.Pop(); + if (comp1 is Int) + { + if (((Int) comp1).mValue <= 0) + { + m_thread.PC += -1 + compareoffset1; + } + else + { + m_thread.PC += 2; + } + } + else + { + m_thread.PC += 2; + } + result = true; + break; + case (byte) OpCode.if_icmpge: + short compareoffset = + (short) + ((GlobalMemory.MethodArea.MethodBuffer[m_thread.PC] << 8) + + GlobalMemory.MethodArea.MethodBuffer[m_thread.PC + 1]); + BaseType bc2 = m_thread.m_currentFrame.OpStack.Pop(); + BaseType bc1 = m_thread.m_currentFrame.OpStack.Pop(); + if (bc1 is Int && bc2 is Int) + { + //Console.WriteLine("comparing " + ((Int)bc1).mValue + " and " + ((Int)bc2).mValue); + if (((Int) bc1).mValue >= ((Int) bc2).mValue) + { + // Console.WriteLine("branch compare true , offset is " +compareoffset); + // Console.WriteLine("current PC is " + this._mThread.PC); + m_thread.PC += -1 + compareoffset; + //Console.WriteLine("new PC is " + this._mThread.PC); + } + else + { + //Console.WriteLine("branch compare false"); + m_thread.PC += 2; + } + } + else + { + m_thread.PC += 2; + } + result = true; + break; + case (byte) OpCode.if_icmple: + short compareloffset = + (short) + ((GlobalMemory.MethodArea.MethodBuffer[m_thread.PC] << 8) + + GlobalMemory.MethodArea.MethodBuffer[m_thread.PC + 1]); + BaseType bcl2 = m_thread.m_currentFrame.OpStack.Pop(); + BaseType bcl1 = m_thread.m_currentFrame.OpStack.Pop(); + if (bcl1 is Int && bcl2 is Int) + { + //Console.WriteLine("comparing " + ((Int)bcl1).mValue + " and " + ((Int)bcl2).mValue); + if (((Int) bcl1).mValue <= ((Int) bcl2).mValue) + { + // Console.WriteLine("branch compare true , offset is " + compareloffset); + // Console.WriteLine("current PC is " + this._mThread.PC); + m_thread.PC += -1 + compareloffset; + // Console.WriteLine("new PC is " + this._mThread.PC); + } + else + { + //Console.WriteLine("branch compare false"); + m_thread.PC += 2; + } + } + else + { + m_thread.PC += 2; + } + result = true; + break; + case (byte) OpCode._goto: + short offset = + (short) + ((GlobalMemory.MethodArea.MethodBuffer[m_thread.PC] << 8) + + GlobalMemory.MethodArea.MethodBuffer[m_thread.PC + 1]); + m_thread.PC += -1 + offset; + result = true; + break; + case (byte) OpCode.getstatic: + short fieldrefIndex = + (short) + ((GlobalMemory.MethodArea.MethodBuffer[m_thread.PC] << 8) + + GlobalMemory.MethodArea.MethodBuffer[m_thread.PC + 1]); + if (m_thread.currentClass.m_constantsPool[fieldrefIndex - 1] is ClassRecord.PoolFieldRef) + { + if ( + ((ClassRecord.PoolFieldRef) m_thread.currentClass.m_constantsPool[fieldrefIndex - 1]). + mClass.Name.Value == m_thread.currentClass.MClass.Name.Value) + { + //from this class + if ( + m_thread.currentClass.StaticFields.ContainsKey( + ((ClassRecord.PoolFieldRef) + m_thread.currentClass.m_constantsPool[fieldrefIndex - 1]).mNameType.Name.Value)) + { + if ( + m_thread.currentClass.StaticFields[ + ((ClassRecord.PoolFieldRef) + m_thread.currentClass.m_constantsPool[fieldrefIndex - 1]).mNameType.Name. + Value] is Float) + { + Float retFloat = new Float(); + retFloat.mValue = + ((Float) + m_thread.currentClass.StaticFields[ + ((ClassRecord.PoolFieldRef) + m_thread.currentClass.m_constantsPool[fieldrefIndex - 1]).mNameType. + Name.Value]).mValue; + m_thread.m_currentFrame.OpStack.Push(retFloat); + } + else if ( + m_thread.currentClass.StaticFields[ + ((ClassRecord.PoolFieldRef) + m_thread.currentClass.m_constantsPool[fieldrefIndex - 1]).mNameType. + Name.Value] is Int) + { + Int retInt = new Int(); + retInt.mValue = + ((Int) + m_thread.currentClass.StaticFields[ + ((ClassRecord.PoolFieldRef) + m_thread.currentClass.m_constantsPool[fieldrefIndex - 1]). + mNameType.Name.Value]).mValue; + // Console.WriteLine("getting static field, " + retInt.mValue); + m_thread.m_currentFrame.OpStack.Push(retInt); + } + } + } + else + { + //get from a different class + } + } + m_thread.PC += 2; + result = true; + break; + case (byte) OpCode.putstatic: + fieldrefIndex = + (short) + ((GlobalMemory.MethodArea.MethodBuffer[m_thread.PC] << 8) + + GlobalMemory.MethodArea.MethodBuffer[m_thread.PC + 1]); + BaseType addstatic = m_thread.m_currentFrame.OpStack.Pop(); + if (m_thread.currentClass.m_constantsPool[fieldrefIndex - 1] is ClassRecord.PoolFieldRef) + { + if ( + ((ClassRecord.PoolFieldRef) m_thread.currentClass.m_constantsPool[fieldrefIndex - 1]). + mClass.Name.Value == m_thread.currentClass.MClass.Name.Value) + { + // this class + if ( + m_thread.currentClass.StaticFields.ContainsKey( + ((ClassRecord.PoolFieldRef) + m_thread.currentClass.m_constantsPool[fieldrefIndex - 1]).mNameType.Name.Value)) + { + if (addstatic is Float) + { + if ( + m_thread.currentClass.StaticFields[ + ((ClassRecord.PoolFieldRef) + m_thread.currentClass.m_constantsPool[fieldrefIndex - 1]).mNameType. + Name.Value] is Float) + { + Float newf = new Float(); + newf.mValue = ((Float) addstatic).mValue; + m_thread.currentClass.StaticFields[ + ((ClassRecord.PoolFieldRef) + m_thread.currentClass.m_constantsPool[fieldrefIndex - 1]).mNameType. + Name.Value] = newf; + } + } + else if (addstatic is Int) + { + if ( + m_thread.currentClass.StaticFields[ + ((ClassRecord.PoolFieldRef) + m_thread.currentClass.m_constantsPool[fieldrefIndex - 1]).mNameType. + Name.Value] is Int) + { + //Console.WriteLine("setting static field to " + ((Int)addstatic).mValue); + Int newi = new Int(); + newi.mValue = ((Int) addstatic).mValue; + m_thread.currentClass.StaticFields[ + ((ClassRecord.PoolFieldRef) + m_thread.currentClass.m_constantsPool[fieldrefIndex - 1]).mNameType. + Name.Value] = newi; + } + } + } + } + else + { + // a different class + } + } + m_thread.PC += 2; + result = true; + break; + } + + return result; + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.Methods.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.Methods.cs new file mode 100644 index 0000000000..59f4c0e6bb --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.Methods.cs @@ -0,0 +1,102 @@ +/* +* 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. +* +*/ +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + partial class Thread + { + private partial class Interpreter + { + private bool IsMethodOpCode(byte opcode) + { + bool result = false; + switch (opcode) + { + case 184: + short refIndex = + (short) + ((GlobalMemory.MethodArea.MethodBuffer[m_thread.PC] << 8) + + GlobalMemory.MethodArea.MethodBuffer[m_thread.PC + 1]); + if (m_thread.currentClass.m_constantsPool[refIndex - 1] is ClassRecord.PoolMethodRef) + { + string typ = + ((ClassRecord.PoolMethodRef) m_thread.currentClass.m_constantsPool[refIndex - 1]). + mNameType.Type.Value; + string typeparam = System.String.Empty; + string typereturn = System.String.Empty; + int firstbrak = 0; + int secondbrak = 0; + firstbrak = typ.LastIndexOf('('); + secondbrak = typ.LastIndexOf(')'); + typeparam = typ.Substring(firstbrak + 1, secondbrak - firstbrak - 1); + typereturn = typ.Substring(secondbrak + 1, typ.Length - secondbrak - 1); + if ( + ((ClassRecord.PoolMethodRef) m_thread.currentClass.m_constantsPool[refIndex - 1]).mClass + .Name.Value == m_thread.currentClass.MClass.Name.Value) + { + //calling a method in this class + if (typeparam.Length == 0) + { + m_thread.JumpToStaticVoidMethod( + ((ClassRecord.PoolMethodRef) m_thread.currentClass.m_constantsPool[refIndex - 1]) + .mNameType.Name.Value, (m_thread.PC + 2)); + } + else + { + m_thread.JumpToStaticParamMethod( + ((ClassRecord.PoolMethodRef) m_thread.currentClass.m_constantsPool[refIndex - 1]) + .mNameType.Name.Value, typeparam, (m_thread.PC + 2)); + } + } + else + { + //calling a method of a different class + + // OpenSimAPI Class + if ( + ((ClassRecord.PoolMethodRef) m_thread.currentClass.m_constantsPool[refIndex - 1]). + mClass.Name.Value == "OpenSimAPI") + { + m_thread.scriptInfo.api.CallMethod( + ((ClassRecord.PoolMethodRef) m_thread.currentClass.m_constantsPool[refIndex - 1]) + .mNameType.Name.Value, null); + } + } + } + else + { + m_thread.PC += 2; + } + result = true; + break; + } + + return result; + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.Return.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.Return.cs new file mode 100644 index 0000000000..60cf8d4cca --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.Return.cs @@ -0,0 +1,36 @@ +/* +* 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. +* +*/ +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + partial class Thread + { + private partial class Interpreter + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.cs new file mode 100644 index 0000000000..64e927594a --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Interpreter.cs @@ -0,0 +1,132 @@ +/* +* 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; +using OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types; +using OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types.PrimitiveTypes; + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + partial class Thread + { + private partial class Interpreter + { + private Thread m_thread; + + public Interpreter(Thread parentThread) + { + m_thread = parentThread; + } + + public bool Excute() + { + bool run = true; + byte currentOpCode = GlobalMemory.MethodArea.MethodBuffer[m_thread.PC++]; + // Console.WriteLine("opCode is: " + currentOpCode); + bool handled = false; + + handled = IsLogicOpCode(currentOpCode); + if (!handled) + { + handled = IsMethodOpCode(currentOpCode); + } + if (!handled) + { + if (currentOpCode == 172) + { + if (m_thread.stack.StackFrames.Count > 1) + { + Console.WriteLine("returning int from function"); + int retPC1 = m_thread.m_currentFrame.ReturnPC; + BaseType bas1 = m_thread.m_currentFrame.OpStack.Pop(); + m_thread.stack.StackFrames.Pop(); + m_thread.m_currentFrame = m_thread.stack.StackFrames.Peek(); + m_thread.PC = retPC1; + if (bas1 is Int) + { + m_thread.m_currentFrame.OpStack.Push((Int) bas1); + } + } + else + { + // Console.WriteLine("No parent function so ending program"); + m_thread.stack.StackFrames.Pop(); + run = false; + } + handled = true; + } + if (currentOpCode == 174) + { + if (m_thread.stack.StackFrames.Count > 1) + { + Console.WriteLine("returning float from function"); + int retPC1 = m_thread.m_currentFrame.ReturnPC; + BaseType bas1 = m_thread.m_currentFrame.OpStack.Pop(); + m_thread.stack.StackFrames.Pop(); + m_thread.m_currentFrame = m_thread.stack.StackFrames.Peek(); + m_thread.PC = retPC1; + if (bas1 is Float) + { + m_thread.m_currentFrame.OpStack.Push((Float) bas1); + } + } + else + { + // Console.WriteLine("No parent function so ending program"); + m_thread.stack.StackFrames.Pop(); + run = false; + } + handled = true; + } + if (currentOpCode == 177) + { + if (m_thread.stack.StackFrames.Count > 1) + { + Console.WriteLine("returning from function"); + int retPC = m_thread.m_currentFrame.ReturnPC; + m_thread.stack.StackFrames.Pop(); + m_thread.m_currentFrame = m_thread.stack.StackFrames.Peek(); + m_thread.PC = retPC; + } + else + { + // Console.WriteLine("No parent function so ending program"); + m_thread.stack.StackFrames.Pop(); + run = false; + } + handled = true; + } + } + if (!handled) + { + Console.WriteLine("opcode " + currentOpCode + " not been handled "); + } + return run; + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/MainMemory.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/MainMemory.cs new file mode 100644 index 0000000000..6e62d5a2ee --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/MainMemory.cs @@ -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. +* +*/ +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + public class MainMemory + { + public Heap HeapArea; + public MethodMemory MethodArea; + + public MainMemory() + { + MethodArea = new MethodMemory(); + HeapArea = new Heap(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/MethodMemory.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/MethodMemory.cs new file mode 100644 index 0000000000..2d3fc47522 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/MethodMemory.cs @@ -0,0 +1,44 @@ +/* +* 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.Collections.Generic; + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + public class MethodMemory + { + public byte[] MethodBuffer; + public List Classes = new List(); + public int NextMethodPC = 0; + public int Methodcount = 0; + + public MethodMemory() + { + MethodBuffer = new byte[20000]; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Object.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Object.cs new file mode 100644 index 0000000000..f17bf434a2 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Object.cs @@ -0,0 +1,33 @@ +/* +* 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. +* +*/ +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + public class Object + { + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/OpCodes.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/OpCodes.cs new file mode 100644 index 0000000000..616b64ec4b --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/OpCodes.cs @@ -0,0 +1,80 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + public enum OpCode : byte + { + iconst_m1 = 2, + iconst_0 = 3, + iconst_1 = 4, + iconst_2 = 5, + iconst_3 = 6, + iconst_4 = 7, + iconst_5 = 8, + fconst_0 = 11, + fconst_1 = 12, + fconst_2 = 13, + bipush = 16, + sipush = 17, + fload = 23, + iload_0 = 26, + iload_1 = 27, + fload_0 = 34, + fload_1 = 35, + fload_2 = 36, + fload_3 = 37, + istore = 54, + fstore = 56, + istore_0 = 59, + istore_1 = 60, + istore_2 = 61, + istore_3 = 62, + fstore_0 = 67, + fstore_1 = 68, + fstore_2 = 69, + fstore_3 = 70, + pop = 87, + fadd = 98, + fsub = 102, + imul = 104, + iinc = 132, + f2i = 139, + fcmpl = 149, + fcmpg = 150, + ifge = 156, + ifgt = 157, + ifle = 158, + if_icmpge = 162, + if_icmpgt = 163, + if_icmple = 164, + _goto = 167, + getstatic = 178, + putstatic = 179 + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Stack.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Stack.cs new file mode 100644 index 0000000000..ff0130752a --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Stack.cs @@ -0,0 +1,40 @@ +/* +* 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.Collections.Generic; + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + public class Stack + { + public Stack StackFrames = new Stack(); + + public Stack() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/StackFrame.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/StackFrame.cs new file mode 100644 index 0000000000..40bec4c2fe --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/StackFrame.cs @@ -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. +* +*/ +using System.Collections.Generic; +using OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types; + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + public class StackFrame + { + public BaseType[] LocalVariables; + public Stack OpStack = new Stack(); + + public int ReturnPC = 0; + public ClassRecord CallingClass = null; + + public StackFrame() + { + LocalVariables = new BaseType[20]; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Thread.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Thread.cs new file mode 100644 index 0000000000..7f3af0e58d --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JVM/Thread.cs @@ -0,0 +1,111 @@ +/* +* 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 OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types; +using OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types.PrimitiveTypes; + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM +{ + public partial class Thread + { + // Is this smart? + public static MainMemory GlobalMemory; + public static Scene World; + private int PC = 0; + private Stack stack; + private Interpreter m_Interpreter; + public ClassRecord currentClass; + public ClassInstance currentInstance; + private StackFrame m_currentFrame; + public int excutionCounter = 0; + public bool running = false; + + public ScriptInfo scriptInfo; + + public Thread() + { + m_Interpreter = new Interpreter(this); + stack = new Stack(); + } + + public void SetPC(int methodpointer) + { + //Console.WriteLine("Thread PC has been set to " + methodpointer); + PC = methodpointer; + } + + public void StartMethod(ClassRecord rec, string methName) + { + m_currentFrame = new StackFrame(); + stack.StackFrames.Push(m_currentFrame); + currentClass = rec; + currentClass.StartMethod(this, methName); + } + + public void StartMethod(string methName) + { + m_currentFrame = new StackFrame(); + stack.StackFrames.Push(m_currentFrame); + currentClass.StartMethod(this, methName); + } + + public void JumpToStaticVoidMethod(string methName, int returnPC) + { + m_currentFrame = new StackFrame(); + m_currentFrame.ReturnPC = returnPC; + stack.StackFrames.Push(m_currentFrame); + currentClass.StartMethod(this, methName); + } + + public void JumpToStaticParamMethod(string methName, string param, int returnPC) + { + if (param == "I") + { + BaseType bs1 = m_currentFrame.OpStack.Pop(); + m_currentFrame = new StackFrame(); + m_currentFrame.ReturnPC = returnPC; + stack.StackFrames.Push(m_currentFrame); + m_currentFrame.LocalVariables[0] = ((Int) bs1); + currentClass.StartMethod(this, methName); + } + if (param == "F") + { + } + } + + public void JumpToClassStaticVoidMethod(string className, string methName, int returnPC) + { + } + + public bool Excute() + { + excutionCounter++; + return m_Interpreter.Excute(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JavaEngine.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JavaEngine.cs new file mode 100644 index 0000000000..ea996262d2 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/JavaEngine.cs @@ -0,0 +1,52 @@ +/* +* 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.Collections.Generic; + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine +{ + public class JavaEngine : IScriptCompiler + { + public string FileExt() + { + return ".java"; + } + + public Dictionary compile(string filename) + { + JVMScript script = new JVMScript(); + Dictionary returns = new Dictionary(); + + script.LoadScript(filename); + + returns.Add(filename, script); + + return returns; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/OpenSimJVM.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/OpenSimJVM.cs new file mode 100644 index 0000000000..449f715147 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/OpenSimJVM.cs @@ -0,0 +1,166 @@ +/* +* 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; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ExtensionsScriptModule.JVMEngine.JVM; + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine +{ + public class JVMScript : IScript + { + private List _threads = new List(); + private BlockingQueue CompileScripts = new BlockingQueue(); + private MainMemory _mainMemory; + + private ScriptInfo scriptInfo; + + public void Initialise(ScriptInfo info) + { + scriptInfo = info; + + _mainMemory = new MainMemory(); + Thread.GlobalMemory = _mainMemory; + Thread.World = info.world; + CompileScript(); + + scriptInfo.events.OnFrame += new EventManager.OnFrameDelegate(events_OnFrame); + scriptInfo.events.OnNewPresence += new EventManager.OnNewPresenceDelegate(events_OnNewPresence); + } + + private void events_OnNewPresence(ScenePresence presence) + { + for (int i = 0; i < _threads.Count; i++) + { + if (!_threads[i].running) + { + _threads[i].StartMethod("OnNewPresence"); + bool run = true; + while (run) + { + run = _threads[i].Excute(); + } + } + } + } + + private void events_OnFrame() + { + for (int i = 0; i < _threads.Count; i++) + { + if (!_threads[i].running) + { + _threads[i].StartMethod("OnFrame"); + bool run = true; + while (run) + { + run = _threads[i].Excute(); + } + } + } + } + + public string Name + { + get { return "JVM Scripting Engine"; } + } + + public void LoadScript(string script) + { + Console.WriteLine("OpenSimJVM - loading new script: " + script); + CompileInfo comp = new CompileInfo(); + comp.script = script; + comp.scriptName = script; + CompileScripts.Enqueue(comp); + } + + public void CompileScript() + { + CompileInfo comp = CompileScripts.Dequeue(); + string script = comp.script; + string scriptName = comp.scriptName; + try + { + //need to compile the script into a java class file + + //first save it to a java source file + TextWriter tw = new StreamWriter(scriptName + ".java"); + tw.WriteLine(script); + tw.Close(); + + //now compile + ProcessStartInfo psi = new ProcessStartInfo("javac.exe", "*.java"); + // psi.RedirectStandardOutput = true; + psi.WindowStyle = ProcessWindowStyle.Hidden; + psi.UseShellExecute = false; + + Process javacomp; + javacomp = Process.Start(psi); + javacomp.WaitForExit(); + + + //now load in class file + ClassRecord class1 = new ClassRecord(); + class1.LoadClassFromFile(scriptName + ".class"); + class1.PrintToConsole(); + //Console.WriteLine(); + _mainMemory.MethodArea.Classes.Add(class1); + class1.AddMethodsToMemory(_mainMemory.MethodArea); + + Thread newThread = new Thread(); + _threads.Add(newThread); + newThread.currentClass = class1; + newThread.scriptInfo = scriptInfo; + + //now delete the created files + File.Delete(scriptName + ".java"); + File.Delete(scriptName + ".class"); + //this.OnFrame(); + } + catch (Exception e) + { + Console.WriteLine("exception"); + Console.WriteLine(e.StackTrace); + Console.WriteLine(e.Message); + } + } + + private class CompileInfo + { + public string script; + public string scriptName; + + public CompileInfo() + { + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/ArrayReference.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/ArrayReference.cs new file mode 100644 index 0000000000..3c8295221b --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/ArrayReference.cs @@ -0,0 +1,34 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types +{ + public class ArrayReference : BaseType + { + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/BaseType.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/BaseType.cs new file mode 100644 index 0000000000..dc93b891e7 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/BaseType.cs @@ -0,0 +1,36 @@ +/* +* 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; + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types +{ + public class BaseType : Object + { + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/ObjectReference.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/ObjectReference.cs new file mode 100644 index 0000000000..4026c10faf --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/ObjectReference.cs @@ -0,0 +1,39 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types +{ + public class ObjectReference : BaseType + { + public ushort Reference; + + public ObjectReference() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Byte.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Byte.cs new file mode 100644 index 0000000000..de1aa87899 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Byte.cs @@ -0,0 +1,34 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types.PrimitiveTypes +{ + public class Byte : BaseType + { + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Char.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Char.cs new file mode 100644 index 0000000000..0e170576d7 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Char.cs @@ -0,0 +1,34 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types.PrimitiveTypes +{ + public class Char : BaseType + { + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Float.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Float.cs new file mode 100644 index 0000000000..ce8648c93c --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Float.cs @@ -0,0 +1,39 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types.PrimitiveTypes +{ + public class Float : BaseType + { + public float mValue = 0; + + public Float() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Int.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Int.cs new file mode 100644 index 0000000000..251b736c8a --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Engines/JVMEngine/Types/PrimitiveTypes/Int.cs @@ -0,0 +1,39 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.ExtensionsScriptModule.JVMEngine.Types.PrimitiveTypes +{ + public class Int : BaseType + { + public int mValue = 0; + + public Int() + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/Script.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/Script.cs new file mode 100644 index 0000000000..d9d569b60c --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/Script.cs @@ -0,0 +1,64 @@ +/* +* 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 OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.ExtensionsScriptModule +{ + public interface IScript + { + void Initialise(ScriptInfo scriptInfo); + string Name { get; } + } + + public class TestScript : IScript + { + private ScriptInfo script; + + public string Name + { + get { return "TestScript 0.1"; } + } + + public void Initialise(ScriptInfo scriptInfo) + { + script = scriptInfo; + script.events.OnFrame += events_OnFrame; + script.events.OnNewPresence += events_OnNewPresence; + } + + private void events_OnNewPresence(ScenePresence presence) + { + script.Log.Info("[TESTSCRIPT]: Hello " + presence.Firstname.ToString() + "!"); + } + + private void events_OnFrame() + { + //script.logger.Info("[TESTSCRIPT]: Hello World!"); + } + } +} diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptAPI.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptAPI.cs new file mode 100644 index 0000000000..9384efa37b --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptAPI.cs @@ -0,0 +1,57 @@ +/* +* 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; +using OpenSim.Region.Environment.Scenes; +using Key = libsecondlife.LLUUID; +using Rotation = libsecondlife.LLQuaternion; +using Vector = libsecondlife.LLVector3; +using LSLList = System.Collections.Generic.List; + + +namespace OpenSim.Region.ExtensionsScriptModule +{ + // This class is to be used for engines which may not be able to access the Scene directly. + // Scene access is preffered, but obviously not possible on some non-.NET languages. + public class ScriptAPI + { + private Scene scene; + private ScriptInterpretedAPI interpretedAPI; + + public ScriptAPI(Scene world, Key taskID) + { + scene = world; + interpretedAPI = new ScriptInterpretedAPI(world, taskID); + } + + public Object CallMethod(String method, Object[] args) + { + return null; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptInfo.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptInfo.cs new file mode 100644 index 0000000000..e90bfc1b62 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptInfo.cs @@ -0,0 +1,67 @@ +/* +* 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 libsecondlife; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.ExtensionsScriptModule +{ + /// + /// Class which provides access to the world + /// + public class ScriptInfo + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Reference to world.eventsManager provided for convenience + public EventManager events; + + // The main world + public Scene world; + + // API Access + public ScriptAPI api; + + public log4net.ILog Log + { + get { return m_log; } + } + + public ScriptInfo(Scene scene) + { + world = scene; + events = world.EventManager; + api = new ScriptAPI(world, LLUUID.Zero); + } + + public void CreateTaskAPI(LLUUID task) + { + api = new ScriptAPI(world, task); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptInterpretedAPI.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptInterpretedAPI.cs new file mode 100644 index 0000000000..0f50358040 --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptInterpretedAPI.cs @@ -0,0 +1,302 @@ +/* +* 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; +using System.Text; +using Axiom.Math; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.LandManagement; +using OpenSim.Region.Environment.Scenes; +using Key = libsecondlife.LLUUID; +using Rotation = libsecondlife.LLQuaternion; +using Vector = libsecondlife.LLVector3; +using LSLList = System.Collections.Generic.List; + +namespace OpenSim.Region.ExtensionsScriptModule +{ + /// + /// A class inteded to act as an API for LSL-styled interpreted languages + /// + /// Avoid at all costs. This should ONLY be used for LSL. + internal class ScriptInterpretedAPI + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected Key m_object; + protected Scene m_scene; + + /// + /// The scene in which this script is acting + /// + public Scene Scene + { + get { return m_scene; } + } + + /// + /// The id of the object our script is supposed to be acting in + /// + public Key ObjectID + { + get { return m_object; } + } + + /// + /// The object our script is supposed to be in + /// + public SceneObjectGroup Task + { + // XXX Casting not ideal, but previous Scene.Objects propery wasn't actually populated, so + // wouldn't have worked anyway. + get { return (SceneObjectGroup)Scene.Entities[ObjectID]; } + } + + /// + /// Creates a new ScriptInterpretedAPI for a specified object + /// + /// The scene the object is located in + /// The specific member being 'occupied' by the script + public ScriptInterpretedAPI(Scene world, Key member) + { + m_scene = world; + m_object = member; + } + + /// + /// Returns the absolute number of a integer value. + /// + /// Input + /// Absolute number of input + public int osAbs(int val) + { + return Math.Abs(val); + } + + public float osAcos(float val) + { + return (float) Math.Acos(val); + } + + [Obsolete("Unimplemented")] + public void osAddToLandPassList(Key avatar, float hours) + { + Vector myPosition = Task.AbsolutePosition; + Land myParcel = Scene.LandManager.getLandObject(myPosition.X, myPosition.Y); + if (myParcel == null) + { + //Dont do anything! + } + m_log.Warn("[script]: " + + "Unimplemented function called by script: osAddToLandPassList(Key avatar, float hours)"); + return; + } + + [Obsolete("Unimplemented")] + public void osAdjustSoundVolume(float volume) + { + m_log.Warn("[script]: Unimplemented function called by script: osAdjustSoundVolume(float volume)"); + return; + } + + [Obsolete("Unimplemented")] + public void osAllowInventoryDrop(int add) + { + return; + } + + [Obsolete("Unimplemented")] + public float osAngleBetween(Rotation a, Rotation b) + { + Quaternion axA = new Quaternion(a.W, a.X, a.Y, a.Z); + Quaternion axB = new Quaternion(b.W, b.X, b.Y, b.Z); + + return 0; + } + + [Obsolete("Unimplemented")] + public void osApplyImpulse(Vector force, int local) + { + return; + } + + [Obsolete("Unimplemented")] + public void osApplyRotationalImpulse(Vector force, int local) + { + return; + } + + public float osAsin(float val) + { + return (float) Math.Asin(val); + } + + public float osAtan2(float x, float y) + { + return (float) Math.Atan2(x, y); + } + + [Obsolete("Unimplemented")] + public void osAttachToAvatar(Key avatar, int attachmentPoint) + { + return; + } + + [Obsolete("Unimplemented")] + public Key osAvatarOnSitTarget() + { + //TODO: Follow this as Children is chanced to be of type entity to support ScenePresences + /* + foreach (KeyValuePair Child in Task.Children) + { + if (Child.Value is ScenePresence) + { + return Child.Value.uuid; + } + } + */ + + return Key.Zero; + } + + public Rotation osAxes2Rot(Vector fwd, Vector left, Vector up) + { + Quaternion axQ = new Quaternion(); + Vector3 axFwd = new Vector3(fwd.X, fwd.Y, fwd.Z); + Vector3 axLeft = new Vector3(left.X, left.Y, left.Z); + Vector3 axUp = new Vector3(up.X, up.Y, up.Z); + + axQ.FromAxes(axFwd, axLeft, axUp); + + return new Rotation(axQ.x, axQ.y, axQ.z, axQ.w); + } + + public Rotation osAxisAngle2Rot(Vector axis, float angle) + { + Quaternion axQ = Quaternion.FromAngleAxis(angle, new Vector3(axis.X, axis.Y, axis.Z)); + + return new Rotation(axQ.x, axQ.y, axQ.z, axQ.w); + } + + public string osBase64ToString(string str) + { + Encoding enc = Encoding.UTF8; + return enc.GetString(Convert.FromBase64String(str)); + } + + [Obsolete("Unimplemented")] + public void osBreakAllLinks() + { + return; + } + + [Obsolete("Unimplemented")] + public void osBreakLink() + { + return; + } + + public LSLList osCSV2List(string src) + { + LSLList retVal = new LSLList(); + retVal.AddRange(src.Split(',')); + + return retVal; + } + + public int osCeil(float val) + { + return (int) Math.Ceiling(val); + } + + [Obsolete("Unimplemented")] + public void osCloseRemoteDataChannel(Key channel) + { + return; + } + + [Obsolete("Unimplemented")] + public float osCloud(Vector offset) + { + return 0.0f; + } + + [Obsolete("Unimplemented")] + public void osCollisionFilter(string name, Key id, int accept) + { + return; + } + + [Obsolete("Unimplemented")] + public void osCollisionSprite(string impact_sprite) + { + return; + } + + public float osCos(float theta) + { + return (float) Math.Cos(theta); + } + + public void osCreateLink(Key target, int parent) + { + if (Scene.Entities[target] is SceneObjectGroup) + Task.LinkToGroup((SceneObjectGroup) Scene.Entities[target]); + + return; + } + + [Obsolete("Partially Unimplemented")] + public LSLList osDeleteSubList(LSLList src, int start, int end) + { + if (start < 0 || end < 0) + { + throw new Exception("Unsupported at this time."); + } + + src.RemoveRange(start, start - end + 1); + return src; + } + + [Obsolete("Partially Unimplemented")] + public string osDeleteSubString(string src, int start, int end) + { + if (start < 0 || end < 0) + { + throw new Exception("Unsupported at this time."); + } + + return src.Remove(start, start - end + 1); + } + + [Obsolete("Unimplemented")] + public void osDetachFromAvatar(Key avatar) + { + return; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptInterpretedEvents.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptInterpretedEvents.cs new file mode 100644 index 0000000000..44feaff4ff --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptInterpretedEvents.cs @@ -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. +* +*/ + +using Key = libsecondlife.LLUUID; + +namespace OpenSim.Region.ExtensionsScriptModule +{ + public class ScriptInterpretedEvents + { + public delegate void OnTouchStartDelegate(Key user); + + public event OnTouchStartDelegate OnTouchStart; + + + public void TriggerTouchStart(Key user) + { + if (OnTouchStart != null) + OnTouchStart(user); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptManager.cs b/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptManager.cs new file mode 100644 index 0000000000..6c2d94031a --- /dev/null +++ b/trunk/OpenSim/Region/ExtensionsScriptModule/ScriptManager.cs @@ -0,0 +1,151 @@ +/* +* 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.Collections.Generic; +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ExtensionsScriptModule.CSharp; +using OpenSim.Region.ExtensionsScriptModule.JScript; +using OpenSim.Region.ExtensionsScriptModule.JVMEngine; + +namespace OpenSim.Region.ExtensionsScriptModule +{ + public class ScriptManager : IRegionModule, IExtensionScriptModule + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private readonly List scripts = new List(); + private Scene m_scene; + private readonly Dictionary compilers = new Dictionary(); + + private void LoadFromCompiler(Dictionary compiledscripts) + { + foreach (KeyValuePair script in compiledscripts) + { + ScriptInfo scriptInfo = new ScriptInfo(m_scene); + // Since each script could potentially corrupt their access with a stray assignment, making a new one for each script. + m_log.Info("[SCRIPT]: Loading " + script.Key); + script.Value.Initialise(scriptInfo); + scripts.Add(script.Value); + } + + m_log.Info("[SCRIPT]: " + string.Format("Finished loading {0} script(s)", compiledscripts.Count)); + } + + public ScriptManager() + { + // Default Engines + CSharpScriptEngine csharpCompiler = new CSharpScriptEngine(); + compilers.Add(csharpCompiler.FileExt(), csharpCompiler); + + JScriptEngine jscriptCompiler = new JScriptEngine(); + compilers.Add(jscriptCompiler.FileExt(), jscriptCompiler); + + JavaEngine javaCompiler = new JavaEngine(); + compilers.Add(javaCompiler.FileExt(), javaCompiler); + } + + public void Initialise(Scene scene, IConfigSource config) + { + m_log.Info("[SCRIPTMODULE]: Initialising Extensions Scripting Module"); + m_scene = scene; + + m_scene.RegisterModuleInterface(this); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "ExtensionsScriptingModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public bool Compile(string filename) + { + foreach (KeyValuePair compiler in compilers) + { + if (filename.EndsWith(compiler.Key)) + { + LoadFromCompiler(compiler.Value.compile(filename)); + break; + } + } + + return true; + } + + public void RunScriptCmd(string[] args) + { + switch (args[0]) + { + case "load": + Compile(args[1]); + break; + + default: + m_log.Error("Unknown script command"); + break; + } + } + + public bool AddPreCompiledScript(IScript script) + { + m_log.Info("[SCRIPT]: Loading script " + script.Name); + ScriptInfo scriptInfo = new ScriptInfo(m_scene); + // Since each script could potentially corrupt their access with a stray assignment, making a new one for each script. + script.Initialise(scriptInfo); + scripts.Add(script); + + return true; + } + } + + public interface IExtensionScriptModule + { + bool Compile(string filename); + bool AddPreCompiledScript(IScript script); + } + + internal interface IScriptCompiler + { + Dictionary compile(string filename); + string FileExt(); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs b/trunk/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs new file mode 100644 index 0000000000..919910cc25 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs @@ -0,0 +1,58 @@ +/* +* 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; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly : AssemblyTitle("BasicPhysicsPlugin")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("BasicPhysicsPlugin")] +[assembly : AssemblyCopyright("")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. + +[assembly : ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly : AssemblyVersion("1.0.*")] diff --git a/trunk/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs b/trunk/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs new file mode 100644 index 0000000000..4e96ce0bfe --- /dev/null +++ b/trunk/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs @@ -0,0 +1,365 @@ +/* +* 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.Collections.Generic; +using Axiom.Math; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.BasicPhysicsPlugin +{ + /// + /// Will be the PhysX plugin but for now will be a very basic physics engine + /// + public class BasicPhysicsPlugin : IPhysicsPlugin + { + public BasicPhysicsPlugin() + { + } + + public bool Init() + { + return true; + } + + public PhysicsScene GetScene() + { + return new BasicScene(); + } + + public string GetName() + { + return ("basicphysics"); + } + + public void Dispose() + { + } + } + + public class BasicScene : PhysicsScene + { + private List _actors = new List(); + private float[] _heightMap; + + public BasicScene() + { + } + + public override void Initialise(IMesher meshmerizer) + { + // Does nothing right now + } + + public override void Dispose() + { + + } + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) + { + BasicActor act = new BasicActor(); + act.Position = position; + _actors.Add(act); + return act; + } + + public override void RemovePrim(PhysicsActor prim) + { + } + + public override void RemoveAvatar(PhysicsActor actor) + { + BasicActor act = (BasicActor) actor; + if (_actors.Contains(act)) + { + _actors.Remove(act); + } + } + +/* + public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation) + { + return null; + } +*/ + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation) + { + return AddPrimShape(primName, pbs, position, size, rotation, false); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical) + { + return null; + } + + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + } + + public override float Simulate(float timeStep) + { + float fps = 0; + for (int i = 0; i < _actors.Count; ++i) + { + BasicActor actor = _actors[i]; + + actor.Position.X += actor.Velocity.X*timeStep; + actor.Position.Y += actor.Velocity.Y*timeStep; + + if (actor.Position.Y < 0) + { + actor.Position.Y = 0.1F; + } + else if (actor.Position.Y >= Constants.RegionSize) + { + actor.Position.Y = 255.9F; + } + + if (actor.Position.X < 0) + { + actor.Position.X = 0.1F; + } + else if (actor.Position.X >= Constants.RegionSize) + { + actor.Position.X = 255.9F; + } + + float height = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + 1.0f; + if (actor.Flying) + { + if (actor.Position.Z + (actor.Velocity.Z*timeStep) < + _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + 2) + { + actor.Position.Z = height; + actor.Velocity.Z = 0; + } + else + { + actor.Position.Z += actor.Velocity.Z*timeStep; + } + } + else + { + actor.Position.Z = height; + actor.Velocity.Z = 0; + } + } + return fps; + } + + public override void GetResults() + { + } + + public override bool IsThreaded + { + get { return (false); // for now we won't be multithreaded + } + } + + public override void SetTerrain(float[] heightMap) + { + _heightMap = heightMap; + } + + public override void DeleteTerrain() + { + } + } + + public class BasicActor : PhysicsActor + { + private PhysicsVector _position; + private PhysicsVector _velocity; + private PhysicsVector _acceleration; + private PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; + private bool flying; + private bool iscolliding; + + public BasicActor() + { + _velocity = new PhysicsVector(); + _position = new PhysicsVector(); + _acceleration = new PhysicsVector(); + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Agent; } + set { return; } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool Flying + { + get { return flying; } + set { flying = value; } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool Stopped + { + get { return false; } + } + + + public override PhysicsVector Position + { + get { return _position; } + set { _position = value; } + } + + public override PhysicsVector Size + { + get { return PhysicsVector.Zero; } + set { } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override float Mass + { + get { return 0f; } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector Velocity + { + get { return _velocity; } + set { _velocity = value; } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override Quaternion Orientation + { + get { return Quaternion.Identity; } + set { } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public override bool Kinematic + { + get { return true; } + set { } + } + + public void SetAcceleration(PhysicsVector accel) + { + _acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + public override void CrossingFailure() + { + + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/BulletXPlugin/AssemblyInfo.cs b/trunk/OpenSim/Region/Physics/BulletXPlugin/AssemblyInfo.cs new file mode 100644 index 0000000000..6b7ce82b33 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/BulletXPlugin/AssemblyInfo.cs @@ -0,0 +1,58 @@ +/* +* 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; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly : AssemblyTitle("BulletXPlugin")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("BulletXPlugin")] +[assembly : AssemblyCopyright("")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. + +[assembly : ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly : AssemblyVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/trunk/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs new file mode 100644 index 0000000000..8482e4cf76 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs @@ -0,0 +1,1559 @@ +/* +* 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. +* +*/ + +#region Copyright + +/* +* Copyright (c) Contributors, http://www.openmetaverse.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. +* +*/ + +#endregion + +#region References + +using System; +using System.Collections.Generic; +using MonoXnaCompactMaths; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Physics.Manager; +using XnaDevRu.BulletX; +using XnaDevRu.BulletX.Dynamics; +using AxiomQuaternion = Axiom.Math.Quaternion; +using BoxShape=XnaDevRu.BulletX.BoxShape; + +#endregion + +namespace OpenSim.Region.Physics.BulletXPlugin +{ + /// + /// BulletXConversions are called now BulletXMaths + /// This Class converts objects and types for BulletX and give some operations + /// + public class BulletXMaths + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + //Vector3 + public static Vector3 PhysicsVectorToXnaVector3(PhysicsVector physicsVector) + { + return new Vector3(physicsVector.X, physicsVector.Y, physicsVector.Z); + } + + public static PhysicsVector XnaVector3ToPhysicsVector(Vector3 xnaVector3) + { + return new PhysicsVector(xnaVector3.X, xnaVector3.Y, xnaVector3.Z); + } + + //Quaternion + public static Quaternion AxiomQuaternionToXnaQuaternion(AxiomQuaternion axiomQuaternion) + { + return new Quaternion(axiomQuaternion.x, axiomQuaternion.y, axiomQuaternion.z, axiomQuaternion.w); + } + + public static AxiomQuaternion XnaQuaternionToAxiomQuaternion(Quaternion xnaQuaternion) + { + return new AxiomQuaternion(xnaQuaternion.W, xnaQuaternion.X, xnaQuaternion.Y, xnaQuaternion.Z); + } + + //Next methods are extracted from XnaDevRu.BulletX(See 3rd party license): + //- SetRotation (class MatrixOperations) + //- GetRotation (class MatrixOperations) + //- GetElement (class MathHelper) + //- SetElement (class MathHelper) + internal static void SetRotation(ref Matrix m, Quaternion q) + { + float d = q.LengthSquared(); + float s = 2f/d; + float xs = q.X*s, ys = q.Y*s, zs = q.Z*s; + float wx = q.W*xs, wy = q.W*ys, wz = q.W*zs; + float xx = q.X*xs, xy = q.X*ys, xz = q.X*zs; + float yy = q.Y*ys, yz = q.Y*zs, zz = q.Z*zs; + m = new Matrix(1 - (yy + zz), xy - wz, xz + wy, 0, + xy + wz, 1 - (xx + zz), yz - wx, 0, + xz - wy, yz + wx, 1 - (xx + yy), 0, + m.M41, m.M42, m.M43, 1); + } + + internal static Quaternion GetRotation(Matrix m) + { + Quaternion q = new Quaternion(); + + float trace = m.M11 + m.M22 + m.M33; + + if (trace > 0) + { + float s = (float) Math.Sqrt(trace + 1); + q.W = s*0.5f; + s = 0.5f/s; + + q.X = (m.M32 - m.M23)*s; + q.Y = (m.M13 - m.M31)*s; + q.Z = (m.M21 - m.M12)*s; + } + else + { + int i = m.M11 < m.M22 + ? + (m.M22 < m.M33 ? 2 : 1) + : + (m.M11 < m.M33 ? 2 : 0); + int j = (i + 1)%3; + int k = (i + 2)%3; + + float s = (float) Math.Sqrt(GetElement(m, i, i) - GetElement(m, j, j) - GetElement(m, k, k) + 1); + SetElement(ref q, i, s*0.5f); + s = 0.5f/s; + + q.W = (GetElement(m, k, j) - GetElement(m, j, k))*s; + SetElement(ref q, j, (GetElement(m, j, i) + GetElement(m, i, j))*s); + SetElement(ref q, k, (GetElement(m, k, i) + GetElement(m, i, k))*s); + } + + return q; + } + + internal static float SetElement(ref Quaternion q, int index, float value) + { + switch (index) + { + case 0: + q.X = value; + break; + case 1: + q.Y = value; + break; + case 2: + q.Z = value; + break; + case 3: + q.W = value; + break; + } + + return 0; + } + + internal static float GetElement(Matrix mat, int row, int col) + { + switch (row) + { + case 0: + switch (col) + { + case 0: + return mat.M11; + case 1: + return mat.M12; + case 2: + return mat.M13; + } + break; + case 1: + switch (col) + { + case 0: + return mat.M21; + case 1: + return mat.M22; + case 2: + return mat.M23; + } + break; + case 2: + switch (col) + { + case 0: + return mat.M31; + case 1: + return mat.M32; + case 2: + return mat.M33; + } + break; + } + + return 0; + } + } + + /// + /// PhysicsPlugin Class for BulletX + /// + public class BulletXPlugin : IPhysicsPlugin + { + private BulletXScene _mScene; + + public BulletXPlugin() + { + } + + public bool Init() + { + return true; + } + + public PhysicsScene GetScene() + { + if (_mScene == null) + { + _mScene = new BulletXScene(); + } + return (_mScene); + } + + public string GetName() + { + return ("modified_BulletX"); //Changed!! "BulletXEngine" To "modified_BulletX" + } + + public void Dispose() + { + } + } + + + // Class to detect and debug collisions + // Mainly used for debugging purposes + internal class CollisionDispatcherLocal : CollisionDispatcher + { + private BulletXScene relatedScene; + + public CollisionDispatcherLocal(BulletXScene s) + : base() + { + relatedScene = s; + } + + public override bool NeedsCollision(CollisionObject bodyA, CollisionObject bodyB) + { + RigidBody rb; + BulletXCharacter bxcA = null; + BulletXPrim bxpA = null; + Type t = bodyA.GetType(); + if (t == typeof (RigidBody)) + { + rb = (RigidBody) bodyA; + relatedScene._characters.TryGetValue(rb, out bxcA); + relatedScene._prims.TryGetValue(rb, out bxpA); + } + String nameA; + if (bxcA != null) + nameA = bxcA._name; + else if (bxpA != null) + nameA = bxpA._name; + else + nameA = "null"; + + BulletXCharacter bxcB = null; + BulletXPrim bxpB = null; + t = bodyB.GetType(); + if (t == typeof (RigidBody)) + { + rb = (RigidBody) bodyB; + relatedScene._characters.TryGetValue(rb, out bxcB); + relatedScene._prims.TryGetValue(rb, out bxpB); + } + String nameB; + if (bxcB != null) + nameB = bxcB._name; + else if (bxpB != null) + nameB = bxpB._name; + else + nameB = "null"; + + bool needsCollision = base.NeedsCollision(bodyA, bodyB); + + //m_log.Debug("[BulletX]: A collision was detected between {0} and {1} --> {2}", nameA, nameB, + //needsCollision); + + + return needsCollision; + } + } + + /// + /// PhysicsScene Class for BulletX + /// + public class BulletXScene : PhysicsScene + { + #region BulletXScene Fields + + public DiscreteDynamicsWorld ddWorld; + private CollisionDispatcher cDispatcher; + private OverlappingPairCache opCache; + private SequentialImpulseConstraintSolver sicSolver; + public static Object BulletXLock = new Object(); + + private const int minXY = 0; + private const int minZ = 0; + private const int maxXY = (int)Constants.RegionSize; + private const int maxZ = 4096; + private const int maxHandles = 32766; //Why? I don't know + private const float gravity = 9.8f; + private const float heightLevel0 = 77.0f; + private const float heightLevel1 = 200.0f; + private const float lowGravityFactor = 0.2f; + //OpenSim calls Simulate 10 times per seconds. So FPS = "Simulate Calls" * simulationSubSteps = 100 FPS + private const int simulationSubSteps = 10; + //private float[] _heightmap; + private BulletXPlanet _simFlatPlanet; + internal Dictionary _characters = new Dictionary(); + internal Dictionary _prims = new Dictionary(); + + public IMesher mesher; + + + public static float Gravity + { + get { return gravity; } + } + + public static float HeightLevel0 + { + get { return heightLevel0; } + } + + public static float HeightLevel1 + { + get { return heightLevel1; } + } + + public static float LowGravityFactor + { + get { return lowGravityFactor; } + } + + public static int MaxXY + { + get { return maxXY; } + } + + public static int MaxZ + { + get { return maxZ; } + } + + private List _forgottenRigidBodies = new List(); + internal string is_ex_message = "Can't remove rigidBody!: "; + + #endregion + + public BulletXScene() + { + cDispatcher = new CollisionDispatcherLocal(this); + Vector3 worldMinDim = new Vector3((float) minXY, (float) minXY, (float) minZ); + Vector3 worldMaxDim = new Vector3((float) maxXY, (float) maxXY, (float) maxZ); + opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles); + sicSolver = new SequentialImpulseConstraintSolver(); + + lock (BulletXLock) + { + ddWorld = new DiscreteDynamicsWorld(cDispatcher, opCache, sicSolver); + ddWorld.Gravity = new Vector3(0, 0, -gravity); + } + //this._heightmap = new float[65536]; + } + + public override void Initialise(IMesher meshmerizer) + { + mesher = meshmerizer; + } + + public override void Dispose() + { + + } + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) + { + PhysicsVector pos = new PhysicsVector(); + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z + 20; + BulletXCharacter newAv = null; + lock (BulletXLock) + { + newAv = new BulletXCharacter(avName, this, pos); + _characters.Add(newAv.RigidBody, newAv); + } + return newAv; + } + + public override void RemoveAvatar(PhysicsActor actor) + { + if (actor is BulletXCharacter) + { + lock (BulletXLock) + { + try + { + ddWorld.RemoveRigidBody(((BulletXCharacter) actor).RigidBody); + } + catch (Exception ex) + { + BulletXMessage(is_ex_message + ex.Message, true); + ((BulletXCharacter) actor).RigidBody.ActivationState = ActivationState.DisableSimulation; + AddForgottenRigidBody(((BulletXCharacter) actor).RigidBody); + } + _characters.Remove(((BulletXCharacter) actor).RigidBody); + } + GC.Collect(); + } + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, AxiomQuaternion rotation) + { + return AddPrimShape(primName, pbs, position, size, rotation, false); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, AxiomQuaternion rotation, bool isPhysical) + { + PhysicsActor result; + + switch (pbs.ProfileShape) + { + case ProfileShape.Square: + /// support simple box & hollow box now; later, more shapes + if (pbs.ProfileHollow == 0) + { + result = AddPrim(primName, position, size, rotation, null, null, isPhysical); + } + else + { + IMesh mesh = mesher.CreateMesh(primName, pbs, size); + result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); + } + break; + + default: + result = AddPrim(primName, position, size, rotation, null, null, isPhysical); + break; + } + + return result; + } + + public PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, AxiomQuaternion rotation, + IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical) + { + BulletXPrim newPrim = null; + lock (BulletXLock) + { + newPrim = new BulletXPrim(name, this, position, size, rotation, mesh, pbs, isPhysical); + _prims.Add(newPrim.RigidBody, newPrim); + } + return newPrim; + } + + public override void RemovePrim(PhysicsActor prim) + { + if (prim is BulletXPrim) + { + lock (BulletXLock) + { + try + { + ddWorld.RemoveRigidBody(((BulletXPrim) prim).RigidBody); + } + catch (Exception ex) + { + BulletXMessage(is_ex_message + ex.Message, true); + ((BulletXPrim) prim).RigidBody.ActivationState = ActivationState.DisableSimulation; + AddForgottenRigidBody(((BulletXPrim) prim).RigidBody); + } + _prims.Remove(((BulletXPrim) prim).RigidBody); + } + GC.Collect(); + } + } + + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + } + + public override float Simulate(float timeStep) + { + float fps = 0; + lock (BulletXLock) + { + //Try to remove garbage + RemoveForgottenRigidBodies(); + //End of remove + MoveAllObjects(timeStep); + + + fps = (timeStep*simulationSubSteps); + + ddWorld.StepSimulation(timeStep, simulationSubSteps, timeStep); + //Extra Heightmap Validation: BulletX's HeightFieldTerrain somestimes doesn't work so fine. + ValidateHeightForAll(); + //End heightmap validation. + UpdateKineticsForAll(); + } + return fps; + } + + private void MoveAllObjects(float timeStep) + { + foreach (BulletXCharacter actor in _characters.Values) + { + actor.Move(timeStep); + } + foreach (BulletXPrim prim in _prims.Values) + { + } + } + + private void ValidateHeightForAll() + { + float _height; + foreach (BulletXCharacter actor in _characters.Values) + { + //_height = HeightValue(actor.RigidBodyPosition); + _height = _simFlatPlanet.HeightValue(actor.RigidBodyPosition); + actor.ValidateHeight(_height); + //if (_simFlatPlanet.heightIsNotValid(actor.RigidBodyPosition, out _height)) actor.ValidateHeight(_height); + } + foreach (BulletXPrim prim in _prims.Values) + { + //_height = HeightValue(prim.RigidBodyPosition); + _height = _simFlatPlanet.HeightValue(prim.RigidBodyPosition); + prim.ValidateHeight(_height); + //if (_simFlatPlanet.heightIsNotValid(prim.RigidBodyPosition, out _height)) prim.ValidateHeight(_height); + } + //foreach (BulletXCharacter actor in _characters) + //{ + // actor.ValidateHeight(0); + //} + //foreach (BulletXPrim prim in _prims) + //{ + // prim.ValidateHeight(0); + //} + } + + private void UpdateKineticsForAll() + { + //UpdatePosition > UpdateKinetics. + //Not only position will be updated, also velocity cause acceleration. + foreach (BulletXCharacter actor in _characters.Values) + { + actor.UpdateKinetics(); + } + foreach (BulletXPrim prim in _prims.Values) + { + prim.UpdateKinetics(); + } + //if(this._simFlatPlanet!=null) this._simFlatPlanet.Restore(); + } + + public override void GetResults() + { + } + + public override bool IsThreaded + { + get { return (false); // for now we won't be multithreaded + } + } + + public override void SetTerrain(float[] heightMap) + { + ////As the same as ODE, heightmap (x,y) must be swapped for BulletX + //for (int i = 0; i < 65536; i++) + //{ + // // this._heightmap[i] = (double)heightMap[i]; + // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) + // int x = i & 0xff; + // int y = i >> 8; + // this._heightmap[i] = heightMap[x * 256 + y]; + //} + + //float[] swappedHeightMap = new float[65536]; + ////As the same as ODE, heightmap (x,y) must be swapped for BulletX + //for (int i = 0; i < 65536; i++) + //{ + // // this._heightmap[i] = (double)heightMap[i]; + // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) + // int x = i & 0xff; + // int y = i >> 8; + // swappedHeightMap[i] = heightMap[x * 256 + y]; + //} + DeleteTerrain(); + //There is a BulletXLock inside the constructor of BulletXPlanet + //this._simFlatPlanet = new BulletXPlanet(this, swappedHeightMap); + _simFlatPlanet = new BulletXPlanet(this, heightMap); + //this._heightmap = heightMap; + } + + public override void DeleteTerrain() + { + if (_simFlatPlanet != null) + { + lock (BulletXLock) + { + try + { + ddWorld.RemoveRigidBody(_simFlatPlanet.RigidBody); + } + catch (Exception ex) + { + BulletXMessage(is_ex_message + ex.Message, true); + _simFlatPlanet.RigidBody.ActivationState = ActivationState.DisableSimulation; + AddForgottenRigidBody(_simFlatPlanet.RigidBody); + } + } + _simFlatPlanet = null; + GC.Collect(); + BulletXMessage("Terrain erased!", false); + } + //this._heightmap = null; + } + + internal void AddForgottenRigidBody(RigidBody forgottenRigidBody) + { + _forgottenRigidBodies.Add(forgottenRigidBody); + } + + private void RemoveForgottenRigidBodies() + { + RigidBody forgottenRigidBody; + int nRigidBodies = _forgottenRigidBodies.Count; + for (int i = nRigidBodies - 1; i >= 0; i--) + { + forgottenRigidBody = _forgottenRigidBodies[i]; + try + { + ddWorld.RemoveRigidBody(forgottenRigidBody); + _forgottenRigidBodies.Remove(forgottenRigidBody); + BulletXMessage("Forgotten Rigid Body Removed", false); + } + catch (Exception ex) + { + BulletXMessage("Can't remove forgottenRigidBody!: " + ex.Message, false); + } + } + GC.Collect(); + } + + internal void BulletXMessage(string message, bool isWarning) + { + PhysicsPluginManager.PhysicsPluginMessage("[Modified BulletX]:\t" + message, isWarning); + } + + //temp + //private float HeightValue(MonoXnaCompactMaths.Vector3 position) + //{ + // int li_x, li_y; + // float height; + // li_x = (int)Math.Round(position.X); if (li_x < 0) li_x = 0; + // li_y = (int)Math.Round(position.Y); if (li_y < 0) li_y = 0; + + // height = this._heightmap[li_y * 256 + li_x]; + // if (height < 0) height = 0; + // else if (height > maxZ) height = maxZ; + + // return height; + //} + } + + /// + /// Generic Physics Actor for BulletX inherit from PhysicActor + /// + public class BulletXActor : PhysicsActor + { + protected bool flying = false; + protected bool _physical = false; + protected PhysicsVector _position; + protected PhysicsVector _velocity; + protected PhysicsVector _size; + protected PhysicsVector _acceleration; + protected AxiomQuaternion _orientation; + protected PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; + protected RigidBody rigidBody; + protected int m_PhysicsActorType; + private Boolean iscolliding = false; + internal string _name; + + public BulletXActor(String name) + { + _name = name; + } + + public override bool Stopped + { + get { return false; } + } + + public override PhysicsVector Position + { + get { return _position; } + set + { + lock (BulletXScene.BulletXLock) + { + _position = value; + Translate(); + } + } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + public override PhysicsVector Velocity + { + get { return _velocity; } + set + { + lock (BulletXScene.BulletXLock) + { + //Static objects don' have linear velocity + if (_physical) + { + _velocity = value; + Speed(); + } + else + { + _velocity = new PhysicsVector(); + } + } + } + } + public override float CollisionScore + { + get { return 0f; } + } + public override PhysicsVector Size + { + get { return _size; } + set + { + lock (BulletXScene.BulletXLock) + { + _size = value; + } + } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public override AxiomQuaternion Orientation + { + get { return _orientation; } + set + { + lock (BulletXScene.BulletXLock) + { + _orientation = value; + ReOrient(); + } + } + } + + public override float Mass + { + get { return ActorMass; } + } + + public virtual float ActorMass + { + get { return 0; } + } + + public override int PhysicsActorType + { + get { return (int) m_PhysicsActorType; } + set { m_PhysicsActorType = value; } + } + + public RigidBody RigidBody + { + get { return rigidBody; } + } + + public Vector3 RigidBodyPosition + { + get { return rigidBody.CenterOfMassPosition; } + } + + public override bool IsPhysical + { + get { return _physical; } + set { _physical = value; } + } + + public override bool Flying + { + get { return flying; } + set { flying = value; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public virtual void SetAcceleration(PhysicsVector accel) + { + lock (BulletXScene.BulletXLock) + { + _acceleration = accel; + } + } + + public override bool Kinematic + { + get { return false; } + set { } + } + + public override void AddForce(PhysicsVector force) + { + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + + internal virtual void ValidateHeight(float heighmapPositionValue) + { + } + + internal virtual void UpdateKinetics() + { + } + + #region Methods for updating values of RigidBody + + protected internal void Translate() + { + Translate(_position); + } + + protected internal void Translate(PhysicsVector _newPos) + { + Vector3 _translation; + _translation = BulletXMaths.PhysicsVectorToXnaVector3(_newPos) - rigidBody.CenterOfMassPosition; + rigidBody.Translate(_translation); + } + + protected internal void Speed() + { + Speed(_velocity); + } + + protected internal void Speed(PhysicsVector _newSpeed) + { + Vector3 _speed; + _speed = BulletXMaths.PhysicsVectorToXnaVector3(_newSpeed); + rigidBody.LinearVelocity = _speed; + } + + protected internal void ReOrient() + { + ReOrient(_orientation); + } + + protected internal void ReOrient(AxiomQuaternion _newOrient) + { + Quaternion _newOrientation; + _newOrientation = BulletXMaths.AxiomQuaternionToXnaQuaternion(_newOrient); + Matrix _comTransform = rigidBody.CenterOfMassTransform; + BulletXMaths.SetRotation(ref _comTransform, _newOrientation); + rigidBody.CenterOfMassTransform = _comTransform; + } + + protected internal void ReSize() + { + ReSize(_size); + } + + protected internal virtual void ReSize(PhysicsVector _newSize) + { + } + + public virtual void ScheduleTerseUpdate() + { + base.RequestPhysicsterseUpdate(); + } + + #endregion + + public override void CrossingFailure() + { + + } + } + + /// + /// PhysicsActor Character Class for BulletX + /// + public class BulletXCharacter : BulletXActor + { + public BulletXCharacter(BulletXScene parent_scene, PhysicsVector pos) + : this(String.Empty, parent_scene, pos) + { + } + + public BulletXCharacter(String avName, BulletXScene parent_scene, PhysicsVector pos) + : this(avName, parent_scene, pos, new PhysicsVector(), new PhysicsVector(), new PhysicsVector(), + AxiomQuaternion.Identity) + { + } + + public BulletXCharacter(String avName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, + PhysicsVector size, PhysicsVector acceleration, AxiomQuaternion orientation) + : base(avName) + { + //This fields will be removed. They're temporal + float _sizeX = 0.5f; + float _sizeY = 0.5f; + float _sizeZ = 1.6f; + //. + _position = pos; + _velocity = velocity; + _size = size; + //--- + _size.X = _sizeX; + _size.Y = _sizeY; + _size.Z = _sizeZ; + //. + _acceleration = acceleration; + _orientation = orientation; + _physical = true; + + float _mass = 50.0f; //This depends of avatar's dimensions + //For RigidBody Constructor. The next values might change + float _linearDamping = 0.0f; + float _angularDamping = 0.0f; + float _friction = 0.5f; + float _restitution = 0.0f; + Matrix _startTransform = Matrix.Identity; + Matrix _centerOfMassOffset = Matrix.Identity; + lock (BulletXScene.BulletXLock) + { + _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); + //CollisionShape _collisionShape = new BoxShape(new MonoXnaCompactMaths.Vector3(1.0f, 1.0f, 1.60f)); + //For now, like ODE, collisionShape = sphere of radious = 1.0 + CollisionShape _collisionShape = new SphereShape(1.0f); + DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); + Vector3 _localInertia = new Vector3(); + _collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0 + rigidBody = + new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, + _friction, _restitution); + //rigidBody.ActivationState = ActivationState.DisableDeactivation; + //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition + Vector3 _vDebugTranslation; + _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition; + rigidBody.Translate(_vDebugTranslation); + parent_scene.ddWorld.AddRigidBody(rigidBody); + } + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Agent; } + set { return; } + } + + public override PhysicsVector Position + { + get { return base.Position; } + set { base.Position = value; } + } + + public override PhysicsVector Velocity + { + get { return base.Velocity; } + set { base.Velocity = value; } + } + + public override PhysicsVector Size + { + get { return base.Size; } + set { base.Size = value; } + } + + public override PhysicsVector Acceleration + { + get { return base.Acceleration; } + } + + public override AxiomQuaternion Orientation + { + get { return base.Orientation; } + set { base.Orientation = value; } + } + + public override bool Flying + { + get { return base.Flying; } + set { base.Flying = value; } + } + + public override bool IsColliding + { + get { return base.IsColliding; } + set { base.IsColliding = value; } + } + + public override bool Kinematic + { + get { return base.Kinematic; } + set { base.Kinematic = value; } + } + + public override void SetAcceleration(PhysicsVector accel) + { + base.SetAcceleration(accel); + } + + public override void AddForce(PhysicsVector force) + { + base.AddForce(force); + } + + public override void SetMomentum(PhysicsVector momentum) + { + base.SetMomentum(momentum); + } + + internal void Move(float timeStep) + { + Vector3 vec = new Vector3(); + //At this point it's supossed that: + //_velocity == rigidBody.LinearVelocity + vec.X = _velocity.X; + vec.Y = _velocity.Y; + vec.Z = _velocity.Z; + if ((vec.X != 0.0f) || (vec.Y != 0.0f) || (vec.Z != 0.0f)) rigidBody.Activate(); + if (flying) + { + //Antigravity with movement + if (_position.Z <= BulletXScene.HeightLevel0) + { + vec.Z += BulletXScene.Gravity*timeStep; + } + //Lowgravity with movement + else if ((_position.Z > BulletXScene.HeightLevel0) + && (_position.Z <= BulletXScene.HeightLevel1)) + { + vec.Z += BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor); + } + //Lowgravity with... + else if (_position.Z > BulletXScene.HeightLevel1) + { + if (vec.Z > 0) //no movement + vec.Z = BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor); + else + vec.Z += BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor); + } + } + rigidBody.LinearVelocity = vec; + } + + //This validation is very basic + internal override void ValidateHeight(float heighmapPositionValue) + { + if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z/2.0f) + { + Matrix m = rigidBody.WorldTransform; + Vector3 v3 = m.Translation; + v3.Z = heighmapPositionValue + _size.Z/2.0f; + m.Translation = v3; + rigidBody.WorldTransform = m; + //When an Avie touch the ground it's vertical velocity it's reduced to ZERO + Speed(new PhysicsVector(rigidBody.LinearVelocity.X, rigidBody.LinearVelocity.Y, 0.0f)); + } + } + + internal override void UpdateKinetics() + { + _position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition); + _velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity); + //Orientation it seems that it will be the default. + ReOrient(); + } + } + + /// + /// PhysicsActor Prim Class for BulletX + /// + public class BulletXPrim : BulletXActor + { + //Density it will depends of material. + //For now all prims have the same density, all prims are made of water. Be water my friend! :D + private const float _density = 1000.0f; + private BulletXScene _parent_scene; + private PhysicsVector m_prev_position = new PhysicsVector(0, 0, 0); + private bool m_lastUpdateSent = false; + + public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size, + AxiomQuaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical) + : this( + primName, parent_scene, pos, new PhysicsVector(), size, new PhysicsVector(), rotation, mesh, pbs, + isPhysical) + { + } + + public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, + PhysicsVector size, + PhysicsVector acceleration, AxiomQuaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, + bool isPhysical) + : base(primName) + { + if ((size.X == 0) || (size.Y == 0) || (size.Z == 0)) throw new Exception("Size 0"); + if (rotation.Norm == 0f) rotation = AxiomQuaternion.Identity; + + _position = pos; + _physical = isPhysical; + _velocity = _physical ? velocity : new PhysicsVector(); + _size = size; + _acceleration = acceleration; + _orientation = rotation; + + _parent_scene = parent_scene; + + CreateRigidBody(parent_scene, mesh, pos, size); + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Prim; } + set { return; } + } + + public override PhysicsVector Position + { + get { return base.Position; } + set { base.Position = value; } + } + + public override PhysicsVector Velocity + { + get { return base.Velocity; } + set { base.Velocity = value; } + } + + public override PhysicsVector Size + { + get { return _size; } + set + { + lock (BulletXScene.BulletXLock) + { + _size = value; + ReSize(); + } + } + } + + public override PhysicsVector Acceleration + { + get { return base.Acceleration; } + } + + public override AxiomQuaternion Orientation + { + get { return base.Orientation; } + set { base.Orientation = value; } + } + + public override float ActorMass + { + get + { + //For now all prims are boxes + return (_physical ? 1 : 0)*_density*_size.X*_size.Y*_size.Z; + } + } + + public override bool IsPhysical + { + get { return base.IsPhysical; } + set + { + base.IsPhysical = value; + if (value) + { + //--- + PhysicsPluginManager.PhysicsPluginMessage("Physical - Recreate", true); + //--- + ReCreateRigidBody(_size); + } + else + { + //--- + PhysicsPluginManager.PhysicsPluginMessage("Physical - SetMassProps", true); + //--- + rigidBody.SetMassProps(Mass, new Vector3()); + } + } + } + + public override bool Flying + { + get { return base.Flying; } + set { base.Flying = value; } + } + + public override bool IsColliding + { + get { return base.IsColliding; } + set { base.IsColliding = value; } + } + + public override bool Kinematic + { + get { return base.Kinematic; } + set { base.Kinematic = value; } + } + + public override void SetAcceleration(PhysicsVector accel) + { + lock (BulletXScene.BulletXLock) + { + _acceleration = accel; + } + } + + public override void AddForce(PhysicsVector force) + { + base.AddForce(force); + } + + public override void SetMomentum(PhysicsVector momentum) + { + base.SetMomentum(momentum); + } + + internal override void ValidateHeight(float heighmapPositionValue) + { + if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z/2.0f) + { + Matrix m = rigidBody.WorldTransform; + Vector3 v3 = m.Translation; + v3.Z = heighmapPositionValue + _size.Z/2.0f; + m.Translation = v3; + rigidBody.WorldTransform = m; + //When a Prim touch the ground it's vertical velocity it's reduced to ZERO + //Static objects don't have linear velocity + if (_physical) + Speed(new PhysicsVector(rigidBody.LinearVelocity.X, rigidBody.LinearVelocity.Y, 0.0f)); + } + } + + internal override void UpdateKinetics() + { + if (_physical) //Updates properties. Prim updates its properties physically + { + _position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition); + + _velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity); + _orientation = BulletXMaths.XnaQuaternionToAxiomQuaternion(rigidBody.Orientation); + + if ((Math.Abs(m_prev_position.X - _position.X) < 0.03) + && (Math.Abs(m_prev_position.Y - _position.Y) < 0.03) + && (Math.Abs(m_prev_position.Z - _position.Z) < 0.03)) + { + if (!m_lastUpdateSent) + { + _velocity = new PhysicsVector(0, 0, 0); + base.ScheduleTerseUpdate(); + m_lastUpdateSent = true; + } + } + else + { + m_lastUpdateSent = false; + base.ScheduleTerseUpdate(); + } + m_prev_position = _position; + } + else //Doesn't updates properties. That's a cancel + { + Translate(); + //Speed(); //<- Static objects don't have linear velocity + ReOrient(); + } + } + + #region Methods for updating values of RigidBody + + protected internal void CreateRigidBody(BulletXScene parent_scene, IMesh mesh, PhysicsVector pos, + PhysicsVector size) + { + //For RigidBody Constructor. The next values might change + float _linearDamping = 0.0f; + float _angularDamping = 0.0f; + float _friction = 1.0f; + float _restitution = 0.0f; + Matrix _startTransform = Matrix.Identity; + Matrix _centerOfMassOffset = Matrix.Identity; + lock (BulletXScene.BulletXLock) + { + _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); + //For now all prims are boxes + CollisionShape _collisionShape; + if (mesh == null) + { + _collisionShape = new BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(size)/2.0f); + } + else + { + int iVertexCount = mesh.getVertexList().Count; + int[] indices = mesh.getIndexListAsInt(); + Vector3[] v3Vertices = new Vector3[iVertexCount]; + for (int i = 0; i < iVertexCount; i++) + { + PhysicsVector v = mesh.getVertexList()[i]; + if (v != null) // Note, null has special meaning. See meshing code for details + v3Vertices[i] = BulletXMaths.PhysicsVectorToXnaVector3(v); + else + v3Vertices[i] = Vector3.Zero; + } + TriangleIndexVertexArray triMesh = new TriangleIndexVertexArray(indices, v3Vertices); + + _collisionShape = new TriangleMeshShape(triMesh); + } + DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); + Vector3 _localInertia = new Vector3(); + if (_physical) _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0 + rigidBody = + new RigidBody(Mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, + _friction, _restitution); + //rigidBody.ActivationState = ActivationState.DisableDeactivation; + //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition + Vector3 _vDebugTranslation; + _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition; + rigidBody.Translate(_vDebugTranslation); + //--- + parent_scene.ddWorld.AddRigidBody(rigidBody); + } + } + + protected internal void ReCreateRigidBody(PhysicsVector size) + { + //There is a bug when trying to remove a rigidBody that is colliding with something.. + try + { + _parent_scene.ddWorld.RemoveRigidBody(rigidBody); + } + catch (Exception ex) + { + _parent_scene.BulletXMessage(_parent_scene.is_ex_message + ex.Message, true); + rigidBody.ActivationState = ActivationState.DisableSimulation; + _parent_scene.AddForgottenRigidBody(rigidBody); + } + CreateRigidBody(_parent_scene, null, _position, size); + // Note, null for the meshing definitely is wrong. It's here for the moment to apease the compiler + if (_physical) Speed(); //Static objects don't have linear velocity + ReOrient(); + GC.Collect(); + } + + protected internal override void ReSize(PhysicsVector _newSize) + { + //I wonder to know how to resize with a simple instruction in BulletX. It seems that for now there isn't + //so i have to do it manually. That's recreating rigidbody + ReCreateRigidBody(_newSize); + } + + #endregion + } + + /// + /// This Class manage a HeighField as a RigidBody. This is for to be added in the BulletXScene + /// + internal class BulletXPlanet + { + private PhysicsVector _staticPosition; + private PhysicsVector _staticVelocity; + private AxiomQuaternion _staticOrientation; + private float _mass; + private BulletXScene _parentscene; + internal float[] _heightField; + private RigidBody _flatPlanet; + + internal RigidBody RigidBody + { + get { return _flatPlanet; } + } + + internal BulletXPlanet(BulletXScene parent_scene, float[] heightField) + { + _staticPosition = new PhysicsVector(BulletXScene.MaxXY/2, BulletXScene.MaxXY/2, 0); + _staticVelocity = new PhysicsVector(); + _staticOrientation = AxiomQuaternion.Identity; + _mass = 0; //No active + _parentscene = parent_scene; + _heightField = heightField; + + float _linearDamping = 0.0f; + float _angularDamping = 0.0f; + float _friction = 0.5f; + float _restitution = 0.0f; + Matrix _startTransform = Matrix.Identity; + Matrix _centerOfMassOffset = Matrix.Identity; + + lock (BulletXScene.BulletXLock) + { + try + { + _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(_staticPosition); + CollisionShape _collisionShape = + new HeightfieldTerrainShape(BulletXScene.MaxXY, BulletXScene.MaxXY, _heightField, + (float) BulletXScene.MaxZ, 2, true, false); + DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); + Vector3 _localInertia = new Vector3(); + //_collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0 + _flatPlanet = + new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, + _angularDamping, _friction, _restitution); + //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition + Vector3 _vDebugTranslation; + _vDebugTranslation = _startTransform.Translation - _flatPlanet.CenterOfMassPosition; + _flatPlanet.Translate(_vDebugTranslation); + parent_scene.ddWorld.AddRigidBody(_flatPlanet); + } + catch (Exception ex) + { + _parentscene.BulletXMessage(ex.Message, true); + } + } + _parentscene.BulletXMessage("BulletXPlanet created.", false); + } + + internal float HeightValue(Vector3 position) + { + int li_x, li_y; + float height; + li_x = (int) Math.Round(position.X); + if (li_x < 0) li_x = 0; + if (li_x >= BulletXScene.MaxXY) li_x = BulletXScene.MaxXY - 1; + li_y = (int) Math.Round(position.Y); + if (li_y < 0) li_y = 0; + if (li_y >= BulletXScene.MaxXY) li_y = BulletXScene.MaxXY - 1; + + height = ((HeightfieldTerrainShape) _flatPlanet.CollisionShape).getHeightFieldValue(li_x, li_y); + if (height < 0) height = 0; + else if (height > BulletXScene.MaxZ) height = BulletXScene.MaxZ; + + return height; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs b/trunk/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs new file mode 100644 index 0000000000..e73c95378e --- /dev/null +++ b/trunk/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs @@ -0,0 +1,198 @@ +/* + Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru + Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + + This file contains a class TriangleIndexVertexArray. I tried using the class with the same name + from the BulletX implementation and found it unusable for the purpose of using triangle meshes + within BulletX as the implementation was painfully incomplete. + The attempt to derive from the original class failed as viable members were hidden. + Fiddling around with BulletX itself was not my intention. + So I copied the class to the BulletX-plugin and modified it. + If you want to fiddle around with it it's up to you to move all this to BulletX. + If someone someday implements the missing functionality in BulletX, feel free to remove this class. + It's just an ugly hack. + + */ +using System; +using System.Collections.Generic; +using MonoXnaCompactMaths; +using XnaDevRu.BulletX; + +namespace OpenSim.Region.Physics.BulletXPlugin +{ + /// + /// IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements + /// instead of the number of indices, we pass the number of triangles + /// + public struct IndexedMesh + { + private int _numTriangles; + private int[] _triangleIndexBase; + private int _triangleIndexStride; + private int _numVertices; + private Vector3[] _vertexBase; + private int _vertexStride; + + public IndexedMesh(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices, + Vector3[] vertexBase, int vertexStride) + { + _numTriangles = numTriangleIndices; + _triangleIndexBase = triangleIndexBase; + _triangleIndexStride = triangleIndexStride; + _vertexBase = vertexBase; + _numVertices = numVertices; + _vertexStride = vertexStride; + } + + public IndexedMesh(int[] triangleIndexBase, Vector3[] vertexBase) + { + _numTriangles = triangleIndexBase.Length; + _triangleIndexBase = triangleIndexBase; + _triangleIndexStride = 32; + _vertexBase = vertexBase; + _numVertices = vertexBase.Length; + _vertexStride = 24; + } + + public int TriangleCount + { + get { return _numTriangles; } + set { _numTriangles = value; } + } + + public int[] TriangleIndexBase + { + get { return _triangleIndexBase; } + set { _triangleIndexBase = value; } + } + + public int TriangleIndexStride + { + get { return _triangleIndexStride; } + set { _triangleIndexStride = value; } + } + + public int VertexCount + { + get { return _numVertices; } + set { _numVertices = value; } + } + + public Vector3[] VertexBase + { + get { return _vertexBase; } + set { _vertexBase = value; } + } + + public int VertexStride + { + get { return _vertexStride; } + set { _vertexStride = value; } + } + } + + /// + /// TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays. + /// Additional meshes can be added using addIndexedMesh + /// + public class TriangleIndexVertexArray : StridingMeshInterface + { + private List _indexedMeshes = new List(); + + public TriangleIndexVertexArray() + { + } + + public TriangleIndexVertexArray(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, + int numVertices, Vector3[] vertexBase, int vertexStride) + { + IndexedMesh mesh = new IndexedMesh(); + mesh.TriangleCount = numTriangleIndices; + mesh.TriangleIndexBase = triangleIndexBase; + mesh.TriangleIndexStride = triangleIndexStride; + mesh.VertexBase = vertexBase; + mesh.VertexCount = numVertices; + mesh.VertexStride = vertexStride; + + AddIndexedMesh(mesh); + } + + public TriangleIndexVertexArray(int[] triangleIndexBase, Vector3[] vertexBase) + : this(triangleIndexBase.Length, triangleIndexBase, 32, vertexBase.Length, vertexBase, 24) + { + } + + public void AddIndexedMesh(IndexedMesh indexedMesh) + { + _indexedMeshes.Add(indexedMesh); + } + + public override void GetLockedVertexIndexBase(out List verts, out List indicies, out int numfaces, + int subpart) + { + throw new Exception("The method or operation is not implemented."); + } + + public override void GetLockedReadOnlyVertexIndexBase(out List verts, out List indicies, + out int numfaces, int subpart) + { + IndexedMesh m = _indexedMeshes[0]; + Vector3[] vertexBase = m.VertexBase; + verts = new List(); + foreach (Vector3 v in vertexBase) + { + verts.Add(v); + } + int[] indexBase = m.TriangleIndexBase; + indicies = new List(); + foreach (int i in indexBase) + { + indicies.Add(i); + } + numfaces = vertexBase.GetLength(0); + } + + public override void UnLockVertexBase(int subpart) + { + throw new Exception("The method or operation is not implemented."); + } + + public override void UnLockReadOnlyVertexBase(int subpart) + { + } + + public override int SubPartsCount() + { + return _indexedMeshes.Count; + } + + public override void PreallocateVertices(int numverts) + { + throw new Exception("The method or operation is not implemented."); + } + + public override void PreallocateIndices(int numindices) + { + throw new Exception("The method or operation is not implemented."); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/Manager/AssemblyInfo.cs b/trunk/OpenSim/Region/Physics/Manager/AssemblyInfo.cs new file mode 100644 index 0000000000..983a2b91b6 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Manager/AssemblyInfo.cs @@ -0,0 +1,58 @@ +/* +* 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; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly : AssemblyTitle("PhysicsManager")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("PhysicsManager")] +[assembly : AssemblyCopyright("")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. + +[assembly : ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly : AssemblyVersion("1.0.*")] \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/Manager/CollisionLocker.cs b/trunk/OpenSim/Region/Physics/Manager/CollisionLocker.cs new file mode 100644 index 0000000000..98e9736a93 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Manager/CollisionLocker.cs @@ -0,0 +1,74 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.Physics.Manager +{ + public class CollisionLocker + { + + + private List worldlock = new List(); + public CollisionLocker() + { + + } + public void dlock(IntPtr world) + { + lock (worldlock) + { + worldlock.Add(world); + } + + } + public void dunlock(IntPtr world) + { + lock (worldlock) + { + worldlock.Remove(world); + } + } + public bool lockquery() + { + return (worldlock.Count > 0); + } + public void drelease(IntPtr world) + { + lock (worldlock) + { + if (worldlock.Contains(world)) + worldlock.Remove(world); + } + } + + } + +} diff --git a/trunk/OpenSim/Region/Physics/Manager/IMesher.cs b/trunk/OpenSim/Region/Physics/Manager/IMesher.cs new file mode 100644 index 0000000000..80b3320c8f --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Manager/IMesher.cs @@ -0,0 +1,51 @@ +/* +* 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; +using System.Collections.Generic; +using OpenSim.Framework; + +namespace OpenSim.Region.Physics.Manager +{ + public interface IMesher + { + IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size); + } + + public interface IVertex + { + } + + public interface IMesh + { + List getVertexList(); + int[] getIndexListAsInt(); + int[] getIndexListAsIntLocked(); + float[] getVertexListAsFloatLocked(); + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/trunk/OpenSim/Region/Physics/Manager/PhysicsActor.cs new file mode 100644 index 0000000000..b96ce27482 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -0,0 +1,360 @@ +/* +* 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; +using System.Collections.Generic; +using Axiom.Math; +using OpenSim.Framework; + +namespace OpenSim.Region.Physics.Manager +{ + public delegate void PositionUpdate(PhysicsVector position); + + public delegate void VelocityUpdate(PhysicsVector velocity); + + public delegate void OrientationUpdate(Quaternion orientation); + + public enum ActorTypes : int + { + Unknown = 0, + Agent = 1, + Prim = 2, + Ground = 3 + } + + public class CollisionEventUpdate : EventArgs + { + // Raising the event on the object, so don't need to provide location.. further up the tree knows that info. + + + public int m_colliderType; + public bool m_startOrEnd; + //public uint m_LocalID; + public List m_objCollisionList; + + public CollisionEventUpdate(uint localID, int colliderType, bool startOrEnd, List objCollisionList) + { + m_colliderType = colliderType; + m_startOrEnd = startOrEnd; + m_objCollisionList = objCollisionList; + } + + public CollisionEventUpdate(bool startOrEnd) + { + m_colliderType = (int) ActorTypes.Unknown; + m_startOrEnd = startOrEnd; + m_objCollisionList = null; + } + + public CollisionEventUpdate() + { + m_colliderType = (int) ActorTypes.Unknown; + m_startOrEnd = false; + m_objCollisionList = null; + } + + public int collidertype + { + get { return m_colliderType; } + set { m_colliderType = value; } + } + + public bool startOrEnd + { + get { return m_startOrEnd; } + set { m_startOrEnd = value; } + } + + public void addCollider(uint localID) + { + m_objCollisionList.Add(localID); + } + } + + + public abstract class PhysicsActor + { + public delegate void RequestTerseUpdate(); + + public delegate void CollisionUpdate(EventArgs e); + + public delegate void OutOfBounds(PhysicsVector pos); + +#pragma warning disable 67 + public event PositionUpdate OnPositionUpdate; + public event VelocityUpdate OnVelocityUpdate; + public event OrientationUpdate OnOrientationUpdate; + public event RequestTerseUpdate OnRequestTerseUpdate; + public event CollisionUpdate OnCollisionUpdate; + public event OutOfBounds OnOutOfBounds; +#pragma warning restore 67 + + public static PhysicsActor Null + { + get { return new NullPhysicsActor(); } + } + + public abstract bool Stopped { get; } + + public abstract PhysicsVector Size { get; set; } + + public abstract PrimitiveBaseShape Shape { set; } + + public abstract bool Grabbed { set; } + + public abstract bool Selected { set; } + + public abstract void CrossingFailure(); + + public virtual void RequestPhysicsterseUpdate() + { + // Make a temporary copy of the event to avoid possibility of + // a race condition if the last subscriber unsubscribes + // immediately after the null check and before the event is raised. + RequestTerseUpdate handler = OnRequestTerseUpdate; + if (handler != null) + { + OnRequestTerseUpdate(); + } + } + + public virtual void RaiseOutOfBounds(PhysicsVector pos) + { + // Make a temporary copy of the event to avoid possibility of + // a race condition if the last subscriber unsubscribes + // immediately after the null check and before the event is raised. + OutOfBounds handler = OnOutOfBounds; + if (handler != null) + { + OnOutOfBounds(pos); + } + } + + public virtual void SendCollisionUpdate(EventArgs e) + { + CollisionUpdate handler = OnCollisionUpdate; + if (handler != null) + { + OnCollisionUpdate(e); + } + } + + + public abstract PhysicsVector Position { get; set; } + + public abstract float Mass { get; } + + public abstract PhysicsVector Force { get; } + + public abstract PhysicsVector GeometricCenter { get; } + + public abstract PhysicsVector CenterOfMass { get; } + + public abstract PhysicsVector Velocity { get; set; } + + public abstract float CollisionScore { get;} + + public abstract PhysicsVector Acceleration { get; } + + public abstract Quaternion Orientation { get; set; } + public abstract int PhysicsActorType { get; set; } + + public abstract bool IsPhysical { get; set; } + + public abstract bool Flying { get; set; } + public abstract bool SetAlwaysRun { get; set; } + public abstract bool ThrottleUpdates { get; set; } + + public abstract bool IsColliding { get; set; } + public abstract bool CollidingGround { get; set; } + public abstract bool CollidingObj { get; set; } + + public abstract PhysicsVector RotationalVelocity { get; set; } + + public abstract bool Kinematic { get; set; } + + public abstract void AddForce(PhysicsVector force); + + public abstract void SetMomentum(PhysicsVector momentum); + + + } + + public class NullPhysicsActor : PhysicsActor + { + public override bool Stopped + { + get{ return false; } + } + + public override PhysicsVector Position + { + get { return PhysicsVector.Zero; } + set { return; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override PhysicsVector Size + { + get { return PhysicsVector.Zero; } + set { return; } + } + + public override float Mass + { + get { return 0f; } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override PhysicsVector Velocity + { + get { return PhysicsVector.Zero; } + set { return; } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override void CrossingFailure() + { + + } + + + public override Quaternion Orientation + { + get { return Quaternion.Identity; } + set { } + } + + public override PhysicsVector Acceleration + { + get { return PhysicsVector.Zero; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool Flying + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool IsColliding + { + get { return false; } + set { return; } + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Unknown; } + set { return; } + } + + public override bool Kinematic + { + get { return true; } + set { return; } + } + + public override void AddForce(PhysicsVector force) + { + return; + } + + public override PhysicsVector RotationalVelocity + { + get { return PhysicsVector.Zero; } + set { return; } + } + + public override void SetMomentum(PhysicsVector momentum) + { + return; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs b/trunk/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs new file mode 100644 index 0000000000..76ea503b62 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs @@ -0,0 +1,176 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Physics.Manager +{ + /// + /// Description of MyClass. + /// + public class PhysicsPluginManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private Dictionary _PhysPlugins = new Dictionary(); + private Dictionary _MeshPlugins = new Dictionary(); + + public PhysicsPluginManager() + { + } + + public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName) + { + if (String.IsNullOrEmpty(physEngineName)) + { + return PhysicsScene.Null; + } + + if (String.IsNullOrEmpty(meshEngineName)) + { + return PhysicsScene.Null; + } + + IMesher meshEngine = null; + if (_MeshPlugins.ContainsKey(meshEngineName)) + { + m_log.Info("[PHYSICS]: creating meshing engine " + meshEngineName); + meshEngine = _MeshPlugins[meshEngineName].GetMesher(); + } + else + { + m_log.WarnFormat("[PHYSICS]: couldn't find meshingEngine: {0}", meshEngineName); + throw new ArgumentException(String.Format("couldn't find meshingEngine: {0}", meshEngineName)); + } + + if (_PhysPlugins.ContainsKey(physEngineName)) + { + m_log.Info("[PHYSICS]: creating " + physEngineName); + PhysicsScene result = _PhysPlugins[physEngineName].GetScene(); + result.Initialise(meshEngine); + return result; + } + else + { + m_log.WarnFormat("[PHYSICS]: couldn't find physicsEngine: {0}", physEngineName); + throw new ArgumentException(String.Format("couldn't find physicsEngine: {0}", physEngineName)); + } + } + + public void LoadPlugins() + { + // Load "plugins", that are hard coded and not existing in form of an external lib + IMeshingPlugin plugHard; + plugHard = new ZeroMesherPlugin(); + _MeshPlugins.Add(plugHard.GetName(), plugHard); + m_log.Info("[PHYSICS]: Added meshing engine: " + plugHard.GetName()); + + // And now walk all assemblies (DLLs effectively) and see if they are home + // of a plugin that is of interest for us + string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Physics"); + string[] pluginFiles = Directory.GetFiles(path, "*.dll"); + + for (int i = 0; i < pluginFiles.Length; i++) + { + AddPlugin(pluginFiles[i]); + } + } + + private void AddPlugin(string FileName) + { + Assembly pluginAssembly = Assembly.LoadFrom(FileName); + + foreach (Type pluginType in pluginAssembly.GetTypes()) + { + if (pluginType.IsPublic) + { + if (!pluginType.IsAbstract) + { + Type physTypeInterface = pluginType.GetInterface("IPhysicsPlugin", true); + + if (physTypeInterface != null) + { + IPhysicsPlugin plug = + (IPhysicsPlugin) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + plug.Init(); + _PhysPlugins.Add(plug.GetName(), plug); + m_log.Info("[PHYSICS]: Added physics engine: " + plug.GetName()); + } + + Type meshTypeInterface = pluginType.GetInterface("IMeshingPlugin", true); + + if (meshTypeInterface != null) + { + IMeshingPlugin plug = + (IMeshingPlugin) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + _MeshPlugins.Add(plug.GetName(), plug); + m_log.Info("[PHYSICS]: Added meshing engine: " + plug.GetName()); + } + + physTypeInterface = null; + meshTypeInterface = null; + } + } + } + + pluginAssembly = null; + } + + //--- + public static void PhysicsPluginMessage(string message, bool isWarning) + { + if (isWarning) + { + m_log.Warn("[PHYSICS]: " + message); + } + else + { + m_log.Info("[PHYSICS]: " + message); + } + } + + //--- + } + + public interface IPhysicsPlugin + { + bool Init(); + PhysicsScene GetScene(); + string GetName(); + void Dispose(); + } + + public interface IMeshingPlugin + { + string GetName(); + IMesher GetMesher(); + } +} diff --git a/trunk/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/trunk/OpenSim/Region/Physics/Manager/PhysicsScene.cs new file mode 100644 index 0000000000..996aed640b --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -0,0 +1,168 @@ +/* +* 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; +using Axiom.Math; +using OpenSim.Framework; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Physics.Manager +{ + public delegate void physicsCrash(); + + public abstract class PhysicsScene + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // The only thing that should register for this event is the InnerScene + // Anything else could cause problems. + + public event physicsCrash OnPhysicsCrash; + + public static PhysicsScene Null + { + get { return new NullPhysicsScene(); } + } + + public virtual void TriggerPhysicsBasedRestart() + { + physicsCrash handler = OnPhysicsCrash; + if (handler != null) + { + OnPhysicsCrash(); + } + } + + + public abstract void Initialise(IMesher meshmerizer); + + public abstract PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size); + + public abstract void RemoveAvatar(PhysicsActor actor); + + public abstract void RemovePrim(PhysicsActor prim); + + public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation); //To be removed + public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical); + + public abstract void AddPhysicsActorTaint(PhysicsActor prim); + + public abstract float Simulate(float timeStep); + + public abstract void GetResults(); + + public abstract void SetTerrain(float[] heightMap); + + public abstract void DeleteTerrain(); + + public abstract void Dispose(); + + public abstract bool IsThreaded { get; } + + private class NullPhysicsScene : PhysicsScene + { + private static int m_workIndicator; + + + public override void Initialise(IMesher meshmerizer) + { + // Does nothing right now + } + + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) + { + m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : AddAvatar({0})", position); + return PhysicsActor.Null; + } + + public override void RemoveAvatar(PhysicsActor actor) + { + } + + public override void RemovePrim(PhysicsActor prim) + { + } + +/* + public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation) + { + m_log.InfoFormat("NullPhysicsScene : AddPrim({0},{1})", position, size); + return PhysicsActor.Null; + } +*/ + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation) //To be removed + { + return AddPrimShape(primName, pbs, position, size, rotation, false); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical) + { + m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : AddPrim({0},{1})", position, size); + return PhysicsActor.Null; + } + + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + } + + public override float Simulate(float timeStep) + { + m_workIndicator = (m_workIndicator + 1) % 10; + + return 0f; + } + + public override void GetResults() + { + m_log.Info("[PHYSICS]: NullPhysicsScene : GetResults()"); + } + + public override void SetTerrain(float[] heightMap) + { + m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : SetTerrain({0} items)", heightMap.Length); + } + + public override void DeleteTerrain() + { + } + + public override bool IsThreaded + { + get { return false; } + } + public override void Dispose() + { + + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/Manager/PhysicsSensor.cs b/trunk/OpenSim/Region/Physics/Manager/PhysicsSensor.cs new file mode 100644 index 0000000000..b85c5b31cb --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Manager/PhysicsSensor.cs @@ -0,0 +1,86 @@ +/* +* 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; +using System.Collections.Generic; +using System.Timers; +using Axiom.Math; +using OpenSim.Framework; + +namespace OpenSim.Region.Physics.Manager +{ + [Flags] + public enum SenseType : uint + { + NONE = 0, + AGENT = 1, + ACTIVE = 2, + PASSIVE = 3, + SCRIPTED = 4 + + } + public abstract class PhysicsSensor + { + + public static PhysicsSensor Null + { + get { return new NullPhysicsSensor(); } + } + public abstract PhysicsVector Position {get; set;} + public abstract void TimerCallback (object obj, ElapsedEventArgs eea); + public abstract float radianarc {get; set;} + public abstract string targetname {get; set;} + public abstract Guid targetKey{get;set;} + public abstract SenseType sensetype { get;set;} + public abstract float range { get;set;} + public abstract float rateSeconds { get;set;} + + + + } + + public class NullPhysicsSensor : PhysicsSensor + { + + public override PhysicsVector Position + { + get { return PhysicsVector.Zero; } + set { return; } + } + public override void TimerCallback(object obj, ElapsedEventArgs eea) + { + // don't do squat + } + public override float radianarc { get { return 0f; } set { } } + public override string targetname { get { return ""; } set { } } + public override Guid targetKey { get { return Guid.Empty; } set { } } + public override SenseType sensetype { get { return SenseType.NONE; } set { } } + public override float range { get { return 0; } set { } } + public override float rateSeconds { get { return 0; } set { } } + + } +} diff --git a/trunk/OpenSim/Region/Physics/Manager/PhysicsVector.cs b/trunk/OpenSim/Region/Physics/Manager/PhysicsVector.cs new file mode 100644 index 0000000000..4b2e7560e8 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Manager/PhysicsVector.cs @@ -0,0 +1,158 @@ +/* +* 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; + +namespace OpenSim.Region.Physics.Manager +{ + public class PhysicsVector + { + public float X; + public float Y; + public float Z; + + public PhysicsVector() + { + } + + public PhysicsVector(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + public void setValues(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + public static readonly PhysicsVector Zero = new PhysicsVector(0f, 0f, 0f); + + public override string ToString() + { + return "<" + X + "," + Y + "," + Z + ">"; + } + + /// + /// These routines are the easiest way to store XYZ values in an LLVector3 without requiring 3 calls. + /// + /// + public byte[] GetBytes() + { + byte[] byteArray = new byte[12]; + + Buffer.BlockCopy(BitConverter.GetBytes(X), 0, byteArray, 0, 4); + Buffer.BlockCopy(BitConverter.GetBytes(Y), 0, byteArray, 4, 4); + Buffer.BlockCopy(BitConverter.GetBytes(Z), 0, byteArray, 8, 4); + + if (!BitConverter.IsLittleEndian) + { + Array.Reverse(byteArray, 0, 4); + Array.Reverse(byteArray, 4, 4); + Array.Reverse(byteArray, 8, 4); + } + + return byteArray; + } + + public void FromBytes(byte[] byteArray, int pos) + { + byte[] conversionBuffer = null; + if (!BitConverter.IsLittleEndian) + { + // Big endian architecture + if (conversionBuffer == null) + conversionBuffer = new byte[12]; + + Buffer.BlockCopy(byteArray, pos, conversionBuffer, 0, 12); + + Array.Reverse(conversionBuffer, 0, 4); + Array.Reverse(conversionBuffer, 4, 4); + Array.Reverse(conversionBuffer, 8, 4); + + X = BitConverter.ToSingle(conversionBuffer, 0); + Y = BitConverter.ToSingle(conversionBuffer, 4); + Z = BitConverter.ToSingle(conversionBuffer, 8); + } + else + { + // Little endian architecture + X = BitConverter.ToSingle(byteArray, pos); + Y = BitConverter.ToSingle(byteArray, pos + 4); + Z = BitConverter.ToSingle(byteArray, pos + 8); + } + } + + // Operations + public static PhysicsVector operator +(PhysicsVector a, PhysicsVector b) + { + return new PhysicsVector(a.X + b.X, a.Y + b.Y, a.Z + b.Z); + } + + public static PhysicsVector operator -(PhysicsVector a, PhysicsVector b) + { + return new PhysicsVector(a.X - b.X, a.Y - b.Y, a.Z - b.Z); + } + + public static PhysicsVector cross(PhysicsVector a, PhysicsVector b) + { + return new PhysicsVector(a.Y*b.Z - a.Z*b.Y, a.Z*b.X - a.X*b.Z, a.X*b.Y - a.Y*b.X); + } + + public float length() + { + return (float) Math.Sqrt(X*X + Y*Y + Z*Z); + } + + public static PhysicsVector operator /(PhysicsVector v, float f) + { + return new PhysicsVector(v.X/f, v.Y/f, v.Z/f); + } + + public static PhysicsVector operator *(PhysicsVector v, float f) + { + return new PhysicsVector(v.X*f, v.Y*f, v.Z*f); + } + + public static PhysicsVector operator *(float f, PhysicsVector v) + { + return v*f; + } + + public virtual bool IsIdentical(PhysicsVector v, float tolerance) + { + PhysicsVector diff = this - v; + float d = diff.length(); + if (d < tolerance) + return true; + + return false; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/Manager/ZeroMesher.cs b/trunk/OpenSim/Region/Physics/Manager/ZeroMesher.cs new file mode 100644 index 0000000000..7dae4ac31e --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Manager/ZeroMesher.cs @@ -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 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; +using OpenSim.Framework; + +/* + * This is the zero mesher. + * Whatever you want him to mesh, he can't, telling you that by responding with a null pointer. + * Effectivly this is for switching off meshing and for testing as each physics machine should deal + * with the null pointer situation. + * But it's also a convenience thing, as physics machines can rely on having a mesher in any situation, even + * if it's a dump one like this. + * Note, that this mesher is *not* living in a module but in the manager itself, so + * it's always availabe and thus the default in case of configuration errors +*/ + +namespace OpenSim.Region.Physics.Manager +{ + public class ZeroMesherPlugin : IMeshingPlugin + { + public ZeroMesherPlugin() + { + } + + public string GetName() + { + return "ZeroMesher"; + } + + public IMesher GetMesher() + { + return new ZeroMesher(); + } + } + + public class ZeroMesher : IMesher + { + public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + { + return null; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/Meshing/Extruder.cs b/trunk/OpenSim/Region/Physics/Meshing/Extruder.cs new file mode 100644 index 0000000000..086261b870 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Meshing/Extruder.cs @@ -0,0 +1,125 @@ +/* +* 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 OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.Meshing +{ + internal class Extruder + { + public float startParameter; + public float stopParameter; + public PhysicsVector size; + + public float taperTopFactorX = 1f; + public float taperTopFactorY = 1f; + public float taperBotFactorX = 1f; + public float taperBotFactorY = 1f; + public float pushX = 0f; + public float pushY = 0f; + + public Mesh Extrude(Mesh m) + { + // Currently only works for iSteps=1; + Mesh result = new Mesh(); + + Mesh workingPlus = m.Clone(); + Mesh workingMinus = m.Clone(); + + foreach (Vertex v in workingPlus.vertices) + { + if (v == null) + continue; + + // This is the top + // Set the Z + .5 to match the rest of the scale of the mesh + // Scale it by Size, and Taper the scaling + v.Z = +.5f; + v.X *= (size.X * taperTopFactorX); + v.Y *= (size.Y * taperTopFactorY); + v.Z *= size.Z; + + //Push the top of the object over by the Top Shear amount + v.X += pushX * size.X; + v.Y += pushY * size.X; + } + + foreach (Vertex v in workingMinus.vertices) + { + if (v == null) + continue; + + // This is the bottom + v.Z = -.5f; + v.X *= (size.X * taperBotFactorX); + v.Y *= (size.Y * taperBotFactorY); + v.Z *= size.Z; + } + + foreach (Triangle t in workingMinus.triangles) + { + t.invertNormal(); + } + + result.Append(workingMinus); + result.Append(workingPlus); + + int iLastNull = 0; + for (int i = 0; i < workingPlus.vertices.Count; i++) + { + int iNext = (i + 1); + + if (workingPlus.vertices[i] == null) // Can't make a simplex here + { + iLastNull = i + 1; + continue; + } + + if (i == workingPlus.vertices.Count - 1) // End of list + { + iNext = iLastNull; + } + + if (workingPlus.vertices[iNext] == null) // Null means wrap to begin of last segment + { + iNext = iLastNull; + } + + Triangle tSide; + tSide = new Triangle(workingPlus.vertices[i], workingMinus.vertices[i], workingPlus.vertices[iNext]); + result.Add(tSide); + + tSide = + new Triangle(workingPlus.vertices[iNext], workingMinus.vertices[i], workingMinus.vertices[iNext]); + result.Add(tSide); + } + + return result; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/Meshing/HelperTypes.cs b/trunk/OpenSim/Region/Physics/Meshing/HelperTypes.cs new file mode 100644 index 0000000000..ac06614fbf --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Meshing/HelperTypes.cs @@ -0,0 +1,304 @@ +/* +* 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; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using OpenSim.Region.Physics.Manager; +using OpenSim.Region.Physics.Meshing; + +public class Vertex : PhysicsVector, IComparable +{ + public Vertex(float x, float y, float z) + : base(x, y, z) + { + } + + public Vertex(PhysicsVector v) + : base(v.X, v.Y, v.Z) + { + } + + public Vertex Clone() + { + return new Vertex(X, Y, Z); + } + + public static Vertex FromAngle(double angle) + { + return new Vertex((float) Math.Cos(angle), (float) Math.Sin(angle), 0.0f); + } + + + public virtual bool Equals(Vertex v, float tolerance) + { + PhysicsVector diff = this - v; + float d = diff.length(); + if (d < tolerance) + return true; + + return false; + } + + + public int CompareTo(Vertex other) + { + if (X < other.X) + return -1; + + if (X > other.X) + return 1; + + if (Y < other.Y) + return -1; + + if (Y > other.Y) + return 1; + + if (Z < other.Z) + return -1; + + if (Z > other.Z) + return 1; + + return 0; + } + + public static bool operator >(Vertex me, Vertex other) + { + return me.CompareTo(other) > 0; + } + + public static bool operator <(Vertex me, Vertex other) + { + return me.CompareTo(other) < 0; + } + + public String ToRaw() + { + // Why this stuff with the number formatter? + // Well, the raw format uses the english/US notation of numbers + // where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1. + // The german notation uses these characters exactly vice versa! + // The Float.ToString() routine is a localized one, giving different results depending on the country + // settings your machine works with. Unusable for a machine readable file format :-( + NumberFormatInfo nfi = new NumberFormatInfo(); + nfi.NumberDecimalSeparator = "."; + nfi.NumberDecimalDigits = 3; + + String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi); + + return s1; + } +} + +public class Triangle +{ + public Vertex v1; + public Vertex v2; + public Vertex v3; + + private float radius_square; + private float cx; + private float cy; + + public Triangle(Vertex _v1, Vertex _v2, Vertex _v3) + { + v1 = _v1; + v2 = _v2; + v3 = _v3; + + CalcCircle(); + } + + public bool isInCircle(float x, float y) + { + float dx, dy; + float dd; + + dx = x - cx; + dy = y - cy; + + dd = dx*dx + dy*dy; + if (dd < radius_square) + return true; + else + return false; + } + + public bool isDegraded() + { + // This means, the vertices of this triangle are somewhat strange. + // They either line up or at least two of them are identical + return (radius_square == 0.0); + } + + private void CalcCircle() + { + // Calculate the center and the radius of a circle given by three points p1, p2, p3 + // It is assumed, that the triangles vertices are already set correctly + double p1x, p2x, p1y, p2y, p3x, p3y; + + // Deviation of this routine: + // A circle has the general equation (M-p)^2=r^2, where M and p are vectors + // this gives us three equations f(p)=r^2, each for one point p1, p2, p3 + // putting respectively two equations together gives two equations + // f(p1)=f(p2) and f(p1)=f(p3) + // bringing all constant terms to one side brings them to the form + // M*v1=c1 resp.M*v2=c2 where v1=(p1-p2) and v2=(p1-p3) (still vectors) + // and c1, c2 are scalars (Naming conventions like the variables below) + // Now using the equations that are formed by the components of the vectors + // and isolate Mx lets you make one equation that only holds My + // The rest is straight forward and eaasy :-) + // + + /* helping variables for temporary results */ + double c1, c2; + double v1x, v1y, v2x, v2y; + + double z, n; + + double rx, ry; + + // Readout the three points, the triangle consists of + p1x = v1.X; + p1y = v1.Y; + + p2x = v2.X; + p2y = v2.Y; + + p3x = v3.X; + p3y = v3.Y; + + /* calc helping values first */ + c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2; + c2 = (p1x*p1x + p1y*p1y - p3x*p3x - p3y*p3y)/2; + + v1x = p1x - p2x; + v1y = p1y - p2y; + + v2x = p1x - p3x; + v2y = p1y - p3y; + + z = (c1*v2x - c2*v1x); + n = (v1y*v2x - v2y*v1x); + + if (n == 0.0) // This is no triangle, i.e there are (at least) two points at the same location + { + radius_square = 0.0f; + return; + } + + cy = (float) (z/n); + + if (v2x != 0.0) + { + cx = (float) ((c2 - v2y*cy)/v2x); + } + else if (v1x != 0.0) + { + cx = (float) ((c1 - v1y*cy)/v1x); + } + else + { + Debug.Assert(false, "Malformed triangle"); /* Both terms zero means nothing good */ + } + + rx = (p1x - cx); + ry = (p1y - cy); + + radius_square = (float) (rx*rx + ry*ry); + } + + public List GetSimplices() + { + List result = new List(); + Simplex s1 = new Simplex(v1, v2); + Simplex s2 = new Simplex(v2, v3); + Simplex s3 = new Simplex(v3, v1); + + result.Add(s1); + result.Add(s2); + result.Add(s3); + + return result; + } + + public override String ToString() + { + NumberFormatInfo nfi = new NumberFormatInfo(); + nfi.CurrencyDecimalDigits = 2; + nfi.CurrencyDecimalSeparator = "."; + + String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">"; + String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">"; + String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">"; + + return s1 + ";" + s2 + ";" + s3; + } + + public PhysicsVector getNormal() + { + // Vertices + + // Vectors for edges + PhysicsVector e1; + PhysicsVector e2; + + e1 = new PhysicsVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); + e2 = new PhysicsVector(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z); + + // Cross product for normal + PhysicsVector n = PhysicsVector.cross(e1, e2); + + // Length + float l = n.length(); + + // Normalized "normal" + n = n/l; + + return n; + } + + public void invertNormal() + { + Vertex vt; + vt = v1; + v1 = v2; + v2 = vt; + } + + // Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and + // debugging purposes + public String ToStringRaw() + { + String output = v1.ToRaw() + " " + v2.ToRaw() + " " + v3.ToRaw(); + return output; + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/Meshing/Mesh.cs b/trunk/OpenSim/Region/Physics/Meshing/Mesh.cs new file mode 100644 index 0000000000..9c2667ee7e --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Meshing/Mesh.cs @@ -0,0 +1,235 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.Meshing +{ + public class Mesh : IMesh + { + public List vertices; + public List triangles; + + public float[] normals; + + public Mesh() + { + vertices = new List(); + triangles = new List(); + } + + public Mesh Clone() + { + Mesh result = new Mesh(); + + foreach (Vertex v in vertices) + { + if (v == null) + result.vertices.Add(null); + else + result.vertices.Add(v.Clone()); + } + + foreach (Triangle t in triangles) + { + int iV1, iV2, iV3; + iV1 = vertices.IndexOf(t.v1); + iV2 = vertices.IndexOf(t.v2); + iV3 = vertices.IndexOf(t.v3); + + Triangle newT = new Triangle(result.vertices[iV1], result.vertices[iV2], result.vertices[iV3]); + result.Add(newT); + } + + return result; + } + + + public void Add(Triangle triangle) + { + int i; + i = vertices.IndexOf(triangle.v1); + if (i < 0) + throw new ArgumentException("Vertex v1 not known to mesh"); + i = vertices.IndexOf(triangle.v2); + if (i < 0) + throw new ArgumentException("Vertex v2 not known to mesh"); + i = vertices.IndexOf(triangle.v3); + if (i < 0) + throw new ArgumentException("Vertex v3 not known to mesh"); + + triangles.Add(triangle); + } + + public void Add(Vertex v) + { + vertices.Add(v); + } + + public void Remove(Vertex v) + { + int i; + + // First, remove all triangles that are build on v + for (i = 0; i < triangles.Count; i++) + { + Triangle t = triangles[i]; + if (t.v1 == v || t.v2 == v || t.v3 == v) + { + triangles.RemoveAt(i); + i--; + } + } + + // Second remove v itself + vertices.Remove(v); + } + + public void RemoveTrianglesOutside(SimpleHull hull) + { + int i; + + for (i = 0; i < triangles.Count; i++) + { + Triangle t = triangles[i]; + Vertex v1 = t.v1; + Vertex v2 = t.v2; + Vertex v3 = t.v3; + PhysicsVector m = v1 + v2 + v3; + m /= 3.0f; + if (!hull.IsPointIn(new Vertex(m))) + { + triangles.RemoveAt(i); + i--; + } + } + } + + + public void Add(List lv) + { + foreach (Vertex v in lv) + { + vertices.Add(v); + } + } + + public List getVertexList() + { + List result = new List(); + foreach (Vertex v in vertices) + { + result.Add(v); + } + return result; + } + + public float[] getVertexListAsFloatLocked() + { + float[] result = new float[vertices.Count*3]; + for (int i = 0; i < vertices.Count; i++) + { + Vertex v = vertices[i]; + if (v == null) + continue; + result[3*i + 0] = v.X; + result[3*i + 1] = v.Y; + result[3*i + 2] = v.Z; + } + GCHandle.Alloc(result, GCHandleType.Pinned); + return result; + } + + public int[] getIndexListAsInt() + { + int[] result = new int[triangles.Count*3]; + for (int i = 0; i < triangles.Count; i++) + { + Triangle t = triangles[i]; + result[3*i + 0] = vertices.IndexOf(t.v1); + result[3*i + 1] = vertices.IndexOf(t.v2); + result[3*i + 2] = vertices.IndexOf(t.v3); + } + return result; + } + + public int[] getIndexListAsIntLocked() + { + int[] result = getIndexListAsInt(); + GCHandle.Alloc(result, GCHandleType.Pinned); + return result; + } + + + public void Append(Mesh newMesh) + { + foreach (Vertex v in newMesh.vertices) + vertices.Add(v); + + foreach (Triangle t in newMesh.triangles) + Add(t); + } + + // Do a linear transformation of mesh. + public void TransformLinear(float[,] matrix, float[] offset) + { + foreach (Vertex v in vertices) + { + if (v == null) + continue; + float x, y, z; + x = v.X*matrix[0, 0] + v.Y*matrix[1, 0] + v.Z*matrix[2, 0]; + y = v.X*matrix[0, 1] + v.Y*matrix[1, 1] + v.Z*matrix[2, 1]; + z = v.X*matrix[0, 2] + v.Y*matrix[1, 2] + v.Z*matrix[2, 2]; + v.X = x + offset[0]; + v.Y = y + offset[1]; + v.Z = z + offset[2]; + } + } + + public void DumpRaw(String path, String name, String title) + { + if (path == null) + return; + String fileName = name + "_" + title + ".raw"; + String completePath = Path.Combine(path, fileName); + StreamWriter sw = new StreamWriter(completePath); + foreach (Triangle t in triangles) + { + String s = t.ToStringRaw(); + sw.WriteLine(s); + } + sw.Close(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/trunk/OpenSim/Region/Physics/Meshing/Meshmerizer.cs new file mode 100644 index 0000000000..9244402329 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -0,0 +1,818 @@ +/* +* 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; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.Meshing +{ + public class MeshmerizerPlugin : IMeshingPlugin + { + public MeshmerizerPlugin() + { + } + + public string GetName() + { + return "Meshmerizer"; + } + + public IMesher GetMesher() + { + return new Meshmerizer(); + } + } + + public class Meshmerizer : IMesher + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Setting baseDir to a path will enable the dumping of raw files + // raw files can be imported by blender so a visual inspection of the results can be done + // const string baseDir = "rawFiles"; + private const string baseDir = null; //"rawFiles"; + + private static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, + PhysicsVector r2, ref float lambda, ref float mu) + { + // p1, p2, points on the straight + // r1, r2, directional vectors of the straight. Not necessarily of length 1! + // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points, + // thus allowing to decide whether an intersection is between two points + + float r1x = r1.X; + float r1y = r1.Y; + float r2x = r2.X; + float r2y = r2.Y; + + float denom = r1y*r2x - r1x*r2y; + + if (denom == 0.0) + { + lambda = Single.NaN; + mu = Single.NaN; + return; + } + + float p1x = p1.X; + float p1y = p1.Y; + float p2x = p2.X; + float p2y = p2.Y; + lambda = (-p2x*r2y + p1x*r2y + (p2y - p1y)*r2x)/denom; + mu = (-p2x*r1y + p1x*r1y + (p2y - p1y)*r1x)/denom; + } + + private static List FindInfluencedTriangles(List triangles, Vertex v) + { + List influenced = new List(); + foreach (Triangle t in triangles) + { + if (t.isInCircle(v.X, v.Y)) + { + influenced.Add(t); + } + } + return influenced; + } + + private static void InsertVertices(List vertices, int usedForSeed, List triangles) + { + // This is a variant of the delaunay algorithm + // each time a new vertex is inserted, all triangles that are influenced by it are deleted + // and replaced by new ones including the new vertex + // It is not very time efficient but easy to implement. + + int iCurrentVertex; + int iMaxVertex = vertices.Count; + for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++) + { + // Background: A triangle mesh fulfills the delaunay condition if (iff!) + // each circumlocutory circle (i.e. the circle that touches all three corners) + // of each triangle is empty of other vertices. + // Obviously a single (seeding) triangle fulfills this condition. + // If we now add one vertex, we need to reconstruct all triangles, that + // do not fulfill this condition with respect to the new triangle + + // Find the triangles that are influenced by the new vertex + Vertex v = vertices[iCurrentVertex]; + if (v == null) + continue; // Null is polygon stop marker. Ignore it + List influencedTriangles = FindInfluencedTriangles(triangles, v); + + List simplices = new List(); + + // Reconstruction phase. First step, dissolve each triangle into it's simplices, + // i.e. it's "border lines" + // Goal is to find "inner" borders and delete them, while the hull gets conserved. + // Inner borders are special in the way that they always come twice, which is how we detect them + foreach (Triangle t in influencedTriangles) + { + List newSimplices = t.GetSimplices(); + simplices.AddRange(newSimplices); + triangles.Remove(t); + } + // Now sort the simplices. That will make identical ones reside side by side in the list + simplices.Sort(); + + // Look for duplicate simplices here. + // Remember, they are directly side by side in the list right now, + // So we only check directly neighbours + int iSimplex; + List innerSimplices = new List(); + for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards + { + if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0) + { + innerSimplices.Add(simplices[iSimplex - 1]); + innerSimplices.Add(simplices[iSimplex]); + } + } + + foreach (Simplex s in innerSimplices) + { + simplices.Remove(s); + } + + // each simplex still in the list belongs to the hull of the region in question + // The new vertex (yes, we still deal with verices here :-) ) forms a triangle + // with each of these simplices. Build the new triangles and add them to the list + foreach (Simplex s in simplices) + { + Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]); + if (!t.isDegraded()) + { + triangles.Add(t); + } + } + } + } + + private static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + // Builds the z (+ and -) surfaces of a box shaped prim + { + UInt16 hollowFactor = primShape.ProfileHollow; + UInt16 profileBegin = primShape.ProfileBegin; + UInt16 profileEnd = primShape.ProfileEnd; + UInt16 taperX = primShape.PathScaleX; + UInt16 taperY = primShape.PathScaleY; + UInt16 pathShearX = primShape.PathShearX; + UInt16 pathShearY = primShape.PathShearY; + + //m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString()); + //m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString()); + //m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString()); + //m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString()); + + // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface + // of a block are basically the same + // They may be warped differently but the shape is identical + // So we only create one surface as a model and derive both plus and minus surface of the block from it + // This is done in a model space where the block spans from -.5 to +.5 in X and Y + // The mapping to Scene space is done later during the "extrusion" phase + + // Base + Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f); + Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f); + Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f); + Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f); + + SimpleHull outerHull = new SimpleHull(); + outerHull.AddVertex(MM); + outerHull.AddVertex(PM); + outerHull.AddVertex(PP); + outerHull.AddVertex(MP); + + // Deal with cuts now + if ((profileBegin != 0) || (profileEnd != 0)) + { + double fProfileBeginAngle = profileBegin/50000.0*360.0; + // In degree, for easier debugging and understanding + fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y + double fProfileEndAngle = 360.0 - profileEnd/50000.0*360.0; // Pathend comes as complement to 1.0 + fProfileEndAngle -= (90.0 + 45.0); + if (fProfileBeginAngle < fProfileEndAngle) + fProfileEndAngle -= 360.0; + + // Note, that we don't want to cut out a triangle, even if this is a + // good approximation for small cuts. Indeed we want to cut out an arc + // and we approximate this arc by a polygon chain + // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space + // So it can easily be subtracted from the outer hull + int iSteps = (int) (((fProfileBeginAngle - fProfileEndAngle)/45.0) + .5); + // how many steps do we need with approximately 45 degree + double dStepWidth = (fProfileBeginAngle - fProfileEndAngle)/iSteps; + + Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); + + // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull + SimpleHull cutHull = new SimpleHull(); + cutHull.AddVertex(origin); + for (int i = 0; i < iSteps; i++) + { + double angle = fProfileBeginAngle - i*dStepWidth; // we count against the angle orientation!!!! + Vertex v = Vertex.FromAngle(angle*Math.PI/180.0); + cutHull.AddVertex(v); + } + Vertex legEnd = Vertex.FromAngle(fProfileEndAngle*Math.PI/180.0); + // Calculated separately to avoid errors + cutHull.AddVertex(legEnd); + + //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName); + SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); + + outerHull = cuttedHull; + } + + // Deal with the hole here + if (hollowFactor > 0) + { + float hollowFactorF = (float) hollowFactor/(float) 50000; + Vertex IMM = new Vertex(-0.5f*hollowFactorF, -0.5f*hollowFactorF, 0.0f); + Vertex IPM = new Vertex(+0.5f*hollowFactorF, -0.5f*hollowFactorF, 0.0f); + Vertex IPP = new Vertex(+0.5f*hollowFactorF, +0.5f*hollowFactorF, 0.0f); + Vertex IMP = new Vertex(-0.5f*hollowFactorF, +0.5f*hollowFactorF, 0.0f); + + + SimpleHull holeHull = new SimpleHull(); + + holeHull.AddVertex(IMM); + holeHull.AddVertex(IMP); + holeHull.AddVertex(IPP); + holeHull.AddVertex(IPM); + + SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); + + outerHull = hollowedHull; + } + + Mesh m = new Mesh(); + + Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); + Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); + Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); + + m.Add(Seed1); + m.Add(Seed2); + m.Add(Seed3); + + m.Add(new Triangle(Seed1, Seed2, Seed3)); + m.Add(outerHull.getVertices()); + + InsertVertices(m.vertices, 3, m.triangles); + m.DumpRaw(baseDir, primName, "Proto first Mesh"); + + m.Remove(Seed1); + m.Remove(Seed2); + m.Remove(Seed3); + m.DumpRaw(baseDir, primName, "Proto seeds removed"); + + m.RemoveTrianglesOutside(outerHull); + m.DumpRaw(baseDir, primName, "Proto outsides removed"); + + foreach (Triangle t in m.triangles) + { + PhysicsVector n = t.getNormal(); + if (n.Z < 0.0) + t.invertNormal(); + } + + Extruder extr = new Extruder(); + + extr.size = size; + + if (taperX != 100) + { + if (taperX > 100) + { + extr.taperTopFactorX = 1.0f - ((float)taperX / 200); + //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString()); + } + else + { + extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100); + //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString()); + } + + } + + if (taperY != 100) + { + if (taperY > 100) + { + extr.taperTopFactorY = 1.0f - ((float)taperY / 200); + //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString()); + } + else + { + extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100); + //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString()); + } + } + + + if (pathShearX != 0) + { + if (pathShearX > 50) { + // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 + extr.pushX = (((float)(256 - pathShearX) / 100) * -1f); + // m_log.Warn("pushX: " + extr.pushX); + } + else + { + extr.pushX = (float)pathShearX / 100; + // m_log.Warn("pushX: " + extr.pushX); + } + } + + if (pathShearY != 0) + { + if (pathShearY > 50) { + // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 + extr.pushY = (((float)(256 - pathShearY) / 100) * -1f); + //m_log.Warn("pushY: " + extr.pushY); + } + else + { + extr.pushY = (float)pathShearY / 100; + //m_log.Warn("pushY: " + extr.pushY); + } + } + + + + Mesh result = extr.Extrude(m); + result.DumpRaw(baseDir, primName, "Z extruded"); + return result; + } + private static Mesh CreateCyllinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + // Builds the z (+ and -) surfaces of a box shaped prim + { + UInt16 hollowFactor = primShape.ProfileHollow; + UInt16 profileBegin = primShape.ProfileBegin; + UInt16 profileEnd = primShape.ProfileEnd; + UInt16 taperX = primShape.PathScaleX; + UInt16 taperY = primShape.PathScaleY; + UInt16 pathShearX = primShape.PathShearX; + UInt16 pathShearY = primShape.PathShearY; + + // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface + // of a block are basically the same + // They may be warped differently but the shape is identical + // So we only create one surface as a model and derive both plus and minus surface of the block from it + // This is done in a model space where the block spans from -.5 to +.5 in X and Y + // The mapping to Scene space is done later during the "extrusion" phase + + // Base + // Q1Q15 = Quadrant 1, Quadrant1, Vertex 5 + Vertex Q1Q15 = new Vertex(-0.35f, -0.35f, 0.0f); + Vertex Q1Q16 = new Vertex(-0.30f, -0.40f, 0.0f); + Vertex Q1Q17 = new Vertex(-0.24f, -0.43f, 0.0f); + Vertex Q1Q18 = new Vertex(-0.18f, -0.46f, 0.0f); + Vertex Q1Q19 = new Vertex(-0.11f, -0.48f, 0.0f); + + Vertex Q2Q10 = new Vertex(+0.0f, -0.50f, 0.0f); + Vertex Q2Q11 = new Vertex(+0.11f, -0.48f, 0.0f); + Vertex Q2Q12 = new Vertex(+0.18f, -0.46f, 0.0f); + Vertex Q2Q13 = new Vertex(+0.24f, -0.43f, 0.0f); + Vertex Q2Q14 = new Vertex(+0.30f, -0.40f, 0.0f); + Vertex Q2Q15 = new Vertex(+0.35f, -0.35f, 0.0f); + Vertex Q2Q16 = new Vertex(+0.40f, -0.30f, 0.0f); + Vertex Q2Q17 = new Vertex(+0.43f, -0.24f, 0.0f); + Vertex Q2Q18 = new Vertex(+0.46f, -0.18f, 0.0f); + Vertex Q2Q19 = new Vertex(+0.48f, -0.11f, 0.0f); + + Vertex Q2Q20 = new Vertex(+0.50f, +0.0f, 0.0f); + Vertex Q2Q21 = new Vertex(+0.48f, +0.11f, 0.0f); + Vertex Q2Q22 = new Vertex(+0.46f, +0.18f, 0.0f); + Vertex Q2Q23 = new Vertex(+0.43f, +0.24f, 0.0f); + Vertex Q2Q24 = new Vertex(+0.40f, +0.30f, 0.0f); + Vertex Q2Q25 = new Vertex(+0.35f, +0.35f, 0.0f); + Vertex Q2Q26 = new Vertex(+0.30f, +0.40f, 0.0f); + Vertex Q2Q27 = new Vertex(+0.24f, +0.43f, 0.0f); + Vertex Q2Q28 = new Vertex(+0.18f, +0.46f, 0.0f); + Vertex Q2Q29 = new Vertex(+0.11f, +0.48f, 0.0f); + + Vertex Q1Q20 = new Vertex(+0.0f, +0.50f, 0.0f); + Vertex Q1Q21 = new Vertex(-0.11f, +0.48f, 0.0f); + Vertex Q1Q22 = new Vertex(-0.18f, +0.46f, 0.0f); + Vertex Q1Q23 = new Vertex(-0.24f, +0.43f, 0.0f); + Vertex Q1Q24 = new Vertex(-0.30f, +0.40f, 0.0f); + Vertex Q1Q25 = new Vertex(-0.35f, +0.35f, 0.0f); + Vertex Q1Q26 = new Vertex(-0.40f, +0.30f, 0.0f); + Vertex Q1Q27 = new Vertex(-0.43f, +0.24f, 0.0f); + Vertex Q1Q28 = new Vertex(-0.46f, +0.18f, 0.0f); + Vertex Q1Q29 = new Vertex(-0.48f, +0.11f, 0.0f); + + Vertex Q1Q10 = new Vertex(-0.50f, +0.0f, 0.0f); + Vertex Q1Q11 = new Vertex(-0.48f, -0.11f, 0.0f); + Vertex Q1Q12 = new Vertex(-0.46f, -0.18f, 0.0f); + Vertex Q1Q13 = new Vertex(-0.43f, -0.24f, 0.0f); + Vertex Q1Q14 = new Vertex(-0.40f, -0.30f, 0.0f); + + + SimpleHull outerHull = new SimpleHull(); + //Clockwise around the quadrants + outerHull.AddVertex(Q1Q15); + outerHull.AddVertex(Q1Q16); + outerHull.AddVertex(Q1Q17); + outerHull.AddVertex(Q1Q18); + outerHull.AddVertex(Q1Q19); + + outerHull.AddVertex(Q2Q10); + outerHull.AddVertex(Q2Q11); + outerHull.AddVertex(Q2Q12); + outerHull.AddVertex(Q2Q13); + outerHull.AddVertex(Q2Q14); + outerHull.AddVertex(Q2Q15); + outerHull.AddVertex(Q2Q16); + outerHull.AddVertex(Q2Q17); + outerHull.AddVertex(Q2Q18); + outerHull.AddVertex(Q2Q19); + + outerHull.AddVertex(Q2Q20); + outerHull.AddVertex(Q2Q21); + outerHull.AddVertex(Q2Q22); + outerHull.AddVertex(Q2Q23); + outerHull.AddVertex(Q2Q24); + outerHull.AddVertex(Q2Q25); + outerHull.AddVertex(Q2Q26); + outerHull.AddVertex(Q2Q27); + outerHull.AddVertex(Q2Q28); + outerHull.AddVertex(Q2Q29); + + outerHull.AddVertex(Q1Q20); + outerHull.AddVertex(Q1Q21); + outerHull.AddVertex(Q1Q22); + outerHull.AddVertex(Q1Q23); + outerHull.AddVertex(Q1Q24); + outerHull.AddVertex(Q1Q25); + outerHull.AddVertex(Q1Q26); + outerHull.AddVertex(Q1Q27); + outerHull.AddVertex(Q1Q28); + outerHull.AddVertex(Q1Q29); + + outerHull.AddVertex(Q1Q10); + outerHull.AddVertex(Q1Q11); + outerHull.AddVertex(Q1Q12); + outerHull.AddVertex(Q1Q13); + outerHull.AddVertex(Q1Q14); + + // Deal with cuts now + if ((profileBegin != 0) || (profileEnd != 0)) + { + double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; + // In degree, for easier debugging and understanding + //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y + double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0 + //fProfileEndAngle -= (90.0 + 45.0); + if (fProfileBeginAngle < fProfileEndAngle) + fProfileEndAngle -= 360.0; + + // Note, that we don't want to cut out a triangle, even if this is a + // good approximation for small cuts. Indeed we want to cut out an arc + // and we approximate this arc by a polygon chain + // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space + // So it can easily be subtracted from the outer hull + int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); + // how many steps do we need with approximately 45 degree + double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps; + + Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); + + // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull + SimpleHull cutHull = new SimpleHull(); + cutHull.AddVertex(origin); + for (int i = 0; i < iSteps; i++) + { + double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!! + Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0); + cutHull.AddVertex(v); + } + Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); + // Calculated separately to avoid errors + cutHull.AddVertex(legEnd); + + // m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName); + SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); + + outerHull = cuttedHull; + } + + // Deal with the hole here + if (hollowFactor > 0) + { + float hollowFactorF = (float)hollowFactor / (float)50000; + + Vertex IQ1Q15 = new Vertex(-0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f); + Vertex IQ1Q16 = new Vertex(-0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f); + Vertex IQ1Q17 = new Vertex(-0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f); + Vertex IQ1Q18 = new Vertex(-0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f); + Vertex IQ1Q19 = new Vertex(-0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f); + + Vertex IQ2Q10 = new Vertex(+0.0f * hollowFactorF, -0.50f * hollowFactorF, 0.0f); + Vertex IQ2Q11 = new Vertex(+0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f); + Vertex IQ2Q12 = new Vertex(+0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f); + Vertex IQ2Q13 = new Vertex(+0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f); + Vertex IQ2Q14 = new Vertex(+0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f); + Vertex IQ2Q15 = new Vertex(+0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f); + Vertex IQ2Q16 = new Vertex(+0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f); + Vertex IQ2Q17 = new Vertex(+0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f); + Vertex IQ2Q18 = new Vertex(+0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f); + Vertex IQ2Q19 = new Vertex(+0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f); + + Vertex IQ2Q20 = new Vertex(+0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f); + Vertex IQ2Q21 = new Vertex(+0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f); + Vertex IQ2Q22 = new Vertex(+0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f); + Vertex IQ2Q23 = new Vertex(+0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f); + Vertex IQ2Q24 = new Vertex(+0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f); + Vertex IQ2Q25 = new Vertex(+0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f); + Vertex IQ2Q26 = new Vertex(+0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f); + Vertex IQ2Q27 = new Vertex(+0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f); + Vertex IQ2Q28 = new Vertex(+0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f); + Vertex IQ2Q29 = new Vertex(+0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f); + + Vertex IQ1Q20 = new Vertex(+0.0f * hollowFactorF, +0.50f * hollowFactorF, 0.0f); + Vertex IQ1Q21 = new Vertex(-0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f); + Vertex IQ1Q22 = new Vertex(-0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f); + Vertex IQ1Q23 = new Vertex(-0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f); + Vertex IQ1Q24 = new Vertex(-0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f); + Vertex IQ1Q25 = new Vertex(-0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f); + Vertex IQ1Q26 = new Vertex(-0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f); + Vertex IQ1Q27 = new Vertex(-0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f); + Vertex IQ1Q28 = new Vertex(-0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f); + Vertex IQ1Q29 = new Vertex(-0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f); + + Vertex IQ1Q10 = new Vertex(-0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f); + Vertex IQ1Q11 = new Vertex(-0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f); + Vertex IQ1Q12 = new Vertex(-0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f); + Vertex IQ1Q13 = new Vertex(-0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f); + Vertex IQ1Q14 = new Vertex(-0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f); + + //Counter clockwise around the quadrants + SimpleHull holeHull = new SimpleHull(); + holeHull.AddVertex(IQ1Q15); + holeHull.AddVertex(IQ1Q14); + holeHull.AddVertex(IQ1Q13); + holeHull.AddVertex(IQ1Q12); + holeHull.AddVertex(IQ1Q11); + holeHull.AddVertex(IQ1Q10); + + holeHull.AddVertex(IQ1Q29); + holeHull.AddVertex(IQ1Q28); + holeHull.AddVertex(IQ1Q27); + holeHull.AddVertex(IQ1Q26); + holeHull.AddVertex(IQ1Q25); + holeHull.AddVertex(IQ1Q24); + holeHull.AddVertex(IQ1Q23); + holeHull.AddVertex(IQ1Q22); + holeHull.AddVertex(IQ1Q21); + holeHull.AddVertex(IQ1Q20); + + holeHull.AddVertex(IQ2Q29); + holeHull.AddVertex(IQ2Q28); + holeHull.AddVertex(IQ2Q27); + holeHull.AddVertex(IQ2Q26); + holeHull.AddVertex(IQ2Q25); + holeHull.AddVertex(IQ2Q24); + holeHull.AddVertex(IQ2Q23); + holeHull.AddVertex(IQ2Q22); + holeHull.AddVertex(IQ2Q21); + holeHull.AddVertex(IQ2Q20); + + holeHull.AddVertex(IQ2Q19); + holeHull.AddVertex(IQ2Q18); + holeHull.AddVertex(IQ2Q17); + holeHull.AddVertex(IQ2Q16); + holeHull.AddVertex(IQ2Q15); + holeHull.AddVertex(IQ2Q14); + holeHull.AddVertex(IQ2Q13); + holeHull.AddVertex(IQ2Q12); + holeHull.AddVertex(IQ2Q11); + holeHull.AddVertex(IQ2Q10); + + holeHull.AddVertex(IQ1Q19); + holeHull.AddVertex(IQ1Q18); + holeHull.AddVertex(IQ1Q17); + holeHull.AddVertex(IQ1Q16); + + SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); + + outerHull = hollowedHull; + } + + Mesh m = new Mesh(); + + Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); + Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); + Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); + + m.Add(Seed1); + m.Add(Seed2); + m.Add(Seed3); + + m.Add(new Triangle(Seed1, Seed2, Seed3)); + m.Add(outerHull.getVertices()); + + InsertVertices(m.vertices, 3, m.triangles); + m.DumpRaw(baseDir, primName, "Proto first Mesh"); + + m.Remove(Seed1); + m.Remove(Seed2); + m.Remove(Seed3); + m.DumpRaw(baseDir, primName, "Proto seeds removed"); + + m.RemoveTrianglesOutside(outerHull); + m.DumpRaw(baseDir, primName, "Proto outsides removed"); + + foreach (Triangle t in m.triangles) + { + PhysicsVector n = t.getNormal(); + if (n.Z < 0.0) + t.invertNormal(); + } + + Extruder extr = new Extruder(); + + extr.size = size; + if (taperX != 100) + { + if (taperX > 100) + { + extr.taperTopFactorX = 1.0f - ((float)taperX / 200); + //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString()); + } + else + { + extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100); + //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString()); + } + + } + + if (taperY != 100) + { + if (taperY > 100) + { + extr.taperTopFactorY = 1.0f - ((float)taperY / 200); + //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString()); + } + else + { + extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100); + //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString()); + } + } + + if (pathShearX != 0) + { + if (pathShearX > 50) + { + // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 + extr.pushX = (((float)(256 - pathShearX) / 100) * -1f); + //m_log.Warn("pushX: " + extr.pushX); + } + else + { + extr.pushX = (float)pathShearX / 100; + //m_log.Warn("pushX: " + extr.pushX); + } + } + + if (pathShearY != 0) + { + if (pathShearY > 50) + { + // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 + extr.pushY = (((float)(256 - pathShearY) / 100) * -1f); + //m_log.Warn("pushY: " + extr.pushY); + } + else + { + extr.pushY = (float)pathShearY / 100; + //m_log.Warn("pushY: " + extr.pushY); + } + } + + Mesh result = extr.Extrude(m); + result.DumpRaw(baseDir, primName, "Z extruded"); + return result; + } + public static void CalcNormals(Mesh mesh) + { + int iTriangles = mesh.triangles.Count; + + mesh.normals = new float[iTriangles*3]; + + int i = 0; + foreach (Triangle t in mesh.triangles) + { + float ux, uy, uz; + float vx, vy, vz; + float wx, wy, wz; + + ux = t.v1.X; + uy = t.v1.Y; + uz = t.v1.Z; + + vx = t.v2.X; + vy = t.v2.Y; + vz = t.v2.Z; + + wx = t.v3.X; + wy = t.v3.Y; + wz = t.v3.Z; + + + // Vectors for edges + float e1x, e1y, e1z; + float e2x, e2y, e2z; + + e1x = ux - vx; + e1y = uy - vy; + e1z = uz - vz; + + e2x = ux - wx; + e2y = uy - wy; + e2z = uz - wz; + + + // Cross product for normal + float nx, ny, nz; + nx = e1y*e2z - e1z*e2y; + ny = e1z*e2x - e1x*e2z; + nz = e1x*e2y - e1y*e2x; + + // Length + float l = (float) Math.Sqrt(nx*nx + ny*ny + nz*nz); + + // Normalized "normal" + nx /= l; + ny /= l; + nz /= l; + + mesh.normals[i] = nx; + mesh.normals[i + 1] = ny; + mesh.normals[i + 2] = nz; + + i += 3; + } + } + + public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + { + Mesh mesh = null; + + switch (primShape.ProfileShape) + { + case ProfileShape.Square: + mesh = CreateBoxMesh(primName, primShape, size); + CalcNormals(mesh); + break; + case ProfileShape.Circle: + if (primShape.PathCurve == (byte)Extrusion.Straight) + { + mesh = CreateCyllinderMesh(primName, primShape, size); + CalcNormals(mesh); + } + break; + default: + mesh = CreateBoxMesh(primName, primShape, size); + CalcNormals(mesh); + //Set default mesh to cube otherwise it'll return + // null and crash on the 'setMesh' method in the physics plugins. + //mesh = null; + break; + } + + return mesh; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/Meshing/SimpleHull.cs b/trunk/OpenSim/Region/Physics/Meshing/SimpleHull.cs new file mode 100644 index 0000000000..91df98f8a2 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Meshing/SimpleHull.cs @@ -0,0 +1,397 @@ +/* +* 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; +using System.Collections.Generic; +using OpenSim.Framework.Console; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.Meshing +{ + // A simple hull is a set of vertices building up to simplices that border a region + // The word simple referes to the fact, that this class assumes, that all simplices + // do not intersect + // Simple hulls can be added and subtracted. + // Vertices can be checked to lie inside a hull + // Also note, that the sequence of the vertices is important and defines if the region that + // is defined by the hull lies inside or outside the simplex chain + public class SimpleHull + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private List vertices = new List(); + private List holeVertices = new List(); // Only used, when the hull is hollow + + // Adds a vertex to the end of the list + public void AddVertex(Vertex v) + { + vertices.Add(v); + } + + public override String ToString() + { + String result = String.Empty; + foreach (Vertex v in vertices) + { + result += "b:" + v.ToString() + "\n"; + } + + return result; + } + + + public List getVertices() + { + List newVertices = new List(); + + newVertices.AddRange(vertices); + newVertices.Add(null); + newVertices.AddRange(holeVertices); + + return newVertices; + } + + public SimpleHull Clone() + { + SimpleHull result = new SimpleHull(); + foreach (Vertex v in vertices) + { + result.AddVertex(v.Clone()); + } + + foreach (Vertex v in holeVertices) + { + result.holeVertices.Add(v.Clone()); + } + + return result; + } + + public bool IsPointIn(Vertex v1) + { + int iCounter = 0; + List simplices = buildSimplexList(); + foreach (Simplex s in simplices) + { + // Send a ray along the positive X-Direction + // Note, that this direction must correlate with the "below" interpretation + // of handling for the special cases below + PhysicsVector intersection = s.RayIntersect(v1, new PhysicsVector(1.0f, 0.0f, 0.0f), true); + + if (intersection == null) + continue; // No intersection. Done. More tests to follow otherwise + + // Did we hit the end of a simplex? + // Then this can be one of two special cases: + // 1. we go through a border exactly at a joint + // 2. we have just marginally touched a corner + // 3. we can slide along a border + // Solution: If the other vertex is "below" the ray, we don't count it + // Thus corners pointing down are counted twice, corners pointing up are not counted + // borders are counted once + if (intersection.IsIdentical(s.v1, 0.001f)) + { + if (s.v2.Y < v1.Y) + continue; + } + // Do this for the other vertex two + if (intersection.IsIdentical(s.v2, 0.001f)) + { + if (s.v1.Y < v1.Y) + continue; + } + iCounter++; + } + + return iCounter%2 == 1; // Point is inside if the number of intersections is odd + } + + public bool containsPointsFrom(SimpleHull otherHull) + { + foreach (Vertex v in otherHull.vertices) + { + if (IsPointIn(v)) + return true; + } + + return false; + } + + + private List buildSimplexList() + { + List result = new List(); + + // Not asserted but assumed: at least three vertices + for (int i = 0; i < vertices.Count - 1; i++) + { + Simplex s = new Simplex(vertices[i], vertices[i + 1]); + result.Add(s); + } + Simplex s1 = new Simplex(vertices[vertices.Count - 1], vertices[0]); + result.Add(s1); + + if (holeVertices.Count == 0) + return result; + + // Same here. At least three vertices in hole assumed + for (int i = 0; i < holeVertices.Count - 1; i++) + { + Simplex s = new Simplex(holeVertices[i], holeVertices[i + 1]); + result.Add(s); + } + + s1 = new Simplex(holeVertices[holeVertices.Count - 1], holeVertices[0]); + result.Add(s1); + return result; + } + + private bool InsertVertex(Vertex v, int iAfter) + { + vertices.Insert(iAfter + 1, v); + return true; + } + + private Vertex getNextVertex(Vertex currentVertex) + { + int iCurrentIndex; + iCurrentIndex = vertices.IndexOf(currentVertex); + + // Error handling for iCurrentIndex==-1 should go here (and probably never will) + + iCurrentIndex++; + if (iCurrentIndex == vertices.Count) + iCurrentIndex = 0; + + return vertices[iCurrentIndex]; + } + + public Vertex FindVertex(Vertex vBase, float tolerance) + { + foreach (Vertex v in vertices) + { + if (v.IsIdentical(vBase, tolerance)) + return v; + } + + return null; + } + + public void FindIntersection(Simplex s, ref Vertex Intersection, ref Vertex nextVertex) + { + Vertex bestIntersection = null; + float distToV1 = Single.PositiveInfinity; + Simplex bestIntersectingSimplex = null; + + List simple = buildSimplexList(); + foreach (Simplex sTest in simple) + { + PhysicsVector vvTemp = Simplex.Intersect(sTest, s, -.001f, -.001f, 0.999f, .999f); + + Vertex vTemp = null; + if (vvTemp != null) + vTemp = new Vertex(vvTemp); + + if (vTemp != null) + { + PhysicsVector diff = (s.v1 - vTemp); + float distTemp = diff.length(); + + if (bestIntersection == null || distTemp < distToV1) + { + bestIntersection = vTemp; + distToV1 = distTemp; + bestIntersectingSimplex = sTest; + } + } // end if vTemp + } // end foreach + + Intersection = bestIntersection; + if (bestIntersectingSimplex != null) + nextVertex = bestIntersectingSimplex.v2; + else + nextVertex = null; + } + + + public static SimpleHull SubtractHull(SimpleHull baseHull, SimpleHull otherHull) + { + SimpleHull baseHullClone = baseHull.Clone(); + SimpleHull otherHullClone = otherHull.Clone(); + bool intersects = false; + + //m_log.Debug("State before intersection detection"); + //m_log.DebugFormat("The baseHull is:\n{1}", 0, baseHullClone.ToString()); + //m_log.DebugFormat("The otherHull is:\n{1}", 0, otherHullClone.ToString()); + + { + int iBase, iOther; + + // Insert into baseHull + for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++) + { + int iBaseNext = (iBase + 1)%baseHullClone.vertices.Count; + Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]); + + for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++) + { + int iOtherNext = (iOther + 1)%otherHullClone.vertices.Count; + Simplex sOther = + new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]); + + PhysicsVector intersect = Simplex.Intersect(sBase, sOther, 0.001f, -.001f, 0.999f, 1.001f); + if (intersect != null) + { + Vertex vIntersect = new Vertex(intersect); + baseHullClone.vertices.Insert(iBase + 1, vIntersect); + sBase.v2 = vIntersect; + intersects = true; + } + } + } + } + + //m_log.Debug("State after intersection detection for the base hull"); + //m_log.DebugFormat("The baseHull is:\n{1}", 0, baseHullClone.ToString()); + + { + int iOther, iBase; + + // Insert into otherHull + for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++) + { + int iOtherNext = (iOther + 1)%otherHullClone.vertices.Count; + Simplex sOther = new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]); + + for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++) + { + int iBaseNext = (iBase + 1)%baseHullClone.vertices.Count; + Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]); + + PhysicsVector intersect = Simplex.Intersect(sBase, sOther, -.001f, 0.001f, 1.001f, 0.999f); + if (intersect != null) + { + Vertex vIntersect = new Vertex(intersect); + otherHullClone.vertices.Insert(iOther + 1, vIntersect); + sOther.v2 = vIntersect; + intersects = true; + } + } + } + } + + //m_log.Debug("State after intersection detection for the base hull"); + //m_log.DebugFormat("The otherHull is:\n{1}", 0, otherHullClone.ToString()); + + + bool otherIsInBase = baseHullClone.containsPointsFrom(otherHullClone); + if (!intersects && otherIsInBase) + { + // We have a hole here + baseHullClone.holeVertices = otherHullClone.vertices; + return baseHullClone; + } + + + SimpleHull result = new SimpleHull(); + + // Find a good starting Simplex from baseHull + // A good starting simplex is one that is outside otherHull + // Such a simplex must exist, otherwise the result will be empty + Vertex baseStartVertex = null; + { + int iBase; + for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++) + { + int iBaseNext = (iBase + 1)%baseHullClone.vertices.Count; + Vertex center = new Vertex((baseHullClone.vertices[iBase] + baseHullClone.vertices[iBaseNext])/2.0f); + bool isOutside = !otherHullClone.IsPointIn(center); + if (isOutside) + { + baseStartVertex = baseHullClone.vertices[iBaseNext]; + break; + } + } + } + + + if (baseStartVertex == null) // i.e. no simplex fulfilled the "outside" condition. + // In otherwords, subtractHull completely embraces baseHull + { + return result; + } + + // The simplex that *starts* with baseStartVertex is outside the cutting hull, + // so we can start our walk with the next vertex without loosing a branch + Vertex V1 = baseStartVertex; + bool onBase = true; + + // And here is how we do the magic :-) + // Start on the base hull. + // Walk the vertices in the positive direction + // For each vertex check, whether it is a vertex shared with the other hull + // if this is the case, switch over to walking the other vertex list. + // Note: The other hull *must* go backwards to our starting point (via several orther vertices) + // Thus it is important that the cutting hull has the inverse directional sense than the + // base hull!!!!!!!!! (means if base goes CW around it's center cutting hull must go CCW) + + bool done = false; + while (!done) + { + result.AddVertex(V1); + Vertex nextVertex = null; + if (onBase) + { + nextVertex = otherHullClone.FindVertex(V1, 0.001f); + } + else + { + nextVertex = baseHullClone.FindVertex(V1, 0.001f); + } + + if (nextVertex != null) // A node that represents an intersection + { + V1 = nextVertex; // Needed to find the next vertex on the other hull + onBase = !onBase; + } + + if (onBase) + V1 = baseHullClone.getNextVertex(V1); + else + V1 = otherHullClone.getNextVertex(V1); + + if (V1 == baseStartVertex) + done = true; + } + + //m_log.DebugFormat("The resulting Hull is:\n{1}", 0, result.ToString()); + + return result; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/Meshing/Simplex.cs b/trunk/OpenSim/Region/Physics/Meshing/Simplex.cs new file mode 100644 index 0000000000..8fba2bf792 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/Meshing/Simplex.cs @@ -0,0 +1,221 @@ +/* +* 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; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.Meshing +{ + // A simplex is a section of a straight line. + // It is defined by its endpoints, i.e. by two vertices + // Operation on vertices are + public class Simplex : IComparable + { + public Vertex v1; + public Vertex v2; + + public Simplex(Vertex _v1, Vertex _v2) + { + v1 = _v1; + v2 = _v2; + } + + public int CompareTo(Simplex other) + { + Vertex lv1, lv2, ov1, ov2, temp; + + lv1 = v1; + lv2 = v2; + ov1 = other.v1; + ov2 = other.v2; + + if (lv1 > lv2) + { + temp = lv1; + lv1 = lv2; + lv2 = temp; + } + + if (ov1 > ov2) + { + temp = ov1; + ov1 = ov2; + ov2 = temp; + } + + if (lv1 > ov1) + { + return 1; + } + if (lv1 < ov1) + { + return -1; + } + + if (lv2 > ov2) + { + return 1; + } + if (lv2 < ov2) + { + return -1; + } + + return 0; + } + + private static void intersectParameter(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, + ref float lambda, ref float mu) + { + // Intersects two straights + // p1, p2, points on the straight + // r1, r2, directional vectors of the straight. Not necessarily of length 1! + // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points, + // thus allowing to decide whether an intersection is between two points + + float r1x = r1.X; + float r1y = r1.Y; + float r2x = r2.X; + float r2y = r2.Y; + + float denom = r1y*r2x - r1x*r2y; + + float p1x = p1.X; + float p1y = p1.Y; + float p2x = p2.X; + float p2y = p2.Y; + + float z1 = -p2x*r2y + p1x*r2y + (p2y - p1y)*r2x; + float z2 = -p2x*r1y + p1x*r1y + (p2y - p1y)*r1x; + + if (denom == 0.0f) // Means the straights are parallel. Either no intersection or an infinite number of them + { + if (z1 == 0.0f) + { +// Means they are identical -> many, many intersections + lambda = Single.NaN; + mu = Single.NaN; + } + else + { + lambda = Single.PositiveInfinity; + mu = Single.PositiveInfinity; + } + return; + } + + + lambda = z1/denom; + mu = z2/denom; + } + + + // Intersects the simplex with another one. + // the borders are used to deal with float inaccuracies + // As a rule of thumb, the borders are + // lowerBorder1 : 0.0 + // lowerBorder2 : 0.0 + // upperBorder1 : 1.0 + // upperBorder2 : 1.0 + // Set these to values near the given parameters (e.g. 0.001 instead of 1 to exclude simplex starts safely, or to -0.001 to include them safely) + public static PhysicsVector Intersect( + Simplex s1, + Simplex s2, + float lowerBorder1, + float lowerBorder2, + float upperBorder1, + float upperBorder2) + { + PhysicsVector firstSimplexDirection = s1.v2 - s1.v1; + PhysicsVector secondSimplexDirection = s2.v2 - s2.v1; + + float lambda = 0.0f; + float mu = 0.0f; + + // Give us the parameters of an intersection. This subroutine does *not* take the constraints + // (intersection must be between v1 and v2 and it must be in the positive direction of the ray) + // into account. We do that afterwards. + intersectParameter(s1.v1, firstSimplexDirection, s2.v1, secondSimplexDirection, ref lambda, ref mu); + + if (Single.IsInfinity(lambda)) // Special case. No intersection at all. directions parallel. + return null; + + if (Single.IsNaN(lambda)) // Special case. many, many intersections. + return null; + + if (lambda > upperBorder1) // We're behind v2 + return null; + + if (lambda < lowerBorder1) + return null; + + if (mu < lowerBorder2) // outside simplex 2 + return null; + + if (mu > upperBorder2) // outside simplex 2 + return null; + + return s1.v1 + lambda*firstSimplexDirection; + } + + // Intersects the simplex with a ray. The ray is defined as all p=origin + lambda*direction + // where lambda >= 0 + public PhysicsVector RayIntersect(Vertex origin, PhysicsVector direction, bool bEndsIncluded) + { + PhysicsVector simplexDirection = v2 - v1; + + float lambda = 0.0f; + float mu = 0.0f; + + // Give us the parameters of an intersection. This subroutine does *not* take the constraints + // (intersection must be between v1 and v2 and it must be in the positive direction of the ray) + // into account. We do that afterwards. + intersectParameter(v1, simplexDirection, origin, direction, ref lambda, ref mu); + + if (Single.IsInfinity(lambda)) // Special case. No intersection at all. directions parallel. + return null; + + if (Single.IsNaN(lambda)) // Special case. many, many intersections. + return null; + + if (mu < 0.0) // We're on the wrong side of the ray + return null; + + if (lambda > 1.0) // We're behind v2 + return null; + + if (lambda == 1.0 && !bEndsIncluded) + return null; // The end of the simplices are not included + + if (lambda < 0.0f) // we're before v1; + return null; + + return v1 + lambda*simplexDirection; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs b/trunk/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs new file mode 100644 index 0000000000..1ea54581a9 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs @@ -0,0 +1,58 @@ +/* +* 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; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly : AssemblyTitle("OdePlugin")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OdePlugin")] +[assembly : AssemblyCopyright("")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. + +[assembly : ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly : AssemblyVersion("1.0.*")] \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/trunk/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs new file mode 100644 index 0000000000..c41f812919 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -0,0 +1,823 @@ +/* +* 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; +using Axiom.Math; +using Ode.NET; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.OdePlugin +{ + /// + /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves. + /// + + public enum dParam : int + { + LowStop = 0, + HiStop = 1, + Vel = 2, + FMax = 3, + FudgeFactor = 4, + Bounce = 5, + CFM = 6, + ERP = 7, + StopCFM = 8, + LoStop2 = 256, + HiStop2 = 257, + LoStop3 = 512, + HiStop3 = 513 + } + public class OdeCharacter : PhysicsActor + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private PhysicsVector _position; + private d.Vector3 _zeroPosition; + private d.Matrix3 m_StandUpRotation; + private bool _zeroFlag = false; + private bool m_lastUpdateSent = false; + private PhysicsVector _velocity; + private PhysicsVector _target_velocity; + private PhysicsVector _acceleration; + private PhysicsVector m_rotationalVelocity; + private float m_mass = 80f; + private float m_density = 60f; + private bool m_pidControllerActive = true; + private float PID_D = 800.0f; + private float PID_P = 900.0f; + private static float POSTURE_SERVO = 10000.0f; + public static float CAPSULE_RADIUS = 0.37f; + public float CAPSULE_LENGTH = 2.140599f; + private float m_tensor = 3800000f; + private bool flying = false; + private bool m_iscolliding = false; + private bool m_iscollidingGround = false; + private bool m_wascolliding = false; + private bool m_wascollidingGround = false; + private bool m_iscollidingObj = false; + private bool m_wascollidingObj = false; + private bool m_alwaysRun = false; + private bool m_hackSentFall = false; + private bool m_hackSentFly = false; + private bool m_foundDebian = false; + private CollisionLocker ode; + + private string m_name = String.Empty; + + private bool[] m_colliderarr = new bool[11]; + private bool[] m_colliderGroundarr = new bool[11]; + + + private bool jumping = false; + //private float gravityAccel; + public IntPtr Body; + private OdeScene _parent_scene; + public IntPtr Shell; + public IntPtr Amotor; + public d.Mass ShellMass; + public bool collidelock = false; + + public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos, CollisionLocker dode, PhysicsVector size) + { + ode = dode; + _velocity = new PhysicsVector(); + _target_velocity = new PhysicsVector(); + _position = pos; + _acceleration = new PhysicsVector(); + _parent_scene = parent_scene; + + if (System.Environment.OSVersion.Platform == PlatformID.Unix) + { + m_foundDebian = true; + m_tensor = 2000000f; + } + else + { + m_tensor = 1300000f; + } + + m_StandUpRotation = + new d.Matrix3(0.5f, 0.7071068f, 0.5f, -0.7071068f, 0f, 0.7071068f, 0.5f, -0.7071068f, + 0.5f); + + for (int i = 0; i < 11; i++) + { + m_colliderarr[i] = false; + } + CAPSULE_LENGTH = (size.Z - ((size.Z * 0.52f))); + + lock (OdeScene.OdeLock) + { + AvatarGeomAndBodyCreation(pos.X, pos.Y, pos.Z, m_tensor); + } + m_name = avName; + parent_scene.geom_name_map[Shell] = avName; + parent_scene.actor_name_map[Shell] = (PhysicsActor) this; + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Agent; } + set { return; } + } + + /// + /// If this is set, the avatar will move faster + /// + public override bool SetAlwaysRun + { + get { return m_alwaysRun; } + set { m_alwaysRun = value; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool Flying + { + get { return flying; } + set { flying = value; } + } + + /// + /// Returns if the avatar is colliding in general. + /// This includes the ground and objects and avatar. + /// + public override bool IsColliding + { + get { return m_iscolliding; } + set + { + int i; + int truecount = 0; + int falsecount = 0; + + if (m_colliderarr.Length >= 10) + { + for (i = 0; i < 10; i++) + { + m_colliderarr[i] = m_colliderarr[i + 1]; + } + } + m_colliderarr[10] = value; + + for (i = 0; i < 11; i++) + { + if (m_colliderarr[i]) + { + truecount++; + } + else + { + falsecount++; + } + } + + // Equal truecounts and false counts means we're colliding with something. + + if (falsecount > 1.2*truecount) + { + m_iscolliding = false; + } + else + { + m_iscolliding = true; + } + if (m_wascolliding != m_iscolliding) + { + //base.SendCollisionUpdate(new CollisionEventUpdate()); + } + m_wascolliding = m_iscolliding; + } + } + + /// + /// Returns if an avatar is colliding with the ground + /// + public override bool CollidingGround + { + get { return m_iscollidingGround; } + set + { + // Collisions against the ground are not really reliable + // So, to get a consistant value we have to average the current result over time + // Currently we use 1 second = 10 calls to this. + int i; + int truecount = 0; + int falsecount = 0; + + if (m_colliderGroundarr.Length >= 10) + { + for (i = 0; i < 10; i++) + { + m_colliderGroundarr[i] = m_colliderGroundarr[i + 1]; + } + } + m_colliderGroundarr[10] = value; + + for (i = 0; i < 11; i++) + { + if (m_colliderGroundarr[i]) + { + truecount++; + } + else + { + falsecount++; + } + } + + // Equal truecounts and false counts means we're colliding with something. + + if (falsecount > 1.2*truecount) + { + m_iscollidingGround = false; + } + else + { + m_iscollidingGround = true; + } + if (m_wascollidingGround != m_iscollidingGround) + { + //base.SendCollisionUpdate(new CollisionEventUpdate()); + } + m_wascollidingGround = m_iscollidingGround; + } + } + + /// + /// Returns if the avatar is colliding with an object + /// + public override bool CollidingObj + { + get { return m_iscollidingObj; } + set + { + m_iscollidingObj = value; + if (value) + m_pidControllerActive = false; + else + m_pidControllerActive = true; + } + } + + /// + /// turn the PID controller on or off. + /// The PID Controller will turn on all by itself in many situations + /// + /// + public void SetPidStatus(bool status) + { + m_pidControllerActive = status; + } + + public override bool Stopped + { + get { return _zeroFlag; } + } + + /// + /// This 'puts' an avatar somewhere in the physics space. + /// Not really a good choice unless you 'know' it's a good + /// spot otherwise you're likely to orbit the avatar. + /// + public override PhysicsVector Position + { + get { return _position; } + set + { + lock (OdeScene.OdeLock) + { + d.BodySetPosition(Body, value.X, value.Y, value.Z); + _position = value; + } + } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + /// + /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight + /// and use it to offset landings properly + /// + public override PhysicsVector Size + { + get { return new PhysicsVector(CAPSULE_RADIUS*2, CAPSULE_RADIUS*2, CAPSULE_LENGTH); } + set + { + m_pidControllerActive = true; + lock (OdeScene.OdeLock) + { + d.JointDestroy(Amotor); + + PhysicsVector SetSize = value; + float prevCapsule = CAPSULE_LENGTH; + float capsuleradius = CAPSULE_RADIUS; + //capsuleradius = 0.2f; + + CAPSULE_LENGTH = (SetSize.Z - ((SetSize.Z*0.52f))); // subtract 43% of the size + //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); + d.BodyDestroy(Body); + + _parent_scene.waitForSpaceUnlock(_parent_scene.space); + + d.GeomDestroy(Shell); + AvatarGeomAndBodyCreation(_position.X, _position.Y, + _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor); + Velocity = new PhysicsVector(0f, 0f, 0f); + + } + _parent_scene.geom_name_map[Shell] = m_name; + _parent_scene.actor_name_map[Shell] = (PhysicsActor) this; + } + } + /// + /// This creates the Avatar's physical Surrogate at the position supplied + /// + /// + /// + /// + private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ, float tensor) + { + + if (System.Environment.OSVersion.Platform == PlatformID.Unix) + { + m_foundDebian = true; + m_tensor = 2000000f; + } + else + { + m_tensor = 550000f; + } + + int dAMotorEuler = 1; + _parent_scene.waitForSpaceUnlock(_parent_scene.space); + Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); + d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH); + Body = d.BodyCreate(_parent_scene.world); + d.BodySetPosition(Body, npositionX, npositionY, npositionZ); + + d.BodySetMass(Body, ref ShellMass); + d.Matrix3 m_caprot; + // 90 Stand up on the cap of the capped cyllinder + d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2)); + + + d.GeomSetRotation(Shell, ref m_caprot); + d.BodySetRotation(Body, ref m_caprot); + + d.GeomSetBody(Shell, Body); + + + // The purpose of the AMotor here is to keep the avatar's physical + // surrogate from rotating while moving + Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); + d.JointAttach(Amotor, Body, IntPtr.Zero); + d.JointSetAMotorMode(Amotor, dAMotorEuler); + d.JointSetAMotorNumAxes(Amotor, 3); + d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0); + d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0); + d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1); + d.JointSetAMotorAngle(Amotor, 0, 0); + d.JointSetAMotorAngle(Amotor, 1, 0); + d.JointSetAMotorAngle(Amotor, 2, 0); + + // These lowstops and high stops are effectively (no wiggle room) + d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f); + + // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the + // capped cyllinder will fall over + d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor); + + //d.Matrix3 bodyrotation = d.BodyGetRotation(Body); + //d.QfromR( + //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068, + // + //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22); + //standupStraight(); + + + + } + + // + /// + /// Uses the capped cyllinder volume formula to calculate the avatar's mass. + /// This may be used in calculations in the scene/scenepresence + /// + public override float Mass + { + get + { + float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH); + return m_density*AVvolume; + } + } + + private void standupStraight() + { + + // The purpose of this routine here is to quickly stabilize the Body while it's popped up in the air. + // The amotor needs a few seconds to stabilize so without it, the avatar shoots up sky high when you + // change appearance and when you enter the simulator + // After this routine is done, the amotor stabilizes much quicker + d.Vector3 feet; + d.Vector3 head; + d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet); + d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head); + float posture = head.Z - feet.Z; + + // restoring force proportional to lack of posture: + float servo = (2.5f - posture) * POSTURE_SERVO; + d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f); + d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f); + //d.Matrix3 bodyrotation = d.BodyGetRotation(Body); + //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22); + } + + public override PhysicsVector Force + { + get { return new PhysicsVector(_target_velocity.X, _target_velocity.Y, _target_velocity.Z); } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override PhysicsVector Velocity + { + get { + // There's a problem with PhysicsVector.Zero! Don't Use it Here! + if (_zeroFlag) + return new PhysicsVector(0f, 0f, 0f); + m_lastUpdateSent = false; + return _velocity; + } + set + { + m_pidControllerActive = true; + _target_velocity = value; + } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override bool Kinematic + { + get { return false; } + set { } + } + + public override Quaternion Orientation + { + get { return Quaternion.Identity; } + set { + //Matrix3 or = Orientation.ToRotationMatrix(); + //d.Matrix3 ord = new d.Matrix3(or.m00, or.m10, or.m20, or.m01, or.m11, or.m21, or.m02, or.m12, or.m22); + //d.BodySetRotation(Body, ref ord); + + } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public void SetAcceleration(PhysicsVector accel) + { + m_pidControllerActive = true; + _acceleration = accel; + } + + /// + /// Adds the force supplied to the Target Velocity + /// The PID controller takes this target velocity and tries to make it a reality + /// + /// + public override void AddForce(PhysicsVector force) + { + m_pidControllerActive = true; + _target_velocity.X += force.X; + _target_velocity.Y += force.Y; + _target_velocity.Z += force.Z; + + //m_lastUpdateSent = false; + } + + /// + /// After all of the forces add up with 'add force' we apply them with doForce + /// + /// + public void doForce(PhysicsVector force) + { + if (!collidelock) + { + d.BodyAddForce(Body, force.X, force.Y, force.Z); + //d.BodySetRotation(Body, ref m_StandUpRotation); + //standupStraight(); + + } + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + + + /// + /// Called from Simulate + /// This is the avatar's movement control + PID Controller + /// + /// + public void Move(float timeStep) + { + // no lock; for now it's only called from within Simulate() + + // If the PID Controller isn't active then we set our force + // calculating base velocity to the current position + if (System.Environment.OSVersion.Platform == PlatformID.Unix) + { + PID_D = 3200.0f; + PID_P = 1400.0f; + } + else + { + PID_D = 2200.0f; + PID_P = 900.0f; + } + + + if (m_pidControllerActive == false) + { + _zeroPosition = d.BodyGetPosition(Body); + } + //PidStatus = true; + + PhysicsVector vec = new PhysicsVector(); + d.Vector3 vel = d.BodyGetLinearVel(Body); + float movementdivisor = 1f; + + if (!m_alwaysRun) + { + movementdivisor = 1.3f; + } + else + { + movementdivisor = 0.8f; + } + + // if velocity is zero, use position control; otherwise, velocity control + 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' + if (!_zeroFlag) + { + _zeroFlag = true; + _zeroPosition = d.BodyGetPosition(Body); + } + if (m_pidControllerActive) + { + // We only want to deactivate the PID Controller if we think we want to have our surrogate + // react to the physics scene by moving it's position. + // Avatar to Avatar collisions + // Prim to avatar collisions + + d.Vector3 pos = d.BodyGetPosition(Body); + vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); + vec.Y = (_target_velocity.Y - vel.Y)*(PID_D) + (_zeroPosition.Y - pos.Y)* (PID_P * 2); + if (flying) + { + vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; + } + } + //PidStatus = true; + } + else + { + m_pidControllerActive = true; + _zeroFlag = false; + if (m_iscolliding && !flying) + { + // We're flying and colliding with something + vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D); + vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D); + } + else if (m_iscolliding && flying) + { + // We're flying and colliding with something + vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*(PID_D / 16); + vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*(PID_D / 16); + } + else if (!m_iscolliding && flying) + { + // We're flying and colliding with something + vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D/6); + vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D/6); + } + + if (m_iscolliding && !flying && _target_velocity.Z > 0.0f) + { + // We're colliding with something and we're not flying but we're moving + // This means we're walking or running. + d.Vector3 pos = d.BodyGetPosition(Body); + vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P; + if (_target_velocity.X > 0) + { + vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D; + } + if (_target_velocity.Y > 0) + { + vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D; + } + } + else if (!m_iscolliding && !flying) + { + // we're not colliding and we're not flying so that means we're falling! + // m_iscolliding includes collisions with the ground. + d.Vector3 pos = d.BodyGetPosition(Body); + if (_target_velocity.X > 0) + { + vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D; + } + if (_target_velocity.Y > 0) + { + vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D; + } + } + + + if (flying) + { + vec.Z = (_target_velocity.Z - vel.Z) * (PID_D); + } + } + if (flying) + { + vec.Z += (9.8f*m_mass); + } + + + doForce(vec); + } + + /// + /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence. + /// + public void UpdatePositionAndVelocity() + { + // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! + d.Vector3 vec = d.BodyGetPosition(Body); + + // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) + if (vec.X < 0.0f) vec.X = 0.0f; + if (vec.Y < 0.0f) vec.Y = 0.0f; + if (vec.X > 255.95f) vec.X = 255.95f; + if (vec.Y > 255.95f) vec.Y = 255.95f; + + _position.X = vec.X; + _position.Y = vec.Y; + _position.Z = vec.Z; + + // Did we move last? = zeroflag + // This helps keep us from sliding all over + + if (_zeroFlag) + { + _velocity.X = 0.0f; + _velocity.Y = 0.0f; + _velocity.Z = 0.0f; + + // Did we send out the 'stopped' message? + if (!m_lastUpdateSent) + { + m_lastUpdateSent = true; + //base.RequestPhysicsterseUpdate(); + + } + } + else + { + m_lastUpdateSent = false; + vec = d.BodyGetLinearVel(Body); + _velocity.X = (vec.X); + _velocity.Y = (vec.Y); + + _velocity.Z = (vec.Z); + if (_velocity.Z < -6 && !m_hackSentFall) + { + // Collisionupdates will be used in the future, right now the're not being used. + m_hackSentFall = true; + //base.SendCollisionUpdate(new CollisionEventUpdate()); + m_pidControllerActive = false; + } + else if (flying && !m_hackSentFly) + { + //m_hackSentFly = true; + //base.SendCollisionUpdate(new CollisionEventUpdate()); + } + else + { + m_hackSentFly = false; + m_hackSentFall = false; + } + } + } + + /// + /// Cleanup the things we use in the scene. + /// + public void Destroy() + { + lock (OdeScene.OdeLock) + { + // Kill the Amotor + d.JointDestroy(Amotor); + + //kill the Geometry + _parent_scene.waitForSpaceUnlock(_parent_scene.space); + + d.GeomDestroy(Shell); + _parent_scene.geom_name_map.Remove(Shell); + + //kill the body + d.BodyDestroy(Body); + } + } + public override void CrossingFailure() + { + + } + } +} diff --git a/trunk/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/trunk/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs new file mode 100644 index 0000000000..50087a5dac --- /dev/null +++ b/trunk/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -0,0 +1,1425 @@ +/* +* 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; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Axiom.Math; +using Ode.NET; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.OdePlugin +{ + public class OdePrim : PhysicsActor + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public PhysicsVector _position; + private PhysicsVector _velocity; + private PhysicsVector m_lastVelocity = new PhysicsVector(0.0f, 0.0f, 0.0f); + private PhysicsVector m_lastposition = new PhysicsVector(0.0f, 0.0f, 0.0f); + private PhysicsVector m_rotationalVelocity; + private PhysicsVector _size; + private PhysicsVector _acceleration; + private Quaternion _orientation; + private PhysicsVector m_taintposition; + private PhysicsVector m_taintsize; + private PhysicsVector m_taintVelocity = PhysicsVector.Zero; + private Quaternion m_taintrot; + private bool m_taintshape = false; + private bool m_taintPhysics = false; + public bool m_taintremove = false; + public bool m_taintdisable = false; + public bool m_disabled = false; + public bool m_taintadd = false; + public GCHandle gc; + private CollisionLocker ode; + + private bool m_taintforce = false; + private List m_forcelist = new List(); + + private IMesh _mesh; + private PrimitiveBaseShape _pbs; + private OdeScene _parent_scene; + public IntPtr m_targetSpace = (IntPtr) 0; + public IntPtr prim_geom; + public IntPtr prev_geom; + public IntPtr _triMeshData; + + private bool iscolliding = false; + private bool m_isphysical = false; + private bool m_throttleUpdates = false; + private int throttleCounter = 0; + public int m_interpenetrationcount = 0; + public int m_collisionscore = 0; + public int m_roundsUnderMotionThreshold = 0; + private int m_crossingfailures = 0; + + public bool outofBounds = false; + private float m_density = 10.000006836f; // Aluminum g/cm3; + + + public bool _zeroFlag = false; + private bool m_lastUpdateSent = false; + + public IntPtr Body = (IntPtr) 0; + private String m_primName; + private PhysicsVector _target_velocity; + public d.Mass pMass; + + private int debugcounter = 0; + + public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size, + Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode) + { + + + gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned); + ode = dode; + _velocity = new PhysicsVector(); + _position = pos; + m_taintposition = pos; + if (_position.X > 257) + { + _position.X = 257; + } + if (_position.X < 0) + { + _position.X = 0; + } + if (_position.Y > 257) + { + _position.Y = 257; + } + if (_position.Y < 0) + { + _position.Y = 0; + } + + prim_geom = (IntPtr)0; + prev_geom = (IntPtr)0; + + _size = size; + m_taintsize = _size; + _acceleration = new PhysicsVector(); + m_rotationalVelocity = PhysicsVector.Zero; + _orientation = rotation; + m_taintrot = _orientation; + _mesh = mesh; + _pbs = pbs; + + _parent_scene = parent_scene; + m_targetSpace = (IntPtr)0; + + if (pos.Z < 0) + m_isphysical = false; + else + { + m_isphysical = pisPhysical; + // If we're physical, we need to be in the master space for now. + // linksets *should* be in a space together.. but are not currently + if (m_isphysical) + m_targetSpace = _parent_scene.space; + } + m_primName = primName; + m_taintadd = true; + _parent_scene.AddPhysicsActorTaint(this); + // don't do .add() here; old geoms get recycled with the same hash + + } + + /// + /// Nasty, however without this you get + /// 'invalid operation for locked space' when things are really loaded down + /// + /// + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Prim; } + set { return; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public void SetGeom(IntPtr geom) + { + prev_geom = prim_geom; + prim_geom = geom; + //m_log.Warn("Setting Geom to: " + prim_geom); + + } + + public void enableBody() + { + // Sets the geom to a body + Body = d.BodyCreate(_parent_scene.world); + + setMass(); + d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.BodySetQuaternion(Body, ref myrot); + d.GeomSetBody(prim_geom, Body); + d.BodySetAutoDisableFlag(Body, true); + d.BodySetAutoDisableSteps(Body, 20); + + m_interpenetrationcount = 0; + m_collisionscore = 0; + m_disabled = false; + + _parent_scene.addActivePrim(this); + } + + private float CalculateMass() + { + float volume = 0; + + // No material is passed to the physics engines yet.. soo.. + // we're using the m_density constant in the class definition + + + float returnMass = 0; + + switch (_pbs.ProfileShape) + { + case ProfileShape.Square: + // Profile Volume + + volume = _size.X*_size.Y*_size.Z; + + // If the user has 'hollowed out' + // ProfileHollow is one of those 0 to 50000 values :P + // we like percentages better.. so turning into a percentage + + if (((float) _pbs.ProfileHollow/50000f) > 0.0) + { + float hollowAmount = (float) _pbs.ProfileHollow/50000f; + + // calculate the hollow volume by it's shape compared to the prim shape + float hollowVolume = 0; + switch (_pbs.HollowShape) + { + case HollowShape.Square: + case HollowShape.Same: + // Cube Hollow volume calculation + float hollowsizex = _size.X*hollowAmount; + float hollowsizey = _size.Y*hollowAmount; + float hollowsizez = _size.Z*hollowAmount; + hollowVolume = hollowsizex*hollowsizey*hollowsizez; + break; + + case HollowShape.Circle: + // Hollow shape is a perfect cyllinder in respect to the cube's scale + // Cyllinder hollow volume calculation + float hRadius = _size.X/2; + float hLength = _size.Z; + + // pi * r2 * h + hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount); + break; + + case HollowShape.Triangle: + // Equilateral Triangular Prism volume hollow calculation + // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y + + float aLength = _size.Y; + // 1/2 abh + hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount); + break; + + default: + hollowVolume = 0; + break; + } + volume = volume - hollowVolume; + } + + break; + + default: + // we don't have all of the volume formulas yet so + // use the common volume formula for all + volume = _size.X*_size.Y*_size.Z; + break; + } + + // Calculate Path cut effect on volume + // Not exact, in the triangle hollow example + // They should never be zero or less then zero.. + // we'll ignore it if it's less then zero + + // ProfileEnd and ProfileBegin are values + // from 0 to 50000 + + // Turning them back into percentages so that I can cut that percentage off the volume + + float PathCutEndAmount = _pbs.ProfileEnd; + float PathCutStartAmount = _pbs.ProfileBegin; + if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f) + { + float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f); + + // Check the return amount for sanity + if (pathCutAmount >= 0.99f) + pathCutAmount = 0.99f; + + volume = volume - (volume*pathCutAmount); + } + + // Mass = density * volume + + returnMass = m_density*volume; + + return returnMass; + } + + public void setMass() + { + if (Body != (IntPtr) 0) + { + d.MassSetBoxTotal(out pMass, CalculateMass(), _size.X, _size.Y, _size.Z); + d.BodySetMass(Body, ref pMass); + } + } + + + public void disableBody() + { + //this kills the body so things like 'mesh' can re-create it. + if (Body != (IntPtr) 0) + { + _parent_scene.remActivePrim(this); + d.BodyDestroy(Body); + Body = (IntPtr) 0; + } + m_disabled = true; + m_collisionscore = 0; + } + + public void setMesh(OdeScene parent_scene, IMesh mesh) + { + // This sleeper is there to moderate how long it takes between + // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object + + System.Threading.Thread.Sleep(10); + + //Kill Body so that mesh can re-make the geom + if (IsPhysical && Body != (IntPtr) 0) + { + disableBody(); + } + + float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory + int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage + int VertexCount = vertexList.GetLength(0)/3; + int IndexCount = indexList.GetLength(0); + + _triMeshData = d.GeomTriMeshDataCreate(); + + d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3*sizeof (float), VertexCount, indexList, IndexCount, + 3*sizeof (int)); + d.GeomTriMeshDataPreprocess(_triMeshData); + + + _parent_scene.waitForSpaceUnlock(m_targetSpace); + + try + { + if (prim_geom == (IntPtr)0) + { + SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); + } + } + catch (System.AccessViolationException) + { + + m_log.Error("[PHYSICS]: MESH LOCKED"); + return; + } + if (IsPhysical && Body == (IntPtr) 0) + { + // Recreate the body + m_interpenetrationcount = 0; + m_collisionscore = 0; + + enableBody(); + + } + } + + public void ProcessTaints(float timestep) + { + + + if (m_taintadd) + { + changeadd(timestep); + } + + if (m_taintposition != _position) + Move(timestep); + + if (m_taintrot != _orientation) + rotate(timestep); + // + + if (m_taintPhysics != m_isphysical) + changePhysicsStatus(timestep); + // + + if (m_taintsize != _size) + changesize(timestep); + // + + if (m_taintshape) + changeshape(timestep); + // + + if (m_taintforce) + changeAddForce(timestep); + + if (m_taintdisable) + changedisable(timestep); + + if (m_taintVelocity != PhysicsVector.Zero) + changevelocity(timestep); + } + + public void ResetTaints() + { + + m_taintposition = _position; + + m_taintrot = _orientation; + + m_taintPhysics = m_isphysical; + + m_taintsize = _size; + + + m_taintshape = false; + + m_taintforce = false; + + m_taintdisable = false; + + m_taintVelocity = PhysicsVector.Zero; + } + public void changeadd(float timestep) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position); + IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position); + + if (targetspace == IntPtr.Zero) + targetspace = _parent_scene.createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); + + m_targetSpace = targetspace; + + + + if (_mesh != null) + { + } + else + { + if (_parent_scene.needsMeshing(_pbs)) + { + // Don't need to re-enable body.. it's done in SetMesh + _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size); + // createmesh returns null when it's a shape that isn't a cube. + } + } + + lock (OdeScene.OdeLock) + { + if (_mesh != null) + { + setMesh(_parent_scene, _mesh); + } + else + { + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + { + if (((_size.X / 2f) > 0f)) + { + + + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { + SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); + } + catch (System.AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); + ode.dunlock(_parent_scene.world); + return; + } + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + catch (System.AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); + ode.dunlock(_parent_scene.world); + return; + } + } + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + catch (System.AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); + ode.dunlock(_parent_scene.world); + return; + } + } + } + //else if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) + //{ + //Cyllinder + //if (_size.X == _size.Y) + //{ + //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z); + //} + //else + //{ + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + //} + //} + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + catch (System.AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); + ode.dunlock(_parent_scene.world); + return; + } + } + } + if (prim_geom != (IntPtr) 0) + { + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + } + + + if (m_isphysical && Body == (IntPtr)0) + { + enableBody(); + } + + + } + ode.dunlock(_parent_scene.world); + _parent_scene.geom_name_map[prim_geom] = this.m_primName; + _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this; + m_taintadd = false; + + + } + public void Move(float timestep) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + + if (m_isphysical) + { + // This is a fallback.. May no longer be necessary. + if (Body == (IntPtr) 0) + enableBody(); + //Prim auto disable after 20 frames, + //if you move it, re-enable the prim manually. + + d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); + d.BodyEnable(Body); + + } + else + { + string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); + int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); + _parent_scene.waitForSpaceUnlock(m_targetSpace); + + IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace); + m_targetSpace = tempspace; + + _parent_scene.waitForSpaceUnlock(m_targetSpace); + if (prim_geom != (IntPtr) 0) + { + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + + _parent_scene.waitForSpaceUnlock(m_targetSpace); + d.SpaceAdd(m_targetSpace, prim_geom); + } + } + ode.dunlock(_parent_scene.world); + + resetCollisionAccounting(); + m_taintposition = _position; + } + + public void rotate(float timestep) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + if (m_isphysical && Body != (IntPtr) 0) + { + d.BodySetQuaternion(Body, ref myrot); + } + + ode.dunlock(_parent_scene.world); + + resetCollisionAccounting(); + m_taintrot = _orientation; + } + + private void resetCollisionAccounting() + { + m_collisionscore = 0; + m_interpenetrationcount = 0; + m_disabled = false; + } + + public void changedisable(float timestep) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + m_disabled = true; + if (Body != (IntPtr)0) + { + d.BodyDisable(Body); + Body = (IntPtr)0; + } + ode.dunlock(_parent_scene.world); + + m_taintdisable = false; + } + + public void changePhysicsStatus(float timestap) + { + lock (ode) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + if (m_isphysical == true) + { + if (Body == (IntPtr)0) + { + enableBody(); + } + } + else + { + if (Body != (IntPtr)0) + { + disableBody(); + } + } + + ode.dunlock(_parent_scene.world); + } + + resetCollisionAccounting(); + m_taintPhysics = m_isphysical; + } + + public void changesize(float timestamp) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + //if (!_parent_scene.geom_name_map.ContainsKey(prim_geom)) + //{ + // m_taintsize = _size; + //return; + //} + string oldname = _parent_scene.geom_name_map[prim_geom]; + + + // Cleanup of old prim geometry + if (_mesh != null) + { + // Cleanup meshing here + } + //kill body to rebuild + if (IsPhysical && Body != (IntPtr) 0) + { + disableBody(); + } + if (d.SpaceQuery(m_targetSpace, prim_geom)) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + d.SpaceRemove(m_targetSpace, prim_geom); + } + d.GeomDestroy(prim_geom); + prim_geom = (IntPtr)0; + // we don't need to do space calculation because the client sends a position update also. + + // Construction of new prim + if (_parent_scene.needsMeshing(_pbs)) + { + // Don't need to re-enable body.. it's done in SetMesh + IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size); + // createmesh returns null when it's a shape that isn't a cube. + if (mesh != null) + { + setMesh(_parent_scene, mesh); + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + + + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + if (IsPhysical && Body == (IntPtr)0) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + d.BodyEnable(Body); + } + } + else + { + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + { + if (((_size.X / 2f) > 0f) && ((_size.X / 2f) < 1000)) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); + } + else + { + m_log.Info("[PHYSICS]: Failed to load a sphere bad size"); + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + } + //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight) + //{ + //Cyllinder + //if (_size.X == _size.Y) + //{ + // prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z); + //} + //else + //{ + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + //} + //} + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + } + } + else + { + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + } + //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight) + //{ + //Cyllinder + //if (_size.X == _size.Y) + //{ + //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z); + //} + //else + //{ + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + //} + //} + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + + + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + if (IsPhysical && Body == (IntPtr) 0) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + d.BodyEnable(Body); + } + } + + _parent_scene.geom_name_map[prim_geom] = oldname; + + ode.dunlock(_parent_scene.world); + + resetCollisionAccounting(); + m_taintsize = _size; + } + + public void changeshape(float timestamp) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + + string oldname = _parent_scene.geom_name_map[prim_geom]; + + // Cleanup of old prim geometry and Bodies + if (IsPhysical && Body != (IntPtr) 0) + { + disableBody(); + } + d.GeomDestroy(prim_geom); + prim_geom = (IntPtr) 0; + // we don't need to do space calculation because the client sends a position update also. + + // Construction of new prim + if (_parent_scene.needsMeshing(_pbs)) + { + // Don't need to re-enable body.. it's done in SetMesh + IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size); + // createmesh returns null when it's a shape that isn't a cube. + if (mesh != null) + { + setMesh(_parent_scene, mesh); + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + + + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + if (IsPhysical && Body == (IntPtr)0) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + d.BodyEnable(Body); + } + } + else + { + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + { + if (((_size.X / 2f) > 0f) && ((_size.X / 2f) < 1000)) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); + } + else + { + m_log.Info("[PHYSICS]: Failed to load a sphere bad size"); + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + } + //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight) + //{ + //Cyllinder + //if (_size.X == _size.Y) + //{ + // prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z); + //} + //else + //{ + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + //} + //} + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + } + } + else + { + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + } + //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight) + //{ + //Cyllinder + //if (_size.X == _size.Y) + //{ + //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z); + //} + //else + //{ + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + //} + //} + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + + + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + if (IsPhysical && Body == (IntPtr)0) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + d.BodyEnable(Body); + } + } + _parent_scene.geom_name_map[prim_geom] = oldname; + + ode.dunlock(_parent_scene.world); + + resetCollisionAccounting(); + m_taintshape = false; + } + + public void changeAddForce(float timestamp) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + + lock (m_forcelist) + { + //m_log.Info("[PHYSICS]: dequeing forcelist"); + if (IsPhysical) + { + PhysicsVector iforce = new PhysicsVector(); + for (int i = 0; i < m_forcelist.Count; i++) + { + iforce = iforce + (m_forcelist[i]*100); + } + d.BodyEnable(Body); + d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z); + } + m_forcelist.Clear(); + } + + ode.dunlock(_parent_scene.world); + + m_collisionscore = 0; + m_interpenetrationcount = 0; + m_taintforce = false; + + } + private void changevelocity(float timestep) + { + lock (ode) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + System.Threading.Thread.Sleep(20); + if (IsPhysical) + { + if (Body != (IntPtr)0) + { + d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z); + } + } + + ode.dunlock(_parent_scene.world); + } + //resetCollisionAccounting(); + m_taintVelocity = PhysicsVector.Zero; + } + public override bool IsPhysical + { + get { return m_isphysical; } + set { m_isphysical = value; } + } + + public void setPrimForRemoval() + { + m_taintremove = true; + } + + public override bool Flying + { + get { return false; //no flying prims for you + } + set { } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return m_throttleUpdates; } + set { m_throttleUpdates = value; } + } + + public override bool Stopped + { + get { return _zeroFlag; } + } + + public override PhysicsVector Position + { + get { return _position; } + + set { _position = value; + //m_log.Info("[PHYSICS]: " + _position.ToString()); + } + } + + public override PhysicsVector Size + { + get { return _size; } + set { _size = value; } + } + + public override float Mass + { + get { return CalculateMass(); } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { + + _pbs = value; + m_taintshape = true; + } + } + + public override PhysicsVector Velocity + { + get + { + // Averate previous velocity with the new one so + // client object interpolation works a 'little' better + PhysicsVector returnVelocity = new PhysicsVector(); + returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2; + returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2; + returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2; + return returnVelocity; + } + set { + _velocity = value; + + m_taintVelocity = value; + _parent_scene.AddPhysicsActorTaint(this); + + + } + } + + public override float CollisionScore + { + get { return m_collisionscore; } + } + + public override bool Kinematic + { + get { return false; } + set { } + } + + public override Quaternion Orientation + { + get { return _orientation; } + set { _orientation = value; } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + + public void SetAcceleration(PhysicsVector accel) + { + _acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + m_forcelist.Add(force); + m_taintforce = true; + //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString()); + } + + public override PhysicsVector RotationalVelocity + { + get { + PhysicsVector pv = new PhysicsVector(0, 0, 0); + if (_zeroFlag) + return pv; + m_lastUpdateSent = false; + + if (m_rotationalVelocity.IsIdentical(pv, 0.2f)) + return pv; + + return m_rotationalVelocity; + } + set { m_rotationalVelocity = value; } + } + public override void CrossingFailure() + { + m_crossingfailures++; + if (m_crossingfailures > 5) + { + base.RaiseOutOfBounds(_position); + return; + + } + else if (m_crossingfailures == 5) + { + m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName); + } + } + public void UpdatePositionAndVelocity() + { + // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! + PhysicsVector pv = new PhysicsVector(0, 0, 0); + if (Body != (IntPtr) 0) + { + d.Vector3 vec = d.BodyGetPosition(Body); + d.Quaternion ori = d.BodyGetQuaternion(Body); + d.Vector3 vel = d.BodyGetLinearVel(Body); + d.Vector3 rotvel = d.BodyGetAngularVel(Body); + + PhysicsVector l_position = new PhysicsVector(); + + + // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) + //if (vec.X < 0.0f) { vec.X = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + //if (vec.Y < 0.0f) { vec.Y = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + //if (vec.X > 255.95f) { vec.X = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + //if (vec.Y > 255.95f) { vec.Y = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + + m_lastposition = _position; + + l_position.X = vec.X; + l_position.Y = vec.Y; + l_position.Z = vec.Z; + + if (l_position.X > 255.95f || l_position.X < 0f || l_position.Y > 255.95f || l_position.Y < 0f) + { + base.RaiseOutOfBounds(_position); + } + //if (m_crossingfailures < 5) + //{ + //base.RequestPhysicsterseUpdate(); + //} + //} + + if (l_position.Z < 0) + { + // This is so prim that get lost underground don't fall forever and suck up + // + // Sim resources and memory. + // Disables the prim's movement physics.... + // It's a hack and will generate a console message if it fails. + + + //IsPhysical = false; + base.RaiseOutOfBounds(_position); + _velocity.X = 0; + _velocity.Y = 0; + _velocity.Z = 0; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + base.RequestPhysicsterseUpdate(); + m_throttleUpdates = false; + throttleCounter = 0; + _zeroFlag = true; + //outofBounds = true; + } + + if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) + && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) + && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02)) + { + _zeroFlag = true; + m_throttleUpdates = false; + } + else + { + //System.Console.WriteLine(Math.Abs(m_lastposition.X - l_position.X).ToString()); + _zeroFlag = false; + } + + + if (_zeroFlag) + { + // Supposedly this is supposed to tell SceneObjectGroup that + // no more updates need to be sent.. + // but it seems broken. + _velocity.X = 0.0f; + _velocity.Y = 0.0f; + _velocity.Z = 0.0f; + //_orientation.w = 0f; + //_orientation.x = 0f; + //_orientation.y = 0f; + //_orientation.z = 0f; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + if (!m_lastUpdateSent) + { + m_throttleUpdates = false; + throttleCounter = 0; + m_rotationalVelocity = pv; + base.RequestPhysicsterseUpdate(); + m_lastUpdateSent = true; + } + } + else + { + m_lastVelocity = _velocity; + + _position = l_position; + + _velocity.X = vel.X; + _velocity.Y = vel.Y; + _velocity.Z = vel.Z; + if (_velocity.IsIdentical(pv, 0.5f)) + { + m_rotationalVelocity = pv; + } + else + { + m_rotationalVelocity.setValues(rotvel.X, rotvel.Y, rotvel.Z); + } + + //System.Console.WriteLine("ODE: " + m_rotationalVelocity.ToString()); + _orientation.w = ori.W; + _orientation.x = ori.X; + _orientation.y = ori.Y; + _orientation.z = ori.Z; + m_lastUpdateSent = false; + if (!m_throttleUpdates || throttleCounter > 15) + { + + base.RequestPhysicsterseUpdate(); + } + else + { + throttleCounter++; + } + } + m_lastposition = l_position; + } + else + { + // Not a body.. so Make sure the client isn't interpolating + _velocity.X = 0; + _velocity.Y = 0; + _velocity.Z = 0; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + _zeroFlag = true; + } + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/trunk/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs new file mode 100644 index 0000000000..3817868753 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -0,0 +1,1710 @@ +/* +* 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; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Axiom.Math; +using Ode.NET; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Physics.Manager; + +//using OpenSim.Region.Physics.OdePlugin.Meshing; + +namespace OpenSim.Region.Physics.OdePlugin +{ + /// + /// ODE plugin + /// + public class OdePlugin : IPhysicsPlugin + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private CollisionLocker ode; + private OdeScene _mScene; + + public OdePlugin() + { + ode = new CollisionLocker(); + } + + public bool Init() + { + return true; + } + + public PhysicsScene GetScene() + { + if (_mScene == null) + { + _mScene = new OdeScene(ode); + } + return (_mScene); + } + + public string GetName() + { + return ("OpenDynamicsEngine"); + } + + public void Dispose() + { + + + } + } + + public class OdeScene : PhysicsScene + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + CollisionLocker ode; + + private const uint m_regionWidth = Constants.RegionSize; + private const uint m_regionHeight = Constants.RegionSize; + + private static float ODE_STEPSIZE = 0.020f; + private static bool RENDER_FLAG = false; + private static float metersInSpace = 29.9f; + + private int interpenetrations_before_disable = 35; + + private IntPtr contactgroup; + private IntPtr LandGeom = (IntPtr) 0; + private float[] _heightmap; + private float[] _origheightmap; + + private d.NearCallback nearCallback; + public d.TriCallback triCallback; + public d.TriArrayCallback triArrayCallback; + private List _characters = new List(); + private List _prims = new List(); + private List _activeprims = new List(); + private List _taintedPrim = new List(); + public Dictionary geom_name_map = new Dictionary(); + public Dictionary actor_name_map = new Dictionary(); + private d.ContactGeom[] contacts = new d.ContactGeom[30]; + private d.Contact contact; + private d.Contact TerrainContact; + private d.Contact AvatarMovementprimContact; + private d.Contact AvatarMovementTerrainContact; + + + + private int m_physicsiterations = 10; + private float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag + private PhysicsActor PANull = new NullPhysicsActor(); + private float step_time = 0.0f; + private int ms = 0; + public IntPtr world; + + public IntPtr space; + + private IntPtr tmpSpace; + // split static geometry collision handling into spaces of 30 meters + public IntPtr[,] staticPrimspace = new IntPtr[(int) (300/metersInSpace),(int) (300/metersInSpace)]; + + public static Object OdeLock = new Object(); + + public IMesher mesher; + + + /// + /// Initiailizes the scene + /// Sets many properties that ODE requires to be stable + /// These settings need to be tweaked 'exactly' right or weird stuff happens. + /// + public OdeScene(CollisionLocker dode) + { + ode = dode; + nearCallback = near; + triCallback = TriCallback; + triArrayCallback = TriArrayCallback; + /* + contact.surface.mode |= d.ContactFlags.Approx1 | d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP; + contact.surface.mu = 10.0f; + contact.surface.bounce = 0.9f; + contact.surface.soft_erp = 0.005f; + contact.surface.soft_cfm = 0.00003f; + */ + + // Centeral contact friction and bounce + contact.surface.mu = 250.0f; + contact.surface.bounce = 0.2f; + + // Terrain contact friction and Bounce + // This is the *non* moving version. Use this when an avatar + // isn't moving to keep it in place better + TerrainContact.surface.mode |= d.ContactFlags.SoftERP; + TerrainContact.surface.mu = 255.0f; + TerrainContact.surface.bounce = 0.1f; + TerrainContact.surface.soft_erp = 0.1025f; + + // Prim contact friction and bounce + // THis is the *non* moving version of friction and bounce + // Use this when an avatar comes in contact with a prim + // and is moving + AvatarMovementprimContact.surface.mu = 75.0f; + AvatarMovementprimContact.surface.bounce = 0.1f; + + // Terrain contact friction bounce and various error correcting calculations + // Use this when an avatar is in contact with the terrain and moving. + AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP; + AvatarMovementTerrainContact.surface.mu = 75.0f; + AvatarMovementTerrainContact.surface.bounce = 0.1f; + AvatarMovementTerrainContact.surface.soft_erp = 0.1025f; + + lock (OdeLock) + { + + // Creat the world and the first space + world = d.WorldCreate(); + space = d.HashSpaceCreate(IntPtr.Zero); + d.HashSpaceSetLevels(space, -4, 128); + contactgroup = d.JointGroupCreate(0); + //contactgroup + + + // Set the gravity,, don't disable things automatically (we set it explicitly on some things) + + d.WorldSetGravity(world, 0.0f, 0.0f, -9.8f); + d.WorldSetAutoDisableFlag(world, false); + d.WorldSetContactSurfaceLayer(world, 0.001f); + + // Set how many steps we go without running collision testing + // This is in addition to the step size. + // Essentially Steps * m_physicsiterations + d.WorldSetQuickStepNumIterations(world, m_physicsiterations); + ///d.WorldSetContactMaxCorrectingVel(world, 1000.0f); + } + + // zero out a heightmap array float array (single dimention [flattened])) + _heightmap = new float[514*514]; + + + // Zero out the prim spaces array (we split our space into smaller spaces so + // we can hit test less. + for (int i = 0; i < staticPrimspace.GetLength(0); i++) + { + for (int j = 0; j < staticPrimspace.GetLength(1); j++) + { + staticPrimspace[i, j] = IntPtr.Zero; + } + } + } + + public void starttiming() + { + ms = Environment.TickCount; + } + public int stoptiming() + { + return Environment.TickCount - ms; + } + // Initialize the mesh plugin + public override void Initialise(IMesher meshmerizer) + { + mesher = meshmerizer; + } + + internal void waitForSpaceUnlock(IntPtr space) + { + + while (d.SpaceLockQuery(space)) + { + + } + + + + } + /// + /// Debug space message for printing the space that a prim/avatar is in. + /// + /// + /// Returns which split up space the given position is in. + public string whichspaceamIin(PhysicsVector pos) + { + return calculateSpaceForGeom(pos).ToString(); + } + + /// + /// This is our near callback. A geometry is near a body + /// + /// The space that contains the geoms. Remember, spaces are also geoms + /// a geometry or space + /// another geometry or space + private void near(IntPtr space, IntPtr g1, IntPtr g2) + { + // no lock here! It's invoked from within Simulate(), which is thread-locked + + // Test if we're collidng a geom with a space. + // If so we have to drill down into the space recursively + + if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) + { + if (g1 == (IntPtr)0 || g2 == (IntPtr)0) + return; + // Separating static prim geometry spaces. + // We'll be calling near recursivly if one + // of them is a space to find all of the + // contact points in the space + try + { + d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); + } + catch (System.AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to collide test a space"); + return; + } + //Colliding a space or a geom with a space or a geom. so drill down + + //Collide all geoms in each space.. + //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); + //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback); + } + else + { + // Colliding Geom To Geom + // This portion of the function 'was' blatantly ripped off from BoxStack.cs + if (g1 == (IntPtr)0 || g2 == (IntPtr)0) + return; + + IntPtr b1 = d.GeomGetBody(g1); + IntPtr b2 = d.GeomGetBody(g2); + + if (g1 == g2) + return; // Can't collide with yourself + + if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) + return; + + + + d.GeomClassID id = d.GeomGetClass(g1); + + String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(g1, out name1)) + { + name1 = "null"; + } + if (!geom_name_map.TryGetValue(g2, out name2)) + { + name2 = "null"; + } + + //if (id == d.GeomClassId.TriMeshClass) + //{ + // m_log.Info("near: A collision was detected between {1} and {2}", 0, name1, name2); + //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); + //} + + // Figure out how many contact points we have + int count = 0; + try + { + //m_log.Warn(g1.ToString() + "|" + g2.ToString()); + count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf); + } + catch (SEHException) + { + m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); + ode.drelease(world); + base.TriggerPhysicsBasedRestart(); + } + catch (System.AccessViolationException) + { + + m_log.Warn("[PHYSICS]: Unable to collide test an object"); + return; + } + + PhysicsActor p1; + PhysicsActor p2; + + for (int i = 0; i < count; i++) + { + //m_log.Warn("[CCOUNT]: " + count); + IntPtr joint; + // If we're colliding with terrain, use 'TerrainContact' instead of contact. + // allows us to have different settings + + + if (!actor_name_map.TryGetValue(g1, out p1)) + { + p1 = PANull; + } + if (!actor_name_map.TryGetValue(g2, out p2)) + { + p2 = PANull; + } + + // We only need to test p2 for 'jump crouch purposes' + p2.IsColliding = true; + + + switch (p1.PhysicsActorType) + { + case (int)ActorTypes.Agent: + p2.CollidingObj = true; + break; + case (int)ActorTypes.Prim: + if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0) + p2.CollidingObj = true; + break; + case (int)ActorTypes.Unknown: + p2.CollidingGround = true; + break; + default: + p2.CollidingGround = true; + break; + } + + // we don't want prim or avatar to explode + + #region InterPenetration Handling - Unintended physics explosions + + if (contacts[i].depth >= 0.08f) + { + //This is disabled at the moment only because it needs more tweaking + //It will eventually be uncommented + + if (contacts[i].depth >= 1.00f) + { + //m_log.Debug("[PHYSICS]: " +contacts[i].depth.ToString()); + } + + //If you interpenetrate a prim with an agent + if ((p2.PhysicsActorType == (int) ActorTypes.Agent && + p1.PhysicsActorType == (int) ActorTypes.Prim) || + (p1.PhysicsActorType == (int) ActorTypes.Agent && + p2.PhysicsActorType == (int) ActorTypes.Prim)) + { + //contacts[i].depth = contacts[i].depth * 4.15f; + /* + if (p2.PhysicsActorType == (int) ActorTypes.Agent) + { + p2.CollidingObj = true; + contacts[i].depth = 0.003f; + p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); + OdeCharacter character = (OdeCharacter) p2; + character.SetPidStatus(true); + contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p1.Size.X / 2), contacts[i].pos.Y + (p1.Size.Y / 2), contacts[i].pos.Z + (p1.Size.Z / 2)); + + } + else + { + + //contacts[i].depth = 0.0000000f; + } + if (p1.PhysicsActorType == (int) ActorTypes.Agent) + { + + p1.CollidingObj = true; + contacts[i].depth = 0.003f; + p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); + contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p2.Size.X / 2), contacts[i].pos.Y + (p2.Size.Y / 2), contacts[i].pos.Z + (p2.Size.Z / 2)); + OdeCharacter character = (OdeCharacter)p1; + character.SetPidStatus(true); + } + else + { + + //contacts[i].depth = 0.0000000f; + } + */ + } + + + // If you interpenetrate a prim with another prim + if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim) + { + //OdePrim op1 = (OdePrim)p1; + //OdePrim op2 = (OdePrim)p2; + //op1.m_collisionscore++; + //op2.m_collisionscore++; + + + //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000) + //{ + //op1.m_taintdisable = true; + //AddPhysicsActorTaint(p1); + //op2.m_taintdisable = true; + //AddPhysicsActorTaint(p2); + //} + + //if (contacts[i].depth >= 0.25f) + //{ + // Don't collide, one or both prim will expld. + + + //op1.m_interpenetrationcount++; + //op2.m_interpenetrationcount++; + //interpenetrations_before_disable = 200; + //if (op1.m_interpenetrationcount >= interpenetrations_before_disable) + //{ + //op1.m_taintdisable = true; + //AddPhysicsActorTaint(p1); + //} + //if (op2.m_interpenetrationcount >= interpenetrations_before_disable) + //{ + // op2.m_taintdisable = true; + //AddPhysicsActorTaint(p2); + //} + + + //contacts[i].depth = contacts[i].depth / 8f; + //contacts[i].normal = new d.Vector3(0, 0, 1); + //} + //if (op1.m_disabled || op2.m_disabled) + //{ + //Manually disabled objects stay disabled + //contacts[i].depth = 0f; + //} + } + if (contacts[i].depth >= 1.00f) + { + //m_log.Info("[P]: " + contacts[i].depth.ToString()); + if ((p2.PhysicsActorType == (int) ActorTypes.Agent && + p1.PhysicsActorType == (int) ActorTypes.Unknown) || + (p1.PhysicsActorType == (int) ActorTypes.Agent && + p2.PhysicsActorType == (int) ActorTypes.Unknown)) + { + if (p2.PhysicsActorType == (int) ActorTypes.Agent) + { + OdeCharacter character = (OdeCharacter) p2; + + //p2.CollidingObj = true; + contacts[i].depth = 0.00000003f; + p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 0.5f); + contacts[i].pos = + new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), + contacts[i].pos.Y + (p1.Size.Y/2), + contacts[i].pos.Z + (p1.Size.Z/2)); + character.SetPidStatus(true); + } + else + { + } + if (p1.PhysicsActorType == (int) ActorTypes.Agent) + { + OdeCharacter character = (OdeCharacter)p1; + + //p2.CollidingObj = true; + contacts[i].depth = 0.00000003f; + p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 0.5f); + contacts[i].pos = + new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), + contacts[i].pos.Y + (p1.Size.Y/2), + contacts[i].pos.Z + (p1.Size.Z/2)); + character.SetPidStatus(true); + } + else + { + //contacts[i].depth = 0.0000000f; + } + } + } + } + + #endregion + + if (contacts[i].depth >= 0f) + { + // If we're collidng against terrain + if (name1 == "Terrain" || name2 == "Terrain") + { + // If we're moving + if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && + (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) + { + // Use the movement terrain contact + AvatarMovementTerrainContact.geom = contacts[i]; + joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); + } + else + { + // Use the non moving terrain contact + TerrainContact.geom = contacts[i]; + joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); + } + } + else + { + // we're colliding with prim or avatar + + // check if we're moving + if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && + (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) + { + // Use the Movement prim contact + AvatarMovementprimContact.geom = contacts[i]; + joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); + } + else + { + // Use the non movement contact + contact.geom = contacts[i]; + joint = d.JointCreateContact(world, contactgroup, ref contact); + } + } + d.JointAttach(joint, b1, b2); + } + + if (count > 3) + { + // If there are more then 3 contact points, it's likely + // that we've got a pile of objects + // + // We don't want to send out hundreds of terse updates over and over again + // so lets throttle them and send them again after it's somewhat sorted out. + p2.ThrottleUpdates = true; + } + //System.Console.WriteLine(count.ToString()); + //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); + } + } + } + private float GetTerrainHeightAtXY(float x, float y) + { + return (float)_origheightmap[(int)y * Constants.RegionSize + (int)x]; + + + } + + /// + /// This is our collision testing routine in ODE + /// + /// + private void collision_optimized(float timeStep) + { + + foreach (OdeCharacter chr in _characters) + { + // Reset the collision values to false + // since we don't know if we're colliding yet + + chr.IsColliding = false; + chr.CollidingGround = false; + chr.CollidingObj = false; + + // test the avatar's geometry for collision with the space + // This will return near and the space that they are the closest to + // And we'll run this again against the avatar and the space segment + // This will return with a bunch of possible objects in the space segment + // and we'll run it again on all of them. + try + { + d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to space collide"); + } + //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y); + //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10) + //{ + //chr.Position.Z = terrainheight + 10.0f; + //forcedZ = true; + //} + } + + + // If the sim is running slow this frame, + // don't process collision for prim! + if (timeStep < (m_SkipFramesAtms/3)) + { + foreach (OdePrim chr in _activeprims) + { + // This if may not need to be there.. it might be skipped anyway. + if (d.BodyIsEnabled(chr.Body) && (!chr.m_disabled)) + { + try + { + d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to space collide"); + } + //calculateSpaceForGeom(chr.Position) + //foreach (OdePrim ch2 in _prims) + /// should be a separate space -- lots of avatars will be N**2 slow + //{ + //if (ch2.IsPhysical && d.BodyIsEnabled(ch2.Body)) + //{ + // Only test prim that are 0.03 meters away in one direction. + // This should be Optimized! + + //if ((Math.Abs(ch2.Position.X - chr.Position.X) < 0.03) || (Math.Abs(ch2.Position.Y - chr.Position.Y) < 0.03) || (Math.Abs(ch2.Position.X - chr.Position.X) < 0.03)) + //{ + //d.SpaceCollide2(chr.prim_geom, ch2.prim_geom, IntPtr.Zero, nearCallback); + //} + //} + //} + } + try + { + d.SpaceCollide2(LandGeom, chr.prim_geom, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to space collide"); + } + } + } + else + { + // Everything is going slow, so we're skipping object to object collisions + // At least collide test against the ground. + foreach (OdePrim chr in _activeprims) + { + // This if may not need to be there.. it might be skipped anyway. + if (d.BodyIsEnabled(chr.Body)) + { + // Collide test the prims with the terrain.. since if you don't do this, + // next frame, all of the physical prim in the scene will awaken and explode upwards + tmpSpace = calculateSpaceForGeom(chr.Position); + if (tmpSpace != (IntPtr) 0 && d.GeomIsSpace(tmpSpace)) + d.SpaceCollide2(calculateSpaceForGeom(chr.Position), chr.prim_geom, IntPtr.Zero, nearCallback); + d.SpaceCollide2(LandGeom, chr.prim_geom, IntPtr.Zero, nearCallback); + } + } + } + } + + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) + { + PhysicsVector pos = new PhysicsVector(); + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z; + OdeCharacter newAv = new OdeCharacter(avName, this, pos, ode, size); + _characters.Add(newAv); + return newAv; + } + + public override void RemoveAvatar(PhysicsActor actor) + { + lock (OdeLock) + { + ((OdeCharacter) actor).Destroy(); + _characters.Remove((OdeCharacter) actor); + } + } + + public override void RemovePrim(PhysicsActor prim) + { + if (prim is OdePrim) + { + lock (OdeLock) + { + OdePrim p = (OdePrim) prim; + + p.setPrimForRemoval(); + AddPhysicsActorTaint(prim); + //RemovePrimThreadLocked(p); + } + } + } + + /// + /// This is called from within simulate but outside the locked portion + /// We need to do our own locking here + /// Essentially, we need to remove the prim from our space segment, whatever segment it's in. + /// + /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory + /// that the space was using. + /// + /// + public void RemovePrimThreadLocked(OdePrim prim) + { + lock (ode) + { + if (prim.prim_geom != (IntPtr)0) + { + while (ode.lockquery()) + { + } + ode.dlock(world); + //System.Threading.Thread.Sleep(20); + prim.ResetTaints(); + + + if (prim.IsPhysical) + { + prim.disableBody(); + } + // we don't want to remove the main space + + // If the geometry is in the targetspace, remove it from the target space + //m_log.Warn(prim.m_targetSpace); + + + //if (prim.m_targetSpace != (IntPtr)0) + //{ + if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom)) + { + + if (d.GeomIsSpace(prim.m_targetSpace)) + { + waitForSpaceUnlock(prim.m_targetSpace); + d.SpaceRemove(prim.m_targetSpace, prim.prim_geom); + prim.m_targetSpace = (IntPtr) 0; + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" + + ((OdePrim)prim).m_targetSpace.ToString()); + } + + } + //} + //m_log.Warn(prim.prim_geom); + try + { + if (prim.prim_geom != (IntPtr)0) + { + d.GeomDestroy(prim.prim_geom); + prim.prim_geom = (IntPtr)0; + } + else + { + m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene"); + } + + } + catch (System.AccessViolationException) + { + m_log.Info("[PHYSICS]: Couldn't remove prim from physics scene, it was already be removed."); + } + _prims.Remove(prim); + + //If there are no more geometries in the sub-space, we don't need it in the main space anymore + //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0) + //{ + //if (!(prim.m_targetSpace.Equals(null))) + //{ + //if (d.GeomIsSpace(prim.m_targetSpace)) + //{ + //waitForSpaceUnlock(prim.m_targetSpace); + //d.SpaceRemove(space, prim.m_targetSpace); + // free up memory used by the space. + //d.SpaceDestroy(prim.m_targetSpace); + //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position); + //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]); + //} + //else + //{ + //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" + + //((OdePrim) prim).m_targetSpace.ToString()); + //} + //} + //} + } + + + + ode.dunlock(world); + + } + } + /// + /// Takes a space pointer and zeros out the array we're using to hold the spaces + /// + /// + public void resetSpaceArrayItemToZero(IntPtr space) + { + for (int x = 0; x < staticPrimspace.GetLength(0); x++) + { + for (int y = 0; y < staticPrimspace.GetLength(1); y++) + { + if (staticPrimspace[x, y] == space) + staticPrimspace[x, y] = IntPtr.Zero; + } + } + } + + public void resetSpaceArrayItemToZero(int arrayitemX, int arrayitemY) + { + staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero; + } + + /// + /// Called when a static prim moves. Allocates a space for the prim based on it's position + /// + /// the pointer to the geom that moved + /// the position that the geom moved to + /// a pointer to the space it was in before it was moved. + /// a pointer to the new space it's in + public IntPtr recalculateSpaceForGeom(IntPtr geom, PhysicsVector pos, IntPtr currentspace) + { + + // Called from setting the Position and Size of an ODEPrim so + // it's already in locked space. + + // we don't want to remove the main space + // we don't need to test physical here because this function should + // never be called if the prim is physical(active) + + // All physical prim end up in the root space + System.Threading.Thread.Sleep(20); + if (currentspace != space) + { + if (d.SpaceQuery(currentspace, geom) && currentspace != (IntPtr) 0) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(currentspace); + d.SpaceRemove(currentspace, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + currentspace.ToString() + + " Geom:" + geom.ToString()); + } + } + else + { + IntPtr sGeomIsIn = d.GeomGetSpace(geom); + if (!(sGeomIsIn.Equals(null))) + { + if (sGeomIsIn != (IntPtr) 0) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(sGeomIsIn); + d.SpaceRemove(sGeomIsIn, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + sGeomIsIn.ToString() + " Geom:" + geom.ToString()); + } + } + } + } + + + //If there are no more geometries in the sub-space, we don't need it in the main space anymore + if (d.SpaceGetNumGeoms(currentspace) == 0) + { + if (currentspace != (IntPtr) 0) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(currentspace); + waitForSpaceUnlock(space); + d.SpaceRemove(space, currentspace); + // free up memory used by the space. + + d.SpaceDestroy(currentspace); + resetSpaceArrayItemToZero(currentspace); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + currentspace.ToString() + " Geom:" + geom.ToString()); + } + } + } + } + else + { + // this is a physical object that got disabled. ;.; + if (currentspace != (IntPtr)0 && geom != (IntPtr)0) + { + if (d.SpaceQuery(currentspace, geom)) + { + + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(currentspace); + d.SpaceRemove(currentspace, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + currentspace.ToString() + " Geom:" + geom.ToString()); + } + } + else + { + IntPtr sGeomIsIn = d.GeomGetSpace(geom); + if (!(sGeomIsIn.Equals(null))) + { + if (sGeomIsIn != (IntPtr)0) + { + if (d.GeomIsSpace(sGeomIsIn)) + { + waitForSpaceUnlock(sGeomIsIn); + d.SpaceRemove(sGeomIsIn, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + sGeomIsIn.ToString() + " Geom:" + geom.ToString()); + } + } + } + } + } + } + + + // The routines in the Position and Size sections do the 'inserting' into the space, + // so all we have to do is make sure that the space that we're putting the prim into + // is in the 'main' space. + int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos); + IntPtr newspace = calculateSpaceForGeom(pos); + + if (newspace == IntPtr.Zero) + { + newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); + d.HashSpaceSetLevels(newspace, -4, 66); + } + + return newspace; + } + + /// + /// Creates a new space at X Y + /// + /// + /// + /// A pointer to the created space + public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY) + { + // creating a new space for prim and inserting it into main space. + staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero); + waitForSpaceUnlock(space); + d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]); + return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; + } + + /// + /// Calculates the space the prim should be in by it's position + /// + /// + /// a pointer to the space. This could be a new space or reused space. + public IntPtr calculateSpaceForGeom(PhysicsVector pos) + { + IntPtr locationbasedspace =IntPtr.Zero; + + int[] xyspace = calculateSpaceArrayItemFromPos(pos); + //m_log.Info("[Physics]: Attempting to use arrayItem: " + xyspace[0].ToString() + "," + xyspace[1].ToString()); + locationbasedspace = staticPrimspace[xyspace[0], xyspace[1]]; + + //locationbasedspace = space; + return locationbasedspace; + } + + /// + /// Holds the space allocation logic + /// + /// + /// an array item based on the position + public int[] calculateSpaceArrayItemFromPos(PhysicsVector pos) + { + int[] returnint = new int[2]; + + returnint[0] = (int) (pos.X/metersInSpace); + + if (returnint[0] > ((int) (259f/metersInSpace))) + returnint[0] = ((int) (259f/metersInSpace)); + if (returnint[0] < 0) + returnint[0] = 0; + + returnint[1] = (int) (pos.Y/metersInSpace); + if (returnint[1] > ((int) (259f/metersInSpace))) + returnint[1] = ((int) (259f/metersInSpace)); + if (returnint[1] < 0) + returnint[1] = 0; + + + return returnint; + } + + private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation, + IMesh mesh, PrimitiveBaseShape pbs, bool isphysical) + { + PhysicsVector pos = new PhysicsVector(); + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z; + PhysicsVector siz = new PhysicsVector(); + siz.X = size.X; + siz.Y = size.Y; + siz.Z = size.Z; + Quaternion rot = new Quaternion(); + rot.w = rotation.w; + rot.x = rotation.x; + rot.y = rotation.y; + rot.z = rotation.z; + + + + OdePrim newPrim; + lock (OdeLock) + { + newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode); + + _prims.Add(newPrim); + } + + + return newPrim; + } + + public void addActivePrim(OdePrim activatePrim) + { + // adds active prim.. (ones that should be iterated over in collisions_optimized + + _activeprims.Add(activatePrim); + } + + public void remActivePrim(OdePrim deactivatePrim) + { + _activeprims.Remove(deactivatePrim); + } + + public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount) + { +/* String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(trimesh, out name1)) + { + name1 = "null"; + } + if (!geom_name_map.TryGetValue(refObject, out name2)) + { + name2 = "null"; + } + + m_log.Info("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2); +*/ + return 1; + } + + public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex) + { + String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(trimesh, out name1)) + { + name1 = "null"; + } + + if (!geom_name_map.TryGetValue(refObject, out name2)) + { + name2 = "null"; + } + +// m_log.Info("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex); + + d.Vector3 v0 = new d.Vector3(); + d.Vector3 v1 = new d.Vector3(); + d.Vector3 v2 = new d.Vector3(); + + d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2); +// m_log.Debug("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z); + + return 1; + } + + /// + /// Routine to figure out if we need to mesh this prim with our mesher + /// + /// + /// + public bool needsMeshing(PrimitiveBaseShape pbs) + { + if (pbs.ProfileHollow != 0) + return true; + + if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) + return true; + + if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100)) + return true; + + if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0)) + return true; + + if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) + return true; + + return false; + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation) //To be removed + { + return AddPrimShape(primName, pbs, position, size, rotation, false); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical) + { + PhysicsActor result; + IMesh mesh = null; + + switch (pbs.ProfileShape) + { + case ProfileShape.Square: + /// support simple box & hollow box now; later, more shapes + if (needsMeshing(pbs)) + { + mesh = mesher.CreateMesh(primName, pbs, size); + } + + break; + } + + result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); + + + return result; + } + + /// + /// Called after our prim properties are set Scale, position etc. + /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex + /// This assures us that we have no race conditions + /// + /// + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + if (prim is OdePrim) + { + OdePrim taintedprim = ((OdePrim) prim); + if (!(_taintedPrim.Contains(taintedprim))) + _taintedPrim.Add(taintedprim); + } + } + + /// + /// This is our main simulate loop + /// It's thread locked by a Mutex in the scene. + /// It holds Collisions, it instructs ODE to step through the physical reactions + /// It moves the objects around in memory + /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) + /// + /// + /// + public override float Simulate(float timeStep) + { + float fps = 0; + + step_time += timeStep; + + + // If We're loaded down by something else, + // or debugging with the Visual Studio project on pause + // skip a few frames to catch up gracefully. + // without shooting the physicsactors all over the place + + + if (step_time >= m_SkipFramesAtms) + { + // Instead of trying to catch up, it'll do 5 physics frames only + step_time = ODE_STEPSIZE; + m_physicsiterations = 5; + } + else + { + m_physicsiterations = 10; + } + lock (OdeLock) + { + // Process 10 frames if the sim is running normal.. + // process 5 frames if the sim is running slow + try + { + d.WorldSetQuickStepNumIterations(world, m_physicsiterations); + } + catch (StackOverflowException) + { + m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim."); + ode.drelease(world); + base.TriggerPhysicsBasedRestart(); + } + + int i = 0; + + // Figure out the Frames Per Second we're going at. + //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size + fps = (step_time/ODE_STEPSIZE) * 1000; + + while (step_time > 0.0f) + { + lock (ode) + { + if (!ode.lockquery()) + { + ode.dlock(world); + try + { + foreach (OdeCharacter actor in _characters) + { + actor.Move(timeStep); + + } + + + collision_optimized(timeStep); + + d.WorldQuickStep(world, ODE_STEPSIZE); + + d.JointGroupEmpty(contactgroup); + ode.dunlock(world); + } + catch (Exception e) + { + m_log.Error("[PHYSICS]: " + e.Message.ToString() + e.TargetSite.ToString()); + ode.dunlock(world); + } + + + + + step_time -= ODE_STEPSIZE; + i++; + } + else + { + fps = 0; + } + } + } + + foreach (OdeCharacter actor in _characters) + { + actor.UpdatePositionAndVelocity(); + } + + if (!ode.lockquery()) + { + bool processedtaints = false; + foreach (OdePrim prim in _taintedPrim) + { + if (prim.m_taintremove) + { + RemovePrimThreadLocked(prim); + } + + prim.ProcessTaints(timeStep); + + processedtaints = true; + prim.m_collisionscore = 0; + } + if (processedtaints) + _taintedPrim = new List(); + } + foreach (OdePrim prim in _activeprims) + { + prim.m_collisionscore = 0; + } + + + + if (timeStep < 0.2f) + { + foreach (OdePrim actor in _activeprims) + { + if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag)) + { + actor.UpdatePositionAndVelocity(); + } + } + } + } + return fps; + } + + public override void GetResults() + { + } + + public override bool IsThreaded + { + // for now we won't be multithreaded + get { return (false); } + } + public float[] ResizeTerrain512NearestNeighbour(float[] heightMap) + { + float[] returnarr = new float[262144]; + float[,] resultarr = new float[m_regionWidth, m_regionHeight]; + + // Filling out the array into it's multi-dimentional components + for (int y = 0; y < m_regionHeight; y++) + { + for (int x = 0; x < m_regionWidth; x++) + { + resultarr[y, x] = heightMap[y * m_regionWidth + x]; + } + } + + // Resize using Nearest Neighbour + + // This particular way is quick but it only works on a multiple of the original + + // The idea behind this method can be described with the following diagrams + // second pass and third pass happen in the same loop really.. just separated + // them to show what this does. + + // First Pass + // ResultArr: + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + + // Second Pass + // ResultArr2: + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + + // Third pass fills in the blanks + // ResultArr2: + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + + // X,Y = . + // X+1,y = ^ + // X,Y+1 = * + // X+1,Y+1 = # + + // Filling in like this; + // .* + // ^# + // 1st . + // 2nd * + // 3rd ^ + // 4th # + // on single loop. + + float[,] resultarr2 = new float[512, 512]; + for (int y = 0; y < m_regionHeight; y++) + { + for (int x = 0; x < m_regionWidth; x++) + { + resultarr2[y * 2, x * 2] = resultarr[y, x]; + + if (y < m_regionHeight) + { + resultarr2[(y * 2) + 1, x * 2] = resultarr[y, x]; + } + if (x < m_regionWidth) + { + resultarr2[y * 2, (x * 2) + 1] = resultarr[y, x]; + } + if (x < m_regionWidth && y < m_regionHeight) + { + resultarr2[(y * 2) + 1, (x * 2) + 1] = resultarr[y, x]; + } + } + } + + //Flatten out the array + int i = 0; + for (int y = 0; y < 512; y++) + { + for (int x = 0; x < 512; x++) + { + if (resultarr2[y, x] <= 0) + returnarr[i] = 0.0000001f; + else + returnarr[i] = resultarr2[y, x]; + + i++; + } + } + + return returnarr; + } + public float[] ResizeTerrain512Interpolation(float[] heightMap) + { + float[] returnarr = new float[262144]; + float[,] resultarr = new float[m_regionWidth,m_regionHeight]; + + // Filling out the array into it's multi-dimentional components + for (int y = 0; y < m_regionHeight; y++) + { + for (int x = 0; x < m_regionWidth; x++) + { + resultarr[y, x] = heightMap[y*m_regionWidth + x]; + } + } + + // Resize using interpolation + + // This particular way is quick but it only works on a multiple of the original + + // The idea behind this method can be described with the following diagrams + // second pass and third pass happen in the same loop really.. just separated + // them to show what this does. + + // First Pass + // ResultArr: + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + + // Second Pass + // ResultArr2: + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + + // Third pass fills in the blanks + // ResultArr2: + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + + // X,Y = . + // X+1,y = ^ + // X,Y+1 = * + // X+1,Y+1 = # + + // Filling in like this; + // .* + // ^# + // 1st . + // 2nd * + // 3rd ^ + // 4th # + // on single loop. + + float[,] resultarr2 = new float[512,512]; + for (int y = 0; y < m_regionHeight; y++) + { + for (int x = 0; x < m_regionWidth; x++) + { + resultarr2[y*2, x*2] = resultarr[y, x]; + + if (y < m_regionHeight) + { + if (y + 1 < m_regionHeight) + { + if (x + 1 < m_regionWidth) + { + resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] + + resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); + } + else + { + resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2); + } + } + else + { + resultarr2[(y*2) + 1, x*2] = resultarr[y, x]; + } + } + if (x < m_regionWidth) + { + if (x + 1 < m_regionWidth) + { + if (y + 1 < m_regionHeight) + { + resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + + resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); + } + else + { + resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2); + } + } + else + { + resultarr2[y*2, (x*2) + 1] = resultarr[y, x]; + } + } + if (x < m_regionWidth && y < m_regionHeight) + { + if ((x + 1 < m_regionWidth) && (y + 1 < m_regionHeight)) + { + resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + + resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); + } + else + { + resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x]; + } + } + } + } + //Flatten out the array + int i = 0; + for (int y = 0; y < 512; y++) + { + for (int x = 0; x < 512; x++) + { + if (resultarr2[y, x] <= 0) + returnarr[i] = 0.0000001f; + else + returnarr[i] = resultarr2[y, x]; + + i++; + } + } + + return returnarr; + } + + public override void SetTerrain(float[] heightMap) + { + // this._heightmap[i] = (double)heightMap[i]; + // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) + // also, creating a buffer zone of one extra sample all around + _origheightmap = heightMap; + const uint heightmapWidth = m_regionWidth + 2; + const uint heightmapHeight = m_regionHeight + 2; + const uint heightmapWidthSamples = 2*m_regionWidth + 2; + const uint heightmapHeightSamples = 2*m_regionHeight + 2; + const float scale = 1.0f; + const float offset = 0.0f; + const float thickness = 0.2f; + const int wrap = 0; + + //Double resolution + heightMap = ResizeTerrain512Interpolation(heightMap); + for (int x = 0; x < heightmapWidthSamples; x++) + { + for (int y = 0; y < heightmapHeightSamples; y++) + { + int xx = Util.Clip(x - 1, 0, 511); + int yy = Util.Clip(y - 1, 0, 511); + + float val = heightMap[yy*512 + xx]; + _heightmap[x*heightmapHeightSamples + y] = val; + } + } + + lock (OdeLock) + { + if (!(LandGeom == (IntPtr) 0)) + { + d.SpaceRemove(space, LandGeom); + } + IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); + d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, heightmapWidth, heightmapHeight, + (int) heightmapWidthSamples, (int) heightmapHeightSamples, scale, + offset, thickness, wrap); + d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight); + LandGeom = d.CreateHeightfield(space, HeightmapData, 1); + geom_name_map[LandGeom] = "Terrain"; + + d.Matrix3 R = new d.Matrix3(); + + Quaternion q1 = Quaternion.FromAngleAxis(1.5707f, new Vector3(1, 0, 0)); + Quaternion q2 = Quaternion.FromAngleAxis(1.5707f, new Vector3(0, 1, 0)); + //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1)); + + q1 = q1*q2; + //q1 = q1 * q3; + Vector3 v3 = new Vector3(); + float angle = 0; + q1.ToAngleAxis(ref angle, ref v3); + + d.RFromAxisAndAngle(out R, v3.x, v3.y, v3.z, angle); + d.GeomSetRotation(LandGeom, ref R); + d.GeomSetPosition(LandGeom, 128, 128, 0); + } + } + + public override void DeleteTerrain() + { + } + public override void Dispose() + { + lock (OdeLock) + { + + foreach (OdePrim prm in _prims) + { + RemovePrim(prm); + } + + foreach (OdeCharacter act in _characters) + { + RemoveAvatar(act); + } + d.WorldDestroy(world); + //d.CloseODE(); + } + } + } +} diff --git a/trunk/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs b/trunk/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs new file mode 100644 index 0000000000..da9f5873fd --- /dev/null +++ b/trunk/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs @@ -0,0 +1,58 @@ +/* +* 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; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly : AssemblyTitle("POSPlugin")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("POSPlugin")] +[assembly : AssemblyCopyright("")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. + +[assembly : ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly : AssemblyVersion("1.0.*")] diff --git a/trunk/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs b/trunk/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs new file mode 100644 index 0000000000..6d1bec707a --- /dev/null +++ b/trunk/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs @@ -0,0 +1,663 @@ +/* +* 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; +using System.Collections.Generic; +using Axiom.Math; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.POSPlugin +{ + /// + /// for now will be a very POS physics engine + /// + public class POSPlugin : IPhysicsPlugin + { + public POSPlugin() + { + } + + public bool Init() + { + return true; + } + + public PhysicsScene GetScene() + { + return new POSScene(); + } + + public string GetName() + { + return ("POS"); + } + + public void Dispose() + { + } + } + + public class POSScene : PhysicsScene + { + private List _characters = new List(); + private List _prims = new List(); + private float[] _heightMap; + private const float gravity = -9.8f; + + public POSScene() + { + } + + public override void Initialise(IMesher meshmerizer) + { + // Does nothing right now + } + public override void Dispose() + { + + } + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) + { + POSCharacter act = new POSCharacter(); + act.Position = position; + _characters.Add(act); + return act; + } + + public override void RemovePrim(PhysicsActor prim) + { + POSPrim p = (POSPrim) prim; + if (_prims.Contains(p)) + { + _prims.Remove(p); + } + } + + public override void RemoveAvatar(PhysicsActor character) + { + POSCharacter act = (POSCharacter) character; + if (_characters.Contains(act)) + { + _characters.Remove(act); + } + } + +/* + public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation) + { + return null; + } +*/ + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation) + { + return AddPrimShape(primName, pbs, position, size, rotation, false); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical) + { + POSPrim prim = new POSPrim(); + prim.Position = position; + prim.Orientation = rotation; + prim.Size = size; + _prims.Add(prim); + return prim; + } + + private bool check_collision(POSCharacter c, POSPrim p) + { + /* + Console.WriteLine("checking whether " + c + " collides with " + p + + " absX: " + Math.Abs(p.Position.X - c.Position.X) + + " sizeX: " + p.Size.X * 0.5 + 0.5); + */ + + Vector3 rotatedPos = p.Orientation.Inverse()* + new Vector3(c.Position.X - p.Position.X, c.Position.Y - p.Position.Y, + c.Position.Z - p.Position.Z); + Vector3 avatarSize = p.Orientation.Inverse()*new Vector3(c.Size.X, c.Size.Y, c.Size.Z); + + if (Math.Abs(rotatedPos.x) >= (p.Size.X*0.5 + Math.Abs(avatarSize.x))) + { + return false; + } + if (Math.Abs(rotatedPos.y) >= (p.Size.Y*0.5 + Math.Abs(avatarSize.y))) + { + return false; + } + if (Math.Abs(rotatedPos.z) >= (p.Size.Z*0.5 + Math.Abs(avatarSize.z))) + { + return false; + } + return true; + } + + private bool check_all_prims(POSCharacter c) + { + for (int i = 0; i < _prims.Count; ++i) + { + if (check_collision(c, _prims[i])) + { + + return true; + } + + } + + return false; + } + + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + } + + public override float Simulate(float timeStep) + { + float fps = 0; + for (int i = 0; i < _characters.Count; ++i) + { + fps++; + POSCharacter character = _characters[i]; + + float oldposX = character.Position.X; + float oldposY = character.Position.Y; + float oldposZ = character.Position.Z; + + if (!character.Flying) + { + character._target_velocity.Z += gravity*timeStep; + } + + bool forcedZ = false; + character.Position.X += character._target_velocity.X*timeStep; + character.Position.Y += character._target_velocity.Y*timeStep; + + if (character.Position.Y < 0) + { + character.Position.Y = 0.1F; + } + else if (character.Position.Y >= Constants.RegionSize) + { + character.Position.Y = Constants.RegionSize - 0.1f; + } + + if (character.Position.X < 0) + { + character.Position.X = 0.1F; + } + else if (character.Position.X >= Constants.RegionSize) + { + character.Position.X = Constants.RegionSize - 0.1f; + } + + float terrainheight = _heightMap[(int)character.Position.Y * Constants.RegionSize + (int)character.Position.X]; + if (character.Position.Z + (character._target_velocity.Z*timeStep) < terrainheight + 2) + { + character.Position.Z = terrainheight + 1.0f; + forcedZ = true; + } + else + { + character.Position.Z += character._target_velocity.Z*timeStep; + } + + /// this is it -- the magic you've all been waiting for! Ladies and gentlemen -- + /// Completely Bogus Collision Detection!!! + /// better known as the CBCD algorithm + + if (check_all_prims(character)) + { + character.Position.Z = oldposZ; // first try Z axis + if (check_all_prims(character)) + { + character.Position.Z = oldposZ + 0.4f; // try harder + if (check_all_prims(character)) + { + character.Position.X = oldposX; + character.Position.Y = oldposY; + character.Position.Z = oldposZ; + character.Position.X = character.Position.X + (character._target_velocity.X*timeStep); + if (check_all_prims(character)) + { + character.Position.X = oldposX; + } + character.Position.Y = character.Position.Y + (character._target_velocity.Y*timeStep); + if (check_all_prims(character)) + { + character.Position.Y = oldposY; + } + } + else + { + forcedZ = true; + } + } + else + { + forcedZ = true; + } + } + + if (character.Position.Y < 0) + { + character.Position.Y = 0.1F; + } + else if (character.Position.Y >= Constants.RegionSize) + { + character.Position.Y = Constants.RegionSize - 0.1f; + } + + if (character.Position.X < 0) + { + character.Position.X = 0.1F; + } + else if (character.Position.X >= Constants.RegionSize) + { + character.Position.X = Constants.RegionSize - 0.1f; + } + + character._velocity.X = (character.Position.X - oldposX)/timeStep; + character._velocity.Y = (character.Position.Y - oldposY)/timeStep; + + if (forcedZ) + { + character._velocity.Z = 0; + character._target_velocity.Z = 0; + ((PhysicsActor)character).IsColliding = true; + character.RequestPhysicsterseUpdate(); + } + else + { + ((PhysicsActor)character).IsColliding = false; + character._velocity.Z = (character.Position.Z - oldposZ)/timeStep; + } + } + return fps; + } + + public override void GetResults() + { + } + + public override bool IsThreaded + { + get { return (false); // for now we won't be multithreaded + } + } + + public override void SetTerrain(float[] heightMap) + { + _heightMap = heightMap; + } + + public override void DeleteTerrain() + { + } + } + + public class POSCharacter : PhysicsActor + { + private PhysicsVector _position; + public PhysicsVector _velocity; + public PhysicsVector _target_velocity = PhysicsVector.Zero; + private PhysicsVector _acceleration; + private PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; + private bool flying; + private bool iscolliding; + + public POSCharacter() + { + _velocity = new PhysicsVector(); + _position = new PhysicsVector(); + _acceleration = new PhysicsVector(); + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Agent; } + set { return; } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool Flying + { + get { return flying; } + set { flying = value; } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool Stopped + { + get { return false; } + } + + public override PhysicsVector Position + { + get { return _position; } + set { _position = value; } + } + + public override PhysicsVector Size + { + get { return new PhysicsVector(0.5f, 0.5f, 1.0f); } + set { } + } + + public override float Mass + { + get { return 0f; } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override PhysicsVector Velocity + { + get { return _velocity; } + set { _target_velocity = value; } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override Quaternion Orientation + { + get { return Quaternion.Identity; } + set { } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public override bool Kinematic + { + get { return true; } + set { } + } + + public void SetAcceleration(PhysicsVector accel) + { + _acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + public override void CrossingFailure() + { + + } + } + + public class POSPrim : PhysicsActor + { + private PhysicsVector _position; + private PhysicsVector _velocity; + private PhysicsVector _acceleration; + private PhysicsVector _size; + private PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; + private Quaternion _orientation; + private bool iscolliding; + + public POSPrim() + { + _velocity = new PhysicsVector(); + _position = new PhysicsVector(); + _acceleration = new PhysicsVector(); + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Prim; } + set { return; } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool Stopped + { + get { return false; } + } + + public override PhysicsVector Position + { + get { return _position; } + set { _position = value; } + } + + public override PhysicsVector Size + { + get { return _size; } + set { _size = value; } + } + + public override float Mass + { + get { return 0f; } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override PhysicsVector Velocity + { + get { return _velocity; } + set { _velocity = value; } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override Quaternion Orientation + { + get { return _orientation; } + set { _orientation = value; } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public override bool Kinematic + { + get { return true; } + set { } + } + + public void SetAcceleration(PhysicsVector accel) + { + _acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + + public override bool Flying + { + get { return false; } + set { } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + public override void CrossingFailure() + { + + } + + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Physics/PhysXPlugin/AssemblyInfo.cs b/trunk/OpenSim/Region/Physics/PhysXPlugin/AssemblyInfo.cs new file mode 100644 index 0000000000..8e6d2a6945 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/PhysXPlugin/AssemblyInfo.cs @@ -0,0 +1,58 @@ +/* +* 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; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly : AssemblyTitle("RealPhysXplugin")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("RealPhysXplugin")] +[assembly : AssemblyCopyright("")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. + +[assembly : ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly : AssemblyVersion("1.0.*")] diff --git a/trunk/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs b/trunk/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs new file mode 100644 index 0000000000..970f6fb642 --- /dev/null +++ b/trunk/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs @@ -0,0 +1,599 @@ +/*/* +* 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; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; +using PhysXWrapper; +using Quaternion=Axiom.Math.Quaternion; + +namespace OpenSim.Region.Physics.PhysXPlugin +{ + /// + /// Will be the PhysX plugin but for now will be a very basic physics engine + /// + public class PhysXPlugin : IPhysicsPlugin + { + private PhysXScene _mScene; + + public PhysXPlugin() + { + } + + public bool Init() + { + return true; + } + + public PhysicsScene GetScene() + { + if (_mScene == null) + { + _mScene = new PhysXScene(); + } + return (_mScene); + } + + public string GetName() + { + return ("RealPhysX"); + } + + public void Dispose() + { + } + } + + public class PhysXScene : PhysicsScene + { + private List _characters = new List(); + private List _prims = new List(); + private float[] _heightMap = null; + private NxPhysicsSDK mySdk; + private NxScene scene; + + public PhysXScene() + { + mySdk = NxPhysicsSDK.CreateSDK(); + Console.WriteLine("Sdk created - now creating scene"); + scene = mySdk.CreateScene(); + } + + public override void Initialise(IMesher meshmerizer) + { + // Does nothing right now + } + public override void Dispose() + { + + } + + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) + { + Vec3 pos = new Vec3(); + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z; + PhysXCharacter act = new PhysXCharacter(scene.AddCharacter(pos)); + act.Position = position; + _characters.Add(act); + return act; + } + + public override void RemovePrim(PhysicsActor prim) + { + } + + public override void RemoveAvatar(PhysicsActor actor) + { + } + + private PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation) + { + Vec3 pos = new Vec3(); + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z; + Vec3 siz = new Vec3(); + siz.X = size.X; + siz.Y = size.Y; + siz.Z = size.Z; + PhysXPrim act = new PhysXPrim(scene.AddNewBox(pos, siz)); + _prims.Add(act); + return act; + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation) //To be removed + { + return AddPrimShape(primName, pbs, position, size, rotation, false); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical) + { + return AddPrim(position, size, rotation); + } + + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + } + + public override float Simulate(float timeStep) + { + float fps = 0f; + try + { + foreach (PhysXCharacter actor in _characters) + { + actor.Move(timeStep); + } + scene.Simulate(timeStep); + scene.FetchResults(); + scene.UpdateControllers(); + + foreach (PhysXCharacter actor in _characters) + { + actor.UpdatePosition(); + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + return fps; + } + + public override void GetResults() + { + } + + public override bool IsThreaded + { + get { return (false); // for now we won't be multithreaded + } + } + + public override void SetTerrain(float[] heightMap) + { + if (_heightMap != null) + { + Console.WriteLine("PhysX - deleting old terrain"); + scene.DeleteTerrain(); + } + _heightMap = heightMap; + scene.AddTerrain(heightMap); + } + + public override void DeleteTerrain() + { + scene.DeleteTerrain(); + } + } + + public class PhysXCharacter : PhysicsActor + { + private PhysicsVector _position; + private PhysicsVector _velocity; + private PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; + private PhysicsVector _acceleration; + private NxCharacter _character; + private bool flying; + private bool iscolliding = false; + private float gravityAccel; + + public PhysXCharacter(NxCharacter character) + { + _velocity = new PhysicsVector(); + _position = new PhysicsVector(); + _acceleration = new PhysicsVector(); + _character = character; + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Agent; } + set { return; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool Flying + { + get { return flying; } + set { flying = value; } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + public override bool Stopped + { + get { return false; } + } + + public override PhysicsVector Position + { + get { return _position; } + set + { + _position = value; + Vec3 ps = new Vec3(); + ps.X = value.X; + ps.Y = value.Y; + ps.Z = value.Z; + _character.Position = ps; + } + } + + public override PhysicsVector Size + { + get { return PhysicsVector.Zero; } + set { } + } + + public override float Mass + { + get { return 0f; } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector Velocity + { + get { return _velocity; } + set { _velocity = value; } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override bool Kinematic + { + get { return false; } + set { } + } + + public override Quaternion Orientation + { + get { return Quaternion.Identity; } + set { } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public void SetAcceleration(PhysicsVector accel) + { + _acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + + public void Move(float timeStep) + { + Vec3 vec = new Vec3(); + vec.X = _velocity.X*timeStep; + vec.Y = _velocity.Y*timeStep; + if (flying) + { + vec.Z = (_velocity.Z)*timeStep; + } + else + { + gravityAccel += -9.8f; + vec.Z = (gravityAccel + _velocity.Z)*timeStep; + } + int res = _character.Move(vec); + if (res == 1) + { + gravityAccel = 0; + } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public void UpdatePosition() + { + Vec3 vec = _character.Position; + _position.X = vec.X; + _position.Y = vec.Y; + _position.Z = vec.Z; + } + public override void CrossingFailure() + { + + } + } + + + public class PhysXPrim : PhysicsActor + { + private PhysicsVector _velocity; + private PhysicsVector _acceleration; + private PhysicsVector m_rotationalVelocity; + private NxActor _prim; + + public PhysXPrim(NxActor prim) + { + _velocity = new PhysicsVector(); + _acceleration = new PhysicsVector(); + _prim = prim; + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Prim; } + set { return; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + public override bool Flying + { + get { return false; //no flying prims for you + } + set { } + } + + public override bool IsColliding + { + get { return false; } + set { } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool Stopped + { + get { return false; } + } + + public override PhysicsVector Position + { + get + { + PhysicsVector pos = new PhysicsVector(); + Vec3 vec = _prim.Position; + pos.X = vec.X; + pos.Y = vec.Y; + pos.Z = vec.Z; + return pos; + } + set + { + PhysicsVector vec = value; + Vec3 pos = new Vec3(); + pos.X = vec.X; + pos.Y = vec.Y; + pos.Z = vec.Z; + _prim.Position = pos; + } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override PhysicsVector Velocity + { + get { return _velocity; } + set { _velocity = value; } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override bool Kinematic + { + get { return _prim.Kinematic; } + set { _prim.Kinematic = value; } + } + + public override Quaternion Orientation + { + get + { + Quaternion res = new Quaternion(); + PhysXWrapper.Quaternion quat = _prim.GetOrientation(); + res.w = quat.W; + res.x = quat.X; + res.y = quat.Y; + res.z = quat.Z; + return res; + } + set { } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public void SetAcceleration(PhysicsVector accel) + { + _acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + + public override PhysicsVector Size + { + get { return PhysicsVector.Zero; } + set { } + } + + public override float Mass + { + get { return 0f; } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + public override void CrossingFailure() + { + + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/Executor.cs b/trunk/OpenSim/Region/ScriptEngine/Common/Executor.cs new file mode 100644 index 0000000000..e35882b659 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/Executor.cs @@ -0,0 +1,92 @@ +/* +* 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; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.Remoting.Lifetime; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public class Executor : ExecutorBase + { + // Cache functions by keeping a reference to them in a dictionary + private Dictionary Events = new Dictionary(); + + public Executor(IScript script) : base(script) + { + } + + protected override void DoExecuteEvent(string FunctionName, object[] args) + { + // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. + // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! + + string EventName = m_Script.State + "_event_" + FunctionName; + +///#if DEBUG +/// Console.WriteLine("ScriptEngine: Script event function name: " + EventName); +///#endif + + if (Events.ContainsKey(EventName) == false) + { + // Not found, create + Type type = m_Script.GetType(); + try + { + MethodInfo mi = type.GetMethod(EventName); + Events.Add(EventName, mi); + } + catch + { + // Event name not found, cache it as not found + Events.Add(EventName, null); + } + } + + // Get event + MethodInfo ev = null; + Events.TryGetValue(EventName, out ev); + + if (ev == null) // No event by that name! + { + //Console.WriteLine("ScriptEngine Can not find any event named: \String.Empty + EventName + "\String.Empty); + return; + } + +//cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined +///#if DEBUG +/// Console.WriteLine("ScriptEngine: Executing function name: " + EventName); +///#endif + // Found + ev.Invoke(m_Script, args); + + } + + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/ExecutorBase.cs b/trunk/OpenSim/Region/ScriptEngine/Common/ExecutorBase.cs new file mode 100644 index 0000000000..fdca9452d5 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/ExecutorBase.cs @@ -0,0 +1,108 @@ +/* +* 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; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public abstract class ExecutorBase : MarshalByRefObject + { + /// + /// Contains the script to execute functions in. + /// + protected IScript m_Script; + /// + /// If set to False events will not be executed. + /// + protected bool m_Running = true; + + /// + /// Create a new instance of ExecutorBase + /// + /// + public ExecutorBase(IScript Script) + { + m_Script = Script; + } + + /// + /// Make sure our object does not timeout when in AppDomain. (Called by ILease base class) + /// + /// + public override Object InitializeLifetimeService() + { + //Console.WriteLine("Executor: InitializeLifetimeService()"); + // return null; + ILease lease = (ILease)base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); + // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); + // lease.RenewOnCallTime = TimeSpan.FromSeconds(2); + } + return lease; + } + + /// + /// Get current AppDomain + /// + /// Current AppDomain + public AppDomain GetAppDomain() + { + return AppDomain.CurrentDomain; + } + + /// + /// Execute a specific function/event in script. + /// + /// Name of function to execute + /// Arguments to pass to function + public void ExecuteEvent(string FunctionName, object[] args) + { + if (m_Running == false) + { + // Script is inactive, do not execute! + return; + } + DoExecuteEvent(FunctionName, args); + } + protected abstract void DoExecuteEvent(string FunctionName, object[] args); + + /// + /// Stop script from running. Event execution will be ignored. + /// + public void StopScript() + { + m_Running = false; + } + + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/IScript.cs b/trunk/OpenSim/Region/ScriptEngine/Common/IScript.cs new file mode 100644 index 0000000000..96c4e3c542 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/IScript.cs @@ -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. +* +*/ + +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public interface IScript + { + string State { get; set; } + ExecutorBase Exec { get; } + string Source { get; set; } + void Start(LSL_BuiltIn_Commands_Interface BuiltIn_Commands); + EventQueueManager.Queue_llDetectParams_Struct llDetectParams { get; set; } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs b/trunk/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs new file mode 100644 index 0000000000..771349080f --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs @@ -0,0 +1,2211 @@ +/* +* 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; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using System.Threading; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; +using integer = System.Int32; +using key = System.String; +using vector = OpenSim.Region.ScriptEngine.Common.LSL_Types.Vector3; +using rotation = OpenSim.Region.ScriptEngine.Common.LSL_Types.Quaternion; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public class LSL_BaseClass : MarshalByRefObject, LSL_BuiltIn_Commands_Interface, IScript + { + // + // Included as base for any LSL-script that is compiled. + // Any function added here will be accessible to the LSL script. But it must also be added to "LSL_BuiltIn_Commands_Interface" in "OpenSim.Region.ScriptEngine.Common" class. + // + // Security note: This script will be running inside an restricted AppDomain. Currently AppDomain is not very restricted. + // + + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Object never expires + public override Object InitializeLifetimeService() + { + //Console.WriteLine("LSL_BaseClass: InitializeLifetimeService()"); + // return null; + ILease lease = (ILease)base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); + //lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); + //lease.RenewOnCallTime = TimeSpan.FromSeconds(2); + } + return lease; + } + + public EventQueueManager.Queue_llDetectParams_Struct _llDetectParams; + EventQueueManager.Queue_llDetectParams_Struct IScript.llDetectParams + { + get { return _llDetectParams; } + set { _llDetectParams = value; } + } + + private Executor m_Exec; + + ExecutorBase IScript.Exec + { + get + { + if (m_Exec == null) + m_Exec = new Executor(this); + return m_Exec; + } + } + + + public LSL_BuiltIn_Commands_Interface m_LSL_Functions; + private string _Source = String.Empty; + public string Source + { + get + { + return _Source; + } + set { _Source = value; } + } + + + public LSL_BaseClass() + { + } + + public string State + { + get { return m_LSL_Functions.State; } + set { m_LSL_Functions.State = value; } + } + + + + public void Start(LSL_BuiltIn_Commands_Interface LSL_Functions) + { + m_LSL_Functions = LSL_Functions; + + //m_log.Info(ScriptEngineName, "LSL_BaseClass.Start() called."); + + // Get this AppDomain's settings and display some of them. + AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation; + Console.WriteLine("AppName={0}, AppBase={1}, ConfigFile={2}", + ads.ApplicationName, + ads.ApplicationBase, + ads.ConfigurationFile + ); + + // Display the name of the calling AppDomain and the name + // of the second domain. + // NOTE: The application's thread has transitioned between + // AppDomains. + Console.WriteLine("Calling to '{0}'.", + Thread.GetDomain().FriendlyName + ); + + return; + } + + + + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + // They are only forwarders to LSL_BuiltIn_Commands.cs + // + public double llSin(double f) + { + return m_LSL_Functions.llSin(f); + } + + public double llCos(double f) + { + return m_LSL_Functions.llCos(f); + } + + public double llTan(double f) + { + return m_LSL_Functions.llTan(f); + } + + public double llAtan2(double x, double y) + { + return m_LSL_Functions.llAtan2(x, y); + } + + public double llSqrt(double f) + { + return m_LSL_Functions.llSqrt(f); + } + + public double llPow(double fbase, double fexponent) + { + return m_LSL_Functions.llPow(fbase, fexponent); + } + + public int llAbs(int i) + { + return m_LSL_Functions.llAbs(i); + } + + public double llFabs(double f) + { + return m_LSL_Functions.llFabs(f); + } + + public double llFrand(double mag) + { + return m_LSL_Functions.llFrand(mag); + } + + public int llFloor(double f) + { + return m_LSL_Functions.llFloor(f); + } + + public int llCeil(double f) + { + return m_LSL_Functions.llCeil(f); + } + + public int llRound(double f) + { + return m_LSL_Functions.llRound(f); + } + + public double llVecMag(vector v) + { + return m_LSL_Functions.llVecMag(v); + } + + public vector llVecNorm(vector v) + { + return m_LSL_Functions.llVecNorm(v); + } + + public double llVecDist(vector a, vector b) + { + return m_LSL_Functions.llVecDist(a, b); + } + + public vector llRot2Euler(rotation r) + { + return m_LSL_Functions.llRot2Euler(r); + } + + public rotation llEuler2Rot(vector v) + { + return m_LSL_Functions.llEuler2Rot(v); + } + + public rotation llAxes2Rot(vector fwd, vector left, vector up) + { + return m_LSL_Functions.llAxes2Rot(fwd, left, up); + } + + public vector llRot2Fwd(rotation r) + { + return m_LSL_Functions.llRot2Fwd(r); + } + + public vector llRot2Left(rotation r) + { + return m_LSL_Functions.llRot2Left(r); + } + + public vector llRot2Up(rotation r) + { + return m_LSL_Functions.llRot2Up(r); + } + + public rotation llRotBetween(vector start, vector end) + { + return m_LSL_Functions.llRotBetween(start, end); + } + + public void llWhisper(int channelID, string text) + { + m_LSL_Functions.llWhisper(channelID, text); + } + + public void llSay(int channelID, string text) + { + m_LSL_Functions.llSay(channelID, text); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llShout(int channelID, string text) + { + m_LSL_Functions.llShout(channelID, text); + } + + public int llListen(int channelID, string name, string ID, string msg) + { + return m_LSL_Functions.llListen(channelID, name, ID, msg); + } + + public void llListenControl(int number, int active) + { + m_LSL_Functions.llListenControl(number, active); + } + + public void llListenRemove(int number) + { + m_LSL_Functions.llListenRemove(number); + } + + public void llSensor(string name, string id, int type, double range, double arc) + { + m_LSL_Functions.llSensor(name, id, type, range, arc); + } + + public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) + { + m_LSL_Functions.llSensorRepeat(name, id, type, range, arc, rate); + } + + public void llSensorRemove() + { + m_LSL_Functions.llSensorRemove(); + } + + public string llDetectedName(int number) + { + return m_LSL_Functions.llDetectedName(number); + } + + public string llDetectedKey(int number) + { + return m_LSL_Functions.llDetectedKey(number); + } + + public string llDetectedOwner(int number) + { + return m_LSL_Functions.llDetectedOwner(number); + } + + public int llDetectedType(int number) + { + return m_LSL_Functions.llDetectedType(number); + } + + public vector llDetectedPos(int number) + { + return m_LSL_Functions.llDetectedPos(number); + } + + public vector llDetectedVel(int number) + { + return m_LSL_Functions.llDetectedVel(number); + } + + public vector llDetectedGrab(int number) + { + return m_LSL_Functions.llDetectedGrab(number); + } + + public rotation llDetectedRot(int number) + { + return m_LSL_Functions.llDetectedRot(number); + } + + public int llDetectedGroup(int number) + { + return m_LSL_Functions.llDetectedGroup(number); + } + + public int llDetectedLinkNumber(int number) + { + return m_LSL_Functions.llDetectedLinkNumber(number); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llDie() + { + m_LSL_Functions.llDie(); + } + + public double llGround(vector offset) + { + return m_LSL_Functions.llGround(offset); + } + + public double llCloud(vector offset) + { + return m_LSL_Functions.llCloud(offset); + } + + public vector llWind(vector offset) + { + return m_LSL_Functions.llWind(offset); + } + + public void llSetStatus(int status, int value) + { + m_LSL_Functions.llSetStatus(status, value); + } + + public int llGetStatus(int status) + { + return m_LSL_Functions.llGetStatus(status); + } + + public void llSetScale(vector scale) + { + m_LSL_Functions.llSetScale(scale); + } + + public vector llGetScale() + { + return m_LSL_Functions.llGetScale(); + } + + public void llSetColor(vector color, int face) + { + m_LSL_Functions.llSetColor(color, face); + } + + public double llGetAlpha(int face) + { + return m_LSL_Functions.llGetAlpha(face); + } + + public void llSetAlpha(double alpha, int face) + { + m_LSL_Functions.llSetAlpha(alpha, face); + } + + public vector llGetColor(int face) + { + return m_LSL_Functions.llGetColor(face); + } + + public void llSetTexture(string texture, int face) + { + m_LSL_Functions.llSetTexture(texture, face); + } + + public void llScaleTexture(double u, double v, int face) + { + m_LSL_Functions.llScaleTexture(u, v, face); + } + + public void llOffsetTexture(double u, double v, int face) + { + m_LSL_Functions.llOffsetTexture(u, v, face); + } + + public void llRotateTexture(double rotation, int face) + { + m_LSL_Functions.llRotateTexture(rotation, face); + } + + public string llGetTexture(int face) + { + return m_LSL_Functions.llGetTexture(face); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llSetPos(vector pos) + { + m_LSL_Functions.llSetPos(pos); + } + + public vector llGetPos() + { + return m_LSL_Functions.llGetPos(); + } + + public vector llGetLocalPos() + { + return m_LSL_Functions.llGetLocalPos(); + } + + public void llSetRot(rotation rot) + { + m_LSL_Functions.llSetRot(rot); + } + + public rotation llGetRot() + { + return m_LSL_Functions.llGetRot(); + } + + public rotation llGetLocalRot() + { + return m_LSL_Functions.llGetLocalRot(); + } + + public void llSetForce(vector force, int local) + { + m_LSL_Functions.llSetForce(force, local); + } + + public vector llGetForce() + { + return m_LSL_Functions.llGetForce(); + } + + public int llTarget(vector position, double range) + { + return m_LSL_Functions.llTarget(position, range); + } + + public void llTargetRemove(int number) + { + m_LSL_Functions.llTargetRemove(number); + } + + public int llRotTarget(rotation rot, double error) + { + return m_LSL_Functions.llRotTarget(rot, error); + } + + public void llRotTargetRemove(int number) + { + m_LSL_Functions.llRotTargetRemove(number); + } + + public void llMoveToTarget(vector target, double tau) + { + m_LSL_Functions.llMoveToTarget(target, tau); + } + + public void llStopMoveToTarget() + { + m_LSL_Functions.llStopMoveToTarget(); + } + + public void llApplyImpulse(vector force, int local) + { + m_LSL_Functions.llApplyImpulse(force, local); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llApplyRotationalImpulse(vector force, int local) + { + m_LSL_Functions.llApplyRotationalImpulse(force, local); + } + + public void llSetTorque(vector torque, int local) + { + m_LSL_Functions.llSetTorque(torque, local); + } + + public vector llGetTorque() + { + return m_LSL_Functions.llGetTorque(); + } + + public void llSetForceAndTorque(vector force, vector torque, int local) + { + m_LSL_Functions.llSetForceAndTorque(force, torque, local); + } + + public vector llGetVel() + { + return m_LSL_Functions.llGetVel(); + } + + public vector llGetAccel() + { + return m_LSL_Functions.llGetAccel(); + } + + public vector llGetOmega() + { + return m_LSL_Functions.llGetOmega(); + } + + public double llGetTimeOfDay() + { + return m_LSL_Functions.llGetTimeOfDay(); + } + + public double llGetWallclock() + { + return m_LSL_Functions.llGetWallclock(); + } + + public double llGetTime() + { + return m_LSL_Functions.llGetTime(); + } + + public void llResetTime() + { + m_LSL_Functions.llResetTime(); + } + + public double llGetAndResetTime() + { + return m_LSL_Functions.llGetAndResetTime(); + } + + public void llSound() + { + m_LSL_Functions.llSound(); + } + + public void llPlaySound(string sound, double volume) + { + m_LSL_Functions.llPlaySound(sound, volume); + } + + public void llLoopSound(string sound, double volume) + { + m_LSL_Functions.llLoopSound(sound, volume); + } + + public void llLoopSoundMaster(string sound, double volume) + { + m_LSL_Functions.llLoopSoundMaster(sound, volume); + } + + public void llLoopSoundSlave(string sound, double volume) + { + m_LSL_Functions.llLoopSoundSlave(sound, volume); + } + + public void llPlaySoundSlave(string sound, double volume) + { + m_LSL_Functions.llPlaySoundSlave(sound, volume); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llTriggerSound(string sound, double volume) + { + m_LSL_Functions.llTriggerSound(sound, volume); + } + + public void llStopSound() + { + m_LSL_Functions.llStopSound(); + } + + public void llPreloadSound(string sound) + { + m_LSL_Functions.llPreloadSound(sound); + } + + public string llGetSubString(string src, int start, int end) + { + return m_LSL_Functions.llGetSubString(src, start, end); + } + + public string llDeleteSubString(string src, int start, int end) + { + return m_LSL_Functions.llDeleteSubString(src, start, end); + } + + public string llInsertString(string dst, int position, string src) + { + return m_LSL_Functions.llInsertString(dst, position, src); + } + + public string llToUpper(string source) + { + return m_LSL_Functions.llToUpper(source); + } + + public string llToLower(string source) + { + return m_LSL_Functions.llToLower(source); + } + + public int llGiveMoney(string destination, int amount) + { + return m_LSL_Functions.llGiveMoney(destination, amount); + } + + public void llMakeExplosion() + { + m_LSL_Functions.llMakeExplosion(); + } + + public void llMakeFountain() + { + m_LSL_Functions.llMakeFountain(); + } + + public void llMakeSmoke() + { + m_LSL_Functions.llMakeSmoke(); + } + + public void llMakeFire() + { + m_LSL_Functions.llMakeFire(); + } + + public void llRezObject(string inventory, vector pos, rotation rot, int param) + { + m_LSL_Functions.llRezObject(inventory, pos, rot, param); + } + + public void llLookAt(vector target, double strength, double damping) + { + m_LSL_Functions.llLookAt(target, strength, damping); + } + + public void llStopLookAt() + { + m_LSL_Functions.llStopLookAt(); + } + + public void llSetTimerEvent(double sec) + { + m_LSL_Functions.llSetTimerEvent(sec); + } + + public void llSleep(double sec) + { + m_LSL_Functions.llSleep(sec); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public double llGetMass() + { + return m_LSL_Functions.llGetMass(); + } + + public void llCollisionFilter(string name, string id, int accept) + { + m_LSL_Functions.llCollisionFilter(name, id, accept); + } + + public void llTakeControls(int controls, int accept, int pass_on) + { + m_LSL_Functions.llTakeControls(controls, accept, pass_on); + } + + public void llReleaseControls() + { + m_LSL_Functions.llReleaseControls(); + } + + public void llAttachToAvatar(int attachment) + { + m_LSL_Functions.llAttachToAvatar(attachment); + } + + public void llDetachFromAvatar() + { + m_LSL_Functions.llDetachFromAvatar(); + } + + public void llTakeCamera() + { + m_LSL_Functions.llTakeCamera(); + } + + public void llReleaseCamera() + { + m_LSL_Functions.llReleaseCamera(); + } + + public string llGetOwner() + { + return m_LSL_Functions.llGetOwner(); + } + + public void llInstantMessage(string user, string message) + { + m_LSL_Functions.llInstantMessage(user, message); + } + + public void llEmail(string address, string subject, string message) + { + m_LSL_Functions.llEmail(address, subject, message); + } + + public void llGetNextEmail(string address, string subject) + { + m_LSL_Functions.llGetNextEmail(address, subject); + } + + public string llGetKey() + { + return m_LSL_Functions.llGetKey(); + } + + public void llSetBuoyancy(double buoyancy) + { + m_LSL_Functions.llSetBuoyancy(buoyancy); + } + + public void llSetHoverHeight(double height, int water, double tau) + { + m_LSL_Functions.llSetHoverHeight(height, water, tau); + } + + public void llStopHover() + { + m_LSL_Functions.llStopHover(); + } + + public void llMinEventDelay(double delay) + { + m_LSL_Functions.llMinEventDelay(delay); + } + + public void llSoundPreload() + { + m_LSL_Functions.llSoundPreload(); + } + + public void llRotLookAt(rotation target, double strength, double damping) + { + m_LSL_Functions.llRotLookAt(target, strength, damping); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public int llStringLength(string str) + { + return m_LSL_Functions.llStringLength(str); + } + + public void llStartAnimation(string anim) + { + m_LSL_Functions.llStartAnimation(anim); + } + + public void llStopAnimation(string anim) + { + m_LSL_Functions.llStopAnimation(anim); + } + + public void llPointAt() + { + m_LSL_Functions.llPointAt(); + } + + public void llStopPointAt() + { + m_LSL_Functions.llStopPointAt(); + } + + public void llTargetOmega(vector axis, double spinrate, double gain) + { + m_LSL_Functions.llTargetOmega(axis, spinrate, gain); + } + + public int llGetStartParameter() + { + return m_LSL_Functions.llGetStartParameter(); + } + + public void llGodLikeRezObject(string inventory, vector pos) + { + m_LSL_Functions.llGodLikeRezObject(inventory, pos); + } + + public void llRequestPermissions(string agent, int perm) + { + m_LSL_Functions.llRequestPermissions(agent, perm); + } + + public string llGetPermissionsKey() + { + return m_LSL_Functions.llGetPermissionsKey(); + } + + public int llGetPermissions() + { + return m_LSL_Functions.llGetPermissions(); + } + + public int llGetLinkNumber() + { + return m_LSL_Functions.llGetLinkNumber(); + } + + public void llSetLinkColor(int linknumber, vector color, int face) + { + m_LSL_Functions.llSetLinkColor(linknumber, color, face); + } + + public void llCreateLink(string target, int parent) + { + m_LSL_Functions.llCreateLink(target, parent); + } + + public void llBreakLink(int linknum) + { + m_LSL_Functions.llBreakLink(linknum); + } + + public void llBreakAllLinks() + { + m_LSL_Functions.llBreakAllLinks(); + } + + public string llGetLinkKey(int linknum) + { + return m_LSL_Functions.llGetLinkKey(linknum); + } + + public string llGetLinkName(int linknum) + { + return m_LSL_Functions.llGetLinkName(linknum); + } + + public int llGetInventoryNumber(int type) + { + return m_LSL_Functions.llGetInventoryNumber(type); + } + + public string llGetInventoryName(int type, int number) + { + return m_LSL_Functions.llGetInventoryName(type, number); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llSetScriptState(string name, int run) + { + m_LSL_Functions.llSetScriptState(name, run); + } + + public double llGetEnergy() + { + return m_LSL_Functions.llGetEnergy(); + } + + public void llGiveInventory(string destination, string inventory) + { + m_LSL_Functions.llGiveInventory(destination, inventory); + } + + public void llRemoveInventory(string item) + { + m_LSL_Functions.llRemoveInventory(item); + } + + public void llSetText(string text, vector color, double alpha) + { + m_LSL_Functions.llSetText(text, color, alpha); + } + + public double llWater(vector offset) + { + return m_LSL_Functions.llWater(offset); + } + + public void llPassTouches(int pass) + { + m_LSL_Functions.llPassTouches(pass); + } + + public string llRequestAgentData(string id, int data) + { + return m_LSL_Functions.llRequestAgentData(id, data); + } + + public string llRequestInventoryData(string name) + { + return m_LSL_Functions.llRequestInventoryData(name); + } + + public void llSetDamage(double damage) + { + m_LSL_Functions.llSetDamage(damage); + } + + public void llTeleportAgentHome(string agent) + { + m_LSL_Functions.llTeleportAgentHome(agent); + } + + public void llModifyLand(int action, int brush) + { + m_LSL_Functions.llModifyLand(action, brush); + } + + public void llCollisionSound(string impact_sound, double impact_volume) + { + m_LSL_Functions.llCollisionSound(impact_sound, impact_volume); + } + + public void llCollisionSprite(string impact_sprite) + { + m_LSL_Functions.llCollisionSprite(impact_sprite); + } + + public string llGetAnimation(string id) + { + return m_LSL_Functions.llGetAnimation(id); + } + + public void llResetScript() + { + m_LSL_Functions.llResetScript(); + } + + public void llMessageLinked(int linknum, int num, string str, string id) + { + m_LSL_Functions.llMessageLinked(linknum, num, str, id); + } + + public void llPushObject(string target, vector impulse, vector ang_impulse, int local) + { + m_LSL_Functions.llPushObject(target, impulse, ang_impulse, local); + } + + public void llPassCollisions(int pass) + { + m_LSL_Functions.llPassCollisions(pass); + } + + public string llGetScriptName() + { + return m_LSL_Functions.llGetScriptName(); + } + + public int llGetNumberOfSides() + { + return m_LSL_Functions.llGetNumberOfSides(); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public rotation llAxisAngle2Rot(vector axis, double angle) + { + return m_LSL_Functions.llAxisAngle2Rot(axis, angle); + } + + public vector llRot2Axis(rotation rot) + { + return m_LSL_Functions.llRot2Axis(rot); + } + + public void llRot2Angle() + { + m_LSL_Functions.llRot2Angle(); + } + + public double llAcos(double val) + { + return m_LSL_Functions.llAcos(val); + } + + public double llAsin(double val) + { + return m_LSL_Functions.llAsin(val); + } + + public double llAngleBetween(rotation a, rotation b) + { + return m_LSL_Functions.llAngleBetween(a, b); + } + + public string llGetInventoryKey(string name) + { + return m_LSL_Functions.llGetInventoryKey(name); + } + + public void llAllowInventoryDrop(int add) + { + m_LSL_Functions.llAllowInventoryDrop(add); + } + + public vector llGetSunDirection() + { + return m_LSL_Functions.llGetSunDirection(); + } + + public vector llGetTextureOffset(int face) + { + return m_LSL_Functions.llGetTextureOffset(face); + } + + public vector llGetTextureScale(int side) + { + return m_LSL_Functions.llGetTextureScale(side); + } + + public double llGetTextureRot(int side) + { + return m_LSL_Functions.llGetTextureRot(side); + } + + public int llSubStringIndex(string source, string pattern) + { + return m_LSL_Functions.llSubStringIndex(source, pattern); + } + + public string llGetOwnerKey(string id) + { + return m_LSL_Functions.llGetOwnerKey(id); + } + + public vector llGetCenterOfMass() + { + return m_LSL_Functions.llGetCenterOfMass(); + } + + public LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending) + { + return m_LSL_Functions.llListSort(src, stride, ascending); + } + + public int llGetListLength(LSL_Types.list src) + { + return m_LSL_Functions.llGetListLength(src); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public int llList2Integer(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Integer(src, index); + } + + public double osList2Double(LSL_Types.list src, int index) + { + return m_LSL_Functions.osList2Double(src, index); + } + + public string llList2String(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2String(src, index); + } + + public string llList2Key(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Key(src, index); + } + + public vector llList2Vector(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Vector(src, index); + } + + public rotation llList2Rot(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Rot(src, index); + } + + public LSL_Types.list llList2List(LSL_Types.list src, int start, int end) + { + return m_LSL_Functions.llList2List(src, start, end); + } + + public LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end) + { + return m_LSL_Functions.llDeleteSubList(src, start, end); + } + + public int llGetListEntryType(LSL_Types.list src, int index) + { + return m_LSL_Functions.llGetListEntryType(src, index); + } + + public string llList2CSV(LSL_Types.list src) + { + return m_LSL_Functions.llList2CSV(src); + } + + public LSL_Types.list llCSV2List(string src) + { + return m_LSL_Functions.llCSV2List(src); + } + + public LSL_Types.list llListRandomize(LSL_Types.list src, int stride) + { + return m_LSL_Functions.llListRandomize(src, stride); + } + + public LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride) + { + return m_LSL_Functions.llList2ListStrided(src, start, end, stride); + } + + public vector llGetRegionCorner() + { + return m_LSL_Functions.llGetRegionCorner(); + } + + public LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start) + { + return m_LSL_Functions.llListInsertList(dest, src, start); + } + + public int llListFindList(LSL_Types.list src, LSL_Types.list test) + { + return m_LSL_Functions.llListFindList(src, test); + } + + public string llGetObjectName() + { + return m_LSL_Functions.llGetObjectName(); + } + + public void llSetObjectName(string name) + { + m_LSL_Functions.llSetObjectName(name); + } + + public string llGetDate() + { + return m_LSL_Functions.llGetDate(); + } + + public int llEdgeOfWorld(vector pos, vector dir) + { + return m_LSL_Functions.llEdgeOfWorld(pos, dir); + } + + public int llGetAgentInfo(string id) + { + return m_LSL_Functions.llGetAgentInfo(id); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llAdjustSoundVolume(double volume) + { + m_LSL_Functions.llAdjustSoundVolume(volume); + } + + public void llSetSoundQueueing(int queue) + { + m_LSL_Functions.llSetSoundQueueing(queue); + } + + public void llSetSoundRadius(double radius) + { + m_LSL_Functions.llSetSoundRadius(radius); + } + + public string llKey2Name(string id) + { + return m_LSL_Functions.llKey2Name(id); + } + + public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + m_LSL_Functions.llSetTextureAnim(mode, face, sizex, sizey, start, length, rate); + } + + public void llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west) + { + m_LSL_Functions.llTriggerSoundLimited(sound, volume, top_north_east, bottom_south_west); + } + + public void llEjectFromLand(string pest) + { + m_LSL_Functions.llEjectFromLand(pest); + } + + public LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers) + { + return m_LSL_Functions.llParseString2List(str,separators,spacers); + } + + public int llOverMyLand(string id) + { + return m_LSL_Functions.llOverMyLand(id); + } + + public string llGetLandOwnerAt(vector pos) + { + return m_LSL_Functions.llGetLandOwnerAt(pos); + } + + public string llGetNotecardLine(string name, int line) + { + return m_LSL_Functions.llGetNotecardLine(name, line); + } + + public vector llGetAgentSize(string id) + { + return m_LSL_Functions.llGetAgentSize(id); + } + + public int llSameGroup(string agent) + { + return m_LSL_Functions.llSameGroup(agent); + } + + public void llUnSit(string id) + { + m_LSL_Functions.llUnSit(id); + } + + public vector llGroundSlope(vector offset) + { + return m_LSL_Functions.llGroundSlope(offset); + } + + public vector llGroundNormal(vector offset) + { + return m_LSL_Functions.llGroundNormal(offset); + } + + public vector llGroundContour(vector offset) + { + return m_LSL_Functions.llGroundContour(offset); + } + + public int llGetAttached() + { + return m_LSL_Functions.llGetAttached(); + } + + public int llGetFreeMemory() + { + return m_LSL_Functions.llGetFreeMemory(); + } + + public string llGetRegionName() + { + return m_LSL_Functions.llGetRegionName(); + } + + public double llGetRegionTimeDilation() + { + return m_LSL_Functions.llGetRegionTimeDilation(); + } + + public double llGetRegionFPS() + { + return m_LSL_Functions.llGetRegionFPS(); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llParticleSystem(LSL_Types.list rules) + { + m_LSL_Functions.llParticleSystem(rules); + } + + public void llGroundRepel(double height, int water, double tau) + { + m_LSL_Functions.llGroundRepel(height, water, tau); + } + + public void llGiveInventoryList() + { + m_LSL_Functions.llGiveInventoryList(); + } + + public void llSetVehicleType(int type) + { + m_LSL_Functions.llSetVehicleType(type); + } + + public void llSetVehicledoubleParam(int param, double value) + { + m_LSL_Functions.llSetVehicledoubleParam(param, value); + } + + public void llSetVehicleVectorParam(int param, vector vec) + { + m_LSL_Functions.llSetVehicleVectorParam(param, vec); + } + + public void llSetVehicleRotationParam(int param, rotation rot) + { + m_LSL_Functions.llSetVehicleRotationParam(param, rot); + } + + public void llSetVehicleFlags(int flags) + { + m_LSL_Functions.llSetVehicleFlags(flags); + } + + public void llRemoveVehicleFlags(int flags) + { + m_LSL_Functions.llRemoveVehicleFlags(flags); + } + + public void llSitTarget(vector offset, rotation rot) + { + m_LSL_Functions.llSitTarget(offset, rot); + } + + public string llAvatarOnSitTarget() + { + return m_LSL_Functions.llAvatarOnSitTarget(); + } + + public void llAddToLandPassList(string avatar, double hours) + { + m_LSL_Functions.llAddToLandPassList(avatar, hours); + } + + public void llSetTouchText(string text) + { + m_LSL_Functions.llSetTouchText(text); + } + + public void llSetSitText(string text) + { + m_LSL_Functions.llSetSitText(text); + } + + public void llSetCameraEyeOffset(vector offset) + { + m_LSL_Functions.llSetCameraEyeOffset(offset); + } + + public void llSetCameraAtOffset(vector offset) + { + m_LSL_Functions.llSetCameraAtOffset(offset); + } + + public string llDumpList2String(LSL_Types.list src, string seperator) + { + return m_LSL_Functions.llDumpList2String(src, seperator); + } + + public void llScriptDanger(vector pos) + { + m_LSL_Functions.llScriptDanger(pos); + } + + public void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel) + { + m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel); + } + + public void llVolumeDetect(int detect) + { + m_LSL_Functions.llVolumeDetect(detect); + } + + public void llResetOtherScript(string name) + { + m_LSL_Functions.llResetOtherScript(name); + } + + public int llGetScriptState(string name) + { + return m_LSL_Functions.llGetScriptState(name); + } + + public void llRemoteLoadScript() + { + m_LSL_Functions.llRemoteLoadScript(); + } + + public void llSetRemoteScriptAccessPin(int pin) + { + m_LSL_Functions.llSetRemoteScriptAccessPin(pin); + } + + public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) + { + m_LSL_Functions.llRemoteLoadScriptPin(target, name, pin, running, start_param); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llOpenRemoteDataChannel() + { + m_LSL_Functions.llOpenRemoteDataChannel(); + } + + public string llSendRemoteData(string channel, string dest, int idata, string sdata) + { + return m_LSL_Functions.llSendRemoteData(channel, dest, idata, sdata); + } + + public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) + { + m_LSL_Functions.llRemoteDataReply(channel, message_id, sdata, idata); + } + + public void llCloseRemoteDataChannel(string channel) + { + m_LSL_Functions.llCloseRemoteDataChannel(channel); + } + + public string llMD5String(string src, int nonce) + { + return m_LSL_Functions.llMD5String(src, nonce); + } + + public void llSetPrimitiveParams(LSL_Types.list rules) + { + m_LSL_Functions.llSetPrimitiveParams(rules); + } + + public string llStringToBase64(string str) + { + return m_LSL_Functions.llStringToBase64(str); + } + + public string llBase64ToString(string str) + { + return m_LSL_Functions.llBase64ToString(str); + } + + public void llXorBase64Strings() + { + m_LSL_Functions.llXorBase64Strings(); + } + + public void llRemoteDataSetRegion() + { + m_LSL_Functions.llRemoteDataSetRegion(); + } + + public double llLog10(double val) + { + return m_LSL_Functions.llLog10(val); + } + + public double llLog(double val) + { + return m_LSL_Functions.llLog(val); + } + + public LSL_Types.list llGetAnimationList(string id) + { + return m_LSL_Functions.llGetAnimationList(id); + } + + public void llSetParcelMusicURL(string url) + { + m_LSL_Functions.llSetParcelMusicURL(url); + } + + public vector llGetRootPosition() + { + return m_LSL_Functions.llGetRootPosition(); + } + + public rotation llGetRootRotation() + { + return m_LSL_Functions.llGetRootRotation(); + } + + public string llGetObjectDesc() + { + return m_LSL_Functions.llGetObjectDesc(); + } + + public void llSetObjectDesc(string desc) + { + m_LSL_Functions.llSetObjectDesc(desc); + } + + public string llGetCreator() + { + return m_LSL_Functions.llGetCreator(); + } + + public string llGetTimestamp() + { + return m_LSL_Functions.llGetTimestamp(); + } + + public void llSetLinkAlpha(int linknumber, double alpha, int face) + { + m_LSL_Functions.llSetLinkAlpha(linknumber, alpha, face); + } + + public int llGetNumberOfPrims() + { + return m_LSL_Functions.llGetNumberOfPrims(); + } + + public string llGetNumberOfNotecardLines(string name) + { + return m_LSL_Functions.llGetNumberOfNotecardLines(name); + } + + public LSL_Types.list llGetBoundingBox(string obj) + { + return m_LSL_Functions.llGetBoundingBox(obj); + } + + public vector llGetGeometricCenter() + { + return m_LSL_Functions.llGetGeometricCenter(); + } + + public void llGetPrimitiveParams() + { + m_LSL_Functions.llGetPrimitiveParams(); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public string llIntegerToBase64(int number) + { + return m_LSL_Functions.llIntegerToBase64(number); + } + + public int llBase64ToInteger(string str) + { + return m_LSL_Functions.llBase64ToInteger(str); + } + + public double llGetGMTclock() + { + return m_LSL_Functions.llGetGMTclock(); + } + + public string llGetSimulatorHostname() + { + return m_LSL_Functions.llGetSimulatorHostname(); + } + + public void llSetLocalRot(rotation rot) + { + m_LSL_Functions.llSetLocalRot(rot); + } + + public LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers) + { + return m_LSL_Functions.llParseStringKeepNulls(src, seperators, spacers); + } + + public void llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, int param) + { + m_LSL_Functions.llRezAtRoot(inventory, position, velocity, rot, param); + } + + public int llGetObjectPermMask(int mask) + { + return m_LSL_Functions.llGetObjectPermMask(mask); + } + + public void llSetObjectPermMask(int mask, int value) + { + m_LSL_Functions.llSetObjectPermMask(mask, value); + } + + public void llGetInventoryPermMask(string item, int mask) + { + m_LSL_Functions.llGetInventoryPermMask(item, mask); + } + + public void llSetInventoryPermMask(string item, int mask, int value) + { + m_LSL_Functions.llSetInventoryPermMask(item, mask, value); + } + + public string llGetInventoryCreator(string item) + { + return m_LSL_Functions.llGetInventoryCreator(item); + } + + public void llOwnerSay(string msg) + { + m_LSL_Functions.llOwnerSay(msg); + } + + public void llRequestSimulatorData(string simulator, int data) + { + m_LSL_Functions.llRequestSimulatorData(simulator, data); + } + + public void llForceMouselook(int mouselook) + { + m_LSL_Functions.llForceMouselook(mouselook); + } + + public double llGetObjectMass(string id) + { + return m_LSL_Functions.llGetObjectMass(id); + } + + public LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end) + { + return m_LSL_Functions.llListReplaceList(dest, src, start, end); + } + + public void llLoadURL(string avatar_id, string message, string url) + { + m_LSL_Functions.llLoadURL(avatar_id, message, url); + } + + public void llParcelMediaCommandList(LSL_Types.list commandList) + { + m_LSL_Functions.llParcelMediaCommandList(commandList); + } + + public void llParcelMediaQuery() + { + m_LSL_Functions.llParcelMediaQuery(); + } + + public int llModPow(int a, int b, int c) + { + return m_LSL_Functions.llModPow(a, b, c); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public int llGetInventoryType(string name) + { + return m_LSL_Functions.llGetInventoryType(name); + } + + public void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons) + { + m_LSL_Functions.llSetPayPrice(price, quick_pay_buttons); + } + + public vector llGetCameraPos() + { + return m_LSL_Functions.llGetCameraPos(); + } + + public rotation llGetCameraRot() + { + return m_LSL_Functions.llGetCameraRot(); + } + + public void llSetPrimURL() + { + m_LSL_Functions.llSetPrimURL(); + } + + public void llRefreshPrimURL() + { + m_LSL_Functions.llRefreshPrimURL(); + } + + public string llEscapeURL(string url) + { + return m_LSL_Functions.llEscapeURL(url); + } + + public string llUnescapeURL(string url) + { + return m_LSL_Functions.llUnescapeURL(url); + } + + public void llMapDestination(string simname, vector pos, vector look_at) + { + m_LSL_Functions.llMapDestination(simname, pos, look_at); + } + + public void llAddToLandBanList(string avatar, double hours) + { + m_LSL_Functions.llAddToLandBanList(avatar, hours); + } + + public void llRemoveFromLandPassList(string avatar) + { + m_LSL_Functions.llRemoveFromLandPassList(avatar); + } + + public void llRemoveFromLandBanList(string avatar) + { + m_LSL_Functions.llRemoveFromLandBanList(avatar); + } + + public void llSetCameraParams(LSL_Types.list rules) + { + m_LSL_Functions.llSetCameraParams(rules); + } + + public void llClearCameraParams() + { + m_LSL_Functions.llClearCameraParams(); + } + + public double llListStatistics(int operation, LSL_Types.list src) + { + return m_LSL_Functions.llListStatistics(operation, src); + } + + public int llGetUnixTime() + { + return m_LSL_Functions.llGetUnixTime(); + } + + public int llGetParcelFlags(vector pos) + { + return m_LSL_Functions.llGetParcelFlags(pos); + } + + public int llGetRegionFlags() + { + return m_LSL_Functions.llGetRegionFlags(); + } + + public string llXorBase64StringsCorrect(string str1, string str2) + { + return m_LSL_Functions.llXorBase64StringsCorrect(str1, str2); + } + + public string llHTTPRequest(string url, LSL_Types.list parameters, string body) + { + return m_LSL_Functions.llHTTPRequest(url, parameters, body); + } + + public void llResetLandBanList() + { + m_LSL_Functions.llResetLandBanList(); + } + + public void llResetLandPassList() + { + m_LSL_Functions.llResetLandPassList(); + } + + public int llGetParcelPrimCount(vector pos, int category, int sim_wide) + { + return m_LSL_Functions.llGetParcelPrimCount(pos, category, sim_wide); + } + + public LSL_Types.list llGetParcelPrimOwners(vector pos) + { + return m_LSL_Functions.llGetParcelPrimOwners(pos); + } + + public int llGetObjectPrimCount(string object_id) + { + return m_LSL_Functions.llGetObjectPrimCount(object_id); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public int llGetParcelMaxPrims(vector pos, int sim_wide) + { + return m_LSL_Functions.llGetParcelMaxPrims(pos, sim_wide); + } + + public LSL_Types.list llGetParcelDetails(vector pos, LSL_Types.list param) + { + return m_LSL_Functions.llGetParcelDetails(pos, param); + } + + public string llStringTrim(string src, int type) + { + return m_LSL_Functions.llStringTrim(src, type); + } + + // + // OpenSim Functions + // + public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, + int timer) + { + return m_LSL_Functions.osSetDynamicTextureURL(dynamicID, contentType, url, extraParams, timer); + } + + public double osTerrainGetHeight(int x, int y) + { + return m_LSL_Functions.osTerrainGetHeight(x, y); + } + + public int osTerrainSetHeight(int x, int y, double val) + { + return m_LSL_Functions.osTerrainSetHeight(x, y, val); + } + + public int osRegionRestart(double seconds) + { + return m_LSL_Functions.osRegionRestart(seconds); + } + + public void osRegionNotice(string msg) + { + m_LSL_Functions.osRegionNotice(msg); + } + + public bool osConsoleCommand(string Command) + { + return m_LSL_Functions.osConsoleCommand(Command); + } + + public double llList2Float(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Float(src, index); + } + + + // LSL CONSTANTS + public const int TRUE = 1; + public const int FALSE = 0; + public const int STATUS_PHYSICS = 1; + public const int STATUS_ROTATE_X = 2; + public const int STATUS_ROTATE_Y = 4; + public const int STATUS_ROTATE_Z = 8; + public const int STATUS_PHANTOM = 16; + public const int STATUS_SANDBOX = 32; + public const int STATUS_BLOCK_GRAB = 64; + public const int STATUS_DIE_AT_EDGE = 128; + public const int STATUS_RETURN_AT_EDGE = 256; + public const int STATUS_CAST_SHADOWS = 512; + public const int AGENT = 1; + public const int ACTIVE = 2; + public const int PASSIVE = 4; + public const int SCRIPTED = 8; + public const int CONTROL_FWD = 1; + public const int CONTROL_BACK = 2; + public const int CONTROL_LEFT = 4; + public const int CONTROL_RIGHT = 8; + public const int CONTROL_UP = 16; + public const int CONTROL_DOWN = 32; + public const int CONTROL_ROT_LEFT = 256; + public const int CONTROL_ROT_RIGHT = 512; + public const int CONTROL_LBUTTON = 268435456; + public const int CONTROL_ML_LBUTTON = 1073741824; + public const int PERMISSION_DEBIT = 2; + public const int PERMISSION_TAKE_CONTROLS = 4; + public const int PERMISSION_REMAP_CONTROLS = 8; + public const int PERMISSION_TRIGGER_ANIMATION = 16; + public const int PERMISSION_ATTACH = 32; + public const int PERMISSION_RELEASE_OWNERSHIP = 64; + public const int PERMISSION_CHANGE_LINKS = 128; + public const int PERMISSION_CHANGE_JOINTS = 256; + public const int PERMISSION_CHANGE_PERMISSIONS = 512; + public const int PERMISSION_TRACK_CAMERA = 1024; + public const int AGENT_FLYING = 1; + public const int AGENT_ATTACHMENTS = 2; + public const int AGENT_SCRIPTED = 4; + public const int AGENT_MOUSELOOK = 8; + public const int AGENT_SITTING = 16; + public const int AGENT_ON_OBJECT = 32; + public const int AGENT_AWAY = 64; + public const int AGENT_WALKING = 128; + public const int AGENT_IN_AIR = 256; + public const int AGENT_TYPING = 512; + public const int AGENT_CROUCHING = 1024; + public const int AGENT_BUSY = 2048; + public const int AGENT_ALWAYS_RUN = 4096; + public const int PSYS_PART_INTERP_COLOR_MASK = 1; + public const int PSYS_PART_INTERP_SCALE_MASK = 2; + public const int PSYS_PART_BOUNCE_MASK = 4; + public const int PSYS_PART_WIND_MASK = 8; + public const int PSYS_PART_FOLLOW_SRC_MASK = 16; + public const int PSYS_PART_FOLLOW_VELOCITY_MASK = 32; + public const int PSYS_PART_TARGET_POS_MASK = 64; + public const int PSYS_PART_TARGET_LINEAR_MASK = 128; + public const int PSYS_PART_EMISSIVE_MASK = 256; + public const int PSYS_PART_FLAGS = 0; + public const int PSYS_PART_START_COLOR = 1; + public const int PSYS_PART_START_ALPHA = 2; + public const int PSYS_PART_END_COLOR = 3; + public const int PSYS_PART_END_ALPHA = 4; + public const int PSYS_PART_START_SCALE = 5; + public const int PSYS_PART_END_SCALE = 6; + public const int PSYS_PART_MAX_AGE = 7; + public const int PSYS_SRC_ACCEL = 8; + public const int PSYS_SRC_PATTERN = 9; + public const int PSYS_SRC_INNERANGLE = 10; + public const int PSYS_SRC_OUTERANGLE = 11; + public const int PSYS_SRC_TEXTURE = 12; + public const int PSYS_SRC_BURST_RATE = 13; + public const int PSYS_SRC_BURST_PART_COUNT = 15; + public const int PSYS_SRC_BURST_RADIUS = 16; + public const int PSYS_SRC_BURST_SPEED_MIN = 17; + public const int PSYS_SRC_BURST_SPEED_MAX = 18; + public const int PSYS_SRC_MAX_AGE = 19; + public const int PSYS_SRC_TARGET_KEY = 20; + public const int PSYS_SRC_OMEGA = 21; + public const int PSYS_SRC_ANGLE_BEGIN = 22; + public const int PSYS_SRC_ANGLE_END = 23; + public const int PSYS_SRC_PATTERN_DROP = 1; + public const int PSYS_SRC_PATTERN_EXPLODE = 2; + public const int PSYS_SRC_PATTERN_ANGLE = 4; + public const int PSYS_SRC_PATTERN_ANGLE_CONE = 8; + public const int PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY = 16; + public const int VEHICLE_TYPE_NONE = 0; + public const int VEHICLE_TYPE_SLED = 1; + public const int VEHICLE_TYPE_CAR = 2; + public const int VEHICLE_TYPE_BOAT = 3; + public const int VEHICLE_TYPE_AIRPLANE = 4; + public const int VEHICLE_TYPE_BALLOON = 5; + public const int VEHICLE_LINEAR_FRICTION_TIMESCALE = 16; + public const int VEHICLE_ANGULAR_FRICTION_TIMESCALE = 17; + public const int VEHICLE_LINEAR_MOTOR_DIRECTION = 18; + public const int VEHICLE_LINEAR_MOTOR_OFFSET = 20; + public const int VEHICLE_ANGULAR_MOTOR_DIRECTION = 19; + public const int VEHICLE_HOVER_HEIGHT = 24; + public const int VEHICLE_HOVER_EFFICIENCY = 25; + public const int VEHICLE_HOVER_TIMESCALE = 26; + public const int VEHICLE_BUOYANCY = 27; + public const int VEHICLE_LINEAR_DEFLECTION_EFFICIENCY = 28; + public const int VEHICLE_LINEAR_DEFLECTION_TIMESCALE = 29; + public const int VEHICLE_LINEAR_MOTOR_TIMESCALE = 30; + public const int VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE = 31; + public const int VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY = 32; + public const int VEHICLE_ANGULAR_DEFLECTION_TIMESCALE = 33; + public const int VEHICLE_ANGULAR_MOTOR_TIMESCALE = 34; + public const int VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE = 35; + public const int VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY = 36; + public const int VEHICLE_VERTICAL_ATTRACTION_TIMESCALE = 37; + public const int VEHICLE_BANKING_EFFICIENCY = 38; + public const int VEHICLE_BANKING_MIX = 39; + public const int VEHICLE_BANKING_TIMESCALE = 40; + public const int VEHICLE_REFERENCE_FRAME = 44; + public const int VEHICLE_FLAG_NO_DEFLECTION_UP = 1; + public const int VEHICLE_FLAG_LIMIT_ROLL_ONLY = 2; + public const int VEHICLE_FLAG_HOVER_WATER_ONLY = 4; + public const int VEHICLE_FLAG_HOVER_TERRAIN_ONLY = 8; + public const int VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT = 16; + public const int VEHICLE_FLAG_HOVER_UP_ONLY = 32; + public const int VEHICLE_FLAG_LIMIT_MOTOR_UP = 64; + public const int VEHICLE_FLAG_MOUSELOOK_STEER = 128; + public const int VEHICLE_FLAG_MOUSELOOK_BANK = 256; + public const int VEHICLE_FLAG_CAMERA_DECOUPLED = 512; + public const int INVENTORY_ALL = -1; + public const int INVENTORY_NONE = -1; + public const int INVENTORY_TEXTURE = 0; + public const int INVENTORY_SOUND = 1; + public const int INVENTORY_LANDMARK = 3; + public const int INVENTORY_CLOTHING = 5; + public const int INVENTORY_OBJECT = 6; + public const int INVENTORY_NOTECARD = 7; + public const int INVENTORY_SCRIPT = 10; + public const int INVENTORY_BODYPART = 13; + public const int INVENTORY_ANIMATION = 20; + public const int INVENTORY_GESTURE = 21; + public const int ATTACH_CHEST = 1; + public const int ATTACH_HEAD = 2; + public const int ATTACH_LSHOULDER = 3; + public const int ATTACH_RSHOULDER = 4; + public const int ATTACH_LHAND = 5; + public const int ATTACH_RHAND = 6; + public const int ATTACH_LFOOT = 7; + public const int ATTACH_RFOOT = 8; + public const int ATTACH_BACK = 9; + public const int ATTACH_PELVIS = 10; + public const int ATTACH_MOUTH = 11; + public const int ATTACH_CHIN = 12; + public const int ATTACH_LEAR = 13; + public const int ATTACH_REAR = 14; + public const int ATTACH_LEYE = 15; + public const int ATTACH_REYE = 16; + public const int ATTACH_NOSE = 17; + public const int ATTACH_RUARM = 18; + public const int ATTACH_RLARM = 19; + public const int ATTACH_LUARM = 20; + public const int ATTACH_LLARM = 21; + public const int ATTACH_RHIP = 22; + public const int ATTACH_RULEG = 23; + public const int ATTACH_RLLEG = 24; + public const int ATTACH_LHIP = 25; + public const int ATTACH_LULEG = 26; + public const int ATTACH_LLLEG = 27; + public const int ATTACH_BELLY = 28; + public const int ATTACH_RPEC = 29; + public const int ATTACH_LPEC = 30; + public const int LAND_LEVEL = 0; + public const int LAND_RAISE = 1; + public const int LAND_LOWER = 2; + public const int LAND_SMOOTH = 3; + public const int LAND_NOISE = 4; + public const int LAND_REVERT = 5; + public const int LAND_SMALL_BRUSH = 1; + public const int LAND_MEDIUM_BRUSH = 2; + public const int LAND_LARGE_BRUSH = 3; + public const int DATA_ONLINE = 1; + public const int DATA_NAME = 2; + public const int DATA_BORN = 3; + public const int DATA_RATING = 4; + public const int DATA_SIM_POS = 5; + public const int DATA_SIM_STATUS = 6; + public const int DATA_SIM_RATING = 7; + public const int ANIM_ON = 1; + public const int LOOP = 2; + public const int REVERSE = 4; + public const int PING_PONG = 8; + public const int SMOOTH = 16; + public const int ROTATE = 32; + public const int SCALE = 64; + public const int ALL_SIDES = -1; + public const int LINK_SET = -1; + public const int LINK_ROOT = 1; + public const int LINK_ALL_OTHERS = -2; + public const int LINK_ALL_CHILDREN = -3; + public const int LINK_THIS = -4; + public const int CHANGED_INVENTORY = 1; + public const int CHANGED_COLOR = 2; + public const int CHANGED_SHAPE = 4; + public const int CHANGED_SCALE = 8; + public const int CHANGED_TEXTURE = 16; + public const int CHANGED_LINK = 32; + public const int CHANGED_ALLOWED_DROP = 64; + public const int CHANGED_OWNER = 128; + public const int TYPE_INVALID = 0; + public const int TYPE_INTEGER = 1; + public const int TYPE_double = 2; + public const int TYPE_STRING = 3; + public const int TYPE_KEY = 4; + public const int TYPE_VECTOR = 5; + public const int TYPE_ROTATION = 6; + public const int REMOTE_DATA_CHANNEL = 1; + public const int REMOTE_DATA_REQUEST = 2; + public const int REMOTE_DATA_REPLY = 3; + + public const int PRIM_MATERIAL = 2; + public const int PRIM_PHYSICS = 3; + public const int PRIM_TEMP_ON_REZ = 4; + public const int PRIM_PHANTOM = 5; + public const int PRIM_POSITION = 6; + public const int PRIM_SIZE = 7; + public const int PRIM_ROTATION = 8; + public const int PRIM_TYPE = 9; + public const int PRIM_TEXTURE = 17; + public const int PRIM_COLOR = 18; + public const int PRIM_BUMP_SHINY = 19; + public const int PRIM_FULLBRIGHT = 20; + public const int PRIM_FLEXIBLE = 21; + public const int PRIM_TEXGEN = 22; + public const int PRIM_CAST_SHADOWS = 24; // Not implemented, here for completeness sake + public const int PRIM_POINT_LIGHT = 23; // Huh? + public const int PRIM_TEXGEN_DEFAULT = 0; + public const int PRIM_TEXGEN_PLANAR = 1; + public const int PRIM_TYPE_BOX = 0; + public const int PRIM_TYPE_CYLINDER = 1; + public const int PRIM_TYPE_PRISM = 2; + public const int PRIM_TYPE_SPHERE = 3; + public const int PRIM_TYPE_TORUS = 4; + public const int PRIM_TYPE_TUBE = 5; + public const int PRIM_TYPE_RING = 6; + public const int PRIM_TYPE_SCULPT = 7; + public const int PRIM_HOLE_DEFAULT = 0; + public const int PRIM_HOLE_CIRCLE = 16; + public const int PRIM_HOLE_SQUARE = 32; + public const int PRIM_HOLE_TRIANGLE = 48; + public const int PRIM_MATERIAL_STONE = 0; + public const int PRIM_MATERIAL_METAL = 1; + public const int PRIM_MATERIAL_GLASS = 2; + public const int PRIM_MATERIAL_WOOD = 3; + public const int PRIM_MATERIAL_FLESH = 4; + public const int PRIM_MATERIAL_PLASTIC = 5; + public const int PRIM_MATERIAL_RUBBER = 6; + public const int PRIM_MATERIAL_LIGHT = 7; + public const int PRIM_SHINY_NONE = 0; + public const int PRIM_SHINY_LOW = 1; + public const int PRIM_SHINY_MEDIUM = 2; + public const int PRIM_SHINY_HIGH = 3; + public const int PRIM_BUMP_NONE = 0; + public const int PRIM_BUMP_BRIGHT = 1; + public const int PRIM_BUMP_DARK = 2; + public const int PRIM_BUMP_WOOD = 3; + public const int PRIM_BUMP_BARK = 4; + public const int PRIM_BUMP_BRICKS = 5; + public const int PRIM_BUMP_CHECKER = 6; + public const int PRIM_BUMP_CONCRETE = 7; + public const int PRIM_BUMP_TILE = 8; + public const int PRIM_BUMP_STONE = 9; + public const int PRIM_BUMP_DISKS = 10; + public const int PRIM_BUMP_GRAVEL = 11; + public const int PRIM_BUMP_BLOBS = 12; + public const int PRIM_BUMP_SIDING = 13; + public const int PRIM_BUMP_LARGETILE = 14; + public const int PRIM_BUMP_STUCCO = 15; + public const int PRIM_BUMP_SUCTION = 16; + public const int PRIM_BUMP_WEAVE = 17; + + public const int PRIM_SCULPT_TYPE_SPHERE = 1; + public const int PRIM_SCULPT_TYPE_TORUS = 2; + public const int PRIM_SCULPT_TYPE_PLANE = 3; + public const int PRIM_SCULPT_TYPE_CYLINDER = 4; + + + public const int MASK_BASE = 0; + public const int MASK_OWNER = 1; + public const int MASK_GROUP = 2; + public const int MASK_EVERYONE = 3; + public const int MASK_NEXT = 4; + public const int PERM_TRANSFER = 8192; + public const int PERM_MODIFY = 16384; + public const int PERM_COPY = 32768; + public const int PERM_MOVE = 524288; + public const int PERM_ALL = 2147483647; + public const int PARCEL_MEDIA_COMMAND_STOP = 0; + public const int PARCEL_MEDIA_COMMAND_PAUSE = 1; + public const int PARCEL_MEDIA_COMMAND_PLAY = 2; + public const int PARCEL_MEDIA_COMMAND_LOOP = 3; + public const int PARCEL_MEDIA_COMMAND_TEXTURE = 4; + public const int PARCEL_MEDIA_COMMAND_URL = 5; + public const int PARCEL_MEDIA_COMMAND_TIME = 6; + public const int PARCEL_MEDIA_COMMAND_AGENT = 7; + public const int PARCEL_MEDIA_COMMAND_UNLOAD = 8; + public const int PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9; + public const int PAY_HIDE = -1; + public const int PAY_DEFAULT = -2; + public const string NULL_KEY = "00000000-0000-0000-0000-000000000000"; + public const string EOF = "\n\n\n"; + public const double PI = 3.14159274f; + public const double TWO_PI = 6.28318548f; + public const double PI_BY_TWO = 1.57079637f; + public const double DEG_TO_RAD = 0.01745329238f; + public const double RAD_TO_DEG = 57.29578f; + public const double SQRT2 = 1.414213538f; + public const int STRING_TRIM_HEAD = 1; + public const int STRING_TRIM_TAIL = 2; + public const int STRING_TRIM = 3; + public const int LIST_STAT_RANGE = 0; + public const int LIST_STAT_MIN = 1; + public const int LIST_STAT_MAX = 2; + public const int LIST_STAT_MEAN = 3; + public const int LIST_STAT_MEDIAN = 4; + public const int LIST_STAT_STD_DEV = 5; + public const int LIST_STAT_SUM = 6; + public const int LIST_STAT_SUM_SQUARES = 7; + public const int LIST_STAT_NUM_COUNT = 8; + public const int LIST_STAT_GEOMETRIC_MEAN = 9; + public const int LIST_STAT_HARMONIC_MEAN = 100; + // Can not be public const? + public vector ZERO_VECTOR = new vector(0.0, 0.0, 0.0); + public rotation ZERO_ROTATION = new rotation(0.0, 0, 0.0, 1.0); + + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/trunk/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs new file mode 100644 index 0000000000..c07f6d76e6 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs @@ -0,0 +1,3709 @@ +/* +* 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; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using System.Text; +using System.Threading; +using Axiom.Math; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; +//using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; + +namespace OpenSim.Region.ScriptEngine.Common +{ + /// + /// Contains all LSL ll-functions. This class will be in Default AppDomain. + /// + public class LSL_BuiltIn_Commands : MarshalByRefObject, LSL_BuiltIn_Commands_Interface + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private ASCIIEncoding enc = new ASCIIEncoding(); + private ScriptEngineBase.ScriptEngine m_ScriptEngine; + private SceneObjectPart m_host; + private uint m_localID; + private LLUUID m_itemID; + private bool throwErrorOnNotImplemented = true; + + public LSL_BuiltIn_Commands(ScriptEngineBase.ScriptEngine ScriptEngine, SceneObjectPart host, uint localID, LLUUID itemID) + { + m_ScriptEngine = ScriptEngine; + m_host = host; + m_localID = localID; + m_itemID = itemID; + + //m_log.Info(ScriptEngineName, "LSL_BaseClass.Start() called. Hosted by [" + m_host.Name + ":" + m_host.UUID + "@" + m_host.AbsolutePosition + "]"); + } + + private DateTime m_timer = DateTime.Now; + private string m_state = "default"; + + public string State + { + get { return m_state; } + set { + bool changed = false; + if (m_state != value) + changed = true; + // Set it + m_state = value; + + if (changed) + { + m_ScriptEngine.m_EventManager.state_entry(m_localID); + } + } + } + + // Object never expires + public override Object InitializeLifetimeService() + { + //Console.WriteLine("LSL_BuiltIn_Commands: InitializeLifetimeService()"); + // return null; + ILease lease = (ILease)base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); + // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); + // lease.RenewOnCallTime = TimeSpan.FromSeconds(2); + } + return lease; + } + + public Scene World + { + get { return m_ScriptEngine.World; } + } + + //These are the implementations of the various ll-functions used by the LSL scripts. + //starting out, we use the System.Math library for trig functions. - ckrinke 8-14-07 + public double llSin(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Sin(f); + } + + public double llCos(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Cos(f); + } + + public double llTan(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Tan(f); + } + + public double llAtan2(double x, double y) + { + m_host.AddScriptLPS(1); + return (double)Math.Atan2(y, x); + } + + public double llSqrt(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Sqrt(f); + } + + public double llPow(double fbase, double fexponent) + { + m_host.AddScriptLPS(1); + return (double)Math.Pow(fbase, fexponent); + } + + public int llAbs(int i) + { + m_host.AddScriptLPS(1); + return (int)Math.Abs(i); + } + + public double llFabs(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Abs(f); + } + + public double llFrand(double mag) + { + m_host.AddScriptLPS(1); + lock (Util.RandomClass) + { + return Util.RandomClass.NextDouble() * mag; + } + } + + public int llFloor(double f) + { + m_host.AddScriptLPS(1); + return (int)Math.Floor(f); + } + + public int llCeil(double f) + { + m_host.AddScriptLPS(1); + return (int)Math.Ceiling(f); + } + + public int llRound(double f) + { + m_host.AddScriptLPS(1); + return (int)Math.Round(f, 0); + } + + //This next group are vector operations involving squaring and square root. ckrinke + public double llVecMag(LSL_Types.Vector3 v) + { + m_host.AddScriptLPS(1); + return (v.x * v.x + v.y * v.y + v.z * v.z); + } + + public LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v) + { + m_host.AddScriptLPS(1); + double mag = v.x * v.x + v.y * v.y + v.z * v.z; + LSL_Types.Vector3 nor = new LSL_Types.Vector3(); + nor.x = v.x / mag; + nor.y = v.y / mag; + nor.z = v.z / mag; + return nor; + } + + public double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b) + { + m_host.AddScriptLPS(1); + double dx = a.x - b.x; + double dy = a.y - b.y; + double dz = a.z - b.z; + return Math.Sqrt(dx * dx + dy * dy + dz * dz); + } + + //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke + public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r) + { + m_host.AddScriptLPS(1); + //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke + LSL_Types.Quaternion t = new LSL_Types.Quaternion(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s); + double m = (t.x + t.y + t.z + t.s); + if (m == 0) return new LSL_Types.Vector3(); + double n = 2 * (r.y * r.s + r.x * r.z); + double p = m * m - n * n; + if (p > 0) + return new LSL_Types.Vector3(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s)), + Math.Atan2(n, Math.Sqrt(p)), + Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))); + else if (n > 0) + return new LSL_Types.Vector3(0.0, Math.PI / 2, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); + else + return new LSL_Types.Vector3(0.0, -Math.PI / 2, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); + } + + public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v) + { + m_host.AddScriptLPS(1); + //this comes from from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions but is incomplete as of 8/19/07 + float err = 0.00001f; + double ax = Math.Sin(v.x / 2); + double aw = Math.Cos(v.x / 2); + double by = Math.Sin(v.y / 2); + double bw = Math.Cos(v.y / 2); + double cz = Math.Sin(v.z / 2); + double cw = Math.Cos(v.z / 2); + LSL_Types.Quaternion a1 = new LSL_Types.Quaternion(0.0, 0.0, cz, cw); + LSL_Types.Quaternion a2 = new LSL_Types.Quaternion(0.0, by, 0.0, bw); + LSL_Types.Quaternion a3 = new LSL_Types.Quaternion(ax, 0.0, 0.0, aw); + LSL_Types.Quaternion a = (a1 * a2) * a3; + //This multiplication doesnt compile, yet. a = a1 * a2 * a3; + LSL_Types.Quaternion b = new LSL_Types.Quaternion(ax * bw * cw + aw * by * cz, + aw * by * cw - ax * bw * cz, aw * bw * cz + ax * by * cw, + aw * bw * cw - ax * by * cz); + LSL_Types.Quaternion c = new LSL_Types.Quaternion(); + //This addition doesnt compile yet c = a + b; + LSL_Types.Quaternion d = new LSL_Types.Quaternion(); + //This addition doesnt compile yet d = a - b; + if ((Math.Abs(c.x) > err && Math.Abs(d.x) > err) || + (Math.Abs(c.y) > err && Math.Abs(d.y) > err) || + (Math.Abs(c.z) > err && Math.Abs(d.z) > err) || + (Math.Abs(c.s) > err && Math.Abs(d.s) > err)) + { + return b; + //return a new Quaternion that is null until I figure this out + // return b; + // return a; + } + return a; + } + + public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up) + { + m_host.AddScriptLPS(1); + return new LSL_Types.Quaternion(); + } + + public LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r) + { + m_host.AddScriptLPS(1); + return (new LSL_Types.Vector3(1,0,0) * r); + } + + public LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r) + { + m_host.AddScriptLPS(1); + return (new LSL_Types.Vector3(0, 1, 0) * r); + } + + public LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r) + { + m_host.AddScriptLPS(1); + return (new LSL_Types.Vector3(0, 0, 1) * r); + } + public LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 a, LSL_Types.Vector3 b) + { + //A and B should both be normalized + m_host.AddScriptLPS(1); + double dotProduct = LSL_Types.Vector3.Dot(a, b); + LSL_Types.Vector3 crossProduct = LSL_Types.Vector3.Cross(a, b); + double magProduct = LSL_Types.Vector3.Mag(a) * LSL_Types.Vector3.Mag(b); + double angle = Math.Acos(dotProduct / magProduct); + LSL_Types.Vector3 axis = LSL_Types.Vector3.Norm(crossProduct); + double s = Math.Sin(angle / 2); + + return new LSL_Types.Quaternion(axis.x * s, axis.y * s, axis.z * s, (float)Math.Cos(angle / 2)); + } + public void llWhisper(int channelID, string text) + { + m_host.AddScriptLPS(1); + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Whisper, channelID, m_host.Name, text); + } + + public void llSay(int channelID, string text) + { + m_host.AddScriptLPS(1); + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Say, channelID, m_host.Name, text); + } + + public void llShout(int channelID, string text) + { + m_host.AddScriptLPS(1); + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Shout, channelID, m_host.Name, text); + } + + public int llListen(int channelID, string name, string ID, string msg) + { + m_host.AddScriptLPS(1); + if (ID == String.Empty) + { + ID = LLUUID.Zero.ToString(); + } + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, ID, msg); + } + + public void llListenControl(int number, int active) + { + m_host.AddScriptLPS(1); + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.ListenControl(number, active); + } + + public void llListenRemove(int number) + { + m_host.AddScriptLPS(1); + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.ListenRemove(number); + } + + public void llSensor(string name, string id, int type, double range, double arc) + { + m_host.AddScriptLPS(1); + NotImplemented("llSensor"); + return; + } + + public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) + { + m_host.AddScriptLPS(1); + NotImplemented("llSensorRepeat"); + return; + } + + public void llSensorRemove() + { + m_host.AddScriptLPS(1); + NotImplemented("llSensorRemove"); + return; + } + + public string llDetectedName(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedName"); + return String.Empty; + } + + public string llDetectedKey(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedKey"); + return String.Empty; + } + + public string llDetectedOwner(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedOwner"); + return String.Empty; + } + + public int llDetectedType(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedType"); + return 0; + } + + public LSL_Types.Vector3 llDetectedPos(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedPos"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llDetectedVel(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedVel"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llDetectedGrab(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedGrab"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Quaternion llDetectedRot(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedRot"); + return new LSL_Types.Quaternion(); + } + + public int llDetectedGroup(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedGroup"); + return 0; + } + + public int llDetectedLinkNumber(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedLinkNumber"); + return 0; + } + + public void llDie() + { + m_host.AddScriptLPS(1); + World.DeleteSceneObjectGroup(m_host.ParentGroup); + return; + } + + public double llGround(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + int x = (int)(m_host.AbsolutePosition.X + offset.x); + int y = (int)(m_host.AbsolutePosition.Y + offset.y); + return World.GetLandHeight(x, y); + } + + public double llCloud(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llCloud"); + return 0; + } + + public LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llWind"); + return new LSL_Types.Vector3(); + } + + public void llSetStatus(int status, int value) + { + m_host.AddScriptLPS(1); + if ((status & LSL_BaseClass.STATUS_PHYSICS) == LSL_BaseClass.STATUS_PHYSICS) + { + m_host.AddFlag(LLObject.ObjectFlags.Physics); + } + if ((status & LSL_BaseClass.STATUS_PHANTOM) == LSL_BaseClass.STATUS_PHANTOM) + { + m_host.AddFlag(LLObject.ObjectFlags.Phantom); + } + if ((status & LSL_BaseClass.STATUS_CAST_SHADOWS) == LSL_BaseClass.STATUS_CAST_SHADOWS) + { + m_host.AddFlag(LLObject.ObjectFlags.CastShadows); + } + if ((status & LSL_BaseClass.STATUS_ROTATE_X) == LSL_BaseClass.STATUS_ROTATE_X) + { + NotImplemented("llSetStatus - STATUS_ROTATE_X"); + } + if ((status & LSL_BaseClass.STATUS_ROTATE_Y) == LSL_BaseClass.STATUS_ROTATE_Y) + { + NotImplemented("llSetStatus - STATUS_ROTATE_Y"); + } + if ((status & LSL_BaseClass.STATUS_ROTATE_Z) == LSL_BaseClass.STATUS_ROTATE_Z) + { + NotImplemented("llSetStatus - STATUS_ROTATE_Z"); + } + if ((status & LSL_BaseClass.STATUS_BLOCK_GRAB) == LSL_BaseClass.STATUS_BLOCK_GRAB) + { + NotImplemented("llSetStatus - STATUS_BLOCK_GRAB"); + } + if ((status & LSL_BaseClass.STATUS_DIE_AT_EDGE) == LSL_BaseClass.STATUS_DIE_AT_EDGE) + { + NotImplemented("llSetStatus - STATUS_DIE_AT_EDGE"); + } + if ((status & LSL_BaseClass.STATUS_RETURN_AT_EDGE) == LSL_BaseClass.STATUS_RETURN_AT_EDGE) + { + NotImplemented("llSetStatus - STATUS_RETURN_AT_EDGE"); + } + if ((status & LSL_BaseClass.STATUS_SANDBOX) == LSL_BaseClass.STATUS_SANDBOX) + { + NotImplemented("llSetStatus - STATUS_SANDBOX"); + } + + return; + } + + public int llGetStatus(int status) + { + m_host.AddScriptLPS(1); + Console.WriteLine(m_host.UUID.ToString() + " status is " + m_host.ObjectFlags.ToString()); + switch (status) + { + case LSL_BaseClass.STATUS_PHYSICS: + if ((m_host.ObjectFlags & (uint)LLObject.ObjectFlags.Physics) == (uint)LLObject.ObjectFlags.Physics) + { + return 1; + } + return 0; + case LSL_BaseClass.STATUS_PHANTOM: + if ((m_host.ObjectFlags & (uint)LLObject.ObjectFlags.Phantom) == (uint)LLObject.ObjectFlags.Phantom) + { + return 1; + } + return 0; + case LSL_BaseClass.STATUS_CAST_SHADOWS: + if ((m_host.ObjectFlags & (uint)LLObject.ObjectFlags.CastShadows) == (uint)LLObject.ObjectFlags.CastShadows) + { + return 1; + } + return 0; + case LSL_BaseClass.STATUS_BLOCK_GRAB: + NotImplemented("llGetStatus - STATUS_BLOCK_GRAB"); + return 0; + case LSL_BaseClass.STATUS_DIE_AT_EDGE: + NotImplemented("llGetStatus - STATUS_DIE_AT_EDGE"); + return 0; + case LSL_BaseClass.STATUS_RETURN_AT_EDGE: + NotImplemented("llGetStatus - STATUS_RETURN_AT_EDGE"); + return 0; + case LSL_BaseClass.STATUS_ROTATE_X: + NotImplemented("llGetStatus - STATUS_ROTATE_X"); + return 0; + case LSL_BaseClass.STATUS_ROTATE_Y: + NotImplemented("llGetStatus - STATUS_ROTATE_Y"); + return 0; + case LSL_BaseClass.STATUS_ROTATE_Z: + NotImplemented("llGetStatus - STATUS_ROTATE_Z"); + return 0; + case LSL_BaseClass.STATUS_SANDBOX: + NotImplemented("llGetStatus - STATUS_SANDBOX"); + return 0; + } + NotImplemented("llGetStatus - Unknown Status parameter"); + return 0; + } + + public void llSetScale(LSL_Types.Vector3 scale) + { + m_host.AddScriptLPS(1); + // TODO: this needs to trigger a persistance save as well + LLVector3 tmp = m_host.Scale; + tmp.X = (float)scale.x; + tmp.Y = (float)scale.y; + tmp.Z = (float)scale.z; + m_host.Scale = tmp; + m_host.SendFullUpdateToAllClients(); + return; + } + + public LSL_Types.Vector3 llGetScale() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z); + } + + public void llSetColor(LSL_Types.Vector3 color, int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[face].RGBA = texcolor; + m_host.UpdateTexture(tex); + return; + } + else if (face == -1) + { + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + } + m_host.UpdateTexture(tex); + return; + } + else + { + NotImplemented("llSetColor"); + } + } + + public double llGetAlpha(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color + { + return (double)((tex.DefaultTexture.RGBA.A * 255) / 255); + } + if (face > -1) + { + return (double)((tex.GetFace((uint)face).RGBA.A * 255) / 255); + } + return 0; + } + + public void llSetAlpha(double alpha, int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[face].RGBA = texcolor; + m_host.UpdateTexture(tex); + return; + } + else if (face == -1) + { + for (int i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + m_host.UpdateTexture(tex); + return; + } + else + { + NotImplemented("llSetAlpha"); + } + } + + public LSL_Types.Vector3 llGetColor(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LLColor texcolor; + LSL_Types.Vector3 rgb; + if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color + { + texcolor = tex.DefaultTexture.RGBA; + rgb.x = (255 - (texcolor.R * 255)) / 255; + rgb.y = (255 - (texcolor.G * 255)) / 255; + rgb.z = (255 - (texcolor.B * 255)) / 255; + return rgb; + } + if (face > -1) + { + texcolor = tex.GetFace((uint)face).RGBA; + rgb.x = (255 - (texcolor.R * 255)) / 255; + rgb.y = (255 - (texcolor.G * 255)) / 255; + rgb.z = (255 - (texcolor.B * 255)) / 255; + return rgb; + } + else + { + NotImplemented("llGetColor"); + return new LSL_Types.Vector3(); + } + } + + public void llSetTexture(string texture, int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + + if (face > -1) + { + LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); + texface.TextureID = new LLUUID(texture); + tex.FaceTextures[face] = texface; + m_host.UpdateTexture(tex); + return; + } + else if (face == -1) + { + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + tex.FaceTextures[i].TextureID = new LLUUID(texture); + } + } + tex.DefaultTexture.TextureID = new LLUUID(texture); + m_host.UpdateTexture(tex); + return; + } + else + { + NotImplemented("llSetTexture"); + } + } + + public void llScaleTexture(double u, double v, int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face > -1) + { + LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); + texface.RepeatU = (float)u; + texface.RepeatV = (float)v; + tex.FaceTextures[face] = texface; + m_host.UpdateTexture(tex); + return; + } + if (face == -1) + { + for (int i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + tex.FaceTextures[i].RepeatU = (float)u; + tex.FaceTextures[i].RepeatV = (float)v; + } + } + tex.DefaultTexture.RepeatU = (float)u; + tex.DefaultTexture.RepeatV = (float)v; + m_host.UpdateTexture(tex); + return; + } + else + { + NotImplemented("llScaleTexture"); + } + } + + public void llOffsetTexture(double u, double v, int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face > -1) + { + LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); + texface.OffsetU = (float)u; + texface.OffsetV = (float)v; + tex.FaceTextures[face] = texface; + m_host.UpdateTexture(tex); + return; + } + if (face == -1) + { + for (int i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + tex.FaceTextures[i].OffsetU = (float)u; + tex.FaceTextures[i].OffsetV = (float)v; + } + } + tex.DefaultTexture.OffsetU = (float)u; + tex.DefaultTexture.OffsetV = (float)v; + m_host.UpdateTexture(tex); + return; + } + else + { + NotImplemented("llOffsetTexture"); + } + } + + public void llRotateTexture(double rotation, int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face > -1) + { + LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); + texface.Rotation = (float)rotation; + tex.FaceTextures[face] = texface; + m_host.UpdateTexture(tex); + return; + } + if (face == -1) + { + for (int i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + tex.FaceTextures[i].Rotation = (float)rotation; + } + } + tex.DefaultTexture.Rotation = (float)rotation; + m_host.UpdateTexture(tex); + return; + } + else + { + NotImplemented("llRotateTexture"); + } + } + + public string llGetTexture(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face == -1) + { + face = 0; + } + if (face > -1) + { + LLObject.TextureEntryFace texface; + texface = tex.GetFace((uint)face); + return texface.TextureID.ToString(); + } + else + { + NotImplemented("llGetTexture"); + return String.Empty; + } + } + + public void llSetPos(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + if (m_host.ParentID != 0) + { + m_host.UpdateOffSet(new LLVector3((float)pos.x, (float)pos.y, (float)pos.z)); + } + else + { + m_host.UpdateGroupPosition(new LLVector3((float)pos.x, (float)pos.y, (float)pos.z)); + } + } + + public LSL_Types.Vector3 llGetPos() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.AbsolutePosition.X, + m_host.AbsolutePosition.Y, + m_host.AbsolutePosition.Z); + } + + public LSL_Types.Vector3 llGetLocalPos() + { + m_host.AddScriptLPS(1); + if (m_host.ParentID != 0) + { + return new LSL_Types.Vector3(m_host.OffsetPosition.X, + m_host.OffsetPosition.Y, + m_host.OffsetPosition.Z); + } + else + { + return new LSL_Types.Vector3(m_host.AbsolutePosition.X, + m_host.AbsolutePosition.Y, + m_host.AbsolutePosition.Z); + } + } + + public void llSetRot(LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + m_host.UpdateRotation(new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s)); + } + + public LSL_Types.Quaternion llGetRot() + { + m_host.AddScriptLPS(1); + LLQuaternion q = m_host.RotationOffset; + return new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); + } + + public LSL_Types.Quaternion llGetLocalRot() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Quaternion(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W); + } + + public void llSetForce(LSL_Types.Vector3 force, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetForce"); + } + + public LSL_Types.Vector3 llGetForce() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetForce"); + return new LSL_Types.Vector3(); + } + + public int llTarget(LSL_Types.Vector3 position, double range) + { + m_host.AddScriptLPS(1); + NotImplemented("llTarget"); + return 0; + } + + public void llTargetRemove(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llTargetRemove"); + } + + public int llRotTarget(LSL_Types.Quaternion rot, double error) + { + m_host.AddScriptLPS(1); + NotImplemented("llRotTarget"); + return 0; + } + + public void llRotTargetRemove(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llRotTargetRemove"); + } + + public void llMoveToTarget(LSL_Types.Vector3 target, double tau) + { + m_host.AddScriptLPS(1); + NotImplemented("llMoveToTarget"); + } + + public void llStopMoveToTarget() + { + m_host.AddScriptLPS(1); + NotImplemented("llStopMoveToTarget"); + } + + public void llApplyImpulse(LSL_Types.Vector3 force, int local) + { + m_host.AddScriptLPS(1); + //No energy force yet + if (local == 1) + { + NotImplemented("llApplyImpulse Local Force"); + } + else + { + if (force.x > 20000) + force.x = 20000; + if (force.y > 20000) + force.y = 20000; + if (force.z > 20000) + force.z = 20000; + + m_host.ApplyImpulse(new LLVector3((float)force.x,(float)force.y,(float)force.z)); + } + } + + public void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llApplyRotationalImpulse"); + } + + public void llSetTorque(LSL_Types.Vector3 torque, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetTorque"); + } + + public LSL_Types.Vector3 llGetTorque() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetTorque"); + return new LSL_Types.Vector3(); + } + + public void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetForceAndTorque"); + } + + public LSL_Types.Vector3 llGetVel() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z); + } + + public LSL_Types.Vector3 llGetAccel() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z); + } + + public LSL_Types.Vector3 llGetOmega() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetOmega"); + return new LSL_Types.Vector3(); + } + + public double llGetTimeOfDay() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetTimeOfDay"); + return 0; + } + + public double llGetWallclock() + { + m_host.AddScriptLPS(1); + return DateTime.Now.TimeOfDay.TotalSeconds; + } + + public double llGetTime() + { + m_host.AddScriptLPS(1); + TimeSpan ScriptTime = DateTime.Now - m_timer; + return (double)(ScriptTime.TotalMilliseconds / 1000); + } + + public void llResetTime() + { + m_host.AddScriptLPS(1); + m_timer = DateTime.Now; + } + + public double llGetAndResetTime() + { + m_host.AddScriptLPS(1); + TimeSpan ScriptTime = DateTime.Now - m_timer; + m_timer = DateTime.Now; + return (double)(ScriptTime.TotalMilliseconds / 1000); + } + + public void llSound() + { + m_host.AddScriptLPS(1); + // This function has been deprecated + // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound + NotImplemented("llSound"); + } + + public void llPlaySound(string sound, double volume) + { + m_host.AddScriptLPS(1); + m_host.SendSound(sound, volume, false); + } + + public void llLoopSound(string sound, double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llLoopSound"); + } + + public void llLoopSoundMaster(string sound, double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llLoopSoundMaster"); + } + + public void llLoopSoundSlave(string sound, double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llLoopSoundSlave"); + } + + public void llPlaySoundSlave(string sound, double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llPlaySoundSlave"); + } + + public void llTriggerSound(string sound, double volume) + { + m_host.AddScriptLPS(1); + m_host.SendSound(sound, volume, true); + } + + public void llStopSound() + { + m_host.AddScriptLPS(1); + NotImplemented("llStopSound"); + } + + public void llPreloadSound(string sound) + { + m_host.AddScriptLPS(1); + m_host.PreloadSound(sound); + } + + public string llGetSubString(string src, int start, int end) + { + m_host.AddScriptLPS(1); + // substring expects length + // return src.Substring(start, end); + + // if one is negative so use length of string as base + // if start > end then it is exclusive + // for length add +1 for char at location=0 + if (start < 0) { start = src.Length-start; } + if (end < 0) { end = src.Length - end; } + if (start > end) + { + return src.Substring(0, 1+end) + src.Substring(start, src.Length - start); + } + else + { + return src.Substring(start, (1+end) - start); + } + } + + public string llDeleteSubString(string src, int start, int end) + { + m_host.AddScriptLPS(1); + //return src.Remove(start, end - start); + // if one is negative so use length of string as base + // if start > end then it is exclusive + // for length add +1 for char at location=0 + if (start < 0) { start = src.Length - start; } + if (end < 0) { end = src.Length - end; } + if (start > end) + { + return src.Remove(0, 1 + end) + src.Remove(start, src.Length - start); + } + else + { + return src.Remove(start, (1 + end) - start); + } + } + + + public string llInsertString(string dst, int position, string src) + { + m_host.AddScriptLPS(1); + return dst.Insert(position, src); + } + + public string llToUpper(string src) + { + m_host.AddScriptLPS(1); + return src.ToUpper(); + } + + public string llToLower(string src) + { + m_host.AddScriptLPS(1); + return src.ToLower(); + } + + public int llGiveMoney(string destination, int amount) + { + m_host.AddScriptLPS(1); + NotImplemented("llGiveMoney"); + return 0; + } + + public void llMakeExplosion() + { + m_host.AddScriptLPS(1); + NotImplemented("llMakeExplosion"); + } + + public void llMakeFountain() + { + m_host.AddScriptLPS(1); + NotImplemented("llMakeFountain"); + } + + public void llMakeSmoke() + { + m_host.AddScriptLPS(1); + NotImplemented("llMakeSmoke"); + } + + public void llMakeFire() + { + m_host.AddScriptLPS(1); + NotImplemented("llMakeFire"); + } + + public void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Quaternion rot, int param) + { + m_host.AddScriptLPS(1); + NotImplemented("llRezObject"); + } + + public void llLookAt(LSL_Types.Vector3 target, double strength, double damping) + { + m_host.AddScriptLPS(1); + NotImplemented("llLookAt"); + } + + public void llStopLookAt() + { + m_host.AddScriptLPS(1); + NotImplemented("llStopLookAt"); + } + + public void llSetTimerEvent(double sec) + { + m_host.AddScriptLPS(1); + // Setting timer repeat + m_ScriptEngine.m_ASYNCLSLCommandManager.SetTimerEvent(m_localID, m_itemID, sec); + } + + public void llSleep(double sec) + { + m_host.AddScriptLPS(1); + Thread.Sleep((int)(sec * 1000)); + } + + public double llGetMass() + { + m_host.AddScriptLPS(1); + return m_host.GetMass(); + } + + public void llCollisionFilter(string name, string id, int accept) + { + m_host.AddScriptLPS(1); + NotImplemented("llCollisionFilter"); + } + + public void llTakeControls(int controls, int accept, int pass_on) + { + m_host.AddScriptLPS(1); + NotImplemented("llTakeControls"); + } + + public void llReleaseControls() + { + m_host.AddScriptLPS(1); + NotImplemented("llReleaseControls"); + } + + public void llAttachToAvatar(int attachment) + { + m_host.AddScriptLPS(1); + NotImplemented("llAttachToAvatar"); + } + + public void llDetachFromAvatar() + { + m_host.AddScriptLPS(1); + NotImplemented("llDetachFromAvatar"); + } + + public void llTakeCamera() + { + m_host.AddScriptLPS(1); + NotImplemented("llTakeCamera"); + } + + public void llReleaseCamera() + { + m_host.AddScriptLPS(1); + NotImplemented("llReleaseCamera"); + } + + public string llGetOwner() + { + m_host.AddScriptLPS(1); + return m_host.ObjectOwner.ToString(); + } + + public void llInstantMessage(string user, string message) + { + m_host.AddScriptLPS(1); + NotImplemented("llInstantMessage"); + + // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. + // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent, + // but I don't think we have a list of scenes available from here. + // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.) + + // TODO: figure out values for client, fromSession, and imSessionID + // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch()); + } + + public void llEmail(string address, string subject, string message) + { + m_host.AddScriptLPS(1); + NotImplemented("llEmail"); + } + + public void llGetNextEmail(string address, string subject) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetNextEmail"); + } + + public string llGetKey() + { + m_host.AddScriptLPS(1); + return m_host.UUID.ToString(); + } + + public void llSetBuoyancy(double buoyancy) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetBuoyancy"); + } + + public void llSetHoverHeight(double height, int water, double tau) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetHoverHeight"); + } + + public void llStopHover() + { + m_host.AddScriptLPS(1); + m_host.AddScriptLPS(1); + NotImplemented("llStopHover"); + } + + public void llMinEventDelay(double delay) + { + m_host.AddScriptLPS(1); + NotImplemented("llMinEventDelay"); + } + + public void llSoundPreload() + { + m_host.AddScriptLPS(1); + NotImplemented("llSoundPreload"); + } + + public void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping) + { + m_host.AddScriptLPS(1); + NotImplemented("llRotLookAt"); + } + + public int llStringLength(string str) + { + m_host.AddScriptLPS(1); + if (str.Length > 0) + { + return str.Length; + } + else + { + return 0; + } + } + + public void llStartAnimation(string anim) + { + m_host.AddScriptLPS(1); + NotImplemented("llStartAnimation"); + } + + public void llStopAnimation(string anim) + { + m_host.AddScriptLPS(1); + NotImplemented("llStopAnimation"); + } + + public void llPointAt() + { + m_host.AddScriptLPS(1); + NotImplemented("llPointAt"); + } + + public void llStopPointAt() + { + m_host.AddScriptLPS(1); + NotImplemented("llStopPointAt"); + } + + public void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain) + { + m_host.AddScriptLPS(1); + m_host.RotationalVelocity = new LLVector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); + m_host.AngularVelocity = new LLVector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); + m_host.ScheduleTerseUpdate(); + m_host.SendTerseUpdateToAllClients(); + //NotImplemented("llTargetOmega"); + } + + public int llGetStartParameter() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetStartParameter"); + return 0; + } + + public void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + NotImplemented("llGodLikeRezObject"); + } + + public void llRequestPermissions(string agent, int perm) + { + m_host.AddScriptLPS(1); + NotImplemented("llRequestPermissions"); + } + + public string llGetPermissionsKey() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetPermissionsKey"); + return String.Empty; + } + + public int llGetPermissions() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetPermissions"); + return 0; + } + + public int llGetLinkNumber() + { + m_host.AddScriptLPS(1); + return m_host.LinkNum; + } + + public void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber); + if (linknumber > -1) + { + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + else if (face == -1) + { + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + return; + } + else if (linknumber == -1) + { + int num = m_host.ParentGroup.PrimCount; + for (int w = 0; w < num; w++) + { + linknumber = w; + part = m_host.ParentGroup.GetLinkNumPart(linknumber); + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + } + else if (face == -1) + { + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + } + } + return; + } + else + { + NotImplemented("llSetLinkColor"); + } + } + + public void llCreateLink(string target, int parent) + { + m_host.AddScriptLPS(1); + NotImplemented("llCreateLink"); + } + + public void llBreakLink(int linknum) + { + m_host.AddScriptLPS(1); + NotImplemented("llBreakLink"); + } + + public void llBreakAllLinks() + { + m_host.AddScriptLPS(1); + NotImplemented("llBreakAllLinks"); + } + + public string llGetLinkKey(int linknum) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); + if (part != null) + { + return part.UUID.ToString(); + } + else + { + return "00000000-0000-0000-0000-000000000000"; + } + } + + public string llGetLinkName(int linknum) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); + if (part != null) + { + return part.Name; + } + else + { + return "00000000-0000-0000-0000-000000000000"; + } + } + + public int llGetInventoryNumber(int type) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetInventoryNumber"); + return 0; + } + + public string llGetInventoryName(int type, int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetInventoryName"); + return String.Empty; + } + + public void llSetScriptState(string name, int run) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetScriptState"); + } + + public double llGetEnergy() + { + m_host.AddScriptLPS(1); + return 1.0f; + } + + public void llGiveInventory(string destination, string inventory) + { + m_host.AddScriptLPS(1); + NotImplemented("llGiveInventory"); + } + + public void llRemoveInventory(string item) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoveInventory"); + } + + public void llSetText(string text, LSL_Types.Vector3 color, double alpha) + { + m_host.AddScriptLPS(1); + Vector3 av3 = new Vector3((float)color.x, (float)color.y, (float)color.z); + m_host.SetText(text, av3, alpha); + } + + public double llWater(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + return World.RegionInfo.EstateSettings.waterHeight; + } + + public void llPassTouches(int pass) + { + m_host.AddScriptLPS(1); + NotImplemented("llPassTouches"); + } + + public string llRequestAgentData(string id, int data) + { + m_host.AddScriptLPS(1); + NotImplemented("llRequestAgentData"); + return String.Empty; + } + + public string llRequestInventoryData(string name) + { + m_host.AddScriptLPS(1); + NotImplemented("llRequestInventoryData"); + return String.Empty; + } + + public void llSetDamage(double damage) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetDamage"); + } + + public void llTeleportAgentHome(string agent) + { + m_host.AddScriptLPS(1); + NotImplemented("llTeleportAgentHome"); + } + + public void llModifyLand(int action, int brush) + { + m_host.AddScriptLPS(1); + double dsize; + if (World.PermissionsMngr.CanTerraform(m_host.OwnerID, new LLVector3(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, 0))) + { + switch (brush) + { + case 1: + dsize = 2; + break; + case 2: + dsize = 4; + break; + case 3: + dsize = 8; + break; + default: + if (brush < 0) + { + dsize = (double)(-1 * brush); + } + else + { + LSLError("Invalid brush size"); + dsize = 0; // Should cease execution, but get unassigned local variable dsize on compile. + } + break; + } + switch (action) + { + case 0: + if (World.Terrain.GetHeight((int)m_host.AbsolutePosition.X, (int)m_host.AbsolutePosition.Y) < m_host.AbsolutePosition.Z) + { + World.Terrain.FlattenTerrain(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, dsize, 1); + } + break; + case 1: + if (World.Terrain.GetHeight((int)m_host.AbsolutePosition.X, (int)m_host.AbsolutePosition.Y) < (double)m_host.AbsolutePosition.Z) + { + World.Terrain.RaiseTerrain(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, dsize, 0.1); + } + break; + case 2: + if (World.Terrain.GetHeight((int)m_host.AbsolutePosition.X, (int)m_host.AbsolutePosition.Y) > 0) + { + World.Terrain.LowerTerrain(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, dsize, 1); + } + break; + case 3: + World.Terrain.SmoothTerrain(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, dsize, 1); + break; + case 4: + World.Terrain.NoiseTerrain(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, dsize, 1); + break; + case 5: + World.Terrain.RevertTerrain(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, dsize, 1); + break; + default: + break; + } + } + } + + public void llCollisionSound(string impact_sound, double impact_volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llCollisionSound"); + } + + public void llCollisionSprite(string impact_sprite) + { + m_host.AddScriptLPS(1); + NotImplemented("llCollisionSprite"); + } + + public string llGetAnimation(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAnimation"); + return String.Empty; + } + + public void llResetScript() + { + m_host.AddScriptLPS(1); + m_ScriptEngine.m_ScriptManager.ResetScript(m_localID, m_itemID); + } + + public void llMessageLinked(int linknum, int num, string str, string id) + { + m_host.AddScriptLPS(1); + } + + public void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local) + { + m_host.AddScriptLPS(1); + } + + public void llPassCollisions(int pass) + { + m_host.AddScriptLPS(1); + } + + public string llGetScriptName() + { + m_host.AddScriptLPS(1); + return String.Empty; + } + + public int llGetNumberOfSides() + { + m_host.AddScriptLPS(1); + return 0; + } + + public LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle) + { + m_host.AddScriptLPS(1); + return new LSL_Types.Quaternion(); + } + + public LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(); + } + + public void llRot2Angle() + { + m_host.AddScriptLPS(1); + } + + public double llAcos(double val) + { + m_host.AddScriptLPS(1); + return (double)Math.Acos(val); + } + + public double llAsin(double val) + { + m_host.AddScriptLPS(1); + return (double)Math.Asin(val); + } + + public double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b) + { + m_host.AddScriptLPS(1); + return 0; + } + + public string llGetInventoryKey(string name) + { + m_host.AddScriptLPS(1); + return String.Empty; + } + + public void llAllowInventoryDrop(int add) + { + m_host.AddScriptLPS(1); + } + + public LSL_Types.Vector3 llGetSunDirection() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGetTextureOffset(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LSL_Types.Vector3 offset; + if (face == -1) + { + face = 0; + } + offset.x = tex.GetFace((uint)face).OffsetU; + offset.y = tex.GetFace((uint)face).OffsetV; + offset.z = 0.0; + return offset; + } + + public LSL_Types.Vector3 llGetTextureScale(int side) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LSL_Types.Vector3 scale; + if (side == -1) + { + side = 0; + } + scale.x = tex.GetFace((uint)side).RepeatU; + scale.y = tex.GetFace((uint)side).RepeatV; + scale.z = 0.0; + return scale; + } + + public double llGetTextureRot(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face == -1) + { + face = 0; + } + return tex.GetFace((uint)face).Rotation; + } + + public int llSubStringIndex(string source, string pattern) + { + m_host.AddScriptLPS(1); + return source.IndexOf(pattern); + } + + public string llGetOwnerKey(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetOwnerKey"); + return String.Empty; + } + + public LSL_Types.Vector3 llGetCenterOfMass() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetCenterOfMass"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending) + { + m_host.AddScriptLPS(1); + // SortedList sorted = new SortedList(); + // Add chunks to an array + //int s = stride; + //if (s < 1) + // s = 1; + //int c = 0; + //LSL_Types.list chunk = new LSL_Types.list(); + //string chunkString = String.Empty; + //foreach (string element in src) + //{ + // c++; + // if (c > s) + // { + // sorted.Add(chunkString, chunk); + // chunkString = String.Empty; + // chunk = new LSL_Types.list(); + // c = 0; + // } + // chunk.Add(element); + // chunkString += element.ToString(); + //} + //if (chunk.Count > 0) + // sorted.Add(chunkString, chunk); + + //LSL_Types.list ret = new LSL_Types.list(); + //foreach (LSL_Types.list ls in sorted.Values) + //{ + // ret.AddRange(ls); + //} + + //if (ascending == LSL_BaseClass.TRUE) + // return ret; + //ret.Reverse(); + //return ret; + NotImplemented("llListSort"); + return new LSL_Types.list(); + } + + public int llGetListLength(LSL_Types.list src) + { + m_host.AddScriptLPS(1); + return src.Length; + } + + public int llList2Integer(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return 0; + } + return Convert.ToInt32(src.Data[index]); + } + + public double osList2Double(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return 0.0; + } + return Convert.ToDouble(src.Data[index]); + } + + public double llList2Float(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return 0.0; + } + return Convert.ToDouble(src.Data[index]); + } + + public string llList2String(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return String.Empty; + } + return src.Data[index].ToString(); + } + + public string llList2Key(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return "00000000-0000-0000-0000-000000000000"; + } + //return OpenSim.Framework.ToString(src[index]); + LLUUID tmpkey; + if (LLUUID.TryParse(src.Data[index].ToString(), out tmpkey)) + { + return tmpkey.ToString(); + } + else + { + return "00000000-0000-0000-0000-000000000000"; + } + } + + public LSL_Types.Vector3 llList2Vector(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return new LSL_Types.Vector3(0, 0, 0); + } + if (src.Data[index].GetType() == typeof(OpenSim.Region.ScriptEngine.Common.LSL_Types.Vector3)) + { + return (LSL_Types.Vector3)src.Data[index]; + } + else + { + return new LSL_Types.Vector3(0, 0, 0); + } + } + + public LSL_Types.Quaternion llList2Rot(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return new LSL_Types.Quaternion(0, 0, 0, 1); + } + if (src.Data[index].GetType() == typeof(OpenSim.Region.ScriptEngine.Common.LSL_Types.Quaternion)) + { + return (LSL_Types.Quaternion)src.Data[index]; + } + else + { + return new LSL_Types.Quaternion(0, 0, 0, 1); + } + } + + public LSL_Types.list llList2List(LSL_Types.list src, int start, int end) + { + m_host.AddScriptLPS(1); + return src.GetSublist(start, end); + } + + public LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end) + { + //LSL_Types.list ret = new LSL_Types.list(src); + //ret.RemoveRange(start, end - start); + //return ret; + + // Just a hunch - needs testing + return src.GetSublist(end, start); + } + + public int llGetListEntryType(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return 0; + } + + if (src.Data[index] is System.Int32) + return 1; + if (src.Data[index] is System.Double) + return 2; + if (src.Data[index] is System.String) + { + LLUUID tuuid; + if (LLUUID.TryParse(src.Data[index].ToString(), out tuuid)) + { + return 3; + } + else + { + return 4; + } + } + if (src.Data[index] is OpenSim.Region.ScriptEngine.Common.LSL_Types.Vector3) + return 5; + if (src.Data[index] is OpenSim.Region.ScriptEngine.Common.LSL_Types.Quaternion) + return 6; + if (src.Data[index] is OpenSim.Region.ScriptEngine.Common.LSL_Types.list) + return 7; + return 0; + + } + + public string llList2CSV(LSL_Types.list src) + { + m_host.AddScriptLPS(1); + string ret = String.Empty; + foreach (object o in src.Data) + { + ret = ret + o.ToString() + ", "; + } + ret = ret.Substring(0, ret.Length - 2); + return ret; + } + + public LSL_Types.list llCSV2List(string src) + { + m_host.AddScriptLPS(1); + return new LSL_Types.list(src.Split(",".ToCharArray())); + } + + public LSL_Types.list llListRandomize(LSL_Types.list src, int stride) + { + m_host.AddScriptLPS(1); + //int s = stride; + //if (s < 1) + // s = 1; + + // This is a cowardly way of doing it ;) + // TODO: Instead, randomize and check if random is mod stride or if it can not be, then array.removerange + //List tmp = new List(); + + // Add chunks to an array + //int c = 0; + //LSL_Types.list chunk = new LSL_Types.list(); + //foreach (string element in src) + //{ + // c++; + // if (c > s) + // { + // tmp.Add(chunk); + // chunk = new LSL_Types.list(); + // c = 0; + // } + // chunk.Add(element); + //} + //if (chunk.Count > 0) + // tmp.Add(chunk); + + // Decreate (<- what kind of word is that? :D ) array back into a list + //int rnd; + //LSL_Types.list ret = new LSL_Types.list(); + //while (tmp.Count > 0) + //{ + // rnd = Util.RandomClass.Next(tmp.Count); + // foreach (string str in tmp[rnd]) + // { + // ret.Add(str); + // } + // tmp.RemoveAt(rnd); + //} + + //return ret; + NotImplemented("llListRandomize"); + return src; + } + + public LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride) + { + m_host.AddScriptLPS(1); + LSL_Types.list ret = new LSL_Types.list(); + //int s = stride; + //if (s < 1) + // s = 1; + + //int sc = s; + //for (int i = start; i < src.Count; i++) + //{ + // sc--; + // if (sc == 0) + // { + // sc = s; + // // Addthis + // ret.Add(src[i]); + // } + // if (i == end) + // break; + //} + NotImplemented("llList2ListStrided"); + return ret; + } + + public LSL_Types.Vector3 llGetRegionCorner() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0); + } + + public LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start) + { + m_host.AddScriptLPS(1); + return dest.GetSublist(0, start - 1) + src + dest.GetSublist(start, -1); + } + + public int llListFindList(LSL_Types.list src, LSL_Types.list test) + { + m_host.AddScriptLPS(1); + //foreach (string s in test) + //{ + // for (int ci = 0; ci < src.Count; ci++) + // { + // if (s == src[ci]) + // return ci; + // } + //} + NotImplemented("llListFindList"); + return -1; + } + + public string llGetObjectName() + { + m_host.AddScriptLPS(1); + return m_host.Name; + } + + public void llSetObjectName(string name) + { + m_host.AddScriptLPS(1); + m_host.Name = name; + } + + public string llGetDate() + { + m_host.AddScriptLPS(1); + DateTime date = DateTime.Now.ToUniversalTime(); + string result = date.ToString("yyyy-MM-dd"); + return result; + } + + public int llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir) + { + m_host.AddScriptLPS(1); + NotImplemented("llEdgeOfWorld"); + return 0; + } + + public int llGetAgentInfo(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAgentInfo"); + return 0; + } + + public void llAdjustSoundVolume(double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llAdjustSoundVolume"); + } + + public void llSetSoundQueueing(int queue) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetSoundQueueing"); + } + + public void llSetSoundRadius(double radius) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetSoundRadius"); + } + + public string llKey2Name(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llKey2Name"); + return String.Empty; + } + + + + public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + m_host.AddScriptLPS(1); + Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation(); + pTexAnim.Flags =(uint) mode; + + //ALL_SIDES + if (face == -1) + face = 255; + + pTexAnim.Face = (uint)face; + pTexAnim.Length = (float)length; + pTexAnim.Rate = (float)rate; + pTexAnim.SizeX = (uint)sizex; + pTexAnim.SizeY = (uint)sizey; + pTexAnim.Start = (float)start; + + m_host.AddTextureAnimation(pTexAnim); + m_host.SendFullUpdateToAllClients(); + } + + public void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east, + LSL_Types.Vector3 bottom_south_west) + { + m_host.AddScriptLPS(1); + NotImplemented("llTriggerSoundLimited"); + } + + public void llEjectFromLand(string pest) + { + m_host.AddScriptLPS(1); + NotImplemented("llEjectFromLand"); + } + + public LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers) + { + m_host.AddScriptLPS(1); + LSL_Types.list ret = new LSL_Types.list(); + object[] delimeters = new object[separators.Length + spacers.Length]; + separators.Data.CopyTo(delimeters, 0); + spacers.Data.CopyTo(delimeters, separators.Length); + bool dfound = false; + do + { + dfound = false; + int cindex = -1; + string cdeli = ""; + for (int i = 0; i < delimeters.Length; i++) + { + int index = str.IndexOf(delimeters[i].ToString()); + bool found = index != -1; + if (found) + { + if ((cindex > index) || (cindex == -1)) + { + cindex = index; + cdeli = (string)delimeters[i]; + } + dfound = dfound || found; + } + } + if (cindex != -1) + { + if (cindex > 0) + { + ret.Add(str.Substring(0, cindex)); + if (spacers.Contains(cdeli)) + { + ret.Add(cdeli); + } + } + if (cindex == 0 && spacers.Contains(cdeli)) + { + ret.Add(cdeli); + } + str = str.Substring(cindex + 1); + } + } + while (dfound); + if (str != "") + { + ret.Add(str); + } + return ret; + } + + public int llOverMyLand(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llOverMyLand"); + return 0; + } + + public string llGetLandOwnerAt(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + return World.GetLandOwner((float)pos.x, (float)pos.y).ToString(); + } + + public string llGetNotecardLine(string name, int line) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetNotecardLine"); + return String.Empty; + } + + public LSL_Types.Vector3 llGetAgentSize(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAgentSize"); + return new LSL_Types.Vector3(); + } + + public int llSameGroup(string agent) + { + m_host.AddScriptLPS(1); + NotImplemented("llSameGroup"); + return 0; + } + + public void llUnSit(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llUnSit"); + } + + public LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llGroundSlope"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llGroundNormal"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llGroundContour"); + return new LSL_Types.Vector3(); + } + + public int llGetAttached() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAttached"); + return 0; + } + + public int llGetFreeMemory() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetFreeMemory"); + return 0; + } + + public string llGetRegionName() + { + m_host.AddScriptLPS(1); + return World.RegionInfo.RegionName; + } + + public double llGetRegionTimeDilation() + { + m_host.AddScriptLPS(1); + return (double)World.TimeDilation; + } + + public double llGetRegionFPS() + { + m_host.AddScriptLPS(1); + return 10.0f; + } + + /* particle system rules should be coming into this routine as doubles, that is + rule[0] should be an integer from this list and rule[1] should be the arg + for the same integer. wiki.secondlife.com has most of this mapping, but some + came from http://www.caligari-designs.com/p4u2 + + We iterate through the list for 'Count' elements, incrementing by two for each + iteration and set the members of Primitive.ParticleSystem, one at a time. + */ + + public enum PrimitiveRule : int + { + PSYS_PART_FLAGS = 0, + PSYS_PART_START_COLOR = 1, + PSYS_PART_START_ALPHA = 2, + PSYS_PART_END_COLOR = 3, + PSYS_PART_END_ALPHA = 4, + PSYS_PART_START_SCALE = 5, + PSYS_PART_END_SCALE = 6, + PSYS_PART_MAX_AGE = 7, + PSYS_SRC_ACCEL = 8, + PSYS_SRC_PATTERN = 9, + PSYS_SRC_TEXTURE = 12, + PSYS_SRC_BURST_RATE = 13, + PSYS_SRC_BURST_PART_COUNT = 15, + PSYS_SRC_BURST_RADIUS = 16, + PSYS_SRC_BURST_SPEED_MIN = 17, + PSYS_SRC_BURST_SPEED_MAX = 18, + PSYS_SRC_MAX_AGE = 19, + PSYS_SRC_TARGET_KEY = 20, + PSYS_SRC_OMEGA = 21, + PSYS_SRC_ANGLE_BEGIN = 22, + PSYS_SRC_ANGLE_END = 23 + } + + internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags) + { + Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None; + + return returnval; + } + + // AL: This does not actually do anything yet. There are issues within Libsecondlife revolving around PSYS_PART_FLAGS + // (need to OR the values, but currently stores this within an enum) as well as discovery of how the CRC works and the + // actual packet. + + public void llParticleSystem(LSL_Types.list rules) + { + m_host.AddScriptLPS(1); + Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); + LSL_Types.Vector3 tempv = new LSL_Types.Vector3(); + + float tempf = 0; + + for (int i = 0; i < rules.Length; i += 2) + { + switch ((int)rules.Data[i]) + { + case (int)LSL_BaseClass.PSYS_PART_FLAGS: + prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)((uint)Convert.ToInt32(rules.Data[i + 1].ToString())); + break; + + case (int)LSL_BaseClass.PSYS_PART_START_COLOR: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.PartStartColor.R = (float)tempv.x; + prules.PartStartColor.G = (float)tempv.y; + prules.PartStartColor.B = (float)tempv.z; + break; + + case (int)LSL_BaseClass.PSYS_PART_START_ALPHA: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.PartStartColor.A = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_PART_END_COLOR: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + //prules.PartEndColor = new LLColor(tempv.x,tempv.y,tempv.z,1); + + prules.PartEndColor.R = (float)tempv.x; + prules.PartEndColor.G = (float)tempv.y; + prules.PartEndColor.B = (float)tempv.z; + break; + + case (int)LSL_BaseClass.PSYS_PART_END_ALPHA: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.PartEndColor.A = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_PART_START_SCALE: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.PartStartScaleX = (float)tempv.x; + prules.PartStartScaleY = (float)tempv.y; + break; + + case (int)LSL_BaseClass.PSYS_PART_END_SCALE: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.PartEndScaleX = (float)tempv.x; + prules.PartEndScaleY = (float)tempv.y; + break; + + case (int)LSL_BaseClass.PSYS_PART_MAX_AGE: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.PartMaxAge = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_ACCEL: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.PartAcceleration.X = (float)tempv.x; + prules.PartAcceleration.Y = (float)tempv.y; + prules.PartAcceleration.Z = (float)tempv.z; + break; + + case (int)LSL_BaseClass.PSYS_SRC_PATTERN: + int tmpi = (int)rules.Data[i + 1]; + prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; + break; + + case (int)LSL_BaseClass.PSYS_SRC_TEXTURE: + prules.Texture = new LLUUID(rules.Data[i + 1].ToString()); + break; + + case (int)LSL_BaseClass.PSYS_SRC_BURST_RATE: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.BurstRate = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_BURST_PART_COUNT: + prules.BurstPartCount = (byte)Convert.ToByte(rules.Data[i + 1].ToString()); + break; + + case (int)LSL_BaseClass.PSYS_SRC_BURST_RADIUS: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.BurstRadius = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_BURST_SPEED_MIN: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.BurstSpeedMin = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_BURST_SPEED_MAX: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.BurstSpeedMax = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_MAX_AGE: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.MaxAge = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_TARGET_KEY: + LLUUID key = LLUUID.Zero; + if (LLUUID.TryParse(rules.Data[i + 1].ToString(), out key)) + { + prules.Target = key; + } + else + { + prules.Target = m_host.UUID; + } + break; + + case (int)LSL_BaseClass.PSYS_SRC_OMEGA: + // AL: This is an assumption, since it is the only thing that would match. + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.AngularVelocity.X = (float)tempv.x; + prules.AngularVelocity.Y = (float)tempv.y; + prules.AngularVelocity.Z = (float)tempv.z; + //cast?? prules.MaxAge = (float)rules[i + 1]; + break; + + case (int)LSL_BaseClass.PSYS_SRC_ANGLE_BEGIN: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.InnerAngle = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_ANGLE_END: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.OuterAngle = (float)tempf; + break; + } + + } + prules.CRC = 1; + + m_host.AddNewParticleSystem(prules); + m_host.SendFullUpdateToAllClients(); + } + + public void llGroundRepel(double height, int water, double tau) + { + m_host.AddScriptLPS(1); + NotImplemented("llGroundRepel"); + } + + public void llGiveInventoryList() + { + m_host.AddScriptLPS(1); + NotImplemented("llGiveInventoryList"); + } + + public void llSetVehicleType(int type) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleType"); + } + + public void llSetVehicledoubleParam(int param, double value) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicledoubleParam"); + } + + public void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleVectorParam"); + } + + public void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleRotationParam"); + } + + public void llSetVehicleFlags(int flags) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleFlags"); + } + + public void llRemoveVehicleFlags(int flags) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoveVehicleFlags"); + } + + public void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + // LSL quaternions can normalize to 0, normal Quaternions can't. + if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) + rot.z = 1; // ZERO_ROTATION = 0,0,0,1 + + m_host.SetSitTarget(new Vector3((float)offset.x, (float)offset.y, (float)offset.z), new Quaternion((float)rot.s, (float)rot.x, (float)rot.y, (float)rot.z)); + } + + public string llAvatarOnSitTarget() + { + m_host.AddScriptLPS(1); + LLUUID AVID = m_host.GetAvatarOnSitTarget(); + + if (AVID != LLUUID.Zero) + return AVID.ToString(); + else + return String.Empty; + } + + public void llAddToLandPassList(string avatar, double hours) + { + m_host.AddScriptLPS(1); + NotImplemented("llAddToLandPassList"); + } + + public void llSetTouchText(string text) + { + m_host.AddScriptLPS(1); + m_host.TouchName = text; + } + + public void llSetSitText(string text) + { + m_host.AddScriptLPS(1); + m_host.SitName = text; + } + + public void llSetCameraEyeOffset(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetCameraEyeOffset"); + } + + public void llSetCameraAtOffset(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetCameraAtOffset"); + } + + public string llDumpList2String(LSL_Types.list src, string seperator) + { + m_host.AddScriptLPS(1); + if (src.Length == 0) + { + return String.Empty; + } + string ret = String.Empty; + foreach (object o in src.Data) + { + ret = ret + o.ToString() + seperator; + } + ret = ret.Substring(0, ret.Length - seperator.Length); + return ret; + } + + public void llScriptDanger(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + NotImplemented("llScriptDanger"); + } + + public void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel) + { + m_host.AddScriptLPS(1); + LLUUID av = new LLUUID(); + if (!LLUUID.TryParse(avatar,out av)) + { + LSLError("First parameter to llDialog needs to be a key"); + return; + } + string[] buts = new string[buttons.Length]; + for(int i = 0; i < buttons.Length; i++) + { + buts[i] = buttons.Data[i].ToString(); + } + World.SendDialogToUser(av, m_host.Name, m_host.UUID, m_host.OwnerID, message, new LLUUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); + //NotImplemented("llDialog"); + } + + public void llVolumeDetect(int detect) + { + m_host.AddScriptLPS(1); + NotImplemented("llVolumeDetect"); + } + + public void llResetOtherScript(string name) + { + m_host.AddScriptLPS(1); + NotImplemented("llResetOtherScript"); + } + + public int llGetScriptState(string name) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetScriptState"); + return 0; + } + + public void llRemoteLoadScript() + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoteLoadScript"); + } + + public void llSetRemoteScriptAccessPin(int pin) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetRemoteScriptAccessPin"); + } + + public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoteLoadScriptPin"); + } + + // remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval) + // Not sure where these constants should live: + // REMOTE_DATA_CHANNEL = 1 + // REMOTE_DATA_REQUEST = 2 + // REMOTE_DATA_REPLY = 3 + public void llOpenRemoteDataChannel() + { + m_host.AddScriptLPS(1); + IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); + if (xmlrpcMod.IsEnabled()) + { + LLUUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID); + object[] resobj = new object[] { 1, channelID.ToString(), LLUUID.Zero.ToString(), String.Empty, 0, String.Empty }; + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(m_localID, m_itemID, "remote_data", EventQueueManager.llDetectNull, resobj); + } + } + + public string llSendRemoteData(string channel, string dest, int idata, string sdata) + { + m_host.AddScriptLPS(1); + NotImplemented("llSendRemoteData"); + return String.Empty; + } + + public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) + { + m_host.AddScriptLPS(1); + IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); + xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); + } + + public void llCloseRemoteDataChannel(string channel) + { + m_host.AddScriptLPS(1); + IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); + xmlrpcMod.CloseXMLRPCChannel(channel); + } + + public string llMD5String(string src, int nonce) + { + m_host.AddScriptLPS(1); + return Util.Md5Hash(src + ":" + nonce.ToString()); + } + + public void llSetPrimitiveParams(LSL_Types.list rules) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetPrimitiveParams"); + } + + public string llStringToBase64(string str) + { + m_host.AddScriptLPS(1); + try + { + byte[] encData_byte = new byte[str.Length]; + encData_byte = Encoding.UTF8.GetBytes(str); + string encodedData = Convert.ToBase64String(encData_byte); + return encodedData; + } + catch (Exception e) + { + throw new Exception("Error in base64Encode" + e.Message); + } + } + + public string llBase64ToString(string str) + { + m_host.AddScriptLPS(1); + UTF8Encoding encoder = new UTF8Encoding(); + Decoder utf8Decode = encoder.GetDecoder(); + try + { + byte[] todecode_byte = Convert.FromBase64String(str); + int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length); + char[] decoded_char = new char[charCount]; + utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0); + string result = new String(decoded_char); + return result; + } + catch (Exception e) + { + throw new Exception("Error in base64Decode" + e.Message); + } + } + + public void llXorBase64Strings() + { + m_host.AddScriptLPS(1); + throw new Exception("Command deprecated! Use llXorBase64StringsCorrect instead."); + } + + public void llRemoteDataSetRegion() + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoteDataSetRegion"); + } + + public double llLog10(double val) + { + m_host.AddScriptLPS(1); + return (double)Math.Log10(val); + } + + public double llLog(double val) + { + m_host.AddScriptLPS(1); + return (double)Math.Log(val); + } + + public LSL_Types.list llGetAnimationList(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAnimationList"); + return new LSL_Types.list(); + } + + public void llSetParcelMusicURL(string url) + { + m_host.AddScriptLPS(1); + LLUUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); + if (landowner.Equals(null)) + { + return; + } + if (landowner != m_host.ObjectOwner) + { + return; + } + World.SetLandMusicURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url); + } + + public LSL_Types.Vector3 llGetRootPosition() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, m_host.ParentGroup.AbsolutePosition.Z); + } + + public LSL_Types.Quaternion llGetRootRotation() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Quaternion(m_host.ParentGroup.GroupRotation.X, m_host.ParentGroup.GroupRotation.Y, m_host.ParentGroup.GroupRotation.Z, m_host.ParentGroup.GroupRotation.W); + } + + public string llGetObjectDesc() + { + return m_host.Description; + } + + public void llSetObjectDesc(string desc) + { + m_host.AddScriptLPS(1); + m_host.Description = desc; + } + + public string llGetCreator() + { + m_host.AddScriptLPS(1); + return m_host.ObjectCreator.ToString(); + } + + public string llGetTimestamp() + { + m_host.AddScriptLPS(1); + return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); + } + + public void llSetLinkAlpha(int linknumber, double alpha, int face) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber); + if (linknumber > -1) + { + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + else if (face == -1) + { + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + return; + } + else if (linknumber == -1) + { + int num = m_host.ParentGroup.PrimCount; + for (int w = 0; w < num; w++) + { + linknumber = w; + part = m_host.ParentGroup.GetLinkNumPart(linknumber); + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + } + else if (face == -1) + { + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + } + } + return; + } + else + { + NotImplemented("llSetLinkAlpha"); + } + } + + public int llGetNumberOfPrims() + { + m_host.AddScriptLPS(1); + return m_host.ParentGroup.PrimCount; + } + + public string llGetNumberOfNotecardLines(string name) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetNumberOfNotecardLines"); + return String.Empty; + } + + public LSL_Types.list llGetBoundingBox(string obj) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetBoundingBox"); + return new LSL_Types.list(); + } + + public LSL_Types.Vector3 llGetGeometricCenter() + { + return new LSL_Types.Vector3(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); + } + + public void llGetPrimitiveParams() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetPrimitiveParams"); + } + + public string llIntegerToBase64(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llIntegerToBase64"); + return String.Empty; + } + + public int llBase64ToInteger(string str) + { + m_host.AddScriptLPS(1); + NotImplemented("llBase64ToInteger"); + return 0; + } + + public double llGetGMTclock() + { + m_host.AddScriptLPS(1); + return DateTime.UtcNow.TimeOfDay.TotalSeconds; + } + + public string llGetSimulatorHostname() + { + m_host.AddScriptLPS(1); + return System.Environment.MachineName; + } + + public void llSetLocalRot(LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + m_host.RotationOffset = new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); + } + + public LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers) + { + m_host.AddScriptLPS(1); + NotImplemented("llParseStringKeepNulls"); + return new LSL_Types.list(); + } + + public void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity, + LSL_Types.Quaternion rot, int param) + { + m_host.AddScriptLPS(1); + NotImplemented("llRezAtRoot"); + } + + public int llGetObjectPermMask(int mask) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetObjectPermMask"); + return 0; + } + + public void llSetObjectPermMask(int mask, int value) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetObjectPermMask"); + } + + public void llGetInventoryPermMask(string item, int mask) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetInventoryPermMask"); + } + + public void llSetInventoryPermMask(string item, int mask, int value) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetInventoryPermMask"); + } + + public string llGetInventoryCreator(string item) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetInventoryCreator"); + return String.Empty; + } + + public void llOwnerSay(string msg) + { + m_host.AddScriptLPS(1); + //temp fix so that lsl wiki examples aren't annoying to use to test other functions + World.SimChat(Helpers.StringToField(msg), ChatTypeEnum.Say, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID); + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Say, 0, m_host.Name, msg); + } + + public void llRequestSimulatorData(string simulator, int data) + { + m_host.AddScriptLPS(1); + NotImplemented("llRequestSimulatorData"); + } + + public void llForceMouselook(int mouselook) + { + m_host.AddScriptLPS(1); + NotImplemented("llForceMouselook"); + } + + public double llGetObjectMass(string id) + { + m_host.AddScriptLPS(1); + LLUUID key = new LLUUID(); + if (LLUUID.TryParse(id,out key)) + { + return (double)World.GetSceneObjectPart(World.Entities[key].LocalId).GetMass(); + } + return 0; + } + + public LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end) + { + m_host.AddScriptLPS(1); + return dest.GetSublist(0, start - 1) + src + dest.GetSublist(end + 1, -1); + } + + public void llLoadURL(string avatar_id, string message, string url) + { + m_host.AddScriptLPS(1); + LLUUID avatarId = new LLUUID(avatar_id); + m_ScriptEngine.World.SendUrlToUser(avatarId, m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message, + url); + } + + public void llParcelMediaCommandList(LSL_Types.list commandList) + { + m_host.AddScriptLPS(1); + NotImplemented("llParcelMediaCommandList"); + } + + public void llParcelMediaQuery() + { + m_host.AddScriptLPS(1); + NotImplemented("llParcelMediaQuery"); + } + + public int llModPow(int a, int b, int c) + { + m_host.AddScriptLPS(1); + Int64 tmp = 0; + Int64 val = Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); + return Convert.ToInt32(tmp); + } + + public int llGetInventoryType(string name) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetInventoryType"); + return 0; + } + + public void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetPayPrice"); + } + + public LSL_Types.Vector3 llGetCameraPos() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetCameraPos"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Quaternion llGetCameraRot() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetCameraRot"); + return new LSL_Types.Quaternion(); + } + + public void llSetPrimURL() + { + m_host.AddScriptLPS(1); + NotImplemented("llSetPrimURL"); + } + + public void llRefreshPrimURL() + { + m_host.AddScriptLPS(1); + NotImplemented("llRefreshPrimURL"); + } + + public string llEscapeURL(string url) + { + m_host.AddScriptLPS(1); + try + { + return Uri.EscapeUriString(url); + } + catch (Exception ex) + { + return "llEscapeURL: " + ex.ToString(); + } + } + + public string llUnescapeURL(string url) + { + m_host.AddScriptLPS(1); + try + { + return Uri.UnescapeDataString(url); + } + catch (Exception ex) + { + return "llUnescapeURL: " + ex.ToString(); + } + } + + public void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at) + { + m_host.AddScriptLPS(1); + NotImplemented("llMapDestination"); + } + + public void llAddToLandBanList(string avatar, double hours) + { + m_host.AddScriptLPS(1); + NotImplemented("llAddToLandBanList"); + } + + public void llRemoveFromLandPassList(string avatar) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoveFromLandPassList"); + } + + public void llRemoveFromLandBanList(string avatar) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoveFromLandBanList"); + } + + public void llSetCameraParams(LSL_Types.list rules) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetCameraParams"); + } + + public void llClearCameraParams() + { + m_host.AddScriptLPS(1); + NotImplemented("llClearCameraParams"); + } + + public double llListStatistics(int operation, LSL_Types.list src) + { + m_host.AddScriptLPS(1); + LSL_Types.list nums = LSL_Types.list.ToDoubleList(src); + switch (operation) + { + case LSL_BaseClass.LIST_STAT_RANGE: + return nums.Range(); + break; + case LSL_BaseClass.LIST_STAT_MIN: + return nums.Min(); + break; + case LSL_BaseClass.LIST_STAT_MAX: + return nums.Max(); + break; + case LSL_BaseClass.LIST_STAT_MEAN: + return nums.Mean(); + break; + case LSL_BaseClass.LIST_STAT_MEDIAN: + return nums.Median(); + break; + case LSL_BaseClass.LIST_STAT_NUM_COUNT: + return nums.NumericLength(); + break; + case LSL_BaseClass.LIST_STAT_STD_DEV: + return nums.StdDev(); + break; + case LSL_BaseClass.LIST_STAT_SUM: + return nums.Sum(); + break; + case LSL_BaseClass.LIST_STAT_SUM_SQUARES: + return nums.SumSqrs(); + break; + case LSL_BaseClass.LIST_STAT_GEOMETRIC_MEAN: + return nums.GeometricMean(); + break; + case LSL_BaseClass.LIST_STAT_HARMONIC_MEAN: + return nums.HarmonicMean(); + break; + default: + return 0.0; + break; + } + } + + public int llGetUnixTime() + { + m_host.AddScriptLPS(1); + return Util.UnixTimeSinceEpoch(); + } + + public int llGetParcelFlags(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + return (int)World.LandManager.getLandObject((float)pos.x, (float)pos.y).landData.landFlags; + } + + public int llGetRegionFlags() + { + m_host.AddScriptLPS(1); + return (int)World.RegionInfo.EstateSettings.regionFlags; + } + + public string llXorBase64StringsCorrect(string str1, string str2) + { + m_host.AddScriptLPS(1); + string ret = String.Empty; + string src1 = llBase64ToString(str1); + string src2 = llBase64ToString(str2); + int c = 0; + for (int i = 0; i < src1.Length; i++) + { + ret += src1[i] ^ src2[c]; + + c++; + if (c > src2.Length) + c = 0; + } + return llStringToBase64(ret); + } + + public string llHTTPRequest(string url, LSL_Types.list parameters, string body) + { + m_host.AddScriptLPS(1); + IHttpRequests httpScriptMod = + m_ScriptEngine.World.RequestModuleInterface(); + List param = new List(); + foreach (object o in parameters.Data) + { + param.Add(o.ToString()); + } + LLUUID reqID = httpScriptMod. + StartHttpRequest(m_localID, m_itemID, url, param, body); + + if (!reqID.Equals(null)) + return reqID.ToString(); + else + return null; + } + + public void llResetLandBanList() + { + m_host.AddScriptLPS(1); + NotImplemented("llResetLandBanList"); + } + + public void llResetLandPassList() + { + m_host.AddScriptLPS(1); + NotImplemented("llResetLandPassList"); + } + + public int llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetParcelPrimCount"); + return 0; + } + + public LSL_Types.list llGetParcelPrimOwners(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetParcelPrimOwners"); + return new LSL_Types.list(); + } + + public int llGetObjectPrimCount(string object_id) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = World.GetSceneObjectPart(new LLUUID(object_id)); + if (part == null) + { + return 0; + } + else + { + return part.ParentGroup.Children.Count; + } + } + + public int llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide) + { + m_host.AddScriptLPS(1); + // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation + // Which probably will be irrelevent in OpenSim.... + LandData land = World.GetLandData((float)pos.x, (float)pos.y); + float bonusfactor = World.RegionInfo.EstateSettings.objectBonusFactor; + if (land == null) + { + return 0; + } + if (sim_wide == 1) + { + decimal v = land.simwideArea * (decimal)(0.22) * (decimal)bonusfactor; + return (int)v; + } + else + { + decimal v = land.area * (decimal)(0.22) * (decimal)bonusfactor; + return (int)v; + } + + } + + public LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param) + { + m_host.AddScriptLPS(1); + LandData land = World.GetLandData((float)pos.x, (float)pos.y); + if (land == null) + { + return new LSL_Types.list(0); + } + LSL_Types.list ret = new LSL_Types.list(); + foreach (object o in param.Data) + { + switch (o.ToString()) + { + case "0": + ret = ret + new LSL_Types.list(land.landName); + break; + case "1": + ret = ret + new LSL_Types.list(land.landDesc); + break; + case "2": + ret = ret + new LSL_Types.list(land.ownerID.ToString()); + break; + case "3": + ret = ret + new LSL_Types.list(land.groupID.ToString()); + break; + case "4": + ret = ret + new LSL_Types.list(land.area); + break; + default: + ret = ret + new LSL_Types.list(0); + break; + } + } + return ret; + } + + public string llStringTrim(string src, int type) + { + m_host.AddScriptLPS(1); + if (type == (int)LSL_BaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); } + if (type == (int)LSL_BaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); } + if (type == (int)LSL_BaseClass.STRING_TRIM) { return src.Trim(); } + return src; + } + + // + // OpenSim functions + // + public int osTerrainSetHeight(int x, int y, double val) + { + m_host.AddScriptLPS(1); + if (x > 255 || x < 0 || y > 255 || y < 0) + LSLError("osTerrainSetHeight: Coordinate out of bounds"); + + if (World.PermissionsMngr.CanTerraform(m_host.OwnerID, new LLVector3(x, y, 0))) + { + World.Terrain.Set(x, y, val); + return 1; + } + else + { + return 0; + } + } + + public double osTerrainGetHeight(int x, int y) + { + m_host.AddScriptLPS(1); + if (x > 255 || x < 0 || y > 255 || y < 0) + LSLError("osTerrainGetHeight: Coordinate out of bounds"); + + return World.Terrain.GetHeight(x, y); + } + + public int osRegionRestart(double seconds) + { + m_host.AddScriptLPS(1); + if (World.PermissionsMngr.CanRestartSim(m_host.OwnerID)) + { + World.Restart((float)seconds); + return 1; + } + else + { + return 0; + } + } + + public void osRegionNotice(string msg) + { + m_host.AddScriptLPS(1); + World.SendGeneralAlert(msg); + } + + public void osSetRot(LLUUID target, Quaternion rotation) + { + m_host.AddScriptLPS(1); + if (World.Entities.ContainsKey(target)) + { + World.Entities[target].Rotation = rotation; + } + else + { + LSLError("osSetRot: Invalid target"); + } + } + + public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, + int timer) + { + m_host.AddScriptLPS(1); + if (dynamicID == String.Empty) + { + IDynamicTextureManager textureManager = World.RequestModuleInterface(); + LLUUID createdTexture = + textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, + extraParams, timer); + return createdTexture.ToString(); + } + else + { + //TODO update existing dynamic textures + } + + return LLUUID.Zero.ToString(); + } + + public bool osConsoleCommand(string Command) + { + m_host.AddScriptLPS(1); + Nini.Config.IConfigSource config = new Nini.Config.IniConfigSource(Application.iniFilePath); + if (config.Configs["LL-Functions"] == null) + config.AddConfig("LL-Functions"); + + if (config.Configs["LL-Functions"].GetBoolean("AllowosConsoleCommand", false)) { + if (World.PermissionsMngr.CanRunConsoleCommand(m_host.OwnerID)) { + OpenSim.Framework.Console.MainConsole.Instance.RunCommand(Command); + return true; + } + return false; + } + return false; + } + + private void NotImplemented(string Command) + { + m_host.AddScriptLPS(1); + if (throwErrorOnNotImplemented) + throw new NotImplementedException("Command not implemented: " + Command); + } + + private void LSLError(string msg) + { + m_host.AddScriptLPS(1); + throw new Exception("LSL Runtime Error: " + msg); + } + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs b/trunk/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs new file mode 100644 index 0000000000..0703523336 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs @@ -0,0 +1,646 @@ +/* +* 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.Collections.Generic; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public interface LSL_BuiltIn_Commands_Interface + { + + // Interface used for loading and executing scripts + + string State { get; set; } + + double llSin(double f); + double llCos(double f); + double llTan(double f); + double llAtan2(double x, double y); + double llSqrt(double f); + double llPow(double fbase, double fexponent); + int llAbs(int i); + double llFabs(double f); + double llFrand(double mag); + int llFloor(double f); + int llCeil(double f); + int llRound(double f); + double llVecMag(LSL_Types.Vector3 v); + LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v); + double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b); + LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r); + LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v); + LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up); + LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r); + LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r); + LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r); + LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 start, LSL_Types.Vector3 end); + void llWhisper(int channelID, string text); + //void llSay(int channelID, string text); + void llSay(int channelID, string text); + void llShout(int channelID, string text); + int llListen(int channelID, string name, string ID, string msg); + void llListenControl(int number, int active); + void llListenRemove(int number); + void llSensor(string name, string id, int type, double range, double arc); + void llSensorRepeat(string name, string id, int type, double range, double arc, double rate); + void llSensorRemove(); + string llDetectedName(int number); + string llDetectedKey(int number); + string llDetectedOwner(int number); + int llDetectedType(int number); + LSL_Types.Vector3 llDetectedPos(int number); + LSL_Types.Vector3 llDetectedVel(int number); + LSL_Types.Vector3 llDetectedGrab(int number); + LSL_Types.Quaternion llDetectedRot(int number); + int llDetectedGroup(int number); + int llDetectedLinkNumber(int number); + void llDie(); + double llGround(LSL_Types.Vector3 offset); + double llCloud(LSL_Types.Vector3 offset); + LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset); + void llSetStatus(int status, int value); + int llGetStatus(int status); + void llSetScale(LSL_Types.Vector3 scale); + LSL_Types.Vector3 llGetScale(); + void llSetColor(LSL_Types.Vector3 color, int face); + double llGetAlpha(int face); + void llSetAlpha(double alpha, int face); + LSL_Types.Vector3 llGetColor(int face); + void llSetTexture(string texture, int face); + void llScaleTexture(double u, double v, int face); + void llOffsetTexture(double u, double v, int face); + void llRotateTexture(double rotation, int face); + string llGetTexture(int face); + void llSetPos(LSL_Types.Vector3 pos); + + //wiki: vector llGetPos() + LSL_Types.Vector3 llGetPos(); + //wiki: vector llGetLocalPos() + LSL_Types.Vector3 llGetLocalPos(); + //wiki: llSetRot(rotation rot) + void llSetRot(LSL_Types.Quaternion rot); + //wiki: rotation llGetRot() + LSL_Types.Quaternion llGetRot(); + //wiki: rotation llGetLocalRot() + LSL_Types.Quaternion llGetLocalRot(); + //wiki: llSetForce(vector force, integer local) + void llSetForce(LSL_Types.Vector3 force, int local); + //wiki: vector llGetForce() + LSL_Types.Vector3 llGetForce(); + //wiki: integer llTarget(vector position, double range) + int llTarget(LSL_Types.Vector3 position, double range); + //wiki: llTargetRemove(integer number) + void llTargetRemove(int number); + //wiki: integer llRotTarget(rotation rot, double error) + int llRotTarget(LSL_Types.Quaternion rot, double error); + //wiki: integer llRotTargetRemove(integer number) + void llRotTargetRemove(int number); + //wiki: llMoveToTarget(vector target, double tau) + void llMoveToTarget(LSL_Types.Vector3 target, double tau); + //wiki: llStopMoveToTarget() + void llStopMoveToTarget(); + //wiki: llApplyImpulse(vector force, integer local) + void llApplyImpulse(LSL_Types.Vector3 force, int local); + //wiki: llapplyRotationalImpulse(vector force, integer local) + void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local); + //wiki: llSetTorque(vector torque, integer local) + void llSetTorque(LSL_Types.Vector3 torque, int local); + //wiki: vector llGetTorque() + LSL_Types.Vector3 llGetTorque(); + //wiki: llSeForceAndTorque(vector force, vector torque, integer local) + void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local); + //wiki: vector llGetVel() + LSL_Types.Vector3 llGetVel(); + //wiki: vector llGetAccel() + LSL_Types.Vector3 llGetAccel(); + //wiki: vector llGetOmega() + LSL_Types.Vector3 llGetOmega(); + //wiki: double llGetTimeOfDay() + double llGetTimeOfDay(); + //wiki: double llGetWallclock() + double llGetWallclock(); + //wiki: double llGetTime() + double llGetTime(); + //wiki: llResetTime() + void llResetTime(); + //wiki: double llGetAndResetTime() + double llGetAndResetTime(); + //wiki (deprecated) llSound(string sound, double volume, integer queue, integer loop) + void llSound(); + //wiki: llPlaySound(string sound, double volume) + void llPlaySound(string sound, double volume); + //wiki: llLoopSound(string sound, double volume) + void llLoopSound(string sound, double volume); + //wiki: llLoopSoundMaster(string sound, double volume) + void llLoopSoundMaster(string sound, double volume); + //wiki: llLoopSoundSlave(string sound, double volume) + void llLoopSoundSlave(string sound, double volume); + //wiki llPlaySoundSlave(string sound, double volume) + void llPlaySoundSlave(string sound, double volume); + //wiki: llTriggerSound(string sound, double volume) + void llTriggerSound(string sound, double volume); + //wiki: llStopSound() + void llStopSound(); + //wiki: llPreloadSound(string sound) + void llPreloadSound(string sound); + //wiki: string llGetSubString(string src, integer start, integer end) + string llGetSubString(string src, int start, int end); + //wiki: string llDeleteSubString(string src, integer start, integer end) + string llDeleteSubString(string src, int start, int end); + //wiki string llInsertString(string dst, integer position, string src) + string llInsertString(string dst, int position, string src); + //wiki: string llToUpper(string source) + string llToUpper(string source); + //wiki: string llToLower(string source) + string llToLower(string source); + //wiki: integer llGiveMoney(key destination, integer amount) + int llGiveMoney(string destination, int amount); + //wiki: (deprecated) + void llMakeExplosion(); + //wiki: (deprecated) + void llMakeFountain(); + //wiki: (deprecated) + void llMakeSmoke(); + //wiki: (deprecated) + void llMakeFire(); + //wiki: llRezObject(string inventory, vector pos, vector rel, rotation rot, integer param) + void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Quaternion rot, int param); + //wiki: llLookAt(vector target, double strength, double damping) + void llLookAt(LSL_Types.Vector3 target, double strength, double damping); + //wiki: llStopLookAt() + void llStopLookAt(); + //wiki: llSetTimerEvent(double sec) + void llSetTimerEvent(double sec); + //wiki: llSleep(double sec) + void llSleep(double sec); + //wiki: double llGetMass() + double llGetMass(); + //wiki: llCollisionFilter(string name, key id, integer accept) + void llCollisionFilter(string name, string id, int accept); + //wiki: llTakeControls(integer controls, integer accept, integer pass_on) + void llTakeControls(int controls, int accept, int pass_on); + //wiki: llReleaseControls() + void llReleaseControls(); + //wiki: llAttachToAvatar(integer attachment) + void llAttachToAvatar(int attachment); + //wiki: llDetachFromAvatar() + void llDetachFromAvatar(); + //wiki: (deprecated) llTakeCamera() + void llTakeCamera(); + //wiki: (deprecated) llReleaseCamera() + void llReleaseCamera(); + //wiki: key llGetOwner() + string llGetOwner(); + //wiki: llInstantMessage(key user, string message) + void llInstantMessage(string user, string message); + //wiki: llEmail(string address, string subject, string message) + void llEmail(string address, string subject, string message); + //wiki: llGetNextEmail(string address, string subject) + void llGetNextEmail(string address, string subject); + //wiki: key llGetKey() + string llGetKey(); + //wiki: llSetBuoyancy(double buoyancy) + void llSetBuoyancy(double buoyancy); + //wiki: llSetHoverHeight(double height, integer water, double tau) + void llSetHoverHeight(double height, int water, double tau); + //wiki: llStopHover + void llStopHover(); + //wiki: llMinEventDelay(double delay) + void llMinEventDelay(double delay); + //wiki: (deprecated) llSoundPreload() + void llSoundPreload(); + //wiki: llRotLookAt(rotation target, double strength, double damping) + void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping); + //wiki: integer llStringLength(string str) + int llStringLength(string str); + //wiki: llStartAnimation(string anim) + void llStartAnimation(string anim); + //wiki: llStopAnimation(string anim) + void llStopAnimation(string anim); + //wiki: (deprecated) llPointAt + void llPointAt(); + //wiki: (deprecated) llStopPointAt + void llStopPointAt(); + //wiki: llTargetOmega(vector axis, double spinrate, double gain) + void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain); + //wiki: integer llGetStartParameter() + int llGetStartParameter(); + //wiki: llGodLikeRezObject(key inventory, vector pos) + void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos); + //wiki: llRequestPermissions(key agent, integer perm) + void llRequestPermissions(string agent, int perm); + //wiki: key llGetPermissionsKey() + string llGetPermissionsKey(); + //wiki: integer llGetPermissions() + int llGetPermissions(); + //wiki integer llGetLinkNumber() + int llGetLinkNumber(); + //wiki: llSetLinkColor(integer linknumber, vector color, integer face) + void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face); + //wiki: llCreateLink(key target, integer parent) + void llCreateLink(string target, int parent); + //wiki: llBreakLink(integer linknum) + void llBreakLink(int linknum); + //wiki: llBreakAllLinks() + void llBreakAllLinks(); + //wiki: key llGetLinkKey(integer linknum) + string llGetLinkKey(int linknum); + //wiki: llGetLinkName(integer linknum) + string llGetLinkName(int linknum); + //wiki: integer llGetInventoryNumber(integer type) + int llGetInventoryNumber(int type); + //wiki: string llGetInventoryName(integer type, integer number) + string llGetInventoryName(int type, int number); + //wiki: llSetScriptState(string name, integer run) + void llSetScriptState(string name, int run); + //wiki: double llGetEnergy() + double llGetEnergy(); + //wiki: llGiveInventory(key destination, string inventory) + void llGiveInventory(string destination, string inventory); + //wiki: llRemoveInventory(string item) + void llRemoveInventory(string item); + //wiki: llSetText(string text, vector color, double alpha) + void llSetText(string text, LSL_Types.Vector3 color, double alpha); + //wiki: double llWater(vector offset) + double llWater(LSL_Types.Vector3 offset); + //wiki: llPassTouches(integer pass) + void llPassTouches(int pass); + //wiki: key llRequestAgentData(key id, integer data) + string llRequestAgentData(string id, int data); + //wiki: key llRequestInventoryData(string name) + string llRequestInventoryData(string name); + //wiki: llSetDamage(double damage) + void llSetDamage(double damage); + //wiki: llTeleportAgentHome(key agent) + void llTeleportAgentHome(string agent); + //wiki: llModifyLand(integer action, integer brush) + void llModifyLand(int action, int brush); + //wiki: llCollisionSound(string impact_sound, double impact_volume) + void llCollisionSound(string impact_sound, double impact_volume); + //wiki: llCollisionSprite(string impact_sprite) + void llCollisionSprite(string impact_sprite); + //wiki: string llGetAnimation(key id) + string llGetAnimation(string id); + //wiki: llResetScript() + void llResetScript(); + //wiki: llMessageLinked(integer linknum, integer num, string str, key id) + void llMessageLinked(int linknum, int num, string str, string id); + //wiki: llPushObject(key target, vector impulse, vector ang_impulse, integer local) + void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local); + //wiki: llPassCollisions(integer pass) + void llPassCollisions(int pass); + //wiki: string llGetScriptName() + string llGetScriptName(); + //wiki: integer llGetNumberOfSides() + int llGetNumberOfSides(); + //wiki: rotation llAxisAngle2Rot(vector axis, double angle) + LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle); + //wiki: vector llRot2Axis(rotation rot) + LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot); + void llRot2Angle(); + //wiki: double llAcos(double val) + double llAcos(double val); + //wiki: double llAsin(double val) + double llAsin(double val); + //wiki: double llAngleBetween(rotation a, rotation b) + double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b); + //wiki: string llGetInventoryKey(string name) + string llGetInventoryKey(string name); + //wiki: llAllowInventoryDrop(integer add) + void llAllowInventoryDrop(int add); + //wiki: vector llGetSunDirection() + LSL_Types.Vector3 llGetSunDirection(); + //wiki: vector llGetTextureOffset(integer face) + LSL_Types.Vector3 llGetTextureOffset(int face); + //wiki: vector llGetTextureScale(integer side) + LSL_Types.Vector3 llGetTextureScale(int side); + //wiki: double llGetTextureRot(integer side) + double llGetTextureRot(int side); + //wiki: integer llSubStringIndex(string source, string pattern) + int llSubStringIndex(string source, string pattern); + //wiki: key llGetOwnerKey(key id) + string llGetOwnerKey(string id); + //wiki: vector llGetCenterOfMass() + LSL_Types.Vector3 llGetCenterOfMass(); + //wiki: list llListSort(list src, integer stride, integer ascending) + LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending); + //integer llGetListLength(list src) + int llGetListLength(LSL_Types.list src); + //wiki: integer llList2Integer(list src, integer index) + int llList2Integer(LSL_Types.list src, int index); + //wiki: double llList2double(list src, integer index) + double llList2Float(LSL_Types.list src, int index); + double osList2Double(LSL_Types.list src, int index); + //wiki: string llList2String(list src, integer index) + string llList2String(LSL_Types.list src, int index); + //wiki: key llList2Key(list src, integer index) + string llList2Key(LSL_Types.list src, int index); + //wiki: vector llList2Vector(list src, integer index) + LSL_Types.Vector3 llList2Vector(LSL_Types.list src, int index); + //wiki rotation llList2Rot(list src, integer index) + LSL_Types.Quaternion llList2Rot(LSL_Types.list src, int index); + //wiki: list llList2List(list src, integer start, integer end) + LSL_Types.list llList2List(LSL_Types.list src, int start, int end); + //wiki: llDeleteSubList(list src, integer start, integer end) + LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end); + //wiki: integer llGetListEntryType( list src, integer index ) + int llGetListEntryType(LSL_Types.list src, int index); + //wiki: string llList2CSV( list src ) + string llList2CSV(LSL_Types.list src); + //wiki: list llCSV2List( string src ) + LSL_Types.list llCSV2List(string src); + //wiki: list llListRandomize( list src, integer stride ) + LSL_Types.list llListRandomize(LSL_Types.list src, int stride); + //wiki: list llList2ListStrided( list src, integer start, integer end, integer stride ) + LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride); + //wiki: vector llGetRegionCorner( ) + LSL_Types.Vector3 llGetRegionCorner(); + //wiki: list llListInsertList( list dest, list src, integer start ) + LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start); + //wiki: integer llListFindList( list src, list test ) + int llListFindList(LSL_Types.list src, LSL_Types.list test); + //wiki: string llGetObjectName() + string llGetObjectName(); + //wiki: llSetObjectName(string name) + void llSetObjectName(string name); + //wiki: string llGetDate() + string llGetDate(); + //wiki: integer llEdgeOfWorld(vector pos, vector dir) + int llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir); + //wiki: integer llGetAgentInfo(key id) + int llGetAgentInfo(string id); + //wiki: llAdjustSoundVolume(double volume) + void llAdjustSoundVolume(double volume); + //wiki: llSetSoundQueueing(integer queue) + void llSetSoundQueueing(int queue); + //wiki: llSetSoundRadius(double radius) + void llSetSoundRadius(double radius); + //wiki: string llKey2Name(key id) + string llKey2Name(string id); + //wiki: llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, double start, double length, double rate) + void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate); + //wiki: llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west) + void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east, + LSL_Types.Vector3 bottom_south_west); + + //wiki: llEjectFromLand(key pest) + void llEjectFromLand(string pest); + LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers); + //wiki: integer llOverMyLand(key id) + int llOverMyLand(string id); + //wiki: key llGetLandOwnerAt(vector pos) + string llGetLandOwnerAt(LSL_Types.Vector3 pos); + //wiki: key llGetNotecardLine(string name, integer line) + string llGetNotecardLine(string name, int line); + //wiki: vector llGetAgentSize(key id) + LSL_Types.Vector3 llGetAgentSize(string id); + //wiki: integer llSameGroup(key agent) + int llSameGroup(string agent); + //wiki: llUnSit(key id) + void llUnSit(string id); + //wiki: vector llGroundSlope(vector offset) + LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset); + //wiki: vector llGroundNormal(vector offset) + LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset); + //wiki: vector llGroundContour(vector offset) + LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset); + //wiki: integer llGetAttached() + int llGetAttached(); + //wiki: integer llGetFreeMemory() + int llGetFreeMemory(); + //wiki: string llGetRegionName() + string llGetRegionName(); + //wiki: double llGetRegionTimeDilation() + double llGetRegionTimeDilation(); + //wiki: double llGetRegionFPS() + double llGetRegionFPS(); + //wiki: llParticleSystem(List rules + void llParticleSystem(LSL_Types.list rules); + //wiki: llGroundRepel(double height, integer water, double tau) + void llGroundRepel(double height, int water, double tau); + void llGiveInventoryList(); + //wiki: llSetVehicleType(integer type) + void llSetVehicleType(int type); + //wiki: llSetVehicledoubleParam(integer param, double value) + void llSetVehicledoubleParam(int param, double value); + //wiki: llSetVehicleVectorParam(integer param, vector vec) + void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec); + //wiki: llSetVehicleRotationParam(integer param, rotation rot) + void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot); + //wiki: llSetVehicleFlags(integer flags) + void llSetVehicleFlags(int flags); + //wiki: llRemoveVehicleFlags(integer flags) + void llRemoveVehicleFlags(int flags); + //wiki: llSitTarget(vector offset, rotation rot) + void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot); + //wiki key llAvatarOnSitTarget() + string llAvatarOnSitTarget(); + //wiki: llAddToLandPassList(key avatar, double hours) + void llAddToLandPassList(string avatar, double hours); + //wiki: llSetTouchText(string text) + void llSetTouchText(string text); + //wiki: llSetSitText(string text) + void llSetSitText(string text); + //wiki: llSetCameraEyeOffset(vector offset) + void llSetCameraEyeOffset(LSL_Types.Vector3 offset); + //wiki: llSeteCameraAtOffset(vector offset) + void llSetCameraAtOffset(LSL_Types.Vector3 offset); + // + string llDumpList2String(LSL_Types.list src, string seperator); + //wiki: integer llScriptDanger(vector pos) + void llScriptDanger(LSL_Types.Vector3 pos); + //wiki: llDialog( key avatar, string message, list buttons, integer chat_channel ) + void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel); + //wiki: llVolumeDetect(integer detect) + void llVolumeDetect(int detect); + //wiki: llResetOtherScript(string name) + void llResetOtherScript(string name); + //wiki: integer llGetScriptState(string name) + int llGetScriptState(string name); + //wiki: (deprecated) + void llRemoteLoadScript(); + //wiki: llSetRemoteScriptAccessPin(integer pin) + void llSetRemoteScriptAccessPin(int pin); + //wiki: llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param) + void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param); + //wiki: llOpenRemoteDataChannel() + void llOpenRemoteDataChannel(); + //wiki: key llSendRemoteData(key channel, string dest, integer idata, string sdata) + string llSendRemoteData(string channel, string dest, int idata, string sdata); + //wiki: llRemoteDataReply(key channel, key message_id, string sdata, integer idata) + void llRemoteDataReply(string channel, string message_id, string sdata, int idata); + //wiki: llCloseRemoteDataChannel(key channel) + void llCloseRemoteDataChannel(string channel); + //wiki: string llMD5String(string src, integer nonce) + string llMD5String(string src, int nonce); + //wiki: llSetPrimitiveParams( list rules ) + void llSetPrimitiveParams(LSL_Types.list rules); + //wiki: string llStringToBase64(string str) + string llStringToBase64(string str); + //wiki: string llBase64ToString(string str) + string llBase64ToString(string str); + //wiki: (deprecated) + void llXorBase64Strings(); + //wiki: llRemoteDataSetRegion() + void llRemoteDataSetRegion(); + //wiki: double llLog10(double val) + double llLog10(double val); + //wiki: double llLog(double val) + double llLog(double val); + //wiki: list llGetAnimationList( key id ) + LSL_Types.list llGetAnimationList(string id); + //wiki: llSetParcelMusicURL(string url) + void llSetParcelMusicURL(string url); + //wiki: vector llGetRootPosition() + LSL_Types.Vector3 llGetRootPosition(); + //wiki: rotation llGetRootRotation() + LSL_Types.Quaternion llGetRootRotation(); + //wiki: string llGetObjectDesc() + string llGetObjectDesc(); + //wiki: llSetObjectDesc(string desc) + void llSetObjectDesc(string desc); + //wiki: key llGetCreator() + string llGetCreator(); + //wiki: string llGetTimestamp() + string llGetTimestamp(); + //wiki: llSetLinkAlpha(integer linknumber, double alpha, integer face) + void llSetLinkAlpha(int linknumber, double alpha, int face); + //wiki: integer llGetNumberOfPrims() + int llGetNumberOfPrims(); + //wiki: key llGetNumberOfNotecardLines(string name) + string llGetNumberOfNotecardLines(string name); + //wiki: list llGetBoundingBox( key object ) + LSL_Types.list llGetBoundingBox(string obj); + //wiki: vector llGetGeometricCenter() + LSL_Types.Vector3 llGetGeometricCenter(); + void llGetPrimitiveParams(); + //wiki: string llIntegerToBase64(integer number) + string llIntegerToBase64(int number); + //wiki integer llBase64ToInteger(string str) + int llBase64ToInteger(string str); + //wiki: double llGetGMTclock() + double llGetGMTclock(); + //wiki: string llGetSimulatorHostname() + string llGetSimulatorHostname(); + //llSetLocalRot(rotation rot) + void llSetLocalRot(LSL_Types.Quaternion rot); + //wiki: list llParseStringKeepNulls( string src, list separators, list spacers ) + LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers); + //wiki: llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, integer param) + void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity, + LSL_Types.Quaternion rot, int param); + + //wiki: integer llGetObjectPermMask(integer mask) + int llGetObjectPermMask(int mask); + //wiki: llSetObjectPermMask(integer mask, integer value) + void llSetObjectPermMask(int mask, int value); + //wiki integer llGetInventoryPermMask(string item, integer mask) + void llGetInventoryPermMask(string item, int mask); + //wiki: llSetInventoryPermMask(string item, integer mask, integer value) + void llSetInventoryPermMask(string item, int mask, int value); + //wiki: key llGetInventoryCreator(string item) + string llGetInventoryCreator(string item); + //wiki: llOwnerSay(string msg) + void llOwnerSay(string msg); + //wiki: key llRequestSimulatorData(string simulator, integer data) + void llRequestSimulatorData(string simulator, int data); + //wiki: llForceMouselook(integer mouselook) + void llForceMouselook(int mouselook); + //wiki: double llGetObjectMass(key id) + double llGetObjectMass(string id); + LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end); + //wiki: llLoadURL(key avatar_id, string message, string url) + void llLoadURL(string avatar_id, string message, string url); + //wiki: llParcelMediaCommandList( list commandList ) + void llParcelMediaCommandList(LSL_Types.list commandList); + void llParcelMediaQuery(); + //wiki integer llModPow(integer a, integer b, integer c) + int llModPow(int a, int b, int c); + //wiki: integer llGetInventoryType(string name) + int llGetInventoryType(string name); + //wiki: llSetPayPrice( integer price, list quick_pay_buttons ) + void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons); + //wiki: vector llGetCameraPos() + LSL_Types.Vector3 llGetCameraPos(); + //wiki rotation llGetCameraRot() + LSL_Types.Quaternion llGetCameraRot(); + //wiki: (deprecated) + void llSetPrimURL(); + //wiki: (deprecated) + void llRefreshPrimURL(); + //wiki: string llEscapeURL(string url) + string llEscapeURL(string url); + //wiki: string llUnescapeURL(string url) + string llUnescapeURL(string url); + //wiki: llMapDestination(string simname, vector pos, vector look_at) + void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at); + //wiki: llAddToLandBanList(key avatar, double hours) + void llAddToLandBanList(string avatar, double hours); + //wiki: llRemoveFromLandPassList(key avatar) + void llRemoveFromLandPassList(string avatar); + //wiki: llRemoveFromLandBanList(key avatar) + void llRemoveFromLandBanList(string avatar); + //wiki: llSetCameraParams( list rules ) + void llSetCameraParams(LSL_Types.list rules); + //wiki: llClearCameraParams() + void llClearCameraParams(); + //wiki: double llListStatistics( integer operation, list src ) + double llListStatistics(int operation, LSL_Types.list src); + //wiki: integer llGetUnixTime() + int llGetUnixTime(); + //wiki: integer llGetParcelFlags(vector pos) + int llGetParcelFlags(LSL_Types.Vector3 pos); + //wiki: integer llGetRegionFlags() + int llGetRegionFlags(); + //wiki: string llXorBase64StringsCorrect(string str1, string str2) + string llXorBase64StringsCorrect(string str1, string str2); + string llHTTPRequest(string url, LSL_Types.list parameters, string body); + //wiki: llResetLandBanList() + void llResetLandBanList(); + //wiki: llResetLandPassList() + void llResetLandPassList(); + //wiki integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide) + int llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide); + //wiki: list llGetParcelPrimOwners( vector pos ) + LSL_Types.list llGetParcelPrimOwners(LSL_Types.Vector3 pos); + //wiki: integer llGetObjectPrimCount(key object_id) + int llGetObjectPrimCount(string object_id); + //wiki: integer llGetParcelMaxPrims( vector pos, integer sim_wide ) + int llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide); + //wiki list llGetParcelDetails(vector pos, list params) + LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param); + string llStringTrim(string src, int type); + //OpenSim functions + string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, int timer); + double osTerrainGetHeight(int x, int y); + int osTerrainSetHeight(int x, int y, double val); + int osRegionRestart(double seconds); + void osRegionNotice(string msg); + bool osConsoleCommand(string Command); + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs b/trunk/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs new file mode 100644 index 0000000000..3cc45bad35 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs @@ -0,0 +1,1070 @@ +/* +* 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; +using System.Text.RegularExpressions; +using System.Collections; + +namespace OpenSim.Region.ScriptEngine.Common +{ + [Serializable] + public partial class LSL_Types + { + + // Types are kept is separate .dll to avoid having to add whatever .dll it is in it to script AppDomain + + [Serializable] + public struct Vector3 + { + public double x; + public double y; + public double z; + + #region Constructors + + public Vector3(Vector3 vector) + { + x = (float)vector.x; + y = (float)vector.y; + z = (float)vector.z; + } + + public Vector3(double X, double Y, double Z) + { + x = X; + y = Y; + z = Z; + } + + public Vector3(string str) + { + str = str.Replace('<', ' '); + str = str.Replace('>', ' '); + string[] tmps = str.Split(new Char[] { ',', '<', '>' }); + bool res; + res = Double.TryParse(tmps[0], out x); + res = res & Double.TryParse(tmps[1], out y); + res = res & Double.TryParse(tmps[2], out z); + } + + #endregion + + #region Overriders + + public override string ToString() + { + return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ">"; + } + + public static explicit operator string(Vector3 vec) + { + return "<" + vec.x.ToString() + ", " + vec.y.ToString() + ", " + vec.z.ToString() + ">"; + } + + public static bool operator ==(Vector3 lhs, Vector3 rhs) + { + return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); + } + + public static bool operator !=(Vector3 lhs, Vector3 rhs) + { + return !(lhs == rhs); + } + + public override int GetHashCode() + { + return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode()); + } + + public override bool Equals(object o) + { + if (!(o is Vector3)) return false; + + Vector3 vector = (Vector3)o; + + return (x == vector.x && x == vector.x && z == vector.z); + } + + #endregion + + #region Vector & Vector Math + + // Vector-Vector Math + public static Vector3 operator +(Vector3 lhs, Vector3 rhs) + { + return new Vector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); + } + + public static Vector3 operator -(Vector3 lhs, Vector3 rhs) + { + return new Vector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); + } + + public static Vector3 operator *(Vector3 lhs, Vector3 rhs) + { + return new Vector3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); + } + + public static Vector3 operator %(Vector3 v1, Vector3 v2) + { + //Cross product + Vector3 tv; + tv.x = (v1.y * v2.z) - (v1.z * v2.y); + tv.y = (v1.z * v2.x) - (v1.x * v2.z); + tv.z = (v1.x * v2.y) - (v1.y * v2.x); + return tv; + } + + #endregion + + #region Vector & Float Math + + // Vector-Float and Float-Vector Math + public static Vector3 operator *(Vector3 vec, float val) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator *(float val, Vector3 vec) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator /(Vector3 v, float f) + { + v.x = v.x / f; + v.y = v.y / f; + v.z = v.z / f; + return v; + } + + #endregion + + #region Vector & Double Math + + public static Vector3 operator *(Vector3 vec, double val) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator *(double val, Vector3 vec) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator /(Vector3 v, double f) + { + v.x = v.x / f; + v.y = v.y / f; + v.z = v.z / f; + return v; + } + + #endregion + + #region Vector & Rotation Math + + // Vector-Rotation Math + public static Vector3 operator *(Vector3 v, Quaternion r) + { + Quaternion vq = new Quaternion(v.x, v.y, v.z, 0); + Quaternion nq = new Quaternion(-r.x, -r.y, -r.z, r.s); + + Quaternion result = (r * vq) * nq; + + return new Vector3(result.x, result.y, result.z); + } + + // I *think* this is how it works.... + public static Vector3 operator /(Vector3 vec, Quaternion quat) + { + quat.s = -quat.s; + Quaternion vq = new Quaternion(vec.x, vec.y, vec.z, 0); + Quaternion nq = new Quaternion(-quat.x, -quat.y, -quat.z, quat.s); + + Quaternion result = (quat * vq) * nq; + + return new Vector3(result.x, result.y, result.z); + } + + #endregion + + #region Static Helper Functions + + public static double Dot(Vector3 v1, Vector3 v2) + { + return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z); + } + + public static Vector3 Cross(Vector3 v1, Vector3 v2) + { + return new Vector3 + ( + v1.y * v2.z - v1.z * v2.y, + v1.z * v2.x - v1.x * v2.z, + v1.x * v2.y - v1.y * v2.x + ); + } + + public static float Mag(Vector3 v) + { + return (float)Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); + } + + public static Vector3 Norm(Vector3 vector) + { + float mag = Mag(vector); + return new Vector3(vector.x / mag, vector.y / mag, vector.z / mag); + } + + #endregion + } + + [Serializable] + public struct Quaternion + { + public double x; + public double y; + public double z; + public double s; + + #region Constructors + + public Quaternion(Quaternion Quat) + { + x = (float)Quat.x; + y = (float)Quat.y; + z = (float)Quat.z; + s = (float)Quat.s; + } + + public Quaternion(double X, double Y, double Z, double S) + { + x = X; + y = Y; + z = Z; + s = S; + } + + public Quaternion(string str) + { + str = str.Replace('<', ' '); + str = str.Replace('>', ' '); + string[] tmps = str.Split(new Char[] { ',', '<', '>' }); + bool res; + res = Double.TryParse(tmps[0], out x); + res = res & Double.TryParse(tmps[1], out y); + res = res & Double.TryParse(tmps[2], out z); + res = res & Double.TryParse(tmps[3], out s); + } + + #endregion + + #region Overriders + + public override int GetHashCode() + { + return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ s.GetHashCode()); + } + + public override bool Equals(object o) + { + if (!(o is Quaternion)) return false; + + Quaternion quaternion = (Quaternion)o; + + return x == quaternion.x && y == quaternion.y && z == quaternion.z && s == quaternion.s; + } + + public override string ToString() + { + return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ", " + s.ToString() + ">"; + } + + public static explicit operator string(Quaternion r) + { + return "<" + r.x.ToString() + ", " + r.y.ToString() + ", " + r.z.ToString() + ", " + r.s.ToString() + ">"; + } + + public static bool operator ==(Quaternion lhs, Quaternion rhs) + { + // Return true if the fields match: + return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.s == rhs.s; + } + + public static bool operator !=(Quaternion lhs, Quaternion rhs) + { + return !(lhs == rhs); + } + + #endregion + + public static Quaternion operator *(Quaternion a, Quaternion b) + { + Quaternion c; + c.x = a.s * b.x + a.x * b.s + a.y * b.z - a.z * b.y; + c.y = a.s * b.y + a.y * b.s + a.z * b.x - a.x * b.z; + c.z = a.s * b.z + a.z * b.s + a.x * b.y - a.y * b.x; + c.s = a.s * b.s - a.x * b.x - a.y * b.y - a.z * b.z; + return c; + } + } + + [Serializable] + public class list + { + private object[] m_data; + + public list(params object[] args) + { + m_data = new object[args.Length]; + m_data = args; + } + + public int Length + { + get { return m_data.Length; } + } + + public object[] Data + { + get { return m_data; } + } + + public static list operator +(list a, list b) + { + object[] tmp; + tmp = new object[a.Length + b.Length]; + a.Data.CopyTo(tmp, 0); + b.Data.CopyTo(tmp, a.Length); + return new list(tmp); + } + + public void Add(object o) + { + object[] tmp; + tmp = new object[m_data.Length + 1]; + m_data.CopyTo(tmp, 0); + tmp[m_data.Length] = o; + m_data = tmp; + } + + public bool Contains(object o) + { + bool ret = false; + foreach (object i in Data) + { + if (i == o) + { + ret = true; + break; + } + } + return ret; + } + + public list GetSublist(int start, int end) + { + Console.WriteLine("GetSublist(" + start.ToString() + "," + end.ToString() + ")"); + object[] ret; + // Take care of neg start or end's + if (start < 0) + { + start = m_data.Length + start; + } + if (end < 0) + { + end = m_data.Length + end; + } + + // Case start <= end + if (start <= end) + { + if (start >= m_data.Length) + { + return new list(); + } + if (end >= m_data.Length) + { + end = m_data.Length - 1; + } + ret = new object[end - start + 1]; + Array.Copy(m_data, start, ret, 0, end - start + 1); + return new list(ret); + } + else + { + if (start >= m_data.Length) + { + return GetSublist(0, end); + } + if (end >= m_data.Length) + { + return new list(); + } + // end < start + //ret = new object[m_data.Length - Math.Abs(end - start + 1)]; + //Array.Copy(m_data, 0, ret, m_data.Length - start, end + 1); + //Array.Copy(m_data, start, ret, 0, m_data.Length - start); + return GetSublist(0, end) + GetSublist(start, Data.Length - 1); + //return new list(ret); + } + } + + #region CSV Methods + + public static list FromCSV(string csv) + { + return new list(csv.Split(',')); + } + + public string ToCSV() + { + string ret = ""; + foreach(object o in this.Data) + { + if(ret == "") + { + ret = o.ToString(); + } + else + { + ret = ret + ", " + o.ToString(); + } + } + return ret; + } + #endregion + + #region Statistic Methods + + public double Min() + { + double minimum = double.PositiveInfinity; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + if (entry < minimum) minimum = entry; + } + } + return minimum; + } + + public double Max() + { + double maximum = double.NegativeInfinity; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + if (entry > maximum) maximum = entry; + } + } + return maximum; + } + + public double Range() + { + return (this.Max() / this.Min()); + } + + public int NumericLength() + { + int count = 0; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + count++; + } + } + return count; + } + + public static list ToDoubleList(list src) + { + list ret = new list(); + double entry; + for (int i = 0; i < src.Data.Length - 1; i++) + { + if (double.TryParse(src.Data[i].ToString(), out entry)) + { + ret.Add(entry); + } + } + return ret; + } + + public double Sum() + { + double sum = 0; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + sum = sum + entry; + } + } + return sum; + } + + public double SumSqrs() + { + double sum = 0; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + sum = sum + Math.Pow(entry, 2); + } + } + return sum; + } + + public double Mean() + { + return (this.Sum() / this.NumericLength()); + } + + public void NumericSort() + { + IComparer Numeric = new NumericComparer(); + Array.Sort(Data, Numeric); + } + + public void AlphaSort() + { + IComparer Alpha = new AlphaCompare(); + Array.Sort(Data, Alpha); + } + + public double Median() + { + return Qi(0.5); + } + + public double GeometricMean() + { + double ret = 1.0; + list nums = list.ToDoubleList(this); + for (int i = 0; i < nums.Data.Length; i++) + { + ret *= (double)nums.Data[i]; + } + return Math.Exp(Math.Log(ret) / (double)nums.Data.Length); + } + + public double HarmonicMean() + { + double ret = 0.0; + list nums = list.ToDoubleList(this); + for (int i = 0; i < nums.Data.Length; i++) + { + ret += 1.0 / (double)nums.Data[i]; + } + return ((double)nums.Data.Length / ret); + } + + public double Variance() + { + double s = 0; + list num = list.ToDoubleList(this); + for (int i = 0; i < num.Data.Length; i++) + { + s += Math.Pow((double)num.Data[i], 2); + } + return (s - num.Data.Length * Math.Pow(num.Mean(), 2)) / (num.Data.Length - 1); + } + + public double StdDev() + { + return Math.Sqrt(this.Variance()); + } + + public double Qi(double i) + { + list j = this; + j.NumericSort(); + double ret; + if (Math.Ceiling(this.Length * i) == this.Length * i) + { + return (double)((double)j.Data[(int)(this.Length * i - 1)] + (double)j.Data[(int)(this.Length * i)]) / 2; + } + else + { + return (double)j.Data[((int)(Math.Ceiling(this.Length * i))) - 1]; + } + } + + #endregion + + public string ToPrettyString() + { + string output; + if (m_data.Length == 0) + { + return "[]"; + } + output = "["; + foreach (object o in m_data) + { + if (o is System.String) + { + output = output + "\"" + o + "\", "; + } + else + { + output = output + o.ToString() + ", "; + } + } + output = output.Substring(0, output.Length - 2); + output = output + "]"; + return output; + } + + public class AlphaCompare : IComparer + { + int IComparer.Compare(object x, object y) + { + return string.Compare(x.ToString(), y.ToString()); + } + } + + public class NumericComparer : IComparer + { + int IComparer.Compare(object x, object y) + { + double a; + double b; + if (!double.TryParse(x.ToString(), out a)) + { + a = 0.0; + } + if (!double.TryParse(y.ToString(), out b)) + { + b = 0.0; + } + if (a < b) + { + return -1; + } + else if (a == b) + { + return 0; + } + else + { + return 1; + } + } + } + + public override string ToString() + { + string output; + output = String.Empty; + if (m_data.Length == 0) + { + return String.Empty; + } + foreach (object o in m_data) + { + output = output + o.ToString(); + } + return output; + + } + + public static explicit operator string(list l) + { + string output; + output = String.Empty; + if (l.m_data.Length == 0) + { + return String.Empty; + } + foreach (object o in l.m_data) + { + output = output + o.ToString(); + } + return output; + } + } + + // + // BELOW IS WORK IN PROGRESS... IT WILL CHANGE, SO DON'T USE YET! :) + // + + public struct StringTest + { + // Our own little string + internal string actualString; + public static implicit operator bool(StringTest mString) + { + if (mString.actualString.Length == 0) + return true; + return false; + } + public override string ToString() + { + return actualString; + } + + } + + [Serializable] + public struct key + { + public string value; + + #region Constructors + public key(string s) + { + value = s; + } + + #endregion + + #region Methods + + static public bool Parse2Key(string s) + { + Regex isuuid = new Regex(@"^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", RegexOptions.Compiled); + if (isuuid.IsMatch(s)) + { + return true; + } + else + { + return false; + } + } + + #endregion + + #region Operators + + static public implicit operator System.Boolean(key k) + { + if (k.value.Length == 0) + { + return false; + } + + if (k.value == "00000000-0000-0000-0000-000000000000") + { + return false; + } + Regex isuuid = new Regex(@"^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", RegexOptions.Compiled); + if (isuuid.IsMatch(k.value)) + { + return true; + } + else + { + return false; + } + } + + static public implicit operator key(string s) + { + return new key(s); + } + + static public implicit operator System.String(key k) + { + return k.value; + } + + public static bool operator ==(key k1, key k2) + { + return k1.value == k2.value; + } + public static bool operator !=(key k1, key k2) + { + return k1.value != k2.value; + } + + #endregion + + #region Overriders + + public override bool Equals(object o) + { + if (o is String) + { + string s = (string)o; + return s == this.value; + } + if (o is key) + { + key k = (key)o; + return this.value == k.value; + } + return false; + } + + public override int GetHashCode() + { + return value.GetHashCode(); + } + + #endregion + } + + [Serializable] + public struct LSLString + { + public string m_string; + #region Constructors + public LSLString(string s) + { + m_string = s; + } + #endregion + + #region Operators + static public implicit operator System.Boolean(LSLString s) + { + if (s.m_string.Length == 0) + { + return false; + } + else + { + return true; + } + } + + static public implicit operator System.String(LSLString s) + { + return s.m_string; + } + + static public implicit operator LSLString(string s) + { + return new LSLString(s); + } + + // Commented out: + /* + [echo] Build Directory is /home/tedd/opensim/trunk/OpenSim/Region/ScriptEngine/Common/bin/Debug + [csc] Compiling 5 files to '/home/tedd/opensim/trunk/OpenSim/Region/ScriptEngine/Common/bin/Debug/OpenSim.Region.ScriptEngine.Common.dll'. + [csc] error CS0121: The call is ambiguous between the following methods or properties: `OpenSim.Region.ScriptEngine.Common.LSL_Types.LSLString.operator /(OpenSim.Region.ScriptEngine.Common.LSL_Types.LSLString, OpenSim.Region.ScriptEngine.Common.LSL_Types.LSLString)' and `string.operator /(string, string)' + [csc] /home/tedd/opensim/trunk/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs(602,32): (Location of the symbol related to previous error) + [csc] /usr/lib/mono/2.0/mscorlib.dll (Location of the symbol related to previous error) + [csc] Compilation failed: 1 error(s), 0 warnings + */ + //public static bool operator ==(LSLString s1, LSLString s2) + //{ + // return s1.m_string == s2.m_string; + //} + //public static bool operator !=(LSLString s1, LSLString s2) + //{ + // return s1.m_string != s2.m_string; + //} + #endregion + + #region Overriders + public override bool Equals(object o) + { + if (o is String) + { + string s = (string)o; + return s == this.m_string; + } + if (o is key) + { + key k = (key)o; + return this.m_string == k.value; + } + if (o is LSLString) + { + LSLString s = (string)o; + return this.m_string == s; + } + return false; + } + + public override int GetHashCode() + { + return m_string.GetHashCode(); + } + + #endregion + + #region " Standard string functions " + //Clone,CompareTo,Contains + //CopyTo,EndsWith,Equals,GetEnumerator,GetHashCode,GetType,GetTypeCode + //IndexOf,IndexOfAny,Insert,IsNormalized,LastIndexOf,LastIndexOfAny + //Length,Normalize,PadLeft,PadRight,Remove,Replace,Split,StartsWith,Substring,ToCharArray,ToLowerInvariant + //ToString,ToUpper,ToUpperInvariant,Trim,TrimEnd,TrimStart + public bool Contains(string value) { return m_string.Contains(value); } + public int IndexOf(string value) { return m_string.IndexOf(value); } + public int Length { get { return m_string.Length; } } + + + #endregion + } + + [Serializable] + public struct LSLInteger + { + public int value; + + #region Constructors + public LSLInteger(int i) + { + value = i; + } + + public LSLInteger(double d) + { + value = (int)d; + } + + #endregion + static public implicit operator System.Int32(LSLInteger i) + { + return i.value; + } + + static public implicit operator System.Boolean(LSLInteger i) + { + if (i.value == 0) + { + return false; + } + else + { + return true; + } + } + + static public implicit operator LSLInteger(int i) + { + return new LSLInteger(i); + } + + static public implicit operator LSLInteger(double d) + { + return new LSLInteger(d); + } + + static public LSLInteger operator &(LSLInteger i1, LSLInteger i2) + { + int ret = i1.value & i2.value; + return ret; + } + + + //static public implicit operator System.Double(LSLInteger i) + //{ + // return (double)i.value; + //} + + #region Overriders + + public override string ToString() + { + return this.value.ToString(); + } + + #endregion + } + + [Serializable] + public struct LSLFloat + { + public double value; + + #region Constructors + public LSLFloat(int i) + { + this.value = (double)i; + } + + public LSLFloat(double d) + { + this.value = d; + } + + #endregion + + #region Operators + + static public implicit operator System.Double(LSLFloat f) + { + return f.value; + } + + //static public implicit operator System.Int32(LSLFloat f) + //{ + // return (int)f.value; + //} + + + static public implicit operator System.Boolean(LSLFloat f) + { + if (f.value == 0) + { + return false; + } + else + { + return true; + } + } + + static public implicit operator LSLFloat(int i) + { + return new LSLFloat(i); + } + + static public implicit operator LSLFloat(double d) + { + return new LSLFloat(d); + } + #endregion + + #region Overriders + public override string ToString() + { + return this.value.ToString(); + } + #endregion + } + + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/Properties/AssemblyInfo.cs b/trunk/OpenSim/Region/ScriptEngine/Common/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..1572a51d54 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/Properties/AssemblyInfo.cs @@ -0,0 +1,64 @@ +/* +* 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.ScriptEngine.Common")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Region.ScriptEngine.Common")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("0bf07c53-ae51-487f-a907-e9b30c251602")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs new file mode 100644 index 0000000000..0fb8d758f6 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs @@ -0,0 +1,254 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + public class AppDomainManager : iScriptEngineFunctionModule + { + // + // This class does AppDomain handling and loading/unloading of scripts in it. + // It is instanced in "ScriptEngine" and controlled from "ScriptManager" + // + // 1. Create a new AppDomain if old one is full (or doesn't exist) + // 2. Load scripts into AppDomain + // 3. Unload scripts from AppDomain (stopping them and marking them as inactive) + // 4. Unload AppDomain completely when all scripts in it has stopped + // + + private int maxScriptsPerAppDomain = 1; + + /// + /// Internal list of all AppDomains + /// + private List appDomains = new List(); + + /// + /// Structure to keep track of data around AppDomain + /// + private class AppDomainStructure + { + /// + /// The AppDomain itself + /// + public AppDomain CurrentAppDomain; + + /// + /// Number of scripts loaded into AppDomain + /// + public int ScriptsLoaded; + + /// + /// Number of dead scripts + /// + public int ScriptsWaitingUnload; + } + + /// + /// Current AppDomain + /// + private AppDomainStructure currentAD; + + private object getLock = new object(); // Mutex + private object freeLock = new object(); // Mutex + + private ScriptEngine m_scriptEngine; + //public AppDomainManager(ScriptEngine scriptEngine) + public AppDomainManager(ScriptEngine scriptEngine) + { + m_scriptEngine = scriptEngine; + ReadConfig(); + } + + public void ReadConfig() + { + maxScriptsPerAppDomain = m_scriptEngine.ScriptConfigSource.GetInt("ScriptsPerAppDomain", 1); + } + + /// + /// Find a free AppDomain, creating one if necessary + /// + /// Free AppDomain + private AppDomainStructure GetFreeAppDomain() + { + // Console.WriteLine("Finding free AppDomain"); + lock (getLock) + { + // Current full? + if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain) + { + // Add it to AppDomains list and empty current + appDomains.Add(currentAD); + currentAD = null; + } + // No current + if (currentAD == null) + { + // Create a new current AppDomain + currentAD = new AppDomainStructure(); + currentAD.CurrentAppDomain = PrepareNewAppDomain(); + } + + // Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded); + return currentAD; + } // lock + } + + private int AppDomainNameCount; + + /// + /// Create and prepare a new AppDomain for scripts + /// + /// The new AppDomain + private AppDomain PrepareNewAppDomain() + { + // Create and prepare a new AppDomain + AppDomainNameCount++; + // TODO: Currently security match current appdomain + + // Construct and initialize settings for a second AppDomain. + AppDomainSetup ads = new AppDomainSetup(); + ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; + ads.DisallowBindingRedirects = false; + ads.DisallowCodeDownload = true; + ads.LoaderOptimization = LoaderOptimization.MultiDomain; // Sounds good ;) + ads.ShadowCopyFiles = "true"; // Enabled shadowing + ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; + + AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads); + m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain Loading: " + + AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString()); + AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll")); + + // Return the new AppDomain + return AD; + } + + /// + /// Unload appdomains that are full and have only dead scripts + /// + private void UnloadAppDomains() + { + lock (freeLock) + { + // Go through all + foreach (AppDomainStructure ads in new ArrayList(appDomains)) + { + // Don't process current AppDomain + if (ads.CurrentAppDomain != currentAD.CurrentAppDomain) + { + // Not current AppDomain + // Is number of unloaded bigger or equal to number of loaded? + if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload) + { + // Remove from internal list + appDomains.Remove(ads); +#if DEBUG + Console.WriteLine("Found empty AppDomain, unloading"); + long m = GC.GetTotalMemory(true); +#endif + // Unload + AppDomain.Unload(ads.CurrentAppDomain); +#if DEBUG + m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + " bytes of memory"); +#endif + } + } + } // foreach + } // lock + } + + public IScript LoadScript(string FileName) + { + // Find next available AppDomain to put it in + AppDomainStructure FreeAppDomain = GetFreeAppDomain(); + +#if DEBUG + m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Loading into AppDomain: " + FileName); +#endif + IScript mbrt = + (IScript) + FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script"); + //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); + FreeAppDomain.ScriptsLoaded++; + + return mbrt; + } + + + /// + /// Increase "dead script" counter for an AppDomain + /// + /// + //[Obsolete("Needs fixing, needs a real purpose in life!!!")] + public void StopScript(AppDomain ad) + { + lock (freeLock) + { +#if DEBUG + m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Stopping script in AppDomain"); +#endif + // Check if it is current AppDomain + if (currentAD.CurrentAppDomain == ad) + { + // Yes - increase + currentAD.ScriptsWaitingUnload++; + return; + } + + // Lopp through all AppDomains + foreach (AppDomainStructure ads in new ArrayList(appDomains)) + { + if (ads.CurrentAppDomain == ad) + { + // Found it + ads.ScriptsWaitingUnload++; + break; + } + } // foreach + } // lock + + UnloadAppDomains(); // Outsite lock, has its own GetLock + } + + /// + /// If set to true then threads and stuff should try to make a graceful exit + /// + public bool PleaseShutdown + { + get { return _PleaseShutdown; } + set { _PleaseShutdown = value; } + } + private bool _PleaseShutdown = false; + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs new file mode 100644 index 0000000000..1afe71c10c --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs @@ -0,0 +1,320 @@ +/* +* 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; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Modules; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc. + /// + public class AsyncLSLCommandManager : iScriptEngineFunctionModule + { + private Thread cmdHandlerThread; + private int cmdHandlerThreadCycleSleepms; + + private ScriptEngine m_ScriptEngine; + + public AsyncLSLCommandManager(ScriptEngine _ScriptEngine) + { + m_ScriptEngine = _ScriptEngine; + ReadConfig(); + + // Start the thread that will be doing the work + cmdHandlerThread = new Thread(CmdHandlerThreadLoop); + cmdHandlerThread.Name = "CmdHandlerThread"; + cmdHandlerThread.Priority = ThreadPriority.BelowNormal; + cmdHandlerThread.IsBackground = true; + cmdHandlerThread.Start(); + } + + public void ReadConfig() + { + cmdHandlerThreadCycleSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("AsyncLLCommandLoopms", 50); + } + + + ~AsyncLSLCommandManager() + { + // Shut down thread + try + { + if (cmdHandlerThread != null) + { + if (cmdHandlerThread.IsAlive == true) + { + cmdHandlerThread.Abort(); + cmdHandlerThread.Join(); + } + } + } + catch + { + } + } + + private void CmdHandlerThreadLoop() + { + while (true) + { + // Check timers + CheckTimerEvents(); + Thread.Sleep(25); + // Check HttpRequests + CheckHttpRequests(); + Thread.Sleep(25); + // Check XMLRPCRequests + CheckXMLRPCRequests(); + Thread.Sleep(25); + // Check Listeners + CheckListeners(); + Thread.Sleep(25); + + // Sleep before next cycle + //Thread.Sleep(cmdHandlerThreadCycleSleepms); + } + } + + /// + /// Remove a specific script (and all its pending commands) + /// + /// + /// + public void RemoveScript(uint localID, LLUUID itemID) + { + // Remove a specific script + + // Remove from: Timers + UnSetTimerEvents(localID, itemID); + // Remove from: HttpRequest + IHttpRequests iHttpReq = + m_ScriptEngine.World.RequestModuleInterface(); + iHttpReq.StopHttpRequest(localID, itemID); + + IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface(); + comms.DeleteListener(itemID); + + IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface(); + xmlrpc.DeleteChannel(itemID); + + } + + #region TIMER + + // + // TIMER + // + private class TimerClass + { + public uint localID; + public LLUUID itemID; + public double interval; + public DateTime next; + } + + private List Timers = new List(); + private object TimerListLock = new object(); + + public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec) + { + Console.WriteLine("SetTimerEvent"); + + // Always remove first, in case this is a re-set + UnSetTimerEvents(m_localID, m_itemID); + if (sec == 0) // Disabling timer + return; + + // Add to timer + TimerClass ts = new TimerClass(); + ts.localID = m_localID; + ts.itemID = m_itemID; + ts.interval = sec; + ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + lock (TimerListLock) + { + Timers.Add(ts); + } + } + + public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID) + { + // Remove from timer + lock (TimerListLock) + { + List NewTimers = new List(); + foreach (TimerClass ts in Timers) + { + if (ts.localID != m_localID && ts.itemID != m_itemID) + { + NewTimers.Add(ts); + } + } + Timers.Clear(); + Timers = NewTimers; + } + } + + public void CheckTimerEvents() + { + // Nothing to do here? + if (Timers.Count == 0) + return; + + lock (TimerListLock) + { + // Go through all timers + foreach (TimerClass ts in Timers) + { + // Time has passed? + if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) + { + // Add it to queue + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer", EventQueueManager.llDetectNull, + new object[] {}); + // set next interval + + + ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + } + } + } // lock + } + + #endregion + + #region HTTP REQUEST + + public void CheckHttpRequests() + { + if (m_ScriptEngine.World == null) + return; + + IHttpRequests iHttpReq = + m_ScriptEngine.World.RequestModuleInterface(); + + HttpRequestClass httpInfo = null; + + if (iHttpReq != null) + httpInfo = iHttpReq.GetNextCompletedRequest(); + + while (httpInfo != null) + { + //Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status); + + // Deliver data to prim's remote_data handler + // + // TODO: Returning null for metadata, since the lsl function + // only returns the byte for HTTP_BODY_TRUNCATED, which is not + // implemented here yet anyway. Should be fixed if/when maxsize + // is supported + + object[] resobj = new object[] + { + httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body + }; + + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + httpInfo.localID, httpInfo.itemID, "http_response", EventQueueManager.llDetectNull, resobj + ); + + httpInfo.Stop(); + httpInfo = null; + + httpInfo = iHttpReq.GetNextCompletedRequest(); + } + } + + #endregion + + public void CheckXMLRPCRequests() + { + if (m_ScriptEngine.World == null) + return; + + IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface(); + + if (xmlrpc != null) + { + while (xmlrpc.hasRequests()) + { + RPCRequestInfo rInfo = xmlrpc.GetNextRequest(); + //Console.WriteLine("PICKED REQUEST"); + + //Deliver data to prim's remote_data handler + object[] resobj = new object[] + { + 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), String.Empty, + rInfo.GetIntValue(), + rInfo.GetStrVal() + }; + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", EventQueueManager.llDetectNull, resobj + ); + } + } + } + + public void CheckListeners() + { + if (m_ScriptEngine.World == null) + return; + IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface(); + + while (comms.HasMessages()) + { + ListenerInfo lInfo = comms.GetNextMessage(); + + //Deliver data to prim's listen handler + object[] resobj = new object[] + { + lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage() + }; + + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj + ); + } + } + + /// + /// If set to true then threads and stuff should try to make a graceful exit + /// + public bool PleaseShutdown + { + get { return _PleaseShutdown; } + set { _PleaseShutdown = value; } + } + private bool _PleaseShutdown = false; + + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs new file mode 100644 index 0000000000..e99f0a72f6 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs @@ -0,0 +1,57 @@ +/* +* 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. +* +*/ + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + public static class Common + { + public static bool debug = true; + public static ScriptEngine mySE; + + // This class just contains some static log stuff used for debugging. + + //public delegate void SendToDebugEventDelegate(string message); + //public delegate void SendToLogEventDelegate(string message); + //static public event SendToDebugEventDelegate SendToDebugEvent; + //static public event SendToLogEventDelegate SendToLogEvent; + + public static void SendToDebug(string message) + { + //if (Debug == true) + mySE.Log.Info("[" + mySE.ScriptEngineName + "]: Debug: " + message); + //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + message); + } + + public static void SendToLog(string message) + { + //if (Debug == true) + mySE.Log.Info("[" + mySE.ScriptEngineName + "]: LOG: " + message); + //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + message); + } + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs new file mode 100644 index 0000000000..607a4ff90d --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs @@ -0,0 +1,288 @@ +/* +* 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; +using libsecondlife; +using OpenSim.Framework; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it. + /// + [Serializable] + public class EventManager : OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.RemoteEvents, iScriptEngineFunctionModule + { + // + // Class is instanced in "ScriptEngine" and Uses "EventQueueManager" that is also instanced in "ScriptEngine". + // This class needs a bit of explaining: + // + // This class it the link between an event inside OpenSim and the corresponding event in a user script being executed. + // + // For example when an user touches an object then the "myScriptEngine.World.EventManager.OnObjectGrab" event is fired inside OpenSim. + // We hook up to this event and queue a touch_start in EventQueueManager with the proper LSL parameters. + // It will then be delivered to the script by EventQueueManager. + // + // You can check debug C# dump of an LSL script if you need to verify what exact parameters are needed. + // + + + private ScriptEngine myScriptEngine; + //public IScriptHost TEMP_OBJECT_ID; + public EventManager(ScriptEngine _ScriptEngine, bool performHookUp) + { + myScriptEngine = _ScriptEngine; + ReadConfig(); + + // Hook up to events from OpenSim + // We may not want to do it because someone is controlling us and will deliver events to us + if (performHookUp) + { + myScriptEngine.Log.Info("[" + myScriptEngine.ScriptEngineName + "]: Hooking up to server events"); + myScriptEngine.World.EventManager.OnObjectGrab += touch_start; + myScriptEngine.World.EventManager.OnRezScript += OnRezScript; + myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript; + myScriptEngine.World.EventManager.OnScriptChangedEvent += changed; + // TODO: HOOK ALL EVENTS UP TO SERVER! + } + } + + public void ReadConfig() + { + } + + public void changed(uint localID, uint change) + { + // Add to queue for all scripts in localID, Object pass change. + myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "changed", EventQueueManager.llDetectNull, new object[] { (int)change }); + } + + public void state_entry(uint localID) + { + // Add to queue for all scripts in ObjectID object + myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "state_entry", EventQueueManager.llDetectNull, new object[] { }); + } + + public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient) + { + // Add to queue for all scripts in ObjectID object + myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "touch_start", EventQueueManager.llDetectNull, new object[] { (int)1 }); + } + + public void OnRezScript(uint localID, LLUUID itemID, string script) + { + Console.WriteLine("OnRezScript localID: " + localID + " LLUID: " + itemID.ToString() + " Size: " + + script.Length); + myScriptEngine.m_ScriptManager.StartScript(localID, itemID, script); + } + + public void OnRemoveScript(uint localID, LLUUID itemID) + { + Console.WriteLine("OnRemoveScript localID: " + localID + " LLUID: " + itemID.ToString()); + myScriptEngine.m_ScriptManager.StopScript( + localID, + itemID + ); + } + + // TODO: Replace placeholders below + // NOTE! THE PARAMETERS FOR THESE FUNCTIONS ARE NOT CORRECT! + // These needs to be hooked up to OpenSim during init of this class + // then queued in EventQueueManager. + // When queued in EventQueueManager they need to be LSL compatible (name and params) + + public void state_exit(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_exit", EventQueueManager.llDetectNull); + } + + public void touch(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch", EventQueueManager.llDetectNull); + } + + public void touch_end(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch_end", EventQueueManager.llDetectNull); + } + + public void collision_start(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_start", EventQueueManager.llDetectNull); + } + + public void collision(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision", EventQueueManager.llDetectNull); + } + + public void collision_end(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_end", EventQueueManager.llDetectNull); + } + + public void land_collision_start(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_start", EventQueueManager.llDetectNull); + } + + public void land_collision(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision", EventQueueManager.llDetectNull); + } + + public void land_collision_end(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_end", EventQueueManager.llDetectNull); + } + + // Handled by long commands + public void timer(uint localID, LLUUID itemID) + { + //myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, String.Empty); + } + + public void listen(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "listen", EventQueueManager.llDetectNull); + } + + public void on_rez(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "on_rez", EventQueueManager.llDetectNull); + } + + public void sensor(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "sensor", EventQueueManager.llDetectNull); + } + + public void no_sensor(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "no_sensor", EventQueueManager.llDetectNull); + } + + public void control(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "control", EventQueueManager.llDetectNull); + } + + public void money(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "money", EventQueueManager.llDetectNull); + } + + public void email(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "email", EventQueueManager.llDetectNull); + } + + public void at_target(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_target", EventQueueManager.llDetectNull); + } + + public void not_at_target(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_target", EventQueueManager.llDetectNull); + } + + public void at_rot_target(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_rot_target", EventQueueManager.llDetectNull); + } + + public void not_at_rot_target(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_rot_target", EventQueueManager.llDetectNull); + } + + public void run_time_permissions(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "run_time_permissions", EventQueueManager.llDetectNull); + } + + public void changed(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "changed", EventQueueManager.llDetectNull); + } + + public void attach(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "attach", EventQueueManager.llDetectNull); + } + + public void dataserver(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "dataserver", EventQueueManager.llDetectNull); + } + + public void link_message(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "link_message", EventQueueManager.llDetectNull); + } + + public void moving_start(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "moving_start", EventQueueManager.llDetectNull); + } + + public void moving_end(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "moving_end", EventQueueManager.llDetectNull); + } + + public void object_rez(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "object_rez", EventQueueManager.llDetectNull); + } + + public void remote_data(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "remote_data", EventQueueManager.llDetectNull); + } + + // Handled by long commands + public void http_response(uint localID, LLUUID itemID) + { + // myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "http_response", EventQueueManager.llDetectNull); + } + + /// + /// If set to true then threads and stuff should try to make a graceful exit + /// + public bool PleaseShutdown + { + get { return _PleaseShutdown; } + set { _PleaseShutdown = value; } + } + private bool _PleaseShutdown = false; + + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs new file mode 100644 index 0000000000..5e06fcdc8f --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs @@ -0,0 +1,467 @@ +/* +* 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; +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes.Scripting; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// EventQueueManager handles event queues + /// Events are queued and executed in separate thread + /// + [Serializable] + public class EventQueueManager : iScriptEngineFunctionModule + { + // + // Class is instanced in "ScriptEngine" and used by "EventManager" also instanced in "ScriptEngine". + // + // Class purpose is to queue and execute functions that are received by "EventManager": + // - allowing "EventManager" to release its event thread immediately, thus not interrupting server execution. + // - allowing us to prioritize and control execution of script functions. + // Class can use multiple threads for simultaneous execution. Mutexes are used for thread safety. + // + // 1. Hold an execution queue for scripts + // 2. Use threads to process queue, each thread executes one script function on each pass. + // 3. Catch any script error and process it + // + // + // Notes: + // * Current execution load balancing is optimized for 1 thread, and can cause unfair execute balancing between scripts. + // Not noticeable unless server is under high load. + // * This class contains the number of threads used for script executions. Since we are not microthreading scripts yet, + // increase number of threads to allow more concurrent script executions in OpenSim. + // + + public ScriptEngine m_ScriptEngine; + + /// + /// List of threads (classes) processing event queue + /// + internal List eventQueueThreads; // Thread pool that we work on + /// + /// Locking access to eventQueueThreads AND staticGlobalEventQueueThreads. + /// Note that this may or may not be a reference to a static object depending on PrivateRegionThreads config setting. + /// + private object eventQueueThreadsLock = new object(); + // Static objects for referencing the objects above if we don't have private threads: + internal static List staticEventQueueThreads; // A static reference used if we don't use private threads + internal static object staticEventQueueThreadsLock; // Statick lock object reference for same reason + + /// + /// Global static list of all threads (classes) processing event queue -- used by max enforcment thread + /// + private List staticGlobalEventQueueThreads = new List(); + + /// + /// Used internally to specify how many threads should exit gracefully + /// + public int ThreadsToExit; + public object ThreadsToExitLock = new object(); + + + public object queueLock = new object(); // Mutex lock object + + /// + /// How many threads to process queue with + /// + internal int numberOfThreads; + + internal static int EventExecutionMaxQueueSize; + + /// + /// Maximum time one function can use for execution before we perform a thread kill. + /// + private int maxFunctionExecutionTimems + { + get { return (int)(maxFunctionExecutionTimens / 10000); } + set { maxFunctionExecutionTimens = value * 10000; } + } + + /// + /// Contains nanoseconds version of maxFunctionExecutionTimems so that it matches time calculations better (performance reasons). + /// WARNING! ONLY UPDATE maxFunctionExecutionTimems, NEVER THIS DIRECTLY. + /// + public long maxFunctionExecutionTimens; + /// + /// Enforce max execution time + /// + public bool EnforceMaxExecutionTime; + /// + /// Kill script (unload) when it exceeds execution time + /// + private bool KillScriptOnMaxFunctionExecutionTime; + + /// + /// List of localID locks for mutex processing of script events + /// + private List objectLocks = new List(); + private object tryLockLock = new object(); // Mutex lock object + + /// + /// Queue containing events waiting to be executed + /// + public Queue eventQueue = new Queue(); + + #region " Queue structures " + /// + /// Queue item structure + /// + public struct QueueItemStruct + { + public uint localID; + public LLUUID itemID; + public string functionName; + public Queue_llDetectParams_Struct llDetectParams; + public object[] param; + } + + /// + /// Shared empty llDetectNull + /// + public readonly static Queue_llDetectParams_Struct llDetectNull = new Queue_llDetectParams_Struct(); + + /// + /// Structure to hold data for llDetect* commands + /// + [Serializable] + public struct Queue_llDetectParams_Struct + { + // More or less just a placeholder for the actual moving of additional data + // should be fixed to something better :) + public LSL_Types.key[] _key; + public LSL_Types.Quaternion[] _Quaternion; + public LSL_Types.Vector3[] _Vector3; + public bool[] _bool; + public int[] _int; + public string[] _string; + } + #endregion + + #region " Initialization / Startup " + public EventQueueManager(ScriptEngine _ScriptEngine) + { + m_ScriptEngine = _ScriptEngine; + + // TODO: We need to move from single EventQueueManager to list of it in to share threads + bool PrivateRegionThreads = true; // m_ScriptEngine.ScriptConfigSource.GetBoolean("PrivateRegionThreads", false); + + // Create thread pool list and lock object + // Determine from config if threads should be dedicated to regions or shared + if (PrivateRegionThreads) + { + // PRIVATE THREAD POOL PER REGION + eventQueueThreads = new List(); + eventQueueThreadsLock = new object(); + } + else + { + // SHARED THREAD POOL + // Crate the static objects + if (staticEventQueueThreads == null) + staticEventQueueThreads = new List(); + if (staticEventQueueThreadsLock == null) + staticEventQueueThreadsLock = new object(); + + // Now reference our locals to them + eventQueueThreads = staticEventQueueThreads; + eventQueueThreadsLock = staticEventQueueThreadsLock; + } + + ReadConfig(); + + } + + public void ReadConfig() + { + // Refresh config + numberOfThreads = m_ScriptEngine.ScriptConfigSource.GetInt("NumberOfScriptThreads", 2); + maxFunctionExecutionTimems = m_ScriptEngine.ScriptConfigSource.GetInt("MaxEventExecutionTimeMs", 5000); + EnforceMaxExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("EnforceMaxEventExecutionTime", false); + KillScriptOnMaxFunctionExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("DeactivateScriptOnTimeout", false); + EventExecutionMaxQueueSize = m_ScriptEngine.ScriptConfigSource.GetInt("EventExecutionMaxQueueSize", 300); + + // Now refresh config in all threads + lock (eventQueueThreadsLock) + { + foreach (EventQueueThreadClass EventQueueThread in eventQueueThreads) + { + EventQueueThread.ReadConfig(); + } + } + } + + #endregion + + #region " Shutdown all threads " + ~EventQueueManager() + { + Stop(); + } + + private void Stop() + { + if (eventQueueThreadsLock != null && eventQueueThreads != null) + { + // Kill worker threads + lock (eventQueueThreadsLock) + { + foreach (EventQueueThreadClass EventQueueThread in eventQueueThreads) + { + AbortThreadClass(EventQueueThread); + } + eventQueueThreads.Clear(); + staticGlobalEventQueueThreads.Clear(); + } + } + + // Remove all entries from our event queue + lock (queueLock) + { + eventQueue.Clear(); + } + } + + #endregion + + #region " Start / stop script execution threads (ThreadClasses) " + private void StartNewThreadClass() + { + EventQueueThreadClass eqtc = new EventQueueThreadClass(this); + eventQueueThreads.Add(eqtc); + staticGlobalEventQueueThreads.Add(eqtc); + m_ScriptEngine.Log.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Started new script execution thread. Current thread count: " + eventQueueThreads.Count); + } + + private void AbortThreadClass(EventQueueThreadClass threadClass) + { + if (eventQueueThreads.Contains(threadClass)) + eventQueueThreads.Remove(threadClass); + if (staticGlobalEventQueueThreads.Contains(threadClass)) + staticGlobalEventQueueThreads.Remove(threadClass); + + try + { + threadClass.Stop(); + } + catch (Exception ex) + { + m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + ":EventQueueManager]: If you see this, could you please report it to Tedd:"); + m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + ":EventQueueManager]: Script thread execution timeout kill ended in exception: " + ex.ToString()); + } + m_ScriptEngine.Log.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Killed script execution thread. Remaining thread count: " + eventQueueThreads.Count); + } + #endregion + + #region " Mutex locks for queue access " + /// + /// Try to get a mutex lock on localID + /// + /// + /// + public bool TryLock(uint localID) + { + lock (tryLockLock) + { + if (objectLocks.Contains(localID) == true) + { + return false; + } + else + { + objectLocks.Add(localID); + return true; + } + } + } + + /// + /// Release mutex lock on localID + /// + /// + public void ReleaseLock(uint localID) + { + lock (tryLockLock) + { + if (objectLocks.Contains(localID) == true) + { + objectLocks.Remove(localID); + } + } + } + #endregion + + #region " Add events to execution queue " + /// + /// Add event to event execution queue + /// + /// Region object ID + /// Name of the function, will be state + "_event_" + FunctionName + /// Array of parameters to match event mask + public void AddToObjectQueue(uint localID, string FunctionName, Queue_llDetectParams_Struct qParams, params object[] param) + { + // Determine all scripts in Object and add to their queue + //myScriptEngine.log.Info("[" + ScriptEngineName + "]: EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName); + + // Do we have any scripts in this object at all? If not, return + if (m_ScriptEngine.m_ScriptManager.Scripts.ContainsKey(localID) == false) + { + //Console.WriteLine("Event \String.Empty + FunctionName + "\" for localID: " + localID + ". No scripts found on this localID."); + return; + } + + Dictionary.KeyCollection scriptKeys = + m_ScriptEngine.m_ScriptManager.GetScriptKeys(localID); + + foreach (LLUUID itemID in scriptKeys) + { + // Add to each script in that object + // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter? + AddToScriptQueue(localID, itemID, FunctionName, qParams, param); + } + } + + /// + /// Add event to event execution queue + /// + /// Region object ID + /// Region script ID + /// Name of the function, will be state + "_event_" + FunctionName + /// Array of parameters to match event mask + public void AddToScriptQueue(uint localID, LLUUID itemID, string FunctionName, Queue_llDetectParams_Struct qParams, params object[] param) + { + lock (queueLock) + { + if (eventQueue.Count >= EventExecutionMaxQueueSize) + { + m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + "]: ERROR: Event execution queue item count is at " + eventQueue.Count + ". Config variable \"EventExecutionMaxQueueSize\" is set to " + EventExecutionMaxQueueSize + ", so ignoring new event."); + m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + "]: Event ignored: localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName); + return; + } + + // Create a structure and add data + QueueItemStruct QIS = new QueueItemStruct(); + QIS.localID = localID; + QIS.itemID = itemID; + QIS.functionName = FunctionName; + QIS.llDetectParams = qParams; + QIS.param = param; + + // Add it to queue + eventQueue.Enqueue(QIS); + } + } + #endregion + + #region " Maintenance thread " + + /// + /// Adjust number of script thread classes. It can start new, but if it needs to stop it will just set number of threads in "ThreadsToExit" and threads will have to exit themselves. + /// Called from MaintenanceThread + /// + public void AdjustNumberOfScriptThreads() + { + // Is there anything here for us to do? + if (eventQueueThreads.Count == numberOfThreads) + return; + + lock (eventQueueThreadsLock) + { + int diff = numberOfThreads - eventQueueThreads.Count; + // Positive number: Start + // Negative number: too many are running + if (diff > 0) + { + // We need to add more threads + for (int ThreadCount = eventQueueThreads.Count; ThreadCount < numberOfThreads; ThreadCount++) + { + StartNewThreadClass(); + } + } + if (diff < 0) + { + // We need to kill some threads + lock (ThreadsToExitLock) + { + ThreadsToExit = Math.Abs(diff); + } + } + } + } + + /// + /// Check if any thread class has been executing an event too long + /// + public void CheckScriptMaxExecTime() + { + // Iterate through all ScriptThreadClasses and check how long their current function has been executing + lock (eventQueueThreadsLock) + { + foreach (EventQueueThreadClass EventQueueThread in staticGlobalEventQueueThreads) + { + // Is thread currently executing anything? + if (EventQueueThread.InExecution) + { + // Has execution time expired? + if (DateTime.Now.Ticks - EventQueueThread.LastExecutionStarted > + maxFunctionExecutionTimens) + { + // Yes! We need to kill this thread! + + // Set flag if script should be removed or not + EventQueueThread.KillCurrentScript = KillScriptOnMaxFunctionExecutionTime; + + // Abort this thread + AbortThreadClass(EventQueueThread); + + // We do not need to start another, MaintenenceThread will do that for us + //StartNewThreadClass(); + } + } + } + } + } + #endregion + + /// + /// If set to true then threads and stuff should try to make a graceful exit + /// + public bool PleaseShutdown + { + get { return _PleaseShutdown; } + set { _PleaseShutdown = value; } + } + private bool _PleaseShutdown = false; + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs new file mode 100644 index 0000000000..e171d80c32 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs @@ -0,0 +1,337 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes.Scripting; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class + /// + public class EventQueueThreadClass: iScriptEngineFunctionModule + { + /// + /// How many ms to sleep if queue is empty + /// + private int nothingToDoSleepms;// = 50; + private ThreadPriority MyThreadPriority; + + public long LastExecutionStarted; + public bool InExecution = false; + public bool KillCurrentScript = false; + + private EventQueueManager eventQueueManager; + public Thread EventQueueThread; + private static int ThreadCount = 0; + + private string ScriptEngineName = "ScriptEngine.Common"; + + public EventQueueThreadClass(EventQueueManager eqm) + { + eventQueueManager = eqm; + ReadConfig(); + Start(); + } + + ~EventQueueThreadClass() + { + Stop(); + } + + public void ReadConfig() + { + ScriptEngineName = eventQueueManager.m_ScriptEngine.ScriptEngineName; + nothingToDoSleepms = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50); + + // Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually + string pri = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal"); + switch (pri.ToLower()) + { + case "lowest": + MyThreadPriority = ThreadPriority.Lowest; + break; + case "belownormal": + MyThreadPriority = ThreadPriority.BelowNormal; + break; + case "normal": + MyThreadPriority = ThreadPriority.Normal; + break; + case "abovenormal": + MyThreadPriority = ThreadPriority.AboveNormal; + break; + case "highest": + MyThreadPriority = ThreadPriority.Highest; + break; + default: + MyThreadPriority = ThreadPriority.BelowNormal; // Default + eventQueueManager.m_ScriptEngine.Log.Error("[ScriptEngineBase]: Unknown priority type \"" + pri + "\" in config file. Defaulting to \"BelowNormal\"."); + break; + } + + // Now set that priority + if (EventQueueThread != null) + if (EventQueueThread.IsAlive) + EventQueueThread.Priority = MyThreadPriority; + } + + /// + /// Start thread + /// + private void Start() + { + EventQueueThread = new Thread(EventQueueThreadLoop); + EventQueueThread.IsBackground = true; + + EventQueueThread.Priority = MyThreadPriority; + EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount; + EventQueueThread.Start(); + + // Look at this... Don't you wish everyone did that solid coding everywhere? :P + if (ThreadCount == int.MaxValue) + ThreadCount = 0; + ThreadCount++; + } + + public void Stop() + { + PleaseShutdown = true; // Set shutdown flag + Thread.Sleep(100); // Wait a bit + if (EventQueueThread != null && EventQueueThread.IsAlive == true) + { + try + { + EventQueueThread.Abort(); // Send abort + EventQueueThread.Join(); // Wait for it + } + catch (Exception) + { + //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Exception killing worker thread: " + e.ToString()); + } + } + } + + /// + /// Queue processing thread loop + /// + private void EventQueueThreadLoop() + { + //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Worker thread spawned"); + try + { + while (true) + { + try + { + EventQueueManager.QueueItemStruct BlankQIS = new EventQueueManager.QueueItemStruct(); + while (true) + { + // Every now and then check if we should shut down + if (PleaseShutdown || eventQueueManager.ThreadsToExit > 0) + { + // Someone should shut down, lets get exclusive lock + lock (eventQueueManager.ThreadsToExitLock) + { + // Lets re-check in case someone grabbed it + if (eventQueueManager.ThreadsToExit > 0) + { + // Its crowded here so we'll shut down + eventQueueManager.ThreadsToExit--; + Stop(); + return; + } + else + { + // We have been asked to shut down + Stop(); + return; + } + } + } + + //try + // { + EventQueueManager.QueueItemStruct QIS = BlankQIS; + bool GotItem = false; + + if (PleaseShutdown) + return; + + if (eventQueueManager.eventQueue.Count == 0) + { + // Nothing to do? Sleep a bit waiting for something to do + Thread.Sleep(nothingToDoSleepms); + } + else + { + // Something in queue, process + //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName); + + // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD + lock (eventQueueManager.queueLock) + { + GotItem = false; + for (int qc = 0; qc < eventQueueManager.eventQueue.Count; qc++) + { + // Get queue item + QIS = eventQueueManager.eventQueue.Dequeue(); + + // Check if object is being processed by someone else + if (eventQueueManager.TryLock(QIS.localID) == false) + { + // Object is already being processed, requeue it + eventQueueManager.eventQueue.Enqueue(QIS); + } + else + { + // We have lock on an object and can process it + GotItem = true; + break; + } + } // go through queue + } // lock + + if (GotItem == true) + { + // Execute function + try + { +///cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined +///#if DEBUG +/// eventQueueManager.m_ScriptEngine.Log.Debug("[" + ScriptEngineName + "]: " + +/// "Executing event:\r\n" +/// + "QIS.localID: " + QIS.localID +/// + ", QIS.itemID: " + QIS.itemID +/// + ", QIS.functionName: " + +/// QIS.functionName); +///#endif + LastExecutionStarted = DateTime.Now.Ticks; + KillCurrentScript = false; + InExecution = true; + eventQueueManager.m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, + QIS.itemID, + QIS.functionName, + QIS.llDetectParams, + QIS.param); + InExecution = false; + } + catch (Exception e) + { + InExecution = false; + // DISPLAY ERROR INWORLD + string text = "Error executing script function \"" + QIS.functionName + + "\":\r\n"; + if (e.InnerException != null) + { + // Send inner exception + text += e.InnerException.Message.ToString(); + } + else + { + text += "\r\n"; + // Send normal + text += e.Message.ToString(); + } + if (KillCurrentScript) + text += "\r\nScript will be deactivated!"; + + try + { + if (text.Length > 1500) + text = text.Substring(0, 1500); + IScriptHost m_host = + eventQueueManager.m_ScriptEngine.World.GetSceneObjectPart(QIS.localID); + //if (m_host != null) + //{ + eventQueueManager.m_ScriptEngine.World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Say, 0, + m_host.AbsolutePosition, + m_host.Name, m_host.UUID); + } + catch + { + //} + //else + //{ + // T oconsole + eventQueueManager.m_ScriptEngine.Log.Error("[" + ScriptEngineName + "]: " + + "Unable to send text in-world:\r\n" + + text); + } + finally + { + // So we are done sending message in-world + if (KillCurrentScript) + { + eventQueueManager.m_ScriptEngine.m_ScriptManager.StopScript( + QIS.localID, QIS.itemID); + } + } + } + finally + { + InExecution = false; + eventQueueManager.ReleaseLock(QIS.localID); + } + } + } // Something in queue + } + } + catch (ThreadAbortException tae) + { + eventQueueManager.m_ScriptEngine.Log.Info("[" + ScriptEngineName + "]: ThreadAbortException while executing function."); + } + catch (Exception e) + { + eventQueueManager.m_ScriptEngine.Log.Error("[" + ScriptEngineName + "]: Exception in EventQueueThreadLoop: " + e.ToString()); + } + } // while + } // try + catch (ThreadAbortException) + { + //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Worker thread killed: " + tae.Message); + } + } + + /// + /// If set to true then threads and stuff should try to make a graceful exit + /// + public bool PleaseShutdown + { + get { return _PleaseShutdown; } + set { _PleaseShutdown = value; } + } + private bool _PleaseShutdown = false; + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs new file mode 100644 index 0000000000..ab4ea04914 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs @@ -0,0 +1,190 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// This class does maintenance on script engine. + /// + public class MaintenanceThread : iScriptEngineFunctionModule + { + public ScriptEngine m_ScriptEngine; + private int MaintenanceLoopms; + + public MaintenanceThread(ScriptEngine _ScriptEngine) + { + m_ScriptEngine = _ScriptEngine; + + ReadConfig(); + + // Start maintenance thread + StartMaintenanceThread(); + } + + ~MaintenanceThread() + { + StopMaintenanceThread(); + } + + public void ReadConfig() + { + MaintenanceLoopms = m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopms", 50); + } + + #region " Maintenance thread " + /// + /// Maintenance thread. Enforcing max execution time for example. + /// + public Thread MaintenanceThreadThread; + + /// + /// Starts maintenance thread + /// + private void StartMaintenanceThread() + { + if (MaintenanceThreadThread == null) + { + MaintenanceThreadThread = new Thread(MaintenanceLoop); + MaintenanceThreadThread.Name = "ScriptMaintenanceThread"; + MaintenanceThreadThread.IsBackground = true; + MaintenanceThreadThread.Start(); + } + } + + /// + /// Stops maintenance thread + /// + private void StopMaintenanceThread() + { +#if DEBUG + m_ScriptEngine.Log.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: StopMaintenanceThread() called"); +#endif + PleaseShutdown = true; + Thread.Sleep(100); + try + { + if (MaintenanceThreadThread != null) + { + if (MaintenanceThreadThread.IsAlive) + { + MaintenanceThreadThread.Abort(); + } + } + } + catch (Exception ex) + { + m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + "]: Exception stopping maintenence thread: " + ex.ToString()); + } + } + + /// + /// A thread should run in this loop and check all running scripts + /// + public void MaintenanceLoop() + { + if (m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens < MaintenanceLoopms) + m_ScriptEngine.Log.Warn("[" + m_ScriptEngine.ScriptEngineName + "]: " + + "Configuration error: MaxEventExecutionTimeMs is less than MaintenanceLoopms. The Maintenance Loop will only check scripts once per run."); + + long Last_maxFunctionExecutionTimens = 0; // DateTime.Now.Ticks; + long Last_ReReadConfigFilens = DateTime.Now.Ticks; + while (true) + { + try + { + while (true) + { + System.Threading.Thread.Sleep(MaintenanceLoopms); // Sleep before next pass + if (PleaseShutdown) + return; + + if (m_ScriptEngine != null) + { + // + // Re-reading config every x seconds + // + if (m_ScriptEngine.RefreshConfigFilens > 0) + { + // Check if its time to re-read config + if (DateTime.Now.Ticks - Last_ReReadConfigFilens > m_ScriptEngine.RefreshConfigFilens) + { + //Console.WriteLine("Time passed: " + (DateTime.Now.Ticks - Last_ReReadConfigFilens) + ">" + m_ScriptEngine.RefreshConfigFilens ); + // Its time to re-read config file + m_ScriptEngine.ReadConfig(); + Last_ReReadConfigFilens = DateTime.Now.Ticks; // Reset time + } + } + + // + // Adjust number of running script threads if not correct + // + if (m_ScriptEngine.m_EventQueueManager != null) + m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads(); + + // + // Check if any script has exceeded its max execution time + // + if (m_ScriptEngine.m_EventQueueManager != null && m_ScriptEngine.m_EventQueueManager.EnforceMaxExecutionTime) + { + // We are enforcing execution time + if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens > + m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens) + { + // Its time to check again + m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check + Last_maxFunctionExecutionTimens = DateTime.Now.Ticks; // Reset time + } + } + } // m_ScriptEngine != null + } + } + catch (Exception ex) + { + m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + "]: Exception in MaintenanceLoopThread. Thread will recover after 5 sec throttle. Exception: " + ex.ToString()); + Thread.Sleep(5000); + } + } + } + #endregion + + /// + /// If set to true then threads and stuff should try to make a graceful exit + /// + public bool PleaseShutdown + { + get { return _PleaseShutdown; } + set { _PleaseShutdown = value; } + } + private bool _PleaseShutdown = false; + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs new file mode 100644 index 0000000000..78d9f7d9a4 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs @@ -0,0 +1,189 @@ +/* +* 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; +using System.IO; +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// This is the root object for ScriptEngine. Objects access each other trough this class. + /// + /// + [Serializable] + public abstract class ScriptEngine : IRegionModule, OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.ScriptEngine, iScriptEngineFunctionModule + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public Scene World; + public EventManager m_EventManager; // Handles and queues incoming events from OpenSim + public EventQueueManager m_EventQueueManager; // Executes events, handles script threads + public ScriptManager m_ScriptManager; // Load, unload and execute scripts + public AppDomainManager m_AppDomainManager; // Handles loading/unloading of scripts into AppDomains + public AsyncLSLCommandManager m_ASYNCLSLCommandManager; // Asyncronous LSL commands (commands that returns with an event) + public MaintenanceThread m_MaintenanceThread; // Thread that does different kinds of maintenance, for example refreshing config and killing scripts that has been running too long + + public IConfigSource ConfigSource; + public IConfig ScriptConfigSource; + public abstract string ScriptEngineName { get; } + + /// + /// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes. + /// + public int RefreshConfigFileSeconds { + get { return (int)(RefreshConfigFilens / 10000000); } + set { RefreshConfigFilens = value * 10000000; } + } + public long RefreshConfigFilens; + + public ScriptManager GetScriptManager() + { + return _GetScriptManager(); + } + + public abstract ScriptManager _GetScriptManager(); + + public log4net.ILog Log + { + get { return m_log; } + } + + public ScriptEngine() + { + //Common.SendToDebug("ScriptEngine Object Initialized"); + Common.mySE = this; + } + + public void InitializeEngine(Scene Sceneworld, IConfigSource config, bool HookUpToServer, ScriptManager newScriptManager) + { + World = Sceneworld; + ConfigSource = config; + m_log.Info("[" + ScriptEngineName + "]: ScriptEngine initializing"); + + // Make sure we have config + if (ConfigSource.Configs[ScriptEngineName] == null) + ConfigSource.AddConfig(ScriptEngineName); + ScriptConfigSource = ConfigSource.Configs[ScriptEngineName]; + + //m_log.Info("[" + ScriptEngineName + "]: InitializeEngine"); + + // Create all objects we'll be using + m_EventQueueManager = new EventQueueManager(this); + m_EventManager = new EventManager(this, HookUpToServer); + // We need to start it + newScriptManager.Start(); + m_ScriptManager = newScriptManager; + m_AppDomainManager = new AppDomainManager(this); + m_ASYNCLSLCommandManager = new AsyncLSLCommandManager(this); + m_MaintenanceThread = new MaintenanceThread(this); + + m_log.Info("[" + ScriptEngineName + "]: Reading configuration from config section \"" + ScriptEngineName + "\""); + ReadConfig(); + + // Should we iterate the region for scripts that needs starting? + // Or can we assume we are loaded before anything else so we can use proper events? + } + + public void Shutdown() + { + // We are shutting down + } + + ScriptServerInterfaces.RemoteEvents ScriptServerInterfaces.ScriptEngine.EventManager() + { + return this.m_EventManager; + } + + public void ReadConfig() + { +//#if DEBUG +// m_log.Debug("[" + ScriptEngineName + "]: Refreshing configuration for all modules"); +//#endif + RefreshConfigFileSeconds = ScriptConfigSource.GetInt("RefreshConfig", 30); + + // Reload from disk? No! + //ConfigSource.Reload(); + //if (File.Exists(OpenSim.Application.iniFilePath)) + //{ + // //ConfigSource.Merge(new IniConfigSource(OpenSim.Application.iniFilePath)); + //} + + + // Create a new object (probably not necessary?) +// ScriptConfigSource = ConfigSource.Configs[ScriptEngineName]; + + if (m_EventQueueManager != null) m_EventQueueManager.ReadConfig(); + if (m_EventManager != null) m_EventManager.ReadConfig(); + if (m_ScriptManager != null) m_ScriptManager.ReadConfig(); + if (m_AppDomainManager != null) m_AppDomainManager.ReadConfig(); + if (m_ASYNCLSLCommandManager != null) m_ASYNCLSLCommandManager.ReadConfig(); + if (m_MaintenanceThread != null) m_MaintenanceThread.ReadConfig(); + } + + #region IRegionModule + + public abstract void Initialise(Scene scene, IConfigSource config); + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "Common." + ScriptEngineName; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + /// + /// If set to true then threads and stuff should try to make a graceful exit + /// + public bool PleaseShutdown + { + get { return _PleaseShutdown; } + set { _PleaseShutdown = value; } + } + private bool _PleaseShutdown = false; + + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs new file mode 100644 index 0000000000..641453e6c4 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs @@ -0,0 +1,423 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.Serialization.Formatters.Binary; +using System.Threading; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// Loads scripts + /// Compiles them if necessary + /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution) + /// + /// + + // This class is as close as you get to the script without being inside script class. It handles all the dirty work for other classes. + // * Keeps track of running scripts + // * Compiles script if necessary (through "Compiler") + // * Loads script (through "AppDomainManager" called from for example "EventQueueManager") + // * Executes functions inside script (called from for example "EventQueueManager" class) + // * Unloads script (through "AppDomainManager" called from for example "EventQueueManager") + // * Dedicated load/unload thread, and queues loading/unloading. + // This so that scripts starting or stopping will not slow down other theads or whole system. + // + [Serializable] + public abstract class ScriptManager : iScriptEngineFunctionModule + { + #region Declares + + private Thread scriptLoadUnloadThread; + private static Thread staticScriptLoadUnloadThread; + private int scriptLoadUnloadThread_IdleSleepms; + private Queue LUQueue = new Queue(); + private static bool PrivateThread; + private int LoadUnloadMaxQueueSize; + + // Load/Unload structure + private struct LUStruct + { + public uint localID; + public LLUUID itemID; + public string script; + public LUType Action; + } + + private enum LUType + { + Unknown = 0, + Load = 1, + Unload = 2 + } + + // Object> + // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. + // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! + public Dictionary> Scripts = + new Dictionary>(); + + public Scene World + { + get { return m_scriptEngine.World; } + } + + #endregion + + public void ReadConfig() + { + scriptLoadUnloadThread_IdleSleepms = m_scriptEngine.ScriptConfigSource.GetInt("ScriptLoadUnloadLoopms", 30); + // TODO: Requires sharing of all ScriptManagers to single thread + PrivateThread = true; // m_scriptEngine.ScriptConfigSource.GetBoolean("PrivateScriptLoadUnloadThread", false); + LoadUnloadMaxQueueSize = m_scriptEngine.ScriptConfigSource.GetInt("LoadUnloadMaxQueueSize", 100); + } + + #region Object init/shutdown + + public ScriptEngineBase.ScriptEngine m_scriptEngine; + + public ScriptManager(ScriptEngineBase.ScriptEngine scriptEngine) + { + m_scriptEngine = scriptEngine; + } + public abstract void Initialize(); + public void Start() + { + ReadConfig(); + Initialize(); + + AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); + + // + // CREATE THREAD + // Private or shared + // + if (PrivateThread) + { + // Assign one thread per region + scriptLoadUnloadThread = StartScriptLoadUnloadThread(); + } + else + { + // Shared thread - make sure one exist, then assign it to the private + if (staticScriptLoadUnloadThread == null) + { + staticScriptLoadUnloadThread = StartScriptLoadUnloadThread(); + } + scriptLoadUnloadThread = staticScriptLoadUnloadThread; + } + } + + private static int privateThreadCount = 0; + private Thread StartScriptLoadUnloadThread() + { + Thread t = new Thread(ScriptLoadUnloadThreadLoop); + string name = "ScriptLoadUnloadThread:"; + if (PrivateThread) + { + name += "Private:" + privateThreadCount; + privateThreadCount++; + } + else + { + name += "Shared"; + } + t.Name = name; + t.IsBackground = true; + t.Priority = ThreadPriority.Normal; + t.Start(); + return t; + } + + ~ScriptManager() + { + // Abort load/unload thread + try + { + PleaseShutdown = true; + Thread.Sleep(100); + if (scriptLoadUnloadThread != null) + { + if (scriptLoadUnloadThread.IsAlive == true) + { + scriptLoadUnloadThread.Abort(); + scriptLoadUnloadThread.Join(); + } + } + } + catch + { + } + } + + #endregion + + #region Load / Unload scripts (Thread loop) + + private void ScriptLoadUnloadThreadLoop() + { + try + { + while (true) + { + if (LUQueue.Count == 0) + Thread.Sleep(scriptLoadUnloadThread_IdleSleepms); + if (PleaseShutdown) + return; + if (LUQueue.Count > 0) + { + LUStruct item = LUQueue.Dequeue(); + lock (startStopLock) // Lock so we have only 1 thread working on loading/unloading of scripts + { + if (item.Action == LUType.Unload) + { + _StopScript(item.localID, item.itemID); + } + if (item.Action == LUType.Load) + { + _StartScript(item.localID, item.itemID, item.script); + } + } + } + } + } + catch (ThreadAbortException tae) + { + string a = tae.ToString(); + a = String.Empty; + // Expected + } + } + + #endregion + + #region Helper functions + + private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) + { + //Console.WriteLine("ScriptManager.CurrentDomain_AssemblyResolve: " + args.Name); + return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null; + } + + #endregion + + + + #region Start/Stop/Reset script + + private readonly Object startStopLock = new Object(); + + /// + /// Fetches, loads and hooks up a script to an objects events + /// + /// + /// + public void StartScript(uint localID, LLUUID itemID, string Script) + { + if (LUQueue.Count >= LoadUnloadMaxQueueSize) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: ERROR: Load/unload queue item count is at " + LUQueue.Count + ". Config variable \"LoadUnloadMaxQueueSize\" is set to " + LoadUnloadMaxQueueSize + ", so ignoring new script."); + return; + } + + LUStruct ls = new LUStruct(); + ls.localID = localID; + ls.itemID = itemID; + ls.script = Script; + ls.Action = LUType.Load; + LUQueue.Enqueue(ls); + } + + /// + /// Disables and unloads a script + /// + /// + /// + public void StopScript(uint localID, LLUUID itemID) + { + LUStruct ls = new LUStruct(); + ls.localID = localID; + ls.itemID = itemID; + ls.Action = LUType.Unload; + LUQueue.Enqueue(ls); + } + + // Create a new instance of the compiler (reuse) + //private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler(); + + public abstract void _StartScript(uint localID, LLUUID itemID, string Script); + public abstract void _StopScript(uint localID, LLUUID itemID); + + + #endregion + + #region Perform event execution in script + + /// + /// Execute a LL-event-function in Script + /// + /// Object the script is located in + /// Script ID + /// Name of function + /// Arguments to pass to function + internal void ExecuteEvent(uint localID, LLUUID itemID, string FunctionName, EventQueueManager.Queue_llDetectParams_Struct qParams, object[] args) + { +//cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined +///#if DEBUG +/// Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName); +///#endif + // Execute a function in the script + //m_scriptEngine.Log.Info("[" + ScriptEngineName + "]: Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName); + //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID); + IScript Script = GetScript(localID, itemID); + if (Script == null) + return; +//cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined +///#if DEBUG +/// Console.WriteLine("ScriptEngine: Executing event: " + FunctionName); +///#endif + // Must be done in correct AppDomain, so leaving it up to the script itself + Script.llDetectParams = qParams; + Script.Exec.ExecuteEvent(FunctionName, args); + } + + #endregion + + #region Internal functions to keep track of script + + public Dictionary.KeyCollection GetScriptKeys(uint localID) + { + if (Scripts.ContainsKey(localID) == false) + return null; + + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + + return Obj.Keys; + } + + public IScript GetScript(uint localID, LLUUID itemID) + { + if (Scripts.ContainsKey(localID) == false) + return null; + + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == false) + return null; + + // Get script + IScript Script; + Obj.TryGetValue(itemID, out Script); + + return Script; + } + + public void SetScript(uint localID, LLUUID itemID, IScript Script) + { + // Create object if it doesn't exist + if (Scripts.ContainsKey(localID) == false) + { + Scripts.Add(localID, new Dictionary()); + } + + // Delete script if it exists + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == true) + Obj.Remove(itemID); + + // Add to object + Obj.Add(itemID, Script); + } + + public void RemoveScript(uint localID, LLUUID itemID) + { + // Don't have that object? + if (Scripts.ContainsKey(localID) == false) + return; + + // Delete script if it exists + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == true) + Obj.Remove(itemID); + } + + #endregion + + + public void ResetScript(uint localID, LLUUID itemID) + { + string script = GetScript(localID, itemID).Source; + StopScript(localID, itemID); + StartScript(localID, itemID, script); + } + + + #region Script serialization/deserialization + + public void GetSerializedScript(uint localID, LLUUID itemID) + { + // Serialize the script and return it + // Should not be a problem + FileStream fs = File.Create("SERIALIZED_SCRIPT_" + itemID); + BinaryFormatter b = new BinaryFormatter(); + b.Serialize(fs, GetScript(localID, itemID)); + fs.Close(); + } + + public void PutSerializedScript(uint localID, LLUUID itemID) + { + // Deserialize the script and inject it into an AppDomain + + // How to inject into an AppDomain? + } + + #endregion + + /// + /// If set to true then threads and stuff should try to make a graceful exit + /// + public bool PleaseShutdown + { + get { return _PleaseShutdown; } + set { _PleaseShutdown = value; } + } + private bool _PleaseShutdown = false; + + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs new file mode 100644 index 0000000000..1c730f5756 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs @@ -0,0 +1,40 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + public interface iScriptEngineFunctionModule + { + void ReadConfig(); + bool PleaseShutdown { get; set; } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs new file mode 100644 index 0000000000..d5031c8996 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs @@ -0,0 +1,90 @@ +/* +* 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 libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public class ScriptServerInterfaces + { + public interface RemoteEvents + { + void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient); + void OnRezScript(uint localID, LLUUID itemID, string script); + void OnRemoveScript(uint localID, LLUUID itemID); + void state_exit(uint localID, LLUUID itemID); + void touch(uint localID, LLUUID itemID); + void touch_end(uint localID, LLUUID itemID); + void collision_start(uint localID, LLUUID itemID); + void collision(uint localID, LLUUID itemID); + void collision_end(uint localID, LLUUID itemID); + void land_collision_start(uint localID, LLUUID itemID); + void land_collision(uint localID, LLUUID itemID); + void land_collision_end(uint localID, LLUUID itemID); + void timer(uint localID, LLUUID itemID); + void listen(uint localID, LLUUID itemID); + void on_rez(uint localID, LLUUID itemID); + void sensor(uint localID, LLUUID itemID); + void no_sensor(uint localID, LLUUID itemID); + void control(uint localID, LLUUID itemID); + void money(uint localID, LLUUID itemID); + void email(uint localID, LLUUID itemID); + void at_target(uint localID, LLUUID itemID); + void not_at_target(uint localID, LLUUID itemID); + void at_rot_target(uint localID, LLUUID itemID); + void not_at_rot_target(uint localID, LLUUID itemID); + void run_time_permissions(uint localID, LLUUID itemID); + void changed(uint localID, LLUUID itemID); + void attach(uint localID, LLUUID itemID); + void dataserver(uint localID, LLUUID itemID); + void link_message(uint localID, LLUUID itemID); + void moving_start(uint localID, LLUUID itemID); + void moving_end(uint localID, LLUUID itemID); + void object_rez(uint localID, LLUUID itemID); + void remote_data(uint localID, LLUUID itemID); + void http_response(uint localID, LLUUID itemID); + } + + public interface ServerRemotingObject + { + RemoteEvents Events(); + } + + public interface ScriptEngine + { + RemoteEvents EventManager(); + void InitializeEngine(Scene Sceneworld, IConfigSource config, bool DontHookUp, ScriptManager newScriptManager); + ScriptManager GetScriptManager(); + } + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/MyBase.cs b/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/MyBase.cs new file mode 100644 index 0000000000..16f77a36a2 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/MyBase.cs @@ -0,0 +1,38 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.Common.TRPC +{ + class MyBase + { + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPClient.cs b/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPClient.cs new file mode 100644 index 0000000000..84ce3c48b5 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPClient.cs @@ -0,0 +1,153 @@ +/* +* 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; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Net.Sockets; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.Common.TRPC +{ + public class TCPClient : TCPCommon.ClientInterface + { + + public TCPClient() + { + } + private readonly Dictionary Clients = new Dictionary(); + private int ClientCount = 0; + + + public event TCPCommon.ClientConnectedDelegate ClientConnected; + public event TCPCommon.DataReceivedDelegate DataReceived; + public event TCPCommon.DataSentDelegate DataSent; + public event TCPCommon.CloseDelegate Close; + public event TCPCommon.ConnectErrorDelegate ConnectError; + + + /// + /// Creates client connection + /// + public void Connect(string RemoteHost, int RemotePort) + { + Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(RemoteHost), RemotePort); + //newsock.BeginConnect(ipe, new AsyncCallback(asyncConnected), newsock); + newsock.Connect(ipe); + } + public int ConnectAndReturnID(string RemoteHost, int RemotePort) + { + Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(RemoteHost), RemotePort); + //newsock.BeginConnect(ipe, new AsyncCallback(asyncConnected), newsock); + newsock.Connect(ipe); + return ProcessConnection(newsock); + } + + + public void Disconnect(int ID) + { + Clients[ID].Disconnect(); + } + + void asyncConnected(IAsyncResult iar) + { + Socket client = (Socket)iar.AsyncState; + client.EndConnect(iar); + ProcessConnection(client); + } + + private int ProcessConnection(Socket client) + { + try + { + + + + int id = ClientCount++; + TCPSocket S = new TCPSocket(id, client); + + // Add to dictionary + Clients.Add(id, S); + + // Add event handlers + S.Close += new TCPSocket.CloseDelegate(S_Close); + S.DataReceived += new TCPSocket.DataReceivedDelegate(S_DataReceived); + S.DataSent += new TCPSocket.DataSentDelegate(S_DataSent); + + // Start it + S.Start(); + + Debug.WriteLine("Connection established: " + client.RemoteEndPoint.ToString()); + + // Fire Connected-event + if (ClientConnected != null) + ClientConnected(id, client.RemoteEndPoint); + + return id; + } + catch (SocketException sex) + { + if (ConnectError != null) + ConnectError(sex.Message); + } + return -1; + } + + + + + void S_DataSent(int ID, int length) + { + if (DataSent != null) + DataSent(ID, length); + } + + void S_DataReceived(int ID, byte[] data, int offset, int length) + { + if (DataReceived != null) + DataReceived(ID, data, offset, length); + } + + void S_Close(int ID) + { + if (Close != null) + Close(ID); + Clients.Remove(ID); + } + + public void Send(int clientID, byte[] data, int offset, int len) + { + Clients[clientID].Send(clientID, data, offset, len); + } + + + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPCommon.cs b/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPCommon.cs new file mode 100644 index 0000000000..69f777d326 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPCommon.cs @@ -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 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. +* +*/ + +namespace OpenSim.Region.ScriptEngine.Common.TRPC +{ + public class TCPCommon + { + public delegate void ClientConnectedDelegate(int ID, System.Net.EndPoint Remote); + public delegate void DataReceivedDelegate(int ID, byte[] data, int offset, int length); + public delegate void DataSentDelegate(int ID, int length); + public delegate void CloseDelegate(int ID); + public delegate void ConnectErrorDelegate(string Reason); + + + public interface ServerAndClientInterface + { + void Send(int clientID, byte[] data, int offset, int len); + event ClientConnectedDelegate ClientConnected; + event DataReceivedDelegate DataReceived; + event DataSentDelegate DataSent; + event CloseDelegate Close; + } + public interface ClientInterface : ServerAndClientInterface + { + event TCPCommon.ConnectErrorDelegate ConnectError; + void Connect(string RemoteHost, int RemotePort); + void Disconnect(int ID); + } + public interface ServerInterface : ServerAndClientInterface + { + void StartListen(); + void StopListen(); + } + + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPServer.cs b/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPServer.cs new file mode 100644 index 0000000000..758d205af2 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPServer.cs @@ -0,0 +1,134 @@ +/* +* 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; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Net.Sockets; +using TCPCommon=OpenSim.Region.ScriptEngine.Common.TRPC.TCPCommon; + +namespace OpenSim.Region.ScriptEngine.Common.TRPC +{ + public class TCPServer: TCPCommon.ServerInterface + { + public readonly int LocalPort; + public TCPServer(int localPort) + { + LocalPort = localPort; + } + + private Socket server; + + /// + /// Starts listening for new connections + /// + public void StartListen() + { + server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + IPEndPoint ipe = new IPEndPoint(IPAddress.Any, LocalPort); + server.Bind(ipe); + server.Listen(10); + server.BeginAccept(new AsyncCallback(AsyncAcceptConnections), server); + } + /// + /// Stops listening for new connections + /// + public void StopListen() + { + server.Close(); + server = null; + } + + private readonly Dictionary Clients = new Dictionary(); + private int ClientCount = 0; + + + public event TCPCommon.ClientConnectedDelegate ClientConnected; + public event TCPCommon.DataReceivedDelegate DataReceived; + public event TCPCommon.DataSentDelegate DataSent; + public event TCPCommon.CloseDelegate Close; + + /// + /// Async callback for new connections + /// + /// + private void AsyncAcceptConnections(IAsyncResult ar) + { + int id = ClientCount++; + Socket oldserver = (Socket)ar.AsyncState; + Socket client = oldserver.EndAccept(ar); + TCPSocket S = new TCPSocket(id, client); + + // Add to dictionary + Clients.Add(id, S); + + // Add event handlers + S.Close += new TCPSocket.CloseDelegate(S_Close); + S.DataReceived += new TCPSocket.DataReceivedDelegate(S_DataReceived); + S.DataSent += new TCPSocket.DataSentDelegate(S_DataSent); + + // Start it + S.Start(); + + Debug.WriteLine("Connection received: " + client.RemoteEndPoint.ToString()); + + // Fire Connected-event + if (ClientConnected != null) + ClientConnected(id, client.RemoteEndPoint); + + } + + void S_DataSent(int ID, int length) + { + if (DataSent != null) + DataSent(ID, length); + } + + void S_DataReceived(int ID, byte[] data, int offset, int length) + { + if (DataReceived != null) + DataReceived(ID, data, offset, length); + } + + void S_Close(int ID) + { + if (Close != null) + Close(ID); + Clients.Remove(ID); + } + + public void Send(int clientID, byte[] data, int offset, int len) + { + Clients[clientID].Send(clientID, data, offset, len); + } + + + + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPSocket.cs b/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPSocket.cs new file mode 100644 index 0000000000..5212e9e902 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/TRPC/TCPSocket.cs @@ -0,0 +1,114 @@ +/* +* 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; +using System.Net.Sockets; + +namespace OpenSim.Region.ScriptEngine.Common.TRPC +{ + public class TCPSocket + { + + public readonly Socket Client; + public readonly int ID; + + public delegate void DataReceivedDelegate(int ID, byte[] data, int offset, int length); + public delegate void DataSentDelegate(int ID, int length); + public delegate void CloseDelegate(int ID); + public event DataReceivedDelegate DataReceived; + public event DataSentDelegate DataSent; + public event CloseDelegate Close; + + private byte[] RecvQueue = new byte[4096]; + private int RecvQueueSize = 4096; + + public TCPSocket(int id, Socket client) + { + ID = id; + Client = client; + } + public void Start() + { + // Start listening + BeginReceive(); + } + + private void BeginReceive() + { + Client.BeginReceive(RecvQueue, 0, RecvQueueSize, SocketFlags.None, new AsyncCallback(asyncDataReceived), Client); + } + + /// + /// Callback for successful receive (or connection close) + /// + /// + private void asyncDataReceived(IAsyncResult ar) + { + Socket client = (Socket)ar.AsyncState; + int recv = client.EndReceive(ar); + + // Is connection closed? + if (recv == 0) + { + client.Close(); + Close(ID); + return; + } + + // Call receive event + DataReceived(ID, RecvQueue, 0, recv); + + // Start new receive + BeginReceive(); + + } + + + public void Send(int clientID, byte[] data, int offset, int len) + { + Client.BeginSend(data, offset, len, SocketFlags.None, new AsyncCallback(asyncDataSent), Client); + } + + /// + /// Callback for successful send + /// + /// + void asyncDataSent(IAsyncResult ar) + { + Socket client = (Socket)ar.AsyncState; + int sent = client.EndSend(ar); + DataSent(ID, sent); + } + + public void Disconnect() + { + Client.Close(); + Close(ID); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/Common/TRPC_Remote.cs b/trunk/OpenSim/Region/ScriptEngine/Common/TRPC_Remote.cs new file mode 100644 index 0000000000..a1b78d524a --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/Common/TRPC_Remote.cs @@ -0,0 +1,205 @@ +/* +* 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; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using libsecondlife; +using OpenSim.Region.ScriptEngine.Common.TRPC; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public class TRPC_Remote + { + public readonly int MaxQueueSize = 1024 * 10; + public readonly TCPCommon.ServerAndClientInterface TCPS; + + public delegate void ReceiveCommandDelegate(int ID, string Command, params object[] p); + public event ReceiveCommandDelegate ReceiveCommand; + System.Collections.Generic.Dictionary TypeDictionary = new Dictionary(); + Type[] Types = + { + typeof(System.String), + typeof(System.Int16), + typeof(System.Int32), + typeof(System.Int64), + typeof(System.Double), + typeof(System.Decimal), + typeof(System.Array), + typeof(LLUUID), + typeof(System.UInt16), + typeof(System.UInt32), + typeof(System.UInt64) + }; + + // TODO: Maybe we should move queue into TCPSocket so we won't have to keep one queue instance per connection + private System.Collections.Generic.Dictionary InQueue = new Dictionary(); + private class InQueueStruct + { + public byte[] Queue; + public int QueueSize; + public object QueueLockObject = new object(); + } + + public TRPC_Remote(TCPCommon.ServerAndClientInterface TCPClientOrServer) + { + TCPS = TCPClientOrServer; + TCPS.Close += new TCPCommon.CloseDelegate(TCPS_Close); + TCPS.ClientConnected += new TCPCommon.ClientConnectedDelegate(TCPS_ClientConnected); + TCPS.DataReceived += new TCPCommon.DataReceivedDelegate(TCPS_DataReceived); + //TCPS.StartListen(); + + // Make a lookup dictionary for types + foreach (Type t in Types) + { + TypeDictionary.Add(t.ToString(), t); + } + } + + void TCPS_ClientConnected(int ID, System.Net.EndPoint Remote) + { + // Create a incoming queue for this connection + InQueueStruct iq = new InQueueStruct(); + iq.Queue = new byte[MaxQueueSize]; + iq.QueueSize = 0; + InQueue.Add(ID, iq); + } + + void TCPS_Close(int ID) + { + // Remove queue + InQueue.Remove(ID); + } + + void TCPS_DataReceived(int ID, byte[] data, int offset, int length) + { + // Copy new data to incoming queue + lock (InQueue[ID].QueueLockObject) + { + Array.Copy(data, offset, InQueue[ID].Queue, InQueue[ID].QueueSize, length); + InQueue[ID].QueueSize += length; + + // Process incoming queue + ProcessQueue(ID); + } + } + + private void ProcessQueue(int ID) + { + + // This is just a temp implementation -- not so fast :) + + InQueueStruct myIQS = InQueue[ID]; + if (myIQS.QueueSize == 0) + return; + + string receivedData = Encoding.ASCII.GetString(myIQS.Queue, 0, myIQS.QueueSize); + Debug.WriteLine("RAW: " + receivedData); + + + byte newLine = 10; + while (true) + { + bool ShouldProcess = false; + int lineEndPos = 0; + + // Look for newline + for (int i = 0; i < myIQS.QueueSize; i++) + { + if (myIQS.Queue[i] == newLine) + { + ShouldProcess = true; + lineEndPos = i; + break; + } + } + + // Process it? + if (!ShouldProcess) + return; + // Yes + string cmdLine = Encoding.ASCII.GetString(myIQS.Queue, 0, lineEndPos); + Debug.WriteLine("Command: " + cmdLine); + + // Fix remaining queue in an inefficient way + byte[] newQueue = new byte[MaxQueueSize]; + Array.Copy(myIQS.Queue, lineEndPos, newQueue, 0, myIQS.QueueSize - lineEndPos); + myIQS.Queue = newQueue; + myIQS.QueueSize -= (lineEndPos + 1); + + // Now back to the command + string[] parts = cmdLine.Split(','); + if (parts.Length > 0) + { + string cmd = parts[0]; + int paramCount = parts.Length - 1; + object[] param = null; + + if (paramCount > 0) + { + // Process all parameters (decoding them from URL encoding) + param = new object[paramCount]; + for (int i = 1; i < parts.Length; i++) + { + string[] spl; + spl = System.Web.HttpUtility.UrlDecode(parts[i]).Split('|'); + string t = spl[0]; + param[i - 1] = Convert.ChangeType(spl[1], TypeLookup(t)); + } + } + + ReceiveCommand(ID, cmd, param); + } + } + } + + private Type TypeLookup(string t) + { + Type ret = TypeDictionary[t]; + if (ret != null) + return ret; + return typeof(object); + } + + public void SendCommand(int ID, string Command, params object[] p) + { + // Call PacketFactory to have it create a packet for us + + //string[] tmpP = new string[p.Length]; + string tmpStr = Command; + for (int i = 0; i < p.Length; i++) + { + tmpStr += "," + p[i].GetType().ToString() + "|" + System.Web.HttpUtility.UrlEncode(p[i].ToString()); // .Replace(",", "%44") + } + tmpStr += "\n"; + byte[] byteData = Encoding.ASCII.GetBytes(tmpStr); + TCPS.Send(ID, byteData, 0, byteData.Length); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs b/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs new file mode 100644 index 0000000000..58586c0b47 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs @@ -0,0 +1,441 @@ +/* +* 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; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Reflection; +using Microsoft.CSharp; +using Microsoft.VisualBasic; +using Microsoft.JScript; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + public class Compiler + { + // * Uses "LSL2Converter" to convert LSL to C# if necessary. + // * Compiles C#-code into an assembly + // * Returns assembly name ready for AppDomain load. + // + // Assembly is compiled using LSL_BaseClass as base. Look at debug C# code file created when LSL script is compiled for full details. + // + + internal enum enumCompileType + { + lsl = 0, + cs = 1, + vb = 2, + js = 3 + } + + /// + /// This contains number of lines WE use for header when compiling script. User will get error in line x-LinesToRemoveOnError when error occurs. + /// + public int LinesToRemoveOnError = 3; + private enumCompileType DefaultCompileLanguage; + private bool WriteScriptSourceToDebugFile; + private bool CompileWithDebugInformation; + private bool CleanUpOldScriptsOnStartup; + private System.Collections.Generic.Dictionary AllowedCompilers = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + private System.Collections.Generic.Dictionary LanguageMapping = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + + private string FilePrefix; + private string ScriptEnginesPath = "ScriptEngines"; + + private static LSL2CSConverter LSL_Converter = new LSL2CSConverter(); + private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider(); + private static VBCodeProvider VBcodeProvider = new VBCodeProvider(); + private static JScriptCodeProvider JScodeProvider = new JScriptCodeProvider(); + + private static int instanceID = new Random().Next(0, int.MaxValue); // Unique number to use on our compiled files + private static UInt64 scriptCompileCounter = 0; // And a counter + + public Common.ScriptEngineBase.ScriptEngine m_scriptEngine; + public Compiler(Common.ScriptEngineBase.ScriptEngine scriptEngine) + { + m_scriptEngine = scriptEngine; + ReadConfig(); + } + public bool in_startup = true; + public void ReadConfig() + { + + // Get some config + WriteScriptSourceToDebugFile = m_scriptEngine.ScriptConfigSource.GetBoolean("WriteScriptSourceToDebugFile", true); + CompileWithDebugInformation = m_scriptEngine.ScriptConfigSource.GetBoolean("CompileWithDebugInformation", true); + CleanUpOldScriptsOnStartup = m_scriptEngine.ScriptConfigSource.GetBoolean("CleanUpOldScriptsOnStartup", true); + + // Get file prefix from scriptengine name and make it file system safe: + FilePrefix = m_scriptEngine.ScriptEngineName; + foreach (char c in Path.GetInvalidFileNameChars()) + { + FilePrefix = FilePrefix.Replace(c, '_'); + } + + // First time we start? Delete old files + if (in_startup) + { + in_startup = false; + DeleteOldFiles(); + } + + // Map name and enum type of our supported languages + LanguageMapping.Add(enumCompileType.cs.ToString(), enumCompileType.cs); + LanguageMapping.Add(enumCompileType.vb.ToString(), enumCompileType.vb); + LanguageMapping.Add(enumCompileType.lsl.ToString(), enumCompileType.lsl); + LanguageMapping.Add(enumCompileType.js.ToString(), enumCompileType.js); + + // Allowed compilers + string allowComp = m_scriptEngine.ScriptConfigSource.GetString("AllowedCompilers", "lsl,cs,vb,js"); + AllowedCompilers.Clear(); + +#if DEBUG + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Allowed languages: " + allowComp); +#endif + + + foreach (string strl in allowComp.Split(',')) + { + string strlan = strl.Trim(" \t".ToCharArray()).ToLower(); + if (!LanguageMapping.ContainsKey(strlan)) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Config error. Compiler is unable to recognize language type \"" + strlan + "\" specified in \"AllowedCompilers\"."); + } + else + { +#if DEBUG + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Config OK. Compiler recognized language type \"" + strlan + "\" specified in \"AllowedCompilers\"."); +#endif + } + AllowedCompilers.Add(strlan, true); + } + if (AllowedCompilers.Count == 0) + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Config error. Compiler could not recognize any language in \"AllowedCompilers\". Scripts will not be executed!"); + + // Default language + string defaultCompileLanguage = m_scriptEngine.ScriptConfigSource.GetString("DefaultCompileLanguage", "lsl").ToLower(); + + // Is this language recognized at all? + if (!LanguageMapping.ContainsKey(defaultCompileLanguage)) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " + + "Config error. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is not recognized as a valid language. Changing default to: \"lsl\"."); + defaultCompileLanguage = "lsl"; + } + + // Is this language in allow-list? + if (!AllowedCompilers.ContainsKey(defaultCompileLanguage)) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " + + "Config error. Default language \"" + defaultCompileLanguage + "\"specified in \"DefaultCompileLanguage\" is not in list of \"AllowedCompilers\". Scripts may not be executed!"); + } + else + { +#if DEBUG + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: " + + "Config OK. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is recognized as a valid language."); +#endif + // LANGUAGE IS IN ALLOW-LIST + DefaultCompileLanguage = LanguageMapping[defaultCompileLanguage]; + } + + // We now have an allow-list, a mapping list, and a default language + + } + + /// + /// Delete old script files + /// + private void DeleteOldFiles() + { + + // CREATE FOLDER IF IT DOESNT EXIST + if (!Directory.Exists(ScriptEnginesPath)) + { + try + { + Directory.CreateDirectory(ScriptEnginesPath); + } + catch (Exception ex) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying to create ScriptEngine directory \"" + ScriptEnginesPath + "\": " + ex.ToString()); + } + } + + foreach (string file in Directory.GetFiles(ScriptEnginesPath)) + { + //m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: FILE FOUND: " + file); + + if (file.ToLower().StartsWith(FilePrefix + "_compiled_") || + file.ToLower().StartsWith(FilePrefix + "_source_")) + { + try + { + File.Delete(file); + } + catch (Exception ex) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying delete old script file \"" + file + "\": " + ex.ToString()); + } + + } + } + + } + + ////private ICodeCompiler icc = codeProvider.CreateCompiler(); + //public string CompileFromFile(string LSOFileName) + //{ + // switch (Path.GetExtension(LSOFileName).ToLower()) + // { + // case ".txt": + // case ".lsl": + // Common.ScriptEngineBase.Common.SendToDebug("Source code is LSL, converting to CS"); + // return CompileFromLSLText(File.ReadAllText(LSOFileName)); + // case ".cs": + // Common.ScriptEngineBase.Common.SendToDebug("Source code is CS"); + // return CompileFromCSText(File.ReadAllText(LSOFileName)); + // default: + // throw new Exception("Unknown script type."); + // } + //} + + /// + /// Converts script from LSL to CS and calls CompileFromCSText + /// + /// LSL script + /// Filename to .dll assembly + public string PerformScriptCompile(string Script) + { + enumCompileType l = DefaultCompileLanguage; + + + if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture)) + l = enumCompileType.cs; + if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture)) + { + l = enumCompileType.vb; + // We need to remove //vb, it won't compile with that + + Script = Script.Substring(4, Script.Length - 4); + } + if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture)) + l = enumCompileType.lsl; + + if (Script.StartsWith("//js", true, CultureInfo.InvariantCulture)) + l = enumCompileType.js; + + if (!AllowedCompilers.ContainsKey(l.ToString())) + { + // Not allowed to compile to this language! + string errtext = String.Empty; + errtext += "The compiler for language \"" + l.ToString() + "\" is not in list of allowed compilers. Script will not be executed!"; + throw new Exception(errtext); + } + + string compileScript = Script; + + if (l == enumCompileType.lsl) + { + // Its LSL, convert it to C# + compileScript = LSL_Converter.Convert(Script); + l = enumCompileType.cs; + } + + switch (l) + { + case enumCompileType.cs: + compileScript = CreateCSCompilerScript(compileScript); + break; + case enumCompileType.vb: + compileScript = CreateVBCompilerScript(compileScript); + break; + case enumCompileType.js: + compileScript = CreateJSCompilerScript(compileScript); + break; + } + return CompileFromDotNetText(compileScript, l); + } + + private static string CreateJSCompilerScript(string compileScript) + { + compileScript = String.Empty + + "import OpenSim.Region.ScriptEngine.Common; import System.Collections.Generic;\r\n" + + "package SecondLife {\r\n" + + "class Script extends OpenSim.Region.ScriptEngine.Common.LSL_BaseClass { \r\n" + + compileScript + + "} }\r\n"; + return compileScript; + } + + private static string CreateCSCompilerScript(string compileScript) + { + compileScript = String.Empty + + "using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic;\r\n" + + String.Empty + "namespace SecondLife { " + + String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Common.LSL_BaseClass { \r\n" + + @"public Script() { } " + + compileScript + + "} }\r\n"; + return compileScript; + } + + private static string CreateVBCompilerScript(string compileScript) + { + compileScript = String.Empty + + "Imports OpenSim.Region.ScriptEngine.Common: Imports System.Collections.Generic: " + + String.Empty + "NameSpace SecondLife:" + + String.Empty + "Public Class Script: Inherits OpenSim.Region.ScriptEngine.Common.LSL_BaseClass: " + + "\r\nPublic Sub New()\r\nEnd Sub: " + + compileScript + + ":End Class :End Namespace\r\n"; + return compileScript; + } + + /// + /// Compile .NET script to .Net assembly (.dll) + /// + /// CS script + /// Filename to .dll assembly + internal string CompileFromDotNetText(string Script, enumCompileType lang) + { + string ext = "." + lang.ToString(); + + // Output assembly name + scriptCompileCounter++; + string OutFile = + Path.Combine("ScriptEngines", + FilePrefix + "_compiled_" + instanceID.ToString() + "_" + scriptCompileCounter.ToString() + ".dll"); +#if DEBUG + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Starting compile of \"" + OutFile + "\"."); +#endif + try + { + File.Delete(OutFile); + } + catch (Exception e) // NOTLEGIT - Should be just catching FileIOException + { + //m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString()); + throw new Exception("Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString()); + } + //string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll"); + + // DEBUG - write source to disk + if (WriteScriptSourceToDebugFile) + { + string srcFileName = FilePrefix + "_source_" + Path.GetFileNameWithoutExtension(OutFile) + ext; + try + { + File.WriteAllText( + Path.Combine("ScriptEngines", srcFileName), + Script); + } + catch (Exception ex) // NOTLEGIT - Should be just catching FileIOException + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception while trying to write script source to file \"" + srcFileName + "\": " + ex.ToString()); + } + } + + // Do actual compile + CompilerParameters parameters = new CompilerParameters(); + + parameters.IncludeDebugInformation = true; + + // Add all available assemblies + foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) + { + //Console.WriteLine("Adding assembly: " + asm.Location); + //parameters.ReferencedAssemblies.Add(asm.Location); + } + + string rootPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory); + string rootPathSE = Path.GetDirectoryName(GetType().Assembly.Location); + //Console.WriteLine("Assembly location: " + rootPath); + parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Common.dll")); + parameters.ReferencedAssemblies.Add(Path.Combine(rootPathSE, "OpenSim.Region.ScriptEngine.DotNetEngine.dll")); + + //parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment"); + parameters.GenerateExecutable = false; + parameters.OutputAssembly = OutFile; + parameters.IncludeDebugInformation = CompileWithDebugInformation; + //parameters.WarningLevel = 1; // Should be 4? + parameters.TreatWarningsAsErrors = false; + + CompilerResults results; + switch (lang) + { + case enumCompileType.vb: + results = VBcodeProvider.CompileAssemblyFromSource(parameters, Script); + break; + case enumCompileType.cs: + results = CScodeProvider.CompileAssemblyFromSource(parameters, Script); + break; + case enumCompileType.js: + results = JScodeProvider.CompileAssemblyFromSource(parameters, Script); + break; + default: + throw new Exception("Compiler is not able to recongnize language type \"" + lang.ToString() + "\""); + } + + // Check result + // Go through errors + + // + // WARNINGS AND ERRORS + // + if (results.Errors.Count > 0) + { + string errtext = String.Empty; + foreach (CompilerError CompErr in results.Errors) + { + errtext += "Line number " + (CompErr.Line - LinesToRemoveOnError) + + ", Error Number: " + CompErr.ErrorNumber + + ", '" + CompErr.ErrorText + "'\r\n"; + } + if (!File.Exists(OutFile)) + { + throw new Exception(errtext); + } + } + + + // + // NO ERRORS, BUT NO COMPILED FILE + // + if (!File.Exists(OutFile)) + { + string errtext = String.Empty; + errtext += "No compile error. But not able to locate compiled file."; + throw new Exception(errtext); + } + return OutFile; + } + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs b/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs new file mode 100644 index 0000000000..613aa32a71 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs @@ -0,0 +1,311 @@ +/* +* 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.Collections.Generic; +using System.Text.RegularExpressions; +using System; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + public class LSL2CSConverter + { + + + // Uses regex to convert LSL code to C# code. + + //private Regex rnw = new Regex(@"[a-zA-Z0-9_\-]", RegexOptions.Compiled); + private Dictionary dataTypes = new Dictionary(); + private Dictionary quotes = new Dictionary(); + + public LSL2CSConverter() + { + // Only the types we need to convert + dataTypes.Add("void", "void"); + dataTypes.Add("integer", "int"); + dataTypes.Add("float", "double"); + dataTypes.Add("string", "string"); + dataTypes.Add("key", "string"); + dataTypes.Add("vector", "LSL_Types.Vector3"); + dataTypes.Add("rotation", "LSL_Types.Quaternion"); + dataTypes.Add("list", "LSL_Types.list"); + dataTypes.Add("null", "null"); + } + + public string Convert(string Script) + { + quotes.Clear(); + string Return = System.String.Empty; + Script = " \r\n" + Script; + + // + // Prepare script for processing + // + + // Clean up linebreaks + Script = Regex.Replace(Script, @"\r\n", "\n"); + Script = Regex.Replace(Script, @"\n", "\r\n"); + + + // QUOTE REPLACEMENT + // temporarily replace quotes so we can work our magic on the script without + // always considering if we are inside our outside quotes's + // TODO: Does this work on half-quotes in strings? ;) + string _Script = System.String.Empty; + string C; + bool in_quote = false; + bool quote_replaced = false; + string quote_replacement_string = "Q_U_O_T_E_REPLACEMENT_"; + string quote = System.String.Empty; + bool last_was_escape = false; + int quote_replaced_count = 0; + for (int p = 0; p < Script.Length; p++) + { + C = Script.Substring(p, 1); + while (true) + { + // found " and last was not \ so this is not an escaped \" + if (C == "\"" && last_was_escape == false) + { + // Toggle inside/outside quote + in_quote = !in_quote; + if (in_quote) + { + quote_replaced_count++; + } + else + { + if (quote == System.String.Empty) + { + // We didn't replace quote, probably because of empty string? + _Script += quote_replacement_string + + quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]); + } + // We just left a quote + quotes.Add( + quote_replacement_string + + quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]), quote); + quote = System.String.Empty; + } + break; + } + + if (!in_quote) + { + // We are not inside a quote + quote_replaced = false; + } + else + { + // We are inside a quote + if (!quote_replaced) + { + // Replace quote + _Script += quote_replacement_string + + quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]); + quote_replaced = true; + } + quote += C; + break; + } + _Script += C; + break; + } + last_was_escape = false; + if (C == @"\") + { + last_was_escape = true; + } + } + Script = _Script; + // + // END OF QUOTE REPLACEMENT + // + + + // + // PROCESS STATES + // Remove state definitions and add state names to start of each event within state + // + int ilevel = 0; + int lastlevel = 0; + string ret = System.String.Empty; + string cache = System.String.Empty; + bool in_state = false; + string current_statename = System.String.Empty; + for (int p = 0; p < Script.Length; p++) + { + C = Script.Substring(p, 1); + while (true) + { + // inc / dec level + if (C == @"{") + ilevel++; + if (C == @"}") + ilevel--; + if (ilevel < 0) + ilevel = 0; + cache += C; + + // if level == 0, add to return + if (ilevel == 1 && lastlevel == 0) + { + // 0 => 1: Get last + Match m = + Regex.Match(cache, @"(?![a-zA-Z_]+)\s*([a-zA-Z_]+)[^a-zA-Z_\(\)]*{", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + in_state = false; + if (m.Success) + { + // Go back to level 0, this is not a state + in_state = true; + current_statename = m.Groups[1].Captures[0].Value; + //Console.WriteLine("Current statename: " + current_statename); + cache = + Regex.Replace(cache, + @"(?(?![a-zA-Z_]+)\s*)" + @"([a-zA-Z_]+)(?[^a-zA-Z_\(\)]*){", + "${s1}${s2}", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + } + ret += cache; + cache = String.Empty; + } + if (ilevel == 0 && lastlevel == 1) + { + // 1 => 0: Remove last } + if (in_state == true) + { + cache = cache.Remove(cache.Length - 1, 1); + //cache = Regex.Replace(cache, "}$", String.Empty, RegexOptions.Multiline | RegexOptions.Singleline); + + //Replace function names + // void dataserver(key query_id, string data) { + //cache = Regex.Replace(cache, @"([^a-zA-Z_]\s*)((?!if|switch|for)[a-zA-Z_]+\s*\([^\)]*\)[^{]*{)", "$1" + "" + "$2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + //Console.WriteLine("Replacing using statename: " + current_statename); + cache = + Regex.Replace(cache, + @"^(\s*)((?!(if|switch|for|while)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", + @"$1public " + current_statename + "_event_$2", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + } + + ret += cache; + cache = String.Empty; + in_state = true; + current_statename = String.Empty; + } + + break; + } + lastlevel = ilevel; + } + ret += cache; + cache = String.Empty; + + Script = ret; + ret = String.Empty; + + + foreach (string key in dataTypes.Keys) + { + string val; + dataTypes.TryGetValue(key, out val); + + // Replace CAST - (integer) with (int) + Script = + Regex.Replace(Script, @"\(" + key + @"\)", @"(" + val + ")", + RegexOptions.Compiled | RegexOptions.Multiline); + // Replace return types and function variables - integer a() and f(integer a, integer a) + Script = + Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s+)", @"$1$2" + val + "$3", + RegexOptions.Compiled | RegexOptions.Multiline); + Script = + Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s*)[,]", @"$1$2" + val + "$3,", + RegexOptions.Compiled | RegexOptions.Multiline); + } + + // Add "void" in front of functions that needs it + Script = + Regex.Replace(Script, + @"^(\s*public\s+)?((?!(if|switch|for)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", + @"$1void $2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + // Replace and + Script = + Regex.Replace(Script, @"<([^,>;]*,[^,>;\)]*,[^,>;\)]*,[^,>;\)]*)>", @"new LSL_Types.Quaternion($1)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + Script = + Regex.Replace(Script, @"<([^,>;]*,[^,>;\)]*,[^,>;\)]*)>", @"new LSL_Types.Vector3($1)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + // Replace List []'s + Script = + Regex.Replace(Script, @"\[([^\]]*)\]", @"new LSL_Types.list($1)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + + // Replace (string) to .ToString() // + Script = + Regex.Replace(Script, @"\(string\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.ToString()", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + Script = + Regex.Replace(Script, @"\((float|int)\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.Parse($2)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + + // REPLACE BACK QUOTES + foreach (string key in quotes.Keys) + { + string val; + quotes.TryGetValue(key, out val); + Script = Script.Replace(key, "\"" + val + "\""); + } + + + // Add namespace, class name and inheritance + + Return = String.Empty;// + + //"using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic;"; + + + //Return += String.Empty + + // "namespace SecondLife { "; + //Return += String.Empty + + // //"[Serializable] " + + // "public class Script : OpenSim.Region.ScriptEngine.Common.LSL_BaseClass { "; + //Return += @"public Script() { } "; + Return += Script; + //Return += "} }\r\n"; + + + quotes.Clear(); + + return Return; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/c_sharp_example.txt b/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/c_sharp_example.txt new file mode 100644 index 0000000000..a39d1dbbc0 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/c_sharp_example.txt @@ -0,0 +1,12 @@ +//c# +namespace SecondLife { + public class Script : OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass +{ + public Script() { } + + public void default_event_state_entry( ) + { + llSay(0, "testing, I've been touched"); + } + +}} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs b/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..e484906a70 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* 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.ScriptEngine.DotNetEngine")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Region.ScriptEngine.DotNetEngine")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("2842257e-6fde-4460-9368-4cde57fa9cc4")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs b/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs new file mode 100644 index 0000000000..514c550a7b --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs @@ -0,0 +1,56 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine +{ + [Serializable] + public class ScriptEngine : OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptEngine + { + // We need to override a few things for our DotNetEngine + public override void Initialise(Scene scene, IConfigSource config) + { + ConfigSource = config; + InitializeEngine(scene, config, true, GetScriptManager()); + } + + public override OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptManager _GetScriptManager() + { + return new ScriptManager(this); + } + + public override string ScriptEngineName + { + get { return "ScriptEngine.DotNetEngine"; } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs b/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs new file mode 100644 index 0000000000..68ac99cc5e --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs @@ -0,0 +1,164 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ + +using System; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine +{ + public class ScriptManager : OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptManager + { + public ScriptManager(Common.ScriptEngineBase.ScriptEngine scriptEngine) + : base(scriptEngine) + { + base.m_scriptEngine = scriptEngine; + } + private Compiler.LSL.Compiler LSLCompiler; + + + public override void Initialize() + { + // Create our compiler + LSLCompiler = new Compiler.LSL.Compiler(m_scriptEngine); + } + + // KEEP TRACK OF SCRIPTS + //internal Dictionary> Scripts = new Dictionary>(); + // LOAD SCRIPT + // UNLOAD SCRIPT + // PROVIDE SCRIPT WITH ITS INTERFACE TO OpenSim + + + public override void _StartScript(uint localID, LLUUID itemID, string Script) + { + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: ScriptManager StartScript: localID: " + localID + ", itemID: " + itemID); + + + //IScriptHost root = host.GetRoot(); + + // We will initialize and start the script. + // It will be up to the script itself to hook up the correct events. + string ScriptSource = String.Empty; + + SceneObjectPart m_host = World.GetSceneObjectPart(localID); + + try + { + // Compile (We assume LSL) + ScriptSource = LSLCompiler.PerformScriptCompile(Script); + +#if DEBUG + long before; + before = GC.GetTotalMemory(true); +#endif + + IScript CompiledScript; + CompiledScript = m_scriptEngine.m_AppDomainManager.LoadScript(ScriptSource); + +#if DEBUG + m_scriptEngine.Log.DebugFormat("[" + m_scriptEngine.ScriptEngineName + "]: Script " + itemID + " occupies {0} bytes", GC.GetTotalMemory(true) - before); +#endif + + CompiledScript.Source = Script; + // Add it to our script memstruct + m_scriptEngine.m_ScriptManager.SetScript(localID, itemID, CompiledScript); + + // We need to give (untrusted) assembly a private instance of BuiltIns + // this private copy will contain Read-Only FullitemID so that it can bring that on to the server whenever needed. + + + LSL_BuiltIn_Commands LSLB = new LSL_BuiltIn_Commands(m_scriptEngine, m_host, localID, itemID); + + // Start the script - giving it BuiltIns + CompiledScript.Start(LSLB); + + // Fire the first start-event + m_scriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_entry", EventQueueManager.llDetectNull, new object[] { }); + } + catch (Exception e) // LEGIT: User Scripting + { + //m_scriptEngine.Log.Error("[ScriptEngine]: Error compiling script: " + e.ToString()); + try + { + // DISPLAY ERROR INWORLD + string text = "Error compiling script:\r\n" + e.Message.ToString(); + if (text.Length > 1500) + text = text.Substring(0, 1500); + World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0, m_host.AbsolutePosition, + m_host.Name, m_host.UUID); + } + catch (Exception e2) // LEGIT: User Scripting + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Error displaying error in-world: " + e2.ToString()); + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " + + "Errormessage: Error compiling script:\r\n" + e.Message.ToString()); + } + } + } + + public override void _StopScript(uint localID, LLUUID itemID) + { + // Stop script +#if DEBUG + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Stop script localID: " + localID + " LLUID: " + itemID.ToString()); +#endif + + // Stop long command on script + m_scriptEngine.m_ASYNCLSLCommandManager.RemoveScript(localID, itemID); + + IScript LSLBC = GetScript(localID, itemID); + if (LSLBC == null) + return; + + // TEMP: First serialize it + //GetSerializedScript(localID, itemID); + + try + { + // Get AppDomain + AppDomain ad = LSLBC.Exec.GetAppDomain(); + // Tell script not to accept new requests + m_scriptEngine.m_ScriptManager.GetScript(localID, itemID).Exec.StopScript(); + // Remove from internal structure + m_scriptEngine.m_ScriptManager.RemoveScript(localID, itemID); + // Tell AppDomain that we have stopped script + m_scriptEngine.m_AppDomainManager.StopScript(ad); + } + catch (Exception e) // LEGIT: User Scripting + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception stopping script localID: " + localID + " LLUID: " + itemID.ToString() + + ": " + e.ToString()); + } + } + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Common.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Common.cs new file mode 100644 index 0000000000..d1bc21d6e5 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Common.cs @@ -0,0 +1,86 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + public static class Common + { + public static bool Debug = true; + public static bool IL_UseTryCatch = true; + public static bool IL_CreateConstructor = true; + public static bool IL_CreateFunctionList = true; + public static bool IL_ProcessCodeChunks = true; + + public delegate void SendToDebugEventDelegate(string Message); + + public delegate void SendToLogEventDelegate(string Message); + + public static event SendToDebugEventDelegate SendToDebugEvent; + public static event SendToLogEventDelegate SendToLogEvent; + + public static void SendToDebug(string Message) + { + //if (Debug == true) + Console.WriteLine("COMPILER:Debug: " + Message); + SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + + public static void SendToLog(string Message) + { + //if (Debug == true) + Console.WriteLine("COMPILER:LOG: " + Message); + SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + } + + public static class IL_Helper + { + public static string ReverseFormatString(string text1, string format) + { + Common.SendToDebug("ReverseFormatString text1: " + text1); + Common.SendToDebug("ReverseFormatString format: " + format); + return string.Format(format, text1); + } + + public static string ReverseFormatString(string text1, UInt32 text2, string format) + { + Common.SendToDebug("ReverseFormatString text1: " + text1); + Common.SendToDebug("ReverseFormatString text2: " + text2.ToString()); + Common.SendToDebug("ReverseFormatString format: " + format); + return string.Format(format, text1, text2.ToString()); + } + + public static string Cast_ToString(object obj) + { + Common.SendToDebug("OBJECT TO BE CASTED: " + obj.GetType().ToString()); + return "ABCDEFGIHJKLMNOPQ123"; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Engine.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Engine.cs new file mode 100644 index 0000000000..c6fa4ce73e --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Engine.cs @@ -0,0 +1,293 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.IO; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.LSOEngine.LSO; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + public class Engine + { + //private string LSO_FileName = @"LSO\AdditionTest.lso"; + private string LSO_FileName; // = @"LSO\CloseToDefault.lso"; + private AppDomain appDomain; + + public string Compile(string LSOFileName) + { + LSO_FileName = LSOFileName; + + + //appDomain = AppDomain.CreateDomain("AlternateAppDomain"); + appDomain = Thread.GetDomain(); + + // Create Assembly Name + AssemblyName asmName = new AssemblyName(); + asmName.Name = Path.GetFileNameWithoutExtension(LSO_FileName); + //asmName.Name = "TestAssembly"; + + string DLL_FileName = asmName.Name + ".dll"; + string DLL_FileName_WithPath = Path.GetDirectoryName(LSO_FileName) + @"\" + DLL_FileName; + + LSOEngine.LSO.Common.SendToLog("LSO File Name: " + Path.GetFileName(LSO_FileName)); + LSOEngine.LSO.Common.SendToLog("Assembly name: " + asmName.Name); + LSOEngine.LSO.Common.SendToLog("Assembly File Name: " + asmName.Name + ".dll"); + LSOEngine.LSO.Common.SendToLog("Starting processing of LSL ByteCode..."); + LSOEngine.LSO.Common.SendToLog(String.Empty); + + + // Create Assembly + AssemblyBuilder asmBuilder = appDomain.DefineDynamicAssembly( + asmName, + AssemblyBuilderAccess.RunAndSave + ); + //// Create Assembly + //AssemblyBuilder asmBuilder = + // Thread.GetDomain().DefineDynamicAssembly + //(asmName, AssemblyBuilderAccess.RunAndSave); + + // Create a module (and save to disk) + ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule + (asmName.Name, + DLL_FileName); + + //Common.SendToDebug("asmName.Name is still \String.Empty + asmName.Name + "\String.Empty); + // Create a Class (/Type) + TypeBuilder typeBuilder = modBuilder.DefineType( + "LSL_ScriptObject", + TypeAttributes.Public | TypeAttributes.BeforeFieldInit, + typeof (LSL_BaseClass)); + //, + // typeof()); + //, typeof(LSL_BuiltIn_Commands_Interface)); + //, + // typeof(object), + // new Type[] { typeof(LSL_CLRInterface.LSLScript) }); + + + /* + * Generate the IL itself + */ + + LSO_Parser LSOP = new LSO_Parser(LSO_FileName, typeBuilder); + LSOP.OpenFile(); + LSOP.Parse(); + + // Constructor has to be created AFTER LSO_Parser because of accumulated variables + if (LSOEngine.LSO.Common.IL_CreateConstructor) + IL_CREATE_CONSTRUCTOR(typeBuilder, LSOP); + + LSOP.CloseFile(); + /* + * Done generating. Create a type and run it. + */ + + + LSOEngine.LSO.Common.SendToLog("Attempting to compile assembly..."); + // Compile it + Type type = typeBuilder.CreateType(); + LSOEngine.LSO.Common.SendToLog("Compilation successful!"); + + LSOEngine.LSO.Common.SendToLog("Saving assembly: " + DLL_FileName); + asmBuilder.Save(DLL_FileName); + + LSOEngine.LSO.Common.SendToLog("Returning assembly filename: " + DLL_FileName); + + + return DLL_FileName; + + + //Common.SendToLog("Creating an instance of new assembly..."); + //// Create an instance we can play with + ////LSLScript hello = (LSLScript)Activator.CreateInstance(type); + ////LSL_CLRInterface.LSLScript MyScript = (LSL_CLRInterface.LSLScript)Activator.CreateInstance(type); + //object MyScript = (object)Activator.CreateInstance(type); + + + //System.Reflection.MemberInfo[] Members = type.GetMembers(); + + //Common.SendToLog("Members of assembly " + type.ToString() + ":"); + //foreach (MemberInfo member in Members) + // Common.SendToLog(member.ToString()); + + + //// Play with it + ////MyScript.event_state_entry("Test"); + //object[] args = { null }; + ////System.Collections.Generic.List Functions = (System.Collections.Generic.List)type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, MyScript, null); + + //string[] ret = { }; + //if (Common.IL_CreateFunctionList) + // ret = (string[])type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, MyScript, null); + + //foreach (string s in ret) + //{ + // Common.SendToLog(String.Empty); + // Common.SendToLog("*** Executing LSL Server Event: " + s); + // //object test = type.GetMember(s); + // //object runner = type.InvokeMember(s, BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, MyScript, args); + // //runner(); + // //objBooks_Late = type.InvokeMember(s, BindingFlags.CreateInstance, null, objApp_Late, null); + // type.InvokeMember(s, BindingFlags.InvokeMethod, null, MyScript, new object[] { "Test" }); + + //} + } + + + private static void IL_CREATE_CONSTRUCTOR(TypeBuilder typeBuilder, LSO_Parser LSOP) + { + LSOEngine.LSO.Common.SendToDebug("IL_CREATE_CONSTRUCTOR()"); + //ConstructorBuilder constructor = typeBuilder.DefineConstructor( + // MethodAttributes.Public, + // CallingConventions.Standard, + // new Type[0]); + ConstructorBuilder constructor = typeBuilder.DefineConstructor( + MethodAttributes.Public | + MethodAttributes.SpecialName | + MethodAttributes.RTSpecialName, + CallingConventions.Standard, + new Type[0]); + + //Define the reflection ConstructorInfor for System.Object + ConstructorInfo conObj = typeof (LSL_BaseClass).GetConstructor(new Type[0]); + + //call constructor of base object + ILGenerator il = constructor.GetILGenerator(); + + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, conObj); + + + //Common.SendToDebug("IL_CREATE_CONSTRUCTOR: Creating global: UInt32 State = 0;"); + //string FieldName; + //// Create state object + //FieldName = "State"; + //FieldBuilder State_fb = typeBuilder.DefineField( + // FieldName, + // typeof(UInt32), + // FieldAttributes.Public); + //il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Ldc_I4, 0); + //il.Emit(OpCodes.Stfld, State_fb); + + + //Common.SendToDebug("IL_CREATE_CONSTRUCTOR: Creating global: LSL_BuiltIn_Commands_TestImplementation LSL_BuiltIns = New LSL_BuiltIn_Commands_TestImplementation();"); + ////Type objType1 = typeof(object); + //Type objType1 = typeof(LSL_BuiltIn_Commands_TestImplementation); + + //FieldName = "LSL_BuiltIns"; + //FieldBuilder LSL_BuiltIns_fb = typeBuilder.DefineField( + // FieldName, + // objType1, + // FieldAttributes.Public); + + ////LSL_BuiltIn_Commands_TestImplementation _ti = new LSL_BuiltIn_Commands_TestImplementation(); + //il.Emit(OpCodes.Ldarg_0); + ////il.Emit(OpCodes.Ldstr, "Test 123"); + //il.Emit(OpCodes.Newobj, objType1.GetConstructor(new Type[] { })); + //il.Emit(OpCodes.Stfld, LSL_BuiltIns_fb); + + foreach (UInt32 pos in LSOP.StaticBlocks.Keys) + { + LSO_Struct.StaticBlock sb; + LSOP.StaticBlocks.TryGetValue(pos, out sb); + + if (sb.ObjectType > 0 && sb.ObjectType < 8) + { + // We don't want void or null's + + il.Emit(OpCodes.Ldarg_0); + // Push position to stack + il.Emit(OpCodes.Ldc_I4, pos); + //il.Emit(OpCodes.Box, typeof(UInt32)); + + + Type datatype = null; + + // Push data to stack + LSOEngine.LSO.Common.SendToDebug("Adding to static (" + pos + ") type: " + + ((LSO_Enums.Variable_Type_Codes) sb.ObjectType).ToString() + " (" + sb.ObjectType + + ")"); + switch ((LSO_Enums.Variable_Type_Codes) sb.ObjectType) + { + case LSO_Enums.Variable_Type_Codes.Float: + case LSO_Enums.Variable_Type_Codes.Integer: + //UInt32 + il.Emit(OpCodes.Ldc_I4, BitConverter.ToUInt32(sb.BlockVariable, 0)); + datatype = typeof (UInt32); + il.Emit(OpCodes.Box, datatype); + break; + case LSO_Enums.Variable_Type_Codes.String: + case LSO_Enums.Variable_Type_Codes.Key: + //String + LSO_Struct.HeapBlock hb = + LSOP.GetHeap(LSOP.myHeader.HR + BitConverter.ToUInt32(sb.BlockVariable, 0) - 1); + il.Emit(OpCodes.Ldstr, Encoding.UTF8.GetString(hb.Data)); + datatype = typeof (string); + break; + case LSO_Enums.Variable_Type_Codes.Vector: + datatype = typeof (LSO_Enums.Vector); + //TODO: Not implemented + break; + case LSO_Enums.Variable_Type_Codes.Rotation: + //Object + //TODO: Not implemented + datatype = typeof (LSO_Enums.Rotation); + break; + default: + datatype = typeof (object); + break; + } + + + // Make call + il.Emit(OpCodes.Call, + typeof (LSL_BaseClass).GetMethod("AddToStatic", new Type[] {typeof (UInt32), datatype})); + } + } + + + ////il.Emit(OpCodes.Newobj, typeof(UInt32)); + //il.Emit(OpCodes.Starg_0); + //// Create LSL function library + //FieldBuilder LSL_BuiltIns_fb = typeBuilder.DefineField("LSL_BuiltIns", typeof(LSL_BuiltIn_Commands_Interface), FieldAttributes.Public); + //il.Emit(OpCodes.Newobj, typeof(LSL_BuiltIn_Commands_Interface)); + //il.Emit(OpCodes.Stloc_1); + + il.Emit(OpCodes.Ret); + } + + + // End of class + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/IL_common_functions.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/IL_common_functions.cs new file mode 100644 index 0000000000..9c57bcddd8 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/IL_common_functions.cs @@ -0,0 +1,51 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Reflection; +using System.Reflection.Emit; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + internal partial class LSO_Parser + { + private static TypeBuilder CreateType(ModuleBuilder modBuilder, string typeName) + { + TypeBuilder typeBuilder = modBuilder.DefineType(typeName, + TypeAttributes.Public | + TypeAttributes.Class | + TypeAttributes.AutoClass | + TypeAttributes.AnsiClass | + TypeAttributes.BeforeFieldInit | + TypeAttributes.AutoLayout, + typeof (object), + new Type[] {typeof (object)}); + return typeBuilder; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_BaseClass_OPCODES.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_BaseClass_OPCODES.cs new file mode 100644 index 0000000000..54cc5c575d --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_BaseClass_OPCODES.cs @@ -0,0 +1,395 @@ +/* +* 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; +using System.Collections.Generic; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + //public partial class LSL_BaseClass + //{ + // /* + // * OPCODES + // * + // * These are internal "assembly" commands, + // * basic operators like "ADD", "PUSH" and "POP" + // * + // * It also contains managed stack and keeps track of internal variables, etc. + // * + // */ + + + // public void StoreToLocal(UInt32 index) + // { + // // TODO: How to determine local? + // LSOEngine.LSO.Common.SendToDebug("::StoreToLocal " + index); + // if (LocalVariables.ContainsKey(index)) + // LocalVariables.Remove(index); + // LocalVariables.Add(index, LSLStack.Peek()); + // } + + // public void StoreToGlobal(UInt32 index) + // { + // LSOEngine.LSO.Common.SendToDebug("::StoreToGlobal " + index); + // if (GlobalVariables.ContainsKey(index)) + // GlobalVariables.Remove(index); + // GlobalVariables.Add(index, LSLStack.Peek()); + // } + + // public void StoreToStatic(UInt32 index) + // { + // LSOEngine.LSO.Common.SendToDebug("::StoreToStatic " + index); + // //if (StaticVariables.ContainsKey(index)) + // // StaticVariables.Remove(index); + // StaticVariables.Add(index, LSLStack.Peek()); + // } + + // public void GetFromLocal(UInt32 index) + // { + // // TODO: How to determine local? + // LSOEngine.LSO.Common.SendToDebug("::GetFromLocal " + index); + // object ret; + // LocalVariables.TryGetValue(index, out ret); + // LSLStack.Push(ret); + // //return ret; + // } + + // public void GetFromGlobal(UInt32 index) + // { + // LSOEngine.LSO.Common.SendToDebug("::GetFromGlobal " + index); + // object ret; + // GlobalVariables.TryGetValue(index, out ret); + // LSLStack.Push(ret); + // //return ret; + // } + + // public void GetFromStatic(UInt32 index) + // { + // LSOEngine.LSO.Common.SendToDebug("::GetFromStatic " + index); + // object ret; + // StaticVariables.TryGetValue(index, out ret); + // LSOEngine.LSO.Common.SendToDebug("::GetFromStatic - ObjectType: " + ret.GetType().ToString()); + // LSLStack.Push(ret); + // //return ret; + // } + + // public object POPToStack() + // { + // LSOEngine.LSO.Common.SendToDebug("::POPToStack"); + // //return LSLStack.Pop(); + // object p = LSLStack.Pop(); + // if (p.GetType() == typeof (UInt32)) + // return (UInt32) p; + // if (p.GetType() == typeof (string)) + // return (string) p; + // if (p.GetType() == typeof (Int32)) + // return (Int32) p; + // if (p.GetType() == typeof (UInt16)) + // return (UInt16) p; + // if (p.GetType() == typeof (float)) + // return (float) p; + // if (p.GetType() == typeof (LSO_Enums.Vector)) + // return (LSO_Enums.Vector) p; + // if (p.GetType() == typeof (LSO_Enums.Rotation)) + // return (LSO_Enums.Rotation) p; + // if (p.GetType() == typeof (LSO_Enums.Key)) + // return (LSO_Enums.Key) p; + + // return p; + // } + + // //public object POPToStack(UInt32 count) + // //{ + // // // POP NUMBER FROM TOP OF STACK + // // //LSLStack.SetLength(LSLStack.Length - 4); + // // Common.SendToDebug("::POPToStack " + count); + // // if (count < 2) + // // return LSLStack.Pop(); + + // // Stack s = new Stack(); + // // for (int i = 0; i < count; i++) + // // { + // // s.Push(LSLStack.Pop); + + // // } + + // //} + + // public void POP() + // { + // // POP NUMBER FROM TOP OF STACK + // //LSLStack.SetLength(LSLStack.Length - 4); + // LSOEngine.LSO.Common.SendToDebug("::POP"); + // if (LSLStack.Count < 1) + // { + // //TODO: Temporary fix + // LSOEngine.LSO.Common.SendToDebug("ERROR: TRYING TO POP EMPTY STACK!"); + // } + // else + // { + // LSLStack.Pop(); + // } + // } + + // public void PUSH(object Param) + // { + // if (Param == null) + // { + // LSOEngine.LSO.Common.SendToDebug("::PUSH: "); + // } + // else + // { + // //Common.SendToDebug("::PUSH: " + Param.GetType()); + // } + + // LSLStack.Push(Param); + // } + + // public void ADD(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::ADD: " + Param); + // object o2 = LSLStack.Pop(); + // object o1 = LSLStack.Pop(); + // LSOEngine.LSO.Common.SendToDebug("::ADD: Debug: o1: " + o1.GetType() + " (" + o1.ToString() + "), o2: " + o2.GetType() + + // " (" + o2.ToString() + ")"); + // if (o2.GetType() == typeof (string)) + // { + // LSLStack.Push((string) o1 + (string) o2); + // return; + // } + // if (o2.GetType() == typeof (UInt32)) + // { + // LSLStack.Push((UInt32) o1 + (UInt32) o2); + // return; + // } + // } + + // public void SUB(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::SUB: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1 - i2)); + // } + + // public void MUL(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::SUB: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1*i2)); + // } + + // public void DIV(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::DIV: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1/i2)); + // } + + + // public void MOD(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::MOD: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1%i2)); + // } + + // public void EQ(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::EQ: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // if (i1 == i2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void NEQ(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::NEQ: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // if (i1 != i2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void LEQ(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::LEQ: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // if (i1 <= i2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void GEQ(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::GEQ: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // if (i1 >= i2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void LESS(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::LESS: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // if (i1 < i2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void GREATER(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::GREATER: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // if (i1 > i2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + + // public void BITAND() + // { + // LSOEngine.LSO.Common.SendToDebug("::BITAND"); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1 & i2)); + // } + + // public void BITOR() + // { + // LSOEngine.LSO.Common.SendToDebug("::BITOR"); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1 | i2)); + // } + + // public void BITXOR() + // { + // LSOEngine.LSO.Common.SendToDebug("::BITXOR"); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1 ^ i2)); + // } + + // public void BOOLAND() + // { + // LSOEngine.LSO.Common.SendToDebug("::BOOLAND"); + // bool b2 = bool.Parse((string) LSLStack.Pop()); + // bool b1 = bool.Parse((string) LSLStack.Pop()); + // if (b1 && b2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void BOOLOR() + // { + // LSOEngine.LSO.Common.SendToDebug("::BOOLOR"); + // bool b2 = bool.Parse((string) LSLStack.Pop()); + // bool b1 = bool.Parse((string) LSLStack.Pop()); + + // if (b1 || b2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void NEG(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::NEG: " + Param); + // //UInt32 i2 = (UInt32)LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1*-1)); + // } + + // public void BITNOT() + // { + // //Common.SendToDebug("::BITNOT"); + // //UInt32 i2 = (UInt32)LSLStack.Pop(); + // //UInt32 i1 = (UInt32)LSLStack.Pop(); + // //LSLStack.Push((UInt32)(i1 / i2)); + // } + + // public void BOOLNOT() + // { + // //Common.SendToDebug("::BOOLNOT"); + // ////UInt32 i2 = (UInt32)LSLStack.Pop(); + // //UInt32 i1 = (UInt32)LSLStack.Pop(); + // //LSLStack.Push((UInt32)(i1)); + // } + //} +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_CLRInterface.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_CLRInterface.cs new file mode 100644 index 0000000000..8bb7712bf3 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_CLRInterface.cs @@ -0,0 +1,75 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + public class LSL_CLRInterface + { + public interface LSLScript + { + //public virtual void Run(object arg) + //{ + //} + //void Run(object arg); + + //void event_state_entry(object arg); + //void event_state_exit(); + //void event_touch_start(object arg); + //void event_touch(); + //void event_touch_end(); + //void event_collision_start(); + //void event_collision(); + //void event_collision_end(); + //void event_land_collision_start(); + //void event_land_collision(); + //void event_land_collision_end(); + //void event_timer(); + //void event_listen(); + //void event_on_rez(); + //void event_sensor(); + //void event_no_sensor(); + //void event_control(); + //void event_money(); + //void event_email(); + //void event_at_target(); + //void event_not_at_target(); + //void event_at_rot_target(); + //void event_not_at_rot_target(); + //void event_run_time_permissions(); + //void event_changed(); + //void event_attach(); + //void event_dataserver(); + //void event_link_message(); + //void event_moving_start(); + //void event_moving_end(); + //void event_object_rez(); + //void event_remote_data(); + //void event_http_response(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_OPCODE_IL_processor.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_OPCODE_IL_processor.cs new file mode 100644 index 0000000000..30d38905c4 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_OPCODE_IL_processor.cs @@ -0,0 +1,435 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Reflection; +using System.Reflection.Emit; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + internal partial class LSO_Parser + { + //internal Stack ILStack = new Stack(); + //LSO_Enums MyLSO_Enums = new LSO_Enums(); + + internal bool LSL_PROCESS_OPCODE(ILGenerator il) + { + byte bp1; + UInt32 u32p1; + float fp1; + UInt16 opcode = br_read(1)[0]; + Common.SendToDebug("OPCODE: " + ((LSO_Enums.Operation_Table) opcode).ToString()); + string idesc = ((LSO_Enums.Operation_Table) opcode).ToString(); + switch ((LSO_Enums.Operation_Table) opcode) + { + /*************** + * IMPLEMENTED * + ***************/ + case LSO_Enums.Operation_Table.NOOP: + break; + case LSO_Enums.Operation_Table.PUSHSP: + // Push Stack Top (Memory Address) to stack + Common.SendToDebug("Instruction " + idesc); + Common.SendToDebug("Instruction " + idesc + + ": Description: Pushing Stack Top (Memory Address from header) to stack"); + IL_Push(il, (UInt32) myHeader.SP); + break; + // BYTE + case LSO_Enums.Operation_Table.PUSHARGB: + Common.SendToDebug("Param1: " + br_read(1)[0]); + break; + // INTEGER + case LSO_Enums.Operation_Table.PUSHARGI: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Instruction " + idesc + ", Param1: " + u32p1); + IL_Push(il, u32p1); + break; + // FLOAT + case LSO_Enums.Operation_Table.PUSHARGF: + fp1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Instruction " + idesc + ", Param1: " + fp1); + IL_Push(il, fp1); + break; + // STRING + case LSO_Enums.Operation_Table.PUSHARGS: + string s = Read_String(); + Common.SendToDebug("Instruction " + idesc + ", Param1: " + s); + IL_Debug(il, "OPCODE: " + idesc + ":" + s); + IL_Push(il, s); + break; + // VECTOR z,y,x + case LSO_Enums.Operation_Table.PUSHARGV: + LSO_Enums.Vector v = new LSO_Enums.Vector(); + v.Z = BitConverter.ToUInt32(br_read(4), 0); + v.Y = BitConverter.ToUInt32(br_read(4), 0); + v.X = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1 Z: " + v.Z); + Common.SendToDebug("Param1 Y: " + v.Y); + Common.SendToDebug("Param1 X: " + v.X); + IL_Push(il, v); + break; + // ROTATION s,z,y,x + case LSO_Enums.Operation_Table.PUSHARGQ: + LSO_Enums.Rotation r = new LSO_Enums.Rotation(); + r.S = BitConverter.ToUInt32(br_read(4), 0); + r.Z = BitConverter.ToUInt32(br_read(4), 0); + r.Y = BitConverter.ToUInt32(br_read(4), 0); + r.X = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1 S: " + r.S); + Common.SendToDebug("Param1 Z: " + r.Z); + Common.SendToDebug("Param1 Y: " + r.Y); + Common.SendToDebug("Param1 X: " + r.X); + IL_Push(il, r); + break; + + case LSO_Enums.Operation_Table.PUSHE: + IL_Push(il, (UInt32) 0); + break; + + case LSO_Enums.Operation_Table.PUSHARGE: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1); + //IL_Push(il, new string(" ".ToCharArray()[0], Convert.ToInt32(u32p1))); + IL_Push(il, u32p1); + break; + // BYTE + case LSO_Enums.Operation_Table.ADD: + case LSO_Enums.Operation_Table.SUB: + case LSO_Enums.Operation_Table.MUL: + case LSO_Enums.Operation_Table.DIV: + case LSO_Enums.Operation_Table.EQ: + case LSO_Enums.Operation_Table.NEQ: + case LSO_Enums.Operation_Table.LEQ: + case LSO_Enums.Operation_Table.GEQ: + case LSO_Enums.Operation_Table.LESS: + case LSO_Enums.Operation_Table.GREATER: + case LSO_Enums.Operation_Table.NEG: + case LSO_Enums.Operation_Table.MOD: + bp1 = br_read(1)[0]; + Common.SendToDebug("Param1: " + bp1); + IL_CallBaseFunction(il, idesc, (UInt32) bp1); + break; + + // NO ARGUMENTS + case LSO_Enums.Operation_Table.BITAND: + case LSO_Enums.Operation_Table.BITOR: + case LSO_Enums.Operation_Table.BITXOR: + case LSO_Enums.Operation_Table.BOOLAND: + case LSO_Enums.Operation_Table.BOOLOR: + case LSO_Enums.Operation_Table.BITNOT: + case LSO_Enums.Operation_Table.BOOLNOT: + IL_CallBaseFunction(il, idesc); + break; + // SHORT + case LSO_Enums.Operation_Table.CALLLIB_TWO_BYTE: + // TODO: What is size of short? + UInt16 U16p1 = BitConverter.ToUInt16(br_read(2), 0); + Common.SendToDebug("Instruction " + idesc + ": Builtin Command: " + + ((LSO_Enums.BuiltIn_Functions) U16p1).ToString()); + //Common.SendToDebug("Param1: " + U16p1); + string fname = ((LSO_Enums.BuiltIn_Functions) U16p1).ToString(); + + bool cmdFound = false; + foreach (MethodInfo mi in typeof (LSL_BuiltIn_Commands_Interface).GetMethods()) + { + // Found command + if (mi.Name == fname) + { + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod("GetLSL_BuiltIn", new Type[] {})); + // Pop required number of items from my stack to .Net stack + IL_PopToStack(il, mi.GetParameters().Length); + il.Emit(OpCodes.Callvirt, mi); + cmdFound = true; + break; + } + } + if (cmdFound == false) + { + Common.SendToDebug("ERROR: UNABLE TO LOCATE OPCODE " + idesc + " IN BASECLASS"); + } + + break; + + // RETURN + case LSO_Enums.Operation_Table.RETURN: + + Common.SendToDebug("OPCODE: RETURN"); + return true; + + case LSO_Enums.Operation_Table.POP: + case LSO_Enums.Operation_Table.POPS: + case LSO_Enums.Operation_Table.POPL: + case LSO_Enums.Operation_Table.POPV: + case LSO_Enums.Operation_Table.POPQ: + // Pops a specific datatype from the stack + // We just ignore the datatype for now + IL_Pop(il); + break; + + // LONG + case LSO_Enums.Operation_Table.STORE: + case LSO_Enums.Operation_Table.STORES: + case LSO_Enums.Operation_Table.STOREL: + case LSO_Enums.Operation_Table.STOREV: + case LSO_Enums.Operation_Table.STOREQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToLocal", u32p1); + break; + + case LSO_Enums.Operation_Table.STOREG: + case LSO_Enums.Operation_Table.STOREGS: + case LSO_Enums.Operation_Table.STOREGL: + case LSO_Enums.Operation_Table.STOREGV: + case LSO_Enums.Operation_Table.STOREGQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToGlobal", u32p1); + break; + + case LSO_Enums.Operation_Table.LOADP: + case LSO_Enums.Operation_Table.LOADSP: + case LSO_Enums.Operation_Table.LOADLP: + case LSO_Enums.Operation_Table.LOADVP: + case LSO_Enums.Operation_Table.LOADQP: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToLocal", u32p1); + IL_Pop(il); + break; + + case LSO_Enums.Operation_Table.LOADGP: + case LSO_Enums.Operation_Table.LOADGSP: + case LSO_Enums.Operation_Table.LOADGLP: + case LSO_Enums.Operation_Table.LOADGVP: + case LSO_Enums.Operation_Table.LOADGQP: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToStatic", u32p1 - 6 + myHeader.GVR); + IL_Pop(il); + break; + + // PUSH FROM LOCAL FRAME + case LSO_Enums.Operation_Table.PUSH: + case LSO_Enums.Operation_Table.PUSHS: + case LSO_Enums.Operation_Table.PUSHL: + case LSO_Enums.Operation_Table.PUSHV: + case LSO_Enums.Operation_Table.PUSHQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "GetFromLocal", u32p1); + + break; + + // PUSH FROM STATIC FRAME + case LSO_Enums.Operation_Table.PUSHG: + case LSO_Enums.Operation_Table.PUSHGS: + case LSO_Enums.Operation_Table.PUSHGL: + case LSO_Enums.Operation_Table.PUSHGV: + case LSO_Enums.Operation_Table.PUSHGQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "GetFromStatic", u32p1 - 6 + myHeader.GVR); + break; + + + /*********************** + * NOT IMPLEMENTED YET * + ***********************/ + + + case LSO_Enums.Operation_Table.POPIP: + case LSO_Enums.Operation_Table.POPSP: + case LSO_Enums.Operation_Table.POPSLR: + case LSO_Enums.Operation_Table.POPARG: + case LSO_Enums.Operation_Table.POPBP: + //Common.SendToDebug("Instruction " + idesc + ": Ignored"); + Common.SendToDebug("Instruction " + idesc + + ": Description: Drop x bytes from the stack (TODO: Only popping 1)"); + //Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + IL_Pop(il); + break; + + + // None + case LSO_Enums.Operation_Table.PUSHIP: + // PUSH INSTRUCTION POINTER + break; + case LSO_Enums.Operation_Table.PUSHBP: + + case LSO_Enums.Operation_Table.PUSHEV: + break; + case LSO_Enums.Operation_Table.PUSHEQ: + break; + + + // LONG + case LSO_Enums.Operation_Table.JUMP: + Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + break; + // BYTE, LONG + case LSO_Enums.Operation_Table.JUMPIF: + case LSO_Enums.Operation_Table.JUMPNIF: + Common.SendToDebug("Param1: " + br_read(1)[0]); + Common.SendToDebug("Param2: " + BitConverter.ToUInt32(br_read(4), 0)); + break; + // LONG + case LSO_Enums.Operation_Table.STATE: + bp1 = br_read(1)[0]; + //il.Emit(OpCodes.Ld); // Load local variable 0 onto stack + //il.Emit(OpCodes.Ldc_I4, 0); // Push index position + //il.Emit(OpCodes.Ldstr, EventList[p1]); // Push value + //il.Emit(OpCodes.Stelem_Ref); // Perform array[index] = value + break; + case LSO_Enums.Operation_Table.CALL: + Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + Common.SendToDebug("ERROR: Function CALL not implemented yet."); + break; + // BYTE + case LSO_Enums.Operation_Table.CAST: + bp1 = br_read(1)[0]; + Common.SendToDebug("Instruction " + idesc + ": Cast to type: " + + ((LSO_Enums.OpCode_Cast_TypeDefs) bp1)); + Common.SendToDebug("Param1: " + bp1); + switch ((LSO_Enums.OpCode_Cast_TypeDefs) bp1) + { + case LSO_Enums.OpCode_Cast_TypeDefs.String: + Common.SendToDebug("Instruction " + idesc + ": il.Emit(OpCodes.Box, ILStack.Pop());"); + break; + default: + Common.SendToDebug("Instruction " + idesc + ": Unknown cast type!"); + break; + } + break; + // LONG + case LSO_Enums.Operation_Table.STACKTOS: + case LSO_Enums.Operation_Table.STACKTOL: + Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + break; + // BYTE + case LSO_Enums.Operation_Table.PRINT: + case LSO_Enums.Operation_Table.CALLLIB: + Common.SendToDebug("Param1: " + br_read(1)[0]); + break; + } + return false; + } + + private void IL_PopToStack(ILGenerator il) + { + IL_PopToStack(il, 1); + } + + private void IL_PopToStack(ILGenerator il, int count) + { + Common.SendToDebug("IL_PopToStack();"); + for (int i = 0; i < count; i++) + { + IL_CallBaseFunction(il, "POPToStack"); + //il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Call, + // typeof(LSL_BaseClass).GetMethod("POPToStack", + // new Type[] { })); + } + } + + private void IL_Pop(ILGenerator il) + { + Common.SendToDebug("IL_Pop();"); + IL_CallBaseFunction(il, "POP"); + } + + private void IL_Debug(ILGenerator il, string text) + { + il.Emit(OpCodes.Ldstr, text); + il.Emit(OpCodes.Call, typeof (Common).GetMethod("SendToDebug", + new Type[] {typeof (string)} + )); + } + + private void IL_CallBaseFunction(ILGenerator il, string methodname) + { + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod(methodname, new Type[] {})); + } + + private void IL_CallBaseFunction(ILGenerator il, string methodname, object data) + { + il.Emit(OpCodes.Ldarg_0); + if (data.GetType() == typeof (string)) + il.Emit(OpCodes.Ldstr, (string) data); + if (data.GetType() == typeof (UInt32)) + il.Emit(OpCodes.Ldc_I4, (UInt32) data); + il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod(methodname, new Type[] {data.GetType()})); + } + + private void IL_Push(ILGenerator il, object data) + { + il.Emit(OpCodes.Ldarg_0); + Common.SendToDebug("PUSH datatype: " + data.GetType()); + + IL_PushDataTypeToILStack(il, data); + + il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod("PUSH", new Type[] {data.GetType()})); + } + + private void IL_PushDataTypeToILStack(ILGenerator il, object data) + { + if (data.GetType() == typeof (UInt16)) + { + il.Emit(OpCodes.Ldc_I4, (UInt16) data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof (UInt32)) + { + il.Emit(OpCodes.Ldc_I4, (UInt32) data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof (Int32)) + { + il.Emit(OpCodes.Ldc_I4, (Int32) data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof (float)) + { + il.Emit(OpCodes.Ldc_I4, (float) data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof (string)) + il.Emit(OpCodes.Ldstr, (string) data); + //if (data.GetType() == typeof(LSO_Enums.Rotation)) + // il.Emit(OpCodes.Ldobj, (LSO_Enums.Rotation)data); + //if (data.GetType() == typeof(LSO_Enums.Vector)) + // il.Emit(OpCodes.Ldobj, (LSO_Enums.Vector)data); + //if (data.GetType() == typeof(LSO_Enums.Key)) + // il.Emit(OpCodes.Ldobj, (LSO_Enums.Key)data); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Enums.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Enums.cs new file mode 100644 index 0000000000..ea84efd850 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Enums.cs @@ -0,0 +1,560 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + public static class LSO_Enums + { + //public System.Collections.Generic.Dictionary OpCode_Add_Types; + + //LSO_Enums() { + // OpCode_Add_Types.Add(51, typeof(String)); + // OpCode_Add_Types.Add(17, typeof(UInt32)); + //} + + [Serializable] + public enum OpCode_Add_TypeDefs + { + String = 51, + UInt32 = 17 + } + + [Serializable] + public enum OpCode_Cast_TypeDefs + { + String = 19 + } + + [Serializable] + public struct Key + { + public string KeyString; + } + + [Serializable] + public struct Vector + { + public UInt32 Z; + public UInt32 Y; + public UInt32 X; + } + + [Serializable] + public struct Rotation + { + public UInt32 S; + public UInt32 Z; + public UInt32 Y; + public UInt32 X; + } + + [Serializable] + public enum Variable_Type_Codes + { + Void = 0, + Integer = 1, + Float = 2, + String = 3, + Key = 4, + Vector = 5, + Rotation = 6, + List = 7, + Null = 8 + } + + [Serializable] + public enum Event_Mask_Values + { + state_entry = 0, + state_exit = 1, + touch_start = 2, + touch = 3, + touch_end = 4, + collision_start = 5, + collision = 6, + collision_end = 7, + land_collision_start = 8, + land_collision = 9, + land_collision_end = 10, + timer = 11, + listen = 12, + on_rez = 13, + sensor = 14, + no_sensor = 15, + control = 16, + money = 17, + email = 18, + at_target = 19, + not_at_target = 20, + at_rot_target = 21, + not_at_rot_target = 22, + run_time_permissions = 23, + changed = 24, + attach = 25, + dataserver = 26, + link_message = 27, + moving_start = 28, + moving_end = 29, + object_rez = 30, + remote_data = 31, + http_response = 32 + } + + [Serializable] + public enum Operation_Table + { + NOOP = 0x0, + POP = 0x1, + POPS = 0x2, + POPL = 0x3, + POPV = 0x4, + POPQ = 0x5, + POPARG = 0x6, + POPIP = 0x7, + POPBP = 0x8, + POPSP = 0x9, + POPSLR = 0xa, + DUP = 0x20, + DUPS = 0x21, + DUPL = 0x22, + DUPV = 0x23, + DUPQ = 0x24, + STORE = 0x30, + STORES = 0x31, + STOREL = 0x32, + STOREV = 0x33, + STOREQ = 0x34, + STOREG = 0x35, + STOREGS = 0x36, + STOREGL = 0x37, + STOREGV = 0x38, + STOREGQ = 0x39, + LOADP = 0x3a, + LOADSP = 0x3b, + LOADLP = 0x3c, + LOADVP = 0x3d, + LOADQP = 0x3e, + LOADGP = 0x3f, + LOADGSP = 0x40, + LOADGLP = 0x41, + LOADGVP = 0x42, + LOADGQP = 0x43, + PUSH = 0x50, + PUSHS = 0x51, + PUSHL = 0x52, + PUSHV = 0x53, + PUSHQ = 0x54, + PUSHG = 0x55, + PUSHGS = 0x56, + PUSHGL = 0x57, + PUSHGV = 0x58, + PUSHGQ = 0x59, + PUSHIP = 0x5a, + PUSHBP = 0x5b, + PUSHSP = 0x5c, + PUSHARGB = 0x5d, + PUSHARGI = 0x5e, + PUSHARGF = 0x5f, + PUSHARGS = 0x60, + PUSHARGV = 0x61, + PUSHARGQ = 0x62, + PUSHE = 0x63, + PUSHEV = 0x64, + PUSHEQ = 0x65, + PUSHARGE = 0x66, + ADD = 0x70, + SUB = 0x71, + MUL = 0x72, + DIV = 0x73, + MOD = 0x74, + EQ = 0x75, + NEQ = 0x76, + LEQ = 0x77, + GEQ = 0x78, + LESS = 0x79, + GREATER = 0x7a, + BITAND = 0x7b, + BITOR = 0x7c, + BITXOR = 0x7d, + BOOLAND = 0x7e, + BOOLOR = 0x7f, + NEG = 0x80, + BITNOT = 0x81, + BOOLNOT = 0x82, + JUMP = 0x90, + JUMPIF = 0x91, + JUMPNIF = 0x92, + STATE = 0x93, + CALL = 0x94, + RETURN = 0x95, + CAST = 0xa0, + STACKTOS = 0xb0, + STACKTOL = 0xb1, + PRINT = 0xc0, + CALLLIB = 0xd0, + CALLLIB_TWO_BYTE = 0xd1, + SHL = 0xe0, + SHR = 0xe1 + } + + [Serializable] + public enum BuiltIn_Functions + { + llSin = 0, + llCos = 1, + llTan = 2, + llAtan2 = 3, + llSqrt = 4, + llPow = 5, + llAbs = 6, + llFabs = 7, + llFrand = 8, + llFloor = 9, + llCeil = 10, + llRound = 11, + llVecMag = 12, + llVecNorm = 13, + llVecDist = 14, + llRot2Euler = 15, + llEuler2Rot = 16, + llAxes2Rot = 17, + llRot2Fwd = 18, + llRot2Left = 19, + llRot2Up = 20, + llRotBetween = 21, + llWhisper = 22, + llSay = 23, + llShout = 24, + llListen = 25, + llListenControl = 26, + llListenRemove = 27, + llSensor = 28, + llSensorRepeat = 29, + llSensorRemove = 30, + llDetectedName = 31, + llDetectedKey = 32, + llDetectedOwner = 33, + llDetectedType = 34, + llDetectedPos = 35, + llDetectedVel = 36, + llDetectedGrab = 37, + llDetectedRot = 38, + llDetectedGroup = 39, + llDetectedLinkNumber = 40, + llDie = 41, + llGround = 42, + llCloud = 43, + llWind = 44, + llSetStatus = 45, + llGetStatus = 46, + llSetScale = 47, + llGetScale = 48, + llSetColor = 49, + llGetAlpha = 50, + llSetAlpha = 51, + llGetColor = 52, + llSetTexture = 53, + llScaleTexture = 54, + llOffsetTexture = 55, + llRotateTexture = 56, + llGetTexture = 57, + llSetPos = 58, + llGetPos = 59, + llGetLocalPos = 60, + llSetRot = 61, + llGetRot = 62, + llGetLocalRot = 63, + llSetForce = 64, + llGetForce = 65, + llTarget = 66, + llTargetRemove = 67, + llRotTarget = 68, + llRotTargetRemove = 69, + llMoveToTarget = 70, + llStopMoveToTarget = 71, + llApplyImpulse = 72, + llApplyRotationalImpulse = 73, + llSetTorque = 74, + llGetTorque = 75, + llSetForceAndTorque = 76, + llGetVel = 77, + llGetAccel = 78, + llGetOmega = 79, + llGetTimeOfDay = 80, + llGetWallclock = 81, + llGetTime = 82, + llResetTime = 83, + llGetAndResetTime = 84, + llSound = 85, + llPlaySound = 86, + llLoopSound = 87, + llLoopSoundMaster = 88, + llLoopSoundSlave = 89, + llPlaySoundSlave = 90, + llTriggerSound = 91, + llStopSound = 92, + llPreloadSound = 93, + llGetSubString = 94, + llDeleteSubString = 95, + llInsertString = 96, + llToUpper = 97, + llToLower = 98, + llGiveMoney = 99, + llMakeExplosion = 100, + llMakeFountain = 101, + llMakeSmoke = 102, + llMakeFire = 103, + llRezObject = 104, + llLookAt = 105, + llStopLookAt = 106, + llSetTimerEvent = 107, + llSleep = 108, + llGetMass = 109, + llCollisionFilter = 110, + llTakeControls = 111, + llReleaseControls = 112, + llAttachToAvatar = 113, + llDetachFromAvatar = 114, + llTakeCamera = 115, + llReleaseCamera = 116, + llGetOwner = 117, + llInstantMessage = 118, + llEmail = 119, + llGetNextEmail = 120, + llGetKey = 121, + llSetBuoyancy = 122, + llSetHoverHeight = 123, + llStopHover = 124, + llMinEventDelay = 125, + llSoundPreload = 126, + llRotLookAt = 127, + llStringLength = 128, + llStartAnimation = 129, + llStopAnimation = 130, + llPointAt = 131, + llStopPointAt = 132, + llTargetOmega = 133, + llGetStartParameter = 134, + llGodLikeRezObject = 135, + llRequestPermissions = 136, + llGetPermissionsKey = 137, + llGetPermissions = 138, + llGetLinkNumber = 139, + llSetLinkColor = 140, + llCreateLink = 141, + llBreakLink = 142, + llBreakAllLinks = 143, + llGetLinkKey = 144, + llGetLinkName = 145, + llGetInventoryNumber = 146, + llGetInventoryName = 147, + llSetScriptState = 148, + llGetEnergy = 149, + llGiveInventory = 150, + llRemoveInventory = 151, + llSetText = 152, + llWater = 153, + llPassTouches = 154, + llRequestAgentData = 155, + llRequestInventoryData = 156, + llSetDamage = 157, + llTeleportAgentHome = 158, + llModifyLand = 159, + llCollisionSound = 160, + llCollisionSprite = 161, + llGetAnimation = 162, + llResetScript = 163, + llMessageLinked = 164, + llPushObject = 165, + llPassCollisions = 166, + llGetScriptName = 167, + llGetNumberOfSides = 168, + llAxisAngle2Rot = 169, + llRot2Axis = 170, + llRot2Angle = 171, + llAcos = 172, + llAsin = 173, + llAngleBetween = 174, + llGetInventoryKey = 175, + llAllowInventoryDrop = 176, + llGetSunDirection = 177, + llGetTextureOffset = 178, + llGetTextureScale = 179, + llGetTextureRot = 180, + llSubStringIndex = 181, + llGetOwnerKey = 182, + llGetCenterOfMass = 183, + llListSort = 184, + llGetListLength = 185, + llList2Integer = 186, + llList2Float = 187, + llList2String = 188, + llList2Key = 189, + llList2Vector = 190, + llList2Rot = 191, + llList2List = 192, + llDeleteSubList = 193, + llGetListEntryType = 194, + llList2CSV = 195, + llCSV2List = 196, + llListRandomize = 197, + llList2ListStrided = 198, + llGetRegionCorner = 199, + llListInsertList = 200, + llListFindList = 201, + llGetObjectName = 202, + llSetObjectName = 203, + llGetDate = 204, + llEdgeOfWorld = 205, + llGetAgentInfo = 206, + llAdjustSoundVolume = 207, + llSetSoundQueueing = 208, + llSetSoundRadius = 209, + llKey2Name = 210, + llSetTextureAnim = 211, + llTriggerSoundLimited = 212, + llEjectFromLand = 213, + llParseString2List = 214, + llOverMyLand = 215, + llGetLandOwnerAt = 216, + llGetNotecardLine = 217, + llGetAgentSize = 218, + llSameGroup = 219, + llUnSit = 220, + llGroundSlope = 221, + llGroundNormal = 222, + llGroundContour = 223, + llGetAttached = 224, + llGetFreeMemory = 225, + llGetRegionName = 226, + llGetRegionTimeDilation = 227, + llGetRegionFPS = 228, + llParticleSystem = 229, + llGroundRepel = 230, + llGiveInventoryList = 231, + llSetVehicleType = 232, + llSetVehicleFloatParam = 233, + llSetVehicleVectorParam = 234, + llSetVehicleRotationParam = 235, + llSetVehicleFlags = 236, + llRemoveVehicleFlags = 237, + llSitTarget = 238, + llAvatarOnSitTarget = 239, + llAddToLandPassList = 240, + llSetTouchText = 241, + llSetSitText = 242, + llSetCameraEyeOffset = 243, + llSetCameraAtOffset = 244, + llDumpList2String = 245, + llScriptDanger = 246, + llDialog = 247, + llVolumeDetect = 248, + llResetOtherScript = 249, + llGetScriptState = 250, + llRemoteLoadScript = 251, + llSetRemoteScriptAccessPin = 252, + llRemoteLoadScriptPin = 253, + llOpenRemoteDataChannel = 254, + llSendRemoteData = 255, + llRemoteDataReply = 256, + llCloseRemoteDataChannel = 257, + llMD5String = 258, + llSetPrimitiveParams = 259, + llStringToBase64 = 260, + llBase64ToString = 261, + llXorBase64Strings = 262, + llRemoteDataSetRegion = 263, + llLog10 = 264, + llLog = 265, + llGetAnimationList = 266, + llSetParcelMusicURL = 267, + llGetRootPosition = 268, + llGetRootRotation = 269, + llGetObjectDesc = 270, + llSetObjectDesc = 271, + llGetCreator = 272, + llGetTimestamp = 273, + llSetLinkAlpha = 274, + llGetNumberOfPrims = 275, + llGetNumberOfNotecardLines = 276, + llGetBoundingBox = 277, + llGetGeometricCenter = 278, + llGetPrimitiveParams = 279, + llIntegerToBase64 = 280, + llBase64ToInteger = 281, + llGetGMTclock = 282, + llGetSimulatorHostname = 283, + llSetLocalRot = 284, + llParseStringKeepNulls = 285, + llRezAtRoot = 286, + llGetObjectPermMask = 287, + llSetObjectPermMask = 288, + llGetInventoryPermMask = 289, + llSetInventoryPermMask = 290, + llGetInventoryCreator = 291, + llOwnerSay = 292, + llRequestSimulatorData = 293, + llForceMouselook = 294, + llGetObjectMass = 295, + llListReplaceList = 296, + llLoadURL = 297, + llParcelMediaCommandList = 298, + llParcelMediaQuery = 299, + llModPow = 300, + llGetInventoryType = 301, + llSetPayPrice = 302, + llGetCameraPos = 303, + llGetCameraRot = 304, + llSetPrimURL = 305, + llRefreshPrimURL = 306, + llEscapeURL = 307, + llUnescapeURL = 308, + llMapDestination = 309, + llAddToLandBanList = 310, + llRemoveFromLandPassList = 311, + llRemoveFromLandBanList = 312, + llSetCameraParams = 313, + llClearCameraParams = 314, + llListStatistics = 315, + llGetUnixTime = 316, + llGetParcelFlags = 317, + llGetRegionFlags = 318, + llXorBase64StringsCorrect = 319, + llHTTPRequest = 320, + llResetLandBanList = 321, + llResetLandPassList = 322, + llGetParcelPrimCount = 323, + llGetParcelPrimOwners = 324, + llGetObjectPrimCount = 325, + llGetParcelMaxPrims = 326, + llGetParcelDetails = 327 + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Parser.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Parser.cs new file mode 100644 index 0000000000..e1fff5c726 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Parser.cs @@ -0,0 +1,729 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using OpenSim.Region.ScriptEngine.LSOEngine.LSO; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + internal partial class LSO_Parser + { + private string FileName; + private FileStream fs; + private BinaryReader br; + internal LSO_Struct.Header myHeader; + internal Dictionary StaticBlocks = new Dictionary(); + //private System.Collections.Hashtable StaticBlocks = new System.Collections.Hashtable(); + + private TypeBuilder typeBuilder; + private List EventList = new List(); + + public LSO_Parser(string _FileName, TypeBuilder _typeBuilder) + { + FileName = _FileName; + typeBuilder = _typeBuilder; + } + + internal void OpenFile() + { + // Open + Common.SendToDebug("Opening filename: " + FileName); + fs = File.Open(FileName, FileMode.Open, FileAccess.Read, FileShare.Read); + br = new BinaryReader(fs, Encoding.BigEndianUnicode); + } + + internal void CloseFile() + { + // Close + br.Close(); + fs.Close(); + } + + + /// + /// Parse LSO file. + /// + public void Parse() + { + // The LSO Format consist of 6 major blocks: header, statics, functions, states, heap, and stack. + + + // HEADER BLOCK + Common.SendToDebug("Reading HEADER BLOCK at: 0"); + fs.Seek(0, SeekOrigin.Begin); + myHeader = new LSO_Struct.Header(); + myHeader.TM = BitConverter.ToUInt32(br_read(4), 0); + myHeader.IP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.VN = BitConverter.ToUInt32(br_read(4), 0); + myHeader.BP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.SP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.HR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.HP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.CS = BitConverter.ToUInt32(br_read(4), 0); + myHeader.NS = BitConverter.ToUInt32(br_read(4), 0); + myHeader.CE = BitConverter.ToUInt32(br_read(4), 0); + myHeader.IE = BitConverter.ToUInt32(br_read(4), 0); + myHeader.ER = BitConverter.ToUInt32(br_read(4), 0); + myHeader.FR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.SLR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.GVR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.GFR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.PR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.ESR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.SR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.NCE = BitConverter.ToUInt64(br_read(8), 0); + myHeader.NIE = BitConverter.ToUInt64(br_read(8), 0); + myHeader.NER = BitConverter.ToUInt64(br_read(8), 0); + + // Print Header Block to debug + Common.SendToDebug("TM - Top of memory (size): " + myHeader.TM); + Common.SendToDebug("IP - Instruction Pointer (0=not running): " + myHeader.IP); + Common.SendToDebug("VN - Version number: " + myHeader.VN); + Common.SendToDebug("BP - Local Frame Pointer: " + myHeader.BP); + Common.SendToDebug("SP - Stack Pointer: " + myHeader.SP); + Common.SendToDebug("HR - Heap Register: " + myHeader.HR); + Common.SendToDebug("HP - Heap Pointer: " + myHeader.HP); + Common.SendToDebug("CS - Current State: " + myHeader.CS); + Common.SendToDebug("NS - Next State: " + myHeader.NS); + Common.SendToDebug("CE - Current Events: " + myHeader.CE); + Common.SendToDebug("IE - In Event: " + myHeader.IE); + Common.SendToDebug("ER - Event Register: " + myHeader.ER); + Common.SendToDebug("FR - Fault Register: " + myHeader.FR); + Common.SendToDebug("SLR - Sleep Register: " + myHeader.SLR); + Common.SendToDebug("GVR - Global Variable Register: " + myHeader.GVR); + Common.SendToDebug("GFR - Global Function Register: " + myHeader.GFR); + Common.SendToDebug("PR - Parameter Register: " + myHeader.PR); + Common.SendToDebug("ESR - Energy Supply Register: " + myHeader.ESR); + Common.SendToDebug("SR - State Register: " + myHeader.SR); + Common.SendToDebug("NCE - 64-bit Current Events: " + myHeader.NCE); + Common.SendToDebug("NIE - 64-bit In Events: " + myHeader.NIE); + Common.SendToDebug("NER - 64-bit Event Register: " + myHeader.NER); + Common.SendToDebug("Read position when exiting HEADER BLOCK: " + fs.Position); + + // STATIC BLOCK + Common.SendToDebug("Reading STATIC BLOCK at: " + myHeader.GVR); + fs.Seek(myHeader.GVR, SeekOrigin.Begin); + int StaticBlockCount = 0; + // Read function blocks until we hit GFR + while (fs.Position < myHeader.GFR) + { + StaticBlockCount++; + long startReadPos = fs.Position; + Common.SendToDebug("Reading Static Block " + StaticBlockCount + " at: " + startReadPos); + + //fs.Seek(myHeader.GVR, SeekOrigin.Begin); + LSO_Struct.StaticBlock myStaticBlock = new LSO_Struct.StaticBlock(); + myStaticBlock.Static_Chunk_Header_Size = BitConverter.ToUInt32(br_read(4), 0); + myStaticBlock.ObjectType = br_read(1)[0]; + Common.SendToDebug("Static Block ObjectType: " + + ((LSO_Enums.Variable_Type_Codes) myStaticBlock.ObjectType).ToString()); + myStaticBlock.Unknown = br_read(1)[0]; + // Size of datatype varies -- what about strings? + if (myStaticBlock.ObjectType != 0) + myStaticBlock.BlockVariable = br_read(getObjectSize(myStaticBlock.ObjectType)); + + StaticBlocks.Add((UInt32) startReadPos, myStaticBlock); + } + Common.SendToDebug("Number of Static Blocks read: " + StaticBlockCount); + + + // FUNCTION BLOCK + // Always right after STATIC BLOCK + LSO_Struct.FunctionBlock myFunctionBlock = new LSO_Struct.FunctionBlock(); + if (myHeader.GFR == myHeader.SR) + { + // If GFR and SR are at same position then there is no fuction block + Common.SendToDebug("No FUNCTION BLOCK found"); + } + else + { + Common.SendToDebug("Reading FUNCTION BLOCK at: " + myHeader.GFR); + fs.Seek(myHeader.GFR, SeekOrigin.Begin); + myFunctionBlock.FunctionCount = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Number of functions in Fuction Block: " + myFunctionBlock.FunctionCount); + if (myFunctionBlock.FunctionCount > 0) + { + myFunctionBlock.CodeChunkPointer = new UInt32[myFunctionBlock.FunctionCount]; + for (int i = 0; i < myFunctionBlock.FunctionCount; i++) + { + Common.SendToDebug("Reading function " + i + " at: " + fs.Position); + // TODO: ADD TO FUNCTION LIST (How do we identify it later?) + // Note! Absolute position + myFunctionBlock.CodeChunkPointer[i] = BitConverter.ToUInt32(br_read(4), 0) + myHeader.GFR; + Common.SendToDebug("Fuction " + i + " code chunk position: " + + myFunctionBlock.CodeChunkPointer[i]); + } + } + } + + + // STATE FRAME BLOCK + // Always right after FUNCTION BLOCK + Common.SendToDebug("Reading STATE BLOCK at: " + myHeader.SR); + fs.Seek(myHeader.SR, SeekOrigin.Begin); + LSO_Struct.StateFrameBlock myStateFrameBlock = new LSO_Struct.StateFrameBlock(); + myStateFrameBlock.StateCount = BitConverter.ToUInt32(br_read(4), 0); + if (myStateFrameBlock.StateCount > 0) + { + // Initialize array + myStateFrameBlock.StatePointer = new LSO_Struct.StatePointerBlock[myStateFrameBlock.StateCount]; + for (int i = 0; i < myStateFrameBlock.StateCount; i++) + { + Common.SendToDebug("Reading STATE POINTER BLOCK " + (i + 1) + " at: " + fs.Position); + // Position is relative to state frame + myStateFrameBlock.StatePointer[i].Location = myHeader.SR + BitConverter.ToUInt32(br_read(4), 0); + myStateFrameBlock.StatePointer[i].EventMask = new BitArray(br_read(8)); + Common.SendToDebug("Pointer: " + myStateFrameBlock.StatePointer[i].Location); + Common.SendToDebug("Total potential EventMask bits: " + + myStateFrameBlock.StatePointer[i].EventMask.Count); + + //// Read STATE BLOCK + //long CurPos = fs.Position; + //fs.Seek(CurPos, SeekOrigin.Begin); + } + } + + + // STATE BLOCK + // For each StateFrameBlock there is one StateBlock with multiple event handlers + + if (myStateFrameBlock.StateCount > 0) + { + // Go through all State Frame Pointers found + for (int i = 0; i < myStateFrameBlock.StateCount; i++) + { + fs.Seek(myStateFrameBlock.StatePointer[i].Location, SeekOrigin.Begin); + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " at: " + fs.Position); + + // READ: STATE BLOCK HEADER + myStateFrameBlock.StatePointer[i].StateBlock = new LSO_Struct.StateBlock(); + myStateFrameBlock.StatePointer[i].StateBlock.StartPos = (UInt32) fs.Position; // Note + myStateFrameBlock.StatePointer[i].StateBlock.HeaderSize = BitConverter.ToUInt32(br_read(4), 0); + myStateFrameBlock.StatePointer[i].StateBlock.Unknown = br_read(1)[0]; + myStateFrameBlock.StatePointer[i].StateBlock.EndPos = (UInt32) fs.Position; // Note + Common.SendToDebug("State block Start Pos: " + myStateFrameBlock.StatePointer[i].StateBlock.StartPos); + Common.SendToDebug("State block Header Size: " + + myStateFrameBlock.StatePointer[i].StateBlock.HeaderSize); + Common.SendToDebug("State block Header End Pos: " + + myStateFrameBlock.StatePointer[i].StateBlock.EndPos); + + // We need to count number of bits flagged in EventMask? + + + // for each bit in myStateFrameBlock.StatePointer[i].EventMask + + // ADDING TO ALL RIGHT NOW, SHOULD LIMIT TO ONLY THE ONES IN USE + //TODO: Create event hooks + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers = + new LSO_Struct.StateBlockHandler[myStateFrameBlock.StatePointer[i].EventMask.Count - 1]; + for (int ii = 0; ii < myStateFrameBlock.StatePointer[i].EventMask.Count - 1; ii++) + { + if (myStateFrameBlock.StatePointer[i].EventMask.Get(ii) == true) + { + // We got an event + // READ: STATE BLOCK HANDLER + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER matching EVENT MASK " + ii + + " (" + ((LSO_Enums.Event_Mask_Values) ii).ToString() + ") at: " + + fs.Position); + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer = + myStateFrameBlock.StatePointer[i].StateBlock.EndPos + + BitConverter.ToUInt32(br_read(4), 0); + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CallFrameSize = + BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER EVENT MASK " + ii + " (" + + ((LSO_Enums.Event_Mask_Values) ii).ToString() + ") Code Chunk Pointer: " + + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii]. + CodeChunkPointer); + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER EVENT MASK " + ii + " (" + + ((LSO_Enums.Event_Mask_Values) ii).ToString() + ") Call Frame Size: " + + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii]. + CallFrameSize); + } + } + } + } + + + //// READ FUNCTION CODE CHUNKS + //// Functions + Function start pos (GFR) + //// TODO: Somehow be able to identify and reference this + //LSO_Struct.CodeChunk[] myFunctionCodeChunk; + //if (myFunctionBlock.FunctionCount > 0) + //{ + // myFunctionCodeChunk = new LSO_Struct.CodeChunk[myFunctionBlock.FunctionCount]; + // for (int i = 0; i < myFunctionBlock.FunctionCount; i++) + // { + // Common.SendToDebug("Reading Function Code Chunk " + i); + // myFunctionCodeChunk[i] = GetCodeChunk((UInt32)myFunctionBlock.CodeChunkPointer[i]); + // } + + //} + // READ EVENT CODE CHUNKS + LSO_Struct.CodeChunk[] myEventCodeChunk; + if (myStateFrameBlock.StateCount > 0) + { + myEventCodeChunk = new LSO_Struct.CodeChunk[myStateFrameBlock.StateCount]; + for (int i = 0; i < myStateFrameBlock.StateCount; i++) + { + // TODO: Somehow organize events and functions so they can be found again, + // two level search ain't no good + for (int ii = 0; ii < myStateFrameBlock.StatePointer[i].EventMask.Count - 1; ii++) + { + if (myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer > 0) + { + Common.SendToDebug("Reading Event Code Chunk state " + i + ", event " + + (LSO_Enums.Event_Mask_Values) ii); + + + // Override a Method / Function + string eventname = i + "_event_" + (LSO_Enums.Event_Mask_Values) ii; + Common.SendToDebug("Event Name: " + eventname); + if (Common.IL_ProcessCodeChunks) + { + EventList.Add(eventname); + + // JUMP TO CODE PROCESSOR + ProcessCodeChunk( + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer, + typeBuilder, eventname); + } + } + } + } + } + + + if (Common.IL_CreateFunctionList) + IL_INSERT_FUNCTIONLIST(); + } + + internal LSO_Struct.HeapBlock GetHeap(UInt32 pos) + { + // HEAP BLOCK + // TODO:? Special read for strings/keys (null terminated) and lists (pointers to other HEAP entries) + Common.SendToDebug("Reading HEAP BLOCK at: " + pos); + fs.Seek(pos, SeekOrigin.Begin); + + LSO_Struct.HeapBlock myHeapBlock = new LSO_Struct.HeapBlock(); + myHeapBlock.DataBlockSize = BitConverter.ToInt32(br_read(4), 0); + myHeapBlock.ObjectType = br_read(1)[0]; + myHeapBlock.ReferenceCount = BitConverter.ToUInt16(br_read(2), 0); + //myHeapBlock.Data = br_read(getObjectSize(myHeapBlock.ObjectType)); + // Don't read it reversed + myHeapBlock.Data = new byte[myHeapBlock.DataBlockSize - 1]; + br.Read(myHeapBlock.Data, 0, myHeapBlock.DataBlockSize - 1); + + + Common.SendToDebug("Heap Block Data Block Size: " + myHeapBlock.DataBlockSize); + Common.SendToDebug("Heap Block ObjectType: " + + ((LSO_Enums.Variable_Type_Codes) myHeapBlock.ObjectType).ToString()); + Common.SendToDebug("Heap Block Reference Count: " + myHeapBlock.ReferenceCount); + + return myHeapBlock; + } + + private byte[] br_read(int len) + { + if (len <= 0) + return null; + + try + { + byte[] bytes = new byte[len]; + for (int i = len - 1; i > -1; i--) + bytes[i] = br.ReadByte(); + return bytes; + } + catch (Exception e) // NOTLEGIT: No user related exceptions throwable here? + { + Common.SendToDebug("Exception: " + e.ToString()); + throw (e); + } + } + + //private byte[] br_read_smallendian(int len) + //{ + // byte[] bytes = new byte[len]; + // br.Read(bytes,0, len); + // return bytes; + //} + private Type getLLObjectType(byte objectCode) + { + switch ((LSO_Enums.Variable_Type_Codes) objectCode) + { + case LSO_Enums.Variable_Type_Codes.Void: + return typeof (void); + case LSO_Enums.Variable_Type_Codes.Integer: + return typeof (UInt32); + case LSO_Enums.Variable_Type_Codes.Float: + return typeof (float); + case LSO_Enums.Variable_Type_Codes.String: + return typeof (string); + case LSO_Enums.Variable_Type_Codes.Key: + return typeof (string); + case LSO_Enums.Variable_Type_Codes.Vector: + return typeof (LSO_Enums.Vector); + case LSO_Enums.Variable_Type_Codes.Rotation: + return typeof (LSO_Enums.Rotation); + case LSO_Enums.Variable_Type_Codes.List: + Common.SendToDebug("TODO: List datatype not implemented yet!"); + return typeof (ArrayList); + case LSO_Enums.Variable_Type_Codes.Null: + Common.SendToDebug("TODO: Datatype null is not implemented, using string instead.!"); + return typeof (string); + default: + Common.SendToDebug("Lookup of LSL datatype " + objectCode + + " to .Net datatype failed: Unknown LSL datatype. Defaulting to object."); + return typeof (object); + } + } + + private int getObjectSize(byte ObjectType) + { + switch ((LSO_Enums.Variable_Type_Codes) ObjectType) + { + case LSO_Enums.Variable_Type_Codes.Integer: + case LSO_Enums.Variable_Type_Codes.Float: + case LSO_Enums.Variable_Type_Codes.String: + case LSO_Enums.Variable_Type_Codes.Key: + case LSO_Enums.Variable_Type_Codes.List: + return 4; + case LSO_Enums.Variable_Type_Codes.Vector: + return 12; + case LSO_Enums.Variable_Type_Codes.Rotation: + return 16; + default: + return 0; + } + } + + private string Read_String() + { + string ret = String.Empty; + byte reader = br_read(1)[0]; + while (reader != 0x000) + { + ret += (char) reader; + reader = br_read(1)[0]; + } + return ret; + } + + /// + /// Reads a code chunk and creates IL + /// + /// Absolute position in file. REMEMBER TO ADD myHeader.GFR! + /// TypeBuilder for assembly + /// Name of event (function) to generate + private void ProcessCodeChunk(UInt32 pos, TypeBuilder typeBuilder, string eventname) + { + LSO_Struct.CodeChunk myCodeChunk = new LSO_Struct.CodeChunk(); + + Common.SendToDebug("Reading Function Code Chunk at: " + pos); + fs.Seek(pos, SeekOrigin.Begin); + myCodeChunk.CodeChunkHeaderSize = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("CodeChunk Header Size: " + myCodeChunk.CodeChunkHeaderSize); + // Read until null + myCodeChunk.Comment = Read_String(); + Common.SendToDebug("Function comment: " + myCodeChunk.Comment); + myCodeChunk.ReturnTypePos = br_read(1)[0]; + myCodeChunk.ReturnType = GetStaticBlock((long) myCodeChunk.ReturnTypePos + (long) myHeader.GVR); + Common.SendToDebug("Return type #" + myCodeChunk.ReturnType.ObjectType + ": " + + ((LSO_Enums.Variable_Type_Codes) myCodeChunk.ReturnType.ObjectType).ToString()); + + + // TODO: How to determine number of codechunks -- does this method work? + myCodeChunk.CodeChunkArguments = new List(); + byte reader = br_read(1)[0]; + reader = br_read(1)[0]; + + // NOTE ON CODE CHUNK ARGUMENTS + // This determins type definition + int ccount = 0; + while (reader != 0x000) + { + ccount++; + Common.SendToDebug("Reading Code Chunk Argument " + ccount); + LSO_Struct.CodeChunkArgument CCA = new LSO_Struct.CodeChunkArgument(); + CCA.FunctionReturnTypePos = reader; + reader = br_read(1)[0]; + CCA.NullString = reader; + CCA.FunctionReturnType = GetStaticBlock(CCA.FunctionReturnTypePos + myHeader.GVR); + myCodeChunk.CodeChunkArguments.Add(CCA); + Common.SendToDebug("Code Chunk Argument " + ccount + " type #" + CCA.FunctionReturnType.ObjectType + + ": " + (LSO_Enums.Variable_Type_Codes) CCA.FunctionReturnType.ObjectType); + } + // Create string array + Type[] MethodArgs = new Type[myCodeChunk.CodeChunkArguments.Count]; + for (int _ic = 0; _ic < myCodeChunk.CodeChunkArguments.Count; _ic++) + { + MethodArgs[_ic] = getLLObjectType(myCodeChunk.CodeChunkArguments[_ic].FunctionReturnType.ObjectType); + Common.SendToDebug("Method argument " + _ic + ": " + + getLLObjectType(myCodeChunk.CodeChunkArguments[_ic].FunctionReturnType.ObjectType). + ToString()); + } + // End marker is 0x000 + myCodeChunk.EndMarker = reader; + + + // + // Emit: START OF METHOD (FUNCTION) + // + + Common.SendToDebug("CLR:" + eventname + ":MethodBuilder methodBuilder = typeBuilder.DefineMethod..."); + MethodBuilder methodBuilder = typeBuilder.DefineMethod(eventname, + MethodAttributes.Public, + typeof (void), + new Type[] {typeof (object)}); + //MethodArgs); + //typeof(void), //getLLObjectType(myCodeChunk.ReturnType), + // new Type[] { typeof(object) }, //); + + //Common.SendToDebug("CLR:" + eventname + ":typeBuilder.DefineMethodOverride(methodBuilder..."); + //typeBuilder.DefineMethodOverride(methodBuilder, + // typeof(LSL_CLRInterface.LSLScript).GetMethod(eventname)); + + // Create the IL generator + + Common.SendToDebug("CLR:" + eventname + ":ILGenerator il = methodBuilder.GetILGenerator();"); + ILGenerator il = methodBuilder.GetILGenerator(); + + + if (Common.IL_UseTryCatch) + IL_INSERT_TRY(il, eventname); + + + // Push Console.WriteLine command to stack ... Console.WriteLine("Hello World!"); + //Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); + //il.Emit(OpCodes.Call, typeof(Console).GetMethod + // ("WriteLine", new Type[] { typeof(string) })); + + //Common.SendToDebug("STARTUP: il.Emit(OpCodes.Ldc_I4_S, 0);"); + + //il.Emit(OpCodes.Ldc_I4_S, 0); + for (int _ic = 0; _ic < myCodeChunk.CodeChunkArguments.Count; _ic++) + { + Common.SendToDebug("PARAMS: il.Emit(OpCodes.Ldarg, " + _ic + ");"); + il.Emit(OpCodes.Ldarg, _ic); + } + + + // + // CALLING OPCODE PROCESSOR, one command at the time TO GENERATE IL + // + bool FoundRet = false; + while (FoundRet == false) + { + FoundRet = LSL_PROCESS_OPCODE(il); + } + + + if (Common.IL_UseTryCatch) + IL_INSERT_END_TRY(il, eventname); + + // Emit: RETURN FROM METHOD + il.Emit(OpCodes.Ret); + + return; + } + + private void IL_INSERT_FUNCTIONLIST() + { + Common.SendToDebug("Creating function list"); + + + string eventname = "GetFunctions"; + + Common.SendToDebug("Creating IL " + eventname); + // Define a private String field. + //FieldBuilder myField = myTypeBuilder.DefineField("EventList", typeof(String[]), FieldAttributes.Public); + + + //FieldBuilder mem = typeBuilder.DefineField("mem", typeof(Array), FieldAttributes.Private); + + + MethodBuilder methodBuilder = typeBuilder.DefineMethod(eventname, + MethodAttributes.Public, + typeof (string[]), + null); + + //typeBuilder.DefineMethodOverride(methodBuilder, + // typeof(LSL_CLRInterface.LSLScript).GetMethod(eventname)); + + ILGenerator il = methodBuilder.GetILGenerator(); + + + // IL_INSERT_TRY(il, eventname); + + // // Push string to stack + // il.Emit(OpCodes.Ldstr, "Inside " + eventname); + + //// Push Console.WriteLine command to stack ... Console.WriteLine("Hello World!"); + //il.Emit(OpCodes.Call, typeof(Console).GetMethod + // ("WriteLine", new Type[] { typeof(string) })); + + //initIL.Emit(OpCodes.Newobj, typeof(string[])); + + //string[] MyArray = new string[2] { "TestItem1" , "TestItem2" }; + + ////il.Emit(OpCodes.Ldarg_0); + + il.DeclareLocal(typeof (string[])); + + ////il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldc_I4, EventList.Count); // Specify array length + il.Emit(OpCodes.Newarr, typeof (String)); // create new string array + il.Emit(OpCodes.Stloc_0); // Store array as local variable 0 in stack + ////SetFunctionList + + for (int lv = 0; lv < EventList.Count; lv++) + { + il.Emit(OpCodes.Ldloc_0); // Load local variable 0 onto stack + il.Emit(OpCodes.Ldc_I4, lv); // Push index position + il.Emit(OpCodes.Ldstr, EventList[lv]); // Push value + il.Emit(OpCodes.Stelem_Ref); // Perform array[index] = value + + //il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Ldstr, EventList[lv]); // Push value + //il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("AddFunction", new Type[] { typeof(string) })); + } + + + // IL_INSERT_END_TRY(il, eventname); + + + il.Emit(OpCodes.Ldloc_0); // Load local variable 0 onto stack + // il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("SetFunctionList", new Type[] { typeof(Array) })); + + il.Emit(OpCodes.Ret); // Return + } + + + private void IL_INSERT_TRY(ILGenerator il, string eventname) + { + /* + * CLR TRY + */ + //Common.SendToDebug("CLR:" + eventname + ":il.BeginExceptionBlock()"); + il.BeginExceptionBlock(); + + // Push "Hello World!" string to stack + //Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Ldstr..."); + //il.Emit(OpCodes.Ldstr, "Starting CLR dynamic execution of: " + eventname); + } + + private void IL_INSERT_END_TRY(ILGenerator il, string eventname) + { + /* + * CATCH + */ + Common.SendToDebug("CLR:" + eventname + ":il.BeginCatchBlock(typeof(Exception));"); + il.BeginCatchBlock(typeof (Exception)); + + // Push "Hello World!" string to stack + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Ldstr..."); + il.Emit(OpCodes.Ldstr, "Execption executing dynamic CLR function " + eventname + ": "); + + //call void [mscorlib]System.Console::WriteLine(string) + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); + il.Emit(OpCodes.Call, typeof (Console).GetMethod + ("Write", new Type[] {typeof (string)})); + + //callvirt instance string [mscorlib]System.Exception::get_Message() + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Callvirt..."); + il.Emit(OpCodes.Callvirt, typeof (Exception).GetMethod + ("get_Message")); + + //call void [mscorlib]System.Console::WriteLine(string) + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); + il.Emit(OpCodes.Call, typeof (Console).GetMethod + ("WriteLine", new Type[] {typeof (string)})); + + /* + * CLR END TRY + */ + //Common.SendToDebug("CLR:" + eventname + ":il.EndExceptionBlock();"); + il.EndExceptionBlock(); + } + + private LSO_Struct.StaticBlock GetStaticBlock(long pos) + { + long FirstPos = fs.Position; + try + { + UInt32 position = (UInt32) pos; + // STATIC BLOCK + Common.SendToDebug("Reading STATIC BLOCK at: " + position); + fs.Seek(position, SeekOrigin.Begin); + + if (StaticBlocks.ContainsKey(position) == true) + { + Common.SendToDebug("Found cached STATIC BLOCK"); + + + return StaticBlocks[pos]; + } + + //int StaticBlockCount = 0; + // Read function blocks until we hit GFR + //while (fs.Position < myHeader.GFR) + //{ + //StaticBlockCount++; + + //Common.SendToDebug("Reading Static Block at: " + position); + + //fs.Seek(myHeader.GVR, SeekOrigin.Begin); + LSO_Struct.StaticBlock myStaticBlock = new LSO_Struct.StaticBlock(); + myStaticBlock.Static_Chunk_Header_Size = BitConverter.ToUInt32(br_read(4), 0); + myStaticBlock.ObjectType = br_read(1)[0]; + Common.SendToDebug("Static Block ObjectType: " + + ((LSO_Enums.Variable_Type_Codes) myStaticBlock.ObjectType).ToString()); + myStaticBlock.Unknown = br_read(1)[0]; + // Size of datatype varies + if (myStaticBlock.ObjectType != 0) + myStaticBlock.BlockVariable = br_read(getObjectSize(myStaticBlock.ObjectType)); + + StaticBlocks.Add(position, myStaticBlock); + //} + Common.SendToDebug("Done reading Static Block."); + return myStaticBlock; + } + finally + { + // Go back to original read pos + fs.Seek(FirstPos, SeekOrigin.Begin); + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Struct.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Struct.cs new file mode 100644 index 0000000000..b38b0991bb --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Struct.cs @@ -0,0 +1,143 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + internal static class LSO_Struct + { + public struct Header + { + public UInt32 TM; + public UInt32 IP; + public UInt32 VN; + public UInt32 BP; + public UInt32 SP; + public UInt32 HR; + public UInt32 HP; + public UInt32 CS; + public UInt32 NS; + public UInt32 CE; + public UInt32 IE; + public UInt32 ER; + public UInt32 FR; + public UInt32 SLR; + public UInt32 GVR; + public UInt32 GFR; + public UInt32 PR; + public UInt32 ESR; + public UInt32 SR; + public UInt64 NCE; + public UInt64 NIE; + public UInt64 NER; + } + + public struct StaticBlock + { + public UInt32 Static_Chunk_Header_Size; + public byte ObjectType; + public byte Unknown; + public byte[] BlockVariable; + } + + /* Not actually a structure + public struct StaticBlockVariable + { + public UInt32 Integer1; + public UInt32 Float1; + public UInt32 HeapPointer_String; + public UInt32 HeapPointer_Key; + public byte[] Vector_12; + public byte[] Rotation_16; + public UInt32 Pointer_List_Structure; + } */ + + public struct HeapBlock + { + public Int32 DataBlockSize; + public byte ObjectType; + public UInt16 ReferenceCount; + public byte[] Data; + } + + public struct StateFrameBlock + { + public UInt32 StateCount; + public StatePointerBlock[] StatePointer; + } + + public struct StatePointerBlock + { + public UInt32 Location; + public BitArray EventMask; + public StateBlock StateBlock; + } + + public struct StateBlock + { + public UInt32 StartPos; + public UInt32 EndPos; + public UInt32 HeaderSize; + public byte Unknown; + public StateBlockHandler[] StateBlockHandlers; + } + + public struct StateBlockHandler + { + public UInt32 CodeChunkPointer; + public UInt32 CallFrameSize; + } + + public struct FunctionBlock + { + public UInt32 FunctionCount; + public UInt32[] CodeChunkPointer; + } + + public struct CodeChunk + { + public UInt32 CodeChunkHeaderSize; + public string Comment; + public List CodeChunkArguments; + public byte EndMarker; + public byte ReturnTypePos; + public StaticBlock ReturnType; + } + + public struct CodeChunkArgument + { + public byte FunctionReturnTypePos; + public byte NullString; + public StaticBlock FunctionReturnType; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSOScript.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSOScript.cs new file mode 100644 index 0000000000..47dfff260e --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/LSOScript.cs @@ -0,0 +1,50 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Text; +using OpenSim.Region.ScriptEngine.LSOEngine.LSO; + +namespace OpenSim.Region.ScriptEngine.LSOEngine +{ + /// + /// This class encapsulated an LSO file and contains execution-specific data + /// + public class LSOScript + { + private byte[] LSOCode = new byte[1024 * 16]; // Contains the LSO-file + //private System.IO.MemoryStream LSOCode = new MemoryStream(1024 * 16); + + public void Execute(LSO_Enums.Event_Mask_Values Event, params object[] param) + { + + } + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/Properties/AssemblyInfo.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..763a7598df --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* 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.ScriptEngine.LSOEngine")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly: AssemblyProduct("OpenSim.Region.ScriptEngine.LSOEngine")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("2842257e-6fde-4460-9368-4cde57fa9cc4")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/ScriptEngine.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/ScriptEngine.cs new file mode 100644 index 0000000000..2a846a96e8 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/ScriptEngine.cs @@ -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 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; +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; +using EventManager = OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.EventManager; +using ScriptManager=OpenSim.Region.ScriptEngine.LSOEngine.ScriptManager; + +namespace OpenSim.Region.ScriptEngine.LSOEngine +{ + [Serializable] + public class ScriptEngine : OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptEngine + { + // We need to override a few things for our DotNetEngine + public override void Initialise(Scene scene, IConfigSource config) + { + InitializeEngine(scene, config, true, GetScriptManager()); + } + + public override OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptManager _GetScriptManager() + { + return new ScriptManager(this); + } + + public override string ScriptEngineName + { + get { return "ScriptEngine.LSOEngine"; } + } + + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/LSOEngine/ScriptManager.cs b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/ScriptManager.cs new file mode 100644 index 0000000000..f10a11fb72 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/LSOEngine/ScriptManager.cs @@ -0,0 +1,160 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.Serialization.Formatters.Binary; +using System.Threading; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; + +namespace OpenSim.Region.ScriptEngine.LSOEngine +{ + public class ScriptManager : OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptManager + { + public ScriptManager(Common.ScriptEngineBase.ScriptEngine scriptEngine) + : base(scriptEngine) + { + base.m_scriptEngine = scriptEngine; + + } + + // KEEP TRACK OF SCRIPTS + //internal Dictionary> Scripts = new Dictionary>(); + // LOAD SCRIPT + // UNLOAD SCRIPT + // PROVIDE SCRIPT WITH ITS INTERFACE TO OpenSim + + public override void _StartScript(uint localID, LLUUID itemID, string Script) + { + //IScriptHost root = host.GetRoot(); + Console.WriteLine("ScriptManager StartScript: localID: " + localID + ", itemID: " + itemID); + + // We will initialize and start the script. + // It will be up to the script itself to hook up the correct events. + string ScriptSource = String.Empty; + + SceneObjectPart m_host = World.GetSceneObjectPart(localID); + + try + { + // Compile (We assume LSL) + //ScriptSource = LSLCompiler.CompileFromLSLText(Script); + +#if DEBUG + long before; + before = GC.GetTotalMemory(true); +#endif + + IScript CompiledScript; + CompiledScript = m_scriptEngine.m_AppDomainManager.LoadScript(ScriptSource); + +#if DEBUG + Console.WriteLine("Script " + itemID + " occupies {0} bytes", GC.GetTotalMemory(true) - before); +#endif + + CompiledScript.Source = ScriptSource; + // Add it to our script memstruct + SetScript(localID, itemID, CompiledScript); + + // We need to give (untrusted) assembly a private instance of BuiltIns + // this private copy will contain Read-Only FullitemID so that it can bring that on to the server whenever needed. + + + LSL_BuiltIn_Commands LSLB = new LSL_BuiltIn_Commands(m_scriptEngine, m_host, localID, itemID); + + // Start the script - giving it BuiltIns + CompiledScript.Start(LSLB); + + // Fire the first start-event + m_scriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_entry", EventQueueManager.llDetectNull, new object[] { }); + } + catch (Exception e) // LEGIT - User Script Compilation + { + //m_scriptEngine.Log.Error("[ScriptEngine]: Error compiling script: " + e.ToString()); + try + { + // DISPLAY ERROR INWORLD + string text = "Error compiling script:\r\n" + e.Message.ToString(); + if (text.Length > 1500) + text = text.Substring(0, 1500); + World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0, m_host.AbsolutePosition, + m_host.Name, m_host.UUID); + } + catch (Exception e2) // LEGIT - User Scripting + { + m_scriptEngine.Log.Error("[ScriptEngine]: Error displaying error in-world: " + e2.ToString()); + m_scriptEngine.Log.Error("[ScriptEngine]: " + + "Errormessage: Error compiling script:\r\n" + e.Message.ToString()); + } + } + } + + public override void _StopScript(uint localID, LLUUID itemID) + { + // Stop script + Console.WriteLine("Stop script localID: " + localID + " LLUID: " + itemID.ToString()); + + // Stop long command on script + m_scriptEngine.m_ASYNCLSLCommandManager.RemoveScript(localID, itemID); + + IScript LSLBC = GetScript(localID, itemID); + if (LSLBC == null) + return; + + // TEMP: First serialize it + //GetSerializedScript(localID, itemID); + + try + { + // Get AppDomain + AppDomain ad = LSLBC.Exec.GetAppDomain(); + // Tell script not to accept new requests + GetScript(localID, itemID).Exec.StopScript(); + // Remove from internal structure + RemoveScript(localID, itemID); + // Tell AppDomain that we have stopped script + m_scriptEngine.m_AppDomainManager.StopScript(ad); + } + catch (Exception e) // LEGIT - Problems caused by User Scripting + { + Console.WriteLine("Exception stopping script localID: " + localID + " LLUID: " + itemID.ToString() + + ": " + e.ToString()); + } + } + + public override void Initialize() + { + } + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/RemoteServer/Common.cs b/trunk/OpenSim/Region/ScriptEngine/RemoteServer/Common.cs new file mode 100644 index 0000000000..e65b8ffaf9 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/RemoteServer/Common.cs @@ -0,0 +1,58 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ + +namespace OpenSim.Region.ScriptEngine.RemoteServer +{ + public static class Common + { + public static bool debug = true; + public static ScriptEngine mySE; + + // This class just contains some static log stuff used for debugging. + + //public delegate void SendToDebugEventDelegate(string Message); + //public delegate void SendToLogEventDelegate(string Message); + //static public event SendToDebugEventDelegate SendToDebugEvent; + //static public event SendToLogEventDelegate SendToLogEvent; + + public static void SendToDebug(string Message) + { + //if (Debug == true) + mySE.Log.Info("[ScriptEngine]: Debug: " + Message); + //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + + public static void SendToLog(string Message) + { + //if (Debug == true) + mySE.Log.Info("[ScriptEngine]: LOG: " + Message); + //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/RemoteServer/EventManager.cs b/trunk/OpenSim/Region/ScriptEngine/RemoteServer/EventManager.cs new file mode 100644 index 0000000000..971982caf9 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/RemoteServer/EventManager.cs @@ -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 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. +* +*/ +/* Original code: Tedd Hansen */ + +using System; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.TRPC; + +namespace OpenSim.Region.ScriptEngine.RemoteServer +{ + /// + /// Handles events from OpenSim. Uses RemoteServer to send commands. + /// + [Serializable] + internal class EventManager + { + System.Collections.Generic.Dictionary remoteScript = new System.Collections.Generic.Dictionary(); + TCPClient m_TCPClient; + TRPC_Remote RPC; + int myScriptServerID; + + string remoteHost = "127.0.0.1"; + int remotePort = 8010; + + private ScriptEngine myScriptEngine; + public EventManager(ScriptEngine _ScriptEngine) + { + myScriptEngine = _ScriptEngine; + + m_TCPClient = new TCPClient(); + RPC = new TRPC_Remote(m_TCPClient); + RPC.ReceiveCommand += new TRPC_Remote.ReceiveCommandDelegate(RPC_ReceiveCommand); + myScriptServerID = m_TCPClient.ConnectAndReturnID(remoteHost, remotePort); + + myScriptEngine.Log.Info("[RemoteEngine]: Hooking up to server events"); + //myScriptEngine.World.EventManager.OnObjectGrab += touch_start; + myScriptEngine.World.EventManager.OnRezScript += OnRezScript; + //myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript; + } + + void RPC_ReceiveCommand(int ID, string Command, params object[] p) + { + myScriptEngine.Log.Info("[REMOTESERVER]: Received command: '" + Command + "'"); + if (p != null) + { + for (int i = 0; i < p.Length; i++) + { + myScriptEngine.Log.Info("[REMOTESERVER]: Param " + i + ": " + p[i].ToString()); + } + } + } + + public void OnRezScript(uint localID, LLUUID itemID, string script) + { + // WE ARE CREATING A NEW SCRIPT ... CREATE SCRIPT, GET A REMOTEID THAT WE MAP FROM LOCALID + myScriptEngine.Log.Info("[RemoteEngine]: Creating new script (with connection)"); + + // Temp for now: We have one connection only - this is hardcoded in myScriptServerID + RPC.SendCommand(myScriptServerID, "OnRezScript", localID, itemID.ToString(), script); + + //ScriptServerInterfaces.ServerRemotingObject obj = myScriptEngine.m_RemoteServer.Connect("localhost", 1234); + //remoteScript.Add(localID, obj); + //remoteScript[localID].Events().OnRezScript(localID, itemID, script); + } + + public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient) + { + //remoteScript[localID].Events.touch_start(localID, offsetPos, remoteClient); + RPC.SendCommand(myScriptServerID, "touch_start", offsetPos, "How to transfer IClientAPI?"); + } + + + // PLACEHOLDERS -- CODE WILL CHANGE! + + + //public void OnRemoveScript(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.OnRemoveScript(localID, itemID); + //} + + //public void state_exit(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.state_exit(localID, itemID); + //} + + //public void touch(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.touch(localID, itemID); + //} + + //public void touch_end(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.touch_end(localID, itemID); + //} + + //public void collision_start(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.collision_start(localID, itemID); + //} + + //public void collision(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.collision(localID, itemID); + //} + + //public void collision_end(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.collision_end(localID, itemID); + //} + + //public void land_collision_start(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.land_collision_start(localID, itemID); + //} + + //public void land_collision(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.land_collision(localID, itemID); + //} + + //public void land_collision_end(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.land_collision_end(localID, itemID); + //} + + //public void timer(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.timer(localID, itemID); + //} + + //public void listen(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.listen(localID, itemID); + //} + + //public void on_rez(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.on_rez(localID, itemID); + //} + + //public void sensor(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.sensor(localID, itemID); + //} + + //public void no_sensor(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.no_sensor(localID, itemID); + //} + + //public void control(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.control(localID, itemID); + //} + + //public void money(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.money(localID, itemID); + //} + + //public void email(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.email(localID, itemID); + //} + + //public void at_target(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.at_target(localID, itemID); + //} + + //public void not_at_target(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.not_at_target(localID, itemID); + //} + + //public void at_rot_target(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.at_rot_target(localID, itemID); + //} + + //public void not_at_rot_target(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.not_at_rot_target(localID, itemID); + //} + + //public void run_time_permissions(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.run_time_permissions(localID, itemID); + //} + + //public void changed(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.changed(localID, itemID); + //} + + //public void attach(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.attach(localID, itemID); + //} + + //public void dataserver(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.dataserver(localID, itemID); + //} + + //public void link_message(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.link_message(localID, itemID); + //} + + //public void moving_start(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.moving_start(localID, itemID); + //} + + //public void moving_end(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.moving_end(localID, itemID); + //} + + //public void object_rez(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.object_rez(localID, itemID); + //} + + //public void remote_data(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.remote_data(localID, itemID); + //} + + //public void http_response(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.http_response(localID, itemID); + //} + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/RemoteServer/Properties/AssemblyInfo.cs b/trunk/OpenSim/Region/ScriptEngine/RemoteServer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..0462ba445d --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/RemoteServer/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* 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.ScriptEngine.RemoteServer")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Region.ScriptEngine.RemoteServer")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("2842257e-6fde-4460-9368-4cde57fa9cc4")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Region/ScriptEngine/RemoteServer/RemoteServer.cs b/trunk/OpenSim/Region/ScriptEngine/RemoteServer/RemoteServer.cs new file mode 100644 index 0000000000..6adfa4e523 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/RemoteServer/RemoteServer.cs @@ -0,0 +1,83 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; +using System.Runtime.Remoting.Channels.Tcp; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Region.ScriptEngine.RemoteServer +{ + class RemoteServer + { + // Handles connections to servers + // Create and returns server object + + public RemoteServer() + { + TcpChannel chan = new TcpChannel(); + ChannelServices.RegisterChannel(chan, true); + } + + public ScriptServerInterfaces.ServerRemotingObject Connect(string hostname, int port) + { + // Create a channel for communicating w/ the remote object + // Notice no port is specified on the client + + try + { + // Create an instance of the remote object + ScriptServerInterfaces.ServerRemotingObject obj = (ScriptServerInterfaces.ServerRemotingObject)Activator.GetObject( + typeof(ScriptServerInterfaces.ServerRemotingObject), + "tcp://" + hostname + ":" + port + "/DotNetEngine"); + + // Use the object + if (obj.Equals(null)) + { + System.Console.WriteLine("Error: unable to locate server"); + } + else + { + return obj; + } + } + catch (System.Net.Sockets.SocketException) + { + System.Console.WriteLine("Error: unable to connect to server"); + } + catch (System.Runtime.Remoting.RemotingException) + { + System.Console.WriteLine("Error: unable to connect to server"); + } + return null; + } + } +} diff --git a/trunk/OpenSim/Region/ScriptEngine/RemoteServer/ScriptEngine.cs b/trunk/OpenSim/Region/ScriptEngine/RemoteServer/ScriptEngine.cs new file mode 100644 index 0000000000..8d27251f27 --- /dev/null +++ b/trunk/OpenSim/Region/ScriptEngine/RemoteServer/ScriptEngine.cs @@ -0,0 +1,104 @@ +/* +* 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. +* +*/ +/* Original code: Tedd Hansen */ + +using System; +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.ScriptEngine.RemoteServer +{ + /// + /// This is the root object for RemoteServer. Objects access each other trough this class. + /// + /// + [Serializable] + public class ScriptEngine : IRegionModule + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + internal Scene World; + internal EventManager m_EventManager; // Handles and queues incoming events from OpenSim + internal RemoteServer m_RemoteServer; // Handles connections to remote servers + + public ScriptEngine() + { + Common.mySE = this; + } + + public log4net.ILog Log + { + get { return m_log; } + } + + public void InitializeEngine(Scene Sceneworld) + { + World = Sceneworld; + + m_log.Info("[ScriptEngine]: RemoteEngine (Remote Script Server) initializing"); + // Create all objects we'll be using + m_EventManager = new EventManager(this); + m_RemoteServer = new RemoteServer(); + m_RemoteServer.Connect("localhost", 1234); + } + + public void Shutdown() + { + // We are shutting down + } + + #region IRegionModule + + public void Initialise(Scene scene, IConfigSource config) + { + InitializeEngine(scene); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "RemoteServerScriptingModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + } +} diff --git a/trunk/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/DB4oDataStore.cs b/trunk/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/DB4oDataStore.cs new file mode 100644 index 0000000000..992f931d26 --- /dev/null +++ b/trunk/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/DB4oDataStore.cs @@ -0,0 +1,133 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.Environment.LandManagement; +using OpenSim.Region.Environment; +using OpenSim.Region.Interfaces; +using OpenSim.Framework.Console; +using libsecondlife; + +using Db4objects.Db4o; +using Db4objects.Db4o.Query; + +namespace OpenSim.DataStore.DB4oStorage +{ + public class SceneObjectQuery : Predicate + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private LLUUID globalIDSearch; + + public SceneObjectQuery(LLUUID find) + { + globalIDSearch = find; + } + + public bool Match(SceneObjectGroup obj) + { + return obj.UUID == globalIDSearch; + } + } + + public class DB4oDataStore : IRegionDataStore + { + private IObjectContainer db; + + public void Initialise(string dbfile, string dbname) + { + m_log.Info("[DATASTORE]: DB4O - Opening " + dbfile); + db = Db4oFactory.OpenFile(dbfile); + } + + public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID) + { + db.Set(obj); + } + + public void RemoveObject(LLUUID obj, LLUUID regionUUID) + { + IObjectSet result = db.Query(new SceneObjectQuery(obj)); + if (result.Count > 0) + { + SceneObjectGroup item = (SceneObjectGroup)result.Next(); + db.Delete(item); + } + } + + public List LoadObjects(LLUUID regionUUID) + { + IObjectSet result = db.Get(typeof(SceneObjectGroup)); + List retvals = new List(); + + m_log.Info("[DATASTORE]: DB4O - LoadObjects found " + result.Count.ToString() + " objects"); + + foreach (Object obj in result) + { + retvals.Add((SceneObjectGroup)obj); + } + + return retvals; + } + + public void StoreTerrain(double[,] ter) + { + } + + public double[,] LoadTerrain() + { + return null; + } + + public void RemoveLandObject(uint id) + { + } + + public void StoreParcel(Land parcel) + { + } + + public List LoadLandObjects() + { + return new List(); + } + + public void Shutdown() + { + if (db != null) + { + db.Commit(); + db.Close(); + } + } + } +} diff --git a/trunk/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/Properties/AssemblyInfo.cs b/trunk/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..ba10862f05 --- /dev/null +++ b/trunk/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/Properties/AssemblyInfo.cs @@ -0,0 +1,63 @@ +/* +* 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.CompilerServices; +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.DataStore.DB4o")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpenSim.DataStore.DB4o")] +[assembly: AssemblyCopyright("Copyright © 2007")] +[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("7a12de8b-fdd1-48f5-89a9-8dc2dafbeebc")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/trunk/OpenSim/Region/Storage/OpenSim.DataStore.MSSQL/MSSQLDataStore.cs b/trunk/OpenSim/Region/Storage/OpenSim.DataStore.MSSQL/MSSQLDataStore.cs new file mode 100644 index 0000000000..0343b79ae1 --- /dev/null +++ b/trunk/OpenSim/Region/Storage/OpenSim.DataStore.MSSQL/MSSQLDataStore.cs @@ -0,0 +1,1100 @@ +/* +* 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; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.IO; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Data; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.LandManagement; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.DataStore.MSSQL +{ + public class MSSQLDataStore : IRegionDataStore + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private const string primSelect = "select * from prims"; + private const string shapeSelect = "select * from primshapes"; + private const string terrainSelect = "select * from terrain"; + + private DataSet ds; + private SqlDataAdapter primDa; + private SqlDataAdapter shapeDa; + private SqlDataAdapter terrainDa; + + // see IRegionDataStore + public void Initialise(string dbfile, bool persistPrimInventories) + { + IniFile GridDataMySqlFile = new IniFile("mssql_connection.ini"); + string settingDataSource = GridDataMySqlFile.ParseFileReadValue("data_source"); + string settingInitialCatalog = GridDataMySqlFile.ParseFileReadValue("initial_catalog"); + string settingPersistSecurityInfo = GridDataMySqlFile.ParseFileReadValue("persist_security_info"); + string settingUserId = GridDataMySqlFile.ParseFileReadValue("user_id"); + string settingPassword = GridDataMySqlFile.ParseFileReadValue("password"); + + string connectionString = "Data Source=" + settingDataSource + ";Initial Catalog=" + settingInitialCatalog + + ";Persist Security Info=" + settingPersistSecurityInfo + ";User ID=" + + settingUserId + ";Password=" + settingPassword + ";"; + + ds = new DataSet(); + + m_log.Info("[DATASTORE]: MSSQL - connecting: " + settingInitialCatalog); + SqlConnection conn = new SqlConnection(connectionString); + SqlCommand primSelectCmd = new SqlCommand(primSelect, conn); + primDa = new SqlDataAdapter(primSelectCmd); + // SqlCommandBuilder primCb = new SqlCommandBuilder(primDa); + + SqlCommand shapeSelectCmd = new SqlCommand(shapeSelect, conn); + shapeDa = new SqlDataAdapter(shapeSelectCmd); + // SqlCommandBuilder shapeCb = new SqlCommandBuilder(shapeDa); + + SqlCommand terrainSelectCmd = new SqlCommand(terrainSelect, conn); + terrainDa = new SqlDataAdapter(terrainSelectCmd); + + + // We fill the data set, now we've got copies in memory for the information + // TODO: see if the linkage actually holds. + // primDa.FillSchema(ds, SchemaType.Source, "PrimSchema"); + TestTables(conn); + + lock (ds) + { + ds.Tables.Add(createPrimTable()); + setupPrimCommands(primDa, conn); + primDa.Fill(ds.Tables["prims"]); + + ds.Tables.Add(createShapeTable()); + setupShapeCommands(shapeDa, conn); + + ds.Tables.Add(createTerrainTable()); + setupTerrainCommands(terrainDa, conn); + + // WORKAROUND: This is a work around for Sql on + // windows, which gets really unhappy with blob columns + // that have no sample data in them. At some point we + // need to actually find a proper way to handle this. + try + { + shapeDa.Fill(ds.Tables["primshapes"]); + } + catch (Exception) + { + m_log.Info("[DATASTORE]: Caught fill error on primshapes table"); + } + try + { + terrainDa.Fill(ds.Tables["terrain"]); + } + catch (Exception) + { + m_log.Info("[DATASTORE]: Caught fill error on terrain table"); + } + return; + } + } + + public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID) + { + lock (ds) + { + foreach (SceneObjectPart prim in obj.Children.Values) + { + m_log.Info("[DATASTORE]: Adding obj: " + obj.UUID + " to region: " + regionUUID); + addPrim(prim, obj.UUID, regionUUID); + } + } + + Commit(); + // m_log.Info("Dump of prims:", ds.GetXml()); + } + + public void RemoveObject(LLUUID obj, LLUUID regionUUID) + { + m_log.InfoFormat("[DATASTORE]: Removing obj: {0} from region: {1}", obj.UUID, regionUUID); + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + string selectExp = "SceneGroupID = '" + obj.ToString() + "'"; + lock (ds) + { + DataRow[] primRows = prims.Select(selectExp); + foreach (DataRow row in primRows) + { + LLUUID uuid = new LLUUID((string) row["UUID"]); + DataRow shapeRow = shapes.Rows.Find(uuid); + if (shapeRow != null) + { + shapeRow.Delete(); + } + row.Delete(); + } + } + + Commit(); + } + + public List LoadObjects(LLUUID regionUUID) + { + Dictionary createdObjects = new Dictionary(); + + List retvals = new List(); + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + string byRegion = "RegionUUID = '" + regionUUID.ToString() + "'"; + string orderByParent = "ParentID ASC"; + + lock (ds) + { + DataRow[] primsForRegion = prims.Select(byRegion, orderByParent); + m_log.Info("[DATASTORE]: " + + "Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); + + foreach (DataRow primRow in primsForRegion) + { + try + { + string uuid = (string) primRow["UUID"]; + string objID = (string) primRow["SceneGroupID"]; + if (uuid == objID) //is new SceneObjectGroup ? + { + SceneObjectGroup group = new SceneObjectGroup(); + SceneObjectPart prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(prim.UUID); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Info( + "No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + group.AddPart(prim); + group.RootPart = prim; + + createdObjects.Add(group.UUID, group); + retvals.Add(group); + } + else + { + SceneObjectPart prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(prim.UUID); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Info( + "No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + createdObjects[new LLUUID(objID)].AddPart(prim); + } + } + catch (Exception e) + { + m_log.Error("[DATASTORE]: Failed create prim object, exception and data follows"); + m_log.Info("[DATASTORE]: " + e.ToString()); + foreach (DataColumn col in prims.Columns) + { + m_log.Info("[DATASTORE]: Col: " + col.ColumnName + " => " + primRow[col]); + } + } + } + } + return retvals; + } + + + public void StoreTerrain(double[,] ter, LLUUID regionID) + { + int revision = Util.UnixTimeSinceEpoch(); + + m_log.Info("[DATASTORE]: Storing terrain revision r" + revision.ToString()); + + DataTable terrain = ds.Tables["terrain"]; + lock (ds) + { + DataRow newrow = terrain.NewRow(); + fillTerrainRow(newrow, regionID, revision, ter); + terrain.Rows.Add(newrow); + + Commit(); + } + } + + public double[,] LoadTerrain(LLUUID regionID) + { + double[,] terret = new double[256,256]; + terret.Initialize(); + + DataTable terrain = ds.Tables["terrain"]; + + lock (ds) + { + DataRow[] rows = terrain.Select("RegionUUID = '" + regionID.ToString() + "'", "Revision DESC"); + + int rev = 0; + + if (rows.Length > 0) + { + DataRow row = rows[0]; + + byte[] heightmap = (byte[]) row["Heightfield"]; + for (int x = 0; x < 256; x++) + { + for (int y = 0; y < 256; y++) + { + terret[x, y] = BitConverter.ToDouble(heightmap, ((x*256) + y)*8); + } + } + + rev = (int) row["Revision"]; + } + else + { + m_log.Info("[DATASTORE]: No terrain found for region"); + return null; + } + + + m_log.Info("[DATASTORE]: Loaded terrain revision r" + rev.ToString()); + } + + return terret; + } + + public void RemoveLandObject(LLUUID globalID) + { + } + + public void StoreLandObject(Land parcel, LLUUID regionUUID) + { + } + + public List LoadLandObjects(LLUUID regionUUID) + { + return new List(); + } + + public void Commit() + { + lock (ds) + { + primDa.Update(ds, "prims"); + shapeDa.Update(ds, "primshapes"); + terrainDa.Update(ds, "terrain"); + ds.AcceptChanges(); + } + } + + public void Shutdown() + { + Commit(); + } + + /*********************************************************************** + * + * Database Definition Functions + * + * This should be db agnostic as we define them in ADO.NET terms + * + **********************************************************************/ + + private void createCol(DataTable dt, string name, Type type) + { + DataColumn col = new DataColumn(name, type); + dt.Columns.Add(col); + } + + private DataTable createTerrainTable() + { + DataTable terrain = new DataTable("terrain"); + + createCol(terrain, "RegionUUID", typeof (String)); + createCol(terrain, "Revision", typeof (Int32)); + createCol(terrain, "Heightfield", typeof (Byte[])); + + return terrain; + } + + private DataTable createPrimTable() + { + DataTable prims = new DataTable("prims"); + + createCol(prims, "UUID", typeof (String)); + createCol(prims, "RegionUUID", typeof (String)); + createCol(prims, "ParentID", typeof (Int32)); + createCol(prims, "CreationDate", typeof (Int32)); + createCol(prims, "Name", typeof (String)); + createCol(prims, "SceneGroupID", typeof (String)); + // various text fields + createCol(prims, "Text", typeof (String)); + createCol(prims, "Description", typeof (String)); + createCol(prims, "SitName", typeof (String)); + createCol(prims, "TouchName", typeof (String)); + // permissions + createCol(prims, "ObjectFlags", typeof (Int32)); + createCol(prims, "CreatorID", typeof (String)); + createCol(prims, "OwnerID", typeof (String)); + createCol(prims, "GroupID", typeof (String)); + createCol(prims, "LastOwnerID", typeof (String)); + createCol(prims, "OwnerMask", typeof (Int32)); + createCol(prims, "NextOwnerMask", typeof (Int32)); + createCol(prims, "GroupMask", typeof (Int32)); + createCol(prims, "EveryoneMask", typeof (Int32)); + createCol(prims, "BaseMask", typeof (Int32)); + // vectors + createCol(prims, "PositionX", typeof (Double)); + createCol(prims, "PositionY", typeof (Double)); + createCol(prims, "PositionZ", typeof (Double)); + createCol(prims, "GroupPositionX", typeof (Double)); + createCol(prims, "GroupPositionY", typeof (Double)); + createCol(prims, "GroupPositionZ", typeof (Double)); + createCol(prims, "VelocityX", typeof (Double)); + createCol(prims, "VelocityY", typeof (Double)); + createCol(prims, "VelocityZ", typeof (Double)); + createCol(prims, "AngularVelocityX", typeof (Double)); + createCol(prims, "AngularVelocityY", typeof (Double)); + createCol(prims, "AngularVelocityZ", typeof (Double)); + createCol(prims, "AccelerationX", typeof (Double)); + createCol(prims, "AccelerationY", typeof (Double)); + createCol(prims, "AccelerationZ", typeof (Double)); + // quaternions + createCol(prims, "RotationX", typeof (Double)); + createCol(prims, "RotationY", typeof (Double)); + createCol(prims, "RotationZ", typeof (Double)); + createCol(prims, "RotationW", typeof (Double)); + + // sit target + createCol(prims, "SitTargetOffsetX", typeof (Double)); + createCol(prims, "SitTargetOffsetY", typeof (Double)); + createCol(prims, "SitTargetOffsetZ", typeof (Double)); + + createCol(prims, "SitTargetOrientW", typeof (Double)); + createCol(prims, "SitTargetOrientX", typeof (Double)); + createCol(prims, "SitTargetOrientY", typeof (Double)); + createCol(prims, "SitTargetOrientZ", typeof (Double)); + + // Add in contraints + prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]}; + + return prims; + } + + private DataTable createShapeTable() + { + DataTable shapes = new DataTable("primshapes"); + createCol(shapes, "UUID", typeof (String)); + // shape is an enum + createCol(shapes, "Shape", typeof (Int32)); + // vectors + createCol(shapes, "ScaleX", typeof (Double)); + createCol(shapes, "ScaleY", typeof (Double)); + createCol(shapes, "ScaleZ", typeof (Double)); + // paths + createCol(shapes, "PCode", typeof (Int32)); + createCol(shapes, "PathBegin", typeof (Int32)); + createCol(shapes, "PathEnd", typeof (Int32)); + createCol(shapes, "PathScaleX", typeof (Int32)); + createCol(shapes, "PathScaleY", typeof (Int32)); + createCol(shapes, "PathShearX", typeof (Int32)); + createCol(shapes, "PathShearY", typeof (Int32)); + createCol(shapes, "PathSkew", typeof (Int32)); + createCol(shapes, "PathCurve", typeof (Int32)); + createCol(shapes, "PathRadiusOffset", typeof (Int32)); + createCol(shapes, "PathRevolutions", typeof (Int32)); + createCol(shapes, "PathTaperX", typeof (Int32)); + createCol(shapes, "PathTaperY", typeof (Int32)); + createCol(shapes, "PathTwist", typeof (Int32)); + createCol(shapes, "PathTwistBegin", typeof (Int32)); + // profile + createCol(shapes, "ProfileBegin", typeof (Int32)); + createCol(shapes, "ProfileEnd", typeof (Int32)); + createCol(shapes, "ProfileCurve", typeof (Int32)); + createCol(shapes, "ProfileHollow", typeof (Int32)); + // text TODO: this isn't right, but I'm not sure the right + // way to specify this as a blob atm + createCol(shapes, "Texture", typeof (Byte[])); + createCol(shapes, "ExtraParams", typeof (Byte[])); + + shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]}; + + return shapes; + } + + /*********************************************************************** + * + * Convert between ADO.NET <=> OpenSim Objects + * + * These should be database independant + * + **********************************************************************/ + + private SceneObjectPart buildPrim(DataRow row) + { + // TODO: this doesn't work yet because something more + // interesting has to be done to actually get these values + // back out. Not enough time to figure it out yet. + SceneObjectPart prim = new SceneObjectPart(); + prim.UUID = new LLUUID((String) row["UUID"]); + // explicit conversion of integers is required, which sort + // of sucks. No idea if there is a shortcut here or not. + prim.ParentID = Convert.ToUInt32(row["ParentID"]); + prim.CreationDate = Convert.ToInt32(row["CreationDate"]); + prim.Name = (String) row["Name"]; + // various text fields + prim.Text = (String) row["Text"]; + prim.Description = (String) row["Description"]; + prim.SitName = (String) row["SitName"]; + prim.TouchName = (String) row["TouchName"]; + // permissions + prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]); + prim.CreatorID = new LLUUID((String) row["CreatorID"]); + prim.OwnerID = new LLUUID((String) row["OwnerID"]); + prim.GroupID = new LLUUID((String) row["GroupID"]); + prim.LastOwnerID = new LLUUID((String) row["LastOwnerID"]); + prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); + prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); + prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); + prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); + prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); + // vectors + prim.OffsetPosition = new LLVector3( + Convert.ToSingle(row["PositionX"]), + Convert.ToSingle(row["PositionY"]), + Convert.ToSingle(row["PositionZ"]) + ); + prim.GroupPosition = new LLVector3( + Convert.ToSingle(row["GroupPositionX"]), + Convert.ToSingle(row["GroupPositionY"]), + Convert.ToSingle(row["GroupPositionZ"]) + ); + prim.Velocity = new LLVector3( + Convert.ToSingle(row["VelocityX"]), + Convert.ToSingle(row["VelocityY"]), + Convert.ToSingle(row["VelocityZ"]) + ); + prim.AngularVelocity = new LLVector3( + Convert.ToSingle(row["AngularVelocityX"]), + Convert.ToSingle(row["AngularVelocityY"]), + Convert.ToSingle(row["AngularVelocityZ"]) + ); + prim.Acceleration = new LLVector3( + Convert.ToSingle(row["AccelerationX"]), + Convert.ToSingle(row["AccelerationY"]), + Convert.ToSingle(row["AccelerationZ"]) + ); + // quaternions + prim.RotationOffset = new LLQuaternion( + Convert.ToSingle(row["RotationX"]), + Convert.ToSingle(row["RotationY"]), + Convert.ToSingle(row["RotationZ"]), + Convert.ToSingle(row["RotationW"]) + ); + + try + { + prim.SetSitTargetLL(new LLVector3( + Convert.ToSingle(row["SitTargetOffsetX"]), + Convert.ToSingle(row["SitTargetOffsetY"]), + Convert.ToSingle(row["SitTargetOffsetZ"])), new LLQuaternion( + Convert.ToSingle( + row["SitTargetOrientX"]), + Convert.ToSingle( + row["SitTargetOrientY"]), + Convert.ToSingle( + row["SitTargetOrientZ"]), + Convert.ToSingle( + row["SitTargetOrientW"]))); + } + catch (InvalidCastException) + { + // Database table was created before we got here and now has null values :P + } + + return prim; + } + + + private void fillPrimRow(DataRow row, SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID) + { + row["UUID"] = prim.UUID; + row["RegionUUID"] = regionUUID; + row["ParentID"] = prim.ParentID; + row["CreationDate"] = prim.CreationDate; + row["Name"] = prim.Name; + row["SceneGroupID"] = sceneGroupID; // the UUID of the root part for this SceneObjectGroup + // various text fields + row["Text"] = prim.Text; + row["Description"] = prim.Description; + row["SitName"] = prim.SitName; + row["TouchName"] = prim.TouchName; + // permissions + row["ObjectFlags"] = prim.ObjectFlags; + row["CreatorID"] = prim.CreatorID; + row["OwnerID"] = prim.OwnerID; + row["GroupID"] = prim.GroupID; + row["LastOwnerID"] = prim.LastOwnerID; + row["OwnerMask"] = prim.OwnerMask; + row["NextOwnerMask"] = prim.NextOwnerMask; + row["GroupMask"] = prim.GroupMask; + row["EveryoneMask"] = prim.EveryoneMask; + row["BaseMask"] = prim.BaseMask; + // vectors + row["PositionX"] = prim.OffsetPosition.X; + row["PositionY"] = prim.OffsetPosition.Y; + row["PositionZ"] = prim.OffsetPosition.Z; + row["GroupPositionX"] = prim.GroupPosition.X; + row["GroupPositionY"] = prim.GroupPosition.Y; + row["GroupPositionZ"] = prim.GroupPosition.Z; + row["VelocityX"] = prim.Velocity.X; + row["VelocityY"] = prim.Velocity.Y; + row["VelocityZ"] = prim.Velocity.Z; + row["AngularVelocityX"] = prim.AngularVelocity.X; + row["AngularVelocityY"] = prim.AngularVelocity.Y; + row["AngularVelocityZ"] = prim.AngularVelocity.Z; + row["AccelerationX"] = prim.Acceleration.X; + row["AccelerationY"] = prim.Acceleration.Y; + row["AccelerationZ"] = prim.Acceleration.Z; + // quaternions + row["RotationX"] = prim.RotationOffset.X; + row["RotationY"] = prim.RotationOffset.Y; + row["RotationZ"] = prim.RotationOffset.Z; + row["RotationW"] = prim.RotationOffset.W; + + try + { + // Sit target + LLVector3 sitTargetPos = prim.GetSitTargetPositionLL(); + row["SitTargetOffsetX"] = sitTargetPos.X; + row["SitTargetOffsetY"] = sitTargetPos.Y; + row["SitTargetOffsetZ"] = sitTargetPos.Z; + + LLQuaternion sitTargetOrient = prim.GetSitTargetOrientationLL(); + row["SitTargetOrientW"] = sitTargetOrient.W; + row["SitTargetOrientX"] = sitTargetOrient.X; + row["SitTargetOrientY"] = sitTargetOrient.Y; + row["SitTargetOrientZ"] = sitTargetOrient.Z; + } + catch (Exception) + { + // TODO: Add Sit Target Rows! + } + } + + private PrimitiveBaseShape buildShape(DataRow row) + { + PrimitiveBaseShape s = new PrimitiveBaseShape(); + s.Scale = new LLVector3( + Convert.ToSingle(row["ScaleX"]), + Convert.ToSingle(row["ScaleY"]), + Convert.ToSingle(row["ScaleZ"]) + ); + // paths + s.PCode = Convert.ToByte(row["PCode"]); + s.PathBegin = Convert.ToUInt16(row["PathBegin"]); + s.PathEnd = Convert.ToUInt16(row["PathEnd"]); + s.PathScaleX = Convert.ToByte(row["PathScaleX"]); + s.PathScaleY = Convert.ToByte(row["PathScaleY"]); + s.PathShearX = Convert.ToByte(row["PathShearX"]); + s.PathShearY = Convert.ToByte(row["PathShearY"]); + s.PathSkew = Convert.ToSByte(row["PathSkew"]); + s.PathCurve = Convert.ToByte(row["PathCurve"]); + s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]); + s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]); + s.PathTaperX = Convert.ToSByte(row["PathTaperX"]); + s.PathTaperY = Convert.ToSByte(row["PathTaperY"]); + s.PathTwist = Convert.ToSByte(row["PathTwist"]); + s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]); + // profile + s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]); + s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); + s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); + s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); + + // text TODO: this isn't right] = but I'm not sure the right + // way to specify this as a blob atm + byte[] textureEntry = (byte[]) row["Texture"]; + s.TextureEntry = textureEntry; + + + s.ExtraParams = (byte[]) row["ExtraParams"]; + // System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); + // string texture = encoding.GetString((Byte[])row["Texture"]); + // if (!texture.StartsWith("<")) + // { + // //here so that we can still work with old format database files (ie from before I added xml serialization) + // LLObject.TextureEntry textureEntry = null; + // textureEntry = new LLObject.TextureEntry(new LLUUID(texture)); + // s.TextureEntry = textureEntry.ToBytes(); + // } + // else + // { + // TextureBlock textureEntry = TextureBlock.FromXmlString(texture); + // s.TextureEntry = textureEntry.TextureData; + // s.ExtraParams = textureEntry.ExtraParams; + // } + + return s; + } + + private void fillShapeRow(DataRow row, SceneObjectPart prim) + { + PrimitiveBaseShape s = prim.Shape; + row["UUID"] = prim.UUID; + // shape is an enum + row["Shape"] = 0; + // vectors + row["ScaleX"] = s.Scale.X; + row["ScaleY"] = s.Scale.Y; + row["ScaleZ"] = s.Scale.Z; + // paths + row["PCode"] = s.PCode; + row["PathBegin"] = s.PathBegin; + row["PathEnd"] = s.PathEnd; + row["PathScaleX"] = s.PathScaleX; + row["PathScaleY"] = s.PathScaleY; + row["PathShearX"] = s.PathShearX; + row["PathShearY"] = s.PathShearY; + row["PathSkew"] = s.PathSkew; + row["PathCurve"] = s.PathCurve; + row["PathRadiusOffset"] = s.PathRadiusOffset; + row["PathRevolutions"] = s.PathRevolutions; + row["PathTaperX"] = s.PathTaperX; + row["PathTaperY"] = s.PathTaperY; + row["PathTwist"] = s.PathTwist; + row["PathTwistBegin"] = s.PathTwistBegin; + // profile + row["ProfileBegin"] = s.ProfileBegin; + row["ProfileEnd"] = s.ProfileEnd; + row["ProfileCurve"] = s.ProfileCurve; + row["ProfileHollow"] = s.ProfileHollow; + // text TODO: this isn't right] = but I'm not sure the right + // way to specify this as a blob atm + + // And I couldn't work out how to save binary data either + // seems that the texture colum is being treated as a string in the Datarow + // if you do a .getType() on it, it returns string, while the other columns return correct type + // MW[10-08-07] + // Added following xml hack but not really ideal , also ExtraParams isn't currently part of the database + // am a bit worried about adding it now as some people will have old format databases, so for now including that data in this xml data + // MW[17-08-07] + row["Texture"] = s.TextureEntry; + row["ExtraParams"] = s.ExtraParams; + // TextureBlock textureBlock = new TextureBlock(s.TextureEntry); + // textureBlock.ExtraParams = s.ExtraParams; + // System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); + // row["Texture"] = encoding.GetBytes(textureBlock.ToXMLString()); + } + + private void addPrim(SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID) + { + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + DataRow primRow = prims.Rows.Find(prim.UUID); + if (primRow == null) + { + primRow = prims.NewRow(); + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + prims.Rows.Add(primRow); + } + else + { + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + } + + DataRow shapeRow = shapes.Rows.Find(prim.UUID); + if (shapeRow == null) + { + shapeRow = shapes.NewRow(); + fillShapeRow(shapeRow, prim); + shapes.Rows.Add(shapeRow); + } + else + { + fillShapeRow(shapeRow, prim); + } + } + + // see IRegionDatastore + public void StorePrimInventory(LLUUID primID, ICollection items) + { + // No implementation yet + } + + /*********************************************************************** + * + * SQL Statement Creation Functions + * + * These functions create SQL statements for update, insert, and create. + * They can probably be factored later to have a db independant + * portion and a db specific portion + * + **********************************************************************/ + + private SqlCommand createInsertCommand(string table, DataTable dt) + { + /** + * This is subtle enough to deserve some commentary. + * Instead of doing *lots* and *lots of hardcoded strings + * for database definitions we'll use the fact that + * realistically all insert statements look like "insert + * into A(b, c) values(:b, :c) on the parameterized query + * front. If we just have a list of b, c, etc... we can + * generate these strings instead of typing them out. + */ + string[] cols = new string[dt.Columns.Count]; + for (int i = 0; i < dt.Columns.Count; i++) + { + DataColumn col = dt.Columns[i]; + cols[i] = col.ColumnName; + } + + string sql = "insert into " + table + "("; + sql += String.Join(", ", cols); + // important, the first ':' needs to be here, the rest get added in the join + sql += ") values (@"; + sql += String.Join(", @", cols); + sql += ")"; + SqlCommand cmd = new SqlCommand(sql); + // this provides the binding for all our parameters, so + // much less code than it used to be + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqlParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + private SqlCommand createUpdateCommand(string table, string pk, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= @" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk; + SqlCommand cmd = new SqlCommand(sql); + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqlParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + + private string defineTable(DataTable dt) + { + string sql = "create table " + dt.TableName + "("; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ",\n"; + } + subsql += col.ColumnName + " " + SqlType(col.DataType); + if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0]) + { + subsql += " primary key"; + } + } + sql += subsql; + sql += ")"; + + return sql; + } + + private void fillTerrainRow(DataRow row, LLUUID regionUUID, int rev, double[,] val) + { + row["RegionUUID"] = regionUUID; + row["Revision"] = rev; + + MemoryStream str = new MemoryStream(65536*sizeof (double)); + BinaryWriter bw = new BinaryWriter(str); + + // TODO: COMPATIBILITY - Add byte-order conversions + for (int x = 0; x < 256; x++) + for (int y = 0; y < 256; y++) + bw.Write(val[x, y]); + + row["Heightfield"] = str.ToArray(); + } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + /// + /// This is a convenience function that collapses 5 repetitive + /// lines for defining SqlParameters to 2 parameters: + /// column name and database type. + /// + /// It assumes certain conventions like :param as the param + /// name to replace in parametrized queries, and that source + /// version is always current version, both of which are fine + /// for us. + /// + ///a built Sql parameter + private SqlParameter createSqlParameter(string name, Type type) + { + SqlParameter param = new SqlParameter(); + param.ParameterName = "@" + name; + param.DbType = dbtypeFromType(type); + param.SourceColumn = name; + param.SourceVersion = DataRowVersion.Current; + return param; + } + + private void setupPrimCommands(SqlDataAdapter da, SqlConnection conn) + { + da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("prims", "UUID=@UUID", ds.Tables["prims"]); + da.UpdateCommand.Connection = conn; + + SqlCommand delete = new SqlCommand("delete from prims where UUID = @UUID"); + delete.Parameters.Add(createSqlParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + private void setupShapeCommands(SqlDataAdapter da, SqlConnection conn) + { + da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primshapes", "UUID=@UUID", ds.Tables["primshapes"]); + da.UpdateCommand.Connection = conn; + + SqlCommand delete = new SqlCommand("delete from primshapes where UUID = @UUID"); + delete.Parameters.Add(createSqlParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + private void setupTerrainCommands(SqlDataAdapter da, SqlConnection conn) + { + da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]); + da.InsertCommand.Connection = conn; + } + + private void InitDB(SqlConnection conn) + { + string createPrims = defineTable(createPrimTable()); + string createShapes = defineTable(createShapeTable()); + string createTerrain = defineTable(createTerrainTable()); + + SqlCommand pcmd = new SqlCommand(createPrims, conn); + SqlCommand scmd = new SqlCommand(createShapes, conn); + SqlCommand tcmd = new SqlCommand(createTerrain, conn); + conn.Open(); + try + { + pcmd.ExecuteNonQuery(); + pcmd.Dispose(); + } + catch (SqlException) + { + m_log.Warn("[MSSQL]: Primitives Table Already Exists"); + } + + try + { + scmd.ExecuteNonQuery(); + scmd.Dispose(); + } + catch (SqlException) + { + m_log.Warn("[MSSQL]: Shapes Table Already Exists"); + } + + try + { + tcmd.ExecuteNonQuery(); + tcmd.Dispose(); + } + catch (SqlException) + { + m_log.Warn("[MSSQL]: Terrain Table Already Exists"); + } + + conn.Close(); + } + + private bool TestTables(SqlConnection conn) + { + SqlCommand primSelectCmd = new SqlCommand(primSelect, conn); + SqlDataAdapter pDa = new SqlDataAdapter(primSelectCmd); + SqlCommand shapeSelectCmd = new SqlCommand(shapeSelect, conn); + SqlDataAdapter sDa = new SqlDataAdapter(shapeSelectCmd); + SqlCommand terrainSelectCmd = new SqlCommand(terrainSelect, conn); + SqlDataAdapter tDa = new SqlDataAdapter(terrainSelectCmd); + + DataSet tmpDS = new DataSet(); + try + { + pDa.Fill(tmpDS, "prims"); + sDa.Fill(tmpDS, "primshapes"); + tDa.Fill(tmpDS, "terrain"); + } + catch (SqlException) + { + m_log.Info("[DATASTORE]: MSSQL Database doesn't exist... creating"); + InitDB(conn); + } + + try + { + if (tmpDS.Tables == null || tmpDS.Tables.Count == 0) + { + pDa.Fill(tmpDS, "prims"); + sDa.Fill(tmpDS, "primshapes"); + tDa.Fill(tmpDS, "terrain"); + } + } + catch (SqlException e) + { + m_log.Info("[DATASTORE]: " + e.ToString()); + } + + foreach (DataColumn col in createPrimTable().Columns) + { + if (!tmpDS.Tables["prims"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing required column:" + col.ColumnName); + return false; + } + } + foreach (DataColumn col in createShapeTable().Columns) + { + if (!tmpDS.Tables["primshapes"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing required column:" + col.ColumnName); + return false; + } + } + foreach (DataColumn col in createTerrainTable().Columns) + { + if (!tmpDS.Tables["terrain"].Columns.Contains(col.ColumnName)) + { + m_log.Info("[DATASTORE]: Missing require column:" + col.ColumnName); + return false; + } + } + return true; + } + + /*********************************************************************** + * + * Type conversion functions + * + **********************************************************************/ + + private DbType dbtypeFromType(Type type) + { + if (type == typeof (String)) + { + return DbType.String; + } + else if (type == typeof (Int32)) + { + return DbType.Int32; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte[])) + { + return DbType.Binary; + } + else + { + return DbType.String; + } + } + + // this is something we'll need to implement for each db + // slightly differently. + private string SqlType(Type type) + { + if (type == typeof (String)) + { + return "varchar(255)"; + } + else if (type == typeof (Int32)) + { + return "integer"; + } + else if (type == typeof (Double)) + { + return "float"; + } + else if (type == typeof (Byte[])) + { + return "image"; + } + else + { + return "string"; + } + } + } +} diff --git a/trunk/OpenSim/Region/Storage/OpenSim.DataStore.NullStorage/NullDataStore.cs b/trunk/OpenSim/Region/Storage/OpenSim.DataStore.NullStorage/NullDataStore.cs new file mode 100644 index 0000000000..29d64a2b7d --- /dev/null +++ b/trunk/OpenSim/Region/Storage/OpenSim.DataStore.NullStorage/NullDataStore.cs @@ -0,0 +1,89 @@ +/* +* 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.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.LandManagement; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.DataStore.NullStorage +{ + public class NullDataStore : IRegionDataStore + { + public void Initialise(string dbfile, bool persistPrimInventories) + { + return; + } + + public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID) + { + } + + public void RemoveObject(LLUUID obj, LLUUID regionUUID) + { + } + + // see IRegionDatastore + public void StorePrimInventory(LLUUID primID, ICollection items) + { + } + + public List LoadObjects(LLUUID regionUUID) + { + return new List(); + } + + public void StoreTerrain(double[,] ter, LLUUID regionID) + { + } + + public double[,] LoadTerrain(LLUUID regionID) + { + return null; + } + + public void RemoveLandObject(LLUUID globalID) + { + } + + public void StoreLandObject(Land land, LLUUID regionUUID) + { + } + + public List LoadLandObjects(LLUUID regionUUID) + { + return new List(); + } + + public void Shutdown() + { + } + } +} diff --git a/trunk/OpenSim/Region/Storage/OpenSim.DataStore.NullStorage/Properties/AssemblyInfo.cs b/trunk/OpenSim/Region/Storage/OpenSim.DataStore.NullStorage/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..3d4dd3c995 --- /dev/null +++ b/trunk/OpenSim/Region/Storage/OpenSim.DataStore.NullStorage/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* 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.DataStore.NullStorage")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.DataStore.NullStorage")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("b4a1656d-de22-4080-a970-fd8166acbf16")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/Properties/AssemblyInfo.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..219ab1cbfa --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/Properties/AssemblyInfo.cs @@ -0,0 +1,65 @@ +/* +* 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.Terrain.BasicTerrain")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Region.Terrain.BasicTerrain")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-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("3263f5b5-0a41-4ed5-91a2-9baaaeecc849")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs new file mode 100644 index 0000000000..decbb73964 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/TerrainEngine.cs @@ -0,0 +1,1456 @@ +/* +* 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; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.Globalization; +using System.IO; +using System.Threading; +using libTerrain; +using OpenJPEGNet; +using OpenSim.Framework; + +namespace OpenSim.Region.Terrain +{ + public class TerrainCommand + { + public virtual bool run(string[] cmdargs, ref string output) + { + return false; + } + + public string args; + public string help; + } + + public class TerrainEngine + { + public static Mutex fileIOLock = new Mutex(); + + /// + /// Plugin library for scripts + /// + public FilterHost customFilters = new FilterHost(); + + /// + /// A [normally] 256x256 heightmap + /// + public Channel heightmap; + + /// + /// A copy of heightmap at the last save point (for reverting) + /// + public Channel revertmap; + + /// + /// Water heightmap (needs clientside mods to work) + /// + public Channel watermap; + + /// + /// Max amount the terrain can be raised from the revert parameters + /// + public double maxRaise = 500.0; + + /// + /// Min amount the terrain can be lowered from the revert parameters + /// + public double minLower = 500.0; + + /// + /// The last time the terrain was edited + /// + public DateTime lastEdit = DateTime.Now; + + + private int counter = 0; + + /// + /// Whether or not the terrain has been modified since it was last saved and sent to the Physics engine. + /// Counts the number of modifications since the last save. (0 = Untainted) + /// + public int tainted; + + private int w, h; + + /// + /// Used to determine what offset to use when loading singular heightmaps across multiple sims + /// + private int offsetX; + + private int offsetY; + + + /// + /// Generate a new TerrainEngine instance and creates a new heightmap + /// + public TerrainEngine(int X, int Y) + { + w = 256; + h = 256; + heightmap = new Channel(w, h); + revertmap = new Channel(w, h); + watermap = new Channel(w, h); + watermap.Fill(20); + + offsetX = X; + offsetY = Y; + + tainted++; + } + + public bool IsTainted() + { + return (tainted != 0); + } + + public bool IsUserStillEditing() + { + TimeSpan gap = DateTime.Now - lastEdit; + + if (gap.TotalSeconds <= 4.0) + return true; + + return false; + } + + public bool IsTainted(int x, int y) + { + return (heightmap.diff[x/16, y/16] != 0); + } + + public void ResetTaint() + { + tainted = 0; + heightmap.diff = new int[w/16,h/16]; + } + + //Testing to see if moving the TerraForming packet handling code into here works well + /// + /// Modifies terrain using the specified information + /// + /// The height at which the user started modifying the terrain + /// The number of seconds the modify button was pressed + /// The size of the brush used + /// The action to be performed + /// Distance from the north border where the cursor is located + /// Distance from the west border where the cursor is located + public void ModifyTerrain(float height, float seconds, byte brushsize, byte action, float north, float west, + float south, float east, + IClientAPI remoteUser) + { + // Shiny. + double size = (double) (1 << brushsize); + //System.Console.WriteLine("SIZE:" + size.ToString() + " Seconds:" + seconds.ToString()); + if (seconds == 1) + { + seconds = 0.0315f; + } + /* Okay, so here's the deal + * This has to handle both when a user draws on the terrain *and* when a user selects + * a selection of AABB on terrain and applies whatever routine the client requests + * There's something currently wrong with the brushsize --> size conversion.. however + * it's workable.. just unpredictable. + * + * North is always higher and East is always higher + * in the AABB representation + * + * Therefore what we're doing is looping from south to north and west to east + * and applying the associated algorithm with the brush. + * + * This works good on the fast ones, but things like smooth take 12 seconds a single click.. + * for now, smooth won't be 'selectionated' + * + * If the user draws instead of selects, north will = south, and east will = west. + * if the user selects, then the selection is inclusive + * it'll always affect at least one point on the heightmap. + * + * that means we use the <= operator + * + * Again, libTerrain is yx instead of xy.. so, it's reflected in the function calls + * + */ + + + switch (action) + { + case 0: + // flatten terrain + for (float x = south; x <= north; x++) + { + for (float y = west; y <= east; y++) + { + FlattenTerrain(y, x, size, (double) seconds/5.0); + lastEdit = DateTime.Now; + //remoteUser.SendLayerData((int)(x / 16), (int)(x / 16), GetHeights1D()); + + } + } + break; + case 1: + // raise terrain + for (float x = south; x <= north; x++) + { + for (float y = west; y <= east; y++) + { + RaiseTerrain(y, x, size, (double) seconds/5.0); + lastEdit = DateTime.Now; + //remoteUser.SendLayerData((int)(x / 16), (int)(x / 16), GetHeights1D()); + } + } + break; + case 2: + //lower terrain + for (float x = south; x <= north; x++) + { + for (float y = west; y <= east; y++) + { + LowerTerrain(y, x, size, (double) seconds/5.0); + lastEdit = DateTime.Now; + //remoteUser.SendLayerData((int)(x / 16), (int)(x / 16), GetHeights1D()); + } + } + break; + case 3: + // smooth terrain + // + // We're leaving this out of the parcel calculations for now + // because just a single one of these will stall your sim for + // 12 seconds. Looping over the parcel on this one is just stupid + // + //for (float x = south; x <= north; x++) + //{ + //for (float y = west; y <= east; y++) + //{ + //SmoothTerrain(y, x , size, (double)seconds / 5.0); + //} + //} + + SmoothTerrain(west, north, size, (double) seconds/5.0); + + break; + case 4: + // noise + for (float x = south; x <= north; x++) + { + for (float y = west; y <= east; y++) + { + NoiseTerrain(y, x, size, (double) seconds/5.0); + lastEdit = DateTime.Now; + } + } + break; + case 5: + // revert + for (float x = south; x <= north; x++) + { + for (float y = west; y <= east; y++) + { + RevertTerrain(y, x, size, (double) seconds/5.0); + lastEdit = DateTime.Now; + } + } + break; + + // CLIENT EXTENSIONS GO HERE + case 128: + // erode-thermal + break; + case 129: + // erode-aerobic + break; + case 130: + // erode-hydraulic + break; + } + + counter++; + if(counter==2) + { + counter=0; + for (int x = 0; x < 16; x++) + { + for (int y = 0; y < 16; y++) + { + if (IsTainted(x*16, y*16)) + { + remoteUser.SendLayerData(x, y, GetHeights1D()); + } + } + } + } + + + lastEdit = DateTime.Now; + + return; + } + + + + + /// + /// Checks to make sure the terrain is within baked values +/- maxRaise/minLower + /// + private void SetTerrainWithinBounds() + { + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + if ((heightmap.Get(x, y) > revertmap.Get(x, y) + maxRaise)) + { + heightmap.map[x, y] = revertmap.Get(x, y) + maxRaise; + } + if ((heightmap.Get(x, y) > revertmap.Get(x, y) - minLower)) + { + heightmap.map[x, y] = revertmap.Get(x, y) - minLower; + } + } + } + } + + + /// + /// Converts the heightmap to a 65536 value 1D floating point array + /// + /// A float[65536] array containing the heightmap + public float[] GetHeights1D() + { + float[] heights = new float[w*h]; + int i; + + for (i = 0; i < w*h; i++) + { + heights[i] = (float) heightmap.map[i%w, i/w]; + } + + return heights; + } + + /// + /// Converts the heightmap to a 256x256 value 2D floating point array. + /// + /// An array of 256,256 values containing the heightmap + public float[,] GetHeights2D() + { + float[,] heights = new float[w,h]; + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + heights[x, y] = (float) heightmap.map[x, y]; + } + } + return heights; + } + + /// + /// Converts the heightmap to a 256x256 value 2D floating point array. Double precision version. + /// + /// An array of 256,256 values containing the heightmap + public double[,] GetHeights2DD() + { + return heightmap.map; + } + + /// + /// Imports a 1D floating point array into the 2D heightmap array + /// + /// The array to import (must have 65536 members) + public void GetHeights1D(float[] heights) + { + int i; + for (i = 0; i < w*h; i++) + { + heightmap.map[i%w, i/w] = heights[i]; + } + + tainted++; + } + + /// + /// Loads a 2D array of values into the heightmap + /// + /// An array of 256,256 float values + public void SetHeights2D(float[,] heights) + { + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + heightmap.Set(x, y, (double) heights[x, y]); + } + } + SaveRevertMap(); + tainted++; + } + + /// + /// Loads a 2D array of values into the heightmap (Double Precision Version) + /// + /// An array of 256,256 float values + public void SetHeights2D(double[,] heights) + { + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + heightmap.Set(x, y, heights[x, y]); + } + } + SaveRevertMap(); + ResetTaint(); + } + + /// + /// Swaps the two heightmap buffers (the 'revert map' and the heightmap) + /// + public void SwapRevertMaps() + { + Channel backup = heightmap.Copy(); + heightmap = revertmap; + revertmap = backup; + } + + /// + /// Saves the current heightmap into the revertmap + /// + public void SaveRevertMap() + { + revertmap = heightmap.Copy(); + } + + /// + /// Processes a terrain-specific command + /// + /// Commandline arguments (space seperated) + /// Reference that returns error or help text if returning false + /// If the operation was successful (if not, the error is placed into resultText) + public bool RunTerrainCmd(string[] args, ref string resultText, string simName) + { + string command; + if (args.Length > 0) + { + command = args[0]; + } + else + { + command = "help"; + } + + try + { + switch (command) + { + case "help": + resultText += "terrain regenerate - rebuilds the sims terrain using a default algorithm\n"; + resultText += + "terrain hills \n"; + resultText += " type should be spheres, blocks, cones, or squared\n"; + resultText += + "terrain voronoi - generates a worley fractal with X points per block"; + resultText += "terrain seed - sets the random seed value to \n"; + resultText += + "terrain load - loads a terrain from disk, type can be 'F32', 'F64', 'RAW' or 'IMG'\n"; + resultText += + "terrain save - saves a terrain to disk, type can be 'F32', 'F64', 'PNG', 'RAW' or 'HIRAW'\n"; + resultText += + "terrain save grdmap - creates a PNG snapshot of the region using a named gradient map\n"; + resultText += + "terrain rescale - rescales a terrain to be between and meters high\n"; + resultText += "terrain fill - fills a terrain at the specified height\n"; + resultText += + "terrain erode aerobic \n"; + resultText += "terrain erode thermal \n"; + resultText += "terrain erode hydraulic \n"; + resultText += "terrain multiply - multiplies a terrain by \n"; + resultText += "terrain elevate - elevates a terrain by \n"; + resultText += "terrain revert - reverts the terrain to the stored original\n"; + resultText += "terrain bake - saves the current terrain into the revert map\n"; + resultText += + "terrain csfilter - loads a new filter from the specified .cs file\n"; + resultText += + "terrain jsfilter - loads a new filter from the specified .js file\n"; + foreach (KeyValuePair filter in customFilters.filters) + { + resultText += filter.Value.Help(); + } + + return false; + + case "revert": + SwapRevertMaps(); + SaveRevertMap(); + break; + + case "bake": + SaveRevertMap(); + break; + + case "seed": + SetSeed(Convert.ToInt32(args[1])); + break; + + case "erode": + return ConsoleErosion(args, ref resultText); + + case "voronoi": + double[] c = new double[2]; + c[0] = -1; + c[1] = 1; + heightmap.VoronoiDiagram(Convert.ToInt32(args[1]), Convert.ToInt32(args[2]), c); + break; + + case "hills": + return ConsoleHills(args, ref resultText); + + case "regenerate": + SetDefaultTerrain(); + break; + + case "rescale": + SetRange(Convert.ToSingle(args[1]), Convert.ToSingle(args[2])); + break; + + case "elevate": + Elevate(Convert.ToSingle(args[1])); + break; + + case "fill": + heightmap.Fill(Convert.ToDouble(args[1])); + tainted++; + break; + + case "clip": + heightmap.Clip(Convert.ToDouble(args[1]), Convert.ToDouble(args[2])); + tainted++; + break; + + case "smooth": + heightmap.Smooth(Convert.ToDouble(args[1])); + tainted++; + break; + + case "add": + heightmap += Convert.ToDouble(args[1]); + tainted++; + break; + + case "multiply": + heightmap *= Convert.ToDouble(args[1]); + tainted++; + break; + + case "load": + string filenameL = args[2].Replace("%name%", simName); + filenameL = filenameL.Replace("%x%", offsetX.ToString()); + filenameL = filenameL.Replace("%y%", offsetY.ToString()); + + switch (args[1].ToLower()) + { + case "f32": + LoadFromFileF32(filenameL); + break; + + case "f64": + LoadFromFileF64(filenameL); + break; + + case "raw": + LoadFromFileSLRAW(filenameL); + break; + + case "img": + heightmap = heightmap.LoadImage(filenameL); + tainted++; + break; + + default: + resultText = "Unknown image or data format"; + return false; + } + break; + + case "load-tile": + switch (args[1].ToLower()) + { + case "f32": + LoadFromFileF32(args[2], Convert.ToInt32(args[3]), Convert.ToInt32(args[4]), + Convert.ToInt32(args[5]), Convert.ToInt32(args[6])); + break; + case "raw": + LoadFromFileSLRAW(args[2], Convert.ToInt32(args[3]), Convert.ToInt32(args[4]), + Convert.ToInt32(args[5]), Convert.ToInt32(args[6])); + break; + case "img": + LoadFromFileIMG(args[2], Convert.ToInt32(args[3]), Convert.ToInt32(args[4]), + Convert.ToInt32(args[5]), Convert.ToInt32(args[6])); + break; + default: + resultText = "Unknown or unsupported image or data format"; + return false; + } + break; + + case "save": + string filename = args[2].Replace("%name%", simName); + filename = filename.Replace("%x%", offsetX.ToString()); + filename = filename.Replace("%y%", offsetY.ToString()); + + switch (args[1].ToLower()) + { + case "f32": + WriteToFileF32(filename); + break; + + case "f64": + WriteToFileF64(filename); + break; + + case "grdmap": + if (args.Length >= 4) + WriteImage(filename, args[3]); + else + WriteImage(filename, "defaultstripe.png"); + break; + + case "png": + heightmap.SaveImage(filename); + break; + + case "raw": + WriteToFileRAW(filename); + break; + + case "hiraw": + WriteToFileHiRAW(filename); + break; + + default: + resultText = "Unknown image or data format"; + return false; + } + break; + + case "csfilter": + customFilters.LoadFilterCSharp(args[1]); + break; + case "jsfilter": + customFilters.LoadFilterJScript(args[1]); + break; + + default: + // Run any custom registered filters + if (customFilters.filters.ContainsKey(command)) + { + customFilters.filters[command].Filter(heightmap, args); + break; + } + else + { + resultText = "Unknown terrain command"; + return false; + } + } + return true; + } + catch (Exception e) // SEMI-LEGIT: Catching problems caused by user input or scripts + { + resultText = "Error running terrain command: " + e.ToString(); + return false; + } + } + + private bool ConsoleErosion(string[] args, ref string resultText) + { + double min = heightmap.FindMin(); + double max = heightmap.FindMax(); + + switch (args[1].ToLower()) + { + case "aerobic": + // WindSpeed, PickupMinimum,DropMinimum,Carry,Rounds,Lowest + heightmap.AerobicErosion(Convert.ToDouble(args[2]), Convert.ToDouble(args[3]), + Convert.ToDouble(args[4]), Convert.ToDouble(args[5]), + Convert.ToInt32(args[6]), Convert.ToBoolean(args[7]), + Convert.ToBoolean(args[8])); + break; + case "thermal": + heightmap.ThermalWeathering(Convert.ToDouble(args[2]), Convert.ToInt32(args[3]), + Convert.ToDouble(args[4])); + break; + case "hydraulic": + Channel rainMap = new Channel(w, h); + rainMap.Fill(Convert.ToDouble(args[2])); + heightmap.HydraulicErosion(rainMap, Convert.ToDouble(args[3]), Convert.ToDouble(args[4]), + Convert.ToInt32(args[5]), Convert.ToInt32(args[6])); + break; + default: + resultText = "Unknown erosion type"; + return false; + } + + heightmap.Normalise(min, max); + + tainted++; + return true; + } + + private bool ConsoleHills(string[] args, ref string resultText) + { + Random RandomClass = new Random(); + SetSeed(RandomClass.Next()); + int count; + double sizeMin; + double sizeRange; + bool island; + bool additive; + bool noisy; + + if (args.GetLength(0) > 2) + { + int.TryParse(args[2].ToString(), out count); + double.TryParse(args[3].ToString(), NumberStyles.AllowDecimalPoint, Culture.NumberFormatInfo, + out sizeMin); + double.TryParse(args[4].ToString(), NumberStyles.AllowDecimalPoint, Culture.NumberFormatInfo, + out sizeRange); + bool.TryParse(args[5].ToString(), out island); + bool.TryParse(args[6].ToString(), out additive); + bool.TryParse(args[7].ToString(), out noisy); + } + else + { + count = 200; + sizeMin = 20; + sizeRange = 40; + island = true; + additive = true; + noisy = false; + } + + switch (args[1].ToLower()) + { + case "blocks": + heightmap.HillsBlocks(count, sizeMin, sizeRange, island, additive, noisy); + break; + case "cones": + heightmap.HillsCones(count, sizeMin, sizeRange, island, additive, noisy); + break; + case "spheres": + heightmap.HillsSpheres(count, sizeMin, sizeRange, island, additive, noisy); + break; + case "squared": + heightmap.HillsSquared(count, sizeMin, sizeRange, island, additive, noisy); + break; + default: + resultText = "Unknown hills type"; + return false; + } + tainted++; + return true; + } + + /// + /// Renormalises the array between min and max + /// + /// Minimum value of the new array + /// Maximum value of the new array + public void SetRange(float min, float max) + { + heightmap.Normalise((double) min, (double) max); + tainted++; + } + + /// + /// Adds meters (positive or negative) to terrain height + /// + /// Positive or negative value to add to new array + public void Elevate(float meters) + { + heightmap.Elevate((double)meters); + tainted++; + } + + /// + /// Loads a file consisting of 256x256 doubles and imports it as an array into the map. + /// + /// TODO: Move this to libTerrain itself + /// The filename of the double array to import + public void LoadFromFileF64(string filename) + { + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + BinaryReader bs = new BinaryReader(s); + int x, y; + for (y = 0; y < h; y++) + { + for (x = 0; x < h; x++) + { + heightmap.Set(x, y, (double) bs.ReadSingle()); + } + } + + bs.Close(); + s.Close(); + + tainted++; + } + + /// + /// Loads a file consisting of 256x256 floats and imports it as an array into the map. + /// + /// TODO: Move this to libTerrain itself + /// The filename of the float array to import + public void LoadFromFileF32(string filename) + { + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + BinaryReader bs = new BinaryReader(s); + int x, y; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + heightmap.Set(x, y, (double) bs.ReadSingle()); + } + } + + bs.Close(); + s.Close(); + + tainted++; + } + + /// + /// Loads a section of a larger heightmap (F32) + /// + /// File to load + /// Size of the file + /// Size of the file + /// Where do the region coords start for this terrain? + /// Where do the region coords start for this terrain? + public void LoadFromFileF32(string filename, int dimensionX, int dimensionY, int lowerboundX, int lowerboundY) + { + fileIOLock.WaitOne(); + try + { + int sectionToLoadX = ((offsetX - lowerboundX)*w); + int sectionToLoadY = ((offsetY - lowerboundY)*h); + + double[,] tempMap = new double[dimensionX,dimensionY]; + + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + BinaryReader bs = new BinaryReader(s); + + int x, y; + for (x = 0; x < dimensionX; x++) + { + for (y = 0; y < dimensionY; y++) + { + tempMap[x, y] = (double) bs.ReadSingle(); + } + } + + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + heightmap.Set(x, y, tempMap[x + sectionToLoadX, y + sectionToLoadY]); + } + } + + bs.Close(); + s.Close(); + + tainted++; + } + finally + { + fileIOLock.ReleaseMutex(); + } + } + + /// + /// Loads a larger tiled image across a terrain + /// + /// Filename to load from (any generic image format should work) + /// The dimensions of the image + /// The dimensions of the image + /// Where sim coords begin for this patch + /// Where sim coords begin for this patch + public void LoadFromFileIMG(string filename, int dimensionX, int dimensionY, int lowerboundX, int lowerboundY) + { + int sectionToLoadX = ((offsetX - lowerboundX)*w); + int sectionToLoadY = ((offsetY - lowerboundY)*h); + + double[,] tempMap = new double[dimensionX,dimensionY]; + + Bitmap lgrBmp = new Bitmap(filename); + + int x, y; + for (x = 0; x < dimensionX; x++) + { + for (y = 0; y < dimensionY; y++) + { + tempMap[x, y] = (float) lgrBmp.GetPixel(x, y).GetBrightness(); + } + } + + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + heightmap.Set(x, y, tempMap[x + sectionToLoadX, y + sectionToLoadY]); + } + } + + tainted++; + } + + /// + /// Loads a file formatted in the SL .RAW Format used on the main grid + /// + /// This file format stinks and is best avoided. + /// A path to the .RAW format + public void LoadFromFileSLRAW(string filename) + { + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + BinaryReader bs = new BinaryReader(s); + int x, y; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + heightmap.Set(x, y, (double) bs.ReadByte()*((double) bs.ReadByte()/127.0)); + bs.ReadBytes(11); // Advance the stream to next bytes. + } + } + + bs.Close(); + s.Close(); + + tainted++; + } + + /// + /// Loads a section of a larger heightmap (RAW) + /// + /// File to load + /// Size of the file + /// Size of the file + /// Where do the region coords start for this terrain? + /// Where do the region coords start for this terrain? + public void LoadFromFileSLRAW(string filename, int dimensionX, int dimensionY, int lowerboundX, int lowerboundY) + { + // TODO: Mutex fails to release readlock on folder! --> only one file can be loaded into sim + //fileIOLock.WaitOne(); + //try + //{ + int sectionToLoadX = ((offsetX - lowerboundX)*w); + int sectionToLoadY = ((offsetY - lowerboundY)*h); + + double[,] tempMap = new double[dimensionX,dimensionY]; + + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + BinaryReader bs = new BinaryReader(s); + + int x, y; + for (x = 0; x < dimensionX; x++) + { + for (y = 0; y < dimensionY; y++) + { + tempMap[x, y] = (double) bs.ReadByte()*((double) bs.ReadByte()/127.0); + bs.ReadBytes(11); // Advance the stream to next bytes. + } + } + + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + heightmap.Set(x, y, tempMap[x + sectionToLoadX, y + sectionToLoadY]); + } + } + + bs.Close(); + s.Close(); + + tainted++; + //} + //finally + //{ + // fileIOLock.ReleaseMutex(); + //} + } + + /// + /// Writes the current terrain heightmap to disk, in the format of a 65536 entry double[] array. + /// + /// The desired output filename + public void WriteToFileF64(string filename) + { + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write); + BinaryWriter bs = new BinaryWriter(s); + + int x, y; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + bs.Write(heightmap.Get(x, y)); + } + } + + bs.Close(); + s.Close(); + } + + /// + /// Writes the current terrain heightmap to disk, in the format of a 65536 entry float[] array + /// + /// The desired output filename + public void WriteToFileF32(string filename) + { + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write); + BinaryWriter bs = new BinaryWriter(s); + + int x, y; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + bs.Write((float) heightmap.Get(x, y)); + } + } + + bs.Close(); + s.Close(); + } + + /// + /// A very fast LL-RAW file output mechanism - lower precision mechanism but wont take 5 minutes to run either. + /// (is also editable in an image application) + /// + /// Filename to write to + public void WriteToFileRAW(string filename) + { + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write); + BinaryWriter binStream = new BinaryWriter(s); + + int x, y; + + // Used for the 'green' channel. + byte avgMultiplier = (byte) heightmap.Avg(); + byte backupMultiplier = (byte) revertmap.Avg(); + + // Limit the multiplier so it can represent points >64m. + if (avgMultiplier > 196) + avgMultiplier = 196; + if (backupMultiplier > 196) + backupMultiplier = 196; + // Make sure it's at least one to prevent a div by zero + if (avgMultiplier < 1) + avgMultiplier = 1; + if (backupMultiplier < 1) + backupMultiplier = 1; + + for (y = 0; y < h; y++) + { + for (x = 0; x < h; x++) + { + byte red = (byte) (heightmap.Get(x, y)/((double) avgMultiplier/128.0)); + byte green = avgMultiplier; + byte blue = (byte) watermap.Get(x, y); + byte alpha1 = 0; // Land Parcels + byte alpha2 = 0; // For Sale Land + byte alpha3 = 0; // Public Edit Object + byte alpha4 = 0; // Public Edit Land + byte alpha5 = 255; // Safe Land + byte alpha6 = 255; // Flying Allowed + byte alpha7 = 255; // Create Landmark + byte alpha8 = 255; // Outside Scripts + byte alpha9 = (byte) (revertmap.Get(x, y)/((double) backupMultiplier/128.0)); + byte alpha10 = backupMultiplier; + + binStream.Write(red); + binStream.Write(green); + binStream.Write(blue); + binStream.Write(alpha1); + binStream.Write(alpha2); + binStream.Write(alpha3); + binStream.Write(alpha4); + binStream.Write(alpha5); + binStream.Write(alpha6); + binStream.Write(alpha7); + binStream.Write(alpha8); + binStream.Write(alpha9); + binStream.Write(alpha10); + } + } + binStream.Close(); + s.Close(); + } + + /// + /// Outputs to a LL compatible RAW in the most efficient manner possible + /// + /// Does not calculate the revert map + /// The filename to output to + public void WriteToFileHiRAW(string filename) + { + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.CreateNew, FileAccess.Write); + BinaryWriter binStream = new BinaryWriter(s); + + // Generate a smegging big lookup table to speed the operation up (it needs it) + double[] lookupHeightTable = new double[65536]; + int i, j, x, y; + for (i = 0; i < 256; i++) + { + for (j = 0; j < 256; j++) + { + lookupHeightTable[i + (j*256)] = ((double) i*((double) j/127.0)); + } + } + + // Output the calculated raw + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + double t = heightmap.Get(x, y); + double min = double.MaxValue; + int index = 0; + + for (i = 0; i < 65536; i++) + { + if (Math.Abs(t - lookupHeightTable[i]) < min) + { + min = Math.Abs(t - lookupHeightTable[i]); + index = i; + } + } + + byte red = (byte) (index & 0xFF); + byte green = (byte) ((index >> 8) & 0xFF); + byte blue = (byte) watermap.Get(x, y); + byte alpha1 = 0; // Land Parcels + byte alpha2 = 0; // For Sale Land + byte alpha3 = 0; // Public Edit Object + byte alpha4 = 0; // Public Edit Land + byte alpha5 = 255; // Safe Land + byte alpha6 = 255; // Flying Allowed + byte alpha7 = 255; // Create Landmark + byte alpha8 = 255; // Outside Scripts + byte alpha9 = red; + byte alpha10 = green; + + binStream.Write(red); + binStream.Write(green); + binStream.Write(blue); + binStream.Write(alpha1); + binStream.Write(alpha2); + binStream.Write(alpha3); + binStream.Write(alpha4); + binStream.Write(alpha5); + binStream.Write(alpha6); + binStream.Write(alpha7); + binStream.Write(alpha8); + binStream.Write(alpha9); + binStream.Write(alpha10); + } + } + + binStream.Close(); + s.Close(); + } + + /// + /// Sets the random seed to be used by procedural functions which involve random numbers. + /// + /// The desired seed + public void SetSeed(int val) + { + heightmap.seed = val; + } + + /// + /// Sets a particular heightmap point to a specified value + /// + /// X Coordinate + /// Y Coordinate + /// Value + public void Set(int x, int y, double val) + { + lock (heightmap) + { + heightmap.Set(x, y, val); + } + tainted++; + } + + /// + /// Raises land in a sphere around the specified coordinates + /// + /// Center of the sphere on the X axis + /// Center of the sphere on the Y axis + /// The radius of the sphere + /// Scale the height of the sphere by this amount (recommended 0..2) + public void RaiseTerrain(double rx, double ry, double size, double amount) + { + lock (heightmap) + { + heightmap.Raise(rx, ry, size, amount); + } + + tainted++; + } + + /// + /// Lowers the land in a sphere around the specified coordinates + /// + /// The center of the sphere at the X axis + /// The center of the sphere at the Y axis + /// The radius of the sphere in meters + /// Scale the height of the sphere by this amount (recommended 0..2) + public void LowerTerrain(double rx, double ry, double size, double amount) + { + lock (heightmap) + { + heightmap.Lower(rx, ry, size, amount); + } + + tainted++; + } + + /// + /// Flattens the land under the brush of specified coordinates (spherical mask) + /// + /// Center of sphere + /// Center of sphere + /// Radius of the sphere + /// Thickness of the mask (0..2 recommended) + public void FlattenTerrain(double rx, double ry, double size, double amount) + { + lock (heightmap) + { + heightmap.Flatten(rx, ry, size, amount); + } + + tainted++; + } + + /// + /// Creates noise within the specified bounds + /// + /// Center of the bounding sphere + /// Center of the bounding sphere + /// The radius of the sphere + /// Strength of the mask (0..2) recommended + public void NoiseTerrain(double rx, double ry, double size, double amount) + { + lock (heightmap) + { + Channel smoothed = new Channel(); + smoothed.Noise(); + + Channel mask = new Channel(); + mask.Raise(rx, ry, size, amount); + + heightmap.Blend(smoothed, mask); + } + + tainted++; + } + + /// + /// Reverts land within the specified bounds + /// + /// Center of the bounding sphere + /// Center of the bounding sphere + /// The radius of the sphere + /// Strength of the mask (0..2) recommended + public void RevertTerrain(double rx, double ry, double size, double amount) + { + lock (heightmap) + { + Channel mask = new Channel(); + mask.Raise(rx, ry, size, amount); + + heightmap.Blend(revertmap, mask); + } + + tainted++; + } + + /// + /// Smooths land under the brush of specified coordinates (spherical mask) + /// + /// Center of the sphere + /// Center of the sphere + /// Radius of the sphere + /// Thickness of the mask (0..2 recommended) + public void SmoothTerrain(double rx, double ry, double size, double amount) + { + lock (heightmap) + { + Channel smoothed = heightmap.Copy(); + smoothed.Smooth(amount); + + Channel mask = new Channel(); + mask.Raise(rx, ry, size, amount); + + heightmap.Blend(smoothed, mask); + } + + tainted++; + } + + /// + /// Generates a simple set of hills in the shape of an island + /// + public void SetDefaultTerrain() + { + lock (heightmap) + { + heightmap.HillsSpheres(200, 20, 40, true, true, false); + heightmap.Normalise(); + heightmap *= 60.0; // Raise to 60m + heightmap.Clip(0.0, 25.0); + heightmap.Pertubation(2.5); + heightmap.Smooth(35.0); + heightmap.Normalise(0.0, 21.0); + } + + tainted++; + } + + /// + /// Wrapper to heightmap.get() + /// + /// X coord + /// Y coord + /// Height at specified coordinates + public double GetHeight(int x, int y) + { + return heightmap.Get(x, y); + } + + /// + /// Multiplies the heightfield by val + /// + /// The heightfield + /// The multiplier + /// + public static TerrainEngine operator *(TerrainEngine terrain, Double val) + { + terrain.heightmap *= val; + terrain.tainted++; + return terrain; + } + + /// + /// Exports the current heightmap to a PNG file + /// + /// The destination filename for the image + /// A 1x*height* image which contains the colour gradient to export with. Must be at least 1x2 pixels, 1x256 or more is ideal. + public void WriteImage(string filename, string gradientmap) + { + try + { + Bitmap bmp = TerrainToBitmap(gradientmap); + + bmp.Save(filename, ImageFormat.Png); + } + catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke + { + Console.WriteLine("Failed generating terrain map: " + e.ToString()); + } + } + + /// + /// Exports the current heightmap in Jpeg2000 format to a byte[] + /// + /// A 1x*height* image which contains the colour gradient to export with. Must be at least 1x2 pixels, 1x256 or more is ideal. + public byte[] WriteJpegImage(string gradientmap) + { + byte[] imageData = null; + try + { + Bitmap bmp = TerrainToBitmap(gradientmap); + + imageData = OpenJPEG.EncodeFromImage(bmp, true); + } + catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke + { + Console.WriteLine("Failed generating terrain map: " + e.ToString()); + } + + return imageData; + } + + private Bitmap TerrainToBitmap(string gradientmap) + { + Bitmap gradientmapLd = new Bitmap(gradientmap); + + int pallete = gradientmapLd.Height; + + Bitmap bmp = new Bitmap(heightmap.w, heightmap.h); + Color[] colours = new Color[pallete]; + + for (int i = 0; i < pallete; i++) + { + colours[i] = gradientmapLd.GetPixel(0, i); + } + + Channel copy = heightmap.Copy(); + for (int y = 0; y < copy.h; y++) + { + for (int x = 0; x < copy.w; x++) + { + // 512 is the largest possible height before colours clamp + int colorindex = (int) (Math.Max(Math.Min(1.0, copy.Get(x, y)/512.0), 0.0)*(pallete - 1)); + bmp.SetPixel(x, copy.h - y - 1, colours[colorindex]); + } + } + return bmp; + } + } +} diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/TerrainFilter.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/TerrainFilter.cs new file mode 100644 index 0000000000..c56e29e9b9 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/TerrainFilter.cs @@ -0,0 +1,125 @@ +/* +* 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; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using libTerrain; +using Microsoft.CSharp; +using Microsoft.JScript; + +namespace OpenSim.Region.Terrain +{ + public interface ITerrainFilter + { + void Filter(Channel heightmap, string[] args); + string Register(); + string Help(); + } + + public class TestFilter : ITerrainFilter + { + public void Filter(Channel heightmap, string[] args) + { + Console.WriteLine("Hello world"); + } + + public string Register() + { + return "demofilter"; + } + + public string Help() + { + return "demofilter - Does nothing"; + } + } + + public class FilterHost + { + public Dictionary filters = new Dictionary(); + + private void LoadFilter(CodeDomProvider compiler, string filename) + { + CompilerParameters compilerParams = new CompilerParameters(); + CompilerResults compilerResults; + compilerParams.GenerateExecutable = false; + compilerParams.GenerateInMemory = true; + compilerParams.IncludeDebugInformation = false; + compilerParams.ReferencedAssemblies.Add("OpenSim.Terrain.BasicTerrain.dll"); + compilerParams.ReferencedAssemblies.Add("System.dll"); + + compilerResults = compiler.CompileAssemblyFromFile(compilerParams, filename); + + if (compilerResults.Errors.Count > 0) + { + Console.WriteLine("Compile errors:"); + foreach (CompilerError error in compilerResults.Errors) + { + Console.WriteLine(error.Line.ToString() + ": " + error.ErrorText.ToString()); + } + } + else + { + foreach (Type pluginType in compilerResults.CompiledAssembly.GetExportedTypes()) + { + Type testInterface = pluginType.GetInterface("ITerrainFilter", true); + + if (testInterface != null) + { + ITerrainFilter filter = + (ITerrainFilter) compilerResults.CompiledAssembly.CreateInstance(pluginType.ToString()); + + string filterName = filter.Register(); + Console.WriteLine("Plugin: " + filterName + " loaded."); + + if (!filters.ContainsKey(filterName)) + { + filters.Add(filterName, filter); + } + else + { + filters[filterName] = filter; + } + } + } + } + } + + public void LoadFilterCSharp(string filename) + { + CSharpCodeProvider compiler = new CSharpCodeProvider(); + LoadFilter(compiler, filename); + } + + public void LoadFilterJScript(string filename) + { + JScriptCodeProvider compiler = new JScriptCodeProvider(); + LoadFilter(compiler, filename); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Bitmap/Bitmap.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Bitmap/Bitmap.cs new file mode 100644 index 0000000000..b761f1eebe --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Bitmap/Bitmap.cs @@ -0,0 +1,86 @@ +/* +* 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.Drawing; +using System.Drawing.Imaging; + +namespace libTerrain +{ + internal class Raster + { + private Bitmap bmp; + + /// + /// Creates a new Raster channel for use with bitmap or GDI functions + /// + /// Width in pixels + /// Height in pixels + public Raster(int width, int height) + { + bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb); + } + + /// + /// Converts a raster image to a channel by averaging the RGB values to a single 0..1 heightmap + /// + /// A libTerrain Channel + public Channel ToChannel() + { + Channel chan = new Channel(bmp.Width, bmp.Height); + + int x, y; + for (x = 0; x < bmp.Width; x++) + { + for (y = 0; y < bmp.Height; y++) + { + Color val = bmp.GetPixel(x, y); + chan.map[x, y] = (((double) val.R + (double) val.G + (double) val.B)/3.0)/255.0; + } + } + + return chan; + } + + /// + /// Draws a piece of text into the specified raster + /// + /// The text string to print + /// The font to use to draw the specified image + /// Font size (points) to use + public void DrawText(string txt, string font, double size) + { + Rectangle area = new Rectangle(0, 0, 256, 256); + StringFormat sf = new StringFormat(); + sf.Alignment = StringAlignment.Center; + sf.LineAlignment = StringAlignment.Center; + + Graphics gd = Graphics.FromImage(bmp); + gd.DrawString(txt, new Font(font, (float) size), new SolidBrush(Color.White), area, sf); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Channel.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Channel.cs new file mode 100644 index 0000000000..a7f7246c07 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Channel.cs @@ -0,0 +1,60 @@ +/* +* 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. +* +*/ + +/* Channel + * A channel is a single heightmap array + * */ + +namespace libTerrain +{ + partial class Channel + { + public double[,] map; + public int[,] diff; + public int w; + public int h; + + public int seed = 1338; // One better than 1337 + + public Channel() + { + w = 256; + h = 256; + map = new double[w,h]; + diff = new int[(int) (w/16),(int) (h/16)]; + } + + public Channel(int width, int height) + { + w = width; + h = height; + map = new double[w,h]; + diff = new int[(int) (w/16),(int) (h/16)]; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Common.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Common.cs new file mode 100644 index 0000000000..8bc4a04083 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Common.cs @@ -0,0 +1,283 @@ +/* +* 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; + +namespace libTerrain +{ + public partial class Channel + { + public int GetWidth() + { + return w; + } + + public int GetHeight() + { + return h; + } + + public Channel Copy() + { + Channel x = new Channel(w, h); + x.map = (double[,]) map.Clone(); + return x; + } + + public void SetDiff() + { + SetDiff(1); + } + + public void SetDiff(int val) + { + for (int x = 0; x < w/16; x++) + { + for (int y = 0; y < h/16; y++) + { + diff[x, y] = val; + } + } + } + + public void SetDiff(int x, int y) + { + diff[x/16, y/16]++; + } + + public void Set(int x, int y, double val) + { + if (x >= w) + throw new Exception("Bounds error while setting pixel (width)"); + if (y >= h) + throw new Exception("Bounds error while setting pixel (height)"); + if (x < 0) + throw new Exception("Bounds error while setting pixel (width)"); + if (y < 0) + throw new Exception("Bounds error while setting pixel (height)"); + + if (map[x, y] != val) + { + SetDiff(x, y); + + map[x, y] = val; + } + } + + public void SetClip(int x, int y, double val) + { + SetDiff(x, y); + + if (x >= w) + throw new Exception("Bounds error while setting pixel (width)"); + if (y >= h) + throw new Exception("Bounds error while setting pixel (height)"); + if (x < 0) + throw new Exception("Bounds error while setting pixel (width)"); + if (y < 0) + throw new Exception("Bounds error while setting pixel (height)"); + + if (val > 1.0) + val = 1.0; + if (val < 0.0) + val = 0.0; + + map[x, y] = val; + } + + private double GetBilinearInterpolate(double x, double y) + { + if (x > w - 2.0) + x = w - 2.0; + if (y > h - 2.0) + y = h - 2.0; + if (x < 0.0) + x = 0.0; + if (y < 0.0) + y = 0.0; + + int stepSize = 1; + double h00 = Get((int) x, (int) y); + double h10 = Get((int) x + stepSize, (int) y); + double h01 = Get((int) x, (int) y + stepSize); + double h11 = Get((int) x + stepSize, (int) y + stepSize); + double h1 = h00; + double h2 = h10; + double h3 = h01; + double h4 = h11; + double a00 = h1; + double a10 = h2 - h1; + double a01 = h3 - h1; + double a11 = h1 - h2 - h3 + h4; + double partialx = x - (int) x; + double partialz = y - (int) y; + double hi = a00 + (a10*partialx) + (a01*partialz) + (a11*partialx*partialz); + return hi; + } + + public double Get(int x, int y) + { + try + { + return map[x, y]; + } + catch (IndexOutOfRangeException) + { + if (x >= w) + x = w - 1; + if (y >= h) + y = h - 1; + if (x < 0) + x = 0; + if (y < 0) + y = 0; + return map[x, y]; + } + } + + public void SetWrap(int x, int y, double val) + { + SetDiff(x, y); + + map[x%w, y%h] = val; + } + + public void SetWrapClip(int x, int y, double val) + { + SetDiff(x, y); + + if (val > 1.0) + val = 1.0; + if (val < 0.0) + val = 0.0; + + map[x%w, y%h] = val; + } + + public void Fill(double val) + { + SetDiff(); + + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + map[x, y] = val; + } + } + } + + public void Fill(double min, double max, double val) + { + SetDiff(); + + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + if (map[x, y] >= min && map[x, y] <= max) + map[x, y] = val; + } + } + } + + public double FindMax() + { + int x, y; + double max = double.MinValue; + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + if (map[x, y] > max) + max = map[x, y]; + } + } + + return max; + } + + public double FindMin() + { + int x, y; + double min = double.MaxValue; + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + if (map[x, y] < min) + min = map[x, y]; + } + } + + return min; + } + + public double Sum() + { + int x, y; + double sum = 0.0; + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + sum += map[x, y]; + } + } + + return sum; + } + + public double Avg() + { + return Sum()/(w*h); + } + + public bool ContainsNaN() + { + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + double elm = map[x, y]; + + if (Double.IsNaN(elm)) + return true; + } + } + return false; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Editing/Flatten.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Editing/Flatten.cs new file mode 100644 index 0000000000..0946c6ac5d --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Editing/Flatten.cs @@ -0,0 +1,144 @@ +/* +* 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; + +namespace libTerrain +{ + partial class Channel + { + /// + /// Flattens the area underneath rx,ry by moving it to the average of the area. Uses a spherical mask provided by the raise() function. + /// + /// The X coordinate of the terrain mask + /// The Y coordinate of the terrain mask + /// The size of the terrain mask + /// The scale of the terrain mask + public void Flatten(double rx, double ry, double size, double amount) + { + FlattenSlow(rx, ry, size, amount); + } + + private void FlattenSlow(double rx, double ry, double size, double amount) + { + // Generate the mask + Channel temp = new Channel(w, h); + temp.Fill(0); + temp.Raise(rx, ry, size, amount); + temp.Normalise(); + double total_mod = temp.Sum(); + + // Establish the average height under the area + Channel newmap = new Channel(w, h); + newmap.map = (double[,]) map.Clone(); + + newmap *= temp; + + double total_terrain = newmap.Sum(); + double avg_height = total_terrain/total_mod; + + // Create a flat terrain using the average height + Channel flat = new Channel(w, h); + flat.Fill(avg_height); + + // Blend the current terrain with the average height terrain + // using the "raised" empty terrain as a mask + Blend(flat, temp); + } + + private void FlattenFast(double rx, double ry, double size, double amount) + { + int x, y; + double avg = 0; + double div = 0; + + int minX = Math.Max(0, (int) (rx - (size + 1))); + int maxX = Math.Min(w, (int) (rx + (size + 1))); + int minY = Math.Max(0, (int) (ry - (size + 1))); + int maxY = Math.Min(h, (int) (ry + (size + 1))); + + for (x = minX; x < maxX; x++) + { + for (y = minY; y < maxY; y++) + { + double z = size; + z *= z; + z -= ((x - rx)*(x - rx)) + ((y - ry)*(y - ry)); + + if (z < 0) + z = 0; + + avg += z*amount; + div += z; + } + } + + double height = avg/div; + + for (x = minX; x < maxX; x++) + { + for (y = minY; y < maxY; y++) + { + double z = size; + z *= z; + z -= ((x - rx)*(x - rx)) + ((y - ry)*(y - ry)); + + if (z > 0.0) + Set(x, y, Tools.LinearInterpolate(map[x, y], height, z)); + } + } + } + + public void Flatten(Channel mask, double amount) + { + // Generate the mask + Channel temp = mask*amount; + temp.Clip(0, 1); // Cut off out-of-bounds values + + double total_mod = temp.Sum(); + + // Establish the average height under the area + Channel map = new Channel(w, h); + map.map = (double[,]) this.map.Clone(); + + map *= temp; + + double total_terrain = map.Sum(); + double avg_height = total_terrain/total_mod; + + // Create a flat terrain using the average height + Channel flat = new Channel(w, h); + flat.Fill(avg_height); + + // Blend the current terrain with the average height terrain + // using the "raised" empty terrain as a mask + Blend(flat, temp); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Editing/Raise.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Editing/Raise.cs new file mode 100644 index 0000000000..523a065c4e --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Editing/Raise.cs @@ -0,0 +1,131 @@ +/* +* 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; + +namespace libTerrain +{ + partial class Channel + { + /// + /// Raises land around the selection + /// + /// The center the X coordinate of where you wish to raise the land + /// The center the Y coordinate of where you wish to raise the land + /// The radius of the dimple + /// How much impact to add to the terrain (0..2 usually) + public void Raise(double rx, double ry, double size, double amount) + { + RaiseSphere(rx, ry, size, amount); + } + + /// + /// Raises land in a sphere around the selection + /// + /// The center the X coordinate of where you wish to raise the land + /// The center the Y coordinate of where you wish to raise the land + /// The radius of the sphere dimple + /// How much impact to add to the terrain (0..2 usually) + public void RaiseSphere(double rx, double ry, double size, double amount) + { + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + double z = size; + z *= z; + z -= ((x - rx)*(x - rx)) + ((y - ry)*(y - ry)); + + if (z > 0.0) + Set(x, y, map[x, y] + (z * amount)); + } + } + } + + /// + /// Raises land in a cone around the selection + /// + /// The center the X coordinate of where you wish to raise the land + /// The center the Y coordinate of where you wish to raise the land + /// The radius of the cone + /// How much impact to add to the terrain (0..2 usually) + public void RaiseCone(double rx, double ry, double size, double amount) + { + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + double z = size; + z -= Math.Sqrt(((x - rx)*(x - rx)) + ((y - ry)*(y - ry))); + + if (z > 0.0) + Set(x, y, map[x, y] + (z * amount)); + } + } + } + + /// + /// Lowers land in a sphere around the selection + /// + /// The center the X coordinate of where you wish to lower the land + /// The center the Y coordinate of where you wish to lower the land + /// The radius of the sphere dimple + /// How much impact to remove from the terrain (0..2 usually) + public void Lower(double rx, double ry, double size, double amount) + { + LowerSphere(rx, ry, size, amount); + } + + /// + /// Lowers land in a sphere around the selection + /// + /// The center the X coordinate of where you wish to lower the land + /// The center the Y coordinate of where you wish to lower the land + /// The radius of the sphere dimple + /// How much impact to remove from the terrain (0..2 usually) + public void LowerSphere(double rx, double ry, double size, double amount) + { + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + double z = size; + z *= z; + z -= ((x - rx)*(x - rx)) + ((y - ry)*(y - ry)); + + if (z > 0.0) + Set(x, y, map[x, y] - (z * amount)); + } + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/File.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/File.cs new file mode 100644 index 0000000000..3d51583427 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/File.cs @@ -0,0 +1,76 @@ +/* +* 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; +using System.Drawing; +using System.Drawing.Imaging; + +namespace libTerrain +{ + partial class Channel + { + public Channel LoadImage(string filename) + { + SetDiff(); + + Bitmap bit = new Bitmap(filename); + Channel chan = new Channel(bit.Width, bit.Height); + + int x, y; + for (x = 0; x < bit.Width; x++) + { + for (y = 0; y < bit.Height; y++) + { + Color val = bit.GetPixel(x, y); + chan.map[x, y] = (((double) val.R + (double) val.G + (double) val.B)/3.0)/255.0; + } + } + + return chan; + } + + public void SaveImage(string filename) + { + Channel outmap = Copy(); + outmap.Normalise(); + + Bitmap bit = new Bitmap(w, h, PixelFormat.Format24bppRgb); + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + int val = Math.Min(255, (int) (outmap.map[x, y]*255)); + Color col = Color.FromArgb(val, val, val); + bit.SetPixel(x, y, col); + } + } + bit.Save(filename); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Cellular.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Cellular.cs new file mode 100644 index 0000000000..19acea6135 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Cellular.cs @@ -0,0 +1,29 @@ +/* +* 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. +* +*/ + +/* Needs BSD rewrite */ diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Fracture.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Fracture.cs new file mode 100644 index 0000000000..992377f99b --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Fracture.cs @@ -0,0 +1,143 @@ +/* +* 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; + +namespace libTerrain +{ + partial class Channel + { + /// + /// Produces a set of coordinates defined by an edge point. Eg - 0 = 0,0. 256 = 0,256. 512 = 256,256 + /// Assumes a 256^2 heightmap. This needs fixing for input values of w,h + /// + /// + /// + /// + /// + private int[] RadialEdge256(int val) + { + // Four cases: + // 1. 000..255 return 0,val + // 2. 256..511 return val - 256,255 + // 3. 512..767 return 255, val - 511 + // 4. 768..1023 return val - 768,0 + + int[] ret = new int[2]; + + if (val < 256) + { + ret[0] = 0; + ret[1] = val; + return ret; + } + if (val < 512) + { + ret[0] = (val%256); + ret[1] = 255; + return ret; + } + if (val < 768) + { + ret[0] = 255; + ret[1] = 255 - (val%256); + return ret; + } + if (val < 1024) + { + ret[0] = 255 - (val%256); + ret[1] = 255; + return ret; + } + + throw new Exception("Out of bounds parameter (val)"); + } + + public void Fracture(int number, double scalemin, double scalemax) + { + SetDiff(); + + Random rand = new Random(seed); + + for (int i = 0; i < number; i++) + { + int[] a, b; + + a = RadialEdge256(rand.Next(1023)); // TODO: Broken + b = RadialEdge256(rand.Next(1023)); // TODO: Broken + double z = rand.NextDouble(); + double u = rand.NextDouble(); + double v = rand.NextDouble(); + + for (int x = 0; x < w; x++) + { + for (int y = 0; y < h; y++) + { + double miny = Tools.LinearInterpolate(a[1], b[1], (double) x/(double) w); + + if (v >= 0.5) + { + if (u >= 0.5) + { + if (y > miny) + { + map[x, y] += Tools.LinearInterpolate(scalemin, scalemax, z); + } + } + else + { + if (y < miny) + { + map[x, y] += Tools.LinearInterpolate(scalemin, scalemax, z); + } + } + } + else + { + if (u >= 0.5) + { + if (x > miny) + { + map[x, y] += Tools.LinearInterpolate(scalemin, scalemax, z); + } + } + else + { + if (x < miny) + { + map[x, y] += Tools.LinearInterpolate(scalemin, scalemax, z); + } + } + } + } + } + } + Normalise(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Gradient.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Gradient.cs new file mode 100644 index 0000000000..6cdf7ce0cb --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Gradient.cs @@ -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 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. +* +*/ + +namespace libTerrain +{ + partial class Channel + { + public void GradientCube() + { + SetDiff(); + + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + map[x, y] = x*y; + } + } + Normalise(); + } + + public void GradientStripe() + { + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + map[x, y] = x; + } + } + Normalise(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/HillPlanter.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/HillPlanter.cs new file mode 100644 index 0000000000..000bfcc7d6 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/HillPlanter.cs @@ -0,0 +1,282 @@ +/* +* 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; + +namespace libTerrain +{ + partial class Channel + { + /// + /// Generates a series of spheres which are then either max()'d or added together. Inspired by suggestion from jh. + /// + /// 3-Clause BSD Licensed + /// The number of hills to generate + /// The minimum size of each hill + /// The maximum size of each hill + /// Whether to bias hills towards the center of the map + /// Whether to add hills together or to pick the largest value + /// Generates hill-shaped noise instead of consistent hills + public void HillsSpheres(int number, double scale_min, double scale_range, bool island, bool additive, + bool noisy) + { + SetDiff(); + + Random random = new Random(seed); + + int x, y; + int i; + + for (i = 0; i < number; i++) + { + double rx = Math.Min(255.0, random.NextDouble()*w); + double ry = Math.Min(255.0, random.NextDouble()*h); + double rand = random.NextDouble(); + + if (island) + { + // Move everything towards the center + rx -= w/2; + rx /= 2; + rx += w/2; + + ry -= h/2; + ry /= 2; + ry += h/2; + } + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + if (noisy) + rand = random.NextDouble(); + + double z = (scale_min + (scale_range*rand)); + z *= z; + z -= ((x - rx)*(x - rx)) + ((y - ry)*(y - ry)); + + if (z < 0) + z = 0; + + if (additive) + { + map[x, y] += z; + } + else + { + map[x, y] = Math.Max(map[x, y], z); + } + } + } + } + + Normalise(); + } + + /// + /// Generates a series of cones which are then either max()'d or added together. Inspired by suggestion from jh. + /// + /// 3-Clause BSD Licensed + /// The number of hills to generate + /// The minimum size of each hill + /// The maximum size of each hill + /// Whether to bias hills towards the center of the map + /// Whether to add hills together or to pick the largest value + /// Generates hill-shaped noise instead of consistent hills + public void HillsCones(int number, double scale_min, double scale_range, bool island, bool additive, bool noisy) + { + SetDiff(); + + Random random = new Random(seed); + + int x, y; + int i; + + for (i = 0; i < number; i++) + { + double rx = Math.Min(255.0, random.NextDouble()*w); + double ry = Math.Min(255.0, random.NextDouble()*h); + double rand = random.NextDouble(); + + if (island) + { + // Move everything towards the center + rx -= w/2; + rx /= 2; + rx += w/2; + + ry -= h/2; + ry /= 2; + ry += h/2; + } + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + if (noisy) + rand = random.NextDouble(); + + double z = (scale_min + (scale_range*rand)); + z -= Math.Sqrt(((x - rx)*(x - rx)) + ((y - ry)*(y - ry))); + + if (z < 0) + z = 0; + + if (additive) + { + map[x, y] += z; + } + else + { + map[x, y] = Math.Max(map[x, y], z); + } + } + } + } + + Normalise(); + } + + public void HillsBlocks(int number, double scale_min, double scale_range, bool island, bool additive, bool noisy) + { + SetDiff(); + + Random random = new Random(seed); + + int x, y; + int i; + + for (i = 0; i < number; i++) + { + double rx = Math.Min(255.0, random.NextDouble()*w); + double ry = Math.Min(255.0, random.NextDouble()*h); + double rand = random.NextDouble(); + + if (island) + { + // Move everything towards the center + rx -= w/2; + rx /= 2; + rx += w/2; + + ry -= h/2; + ry /= 2; + ry += h/2; + } + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + if (noisy) + rand = random.NextDouble(); + + double z = (scale_min + (scale_range*rand)); + z -= Math.Abs(x - rx) + Math.Abs(y - ry); + //z -= Math.Sqrt(((x - rx) * (x - rx)) + ((y - ry) * (y - ry))); + + if (z < 0) + z = 0; + + if (additive) + { + map[x, y] += z; + } + else + { + map[x, y] = Math.Max(map[x, y], z); + } + } + } + } + + Normalise(); + } + + public void HillsSquared(int number, double scale_min, double scale_range, bool island, bool additive, + bool noisy) + { + SetDiff(); + + Random random = new Random(seed); + + int x, y; + int i; + + for (i = 0; i < number; i++) + { + double rx = Math.Min(255.0, random.NextDouble()*w); + double ry = Math.Min(255.0, random.NextDouble()*h); + double rand = random.NextDouble(); + + if (island) + { + // Move everything towards the center + rx -= w/2; + rx /= 2; + rx += w/2; + + ry -= h/2; + ry /= 2; + ry += h/2; + } + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + if (noisy) + rand = random.NextDouble(); + + double z = (scale_min + (scale_range*rand)); + z *= z*z*z; + double dx = Math.Abs(x - rx); + double dy = Math.Abs(y - ry); + z -= (dx*dx*dx*dx) + (dy*dy*dy*dy); + + if (z < 0) + z = 0; + + if (additive) + { + map[x, y] += z; + } + else + { + map[x, y] = Math.Max(map[x, y], z); + } + } + } + } + + Normalise(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Midpoint.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Midpoint.cs new file mode 100644 index 0000000000..19acea6135 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Midpoint.cs @@ -0,0 +1,29 @@ +/* +* 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. +* +*/ + +/* Needs BSD rewrite */ diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Mountain.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Mountain.cs new file mode 100644 index 0000000000..19acea6135 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Mountain.cs @@ -0,0 +1,29 @@ +/* +* 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. +* +*/ + +/* Needs BSD rewrite */ diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Noise.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Noise.cs new file mode 100644 index 0000000000..0bce1b22fb --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Noise.cs @@ -0,0 +1,54 @@ +/* +* 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; + +namespace libTerrain +{ + partial class Channel + { + /// + /// Fills a channel with 0..1 noise + /// + /// 3-Clause BSD Licensed + public void Noise() + { + SetDiff(); + + Random rand = new Random(seed); + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + map[x, y] = rand.NextDouble(); + } + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Spiral.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Spiral.cs new file mode 100644 index 0000000000..414f8447e0 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Spiral.cs @@ -0,0 +1,157 @@ +/* +* 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; +using System.Collections.Generic; + +namespace libTerrain +{ + partial class Channel + { + private double[] CoordinatesToPolar(int x, int y) + { + double theta = Math.Atan2(x - (w/2), y - (h/2)); + double rx = (double) x - ((double) w/2); + double ry = (double) y - ((double) h/2); + double r = Math.Sqrt((rx*rx) + (ry*ry)); + + double[] coords = new double[2]; + coords[0] = r; + coords[1] = theta; + return coords; + } + + public int[] PolarToCoordinates(double r, double theta) + { + double nx; + double ny; + + nx = (double) r*Math.Cos(theta); + ny = (double) r*Math.Sin(theta); + + nx += w/2; + ny += h/2; + + if (nx >= w) + nx = w - 1; + + if (ny >= h) + ny = h - 1; + + if (nx < 0) + nx = 0; + + if (ny < 0) + ny = 0; + + int[] coords = new int[2]; + coords[0] = (int) nx; + coords[1] = (int) ny; + return coords; + } + + public void Polar() + { + SetDiff(); + + Channel n = Copy(); + + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + double[] coords = CoordinatesToPolar(x, y); + + coords[0] += w/2.0; + coords[1] += h/2.0; + + map[x, y] = n.map[(int) coords[0]%n.w, (int) coords[1]%n.h]; + } + } + } + + public void SpiralPlanter(int steps, double incAngle, double incRadius, double offsetRadius, double offsetAngle) + { + SetDiff(); + + int i; + double r = offsetRadius; + double theta = offsetAngle; + for (i = 0; i < steps; i++) + { + r += incRadius; + theta += incAngle; + + int[] coords = PolarToCoordinates(r, theta); + Raise(coords[0], coords[1], 20, 1); + } + } + + public void SpiralCells(int steps, double incAngle, double incRadius, double offsetRadius, double offsetAngle, + double[] c) + { + SetDiff(); + + List points = new List(); + + int i; + double r = offsetRadius; + double theta = offsetAngle; + for (i = 0; i < steps; i++) + { + r += incRadius; + theta += incAngle; + + int[] coords = PolarToCoordinates(r, theta); + points.Add(new Point2D(coords[0], coords[1])); + } + + VoronoiDiagram(points, c); + } + + public void Spiral(double wid, double hig, double offset) + { + SetDiff(); + + int x, y, z; + z = 0; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + z++; + double dx = Math.Abs((w/2) - x); + double dy = Math.Abs((h/2) - y); + map[x, y] += Math.Sin(dx/wid) + Math.Cos(dy/hig); + } + } + Normalise(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Voronoi.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Voronoi.cs new file mode 100644 index 0000000000..e1884868e7 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Voronoi.cs @@ -0,0 +1,212 @@ +/* +* 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; +using System.Collections.Generic; + +namespace libTerrain +{ + partial class Channel + { + /// + /// Generates a Voronoi diagram (sort of a stained glass effect) which will fill the entire channel + /// + /// 3-Clause BSD Licensed + /// The number of generator points in each block + /// A multiple of the channel width and height which will have voronoi points generated in it. + /// This is to ensure a more even distribution of the points than pure random allocation. + /// The Voronoi diagram type. Usually an array with values consisting of [-1,1]. Experiment with the chain, you can have as many values as you like. + public void VoronoiDiagram(int pointsPerBlock, int blockSize, double[] c) + { + SetDiff(); + + List points = new List(); + Random generator = new Random(seed); + + // Generate the emitter points + int x, y, i; + for (x = -blockSize; x < w + blockSize; x += blockSize) + { + for (y = -blockSize; y < h + blockSize; y += blockSize) + { + for (i = 0; i < pointsPerBlock; i++) + { + double pX = x + (generator.NextDouble()*(double) blockSize); + double pY = y + (generator.NextDouble()*(double) blockSize); + + points.Add(new Point2D(pX, pY)); + } + } + } + + double[] distances = new double[points.Count]; + + // Calculate the distance each pixel is from an emitter + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + for (i = 0; i < points.Count; i++) + { + double dx, dy; + dx = Math.Abs((double) x - points[i].x); + dy = Math.Abs((double) y - points[i].y); + + distances[i] = (dx*dx + dy*dy); + } + + Array.Sort(distances); + + double f = 0.0; + + // Multiply the distances with their 'c' counterpart + // ordering the distances descending + for (i = 0; i < c.Length; i++) + { + if (i >= points.Count) + break; + + f += c[i]*distances[i]; + } + + map[x, y] = f; + } + } + + // Normalise the result + Normalise(); + } + + public void VoronoiDiagram(List points, double[] c) + { + SetDiff(); + + int x, y, i; + double[] distances = new double[points.Count]; + + // Calculate the distance each pixel is from an emitter + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + for (i = 0; i < points.Count; i++) + { + double dx, dy; + dx = Math.Abs((double) x - points[i].x); + dy = Math.Abs((double) y - points[i].y); + + distances[i] = (dx*dx + dy*dy); + } + + Array.Sort(distances); + + double f = 0.0; + + // Multiply the distances with their 'c' counterpart + // ordering the distances descending + for (i = 0; i < c.Length; i++) + { + if (i >= points.Count) + break; + + f += c[i]*distances[i]; + } + + map[x, y] = f; + } + } + + // Normalise the result + Normalise(); + } + + public void VoroflatDiagram(int pointsPerBlock, int blockSize) + { + SetDiff(); + + List points = new List(); + Random generator = new Random(seed); + + // Generate the emitter points + int x, y, i; + for (x = -blockSize; x < w + blockSize; x += blockSize) + { + for (y = -blockSize; y < h + blockSize; y += blockSize) + { + for (i = 0; i < pointsPerBlock; i++) + { + double pX = x + (generator.NextDouble()*(double) blockSize); + double pY = y + (generator.NextDouble()*(double) blockSize); + + points.Add(new Point2D(pX, pY)); + } + } + } + + double[] distances = new double[points.Count]; + + // Calculate the distance each pixel is from an emitter + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + for (i = 0; i < points.Count; i++) + { + double dx, dy; + dx = Math.Abs((double) x - points[i].x); + dy = Math.Abs((double) y - points[i].y); + + distances[i] = (dx*dx + dy*dy); + } + + //Array.Sort(distances); + + double f = 0.0; + + double min = double.MaxValue; + for (int j = 0; j < distances.Length; j++) + { + if (distances[j] < min) + { + min = distances[j]; + f = j; + } + } + + // Multiply the distances with their 'c' counterpart + // ordering the distances descending + + map[x, y] = f; + } + } + + // Normalise the result + Normalise(); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Worms.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Worms.cs new file mode 100644 index 0000000000..8f9f14b2c4 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Generators/Worms.cs @@ -0,0 +1,72 @@ +/* +* 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; + +namespace libTerrain +{ + partial class Channel + { + /// + /// Generates 'number' of worms which navigate randomly around the landscape creating terrain as they go. + /// + /// The number of worms which will traverse the map + /// The number of steps each worm will traverse + /// The maximum distance each worm will move each step + /// The size of the area around the worm modified + /// Do worms start in the middle, or randomly? + public void Worms(int number, int rounds, double movement, double size, bool centerspawn) + { + SetDiff(); + + Random random = new Random(seed); + int i, j; + + for (i = 0; i < number; i++) + { + double rx, ry; + if (centerspawn) + { + rx = w/2.0; + ry = h/2.0; + } + else + { + rx = random.NextDouble()*(w - 1); + ry = random.NextDouble()*(h - 1); + } + for (j = 0; j < rounds; j++) + { + rx += (random.NextDouble()*movement) - (movement/2.0); + ry += (random.NextDouble()*movement) - (movement/2.0); + Raise(rx, ry, size, 1.0); + } + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Grid.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Grid.cs new file mode 100644 index 0000000000..1a86572fd2 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Grid.cs @@ -0,0 +1,377 @@ +/* +* 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; + +namespace libTerrain +{ + partial class Channel + { + public Channel Normalise() + { + SetDiff(); + + double max = FindMax(); + double min = FindMin(); + + int x, y; + + if (max != min) + { + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + map[x, y] = (map[x, y] - min)*(1.0/(max - min)); + } + } + } + else + { + Fill(0.5); + } + + return this; + } + + public Channel Normalise(double minv, double maxv) + { + SetDiff(); + + if (minv == maxv) + { + Fill(minv); + return this; + } + + double max = FindMax(); + double min = FindMin(); + + int x, y; + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + if (min != max) + { + double val = (map[x, y] - min)*(1.0/(max - min)); + val *= maxv - minv; + val += minv; + + map[x, y] = val; + } + else + { + map[x, y] = 0.5; + } + } + } + + return this; + } + + public Channel Elevate(double meters) + { + SetDiff(); + + int x, y; + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + map[x, y] += meters; + } + } + + return this; + } + + + public Channel Clip() + { + int x, y; + + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + SetClip(x, y, map[x, y]); + } + } + + return this; + } + + public Channel Clip(double min, double max) + { + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + double val = map[x, y]; + if (val > max) val = max; + if (val < min) val = min; + + Set(x, y, val); + } + } + return this; + } + + public Channel Crop(int x1, int y1, int x2, int y2) + { + int width = x1 - x2 + 1; + int height = y1 - y2 + 1; + Channel chan = new Channel(width, height); + + int x, y; + int nx, ny; + + nx = 0; + for (x = x1; x < x2; x++) + { + ny = 0; + for (y = y1; y < y2; y++) + { + chan.map[nx, ny] = map[x, y]; + + ny++; + } + nx++; + } + + return this; + } + + public Channel AddClip(Channel other) + { + SetDiff(); + + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + map[x, y] = other.map[x, y]; + if (map[x, y] > 1) + map[x, y] = 1; + if (map[x, y] < 0) + map[x, y] = 0; + } + } + return this; + } + + public void Smooth(double amount) + { + SetDiff(); + + double area = amount; + double step = amount/4.0; + + double[,] manipulate = new double[w,h]; + int x, y; + double n, l; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + double average = 0.0; + int avgsteps = 0; + + for (n = 0.0 - area; n < area; n += step) + { + for (l = 0.0 - area; l < area; l += step) + { + avgsteps++; + average += GetBilinearInterpolate(x + n, y + l); + } + } + + manipulate[x, y] = average/avgsteps; + } + } + map = manipulate; + } + + public void Pertubation(double amount) + { + SetDiff(); + + // Simple pertubation filter + double[,] manipulated = new double[w,h]; + Random generator = new Random(seed); // Seeds FTW! + //double amount = 8.0; + + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + double offset_x = (double) x + (generator.NextDouble()*amount) - (amount/2.0); + double offset_y = (double) y + (generator.NextDouble()*amount) - (amount/2.0); + double p = GetBilinearInterpolate(offset_x, offset_y); + manipulated[x, y] = p; + } + } + map = manipulated; + } + + public void PertubationMask(Channel mask) + { + // Simple pertubation filter + double[,] manipulated = new double[w,h]; + Random generator = new Random(seed); // Seeds FTW! + //double amount = 8.0; + + double amount; + + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + amount = mask.map[x, y]; + double offset_x = (double) x + (generator.NextDouble()*amount) - (amount/2.0); + double offset_y = (double) y + (generator.NextDouble()*amount) - (amount/2.0); + + if (offset_x > w) + offset_x = w - 1; + if (offset_y > h) + offset_y = h - 1; + if (offset_y < 0) + offset_y = 0; + if (offset_x < 0) + offset_x = 0; + + double p = GetBilinearInterpolate(offset_x, offset_y); + manipulated[x, y] = p; + SetDiff(x, y); + } + } + map = manipulated; + } + + public void Distort(Channel mask, double str) + { + // Simple pertubation filter + double[,] manipulated = new double[w,h]; + + double amount; + + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + amount = mask.map[x, y]; + double offset_x = (double) x + (amount*str) - (0.5*str); + double offset_y = (double) y + (amount*str) - (0.5*str); + + if (offset_x > w) + offset_x = w - 1; + if (offset_y > h) + offset_y = h - 1; + if (offset_y < 0) + offset_y = 0; + if (offset_x < 0) + offset_x = 0; + + double p = GetBilinearInterpolate(offset_x, offset_y); + manipulated[x, y] = p; + SetDiff(x, y); + } + } + map = manipulated; + } + + public void Distort(Channel mask, Channel mask2, double str) + { + // Simple pertubation filter + double[,] manipulated = new double[w,h]; + + double amountX; + double amountY; + + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + amountX = mask.map[x, y]; + amountY = mask2.map[x, y]; + double offset_x = (double) x + (amountX*str) - (0.5*str); + double offset_y = (double) y + (amountY*str) - (0.5*str); + + if (offset_x > w) + offset_x = w - 1; + if (offset_y > h) + offset_y = h - 1; + if (offset_y < 0) + offset_y = 0; + if (offset_x < 0) + offset_x = 0; + + double p = GetBilinearInterpolate(offset_x, offset_y); + manipulated[x, y] = p; + SetDiff(x, y); + } + } + map = manipulated; + } + + public Channel Blend(Channel other, double amount) + { + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + Set(x, y, Tools.LinearInterpolate(map[x, y], other.map[x, y], amount)); + } + } + return this; + } + + public Channel Blend(Channel other, Channel amount) + { + int x, y; + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + Set(x, y, Tools.LinearInterpolate(map[x, y], other.map[x, y], amount.map[x, y])); + } + } + return this; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/AerobicErosion.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/AerobicErosion.cs new file mode 100644 index 0000000000..8e8d30ffb6 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/AerobicErosion.cs @@ -0,0 +1,212 @@ +/* +* 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; + +namespace libTerrain +{ + partial class Channel + { + // Ideas for Aerobic erosion + // + // Unlike thermal (gravity) and hydraulic (water suspension) + // aerobic erosion should displace mass by moving sediment + // in "hops". The length of the hop being dictated by the + // presence of sharp cliffs and wind speed. + + // The ability to pickup sediment is defined by the total + // surface area, such that: + // 0 0 0 + // 0 1 0 + // 0 0 0 + // Would be the best possible value for sediment to be + // picked up (total difference = 8) and flatter land + // will erode less quickly. + + // Suspended particles assist the erosion process by hitting + // the surface and chiselling additional particles off faster + // than alone. + + // Particles are deposited when one of two conditions is met + // First: + // When particles hit a wall - such that the + // wind direction points at a difference >= the + // deposition mininum talus. + // Second: + // When wind speed is lowered to below the minimum + // required for transit. An idea for this is to + // use the navier-stokes algorithms for simulating + // pressure across the terrain. + + /// + /// An experimental erosion algorithm developed by Adam. Moves sediment by factoring the surface area of each height point. + /// + /// 0..1 The speed of the wind + /// The minimum angle at which rock is eroded 0..1 (recommended: <= 0.30) + /// The minimum angle at which rock is dropped 0..1 (recommended: >= 0.00) + /// The percentage of rock which can be picked up to pickup 0..1 + /// The number of erosion rounds (recommended: 25+) + /// Drop sediment at the lowest point? + public void AerobicErosion(double windspeed, double pickupTalusMinimum, double dropTalusMinimum, double carry, + int rounds, bool lowest, bool usingFluidDynamics) + { + bool debugImages = false; + + Channel wind = new Channel(w, h); + Channel sediment = new Channel(w, h); + int x, y, i, j; + + Normalise(); + + wind = Copy(); + wind.Noise(); + + if (debugImages) + wind.SaveImage("testimg/wind_start.png"); + + if (usingFluidDynamics) + { + wind.navierStokes(20, 0.1, 0.0, 0.0); + } + else + { + wind.Pertubation(30); + } + + if (debugImages) + wind.SaveImage("testimg/wind_begin.png"); + + for (i = 0; i < rounds; i++) + { + // Convert some rocks to sand + for (x = 1; x < w - 1; x++) + { + for (y = 1; y < h - 1; y++) + { + double me = Get(x, y); + double surfacearea = 0.3; // Everything will erode even if it's flat. Just slower. + + for (j = 0; j < 9; j++) + { + int[] coords = Neighbours(NeighbourSystem.Moore, j); + double target = Get(x + coords[0], y + coords[1]); + + surfacearea += Math.Abs(target - me); + } + + double amount = surfacearea*wind.map[x, y]*carry; + + if (amount < 0) + amount = 0; + + if (surfacearea > pickupTalusMinimum) + { + Set(x, y, map[x, y] - amount); + sediment.map[x, y] += amount; + } + } + } + + if (usingFluidDynamics) + { + sediment.navierStokes(7, 0.1, 0.0, 0.1); + + Channel noiseChan = new Channel(w, h); + noiseChan.Noise(); + wind.Blend(noiseChan, 0.01); + + wind.navierStokes(10, 0.1, 0.01, 0.01); + + sediment.Distort(wind, windspeed); + } + else + { + wind.Pertubation(15); // Can do better later + wind.seed++; + sediment.Pertubation(10); // Sediment is blown around a bit + sediment.seed++; + } + + if (debugImages) + wind.SaveImage("testimg/wind_" + i.ToString() + ".png"); + + // Convert some sand to rock + for (x = 1; x < w - 1; x++) + { + for (y = 1; y < h - 1; y++) + { + double me = Get(x, y); + double surfacearea = 0.01; // Flat land does not get deposition + double min = double.MaxValue; + int[] minside = new int[2]; + + for (j = 0; j < 9; j++) + { + int[] coords = Neighbours(NeighbourSystem.Moore, j); + double target = Get(x + coords[0], y + coords[1]); + + surfacearea += Math.Abs(target - me); + + if (target < min && lowest) + { + minside = (int[]) coords.Clone(); + min = target; + } + } + + double amount = surfacearea*(1.0 - wind.map[x, y])*carry; + + if (amount < 0) + amount = 0; + + if (surfacearea > dropTalusMinimum) + { + Set(x + minside[0], y + minside[1], map[x + minside[0], y + minside[1]] + amount); + sediment.map[x, y] -= amount; + } + } + } + + if (debugImages) + sediment.SaveImage("testimg/sediment_" + i.ToString() + ".png"); + + wind.Normalise(); + wind *= windspeed; + + Normalise(); + } + + Channel myself = this; + myself += sediment; + myself.Normalise(); + + if (debugImages) + SaveImage("testimg/output.png"); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/HydraulicErosion.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/HydraulicErosion.cs new file mode 100644 index 0000000000..abb620a159 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/HydraulicErosion.cs @@ -0,0 +1,145 @@ +/* +* 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; + +namespace libTerrain +{ + partial class Channel + { + public void HydraulicErosion(Channel rain, double evaporation, double solubility, int frequency, int rounds) + { + SetDiff(); + + Channel water = new Channel(w, h); + Channel sediment = new Channel(w, h); + Channel terrain = this; + Channel waterFlow = new Channel(w, h); + + NeighbourSystem type = NeighbourSystem.Moore; + int NEIGHBOUR_ME = 4; + + int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5; + + for (int i = 0; i < rounds; i++) + { + water += rain; + + sediment = terrain*water; + terrain -= sediment; + + for (int x = 1; x < w - 1; x++) + { + for (int y = 1; y < h - 1; y++) + { + double[] heights = new double[NEIGHBOUR_MAX]; + double[] diffs = new double[NEIGHBOUR_MAX]; + + double heightCenter = map[x, y]; + + for (int j = 0; j < NEIGHBOUR_MAX; j++) + { + if (j != NEIGHBOUR_ME) + { + int[] coords = Neighbours(type, j); + coords[0] += x; + coords[1] += y; + + heights[j] = map[coords[0], coords[1]] + water.map[coords[0], coords[1]] + + sediment.map[coords[0], coords[1]]; + diffs[j] = heightCenter - heights[j]; + } + } + + double totalHeight = 0; + double totalHeightDiff = 0; + int totalCellsCounted = 1; + + for (int j = 0; j < NEIGHBOUR_MAX; j++) + { + if (j != NEIGHBOUR_ME) + { + if (diffs[j] > 0) + { + totalHeight += heights[j]; + totalHeightDiff += diffs[j]; + totalCellsCounted++; + } + } + } + + if (totalCellsCounted == 1) + continue; + + double averageHeight = totalHeight/totalCellsCounted; + double waterAmount = Math.Min(water.map[x, y], heightCenter - averageHeight); + + // TODO: Check this. + waterFlow.map[x, y] += waterFlow.map[x, y] - waterAmount; + + double totalInverseDiff = waterAmount/totalHeightDiff; + + for (int j = 0; j < NEIGHBOUR_MAX; j++) + { + if (j != NEIGHBOUR_ME) + { + int[] coords = Neighbours(type, j); + coords[0] += x; + coords[1] += y; + + if (diffs[j] > 0) + { + waterFlow.SetWrap(coords[0], coords[1], + waterFlow.map[coords[0], coords[1]] + diffs[j]*totalInverseDiff); + } + } + } + } + } + + water += waterFlow; + waterFlow.Fill(0); + + water *= evaporation; + + for (int x = 0; x < w; x++) + { + for (int y = 0; y < h; y++) + { + double deposition = sediment.map[x, y] - water.map[x, y]*solubility; + if (deposition > 0) + { + sediment.map[x, y] -= deposition; + terrain.map[x, y] += deposition; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/NavierStokes.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/NavierStokes.cs new file mode 100644 index 0000000000..896c354a42 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/NavierStokes.cs @@ -0,0 +1,307 @@ +/* +* 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. +* +*/ + +namespace libTerrain +{ + partial class Channel + { + // Navier Stokes Algorithms ported from + // "Real-Time Fluid Dynamics for Games" by Jos Stam. + // presented at GDC 2003. + + // Poorly ported from C++. (I gave up making it properly native somewhere after nsSetBnd) + + private static int nsIX(int i, int j, int N) + { + return ((i) + (N + 2)*(j)); + } + + private static void nsSwap(ref double x0, ref double x) + { + double tmp = x0; + x0 = x; + x = tmp; + } + + private static void nsSwap(ref double[] x0, ref double[] x) + { + double[] tmp = x0; + x0 = x; + x = tmp; + } + + private void nsAddSource(int N, ref double[] x, ref double[] s, double dt) + { + int i; + int size = (N + 2)*(N + 2); + for (i = 0; i < size; i++) + { + x[i] += dt*s[i]; + } + } + + private void nsSetBnd(int N, int b, ref double[] x) + { + int i; + for (i = 0; i <= N; i++) + { + x[nsIX(0, i, N)] = b == 1 ? -x[nsIX(1, i, N)] : x[nsIX(1, i, N)]; + x[nsIX(0, N + 1, N)] = b == 1 ? -x[nsIX(N, i, N)] : x[nsIX(N, i, N)]; + x[nsIX(i, 0, N)] = b == 2 ? -x[nsIX(i, 1, N)] : x[nsIX(i, 1, N)]; + x[nsIX(i, N + 1, N)] = b == 2 ? -x[nsIX(i, N, N)] : x[nsIX(i, N, N)]; + } + x[nsIX(0, 0, N)] = 0.5f*(x[nsIX(1, 0, N)] + x[nsIX(0, 1, N)]); + x[nsIX(0, N + 1, N)] = 0.5f*(x[nsIX(1, N + 1, N)] + x[nsIX(0, N, N)]); + x[nsIX(N + 1, 0, N)] = 0.5f*(x[nsIX(N, 0, N)] + x[nsIX(N + 1, 1, N)]); + x[nsIX(N + 1, N + 1, N)] = 0.5f*(x[nsIX(N, N + 1, N)] + x[nsIX(N + 1, N, N)]); + } + + private void nsLinSolve(int N, int b, ref double[] x, ref double[] x0, double a, double c) + { + int i, j; + for (i = 1; i <= N; i++) + { + for (j = 1; j <= N; j++) + { + x[nsIX(i, j, N)] = (x0[nsIX(i, j, N)] + a* + (x[nsIX(i - 1, j, N)] + + x[nsIX(i + 1, j, N)] + + x[nsIX(i, j - 1, N)] + x[nsIX(i, j + 1, N)]) + )/c; + } + } + + nsSetBnd(N, b, ref x); + } + + private void nsDiffuse(int N, int b, ref double[] x, ref double[] x0, double diff, double dt) + { + double a = dt*diff*N*N; + nsLinSolve(N, b, ref x, ref x0, a, 1 + 4*a); + } + + private void nsAdvect(int N, int b, ref double[] d, ref double[] d0, ref double[] u, ref double[] v, double dt) + { + int i, j, i0, j0, i1, j1; + double x, y, s0, t0, s1, t1, dt0; + + dt0 = dt*N; + + for (i = 1; i <= N; i++) + { + for (j = 1; j <= N; j++) + { + x = i - dt0*u[nsIX(i, j, N)]; + y = j - dt0*v[nsIX(i, j, N)]; + + if (x < 0.5) + x = 0.5; + if (x > N + 0.5) + x = N + 0.5; + i0 = (int) x; + i1 = i0 + 1; + + if (y < 0.5) + y = 0.5; + if (y > N + 0.5) + y = N + 0.5; + j0 = (int) y; + j1 = j0 + 1; + + s1 = x - i0; + s0 = 1 - s1; + t1 = y - j0; + t0 = 1 - t1; + + d[nsIX(i, j, N)] = s0*(t0*d0[nsIX(i0, j0, N)] + t1*d0[nsIX(i0, j1, N)]) + + s1*(t0*d0[nsIX(i1, j0, N)] + t1*d0[nsIX(i1, j1, N)]); + } + } + + nsSetBnd(N, b, ref d); + } + + public void nsProject(int N, ref double[] u, ref double[] v, ref double[] p, ref double[] div) + { + int i, j; + + for (i = 1; i <= N; i++) + { + for (j = 1; j <= N; j++) + { + div[nsIX(i, j, N)] = -0.5* + (u[nsIX(i + 1, j, N)] - u[nsIX(i - 1, j, N)] + v[nsIX(i, j + 1, N)] - + v[nsIX(i, j - 1, N)])/N; + p[nsIX(i, j, N)] = 0; + } + } + + nsSetBnd(N, 0, ref div); + nsSetBnd(N, 0, ref p); + + nsLinSolve(N, 0, ref p, ref div, 1, 4); + + for (i = 1; i <= N; i++) + { + for (j = 1; j <= N; j++) + { + u[nsIX(i, j, N)] -= 0.5*N*(p[nsIX(i + 1, j, N)] - p[nsIX(i - 1, j, N)]); + v[nsIX(i, j, N)] -= 0.5*N*(p[nsIX(i, j + 1, N)] - p[nsIX(i, j - 1, N)]); + } + } + + nsSetBnd(N, 1, ref u); + nsSetBnd(N, 2, ref v); + } + + private void nsDensStep(int N, ref double[] x, ref double[] x0, ref double[] u, ref double[] v, double diff, + double dt) + { + nsAddSource(N, ref x, ref x0, dt); + nsSwap(ref x0, ref x); + nsDiffuse(N, 0, ref x, ref x0, diff, dt); + nsSwap(ref x0, ref x); + nsAdvect(N, 0, ref x, ref x0, ref u, ref v, dt); + } + + private void nsVelStep(int N, ref double[] u, ref double[] v, ref double[] u0, ref double[] v0, double visc, + double dt) + { + nsAddSource(N, ref u, ref u0, dt); + nsAddSource(N, ref v, ref v0, dt); + nsSwap(ref u0, ref u); + nsDiffuse(N, 1, ref u, ref u0, visc, dt); + nsSwap(ref v0, ref v); + nsDiffuse(N, 2, ref v, ref v0, visc, dt); + nsProject(N, ref u, ref v, ref u0, ref v0); + nsSwap(ref u0, ref u); + nsSwap(ref v0, ref v); + nsAdvect(N, 1, ref u, ref u0, ref u0, ref v0, dt); + nsAdvect(N, 2, ref v, ref v0, ref u0, ref v0, dt); + nsProject(N, ref u, ref v, ref u0, ref v0); + } + + private void nsBufferToDoubles(ref double[] dens, int N, ref double[,] doubles) + { + int i; + int j; + + for (i = 1; i <= N; i++) + { + for (j = 1; j <= N; j++) + { + doubles[i - 1, j - 1] = dens[nsIX(i, j, N)]; + } + } + } + + private void nsDoublesToBuffer(double[,] doubles, int N, ref double[] dens) + { + int i; + int j; + + for (i = 1; i <= N; i++) + { + for (j = 1; j <= N; j++) + { + dens[nsIX(i, j, N)] = doubles[i - 1, j - 1]; + } + } + } + + private void nsSimulate(int N, int rounds, double dt, double diff, double visc) + { + int size = (N*2)*(N*2); + + double[] u = new double[size]; // Force, X axis + double[] v = new double[size]; // Force, Y axis + double[] u_prev = new double[size]; + double[] v_prev = new double[size]; + double[] dens = new double[size]; + double[] dens_prev = new double[size]; + + nsDoublesToBuffer(map, N, ref dens); + nsDoublesToBuffer(map, N, ref dens_prev); + + for (int i = 0; i < rounds; i++) + { + u_prev = u; + v_prev = v; + dens_prev = dens; + + nsVelStep(N, ref u, ref v, ref u_prev, ref v_prev, visc, dt); + nsDensStep(N, ref dens, ref dens_prev, ref u, ref v, diff, dt); + } + + nsBufferToDoubles(ref dens, N, ref map); + } + + /// + /// Performs computational fluid dynamics on a channel + /// + /// The number of steps to perform (Recommended: 20) + /// Delta Time - The time between steps (Recommended: 0.1) + /// Fluid diffusion rate (Recommended: 0.0) + /// Fluid viscosity (Recommended: 0.0) + public void navierStokes(int rounds, double dt, double diff, double visc) + { + nsSimulate(h, rounds, dt, diff, visc); + } + + public void navierStokes(int rounds, double dt, double diff, double visc, ref double[,] uret, ref double[,] vret) + { + int N = h; + + int size = (N*2)*(N*2); + + double[] u = new double[size]; // Force, X axis + double[] v = new double[size]; // Force, Y axis + double[] u_prev = new double[size]; + double[] v_prev = new double[size]; + double[] dens = new double[size]; + double[] dens_prev = new double[size]; + + nsDoublesToBuffer(map, N, ref dens); + nsDoublesToBuffer(map, N, ref dens_prev); + + for (int i = 0; i < rounds; i++) + { + u_prev = u; + v_prev = v; + dens_prev = dens; + + nsVelStep(N, ref u, ref v, ref u_prev, ref v_prev, visc, dt); + nsDensStep(N, ref dens, ref dens_prev, ref u, ref v, diff, dt); + } + + nsBufferToDoubles(ref u, N, ref uret); + nsBufferToDoubles(ref v, N, ref vret); + nsBufferToDoubles(ref dens, N, ref map); + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/ThermalWeathering.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/ThermalWeathering.cs new file mode 100644 index 0000000000..5be239f608 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Manipulators/ThermalWeathering.cs @@ -0,0 +1,108 @@ +/* +* 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. +* +*/ + +namespace libTerrain +{ + partial class Channel + { + /// + /// A thermal weathering implementation based on Musgrave's original 1989 algorithm. This is Adam's custom implementation which may differ slightly from the original. + /// + /// The rock angle (represented as a dy/dx ratio) at which point it will be succeptible to breakage + /// The number of erosion rounds + /// The amount of rock to carry each round + public Channel ThermalWeathering(double talus, int rounds, double c) + { + SetDiff(); + + double[,] lastFrame; + double[,] thisFrame; + + lastFrame = (double[,]) map.Clone(); + thisFrame = (double[,]) map.Clone(); + + NeighbourSystem type = NeighbourSystem.Moore; + // Using moore neighbourhood (twice as computationally expensive) + int NEIGHBOUR_ME = 4; // I am always 4 in both systems. + + int NEIGHBOUR_MAX = type == NeighbourSystem.Moore ? 9 : 5; + + int frames = rounds; // Number of thermal erosion iterations to run + int i, j; + int x, y; + + for (i = 0; i < frames; i++) + { + for (x = 0; x < w; x++) + { + for (y = 0; y < h; y++) + { + for (j = 0; j < NEIGHBOUR_MAX; j++) + { + if (j != NEIGHBOUR_ME) + { + int[] coords = Neighbours(type, j); + + coords[0] += x; + coords[1] += y; + + if (coords[0] > w - 1) + coords[0] = w - 1; + if (coords[1] > h - 1) + coords[1] = h - 1; + if (coords[0] < 0) + coords[0] = 0; + if (coords[1] < 0) + coords[1] = 0; + + double heightF = thisFrame[x, y]; + double target = thisFrame[coords[0], coords[1]]; + + if (target > heightF + talus) + { + double calc = c*((target - heightF) - talus); + heightF += calc; + target -= calc; + } + + thisFrame[x, y] = heightF; + thisFrame[coords[0], coords[1]] = target; + } + } + } + } + lastFrame = (double[,]) thisFrame.Clone(); + } + + map = thisFrame; + + Normalise(); // Just to guaruntee a smooth 0..1 value + return this; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Neighbours.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Neighbours.cs new file mode 100644 index 0000000000..a946b098f9 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Neighbours.cs @@ -0,0 +1,137 @@ +/* +* 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. +* +*/ + +namespace libTerrain +{ + partial class Channel + { + private enum NeighbourSystem + { + Moore, + VonNeumann + } ; + + private int[] Neighbours(NeighbourSystem type, int index) + { + int[] coord = new int[2]; + + index++; + + switch (type) + { + case NeighbourSystem.Moore: + switch (index) + { + case 1: + coord[0] = -1; + coord[1] = -1; + break; + + case 2: + coord[0] = -0; + coord[1] = -1; + break; + + case 3: + coord[0] = +1; + coord[1] = -1; + break; + + case 4: + coord[0] = -1; + coord[1] = -0; + break; + + case 5: + coord[0] = -0; + coord[1] = -0; + break; + + case 6: + coord[0] = +1; + coord[1] = -0; + break; + + case 7: + coord[0] = -1; + coord[1] = +1; + break; + + case 8: + coord[0] = -0; + coord[1] = +1; + break; + + case 9: + coord[0] = +1; + coord[1] = +1; + break; + + default: + break; + } + break; + + case NeighbourSystem.VonNeumann: + switch (index) + { + case 1: + coord[0] = 0; + coord[1] = -1; + break; + + case 2: + coord[0] = -1; + coord[1] = 0; + break; + + case 3: + coord[0] = +1; + coord[1] = 0; + break; + + case 4: + coord[0] = 0; + coord[1] = +1; + break; + + case 5: + coord[0] = -0; + coord[1] = -0; + break; + + default: + break; + } + break; + } + + return coord; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Operators.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Operators.cs new file mode 100644 index 0000000000..6de16ff9ce --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Channel/Operators.cs @@ -0,0 +1,240 @@ +/* +* 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; + +namespace libTerrain +{ + partial class Channel + { + /* Operator combination of channel datatypes */ + + public static Channel operator +(Channel A, Channel B) + { + if (A.h != B.h) + throw new Exception("Cannot add heightmaps, of different height."); + if (A.w != B.w) + throw new Exception("Cannot add heightmaps, of different width."); + + int x, y; + + for (x = 0; x < A.w; x++) + { + for (y = 0; y < A.h; y++) + { + if (B.map[x, y] != 0) + A.SetDiff(x, y); + + A.map[x, y] += B.map[x, y]; + } + } + + return A; + } + + public static Channel operator *(Channel A, Channel B) + { + if (A.h != B.h) + throw new Exception("Cannot multiply heightmaps, of different height."); + if (A.w != B.w) + throw new Exception("Cannot multiply heightmaps, of different width."); + + int x, y; + + for (x = 0; x < A.w; x++) + { + for (y = 0; y < A.h; y++) + { + A.map[x, y] *= B.map[x, y]; + } + } + + A.SetDiff(); + + return A; + } + + public static Channel operator -(Channel A, Channel B) + { + if (A.h != B.h) + throw new Exception("Cannot subtract heightmaps, of different height."); + if (A.w != B.w) + throw new Exception("Cannot subtract heightmaps, of different width."); + + int x, y; + + for (x = 0; x < A.w; x++) + { + for (y = 0; y < A.h; y++) + { + if (B.map[x, y] != 0) + A.SetDiff(x, y); + A.map[x, y] -= B.map[x, y]; + } + } + + return A; + } + + public static Channel operator /(Channel A, Channel B) + { + if (A.h != B.h) + throw new Exception("Cannot divide heightmaps, of different height."); + if (A.w != B.w) + throw new Exception("Cannot divide heightmaps, of different width."); + + int x, y; + + for (x = 0; x < A.w; x++) + { + for (y = 0; y < A.h; y++) + { + A.map[x, y] /= B.map[x, y]; + } + } + + A.SetDiff(); + + return A; + } + + public static Channel operator ^(Channel A, Channel B) + { + if (A.h != B.h) + throw new Exception("Cannot divide heightmaps, of different height."); + if (A.w != B.w) + throw new Exception("Cannot divide heightmaps, of different width."); + + int x, y; + + for (x = 0; x < A.w; x++) + { + for (y = 0; y < A.h; y++) + { + A.map[x, y] = Math.Pow(A.map[x, y], B.map[x, y]); + } + } + + A.SetDiff(); + + return A; + } + + + /* Operator combination of channel and double datatypes */ + + public static Channel operator +(Channel A, double B) + { + int x, y; + + for (x = 0; x < A.w; x++) + { + for (y = 0; y < A.h; y++) + { + A.map[x, y] += B; + } + } + + if (B != 0) + A.SetDiff(); + + return A; + } + + public static Channel operator -(Channel A, double B) + { + int x, y; + + for (x = 0; x < A.w; x++) + { + for (y = 0; y < A.h; y++) + { + A.map[x, y] -= B; + } + } + + if (B != 0) + A.SetDiff(); + + return A; + } + + public static Channel operator *(Channel A, double B) + { + int x, y; + + for (x = 0; x < A.w; x++) + { + for (y = 0; y < A.h; y++) + { + A.map[x, y] *= B; + } + } + + if (B != 1) + A.SetDiff(); + + return A; + } + + public static Channel operator /(Channel A, double B) + { + int x, y; + + for (x = 0; x < A.w; x++) + { + for (y = 0; y < A.h; y++) + { + A.map[x, y] /= B; + } + } + + if (B != 1) + A.SetDiff(); + + return A; + } + + public static Channel operator ^(Channel A, double B) + { + int x, y; + + for (x = 0; x < A.w; x++) + { + for (y = 0; y < A.h; y++) + { + A.map[x, y] = Math.Pow(A.map[x, y], B); + } + } + + A.SetDiff(); + + return A; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Tools/Point2D.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Tools/Point2D.cs new file mode 100644 index 0000000000..1d52da91bd --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Tools/Point2D.cs @@ -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. +* +*/ + +namespace libTerrain +{ + public class Point2D + { + public double x; + public double y; + + public Point2D(double X, double Y) + { + x = X; + y = Y; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Tools/Tools.cs b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Tools/Tools.cs new file mode 100644 index 0000000000..d805794d53 --- /dev/null +++ b/trunk/OpenSim/Region/Terrain.BasicTerrain/libTerrainBSD/Tools/Tools.cs @@ -0,0 +1,60 @@ +/* +* 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; + +namespace libTerrain +{ + internal class Tools + { + public static double LinearInterpolate(double a, double b, double amount) + { + return a + ((b - a)*amount); + } + + public static double ExponentialInterpolate(double a, double b, double amount) + { + a = Math.Pow(a, amount); + b = Math.Pow(b - a, 1.0 - amount); + return a + b; + } + + public static int PowerOf2Log2(int n) + { + for (int i = 0; i < 31; i++) + { + if ((n & 1) == 1) + { + return i; + } + n >>= 1; + } + return 0; + } + } +} \ No newline at end of file diff --git a/trunk/OpenSim/Tests/Common/ANumericalToleranceConstraint.cs b/trunk/OpenSim/Tests/Common/ANumericalToleranceConstraint.cs new file mode 100644 index 0000000000..893862f330 --- /dev/null +++ b/trunk/OpenSim/Tests/Common/ANumericalToleranceConstraint.cs @@ -0,0 +1,57 @@ +/* +* 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; +using NUnit.Framework.Constraints; + +namespace OpenSim.Tests.Common +{ + public abstract class ANumericalToleranceConstraint : Constraint + { + protected double _tolerance; + + public ANumericalToleranceConstraint(double tolerance) + { + if (tolerance < 0) + { + throw new ArgumentException("Tolerance cannot be negative."); + } + _tolerance = tolerance; + } + + protected bool IsWithinDoubleConstraint(double doubleValue, double baseValue) + { + if (doubleValue >= baseValue - _tolerance && doubleValue <= baseValue + _tolerance) + { + return true; + } + + return false; + } + } +} diff --git a/trunk/OpenSim/Tests/Common/DoubleToleranceConstraint.cs b/trunk/OpenSim/Tests/Common/DoubleToleranceConstraint.cs new file mode 100644 index 0000000000..29b808df6d --- /dev/null +++ b/trunk/OpenSim/Tests/Common/DoubleToleranceConstraint.cs @@ -0,0 +1,80 @@ +/* +* 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; +using NUnit.Framework; +using NUnit.Framework.Constraints; +using OpenSim.Tests.Common; + +namespace OpenSim.Tests.Common +{ + public class DoubleToleranceConstraint : ANumericalToleranceConstraint + { + + private double _baseValue; + private double _valueToBeTested; + + public DoubleToleranceConstraint(double baseValue, double tolerance) : base(tolerance) + { + _baseValue = baseValue; + } + + /// + ///Test whether the constraint is satisfied by a given value + /// + ///The value to be tested + /// + ///True for success, false for failure + /// + public override bool Matches(object valueToBeTested) + { + if (valueToBeTested == null) + { + throw new ArgumentException("Constraint cannot be used upon null values."); + } + if( valueToBeTested.GetType() != typeof(double)) + { + throw new ArgumentException("Constraint cannot be used upon non double-values."); + } + + _valueToBeTested = (double)valueToBeTested; + + return IsWithinDoubleConstraint(_valueToBeTested, _baseValue ); + } + + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WriteExpectedValue(string.Format("A value {0} within tolerance of plus or minus {1}",_baseValue,_tolerance)); + } + + public override void WriteActualValueTo(MessageWriter writer) + { + writer.WriteActualValue(_valueToBeTested); + } + } +} diff --git a/trunk/OpenSim/Tests/Common/TestHelper.cs b/trunk/OpenSim/Tests/Common/TestHelper.cs new file mode 100644 index 0000000000..1ec9e65ec7 --- /dev/null +++ b/trunk/OpenSim/Tests/Common/TestHelper.cs @@ -0,0 +1,53 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Tests.Common +{ + public delegate void TestDelegate(); + + public class TestHelper + { + public static bool AssertThisDelegateCausesArgumentException(TestDelegate d) + { + try + { + d(); + } + catch(ArgumentException e) + { + return true; + } + + return false; + } + } +} diff --git a/trunk/OpenSim/Tests/Common/VectorToleranceConstraint.cs b/trunk/OpenSim/Tests/Common/VectorToleranceConstraint.cs new file mode 100644 index 0000000000..39f1b1a59d --- /dev/null +++ b/trunk/OpenSim/Tests/Common/VectorToleranceConstraint.cs @@ -0,0 +1,86 @@ +/* +* 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; +using libsecondlife; +using NUnit.Framework; + +namespace OpenSim.Tests.Common +{ + public class VectorToleranceConstraint : ANumericalToleranceConstraint + { + private LLVector3 _baseValue; + private LLVector3 _valueToBeTested; + + public VectorToleranceConstraint(LLVector3 baseValue, double tolerance) : base(tolerance) + { + _baseValue = baseValue; + } + + /// + ///Test whether the constraint is satisfied by a given value + /// + ///The value to be tested + /// + ///True for success, false for failure + /// + public override bool Matches(object valueToBeTested) + { + if (valueToBeTested == null) + { + throw new ArgumentException("Constraint cannot be used upon null values."); + } + if (valueToBeTested.GetType() != typeof (LLVector3)) + { + throw new ArgumentException("Constraint cannot be used upon non vector values."); + } + + _valueToBeTested = (LLVector3) valueToBeTested; + + if ( IsWithinDoubleConstraint(_valueToBeTested.X,_baseValue.X) && + IsWithinDoubleConstraint(_valueToBeTested.Y,_baseValue.Y) && + IsWithinDoubleConstraint(_valueToBeTested.Z,_baseValue.Z) ) + { + return true; + } + + return false; + } + + public override void WriteDescriptionTo(MessageWriter writer) + { + writer.WriteExpectedValue( + string.Format("A value {0} within tolerance of plus or minus {1}", _baseValue, _tolerance)); + } + + public override void WriteActualValueTo(MessageWriter writer) + { + writer.WriteActualValue(_valueToBeTested); + } + } +} diff --git a/trunk/OpenSim/Tests/Inventory/Properties/AssemblyInfo.cs b/trunk/OpenSim/Tests/Inventory/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..405c0990b0 --- /dev/null +++ b/trunk/OpenSim/Tests/Inventory/Properties/AssemblyInfo.cs @@ -0,0 +1,63 @@ +/* +* 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.CompilerServices; +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("Inventory")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Lauridsen")] +[assembly: AssemblyProduct("Inventory")] +[assembly: AssemblyCopyright("Copyright © Lauridsen 2007")] +[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("2330add7-08a2-4f33-9ab8-74894fe7e3dd")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/trunk/OpenSim/Tests/Inventory/TestInventory.cs b/trunk/OpenSim/Tests/Inventory/TestInventory.cs new file mode 100644 index 0000000000..e905dd8358 --- /dev/null +++ b/trunk/OpenSim/Tests/Inventory/TestInventory.cs @@ -0,0 +1,1008 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using NUnit.Framework; + +using libsecondlife; +using OpenSim.Framework.Types; +using OpenSim.Framework.Data; +using OpenSim.Framework.Data.SQLite; +using OpenSim.Framework.Data.MySQL; +using OpenSim.Framework.Console; + +namespace OpenSim.Test.Inventory +{ + [TestFixture] + public class TestInventory + { + IInventoryData _dbPlugin; + LLUUID _agent_1_id; + public static LLUUID LibraryFolderRootUuid = new LLUUID("5926de2a-c2d7-4c11-ac4e-74512ffeb6d1"); + + Random _rnd = new Random((int)DateTime.Now.Ticks); + + [TestFixtureSetUp] + public void SetupInventoryTest() + { + _agent_1_id = LLUUID.Random(); + + MainConsole.Instance = new ConsoleBase("TEST", null); + +// _dbPlugin = new SQLiteInventoryStore(); + _dbPlugin = new MySQLInventoryData(); + _dbPlugin.Initialise(); + } + + [TestFixtureTearDown] + public void TeardownInventoryTest() + { + _dbPlugin.Close(); + } + + private bool AreFoldersIdentical(InventoryFolderBase a, InventoryFolderBase b) + { + if (a.agentID != b.agentID) return false; + if (a.folderID != b.folderID) return false; + if (a.name != b.name) return false; + if (a.parentID != b.parentID) return false; + if (a.type != b.type) return false; + if (a.version != b.version) return false; + return true; + } + + private bool AreItemsIdentical(InventoryItemBase a, InventoryItemBase b) + { + if (a.assetID != b.assetID) return false; + if (a.assetType != b.assetType) return false; + if (a.avatarID != b.avatarID) return false; + if (a.creatorsID != b.creatorsID) return false; + if (a.inventoryBasePermissions != b.inventoryBasePermissions) return false; + if (a.inventoryCurrentPermissions != b.inventoryCurrentPermissions) return false; + if (a.inventoryEveryOnePermissions != b.inventoryEveryOnePermissions) return false; + if (a.inventoryNextPermissions != b.inventoryNextPermissions) return false; + if (a.inventoryID != b.inventoryID) return false; + if (a.inventoryDescription != b.inventoryDescription) return false; + if (a.inventoryName != b.inventoryName) return false; + if (a.invType != b.invType) return false; + if (a.parentFolderID != b.parentFolderID) return false; + return true; + } + + /// + /// Test that we can insert a root folder + /// + [Test] + public void T01_SetupRootFolder() + { + InventoryFolderBase root = new InventoryFolderBase(); + root.agentID = _agent_1_id; + root.folderID = _agent_1_id; + root.name = "Root folder"; + root.parentID = LLUUID.Zero; + root.type = 2; + root.version = 2; + _dbPlugin.addInventoryFolder(root); + + InventoryFolderBase f = _dbPlugin.getInventoryFolder(root.folderID); + Assert.IsNotNull(f, "Failed to get existing folder"); + Assert.IsTrue(AreFoldersIdentical(root, f), "Difference between stored and retrieved folder data"); + + // Test that we only get the root folder, based on it's id, i.e. any other gui will not find the folder + f = _dbPlugin.getInventoryFolder(LLUUID.Zero); + Assert.IsNull(f, "get folder returned a folder, but shouldn't find one"); + + f = _dbPlugin.getInventoryFolder(LLUUID.Random()); + Assert.IsNull(f, "get folder returned a folder, but shouldn't find one"); + + // test that we can delete the folder + + _dbPlugin.deleteInventoryFolder(_agent_1_id); + f = _dbPlugin.getInventoryFolder(root.folderID); + Assert.IsNull(f, "get folder returned a folder, but it should have been deleted"); + } + + /// + /// Make sure that all folders reported as root folders are root folders + /// + [Test] + public void T02_TestRootFolder() + { + InventoryFolderBase root = new InventoryFolderBase(); + root.agentID = _agent_1_id; + root.folderID = _agent_1_id; + root.name = "Root folder"; + root.parentID = LLUUID.Zero; + root.type = 2; + root.version = 2; + _dbPlugin.addInventoryFolder(root); + + List folders = _dbPlugin.getUserRootFolders(_agent_1_id); + Assert.IsNotNull(folders, "Failed to get rootfolders for user"); + + bool foundRoot = false; + foreach(InventoryFolderBase f in folders) { + + // a root folder has a zero valued LLUUID + Assert.AreEqual(f.parentID, LLUUID.Zero, "non root folder returned"); + + + if(f.agentID == root.agentID) + { + // we cannot have two different user specific root folders + Assert.IsFalse(foundRoot, "Two different user specific root folders returned"); + + Assert.IsTrue(AreFoldersIdentical(root, f), "Difference between stored and retrieved folder data"); + foundRoot = false; + } + } + _dbPlugin.deleteInventoryFolder(_agent_1_id); + } + + /// + /// Test of folder hierarchy + /// + [Test] + public void T03_TestRootFolder() + { + InventoryFolderBase root = new InventoryFolderBase(); + root.agentID = _agent_1_id; + root.folderID = _agent_1_id; + root.name = "Root folder"; + root.parentID = LLUUID.Zero; + root.type = 2; + root.version = 2; + _dbPlugin.addInventoryFolder(root); + + List folders = _dbPlugin.getInventoryFolders(_agent_1_id); + Assert.IsNotNull(folders, "null was returned, but an empty list of subfolders were expected"); + Assert.IsEmpty(folders, "non empty collection was returned, even though the list of sub-folders should be empty"); + + InventoryFolderBase child1 = new InventoryFolderBase(); + child1.agentID = _agent_1_id; + child1.folderID = LLUUID.Random(); + child1.name = "Child 1"; + child1.parentID = root.folderID; + child1.type = 3; + child1.version = 3; + _dbPlugin.addInventoryFolder(child1); + + InventoryFolderBase child2 = new InventoryFolderBase(); + child2.agentID = _agent_1_id; + child2.folderID = LLUUID.Random(); + child2.name = "Child 2"; + child2.parentID = root.folderID; + child2.type = 4; + child2.version = 4; + _dbPlugin.addInventoryFolder(child2); + + folders = _dbPlugin.getInventoryFolders(_agent_1_id); + Assert.IsNotNull(folders, "null was returned, but an empty list of subfolders were expected"); + Assert.AreEqual(folders.Count, 2, "two children were reported as inserted into the root folder"); + + bool foundChild1 = false; + bool foundChild2 = false; + + foreach (InventoryFolderBase f in folders) + { + if (f.folderID == child1.folderID) + { + Assert.IsTrue(AreFoldersIdentical(child1, f), "Difference between stored and retrieved folder data"); + foundChild1 = true; + } + else if (f.folderID == child2.folderID) + { + Assert.IsTrue(AreFoldersIdentical(child2, f), "Difference between stored and retrieved folder data"); + foundChild2 = true; + } + else + { + Assert.Fail("found unknown child folder"); + } + } + + if (foundChild1 == false || foundChild2 == false) + { + Assert.Fail("one of the two child folders was not returned"); + } + + _dbPlugin.deleteInventoryFolder(child2.folderID); + _dbPlugin.deleteInventoryFolder(child1.folderID); + _dbPlugin.deleteInventoryFolder(_agent_1_id); + } + + /// + /// Test of folder hierarchy, and deletion + /// + [Test] + public void T04_TestRootFolder() + { + InventoryFolderBase root = new InventoryFolderBase(); + root.agentID = _agent_1_id; + root.folderID = _agent_1_id; + root.name = "Root folder"; + root.parentID = LLUUID.Zero; + root.type = 2; + root.version = 2; + _dbPlugin.addInventoryFolder(root); + + InventoryFolderBase child1 = new InventoryFolderBase(); + child1.agentID = _agent_1_id; + child1.folderID = LLUUID.Random(); + child1.name = "Child 1"; + child1.parentID = root.folderID; + child1.type = 3; + child1.version = 3; + _dbPlugin.addInventoryFolder(child1); + + InventoryFolderBase child2 = new InventoryFolderBase(); + child2.agentID = _agent_1_id; + child2.folderID = LLUUID.Random(); + child2.name = "Child 2"; + child2.parentID = root.folderID; + child2.type = 4; + child2.version = 4; + _dbPlugin.addInventoryFolder(child2); + + _dbPlugin.deleteInventoryFolder(_agent_1_id); + + List folders = _dbPlugin.getInventoryFolders(_agent_1_id); + Assert.IsNotNull(folders, "null was returned, but an empty list of subfolders were expected"); + Assert.IsEmpty(folders, "non empty collection was returned, even though the list of sub-folders should be empty"); + + InventoryFolderBase f = _dbPlugin.getInventoryFolder(_agent_1_id); + Assert.IsNull(f, "Folder was returned, even though is has been deleted"); + + f = _dbPlugin.getInventoryFolder(child1.folderID); + Assert.IsNull(f, "Folder was returned, even though is has been deleted"); + + f = _dbPlugin.getInventoryFolder(child2.folderID); + Assert.IsNull(f, "Folder was returned, even though is has been deleted"); + } + + /// + /// Folder update + /// + [Test] + public void T05_UpdateFolder() + { + InventoryFolderBase root = new InventoryFolderBase(); + root.agentID = _agent_1_id; + root.folderID = _agent_1_id; + root.name = "Root folder"; + root.parentID = LLUUID.Zero; + root.type = 2; + root.version = 2; + _dbPlugin.addInventoryFolder(root); + + InventoryFolderBase f = _dbPlugin.getInventoryFolder(_agent_1_id); + Assert.IsTrue(AreFoldersIdentical(root, f), "Difference between stored and retrieved folder data"); + + root.agentID = LLUUID.Random(); + _dbPlugin.updateInventoryFolder(root); + f = _dbPlugin.getInventoryFolder(root.folderID); + Assert.IsTrue(AreFoldersIdentical(root, f), "Difference between stored and retrieved folder data"); + + root.folderID = LLUUID.Random(); + _dbPlugin.updateInventoryFolder(root); + f = _dbPlugin.getInventoryFolder(root.folderID); + Assert.IsTrue(AreFoldersIdentical(root, f), "Difference between stored and retrieved folder data"); + + root.name = "Root folder 2"; + _dbPlugin.updateInventoryFolder(root); + f = _dbPlugin.getInventoryFolder(root.folderID); + Assert.IsTrue(AreFoldersIdentical(root, f), "Difference between stored and retrieved folder data"); + + root.parentID = LLUUID.Random(); + _dbPlugin.updateInventoryFolder(root); + f = _dbPlugin.getInventoryFolder(root.folderID); + Assert.IsTrue(AreFoldersIdentical(root, f), "Difference between stored and retrieved folder data"); + + root.type = (short)(root.type + 1); + _dbPlugin.updateInventoryFolder(root); + f = _dbPlugin.getInventoryFolder(root.folderID); + Assert.IsTrue(AreFoldersIdentical(root, f), "Difference between stored and retrieved folder data"); + + root.version = (ushort)(root.version + 1); + _dbPlugin.updateInventoryFolder(root); + f = _dbPlugin.getInventoryFolder(root.folderID); + Assert.IsTrue(AreFoldersIdentical(root, f), "Difference between stored and retrieved folder data"); + + _dbPlugin.deleteInventoryFolder(_agent_1_id); + _dbPlugin.deleteInventoryFolder(root.folderID); + } + + /// + /// Test that we can insert a root folder + /// + [Test] + public void T06_SetupInventoryWithItems() + { + + // Setup inventory + InventoryFolderBase root = new InventoryFolderBase(); + root.agentID = _agent_1_id; + root.folderID = _agent_1_id; + root.name = "Root folder"; + root.parentID = LLUUID.Zero; + root.type = 2; + root.version = 2; + _dbPlugin.addInventoryFolder(root); + + InventoryFolderBase child1 = new InventoryFolderBase(); + child1.agentID = _agent_1_id; + child1.folderID = LLUUID.Random(); + child1.name = "Child 1"; + child1.parentID = root.folderID; + child1.type = 3; + child1.version = 3; + _dbPlugin.addInventoryFolder(child1); + + InventoryFolderBase child1Child = new InventoryFolderBase(); + child1Child.agentID = _agent_1_id; + child1Child.folderID = LLUUID.Random(); + child1Child.name = "Child 1 child"; + child1Child.parentID = child1.folderID; + child1Child.type = 4; + child1Child.version = 4; + _dbPlugin.addInventoryFolder(child1Child); + + InventoryFolderBase child2 = new InventoryFolderBase(); + child2.agentID = _agent_1_id; + child2.folderID = LLUUID.Random(); + child2.name = "Child 2"; + child2.parentID = root.folderID; + child2.type = 5; + child2.version = 5; + _dbPlugin.addInventoryFolder(child2); + + InventoryFolderBase child2Child = new InventoryFolderBase(); + child2Child.agentID = _agent_1_id; + child2Child.folderID = LLUUID.Random(); + child2Child.name = "Child 2 child"; + child2Child.parentID = child2.folderID; + child2Child.type = 6; + child2Child.version = 6; + _dbPlugin.addInventoryFolder(child2Child); + + InventoryItemBase rootItem = new InventoryItemBase(); + rootItem.assetID = LLUUID.Random(); + rootItem.assetType = _rnd.Next(1, 1000); + rootItem.avatarID = _agent_1_id; + rootItem.creatorsID = LLUUID.Random(); + rootItem.inventoryBasePermissions = (uint)_rnd.Next(1,1000000); + rootItem.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryID = LLUUID.Random(); + rootItem.inventoryDescription = "Root item, Description"; + rootItem.inventoryName = "Root item"; + rootItem.invType = _rnd.Next(1, 1000); + rootItem.parentFolderID = root.folderID; + _dbPlugin.addInventoryItem(rootItem); + + InventoryItemBase child1Item = new InventoryItemBase(); + child1Item.assetID = LLUUID.Random(); + child1Item.assetType = _rnd.Next(1, 1000); + child1Item.avatarID = _agent_1_id; + child1Item.creatorsID = LLUUID.Random(); + child1Item.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + child1Item.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + child1Item.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + child1Item.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + child1Item.inventoryID = LLUUID.Random(); + child1Item.inventoryDescription = "child1 item, Description"; + child1Item.inventoryName = "child1 item"; + child1Item.invType = _rnd.Next(1, 1000); + child1Item.parentFolderID = child1.folderID; + _dbPlugin.addInventoryItem(child1Item); + + InventoryItemBase child1ChildItem = new InventoryItemBase(); + child1ChildItem.assetID = LLUUID.Random(); + child1ChildItem.assetType = _rnd.Next(1, 1000); + child1ChildItem.avatarID = _agent_1_id; + child1ChildItem.creatorsID = LLUUID.Random(); + child1ChildItem.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + child1ChildItem.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + child1ChildItem.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + child1ChildItem.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + child1ChildItem.inventoryID = LLUUID.Random(); + child1ChildItem.inventoryDescription = "child1Child item, Description"; + child1ChildItem.inventoryName = "child1Child item"; + child1ChildItem.invType = _rnd.Next(1, 1000); + child1ChildItem.parentFolderID = child1Child.folderID; + _dbPlugin.addInventoryItem(child1ChildItem); + + InventoryItemBase child2Item = new InventoryItemBase(); + child2Item.assetID = LLUUID.Random(); + child2Item.assetType = _rnd.Next(1, 1000); + child2Item.avatarID = _agent_1_id; + child2Item.creatorsID = LLUUID.Random(); + child2Item.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + child2Item.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + child2Item.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + child2Item.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + child2Item.inventoryID = LLUUID.Random(); + child2Item.inventoryDescription = "child2 item, Description"; + child2Item.inventoryName = "child2 item"; + child2Item.invType = _rnd.Next(1, 1000); + child2Item.parentFolderID = child2.folderID; + _dbPlugin.addInventoryItem(child2Item); + + InventoryItemBase child2ChildItem = new InventoryItemBase(); + child2ChildItem.assetID = LLUUID.Random(); + child2ChildItem.assetType = _rnd.Next(1, 1000); + child2ChildItem.avatarID = _agent_1_id; + child2ChildItem.creatorsID = LLUUID.Random(); + child2ChildItem.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + child2ChildItem.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + child2ChildItem.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + child2ChildItem.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + child2ChildItem.inventoryID = LLUUID.Random(); + child2ChildItem.inventoryDescription = "child2Child item, Description"; + child2ChildItem.inventoryName = "child2Child item"; + child2ChildItem.invType = _rnd.Next(1, 1000); + child2ChildItem.parentFolderID = child2Child.folderID; + _dbPlugin.addInventoryItem(child2ChildItem); + + // test read of items + + InventoryItemBase item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + item = _dbPlugin.getInventoryItem(child1Item.inventoryID); + Assert.IsTrue(AreItemsIdentical(child1Item, item)); + + item = _dbPlugin.getInventoryItem(child1ChildItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(child1ChildItem, item)); + + item = _dbPlugin.getInventoryItem(child2Item.inventoryID); + Assert.IsTrue(AreItemsIdentical(child2Item, item)); + + item = _dbPlugin.getInventoryItem(child2ChildItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(child2ChildItem, item)); + + _dbPlugin.deleteInventoryItem(rootItem.inventoryID); + _dbPlugin.deleteInventoryItem(child1Item.inventoryID); + _dbPlugin.deleteInventoryItem(child1ChildItem.inventoryID); + _dbPlugin.deleteInventoryItem(child2Item.inventoryID); + _dbPlugin.deleteInventoryItem(child2ChildItem.inventoryID); + } + + /// + /// Test that we can insert a root folder + /// + [Test] + public void T07_DeleteInventoryWithItems() + { + + // Setup inventory + InventoryFolderBase root = new InventoryFolderBase(); + root.agentID = _agent_1_id; + root.folderID = _agent_1_id; + root.name = "Root folder"; + root.parentID = LLUUID.Zero; + root.type = 2; + root.version = 2; + _dbPlugin.addInventoryFolder(root); + + InventoryFolderBase child1 = new InventoryFolderBase(); + child1.agentID = _agent_1_id; + child1.folderID = LLUUID.Random(); + child1.name = "Child 1"; + child1.parentID = root.folderID; + child1.type = 3; + child1.version = 3; + _dbPlugin.addInventoryFolder(child1); + + InventoryFolderBase child1Child = new InventoryFolderBase(); + child1Child.agentID = _agent_1_id; + child1Child.folderID = LLUUID.Random(); + child1Child.name = "Child 1 child"; + child1Child.parentID = child1.folderID; + child1Child.type = 4; + child1Child.version = 4; + _dbPlugin.addInventoryFolder(child1Child); + + InventoryFolderBase child2 = new InventoryFolderBase(); + child2.agentID = _agent_1_id; + child2.folderID = LLUUID.Random(); + child2.name = "Child 2"; + child2.parentID = root.folderID; + child2.type = 5; + child2.version = 5; + _dbPlugin.addInventoryFolder(child2); + + InventoryFolderBase child2Child = new InventoryFolderBase(); + child2Child.agentID = _agent_1_id; + child2Child.folderID = LLUUID.Random(); + child2Child.name = "Child 2 child"; + child2Child.parentID = child2.folderID; + child2Child.type = 6; + child2Child.version = 6; + _dbPlugin.addInventoryFolder(child2Child); + + InventoryItemBase rootItem = new InventoryItemBase(); + rootItem.assetID = LLUUID.Random(); + rootItem.assetType = _rnd.Next(1, 1000); + rootItem.avatarID = _agent_1_id; + rootItem.creatorsID = LLUUID.Random(); + rootItem.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryID = LLUUID.Random(); + rootItem.inventoryDescription = "Root item, Description"; + rootItem.inventoryName = "Root item"; + rootItem.invType = _rnd.Next(1, 1000); + rootItem.parentFolderID = root.folderID; + _dbPlugin.addInventoryItem(rootItem); + + InventoryItemBase child1Item = new InventoryItemBase(); + child1Item.assetID = LLUUID.Random(); + child1Item.assetType = _rnd.Next(1, 1000); + child1Item.avatarID = _agent_1_id; + child1Item.creatorsID = LLUUID.Random(); + child1Item.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + child1Item.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + child1Item.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + child1Item.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + child1Item.inventoryID = LLUUID.Random(); + child1Item.inventoryDescription = "child1 item, Description"; + child1Item.inventoryName = "child1 item"; + child1Item.invType = _rnd.Next(1, 1000); + child1Item.parentFolderID = child1.folderID; + _dbPlugin.addInventoryItem(child1Item); + + InventoryItemBase child1ChildItem = new InventoryItemBase(); + child1ChildItem.assetID = LLUUID.Random(); + child1ChildItem.assetType = _rnd.Next(1, 1000); + child1ChildItem.avatarID = _agent_1_id; + child1ChildItem.creatorsID = LLUUID.Random(); + child1ChildItem.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + child1ChildItem.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + child1ChildItem.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + child1ChildItem.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + child1ChildItem.inventoryID = LLUUID.Random(); + child1ChildItem.inventoryDescription = "child1Child item, Description"; + child1ChildItem.inventoryName = "child1Child item"; + child1ChildItem.invType = _rnd.Next(1, 1000); + child1ChildItem.parentFolderID = child1Child.folderID; + _dbPlugin.addInventoryItem(child1ChildItem); + + InventoryItemBase child2Item = new InventoryItemBase(); + child2Item.assetID = LLUUID.Random(); + child2Item.assetType = _rnd.Next(1, 1000); + child2Item.avatarID = _agent_1_id; + child2Item.creatorsID = LLUUID.Random(); + child2Item.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + child2Item.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + child2Item.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + child2Item.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + child2Item.inventoryID = LLUUID.Random(); + child2Item.inventoryDescription = "child2 item, Description"; + child2Item.inventoryName = "child2 item"; + child2Item.invType = _rnd.Next(1, 1000); + child2Item.parentFolderID = child2.folderID; + _dbPlugin.addInventoryItem(child2Item); + + InventoryItemBase child2ChildItem = new InventoryItemBase(); + child2ChildItem.assetID = LLUUID.Random(); + child2ChildItem.assetType = _rnd.Next(1, 1000); + child2ChildItem.avatarID = _agent_1_id; + child2ChildItem.creatorsID = LLUUID.Random(); + child2ChildItem.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + child2ChildItem.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + child2ChildItem.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + child2ChildItem.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + child2ChildItem.inventoryID = LLUUID.Random(); + child2ChildItem.inventoryDescription = "child2Child item, Description"; + child2ChildItem.inventoryName = "child2Child item"; + child2ChildItem.invType = _rnd.Next(1, 1000); + child2ChildItem.parentFolderID = child2Child.folderID; + _dbPlugin.addInventoryItem(child2ChildItem); + + // test deletetion of items + + _dbPlugin.deleteInventoryItem(rootItem.inventoryID); + _dbPlugin.deleteInventoryItem(child1Item.inventoryID); + _dbPlugin.deleteInventoryItem(child1ChildItem.inventoryID); + _dbPlugin.deleteInventoryItem(child2Item.inventoryID); + _dbPlugin.deleteInventoryItem(child2ChildItem.inventoryID); + + InventoryItemBase item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsNull(item); + + item = _dbPlugin.getInventoryItem(child1Item.inventoryID); + Assert.IsNull(item); + + item = _dbPlugin.getInventoryItem(child1ChildItem.inventoryID); + Assert.IsNull(item); + + item = _dbPlugin.getInventoryItem(child2Item.inventoryID); + Assert.IsNull(item); + + item = _dbPlugin.getInventoryItem(child2ChildItem.inventoryID); + Assert.IsNull(item); + + _dbPlugin.deleteInventoryFolder(_agent_1_id); + } + + + /// + /// Test that we can insert a root folder + /// + [Test] + public void T08_DeleteInventoryWithItems() + { + + // Setup inventory + InventoryFolderBase root = new InventoryFolderBase(); + root.agentID = _agent_1_id; + root.folderID = _agent_1_id; + root.name = "Root folder"; + root.parentID = LLUUID.Zero; + root.type = 2; + root.version = 2; + _dbPlugin.addInventoryFolder(root); + + InventoryFolderBase child1 = new InventoryFolderBase(); + child1.agentID = _agent_1_id; + child1.folderID = LLUUID.Random(); + child1.name = "Child 1"; + child1.parentID = root.folderID; + child1.type = 3; + child1.version = 3; + _dbPlugin.addInventoryFolder(child1); + + InventoryFolderBase child1Child = new InventoryFolderBase(); + child1Child.agentID = _agent_1_id; + child1Child.folderID = LLUUID.Random(); + child1Child.name = "Child 1 child"; + child1Child.parentID = child1.folderID; + child1Child.type = 4; + child1Child.version = 4; + _dbPlugin.addInventoryFolder(child1Child); + + InventoryFolderBase child2 = new InventoryFolderBase(); + child2.agentID = _agent_1_id; + child2.folderID = LLUUID.Random(); + child2.name = "Child 2"; + child2.parentID = root.folderID; + child2.type = 5; + child2.version = 5; + _dbPlugin.addInventoryFolder(child2); + + InventoryFolderBase child2Child = new InventoryFolderBase(); + child2Child.agentID = _agent_1_id; + child2Child.folderID = LLUUID.Random(); + child2Child.name = "Child 2 child"; + child2Child.parentID = child2.folderID; + child2Child.type = 6; + child2Child.version = 6; + _dbPlugin.addInventoryFolder(child2Child); + + InventoryItemBase rootItem = new InventoryItemBase(); + rootItem.assetID = LLUUID.Random(); + rootItem.assetType = _rnd.Next(1, 1000); + rootItem.avatarID = _agent_1_id; + rootItem.creatorsID = LLUUID.Random(); + rootItem.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryID = LLUUID.Random(); + rootItem.inventoryDescription = "Root item, Description"; + rootItem.inventoryName = "Root item"; + rootItem.invType = _rnd.Next(1, 1000); + rootItem.parentFolderID = root.folderID; + _dbPlugin.addInventoryItem(rootItem); + + InventoryItemBase child1Item = new InventoryItemBase(); + child1Item.assetID = LLUUID.Random(); + child1Item.assetType = _rnd.Next(1, 1000); + child1Item.avatarID = _agent_1_id; + child1Item.creatorsID = LLUUID.Random(); + child1Item.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + child1Item.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + child1Item.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + child1Item.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + child1Item.inventoryID = LLUUID.Random(); + child1Item.inventoryDescription = "child1 item, Description"; + child1Item.inventoryName = "child1 item"; + child1Item.invType = _rnd.Next(1, 1000); + child1Item.parentFolderID = child1.folderID; + _dbPlugin.addInventoryItem(child1Item); + + InventoryItemBase child1ChildItem = new InventoryItemBase(); + child1ChildItem.assetID = LLUUID.Random(); + child1ChildItem.assetType = _rnd.Next(1, 1000); + child1ChildItem.avatarID = _agent_1_id; + child1ChildItem.creatorsID = LLUUID.Random(); + child1ChildItem.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + child1ChildItem.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + child1ChildItem.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + child1ChildItem.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + child1ChildItem.inventoryID = LLUUID.Random(); + child1ChildItem.inventoryDescription = "child1Child item, Description"; + child1ChildItem.inventoryName = "child1Child item"; + child1ChildItem.invType = _rnd.Next(1, 1000); + child1ChildItem.parentFolderID = child1Child.folderID; + _dbPlugin.addInventoryItem(child1ChildItem); + + InventoryItemBase child2Item = new InventoryItemBase(); + child2Item.assetID = LLUUID.Random(); + child2Item.assetType = _rnd.Next(1, 1000); + child2Item.avatarID = _agent_1_id; + child2Item.creatorsID = LLUUID.Random(); + child2Item.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + child2Item.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + child2Item.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + child2Item.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + child2Item.inventoryID = LLUUID.Random(); + child2Item.inventoryDescription = "child2 item, Description"; + child2Item.inventoryName = "child2 item"; + child2Item.invType = _rnd.Next(1, 1000); + child2Item.parentFolderID = child2.folderID; + _dbPlugin.addInventoryItem(child2Item); + + InventoryItemBase child2ChildItem = new InventoryItemBase(); + child2ChildItem.assetID = LLUUID.Random(); + child2ChildItem.assetType = _rnd.Next(1, 1000); + child2ChildItem.avatarID = _agent_1_id; + child2ChildItem.creatorsID = LLUUID.Random(); + child2ChildItem.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + child2ChildItem.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + child2ChildItem.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + child2ChildItem.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + child2ChildItem.inventoryID = LLUUID.Random(); + child2ChildItem.inventoryDescription = "child2Child item, Description"; + child2ChildItem.inventoryName = "child2Child item"; + child2ChildItem.invType = _rnd.Next(1, 1000); + child2ChildItem.parentFolderID = child2Child.folderID; + _dbPlugin.addInventoryItem(child2ChildItem); + + // test deletetion of items + + _dbPlugin.deleteInventoryFolder(_agent_1_id); + + InventoryItemBase item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsNull(item); + + item = _dbPlugin.getInventoryItem(child1Item.inventoryID); + Assert.IsNull(item); + + item = _dbPlugin.getInventoryItem(child1ChildItem.inventoryID); + Assert.IsNull(item); + + item = _dbPlugin.getInventoryItem(child2Item.inventoryID); + Assert.IsNull(item); + + item = _dbPlugin.getInventoryItem(child2ChildItem.inventoryID); + Assert.IsNull(item); + + } + + /// + /// Test that we can update items + /// + [Test] + public void T09_UpdateItem() + { + + // Setup inventory + InventoryFolderBase root = new InventoryFolderBase(); + root.agentID = _agent_1_id; + root.folderID = _agent_1_id; + root.name = "Root folder"; + root.parentID = LLUUID.Zero; + root.type = 2; + root.version = 2; + _dbPlugin.addInventoryFolder(root); + + InventoryItemBase rootItem = new InventoryItemBase(); + rootItem.assetID = LLUUID.Random(); + rootItem.assetType = _rnd.Next(1, 1000); + rootItem.avatarID = _agent_1_id; + rootItem.creatorsID = LLUUID.Random(); + rootItem.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + rootItem.inventoryID = LLUUID.Random(); + rootItem.inventoryDescription = "Root item, Description"; + rootItem.inventoryName = "Root item"; + rootItem.invType = _rnd.Next(1, 1000); + rootItem.parentFolderID = root.folderID; + _dbPlugin.addInventoryItem(rootItem); + + rootItem.assetID = LLUUID.Random(); + _dbPlugin.updateInventoryItem(rootItem); + InventoryItemBase item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + rootItem.assetType = rootItem.assetType+1; + _dbPlugin.updateInventoryItem(rootItem); + item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + rootItem.avatarID = LLUUID.Random(); + _dbPlugin.updateInventoryItem(rootItem); + item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + rootItem.creatorsID = LLUUID.Random(); + _dbPlugin.updateInventoryItem(rootItem); + item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + rootItem.inventoryBasePermissions = rootItem.inventoryBasePermissions+1; + _dbPlugin.updateInventoryItem(rootItem); + item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + rootItem.inventoryCurrentPermissions = rootItem.inventoryCurrentPermissions+1; + _dbPlugin.updateInventoryItem(rootItem); + item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + rootItem.inventoryDescription = "New description"; + _dbPlugin.updateInventoryItem(rootItem); + item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + rootItem.inventoryEveryOnePermissions = rootItem.inventoryEveryOnePermissions+1; + _dbPlugin.updateInventoryItem(rootItem); + item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + rootItem.inventoryName = "New name"; + _dbPlugin.updateInventoryItem(rootItem); + item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + rootItem.inventoryNextPermissions = rootItem.inventoryNextPermissions+1; + _dbPlugin.updateInventoryItem(rootItem); + item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + rootItem.invType = rootItem.invType+1; + _dbPlugin.updateInventoryItem(rootItem); + item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + rootItem.parentFolderID = LLUUID.Zero; + _dbPlugin.updateInventoryItem(rootItem); + item = _dbPlugin.getInventoryItem(rootItem.inventoryID); + Assert.IsTrue(AreItemsIdentical(rootItem, item)); + + _dbPlugin.deleteInventoryFolder(_agent_1_id); + _dbPlugin.deleteInventoryItem(rootItem.inventoryID); + } + + + /// + /// Test that we can insert a root folder + /// + [Test] + public void T10_GetListOfItemsInFolder() + { + + // Setup inventory + InventoryFolderBase root = new InventoryFolderBase(); + root.agentID = _agent_1_id; + root.folderID = _agent_1_id; + root.name = "Root folder"; + root.parentID = LLUUID.Zero; + root.type = 2; + root.version = 2; + _dbPlugin.addInventoryFolder(root); + + InventoryFolderBase child1 = new InventoryFolderBase(); + child1.agentID = _agent_1_id; + child1.folderID = LLUUID.Random(); + child1.name = "Child 1"; + child1.parentID = root.folderID; + child1.type = 3; + child1.version = 3; + _dbPlugin.addInventoryFolder(child1); + + InventoryFolderBase child1Child = new InventoryFolderBase(); + child1Child.agentID = _agent_1_id; + child1Child.folderID = LLUUID.Random(); + child1Child.name = "Child 1 child"; + child1Child.parentID = child1.folderID; + child1Child.type = 4; + child1Child.version = 4; + _dbPlugin.addInventoryFolder(child1Child); + + + InventoryItemBase item1 = new InventoryItemBase(); + item1.assetID = LLUUID.Random(); + item1.assetType = _rnd.Next(1, 1000); + item1.avatarID = _agent_1_id; + item1.creatorsID = LLUUID.Random(); + item1.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + item1.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + item1.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + item1.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + item1.inventoryID = LLUUID.Random(); + item1.inventoryDescription = "Item 1, description"; + item1.inventoryName = "Item 1"; + item1.invType = _rnd.Next(1, 1000); + item1.parentFolderID = child1Child.folderID; + _dbPlugin.addInventoryItem(item1); + + InventoryItemBase item2 = new InventoryItemBase(); + item2.assetID = LLUUID.Random(); + item2.assetType = _rnd.Next(1, 1000); + item2.avatarID = _agent_1_id; + item2.creatorsID = LLUUID.Random(); + item2.inventoryBasePermissions = (uint)_rnd.Next(1, 1000000); + item2.inventoryCurrentPermissions = (uint)_rnd.Next(1, 1000000); + item2.inventoryEveryOnePermissions = (uint)_rnd.Next(1, 1000000); + item2.inventoryNextPermissions = (uint)_rnd.Next(1, 1000000); + item2.inventoryID = LLUUID.Random(); + item2.inventoryDescription = "Item 1, description"; + item2.inventoryName = "Item 1"; + item2.invType = _rnd.Next(1, 1000); + item2.parentFolderID = child1Child.folderID; + _dbPlugin.addInventoryItem(item2); + + List items = _dbPlugin.getInventoryInFolder(child1Child.folderID); + Assert.IsNotNull(items); + Assert.IsNotEmpty(items); + + bool foundItem1 = false; + bool foundItem2 = false; + + foreach (InventoryItemBase i in items) + { + if (i.inventoryID == item1.inventoryID) + { + foundItem1 = true; + Assert.IsTrue(AreItemsIdentical(item1, i)); + } + else if (i.inventoryID == item2.inventoryID) + { + foundItem2 = true; + Assert.IsTrue(AreItemsIdentical(item2, i)); + } + else + { + Assert.Fail("Unknown inventory item found"); + } + } + + Assert.IsTrue(foundItem1 && foundItem2, "not all items were returned"); + _dbPlugin.deleteInventoryFolder(_agent_1_id); + } + } +} diff --git a/trunk/OpenSim/Tests/OpenSim/Framework/UtilTest.cs b/trunk/OpenSim/Tests/OpenSim/Framework/UtilTest.cs new file mode 100644 index 0000000000..78acc50689 --- /dev/null +++ b/trunk/OpenSim/Tests/OpenSim/Framework/UtilTest.cs @@ -0,0 +1,143 @@ +/* +* 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 libsecondlife; +using NUnit.Framework; +using NUnit.Framework.SyntaxHelpers; + +using OpenSim.Tests.Common; + +namespace OpenSim.Framework.Tests +{ + [TestFixture] + public class UtilTests + { + [Test] + public void VectorOperationTests() + { + LLVector3 v1, v2; + double expectedDistance; + double expectedMagnitude; + double lowPrecisionTolerance = 0.001; + + //Lets test a simple case of <0,0,0> and <5,5,5> + { + v1 = new LLVector3(0, 0, 0); + v2 = new LLVector3(5, 5, 5); + expectedDistance = 8.66; + Assert.That(Util.GetDistanceTo(v1, v2), + new DoubleToleranceConstraint(expectedDistance, lowPrecisionTolerance), + "Calculated distance between two vectors was not within tolerances."); + + expectedMagnitude = 0; + Assert.That(Util.GetMagnitude(v1), Is.EqualTo(0), "Magnitude of null vector was not zero."); + + expectedMagnitude = 8.66; + Assert.That(Util.GetMagnitude(v2), + new DoubleToleranceConstraint(expectedMagnitude, lowPrecisionTolerance), + "Magnitude of vector was incorrect."); + + TestDelegate d = delegate() { Util.GetNormalizedVector(v1); }; + bool causesArgumentException = TestHelper.AssertThisDelegateCausesArgumentException(d); + Assert.That(causesArgumentException, Is.True, + "Getting magnitude of null vector did not cause argument exception."); + + LLVector3 expectedNormalizedVector = new LLVector3(.577f, .577f, .577f); + double expectedNormalizedMagnitude = 1; + LLVector3 normalizedVector = Util.GetNormalizedVector(v2); + Assert.That(normalizedVector, + new VectorToleranceConstraint(expectedNormalizedVector, lowPrecisionTolerance), + "Normalized vector generated from vector was not what was expected."); + Assert.That(Util.GetMagnitude(normalizedVector), + new DoubleToleranceConstraint(expectedNormalizedMagnitude, lowPrecisionTolerance), + "Normalized vector generated from vector does not have magnitude of 1."); + } + + //Lets test a simple case of <0,0,0> and <0,0,0> + { + v1 = new LLVector3(0, 0, 0); + v2 = new LLVector3(0, 0, 0); + expectedDistance = 0; + Assert.That(Util.GetDistanceTo(v1, v2), + new DoubleToleranceConstraint(expectedDistance, lowPrecisionTolerance), + "Calculated distance between two vectors was not within tolerances."); + + expectedMagnitude = 0; + Assert.That(Util.GetMagnitude(v1), Is.EqualTo(0), "Magnitude of null vector was not zero."); + + expectedMagnitude = 0; + Assert.That(Util.GetMagnitude(v2), + new DoubleToleranceConstraint(expectedMagnitude, lowPrecisionTolerance), + "Magnitude of vector was incorrect."); + + TestDelegate d = delegate() { Util.GetNormalizedVector(v1); }; + bool causesArgumentException = TestHelper.AssertThisDelegateCausesArgumentException(d); + Assert.That(causesArgumentException, Is.True, + "Getting magnitude of null vector did not cause argument exception."); + + d = delegate() { Util.GetNormalizedVector(v2); }; + causesArgumentException = TestHelper.AssertThisDelegateCausesArgumentException(d); + Assert.That(causesArgumentException, Is.True, + "Getting magnitude of null vector did not cause argument exception."); + } + + //Lets test a simple case of <0,0,0> and <-5,-5,-5> + { + v1 = new LLVector3(0, 0, 0); + v2 = new LLVector3(-5, -5, -5); + expectedDistance = 8.66; + Assert.That(Util.GetDistanceTo(v1, v2), + new DoubleToleranceConstraint(expectedDistance, lowPrecisionTolerance), + "Calculated distance between two vectors was not within tolerances."); + + expectedMagnitude = 0; + Assert.That(Util.GetMagnitude(v1), Is.EqualTo(0), "Magnitude of null vector was not zero."); + + expectedMagnitude = 8.66; + Assert.That(Util.GetMagnitude(v2), + new DoubleToleranceConstraint(expectedMagnitude, lowPrecisionTolerance), + "Magnitude of vector was incorrect."); + + TestDelegate d = delegate() { Util.GetNormalizedVector(v1); }; + bool causesArgumentException = TestHelper.AssertThisDelegateCausesArgumentException(d); + Assert.That(causesArgumentException, Is.True, + "Getting magnitude of null vector did not cause argument exception."); + + LLVector3 expectedNormalizedVector = new LLVector3(-.577f, -.577f, -.577f); + double expectedNormalizedMagnitude = 1; + LLVector3 normalizedVector = Util.GetNormalizedVector(v2); + Assert.That(normalizedVector, + new VectorToleranceConstraint(expectedNormalizedVector, lowPrecisionTolerance), + "Normalized vector generated from vector was not what was expected."); + Assert.That(Util.GetMagnitude(normalizedVector), + new DoubleToleranceConstraint(expectedNormalizedMagnitude, lowPrecisionTolerance), + "Normalized vector generated from vector does not have magnitude of 1."); + } + } + } +} diff --git a/trunk/OpenSim/Tests/UserServer/Stress/UserServerStressTest.cs b/trunk/OpenSim/Tests/UserServer/Stress/UserServerStressTest.cs new file mode 100644 index 0000000000..a523d8369b --- /dev/null +++ b/trunk/OpenSim/Tests/UserServer/Stress/UserServerStressTest.cs @@ -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. +* +*/ + +using System; + +namespace OpenSim.Tests.UserServer.Stress +{ + /// + /// In the future this class will programatically stress test the user server + /// + public class UserServerStressTest + { + public static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + System.Console.WriteLine("Aborting - not yet functional"); + } + } +} diff --git a/trunk/OpenSim/Tools/Export/OpenSimExport.cs b/trunk/OpenSim/Tools/Export/OpenSimExport.cs new file mode 100644 index 0000000000..8eebe35cb2 --- /dev/null +++ b/trunk/OpenSim/Tools/Export/OpenSimExport.cs @@ -0,0 +1,110 @@ +/* +* 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; +using System.IO; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Tools.Export +{ + public class OpenSimExport + { + public IniConfigSource config; + public StorageManager sman; + + public OpenSimExport(IniConfigSource config) + { + this.config = config; + IConfig startup = config.Configs["Startup"]; + // AddinManager.Initialize("."); + // AddinManager.Registry.Update(null); + + MainConsole.Instance = CreateConsole(); + + sman = new StorageManager( + startup.GetString("storage_plugin", "OpenSim.DataStore.NullStorage.dll"), + startup.GetString("storage_connection_string", String.Empty), + false + ); + } + + public static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + OpenSimExport export = new OpenSimExport(InitConfig(args)); + RegionInfo reg = new RegionInfo("Sara Jane", "Regions/1000-1000.xml",false); + + Console.WriteLine("This application does nothing useful yet: " + reg.RegionID); + foreach (SceneObjectGroup group in export.sman.DataStore.LoadObjects(reg.RegionID)) + { + Console.WriteLine("{0} -> {1}", reg.RegionID, group.UUID); + } + } + + protected ConsoleBase CreateConsole() + { + return new ConsoleBase("Export", null); + } + + private static IniConfigSource InitConfig(string[] args) + { + Console.WriteLine("Good"); + ArgvConfigSource configSource = new ArgvConfigSource(args); + configSource.AddSwitch("Startup", "inifile"); + + IConfig startupConfig = configSource.Configs["Startup"]; + string iniFilePath = startupConfig.GetString("inifile", "OpenSim.ini"); + Console.WriteLine(iniFilePath); + IniConfigSource config = new IniConfigSource(); + //check for .INI file (either default or name passed in command line) + if (! File.Exists(iniFilePath)) + { + iniFilePath = Path.Combine(Util.configDir(), iniFilePath); + } + + if (File.Exists(iniFilePath)) + { + config.Merge(new IniConfigSource(iniFilePath)); + config.Merge(configSource); + } + else + { + // no default config files, so set default values, and save it + Console.WriteLine("We didn't find a config!"); + config.Merge(OpenSimMain.DefaultConfig()); + config.Merge(configSource); + } + + return config; + } + } +} diff --git a/trunk/OpenSim/Tools/LaunchSLClient/Form1.Designer.cs b/trunk/OpenSim/Tools/LaunchSLClient/Form1.Designer.cs new file mode 100644 index 0000000000..b841f0b03e --- /dev/null +++ b/trunk/OpenSim/Tools/LaunchSLClient/Form1.Designer.cs @@ -0,0 +1,108 @@ +/* +* 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. +* +*/ + +namespace LaunchSLClient +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // comboBox1 + // + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "Local Sandbox", + "Local Grid Server", + "DeepGrid - www.deepgrid.com", + "OSGrid - www.osgrid.org", + "Linden Labs - www.secondlife.com"}); + this.comboBox1.Location = new System.Drawing.Point(37, 83); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(348, 21); + this.comboBox1.TabIndex = 0; + this.comboBox1.Text = "Choose from list"; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // textBox1 + // + this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.textBox1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.textBox1.Location = new System.Drawing.Point(37, 32); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + this.textBox1.Size = new System.Drawing.Size(292, 19); + this.textBox1.TabIndex = 1; + this.textBox1.Text = "Choose from one of the following:"; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(501, 339); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.comboBox1); + this.Name = "Form1"; + this.Text = "OpenSim Client Launcher"; + this.ResumeLayout(false); + this.PerformLayout(); + } + + #endregion + + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.TextBox textBox1; + } +} diff --git a/trunk/OpenSim/Tools/LaunchSLClient/Form1.cs b/trunk/OpenSim/Tools/LaunchSLClient/Form1.cs new file mode 100644 index 0000000000..183a104b23 --- /dev/null +++ b/trunk/OpenSim/Tools/LaunchSLClient/Form1.cs @@ -0,0 +1,211 @@ +/* +* 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; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using Microsoft.Win32; + +namespace LaunchSLClient +{ + public partial class Form1 : Form + { + const string deepGridUrl = "http://user.deepgrid.com:8002/"; + const string osGridUrl = "http://www.osgrid.org:8002/"; + const string openLifeGridUrl = "http://logingrid.net:8002"; + + string gridUrl = ""; + string sandboxUrl = ""; + string runUrl = ""; + string runLine = ""; + string exeFlags = ""; + string exePath = ""; + + private void addLocalSandbox(ref ArrayList menuItems) + { + // build sandbox URL from Regions\default.xml + // this is highly dependant on a standard default.xml + if (File.Exists(@"Regions\default.xml")) + { + string sandboxHostName = ""; + string sandboxPort = ""; + string text; + + Regex myRegex = new Regex(".*internal_ip_port=\\\"(?.*?)\\\".*external_host_name=\\\"(?.*?)\\\".*"); + + FileInfo defaultFile = new FileInfo(@"Regions\default.xml"); + StreamReader stream = defaultFile.OpenText(); + do + { + text = stream.ReadLine(); + if (text == null) + { + break; + } + MatchCollection theMatches = myRegex.Matches(text); + foreach (Match theMatch in theMatches) + { + if (theMatch.Length != 0) + { + sandboxHostName = theMatch.Groups["name"].ToString(); + sandboxPort = theMatch.Groups["port"].ToString(); + } + } + } while (text != null); + + stream.Close(); + sandboxUrl = "http:\\" + sandboxHostName + ":" + sandboxPort; + menuItems.Add("Local Sandbox"); + } + } + + private void addLocalGrid(ref ArrayList menuItems) + { + //build local grid URL from network_servers_information.xml + // this is highly dependant on a standard default.xml + if (File.Exists(@"network_servers_information.xml")) + { + string text; + FileInfo defaultFile = new FileInfo(@"network_servers_information.xml"); + Regex myRegex = new Regex(".*UserServerURL=\\\"(?.*?)\\\".*"); + StreamReader stream = defaultFile.OpenText(); + + do + { + text = stream.ReadLine(); + if (text == null) + { + break; + } + foreach (Match theMatch in myRegex.Matches(text)) + { + if (theMatch.Length != 0) + { + gridUrl = theMatch.Groups["url"].ToString(); + } + } + } while (text != null); + stream.Close(); + if (gridUrl != null) + { + menuItems.Add("Local Grid Server"); + } + } + } + + private void addLocalSims(ref ArrayList menuItems) + { + // find opensim directory + RegistryKey exeKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\OpenSim\OpenSim"); + if (exeKey != null) + { + Object simPath = exeKey.GetValue("Path"); + + Directory.SetCurrentDirectory(simPath.ToString()); //this should be set to wherever we decide to put the binaries + + addLocalSandbox(ref menuItems); + addLocalGrid(ref menuItems); + } + else + { + MessageBox.Show("No OpenSim installed. Showing public grids only", "No OpenSim"); + } + } + + private void getClient(ref string exePath, ref string runLine, ref string exeFlags) + { + // get executable path from registry + RegistryKey regKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Linden Research, Inc.\SecondLife"); + if (regKey == null) + { + regKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Linden Research, Inc.\SecondLife"); + if (regKey == null) + { + throw new LauncherException("Can't find Second Life. Are you sure it is installed?", "LauncherException.Form1"); + } + } + string exe = regKey.GetValue("Exe").ToString(); + exeFlags = regKey.GetValue("Flags").ToString(); + exePath = regKey.GetValue("").ToString(); + runLine = exePath + "\\" + exe; + Registry.LocalMachine.Flush(); + Registry.LocalMachine.Close(); + } + + public Form1() + { + InitializeComponent(); + ArrayList menuItems = new ArrayList(); + + getClient(ref exePath, ref runLine, ref exeFlags); + + menuItems.Add("Please select one:"); + + addLocalSims(ref menuItems); + + menuItems.Add("OSGrid - www.osgrid.org"); + menuItems.Add("DeepGrid - www.deepgrid.com"); + menuItems.Add("OpenlifeGrid - www.openlifegrid.com"); + menuItems.Add("Linden Labs - www.secondlife.com"); + + comboBox1.DataSource = menuItems; + } + + private void radioButton1_CheckedChanged(object sender, EventArgs e) + { + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBox1.Text == "Please select one:") { return; } + if (comboBox1.Text == "Local Sandbox") { runUrl=" -loginuri " + sandboxUrl;} + if (comboBox1.Text == "Local Grid Server") { runUrl = " -loginuri " + gridUrl; } + if (comboBox1.Text == "DeepGrid - www.deepgrid.com") { runUrl = " -loginuri " + deepGridUrl; } + if (comboBox1.Text == "OSGrid - www.osgrid.org") { runUrl = " -loginuri " + osGridUrl; } + if (comboBox1.Text == "OpenlifeGrid - www.openlifegrid.com") { runUrl = " -loginuri " + openLifeGridUrl; } + if (comboBox1.Text == "Linden Labs - www.secondlife.com") { runUrl = ""; } + + System.Diagnostics.Process proc = new System.Diagnostics.Process(); + proc.StartInfo.FileName = runLine; + proc.StartInfo.Arguments = exeFlags.ToString() + " " + runUrl; + proc.StartInfo.UseShellExecute = false; + proc.StartInfo.RedirectStandardOutput = false; + proc.StartInfo.WorkingDirectory = exePath.ToString(); + proc.Start(); + proc.WaitForExit(); + } + } +} diff --git a/trunk/OpenSim/Tools/LaunchSLClient/Form1.resx b/trunk/OpenSim/Tools/LaunchSLClient/Form1.resx new file mode 100644 index 0000000000..19dc0dd8b3 --- /dev/null +++ b/trunk/OpenSim/Tools/LaunchSLClient/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/trunk/OpenSim/Tools/LaunchSLClient/LauncherException.cs b/trunk/OpenSim/Tools/LaunchSLClient/LauncherException.cs new file mode 100644 index 0000000000..e31bd1de87 --- /dev/null +++ b/trunk/OpenSim/Tools/LaunchSLClient/LauncherException.cs @@ -0,0 +1,53 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; + +namespace LaunchSLClient +{ + class LauncherException : ApplicationException + { + private const string CUSTOMMESSAGE = "The SL Client Launcher has failed with the following error: "; + + private LauncherException() { } + + public LauncherException(string errorMesssage, string source) + : base (CUSTOMMESSAGE + errorMesssage) + { + base.Source = source; + } + + public LauncherException(string errorMessage, string source, Exception innerException) + : base(CUSTOMMESSAGE + errorMessage, innerException) + { + base.Source = source; + } + } +} diff --git a/trunk/OpenSim/Tools/LaunchSLClient/Program.cs b/trunk/OpenSim/Tools/LaunchSLClient/Program.cs new file mode 100644 index 0000000000..778d5c0606 --- /dev/null +++ b/trunk/OpenSim/Tools/LaunchSLClient/Program.cs @@ -0,0 +1,56 @@ +/* +* 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; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace LaunchSLClient +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + try + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + catch (Exception ex) + { + // Handles all unhandled errors + MessageBox.Show(ex.Message,"Unhandled Error"); + } + } + } +} diff --git a/trunk/OpenSim/Tools/LaunchSLClient/Properties/AssemblyInfo.cs b/trunk/OpenSim/Tools/LaunchSLClient/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..87a4ac4883 --- /dev/null +++ b/trunk/OpenSim/Tools/LaunchSLClient/Properties/AssemblyInfo.cs @@ -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 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.CompilerServices; +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("LaunchSLClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Home")] +[assembly: AssemblyProduct("LaunchSLClient")] +[assembly: AssemblyCopyright("Copyright © Home 2007")] +[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("b08c6904-e6cc-4d9c-8d24-feb0464b1648")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/trunk/OpenSim/Tools/LaunchSLClient/Properties/Resources.Designer.cs b/trunk/OpenSim/Tools/LaunchSLClient/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..4e9188d308 --- /dev/null +++ b/trunk/OpenSim/Tools/LaunchSLClient/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.832 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace LaunchSLClient.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LaunchSLClient.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/trunk/OpenSim/Tools/LaunchSLClient/Properties/Resources.resx b/trunk/OpenSim/Tools/LaunchSLClient/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebbac --- /dev/null +++ b/trunk/OpenSim/Tools/LaunchSLClient/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/trunk/OpenSim/Tools/LaunchSLClient/Properties/Settings.Designer.cs b/trunk/OpenSim/Tools/LaunchSLClient/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..3dcc200625 --- /dev/null +++ b/trunk/OpenSim/Tools/LaunchSLClient/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.832 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace LaunchSLClient.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/trunk/OpenSim/Tools/LaunchSLClient/Properties/Settings.settings b/trunk/OpenSim/Tools/LaunchSLClient/Properties/Settings.settings new file mode 100644 index 0000000000..39645652af --- /dev/null +++ b/trunk/OpenSim/Tools/LaunchSLClient/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/trunk/OpenSim/Tools/OpenSim.32BitLaunch/OpenSim.32BitLaunch.csproj b/trunk/OpenSim/Tools/OpenSim.32BitLaunch/OpenSim.32BitLaunch.csproj new file mode 100644 index 0000000000..bfca5e4d77 --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.32BitLaunch/OpenSim.32BitLaunch.csproj @@ -0,0 +1,63 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {595D67F3-B413-4A43-8568-5B5930E3B31D} + Exe + Properties + OpenSim._32BitLaunch + OpenSim.32BitLaunch + v2.0 + 512 + + + true + full + false + ..\..\..\bin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + 3.5 + + + + + + + + + + + {AC9EB8AB-0000-0000-0000-000000000000} + OpenSim + + + + + \ No newline at end of file diff --git a/trunk/OpenSim/Tools/OpenSim.32BitLaunch/Program.cs b/trunk/OpenSim/Tools/OpenSim.32BitLaunch/Program.cs new file mode 100644 index 0000000000..78ba598636 --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.32BitLaunch/Program.cs @@ -0,0 +1,60 @@ +/* +* 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; + +namespace OpenSim._32BitLaunch +{ + class Program + { + static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + System.Console.WriteLine("32-bit OpenSim executor"); + System.Console.WriteLine("-----------------------"); + System.Console.WriteLine(""); + System.Console.WriteLine("This application is compiled for 32-bit CPU and will run under WOW32 or similar."); + System.Console.WriteLine("All 64-bit incompatibilities should be gone."); + System.Console.WriteLine(""); + System.Threading.Thread.Sleep(300); + try + { + OpenSim.Application.Main(args); + } + catch (Exception ex) + { + System.Console.WriteLine("OpenSim threw an exception:"); + System.Console.WriteLine(ex.ToString()); + System.Console.WriteLine(""); + System.Console.WriteLine("Application will now terminate!"); + System.Console.WriteLine(""); + } + } + } +} diff --git a/trunk/OpenSim/Tools/OpenSim.32BitLaunch/Properties/AssemblyInfo.cs b/trunk/OpenSim/Tools/OpenSim.32BitLaunch/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..31543f8f74 --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.32BitLaunch/Properties/AssemblyInfo.cs @@ -0,0 +1,64 @@ +/* +* 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.CompilerServices; +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.32BitLaunch")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpenSim.32BitLaunch")] +[assembly: AssemblyCopyright("Copyright © 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("5072e919-46ab-47e6-8a63-08108324ccdf")] + +// 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("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/InputTextBoxControl.cs b/trunk/OpenSim/Tools/OpenSim.GUI/InputTextBoxControl.cs new file mode 100644 index 0000000000..467942e810 --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/InputTextBoxControl.cs @@ -0,0 +1,116 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; + +namespace OpenSim.GUI +{ + class InputTextBoxControl:System.Windows.Forms.TextBox + { + public InputTextBoxControl() + { + this.KeyDown += new System.Windows.Forms.KeyEventHandler(TextInputControl_KeyDown); + } + + + private List CommandHistory = new List(); + private bool InHistory = false; + private int HistoryPosition = -1; + + void TextInputControl_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) + { + + + if (e.KeyCode == Keys.Enter && InHistory == false) + { + CommandHistory.Add(this.Text); + } + + + if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down) + { + // if not inside buffer, enter + // InBuffer = true + //Console.WriteLine("History: Check"); + if (InHistory == false) + { + if (this.Text != "") + { + //Console.WriteLine("History: Add"); + CommandHistory.Add(this.Text); + HistoryPosition = CommandHistory.Count; + } + else + { + //HistoryPosition = CommandHistory.Count + 1; + } + //Console.WriteLine("History: InHistory"); + InHistory = true; + } + + if (e.KeyCode == Keys.Up) + HistoryPosition -= 1; + if (e.KeyCode == Keys.Down) + HistoryPosition += 1; + + if (HistoryPosition > CommandHistory.Count - 1) + HistoryPosition = -1; + if (HistoryPosition < -1) + HistoryPosition = CommandHistory.Count - 1; + + //Console.WriteLine("History: Pos: " + HistoryPosition); + //Console.WriteLine("History: HaveInHistCount: " + CommandHistory.Count); + if (CommandHistory.Count != 0) + { + if (HistoryPosition != -1) + { + //Console.WriteLine("History: Getting"); + //this.Text = CommandHistory.Item(HistoryPosition); + this.Text = CommandHistory[HistoryPosition]; + this.SelectionStart = this.Text.Length; + this.SelectionLength = 0; + } + else + { + //Console.WriteLine("History: Nothing"); + this.Text = ""; + } + } + e.Handled = true; + } else { + InHistory = false; + HistoryPosition = -1; + } + } + + + } +} diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/Main.Designer.cs b/trunk/OpenSim/Tools/OpenSim.GUI/Main.Designer.cs new file mode 100644 index 0000000000..d693b9a381 --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/Main.Designer.cs @@ -0,0 +1,1436 @@ +/* +* 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. +* +*/ + +namespace OpenSim.GUI +{ + partial class Main + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.timer1 = new System.Windows.Forms.Timer(this.components); + this.clientBox1 = new System.Windows.Forms.TextBox(); + this.btnStart = new System.Windows.Forms.Button(); + this.btnStop = new System.Windows.Forms.Button(); + this.rbGridRegionMode = new System.Windows.Forms.RadioButton(); + this.rbStandAloneMode = new System.Windows.Forms.RadioButton(); + this.rbGridServer = new System.Windows.Forms.RadioButton(); + this.Launch1 = new System.Windows.Forms.Button(); + this.gbLog = new System.Windows.Forms.GroupBox(); + this.tabLogs = new System.Windows.Forms.TabControl(); + this.tabMainLog = new System.Windows.Forms.TabPage(); + this.txtMainLog = new System.Windows.Forms.TextBox(); + this.tabRegionServer = new System.Windows.Forms.TabPage(); + this.txtInputRegionServer = new OpenSim.GUI.InputTextBoxControl(); + this.label1 = new System.Windows.Forms.Label(); + this.txtOpenSim = new System.Windows.Forms.TextBox(); + this.tabUserServer = new System.Windows.Forms.TabPage(); + this.txtInputUserServer = new OpenSim.GUI.InputTextBoxControl(); + this.label2 = new System.Windows.Forms.Label(); + this.txtUserServer = new System.Windows.Forms.TextBox(); + this.tabAssetServer = new System.Windows.Forms.TabPage(); + this.txtInputAssetServer = new OpenSim.GUI.InputTextBoxControl(); + this.label3 = new System.Windows.Forms.Label(); + this.txtAssetServer = new System.Windows.Forms.TextBox(); + this.tabGridServer = new System.Windows.Forms.TabPage(); + this.txtInputGridServer = new OpenSim.GUI.InputTextBoxControl(); + this.label4 = new System.Windows.Forms.Label(); + this.txtGridServer = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.noProbe1 = new System.Windows.Forms.CheckBox(); + this.label6 = new System.Windows.Forms.Label(); + this.multiple1 = new System.Windows.Forms.CheckBox(); + this.label7 = new System.Windows.Forms.Label(); + this.noMultiple1 = new System.Windows.Forms.CheckBox(); + this.ignorepixeldepth1 = new System.Windows.Forms.CheckBox(); + this.nothread1 = new System.Windows.Forms.CheckBox(); + this.safe1 = new System.Windows.Forms.CheckBox(); + this.noconsole1 = new System.Windows.Forms.CheckBox(); + this.log1 = new System.Windows.Forms.CheckBox(); + this.helperuri1 = new System.Windows.Forms.CheckBox(); + this.autologin1 = new System.Windows.Forms.CheckBox(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.dialog1 = new System.Windows.Forms.CheckBox(); + this.previous1 = new System.Windows.Forms.CheckBox(); + this.simple1 = new System.Windows.Forms.CheckBox(); + this.noinvlib1 = new System.Windows.Forms.CheckBox(); + this.debugst1 = new System.Windows.Forms.CheckBox(); + this.spanish1 = new System.Windows.Forms.CheckBox(); + this.korean1 = new System.Windows.Forms.CheckBox(); + this.local1 = new System.Windows.Forms.CheckBox(); + this.purge1 = new System.Windows.Forms.CheckBox(); + this.nofmod1 = new System.Windows.Forms.CheckBox(); + this.noaudio1 = new System.Windows.Forms.CheckBox(); + this.nosound1 = new System.Windows.Forms.CheckBox(); + this.url1 = new System.Windows.Forms.CheckBox(); + this.port1 = new System.Windows.Forms.CheckBox(); + this.simBox1 = new System.Windows.Forms.TextBox(); + this.portBox1 = new System.Windows.Forms.TextBox(); + this.user1 = new System.Windows.Forms.CheckBox(); + this.quitAfter1 = new System.Windows.Forms.CheckBox(); + this.techTag1 = new System.Windows.Forms.CheckBox(); + this.yield1 = new System.Windows.Forms.CheckBox(); + this.logfile1 = new System.Windows.Forms.CheckBox(); + this.settings1 = new System.Windows.Forms.CheckBox(); + this.outbw1 = new System.Windows.Forms.CheckBox(); + this.inbw1 = new System.Windows.Forms.CheckBox(); + this.drop1 = new System.Windows.Forms.CheckBox(); + this.dropBox1 = new System.Windows.Forms.TextBox(); + this.inbwBox1 = new System.Windows.Forms.TextBox(); + this.outbwBox1 = new System.Windows.Forms.TextBox(); + this.settingsBox1 = new System.Windows.Forms.TextBox(); + this.logfileBox1 = new System.Windows.Forms.TextBox(); + this.yieldBox1 = new System.Windows.Forms.TextBox(); + this.techtagBox1 = new System.Windows.Forms.TextBox(); + this.quitafterBox1 = new System.Windows.Forms.TextBox(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.loginuri1 = new System.Windows.Forms.CheckBox(); + this.loginuriBox1 = new System.Windows.Forms.TextBox(); + this.set1 = new System.Windows.Forms.CheckBox(); + this.setBox1 = new System.Windows.Forms.TextBox(); + this.errmask1 = new System.Windows.Forms.CheckBox(); + this.skin1 = new System.Windows.Forms.CheckBox(); + this.login1 = new System.Windows.Forms.CheckBox(); + this.errmaskBox1 = new System.Windows.Forms.TextBox(); + this.skinBox1 = new System.Windows.Forms.TextBox(); + this.firstBox1 = new System.Windows.Forms.TextBox(); + this.lastBox1 = new System.Windows.Forms.TextBox(); + this.noutc1 = new System.Windows.Forms.CheckBox(); + this.passBox1 = new System.Windows.Forms.TextBox(); + this.raw1 = new System.Windows.Forms.CheckBox(); + this.rawBox1 = new System.Windows.Forms.TextBox(); + this.clear1 = new System.Windows.Forms.Button(); + this.nataddress1 = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.exeBox1 = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.label11 = new System.Windows.Forms.Label(); + this.label12 = new System.Windows.Forms.Label(); + this.label13 = new System.Windows.Forms.Label(); + this.menuStrip1.SuspendLayout(); + this.gbLog.SuspendLayout(); + this.tabLogs.SuspendLayout(); + this.tabMainLog.SuspendLayout(); + this.tabRegionServer.SuspendLayout(); + this.tabUserServer.SuspendLayout(); + this.tabAssetServer.SuspendLayout(); + this.tabGridServer.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip1 + // + this.menuStrip1.AutoSize = false; + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(900, 20); + this.menuStrip1.TabIndex = 7; + this.menuStrip1.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.exitToolStripMenuItem}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(35, 16); + this.fileToolStripMenuItem.Text = "File"; + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.Size = new System.Drawing.Size(130, 22); + this.exitToolStripMenuItem.Text = "Exit Cleanly"; + this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); + // + // timer1 + // + this.timer1.Enabled = true; + // + // clientBox1 + // + this.clientBox1.Location = new System.Drawing.Point(680, 27); + this.clientBox1.Name = "clientBox1"; + this.clientBox1.Size = new System.Drawing.Size(213, 20); + this.clientBox1.TabIndex = 8; + this.clientBox1.Text = "C://Secondlife//"; + // + // btnStart + // + this.btnStart.Location = new System.Drawing.Point(7, 366); + this.btnStart.Name = "btnStart"; + this.btnStart.Size = new System.Drawing.Size(80, 23); + this.btnStart.TabIndex = 2; + this.btnStart.Text = "Start"; + this.btnStart.UseVisualStyleBackColor = true; + this.btnStart.Click += new System.EventHandler(this.btnStart_Click); + // + // btnStop + // + this.btnStop.Location = new System.Drawing.Point(92, 366); + this.btnStop.Name = "btnStop"; + this.btnStop.Size = new System.Drawing.Size(80, 23); + this.btnStop.TabIndex = 3; + this.btnStop.Text = "Stop"; + this.btnStop.UseVisualStyleBackColor = true; + this.btnStop.Click += new System.EventHandler(this.btnStop_Click); + // + // rbGridRegionMode + // + this.rbGridRegionMode.AutoSize = true; + this.rbGridRegionMode.Location = new System.Drawing.Point(96, 27); + this.rbGridRegionMode.Name = "rbGridRegionMode"; + this.rbGridRegionMode.Size = new System.Drawing.Size(76, 17); + this.rbGridRegionMode.TabIndex = 4; + this.rbGridRegionMode.Text = "Grid region"; + this.rbGridRegionMode.UseVisualStyleBackColor = true; + this.rbGridRegionMode.CheckedChanged += new System.EventHandler(this.rbGridRegionMode_CheckedChanged); + // + // rbStandAloneMode + // + this.rbStandAloneMode.AutoSize = true; + this.rbStandAloneMode.Checked = true; + this.rbStandAloneMode.Location = new System.Drawing.Point(8, 27); + this.rbStandAloneMode.Name = "rbStandAloneMode"; + this.rbStandAloneMode.Size = new System.Drawing.Size(82, 17); + this.rbStandAloneMode.TabIndex = 5; + this.rbStandAloneMode.TabStop = true; + this.rbStandAloneMode.Text = "Stand alone"; + this.rbStandAloneMode.UseVisualStyleBackColor = true; + this.rbStandAloneMode.CheckedChanged += new System.EventHandler(this.rbStandAloneMode_CheckedChanged); + // + // rbGridServer + // + this.rbGridServer.AutoSize = true; + this.rbGridServer.Location = new System.Drawing.Point(178, 27); + this.rbGridServer.Name = "rbGridServer"; + this.rbGridServer.Size = new System.Drawing.Size(76, 17); + this.rbGridServer.TabIndex = 6; + this.rbGridServer.Text = "Grid server"; + this.rbGridServer.UseVisualStyleBackColor = true; + this.rbGridServer.CheckedChanged += new System.EventHandler(this.rbGridServer_CheckedChanged); + // + // Launch1 + // + this.Launch1.Location = new System.Drawing.Point(264, 366); + this.Launch1.Name = "Launch1"; + this.Launch1.Size = new System.Drawing.Size(80, 23); + this.Launch1.TabIndex = 9; + this.Launch1.Text = "Client Launch"; + this.Launch1.UseVisualStyleBackColor = true; + this.Launch1.Click += new System.EventHandler(this.Launch1_Click); + // + // gbLog + // + this.gbLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gbLog.Controls.Add(this.tabLogs); + this.gbLog.Location = new System.Drawing.Point(8, 50); + this.gbLog.Name = "gbLog"; + this.gbLog.Size = new System.Drawing.Size(345, 310); + this.gbLog.TabIndex = 1; + this.gbLog.TabStop = false; + this.gbLog.Text = "Logs"; + // + // tabLogs + // + this.tabLogs.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tabLogs.Controls.Add(this.tabMainLog); + this.tabLogs.Controls.Add(this.tabRegionServer); + this.tabLogs.Controls.Add(this.tabUserServer); + this.tabLogs.Controls.Add(this.tabAssetServer); + this.tabLogs.Controls.Add(this.tabGridServer); + this.tabLogs.Location = new System.Drawing.Point(6, 19); + this.tabLogs.Name = "tabLogs"; + this.tabLogs.SelectedIndex = 0; + this.tabLogs.Size = new System.Drawing.Size(333, 285); + this.tabLogs.TabIndex = 0; + // + // tabMainLog + // + this.tabMainLog.Controls.Add(this.txtMainLog); + this.tabMainLog.Location = new System.Drawing.Point(4, 22); + this.tabMainLog.Name = "tabMainLog"; + this.tabMainLog.Size = new System.Drawing.Size(325, 259); + this.tabMainLog.TabIndex = 4; + this.tabMainLog.Text = "Main log"; + this.tabMainLog.UseVisualStyleBackColor = true; + // + // txtMainLog + // + this.txtMainLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtMainLog.Location = new System.Drawing.Point(0, 0); + this.txtMainLog.Multiline = true; + this.txtMainLog.Name = "txtMainLog"; + this.txtMainLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtMainLog.Size = new System.Drawing.Size(325, 259); + this.txtMainLog.TabIndex = 1; + // + // tabRegionServer + // + this.tabRegionServer.Controls.Add(this.txtInputRegionServer); + this.tabRegionServer.Controls.Add(this.label1); + this.tabRegionServer.Controls.Add(this.txtOpenSim); + this.tabRegionServer.Location = new System.Drawing.Point(4, 22); + this.tabRegionServer.Name = "tabRegionServer"; + this.tabRegionServer.Padding = new System.Windows.Forms.Padding(3); + this.tabRegionServer.Size = new System.Drawing.Size(325, 259); + this.tabRegionServer.TabIndex = 0; + this.tabRegionServer.Text = "Region server"; + this.tabRegionServer.UseVisualStyleBackColor = true; + // + // txtInputRegionServer + // + this.txtInputRegionServer.Location = new System.Drawing.Point(53, 239); + this.txtInputRegionServer.Name = "txtInputRegionServer"; + this.txtInputRegionServer.Size = new System.Drawing.Size(272, 20); + this.txtInputRegionServer.TabIndex = 5; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(0, 242); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(57, 13); + this.label1.TabIndex = 4; + this.label1.Text = "Command:"; + // + // txtOpenSim + // + this.txtOpenSim.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtOpenSim.Location = new System.Drawing.Point(0, 0); + this.txtOpenSim.Multiline = true; + this.txtOpenSim.Name = "txtOpenSim"; + this.txtOpenSim.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtOpenSim.Size = new System.Drawing.Size(325, 236); + this.txtOpenSim.TabIndex = 0; + // + // tabUserServer + // + this.tabUserServer.Controls.Add(this.txtInputUserServer); + this.tabUserServer.Controls.Add(this.label2); + this.tabUserServer.Controls.Add(this.txtUserServer); + this.tabUserServer.Location = new System.Drawing.Point(4, 22); + this.tabUserServer.Name = "tabUserServer"; + this.tabUserServer.Padding = new System.Windows.Forms.Padding(3); + this.tabUserServer.Size = new System.Drawing.Size(325, 259); + this.tabUserServer.TabIndex = 1; + this.tabUserServer.Text = "User server"; + this.tabUserServer.UseVisualStyleBackColor = true; + // + // txtInputUserServer + // + this.txtInputUserServer.Location = new System.Drawing.Point(53, 239); + this.txtInputUserServer.Name = "txtInputUserServer"; + this.txtInputUserServer.Size = new System.Drawing.Size(272, 20); + this.txtInputUserServer.TabIndex = 7; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(0, 242); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(57, 13); + this.label2.TabIndex = 6; + this.label2.Text = "Command:"; + // + // txtUserServer + // + this.txtUserServer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtUserServer.Location = new System.Drawing.Point(0, 0); + this.txtUserServer.Multiline = true; + this.txtUserServer.Name = "txtUserServer"; + this.txtUserServer.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtUserServer.Size = new System.Drawing.Size(325, 236); + this.txtUserServer.TabIndex = 1; + // + // tabAssetServer + // + this.tabAssetServer.Controls.Add(this.txtInputAssetServer); + this.tabAssetServer.Controls.Add(this.label3); + this.tabAssetServer.Controls.Add(this.txtAssetServer); + this.tabAssetServer.Location = new System.Drawing.Point(4, 22); + this.tabAssetServer.Name = "tabAssetServer"; + this.tabAssetServer.Size = new System.Drawing.Size(325, 259); + this.tabAssetServer.TabIndex = 2; + this.tabAssetServer.Text = "Asset server"; + this.tabAssetServer.UseVisualStyleBackColor = true; + // + // txtInputAssetServer + // + this.txtInputAssetServer.Location = new System.Drawing.Point(53, 239); + this.txtInputAssetServer.Name = "txtInputAssetServer"; + this.txtInputAssetServer.Size = new System.Drawing.Size(272, 20); + this.txtInputAssetServer.TabIndex = 7; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(0, 242); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(57, 13); + this.label3.TabIndex = 6; + this.label3.Text = "Command:"; + // + // txtAssetServer + // + this.txtAssetServer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtAssetServer.Location = new System.Drawing.Point(0, 0); + this.txtAssetServer.Multiline = true; + this.txtAssetServer.Name = "txtAssetServer"; + this.txtAssetServer.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtAssetServer.Size = new System.Drawing.Size(325, 236); + this.txtAssetServer.TabIndex = 1; + // + // tabGridServer + // + this.tabGridServer.Controls.Add(this.txtInputGridServer); + this.tabGridServer.Controls.Add(this.label4); + this.tabGridServer.Controls.Add(this.txtGridServer); + this.tabGridServer.Location = new System.Drawing.Point(4, 22); + this.tabGridServer.Name = "tabGridServer"; + this.tabGridServer.Size = new System.Drawing.Size(325, 259); + this.tabGridServer.TabIndex = 3; + this.tabGridServer.Text = "Grid server"; + this.tabGridServer.UseVisualStyleBackColor = true; + // + // txtInputGridServer + // + this.txtInputGridServer.Location = new System.Drawing.Point(53, 239); + this.txtInputGridServer.Name = "txtInputGridServer"; + this.txtInputGridServer.Size = new System.Drawing.Size(272, 20); + this.txtInputGridServer.TabIndex = 7; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(0, 242); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(57, 13); + this.label4.TabIndex = 6; + this.label4.Text = "Command:"; + // + // txtGridServer + // + this.txtGridServer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtGridServer.Location = new System.Drawing.Point(0, 0); + this.txtGridServer.Multiline = true; + this.txtGridServer.Name = "txtGridServer"; + this.txtGridServer.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtGridServer.Size = new System.Drawing.Size(325, 236); + this.txtGridServer.TabIndex = 1; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))), System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label5.Location = new System.Drawing.Point(460, 55); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(205, 20); + this.label5.TabIndex = 11; + this.label5.Text = "Command Line Switches"; + // + // noProbe1 + // + this.noProbe1.AutoSize = true; + this.noProbe1.Location = new System.Drawing.Point(359, 275); + this.noProbe1.Name = "noProbe1"; + this.noProbe1.Size = new System.Drawing.Size(68, 17); + this.noProbe1.TabIndex = 12; + this.noProbe1.Text = "-noprobe"; + this.toolTip1.SetToolTip(this.noProbe1, "disable hardware probe"); + this.noProbe1.UseVisualStyleBackColor = true; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(8, 415); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(0, 13); + this.label6.TabIndex = 14; + this.label6.Click += new System.EventHandler(this.label6_Click); + // + // multiple1 + // + this.multiple1.AutoSize = true; + this.multiple1.Location = new System.Drawing.Point(359, 185); + this.multiple1.Name = "multiple1"; + this.multiple1.Size = new System.Drawing.Size(64, 17); + this.multiple1.TabIndex = 15; + this.multiple1.Text = "-multiple"; + this.toolTip1.SetToolTip(this.multiple1, "allow multiple viewers"); + this.multiple1.UseVisualStyleBackColor = true; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))), System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label7.Location = new System.Drawing.Point(8, 396); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(338, 13); + this.label7.TabIndex = 16; + this.label7.Text = "Client Command Line String Used and Program Messages :"; + // + // noMultiple1 + // + this.noMultiple1.AutoSize = true; + this.noMultiple1.Location = new System.Drawing.Point(359, 260); + this.noMultiple1.Name = "noMultiple1"; + this.noMultiple1.Size = new System.Drawing.Size(76, 17); + this.noMultiple1.TabIndex = 17; + this.noMultiple1.Text = "-nomultiple"; + this.toolTip1.SetToolTip(this.noMultiple1, "block multiple viewers (secondlife.exe instances)"); + this.noMultiple1.UseVisualStyleBackColor = true; + // + // ignorepixeldepth1 + // + this.ignorepixeldepth1.AutoSize = true; + this.ignorepixeldepth1.Location = new System.Drawing.Point(359, 125); + this.ignorepixeldepth1.Name = "ignorepixeldepth1"; + this.ignorepixeldepth1.Size = new System.Drawing.Size(106, 17); + this.ignorepixeldepth1.TabIndex = 18; + this.ignorepixeldepth1.Text = "-ignorepixeldepth"; + this.toolTip1.SetToolTip(this.ignorepixeldepth1, "ignore pixel depth settings"); + this.ignorepixeldepth1.UseVisualStyleBackColor = true; + // + // nothread1 + // + this.nothread1.AutoSize = true; + this.nothread1.Location = new System.Drawing.Point(359, 305); + this.nothread1.Name = "nothread1"; + this.nothread1.Size = new System.Drawing.Size(71, 17); + this.nothread1.TabIndex = 19; + this.nothread1.Text = "-nothread"; + this.toolTip1.SetToolTip(this.nothread1, "run VFS (Virtual File System) in single thread"); + this.nothread1.UseVisualStyleBackColor = true; + // + // safe1 + // + this.safe1.AutoSize = true; + this.safe1.Location = new System.Drawing.Point(359, 365); + this.safe1.Name = "safe1"; + this.safe1.Size = new System.Drawing.Size(49, 17); + this.safe1.TabIndex = 20; + this.safe1.Text = "-safe"; + this.toolTip1.SetToolTip(this.safe1, "reset preferences, run in safe mode"); + this.safe1.UseVisualStyleBackColor = true; + // + // noconsole1 + // + this.noconsole1.AutoSize = true; + this.noconsole1.Location = new System.Drawing.Point(359, 215); + this.noconsole1.Name = "noconsole1"; + this.noconsole1.Size = new System.Drawing.Size(78, 17); + this.noconsole1.TabIndex = 21; + this.noconsole1.Text = "-noconsole"; + this.toolTip1.SetToolTip(this.noconsole1, "hide the console if not already hidden"); + this.noconsole1.UseVisualStyleBackColor = true; + // + // log1 + // + this.log1.AutoSize = true; + this.log1.Location = new System.Drawing.Point(359, 170); + this.log1.Name = "log1"; + this.log1.Size = new System.Drawing.Size(43, 17); + this.log1.TabIndex = 22; + this.log1.Text = "-log"; + this.toolTip1.SetToolTip(this.log1, "--no info avail--"); + this.log1.UseVisualStyleBackColor = true; + // + // helperuri1 + // + this.helperuri1.AutoSize = true; + this.helperuri1.Location = new System.Drawing.Point(359, 110); + this.helperuri1.Name = "helperuri1"; + this.helperuri1.Size = new System.Drawing.Size(69, 17); + this.helperuri1.TabIndex = 23; + this.helperuri1.Text = "-helperuri"; + this.toolTip1.SetToolTip(this.helperuri1, "--no info avail--"); + this.helperuri1.UseVisualStyleBackColor = true; + // + // autologin1 + // + this.autologin1.AutoSize = true; + this.autologin1.Location = new System.Drawing.Point(359, 65); + this.autologin1.Name = "autologin1"; + this.autologin1.Size = new System.Drawing.Size(75, 17); + this.autologin1.TabIndex = 24; + this.autologin1.Text = "--autologin"; + this.toolTip1.SetToolTip(this.autologin1, "--no info avail--"); + this.autologin1.UseVisualStyleBackColor = true; + // + // dialog1 + // + this.dialog1.AutoSize = true; + this.dialog1.Location = new System.Drawing.Point(359, 95); + this.dialog1.Name = "dialog1"; + this.dialog1.Size = new System.Drawing.Size(57, 17); + this.dialog1.TabIndex = 25; + this.dialog1.Text = "-dialog"; + this.toolTip1.SetToolTip(this.dialog1, "some arcane dialog box that is impossible to raise"); + this.dialog1.UseVisualStyleBackColor = true; + // + // previous1 + // + this.previous1.AutoSize = true; + this.previous1.Location = new System.Drawing.Point(359, 335); + this.previous1.Name = "previous1"; + this.previous1.Size = new System.Drawing.Size(69, 17); + this.previous1.TabIndex = 26; + this.previous1.Text = "-previous"; + this.toolTip1.SetToolTip(this.previous1, "--no info avail--"); + this.previous1.UseVisualStyleBackColor = true; + // + // simple1 + // + this.simple1.AutoSize = true; + this.simple1.Location = new System.Drawing.Point(359, 380); + this.simple1.Name = "simple1"; + this.simple1.Size = new System.Drawing.Size(58, 17); + this.simple1.TabIndex = 27; + this.simple1.Text = "-simple"; + this.toolTip1.SetToolTip(this.simple1, "--no info avail--"); + this.simple1.UseVisualStyleBackColor = true; + // + // noinvlib1 + // + this.noinvlib1.AutoSize = true; + this.noinvlib1.Location = new System.Drawing.Point(359, 245); + this.noinvlib1.Name = "noinvlib1"; + this.noinvlib1.Size = new System.Drawing.Size(65, 17); + this.noinvlib1.TabIndex = 28; + this.noinvlib1.Text = "-noinvlib"; + this.toolTip1.SetToolTip(this.noinvlib1, "do not request inventory library"); + this.noinvlib1.UseVisualStyleBackColor = true; + // + // debugst1 + // + this.debugst1.AutoSize = true; + this.debugst1.Location = new System.Drawing.Point(359, 80); + this.debugst1.Name = "debugst1"; + this.debugst1.Size = new System.Drawing.Size(67, 17); + this.debugst1.TabIndex = 30; + this.debugst1.Text = "-debugst"; + this.toolTip1.SetToolTip(this.debugst1, "debug mask"); + this.debugst1.UseVisualStyleBackColor = true; + // + // spanish1 + // + this.spanish1.AutoSize = true; + this.spanish1.Location = new System.Drawing.Point(359, 395); + this.spanish1.Name = "spanish1"; + this.spanish1.Size = new System.Drawing.Size(65, 17); + this.spanish1.TabIndex = 31; + this.spanish1.Text = "-spanish"; + this.toolTip1.SetToolTip(this.spanish1, "activate (incomplete) Spanish UI translation"); + this.spanish1.UseVisualStyleBackColor = true; + // + // korean1 + // + this.korean1.AutoSize = true; + this.korean1.Location = new System.Drawing.Point(359, 140); + this.korean1.Name = "korean1"; + this.korean1.Size = new System.Drawing.Size(62, 17); + this.korean1.TabIndex = 32; + this.korean1.Text = "-korean"; + this.toolTip1.SetToolTip(this.korean1, "activate (incomplete) Korean UI translation"); + this.korean1.UseVisualStyleBackColor = true; + // + // local1 + // + this.local1.AutoSize = true; + this.local1.Location = new System.Drawing.Point(359, 155); + this.local1.Name = "local1"; + this.local1.Size = new System.Drawing.Size(51, 17); + this.local1.TabIndex = 46; + this.local1.Text = "-local"; + this.toolTip1.SetToolTip(this.local1, "run without simulator"); + this.local1.UseVisualStyleBackColor = true; + // + // purge1 + // + this.purge1.AutoSize = true; + this.purge1.Location = new System.Drawing.Point(359, 350); + this.purge1.Name = "purge1"; + this.purge1.Size = new System.Drawing.Size(56, 17); + this.purge1.TabIndex = 56; + this.purge1.Text = "-purge"; + this.toolTip1.SetToolTip(this.purge1, "delete files in cache"); + this.purge1.UseVisualStyleBackColor = true; + // + // nofmod1 + // + this.nofmod1.AutoSize = true; + this.nofmod1.Location = new System.Drawing.Point(359, 230); + this.nofmod1.Name = "nofmod1"; + this.nofmod1.Size = new System.Drawing.Size(64, 17); + this.nofmod1.TabIndex = 45; + this.nofmod1.Text = "-nofmod"; + this.toolTip1.SetToolTip(this.nofmod1, "FMOD is the API used to distort sound while moving"); + this.nofmod1.UseVisualStyleBackColor = true; + // + // noaudio1 + // + this.noaudio1.AutoSize = true; + this.noaudio1.Location = new System.Drawing.Point(359, 200); + this.noaudio1.Name = "noaudio1"; + this.noaudio1.Size = new System.Drawing.Size(67, 17); + this.noaudio1.TabIndex = 44; + this.noaudio1.Text = "-noaudio"; + this.toolTip1.SetToolTip(this.noaudio1, "no audio, different from -nosound?"); + this.noaudio1.UseVisualStyleBackColor = true; + // + // nosound1 + // + this.nosound1.AutoSize = true; + this.nosound1.Location = new System.Drawing.Point(359, 290); + this.nosound1.Name = "nosound1"; + this.nosound1.Size = new System.Drawing.Size(70, 17); + this.nosound1.TabIndex = 55; + this.nosound1.Text = "-nosound"; + this.toolTip1.SetToolTip(this.nosound1, "no sound, different from -noaudio?"); + this.nosound1.UseVisualStyleBackColor = true; + // + // url1 + // + this.url1.AutoSize = true; + this.url1.Location = new System.Drawing.Point(488, 245); + this.url1.Name = "url1"; + this.url1.Size = new System.Drawing.Size(40, 17); + this.url1.TabIndex = 43; + this.url1.Text = "-url"; + this.toolTip1.SetToolTip(this.url1, "handles secondlife://sim/x/y/z URLs"); + this.url1.UseVisualStyleBackColor = true; + // + // port1 + // + this.port1.AutoSize = true; + this.port1.Location = new System.Drawing.Point(488, 171); + this.port1.Name = "port1"; + this.port1.Size = new System.Drawing.Size(47, 17); + this.port1.TabIndex = 49; + this.port1.Text = "-port"; + this.toolTip1.SetToolTip(this.port1, "Set the TCP port for the client; useful to run multiple instances of SL on the sa" + + "me local home network. Values that may work: 13000 and 13001 (Valid numbers are " + + "13000 to 13050)"); + this.port1.UseVisualStyleBackColor = true; + // + // simBox1 + // + this.simBox1.Location = new System.Drawing.Point(549, 243); + this.simBox1.Name = "simBox1"; + this.simBox1.Size = new System.Drawing.Size(344, 20); + this.simBox1.TabIndex = 66; + this.simBox1.Text = "secondlife://lutra/127/128/60"; + this.toolTip1.SetToolTip(this.simBox1, "type URL here"); + // + // portBox1 + // + this.portBox1.Location = new System.Drawing.Point(549, 169); + this.portBox1.Name = "portBox1"; + this.portBox1.Size = new System.Drawing.Size(58, 20); + this.portBox1.TabIndex = 67; + this.portBox1.Text = "13000"; + this.toolTip1.SetToolTip(this.portBox1, "enter port number here"); + // + // user1 + // + this.user1.AutoSize = true; + this.user1.Location = new System.Drawing.Point(488, 191); + this.user1.Name = "user1"; + this.user1.Size = new System.Drawing.Size(49, 17); + this.user1.TabIndex = 42; + this.user1.Text = "-user"; + this.user1.ThreeState = true; + this.toolTip1.SetToolTip(this.user1, "specify user server in dotted quad"); + this.user1.UseVisualStyleBackColor = true; + // + // quitAfter1 + // + this.quitAfter1.AutoSize = true; + this.quitAfter1.Location = new System.Drawing.Point(680, 65); + this.quitAfter1.Name = "quitAfter1"; + this.quitAfter1.Size = new System.Drawing.Size(67, 17); + this.quitAfter1.TabIndex = 41; + this.quitAfter1.Text = "-quitafter"; + this.toolTip1.SetToolTip(this.quitAfter1, "SL quits after elapsed time in seconds"); + this.quitAfter1.UseVisualStyleBackColor = true; + // + // techTag1 + // + this.techTag1.AutoSize = true; + this.techTag1.Location = new System.Drawing.Point(488, 211); + this.techTag1.Name = "techTag1"; + this.techTag1.Size = new System.Drawing.Size(65, 17); + this.techTag1.TabIndex = 47; + this.techTag1.Text = "-techtag"; + this.toolTip1.SetToolTip(this.techTag1, "unknown (but requires a parameter)"); + this.techTag1.UseVisualStyleBackColor = true; + // + // yield1 + // + this.yield1.AutoSize = true; + this.yield1.Location = new System.Drawing.Point(488, 91); + this.yield1.Name = "yield1"; + this.yield1.Size = new System.Drawing.Size(50, 17); + this.yield1.TabIndex = 48; + this.yield1.Text = "-yield"; + this.toolTip1.SetToolTip(this.yield1, "yield some idle time to local host (changed from - cooperative)"); + this.yield1.UseVisualStyleBackColor = true; + // + // logfile1 + // + this.logfile1.AutoSize = true; + this.logfile1.Location = new System.Drawing.Point(680, 125); + this.logfile1.Name = "logfile1"; + this.logfile1.Size = new System.Drawing.Size(56, 17); + this.logfile1.TabIndex = 54; + this.logfile1.Text = "-logfile"; + this.toolTip1.SetToolTip(this.logfile1, "change the log filename"); + this.logfile1.UseVisualStyleBackColor = true; + // + // settings1 + // + this.settings1.AutoSize = true; + this.settings1.Location = new System.Drawing.Point(680, 95); + this.settings1.Name = "settings1"; + this.settings1.Size = new System.Drawing.Size(65, 17); + this.settings1.TabIndex = 53; + this.settings1.Text = "-settings"; + this.toolTip1.SetToolTip(this.settings1, "specify configuration filename; default is \"settings.ini\""); + this.settings1.UseVisualStyleBackColor = true; + // + // outbw1 + // + this.outbw1.AutoSize = true; + this.outbw1.Location = new System.Drawing.Point(488, 111); + this.outbw1.Name = "outbw1"; + this.outbw1.Size = new System.Drawing.Size(58, 17); + this.outbw1.TabIndex = 52; + this.outbw1.Text = "-outbw"; + this.toolTip1.SetToolTip(this.outbw1, "set outgoing bandwidth"); + this.outbw1.UseVisualStyleBackColor = true; + // + // inbw1 + // + this.inbw1.AutoSize = true; + this.inbw1.Location = new System.Drawing.Point(488, 131); + this.inbw1.Name = "inbw1"; + this.inbw1.Size = new System.Drawing.Size(51, 17); + this.inbw1.TabIndex = 51; + this.inbw1.Text = "-inbw"; + this.toolTip1.SetToolTip(this.inbw1, "set incoming bandwidth"); + this.inbw1.UseVisualStyleBackColor = true; + // + // drop1 + // + this.drop1.AutoSize = true; + this.drop1.Location = new System.Drawing.Point(488, 151); + this.drop1.Name = "drop1"; + this.drop1.Size = new System.Drawing.Size(50, 17); + this.drop1.TabIndex = 50; + this.drop1.Text = "-drop"; + this.toolTip1.SetToolTip(this.drop1, "drop number% of incoming network packets"); + this.drop1.UseVisualStyleBackColor = true; + // + // dropBox1 + // + this.dropBox1.Location = new System.Drawing.Point(549, 149); + this.dropBox1.Name = "dropBox1"; + this.dropBox1.Size = new System.Drawing.Size(58, 20); + this.dropBox1.TabIndex = 68; + this.dropBox1.Text = "0"; + this.toolTip1.SetToolTip(this.dropBox1, "enter percent of packets to drop"); + // + // inbwBox1 + // + this.inbwBox1.Location = new System.Drawing.Point(549, 129); + this.inbwBox1.Name = "inbwBox1"; + this.inbwBox1.Size = new System.Drawing.Size(57, 20); + this.inbwBox1.TabIndex = 69; + this.toolTip1.SetToolTip(this.inbwBox1, "enter incoming cap"); + // + // outbwBox1 + // + this.outbwBox1.Location = new System.Drawing.Point(549, 109); + this.outbwBox1.Name = "outbwBox1"; + this.outbwBox1.Size = new System.Drawing.Size(58, 20); + this.outbwBox1.TabIndex = 70; + this.toolTip1.SetToolTip(this.outbwBox1, "enter outgoing cap"); + // + // settingsBox1 + // + this.settingsBox1.Location = new System.Drawing.Point(741, 93); + this.settingsBox1.Name = "settingsBox1"; + this.settingsBox1.Size = new System.Drawing.Size(152, 20); + this.settingsBox1.TabIndex = 71; + this.settingsBox1.Text = "settings.ini"; + this.toolTip1.SetToolTip(this.settingsBox1, "enter settings file name"); + // + // logfileBox1 + // + this.logfileBox1.Location = new System.Drawing.Point(733, 123); + this.logfileBox1.Name = "logfileBox1"; + this.logfileBox1.Size = new System.Drawing.Size(160, 20); + this.logfileBox1.TabIndex = 72; + this.logfileBox1.Text = "mylogfile.txt"; + this.toolTip1.SetToolTip(this.logfileBox1, "enter log file name here"); + // + // yieldBox1 + // + this.yieldBox1.Location = new System.Drawing.Point(549, 89); + this.yieldBox1.Name = "yieldBox1"; + this.yieldBox1.Size = new System.Drawing.Size(58, 20); + this.yieldBox1.TabIndex = 73; + this.toolTip1.SetToolTip(this.yieldBox1, "enter time to yield in "); + // + // techtagBox1 + // + this.techtagBox1.Location = new System.Drawing.Point(549, 209); + this.techtagBox1.Name = "techtagBox1"; + this.techtagBox1.Size = new System.Drawing.Size(58, 20); + this.techtagBox1.TabIndex = 74; + this.toolTip1.SetToolTip(this.techtagBox1, "enter unknown param here"); + // + // quitafterBox1 + // + this.quitafterBox1.Location = new System.Drawing.Point(745, 63); + this.quitafterBox1.Name = "quitafterBox1"; + this.quitafterBox1.Size = new System.Drawing.Size(148, 20); + this.quitafterBox1.TabIndex = 75; + this.toolTip1.SetToolTip(this.quitafterBox1, "enter time in seconds"); + // + // comboBox1 + // + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "agni", + "colo", + "dmz", + "durga", + "siva"}); + this.comboBox1.Location = new System.Drawing.Point(549, 189); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(58, 21); + this.comboBox1.TabIndex = 76; + this.comboBox1.Text = "agni"; + this.toolTip1.SetToolTip(this.comboBox1, "select LL user server"); + // + // loginuri1 + // + this.loginuri1.AutoSize = true; + this.loginuri1.Location = new System.Drawing.Point(488, 275); + this.loginuri1.Name = "loginuri1"; + this.loginuri1.Size = new System.Drawing.Size(62, 17); + this.loginuri1.TabIndex = 77; + this.loginuri1.Text = "-loginuri"; + this.toolTip1.SetToolTip(this.loginuri1, "login server and CGI script to use"); + this.loginuri1.UseVisualStyleBackColor = true; + // + // loginuriBox1 + // + this.loginuriBox1.Location = new System.Drawing.Point(549, 273); + this.loginuriBox1.Name = "loginuriBox1"; + this.loginuriBox1.Size = new System.Drawing.Size(344, 20); + this.loginuriBox1.TabIndex = 78; + this.loginuriBox1.Text = "localhost:9000"; + this.toolTip1.SetToolTip(this.loginuriBox1, "enter login url here"); + // + // set1 + // + this.set1.AutoSize = true; + this.set1.Location = new System.Drawing.Point(636, 185); + this.set1.Name = "set1"; + this.set1.Size = new System.Drawing.Size(43, 17); + this.set1.TabIndex = 79; + this.set1.Text = "-set"; + this.toolTip1.SetToolTip(this.set1, "specify value of a particular configuration variable; can be used multiple times " + + "in a single command-line"); + this.set1.UseVisualStyleBackColor = true; + // + // setBox1 + // + this.setBox1.Location = new System.Drawing.Point(680, 183); + this.setBox1.Name = "setBox1"; + this.setBox1.Size = new System.Drawing.Size(213, 20); + this.setBox1.TabIndex = 80; + this.setBox1.Text = "SystemLanguage en-us"; + this.toolTip1.SetToolTip(this.setBox1, "enter params"); + // + // errmask1 + // + this.errmask1.AutoSize = true; + this.errmask1.Location = new System.Drawing.Point(636, 154); + this.errmask1.Name = "errmask1"; + this.errmask1.Size = new System.Drawing.Size(66, 17); + this.errmask1.TabIndex = 81; + this.errmask1.Text = "-errmask"; + this.toolTip1.SetToolTip(this.errmask1, "32-bit bitmask for error type mask"); + this.errmask1.UseVisualStyleBackColor = true; + // + // skin1 + // + this.skin1.AutoSize = true; + this.skin1.Location = new System.Drawing.Point(635, 215); + this.skin1.Name = "skin1"; + this.skin1.Size = new System.Drawing.Size(48, 17); + this.skin1.TabIndex = 82; + this.skin1.Text = "-skin"; + this.toolTip1.SetToolTip(this.skin1, "load skins//skin.xml as the default UI appearance (incomplete)"); + this.skin1.UseVisualStyleBackColor = true; + // + // login1 + // + this.login1.AutoSize = true; + this.login1.Location = new System.Drawing.Point(457, 304); + this.login1.Name = "login1"; + this.login1.Size = new System.Drawing.Size(51, 17); + this.login1.TabIndex = 83; + this.login1.Text = "-login"; + this.toolTip1.SetToolTip(this.login1, "log in as a user"); + this.login1.UseVisualStyleBackColor = true; + // + // errmaskBox1 + // + this.errmaskBox1.Location = new System.Drawing.Point(704, 153); + this.errmaskBox1.Name = "errmaskBox1"; + this.errmaskBox1.Size = new System.Drawing.Size(189, 20); + this.errmaskBox1.TabIndex = 84; + this.toolTip1.SetToolTip(this.errmaskBox1, "32-bit bitmask for error type mask"); + // + // skinBox1 + // + this.skinBox1.Location = new System.Drawing.Point(679, 213); + this.skinBox1.Name = "skinBox1"; + this.skinBox1.Size = new System.Drawing.Size(214, 20); + this.skinBox1.TabIndex = 85; + this.skinBox1.Text = "C://Secondlife//"; + this.toolTip1.SetToolTip(this.skinBox1, "enter directory where skin.xml is"); + // + // firstBox1 + // + this.firstBox1.Location = new System.Drawing.Point(549, 303); + this.firstBox1.Name = "firstBox1"; + this.firstBox1.Size = new System.Drawing.Size(80, 20); + this.firstBox1.TabIndex = 86; + this.firstBox1.Text = "Test"; + this.toolTip1.SetToolTip(this.firstBox1, "firstname"); + // + // lastBox1 + // + this.lastBox1.Location = new System.Drawing.Point(668, 303); + this.lastBox1.Name = "lastBox1"; + this.lastBox1.Size = new System.Drawing.Size(80, 20); + this.lastBox1.TabIndex = 92; + this.lastBox1.Text = "User"; + this.toolTip1.SetToolTip(this.lastBox1, "lastname"); + // + // noutc1 + // + this.noutc1.AutoSize = true; + this.noutc1.Location = new System.Drawing.Point(359, 320); + this.noutc1.Name = "noutc1"; + this.noutc1.Size = new System.Drawing.Size(56, 17); + this.noutc1.TabIndex = 29; + this.noutc1.Text = "-noutc"; + this.toolTip1.SetToolTip(this.noutc1, "logs in local time, not UTC"); + this.noutc1.UseVisualStyleBackColor = true; + // + // passBox1 + // + this.passBox1.Location = new System.Drawing.Point(790, 303); + this.passBox1.Name = "passBox1"; + this.passBox1.Size = new System.Drawing.Size(103, 20); + this.passBox1.TabIndex = 93; + this.passBox1.Text = "test"; + this.toolTip1.SetToolTip(this.passBox1, "password"); + // + // raw1 + // + this.raw1.AutoSize = true; + this.raw1.Location = new System.Drawing.Point(457, 336); + this.raw1.Name = "raw1"; + this.raw1.Size = new System.Drawing.Size(81, 17); + this.raw1.TabIndex = 94; + this.raw1.Text = "Raw CMD :"; + this.toolTip1.SetToolTip(this.raw1, "Raw CMD options, may crash everything"); + this.raw1.UseVisualStyleBackColor = true; + // + // rawBox1 + // + this.rawBox1.Location = new System.Drawing.Point(549, 333); + this.rawBox1.Name = "rawBox1"; + this.rawBox1.Size = new System.Drawing.Size(344, 20); + this.rawBox1.TabIndex = 95; + this.toolTip1.SetToolTip(this.rawBox1, "Raw CMD options, may crash everything"); + // + // clear1 + // + this.clear1.Location = new System.Drawing.Point(178, 366); + this.clear1.Name = "clear1"; + this.clear1.Size = new System.Drawing.Size(80, 23); + this.clear1.TabIndex = 96; + this.clear1.Text = "Clear"; + this.toolTip1.SetToolTip(this.clear1, "clear all switch boxes"); + this.clear1.UseVisualStyleBackColor = true; + this.clear1.Click += new System.EventHandler(this.clear1_Click); + // + // nataddress1 + // + this.nataddress1.Location = new System.Drawing.Point(457, 389); + this.nataddress1.Name = "nataddress1"; + this.nataddress1.Size = new System.Drawing.Size(436, 20); + this.nataddress1.TabIndex = 58; + this.nataddress1.Text = "UNUSED ATM"; + this.nataddress1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))), System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label8.Location = new System.Drawing.Point(588, 360); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(175, 20); + this.label8.TabIndex = 59; + this.label8.Text = "World/NAT Address :"; + // + // label9 + // + this.label9.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))), System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label9.Location = new System.Drawing.Point(633, 27); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(47, 20); + this.label9.TabIndex = 60; + this.label9.Text = "Path :"; + this.label9.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // exeBox1 + // + this.exeBox1.Location = new System.Drawing.Point(530, 27); + this.exeBox1.Name = "exeBox1"; + this.exeBox1.Size = new System.Drawing.Size(100, 20); + this.exeBox1.TabIndex = 61; + this.exeBox1.Text = "Secondlife.exe"; + // + // label10 + // + this.label10.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))), System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label10.Location = new System.Drawing.Point(392, 27); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(138, 20); + this.label10.TabIndex = 62; + this.label10.Text = "Executable Name :"; + this.label10.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(514, 306); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(32, 13); + this.label11.TabIndex = 89; + this.label11.Text = "First :"; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(632, 306); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(33, 13); + this.label12.TabIndex = 90; + this.label12.Text = "Last :"; + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(751, 306); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(36, 13); + this.label13.TabIndex = 91; + this.label13.Text = "Pass :"; + // + // Main + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(900, 431); + this.Controls.Add(this.clear1); + this.Controls.Add(this.rawBox1); + this.Controls.Add(this.raw1); + this.Controls.Add(this.passBox1); + this.Controls.Add(this.lastBox1); + this.Controls.Add(this.label13); + this.Controls.Add(this.label12); + this.Controls.Add(this.label11); + this.Controls.Add(this.firstBox1); + this.Controls.Add(this.skinBox1); + this.Controls.Add(this.errmaskBox1); + this.Controls.Add(this.login1); + this.Controls.Add(this.skin1); + this.Controls.Add(this.errmask1); + this.Controls.Add(this.setBox1); + this.Controls.Add(this.set1); + this.Controls.Add(this.loginuriBox1); + this.Controls.Add(this.loginuri1); + this.Controls.Add(this.comboBox1); + this.Controls.Add(this.quitafterBox1); + this.Controls.Add(this.techtagBox1); + this.Controls.Add(this.yieldBox1); + this.Controls.Add(this.logfileBox1); + this.Controls.Add(this.settingsBox1); + this.Controls.Add(this.outbwBox1); + this.Controls.Add(this.inbwBox1); + this.Controls.Add(this.dropBox1); + this.Controls.Add(this.portBox1); + this.Controls.Add(this.simBox1); + this.Controls.Add(this.label10); + this.Controls.Add(this.exeBox1); + this.Controls.Add(this.label9); + this.Controls.Add(this.label8); + this.Controls.Add(this.nataddress1); + this.Controls.Add(this.purge1); + this.Controls.Add(this.nosound1); + this.Controls.Add(this.logfile1); + this.Controls.Add(this.settings1); + this.Controls.Add(this.outbw1); + this.Controls.Add(this.inbw1); + this.Controls.Add(this.drop1); + this.Controls.Add(this.port1); + this.Controls.Add(this.yield1); + this.Controls.Add(this.techTag1); + this.Controls.Add(this.local1); + this.Controls.Add(this.nofmod1); + this.Controls.Add(this.noaudio1); + this.Controls.Add(this.url1); + this.Controls.Add(this.user1); + this.Controls.Add(this.quitAfter1); + this.Controls.Add(this.korean1); + this.Controls.Add(this.spanish1); + this.Controls.Add(this.debugst1); + this.Controls.Add(this.noutc1); + this.Controls.Add(this.noinvlib1); + this.Controls.Add(this.simple1); + this.Controls.Add(this.previous1); + this.Controls.Add(this.dialog1); + this.Controls.Add(this.autologin1); + this.Controls.Add(this.helperuri1); + this.Controls.Add(this.log1); + this.Controls.Add(this.noconsole1); + this.Controls.Add(this.safe1); + this.Controls.Add(this.nothread1); + this.Controls.Add(this.ignorepixeldepth1); + this.Controls.Add(this.noMultiple1); + this.Controls.Add(this.label7); + this.Controls.Add(this.multiple1); + this.Controls.Add(this.label6); + this.Controls.Add(this.noProbe1); + this.Controls.Add(this.label5); + this.Controls.Add(this.Launch1); + this.Controls.Add(this.clientBox1); + this.Controls.Add(this.rbGridServer); + this.Controls.Add(this.rbStandAloneMode); + this.Controls.Add(this.rbGridRegionMode); + this.Controls.Add(this.btnStop); + this.Controls.Add(this.btnStart); + this.Controls.Add(this.gbLog); + this.Controls.Add(this.menuStrip1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D; + this.MainMenuStrip = this.menuStrip1; + this.MaximizeBox = false; + this.Name = "Main"; + this.Text = "OpenSim"; + this.toolTip1.SetToolTip(this, "logs in local time, not UTC"); + this.Load += new System.EventHandler(this.Main_Load); + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.gbLog.ResumeLayout(false); + this.tabLogs.ResumeLayout(false); + this.tabMainLog.ResumeLayout(false); + this.tabMainLog.PerformLayout(); + this.tabRegionServer.ResumeLayout(false); + this.tabRegionServer.PerformLayout(); + this.tabUserServer.ResumeLayout(false); + this.tabUserServer.PerformLayout(); + this.tabAssetServer.ResumeLayout(false); + this.tabAssetServer.PerformLayout(); + this.tabGridServer.ResumeLayout(false); + this.tabGridServer.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.Timer timer1; + private System.Windows.Forms.TextBox clientBox1; + private System.Windows.Forms.Button btnStart; + private System.Windows.Forms.Button btnStop; + private System.Windows.Forms.RadioButton rbGridRegionMode; + private System.Windows.Forms.RadioButton rbStandAloneMode; + private System.Windows.Forms.RadioButton rbGridServer; + private System.Windows.Forms.Button Launch1; + private System.Windows.Forms.GroupBox gbLog; + private System.Windows.Forms.TabControl tabLogs; + private System.Windows.Forms.TabPage tabMainLog; + private System.Windows.Forms.TabPage tabRegionServer; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox txtOpenSim; + private System.Windows.Forms.TabPage tabUserServer; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox txtUserServer; + private System.Windows.Forms.TabPage tabAssetServer; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox txtAssetServer; + private System.Windows.Forms.TabPage tabGridServer; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox txtGridServer; + private System.Windows.Forms.TextBox txtMainLog; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.CheckBox noProbe1; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.CheckBox multiple1; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.CheckBox noMultiple1; + private System.Windows.Forms.CheckBox ignorepixeldepth1; + private System.Windows.Forms.CheckBox nothread1; + private System.Windows.Forms.CheckBox safe1; + private System.Windows.Forms.CheckBox noconsole1; + private System.Windows.Forms.CheckBox log1; + private System.Windows.Forms.CheckBox helperuri1; + private System.Windows.Forms.CheckBox autologin1; + private System.Windows.Forms.ToolTip toolTip1; + private System.Windows.Forms.CheckBox dialog1; + private System.Windows.Forms.CheckBox previous1; + private System.Windows.Forms.CheckBox simple1; + private System.Windows.Forms.CheckBox noinvlib1; + private System.Windows.Forms.CheckBox noutc1; + private System.Windows.Forms.CheckBox debugst1; + private System.Windows.Forms.CheckBox spanish1; + private System.Windows.Forms.CheckBox korean1; + private System.Windows.Forms.CheckBox local1; + private System.Windows.Forms.CheckBox nofmod1; + private System.Windows.Forms.CheckBox noaudio1; + private System.Windows.Forms.CheckBox url1; + private System.Windows.Forms.CheckBox user1; + private System.Windows.Forms.CheckBox quitAfter1; + private System.Windows.Forms.CheckBox techTag1; + private System.Windows.Forms.CheckBox yield1; + private System.Windows.Forms.CheckBox purge1; + private System.Windows.Forms.CheckBox nosound1; + private System.Windows.Forms.CheckBox logfile1; + private System.Windows.Forms.CheckBox settings1; + private System.Windows.Forms.CheckBox outbw1; + private System.Windows.Forms.CheckBox inbw1; + private System.Windows.Forms.CheckBox drop1; + private System.Windows.Forms.CheckBox port1; + private System.Windows.Forms.TextBox nataddress1; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.TextBox exeBox1; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.TextBox simBox1; + private System.Windows.Forms.TextBox portBox1; + private System.Windows.Forms.TextBox dropBox1; + private System.Windows.Forms.TextBox inbwBox1; + private System.Windows.Forms.TextBox outbwBox1; + private System.Windows.Forms.TextBox settingsBox1; + private System.Windows.Forms.TextBox logfileBox1; + private System.Windows.Forms.TextBox yieldBox1; + private System.Windows.Forms.TextBox techtagBox1; + private System.Windows.Forms.TextBox quitafterBox1; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.CheckBox loginuri1; + private System.Windows.Forms.TextBox loginuriBox1; + private System.Windows.Forms.CheckBox set1; + private System.Windows.Forms.TextBox setBox1; + private System.Windows.Forms.CheckBox errmask1; + private System.Windows.Forms.CheckBox skin1; + private System.Windows.Forms.CheckBox login1; + private System.Windows.Forms.TextBox errmaskBox1; + private System.Windows.Forms.TextBox skinBox1; + private System.Windows.Forms.TextBox firstBox1; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.TextBox lastBox1; + private System.Windows.Forms.TextBox passBox1; + private InputTextBoxControl txtInputUserServer; + private InputTextBoxControl txtInputAssetServer; + private InputTextBoxControl txtInputRegionServer; + private InputTextBoxControl txtInputGridServer; + private System.Windows.Forms.CheckBox raw1; + private System.Windows.Forms.TextBox rawBox1; + private System.Windows.Forms.Button clear1; + } +} + diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/Main.cs b/trunk/OpenSim/Tools/OpenSim.GUI/Main.cs new file mode 100644 index 0000000000..24e7baea15 --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/Main.cs @@ -0,0 +1,537 @@ +/* +* 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; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace OpenSim.GUI +{ + public partial class Main : Form + { + + public ProcessManager proc_OpenSim; + public ProcessManager proc_UserServer; + public ProcessManager proc_GridServer; + public ProcessManager proc_AssetServer; + + public Main() + { + InitializeComponent(); + } + + private void Main_Load(object sender, EventArgs e) + { + txtInputUserServer.KeyPress += new KeyPressEventHandler(txtInputUserServer_KeyPress); + txtInputGridServer.KeyPress += new KeyPressEventHandler(txtInputGridServer_KeyPress); + txtInputAssetServer.KeyPress += new KeyPressEventHandler(txtInputAssetServer_KeyPress); + txtInputRegionServer.KeyPress += new KeyPressEventHandler(txtInputRegionServer_KeyPress); + + tabLogs.Selected += new TabControlEventHandler(tabLogs_Selected); + + UpdateTabVisibility(); + } + + void tabLogs_Selected(object sender, TabControlEventArgs e) + { + if (e.TabPage == tabUserServer) + txtInputUserServer.Focus(); + if (e.TabPage == tabGridServer) + txtInputGridServer.Focus(); + if (e.TabPage == tabAssetServer) + txtInputAssetServer.Focus(); + if (e.TabPage == tabRegionServer) + txtInputRegionServer.Focus(); + } + + void txtInputUserServer_KeyPress(object sender, KeyPressEventArgs e) + { + + if (e.KeyChar == 13) + { + // We got a command + e.Handled = true; + proc_UserServer.StandardInput.WriteLine(txtInputUserServer.Text + "\r\n"); + txtInputUserServer.Text = ""; + } + } + + void txtInputGridServer_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar == 13) + { + // We got a command + e.Handled = true; + proc_GridServer.StandardInput.WriteLine(txtInputGridServer.Text + "\r\n"); + txtInputGridServer.Text = ""; + } + } + + void txtInputAssetServer_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar == 13) + { + // We got a command + e.Handled = true; + proc_AssetServer.StandardInput.WriteLine(txtInputAssetServer.Text + "\r\n"); + txtInputAssetServer.Text = ""; + } + } + + void txtInputRegionServer_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar == 13) + { + // We got a command + e.Handled = true; + proc_OpenSim.StandardInput.WriteLine(txtInputRegionServer.Text + "\r\n"); + txtInputRegionServer.Text = ""; + } + } + + private void btnStart_Click(object sender, EventArgs e) + { + noProbe1.Checked = true; + multiple1.Checked = true; + loginuri1.Checked = true; + login1.Checked = true; + // + // THIS PART NEEDS TO BE MOVED TO A SEPARATE THREAD OR A TIMER OF SOME SORT + // should not block on wait + // ALSO - IF SOME SERVICES ARE NOT CONFIGURED, POP UP CONFIGURATION BOX FOR THAT SERVICE! + // + + btnStart.Enabled = false; + btnStop.Enabled = false; + + + + if (rbGridServer.Checked) + { + // Start UserServer + proc_UserServer = new ProcessManager("OpenSim.Grid.UserServer.exe", ""); + txtMainLog.AppendText("Starting: User server" + "\r\n"); + proc_UserServer.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_UserServer_DataReceived); + proc_UserServer.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_UserServer_DataReceived); + proc_UserServer.StartProcess(); + System.Threading.Thread.Sleep(3000); + + // Start GridServer + proc_GridServer = new ProcessManager("OpenSim.Grid.GridServer.exe", ""); + txtMainLog.AppendText("Starting: Grid server" + "\r\n"); + proc_GridServer.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_GridServer_DataReceived); + proc_GridServer.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_GridServer_DataReceived); + proc_GridServer.StartProcess(); + System.Threading.Thread.Sleep(3000); + + // Start AssetServer + proc_AssetServer = new ProcessManager("OpenSim.Grid.AssetServer.exe", ""); + txtMainLog.AppendText("Starting: Asset server" + "\r\n"); + proc_AssetServer.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_AssetServer_DataReceived); + proc_AssetServer.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_AssetServer_DataReceived); + proc_AssetServer.StartProcess(); + System.Threading.Thread.Sleep(3000); + } + + // Start OpenSim + string p = ""; + if (rbGridServer.Checked) + p = "-gridmode=true"; + + proc_OpenSim = new ProcessManager("OpenSim.EXE", p); + txtMainLog.AppendText("Starting: OpenSim (Region server)" + "\r\n"); + proc_OpenSim.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_OpenSim_DataReceived); + proc_OpenSim.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_OpenSim_DataReceived); + proc_OpenSim.StartProcess(); + + btnStart.Enabled = false; + btnStop.Enabled = true; + + } + public delegate void AppendText(string Text); + void proc_UserServer_DataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) + { + this.Invoke(new AppendText(txtUserServer.AppendText), new object[] { e.Data + "\r\n" }); + this.Invoke(new AppendText(txtMainLog.AppendText), new object[] { "UserServer: " + e.Data + "\r\n" }); + } + void proc_GridServer_DataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) + { + this.Invoke(new AppendText(txtGridServer.AppendText), new object[] { e.Data + "\r\n" }); + this.Invoke(new AppendText(txtMainLog.AppendText), new object[] { "GridServer: " + e.Data + "\r\n" }); + } + void proc_AssetServer_DataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) + { + this.Invoke(new AppendText(txtAssetServer.AppendText), new object[] { e.Data + "\r\n" }); + this.Invoke(new AppendText(txtMainLog.AppendText), new object[] { "AssetServer: " + e.Data + "\r\n" }); + } + void proc_OpenSim_DataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) + { + this.Invoke(new AppendText(txtOpenSim.AppendText), new object[] { e.Data + "\r\n" }); + this.Invoke(new AppendText(txtMainLog.AppendText), new object[] { "OpenSim: " + e.Data + "\r\n" }); + } + + private void btnStop_Click(object sender, EventArgs e) + { + btnStart.Enabled = false; + btnStop.Enabled = false; + Stop(); + btnStart.Enabled = true; + btnStop.Enabled = false; + } + + private void clear1_Click(object sender, EventArgs e) + { + noProbe1.Checked = false; multiple1.Checked = false; loginuri1.Checked = false; + noMultiple1.Checked = false; korean1.Checked = false; spanish1.Checked = false; + ignorepixeldepth1.Checked = false; nothread1.Checked = false; safe1.Checked = false; + noconsole1.Checked = false; log1.Checked = false; helperuri1.Checked = false; + autologin1.Checked = false; dialog1.Checked = false; previous1.Checked = false; + simple1.Checked = false; noinvlib1.Checked = false; noutc1.Checked = false; + debugst1.Checked = false; local1.Checked = false; purge1.Checked = false; + nofmod1.Checked = false; nosound1.Checked = false; noaudio1.Checked = false; + url1.Checked = false; port1.Checked = false; drop1.Checked = false; + inbw1.Checked = false; outbw1.Checked = false; settings1.Checked = false; + logfile1.Checked = false; yield1.Checked = false; techTag1.Checked = false; + quitAfter1.Checked = false; loginuri1.Checked = false; set1.Checked = false; + errmask1.Checked = false; raw1.Checked = false; skin1.Checked = false; + user1.Checked = false; login1.Checked = false; + } + + private void Stop() + { + if (proc_UserServer != null) + { + txtMainLog.AppendText("Shutting down UserServer. CPU time used: " + proc_UserServer.TotalProcessorTime.ToString() + "\r\n"); + proc_UserServer.StopProcess(); + proc_UserServer = null; + } + if (proc_GridServer != null) + { + txtMainLog.AppendText("Shutting down GridServer. CPU time used: " + proc_GridServer.TotalProcessorTime.ToString() + "\r\n"); + proc_GridServer.StopProcess(); + proc_GridServer = null; + } + if (proc_AssetServer != null) + { + txtMainLog.AppendText("Shutting down AssetServer. CPU time used: " + proc_AssetServer.TotalProcessorTime.ToString() + "\r\n"); + proc_AssetServer.StopProcess(); + proc_AssetServer = null; + } + if (proc_OpenSim != null) + { + txtMainLog.AppendText("Shutting down OpenSim. CPU time used: " + proc_OpenSim.TotalProcessorTime.ToString() + "\r\n"); + proc_OpenSim.StopProcess(); + proc_OpenSim = null; + } + } + private void UpdateTabVisibility() + { + if (rbStandAloneMode.Checked) + { + if (tabLogs.TabPages.Contains(tabUserServer)) + tabLogs.TabPages.Remove(tabUserServer); + if (tabLogs.TabPages.Contains(tabGridServer)) + tabLogs.TabPages.Remove(tabGridServer); + if (tabLogs.TabPages.Contains(tabAssetServer)) + tabLogs.TabPages.Remove(tabAssetServer); + } + else + { + if (!tabLogs.TabPages.Contains(tabUserServer)) + tabLogs.TabPages.Add(tabUserServer); + if (!tabLogs.TabPages.Contains(tabGridServer)) + tabLogs.TabPages.Add(tabGridServer); + if (!tabLogs.TabPages.Contains(tabAssetServer)) + tabLogs.TabPages.Add(tabAssetServer); + } + } + + private void rbStandAloneMode_CheckedChanged(object sender, EventArgs e) + { + UpdateTabVisibility(); + } + + private void rbGridRegionMode_CheckedChanged(object sender, EventArgs e) + { + UpdateTabVisibility(); + } + + private void rbGridServer_CheckedChanged(object sender, EventArgs e) + { + UpdateTabVisibility(); + } + + private int counter; + + private void Exit() + { + counter = 0; + timer1.Interval = 600; + timer1.Enabled = true; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + } + + private void timer1_Tick(object sender, System.EventArgs e) + { + if (counter >= 10) + { + timer1.Enabled = false; + counter = 0; + Application.Exit(); + } + else + { + counter = counter + 1; + } + } + + private void exitToolStripMenuItem_Click(object sender, EventArgs e) + { + if (proc_UserServer != null || proc_GridServer != null || proc_AssetServer != null || proc_OpenSim != null) + { + label6.Text = "Stopping server(s) and waiting to safely close.............."; + Stop(); + Exit(); + } + else + { + Application.Exit(); + } + } + /// + /// CLIENT SECTION + /// + string exeString; + string exeArgs; + string usrsvr; + string error = "Reconsider your commandline choices, you have opposing values selected!"; + + private void label6_Click(object sender, EventArgs e) + { + label6.Text = clientBox1.Text; + } + private void errorSwitches() + { + MessageBox.Show(error); + label6.Text = error; + } + bool exists; + private void Launch1_Click(object sender, EventArgs e) + { + if (exists = System.IO.File.Exists(clientBox1.Text + exeBox1.Text)) + { + executeClient(); + } + else + { + MessageBox.Show("FILE DOES NOT EXIST!!!"); + label6.Text = "FILE DOES NOT EXIST!!!"; + } + } + private void NATfix() + { + } + private void executeClient() + { + label6.Text = ""; + exeArgs = ""; + exeString = clientBox1.Text; + exeString = exeString += exeBox1.Text; + + if (multiple1.Checked == true && noMultiple1.Checked == true) errorSwitches(); + else if (korean1.Checked == true && spanish1.Checked == true) errorSwitches(); + else + { + if (noProbe1.Checked == true) exeArgs = exeArgs += " -noprobe"; + if (multiple1.Checked == true) exeArgs = exeArgs += " -multiple"; + if (noMultiple1.Checked == true) exeArgs = exeArgs += " -nomultiple"; + if (korean1.Checked == true) exeArgs = exeArgs += " -korean"; + if (spanish1.Checked == true) exeArgs = exeArgs += " -spanish"; + if (ignorepixeldepth1.Checked == true) exeArgs = exeArgs += " -ignorepixeldepth"; + if (nothread1.Checked == true) exeArgs = exeArgs += " -nothread"; + if (safe1.Checked == true) exeArgs = exeArgs += " -safe"; + if (noconsole1.Checked == true) exeArgs = exeArgs += " -noconsole"; + if (log1.Checked == true) exeArgs = exeArgs += " -log"; + if (helperuri1.Checked == true) exeArgs = exeArgs += " -helperuri"; + if (autologin1.Checked == true) exeArgs = exeArgs += " --autologin"; + if (dialog1.Checked == true) exeArgs = exeArgs += " -dialog"; + if (previous1.Checked == true) exeArgs = exeArgs += " -previous"; + if (simple1.Checked == true) exeArgs = exeArgs += " -simple"; + if (noinvlib1.Checked == true) exeArgs = exeArgs += " -noinvlib"; + if (noutc1.Checked == true) exeArgs = exeArgs += " -noutc"; + if (debugst1.Checked == true) exeArgs = exeArgs += " -debugst"; + if (local1.Checked == true) exeArgs = exeArgs += " -local"; + if (purge1.Checked == true) exeArgs = exeArgs += " -purge"; + if (nofmod1.Checked == true) exeArgs = exeArgs += " -nofmod"; + if (nosound1.Checked == true) exeArgs = exeArgs += " -nosound"; + if (noaudio1.Checked == true) exeArgs = exeArgs += " -noaudio"; + if (url1.Checked == true) + { + exeArgs = exeArgs += " -url "; + exeArgs = exeArgs += simBox1.Text; + } + if (port1.Checked == true) + { + int aPort; + aPort = Convert.ToInt32(portBox1.Text); + if (aPort > 13050) + { + portBox1.Text = "13050"; + MessageBox.Show("Enter Usable port number, defaulting to 13050."); + } + if(aPort < 13000) + { + portBox1.Text = "13000"; + MessageBox.Show("Enter Usable port number, defaulting to 13000."); + } + else + { + } + exeArgs = exeArgs += " -port "; + exeArgs = exeArgs += portBox1.Text; + } + if (drop1.Checked == true) + { + int aPct; + aPct = Convert.ToInt32(dropBox1.Text); + if (aPct > 100) + { + dropBox1.Text = "100"; + MessageBox.Show("Enter Usable port number, defaulting to 100."); + } + if (aPct < 0) + { + dropBox1.Text = "0"; + MessageBox.Show("Enter Usable port number, defaulting to 0."); + } + else + { + } + exeArgs = exeArgs += " -drop "; + exeArgs = exeArgs += dropBox1.Text; + } + if (inbw1.Checked == true) + { + exeArgs = exeArgs += " -inbw "; + exeArgs = exeArgs += inbwBox1.Text; + } + if (outbw1.Checked == true) + { + exeArgs = exeArgs += " -outbw "; + exeArgs = exeArgs += outbwBox1.Text; + } + if (settings1.Checked == true) + { + exeArgs = exeArgs += " -settings "; + exeArgs = exeArgs += settingsBox1.Text; + } + if (logfile1.Checked == true) + { + exeArgs = exeArgs += " -logfile "; + exeArgs = exeArgs += logfileBox1.Text; + } + if (yield1.Checked == true) + { + exeArgs = exeArgs += " -yield "; + exeArgs = exeArgs += yieldBox1.Text; + } + if (techTag1.Checked == true) + { + exeArgs = exeArgs += " -techtag "; + exeArgs = exeArgs += techtagBox1.Text; + } + if (quitAfter1.Checked == true) + { + exeArgs = exeArgs += " -quitafter "; + exeArgs = exeArgs += quitafterBox1.Text; + } + if (loginuri1.Checked == true) + { + exeArgs = exeArgs += " -loginuri "; + exeArgs = exeArgs += loginuriBox1.Text; + } + if (set1.Checked == true) + { + exeArgs = exeArgs += " -set "; + exeArgs = exeArgs += setBox1.Text; + } + if (errmask1.Checked == true) + { + exeArgs = exeArgs += " -errmask "; + exeArgs = exeArgs += errmaskBox1.Text; + } + if (raw1.Checked == true) + { + exeArgs = exeArgs += " " + rawBox1.Text; + } + if (skin1.Checked == true) + { + bool exists; + if (exists = System.IO.File.Exists(skinBox1.Text + "skin.xml")) + { + exeArgs = exeArgs += " -skin "; + exeArgs = exeArgs += skinBox1.Text + "skin.xml"; + } + else + { + MessageBox.Show("SKIN FILE DOES NOT EXIST AT SPECIFIED LOCATION!!!"); + skin1.Checked = false; + executeClient(); + } + } + if (user1.Checked == true) + { + //find actual login urls + if (comboBox1.Text == "agni") { usrsvr = " -user " + "--agni"; } + if (comboBox1.Text == "colo") { usrsvr = " -user " + "--colo"; } + if (comboBox1.Text == "dmz") { usrsvr = " -user " + "--dmz"; } + if (comboBox1.Text == "durga") { usrsvr = " -user " + "--Durga"; } + if (comboBox1.Text == "siva") { usrsvr = " -user " + "--siva"; } + exeArgs = exeArgs += usrsvr; + } + if (login1.Checked == true) + { + exeArgs = exeArgs += " -login "; + exeArgs = exeArgs += firstBox1.Text + " " + lastBox1.Text + " " + passBox1.Text; + } + label6.Text = exeString + exeArgs; + System.Diagnostics.Process proc = new System.Diagnostics.Process(); + proc.StartInfo.FileName = exeString; + proc.StartInfo.Arguments = exeArgs; + proc.StartInfo.UseShellExecute = false; + proc.StartInfo.RedirectStandardOutput = false; + proc.StartInfo.WorkingDirectory = clientBox1.Text; + proc.Start(); + } + } + } +} diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/Main.resx b/trunk/OpenSim/Tools/OpenSim.GUI/Main.resx new file mode 100644 index 0000000000..517179d1e1 --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/Main.resx @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 126, 17 + + + 209, 17 + + + 209, 17 + + + 39 + + diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/OpenSim.GUI.csproj b/trunk/OpenSim/Tools/OpenSim.GUI/OpenSim.GUI.csproj new file mode 100644 index 0000000000..e722fec47e --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/OpenSim.GUI.csproj @@ -0,0 +1,94 @@ + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {78AEEDD5-4DA8-4E05-8D53-F3C5476A0B97} + WinExe + Properties + OpenSim.GUI + OpenSim.GUI + + + true + full + false + ..\..\..\bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + Form + + + frmConfiguration.cs + + + Component + + + Form + + + Main.cs + + + Component + + + + + Designer + frmConfiguration.cs + + + Designer + Main.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + \ No newline at end of file diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/ProcessManager.cs b/trunk/OpenSim/Tools/OpenSim.GUI/ProcessManager.cs new file mode 100644 index 0000000000..8421f0ed7e --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/ProcessManager.cs @@ -0,0 +1,99 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; + +namespace OpenSim.GUI +{ + public class ProcessManager : Process + { + private string m_FileName; + private string m_Arguments; + public ProcessManager(string FileName,string Arguments) + { + m_FileName = FileName; + m_Arguments = Arguments; + +// MyProc = new Process(); + StartInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory; + Console.WriteLine("WorkingDirectory: " + StartInfo.WorkingDirectory); + StartInfo.FileName = m_FileName; + + //p.StartInfo.Arguments = ""; + StartInfo.UseShellExecute = false; + StartInfo.RedirectStandardError = true; + StartInfo.RedirectStandardInput = true; + StartInfo.RedirectStandardOutput = true; + StartInfo.CreateNoWindow = true; + + + + } + + public void StartProcess() + { + try + { + Start(); + BeginOutputReadLine(); + BeginErrorReadLine(); + } + catch (Exception ex) + { + Console.WriteLine("Exception Occurred :{0},{1}", + ex.Message, ex.StackTrace.ToString()); + } + } + public void StopProcess() + { + try + { + CancelErrorRead(); + CancelErrorRead(); + if (!HasExited) + { + StandardInput.WriteLine("quit"); + StandardInput.WriteLine("shutdown"); + System.Threading.Thread.Sleep(500); + if (!HasExited) + { + Kill(); + } + } + } + catch (Exception ex) + { + Console.WriteLine("Exception Occurred :{0},{1}", + ex.Message, ex.StackTrace.ToString()); + } + } + } +} diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/Program.cs b/trunk/OpenSim/Tools/OpenSim.GUI/Program.cs new file mode 100644 index 0000000000..e646b9c649 --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/Program.cs @@ -0,0 +1,48 @@ +/* +* 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; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace OpenSim.GUI +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Main()); + } + } +} diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/Properties/AssemblyInfo.cs b/trunk/OpenSim/Tools/OpenSim.GUI/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..f579a3f49e --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/Properties/AssemblyInfo.cs @@ -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 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.CompilerServices; +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.GUI")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpenSim.GUI")] +[assembly: AssemblyCopyright("Copyright © 2007")] +[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("c8dbda49-66bd-476b-93b3-71774870b73e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/Properties/Resources.Designer.cs b/trunk/OpenSim/Tools/OpenSim.GUI/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..33e67d416a --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.312 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace OpenSim.GUI.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpenSim.GUI.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/Properties/Resources.resx b/trunk/OpenSim/Tools/OpenSim.GUI/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebbac --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/Properties/Settings.Designer.cs b/trunk/OpenSim/Tools/OpenSim.GUI/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..dd1db86566 --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.312 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace OpenSim.GUI.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/Properties/Settings.settings b/trunk/OpenSim/Tools/OpenSim.GUI/Properties/Settings.settings new file mode 100644 index 0000000000..39645652af --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/frmConfiguration.Designer.cs b/trunk/OpenSim/Tools/OpenSim.GUI/frmConfiguration.Designer.cs new file mode 100644 index 0000000000..6da9bc12b7 --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/frmConfiguration.Designer.cs @@ -0,0 +1,89 @@ +/* +* 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. +* +*/ + +namespace OpenSim.GUI +{ + partial class frmConfiguration + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmConfiguration)); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(12, 12); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(570, 190); + this.textBox1.TabIndex = 0; + this.textBox1.Text = resources.GetString("textBox1.Text"); + // + // frmConfiguration + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(664, 413); + this.Controls.Add(this.textBox1); + this.Name = "frmConfiguration"; + this.Text = "Configuration"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + } +} diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/frmConfiguration.cs b/trunk/OpenSim/Tools/OpenSim.GUI/frmConfiguration.cs new file mode 100644 index 0000000000..2c9b97a757 --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/frmConfiguration.cs @@ -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. +* +*/ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace OpenSim.GUI +{ + public partial class frmConfiguration : Form + { + public frmConfiguration() + { + InitializeComponent(); + } + } +} diff --git a/trunk/OpenSim/Tools/OpenSim.GUI/frmConfiguration.resx b/trunk/OpenSim/Tools/OpenSim.GUI/frmConfiguration.resx new file mode 100644 index 0000000000..084547c86f --- /dev/null +++ b/trunk/OpenSim/Tools/OpenSim.GUI/frmConfiguration.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + What I want here: +* Region configuration add/disable/modify) +* OpenSim config: what physics/sql/scriptengine modules +* Configuration for each of the servers +* An option of what parts the server will run: "Stand Alone, Grid region, Grid Server, Custom" +Custom = you can enable/disable one or more services, for example if you only run AssetServer on this machine. +* User manager (add/remove/lockout/modify) -- maybe a separate form for this? + + \ No newline at end of file diff --git a/trunk/OpenSim/Tools/Windows/Installer/OpenSim.nsi b/trunk/OpenSim/Tools/Windows/Installer/OpenSim.nsi new file mode 100644 index 0000000000..3c3fe812b9 --- /dev/null +++ b/trunk/OpenSim/Tools/Windows/Installer/OpenSim.nsi @@ -0,0 +1,151 @@ +!include "MUI.nsh" + +Name "OpenSim" +OutFile "OpenSim Setup 0.5.exe" + +CRCCheck On + +InstallDir "$PROGRAMFILES\OpenSim" +InstallDirRegKey HKCU "Software\OpenSim" "" + +;Vista redirects $SMPROGRAMS to all users without this +RequestExecutionLevel admin + +Var MUI_TEMP +Var STARTMENU_FOLDER + +!define MUI_LANGDLL_REGISTRY_ROOT "HKCU" +!define MUI_LANGDLL_REGISTRY_KEY "Software\OpenSim" +!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language" + +!define MUI_ABORTWARNING + +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_LICENSE "LICENSE.txt" +!insertmacro MUI_PAGE_DIRECTORY + +!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU" +!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\OpenSim" +!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" + +!insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER + +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_PAGE_FINISH + +!insertmacro MUI_UNPAGE_WELCOME +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES +!insertmacro MUI_UNPAGE_FINISH + +!insertmacro MUI_LANGUAGE "English" +!insertmacro MUI_LANGUAGE "French" +!insertmacro MUI_LANGUAGE "German" +!insertmacro MUI_LANGUAGE "Spanish" +!insertmacro MUI_LANGUAGE "SpanishInternational" +!insertmacro MUI_LANGUAGE "SimpChinese" +!insertmacro MUI_LANGUAGE "TradChinese" +!insertmacro MUI_LANGUAGE "Japanese" +!insertmacro MUI_LANGUAGE "Korean" +!insertmacro MUI_LANGUAGE "Italian" +!insertmacro MUI_LANGUAGE "Dutch" +!insertmacro MUI_LANGUAGE "Danish" +!insertmacro MUI_LANGUAGE "Swedish" +!insertmacro MUI_LANGUAGE "Norwegian" +!insertmacro MUI_LANGUAGE "NorwegianNynorsk" +!insertmacro MUI_LANGUAGE "Finnish" +!insertmacro MUI_LANGUAGE "Greek" +!insertmacro MUI_LANGUAGE "Russian" +!insertmacro MUI_LANGUAGE "Portuguese" +!insertmacro MUI_LANGUAGE "PortugueseBR" +!insertmacro MUI_LANGUAGE "Polish" +!insertmacro MUI_LANGUAGE "Ukrainian" +!insertmacro MUI_LANGUAGE "Czech" +!insertmacro MUI_LANGUAGE "Slovak" +!insertmacro MUI_LANGUAGE "Croatian" +!insertmacro MUI_LANGUAGE "Bulgarian" +!insertmacro MUI_LANGUAGE "Hungarian" +!insertmacro MUI_LANGUAGE "Thai" +!insertmacro MUI_LANGUAGE "Romanian" +!insertmacro MUI_LANGUAGE "Latvian" +!insertmacro MUI_LANGUAGE "Macedonian" +!insertmacro MUI_LANGUAGE "Estonian" +!insertmacro MUI_LANGUAGE "Turkish" +!insertmacro MUI_LANGUAGE "Lithuanian" +!insertmacro MUI_LANGUAGE "Slovenian" +!insertmacro MUI_LANGUAGE "Serbian" +!insertmacro MUI_LANGUAGE "SerbianLatin" +!insertmacro MUI_LANGUAGE "Arabic" +!insertmacro MUI_LANGUAGE "Farsi" +!insertmacro MUI_LANGUAGE "Hebrew" +!insertmacro MUI_LANGUAGE "Indonesian" +!insertmacro MUI_LANGUAGE "Mongolian" +!insertmacro MUI_LANGUAGE "Luxembourgish" +!insertmacro MUI_LANGUAGE "Albanian" +!insertmacro MUI_LANGUAGE "Breton" +!insertmacro MUI_LANGUAGE "Belarusian" +!insertmacro MUI_LANGUAGE "Icelandic" +!insertmacro MUI_LANGUAGE "Malay" +!insertmacro MUI_LANGUAGE "Bosnian" +!insertmacro MUI_LANGUAGE "Kurdish" +!insertmacro MUI_LANGUAGE "Irish" +!insertmacro MUI_LANGUAGE "Uzbek" +!insertmacro MUI_LANGUAGE "Galician" +!insertmacro MUI_LANGUAGE "Afrikaans" +!insertmacro MUI_LANGUAGE "Catalan" + +!insertmacro MUI_RESERVEFILE_LANGDLL + +Section "Install" + SetOutPath "$INSTDIR" + + SetCompress Auto + SetOverwrite IfNewer + File /r "bin\*.*" + + WriteRegStr HKCU "Software\OpenSim" "" $INSTDIR + WriteUninstaller "$INSTDIR\Uninstall.exe" + + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\OpenSim.lnk" "$INSTDIR\OpenSim.exe" + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe" + !insertmacro MUI_STARTMENU_WRITE_END + + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSim" "DisplayName" "OpenSim (remove only)" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSim" "UninstallString" "$INSTDIR\Uninstall.exe" +SectionEnd + +Function .onInit + !insertmacro MUI_LANGDLL_DISPLAY +FunctionEnd + +Section "Uninstall" + Delete "$INSTDIR\*.*" + RMDir /r "$INSTDIR" + +!insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP + + Delete "$SMPROGRAMS\$MUI_TEMP\OpenSim.lnk" + Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" + + ;Delete empty start menu parent diretories + StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" + + startMenuDeleteLoop: + ClearErrors + RMDir $MUI_TEMP + GetFullPathName $MUI_TEMP "$MUI_TEMP\.." + + IfErrors startMenuDeleteLoopDone + + StrCmp $MUI_TEMP $SMPROGRAMS startMenuDeleteLoopDone startMenuDeleteLoop + startMenuDeleteLoopDone: + + DeleteRegKey /ifempty HKCU "Software\OpenSim" + DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenSim" +SectionEnd + +Function un.onInit + !insertmacro MUI_UNGETLANGUAGE +FunctionEnd diff --git a/trunk/OpenSim/Tools/classaudit.pl b/trunk/OpenSim/Tools/classaudit.pl new file mode 100755 index 0000000000..9c92720a3d --- /dev/null +++ b/trunk/OpenSim/Tools/classaudit.pl @@ -0,0 +1,133 @@ +#!/usr/bin/perl +# +# Audit tool for OpenSim class and namespace definitions. +# +# Copyright 2007 IBM +# +# Authors: Sean Dague +# +# 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. + +use strict; +use File::Find; +use Data::Dumper; +use constant YELLOW => "\033[33m"; +use constant RED => "\033[31m"; +use constant CLEAR => "\033[0m"; +our %totals; + + +find(\&test, "../OpenSim"); +print Dumper(\%totals); + +sub test { + my $file = $File::Find::name; + my $dir = $File::Find::dir; + $file =~ s{^../}{}; #strip off prefix + $dir =~ s{^../}{}; #strip off prefix + + return if ($file !~ /\.cs$/); + return if ($file =~ /AssemblyInfo\.cs$/); + + print "Processing File: $file\n"; + + my $namespace = find_namespace($_); + my $class = find_class($_); + + + + if(cmp_namespace($namespace, $dir) == 1) { + $totals{goodns}++; + } else { + $totals{badns}++; + } + + + if(cmp_class($namespace, $class, $file) == 1) { + $totals{goodclass}++; + } else { + $totals{badclass}++; + } + print "\n"; +} + +sub find_class { + my $file = shift; + my $content = slurp($file); + if ($content =~ /\n\s*(public|private|protected)?\s*(class|interface)\s+(\S+)/) { + return $3; + } + return ""; +} + +sub find_namespace { + my $file = shift; + my $content = slurp($file); + + if ($content =~ /\bnamespace\s+(\S+)/s) { + return $1; + } + return ""; +} + +sub slurp { + my $file = shift; + local(*IN); + local $/ = undef; + + open(IN, "$file") or die "Can't open '$file': $!"; + my $content = ; + close(IN); + + return $content; +} + +sub cmp_class { + my ($ns, $class, $file) = @_; + $class = "$ns.$class"; + my $classtrans = $class; + $classtrans =~ s{\.}{/}g; + $classtrans .= ".cs"; + + if($classtrans ne $file) { + error(YELLOW, "CLASS: $class != $file"); + return -1; + } + return 1; +} + +sub cmp_namespace { + my ($ns, $dir) = @_; + my $nstrans = $ns; + $nstrans =~ s{\.}{/}g; + + if($nstrans ne $dir) { + error(RED, "NS: $ns != $dir"); + return -1; + } + return 1; +} + +sub error { + print @_, CLEAR, "\n"; +} diff --git a/trunk/OpenSim/Tools/pCampBot/BotManager.cs b/trunk/OpenSim/Tools/pCampBot/BotManager.cs new file mode 100644 index 0000000000..0c7fa4ef48 --- /dev/null +++ b/trunk/OpenSim/Tools/pCampBot/BotManager.cs @@ -0,0 +1,235 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using System.IO; +using libsecondlife; +using libsecondlife.Packets; +using Nini.Config; +using System.Threading; +using OpenSim.Framework; +using OpenSim.Framework.Console; + +namespace pCampBot +{ + /// + /// Thread/Bot manager for the application + /// + public class BotManager : conscmd_callback + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + protected ConsoleBase m_console; + protected List m_lBot; + protected Thread[] m_td; + protected bool m_verbose = true; + protected Random somthing = new Random(System.Environment.TickCount); + protected int numbots = 0; + protected IConfig Previous_config; + + /// + /// Constructor Creates MainConsole.Instance to take commands and provide the place to write data + /// + public BotManager() + { + m_console = CreateConsole(); + MainConsole.Instance = m_console; + m_lBot = new List(); + } + + /// + /// Startup number of bots specified in the starting arguments + /// + /// How many bots to start up + /// The configuration for the bots to use + public void dobotStartup(int botcount, IConfig cs) + { + Previous_config = cs; + m_td = new Thread[botcount]; + for (int i = 0; i < botcount; i++) + { + startupBot(i, cs); + } + } + + /// + /// Add additional bots (and threads) to our bot pool + /// + /// How Many of them to add + public void addbots(int botcount) + { + int len = m_td.Length; + Thread[] m_td2 = new Thread[len + botcount]; + for (int i = 0; i < len; i++) + { + m_td2[i] = m_td[i]; + } + m_td = m_td2; + int newlen = len + botcount; + for (int i = len; i < newlen; i++) + { + startupBot(i, Previous_config); + } + } + + /// + /// This starts up the bot and stores the thread for the bot in the thread array + /// + /// The position in the thread array to stick the bot's thread + /// Configuration of the bot + public void startupBot(int pos, IConfig cs) + { + PhysicsBot pb = new PhysicsBot(cs); + + pb.OnConnected += handlebotEvent; + pb.OnDisconnected += handlebotEvent; + if (cs.GetString("firstname", "random") == "random") pb.firstname = CreateRandomName(); + if (cs.GetString("lastname", "random") == "random") pb.lastname = CreateRandomName(); + + m_td[pos] = new Thread(pb.startup); + m_td[pos].Start(); + m_lBot.Add(pb); + } + + /// + /// Creates a random name for the bot + /// + /// + private string CreateRandomName() + { + string returnstring = ""; + string chars = "abcdefghijklmnopqrstuvwxyz0123456789"; + + for (int i = 0; i < 7; i++) + { + returnstring += chars.Substring(somthing.Next(chars.Length),1); + } + return returnstring; + } + + /// + /// High level connnected/disconnected events so we can keep track of our threads by proxy + /// + /// + /// + public void handlebotEvent(PhysicsBot callbot, EventType eventt) + { + switch (eventt) + { + case EventType.CONNECTED: + m_log.Info("[ " + callbot.firstname + " " + callbot.lastname + "]: Connected"); + numbots++; + break; + case EventType.DISCONNECTED: + m_log.Info("[ " + callbot.firstname + " " + callbot.lastname + "]: Disconnected"); + m_td[m_lBot.IndexOf(callbot)].Abort(); + numbots--; + if (numbots >1) + Environment.Exit(0); + break; + } + } + + /// + /// Shutting down all bots + /// + public void doBotShutdown() + { + foreach (PhysicsBot pb in m_lBot) + { + pb.shutdown(); + } + } + + /// + /// Standard CreateConsole routine + /// + /// + protected ConsoleBase CreateConsole() + { + return new ConsoleBase("Region", this); + } + + /// + /// I don't think the bots use this.. + /// + /// + /// + /// + private string CombineParams(string[] commandParams, int pos) + { + string result = String.Empty; + for (int i = pos; i < commandParams.Length; i++) + { + result += commandParams[i] + " "; + } + result = result.TrimEnd(' '); + return result; + } + + /// + /// Command runnint tool.. Currently use it to add bots, shutdown and (dangerous)Forcequit + /// + /// + /// + public void RunCmd(string command, string[] cmdparams) + { + switch (command) + { + case "shutdown": + m_console.Warn("BOTMANAGER", "Shutting down bots"); + doBotShutdown(); + break; + case "quit": + m_console.Warn("DANGER", "This should only be used to quit the program if you've already used the shutdown command and the program hasn't quit"); + Environment.Exit(0); + break; + case "addbots": + int newbots = 0; + Helpers.TryParse(cmdparams[0], out newbots); + + if (newbots > 0) + addbots(newbots); + break; + case "help": + m_console.Notice("HELP", "\nshutdown - graceful shutdown\naddbots - adds n bots to the test\nquit - forcequits, dangerous if you have not already run shutdown"); + break; + } + } + + /// + /// Required method to implement the conscmd_callback interface + /// + /// + public void Show(string ShowWhat) + { + } + } +} diff --git a/trunk/OpenSim/Tools/pCampBot/PhysicsBot.cs b/trunk/OpenSim/Tools/pCampBot/PhysicsBot.cs new file mode 100644 index 0000000000..48ce062692 --- /dev/null +++ b/trunk/OpenSim/Tools/pCampBot/PhysicsBot.cs @@ -0,0 +1,201 @@ +/* +* 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; +using System.Collections.Generic; +using System.IO; +using System.Text; +using libsecondlife; +using libsecondlife.Packets; +using Nini.Config; +using System.Threading; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using Timer = System.Timers.Timer; + +namespace pCampBot +{ + public class PhysicsBot + { + public delegate void AnEvent(PhysicsBot callbot, EventType someevent); // event delegate for bot events + public IConfig startupConfig; // bot config, passed from BotManager + + public string firstname; + public string lastname; + public string password; + public string loginURI; + + public event AnEvent OnConnected; + public event AnEvent OnDisconnected; + + protected Timer m_action; // Action Timer + + protected Random somthing = new Random(System.Environment.TickCount);// We do stuff randomly here + + //New instance of a SecondLife client + public SecondLife client = new SecondLife(); + + protected string[] talkarray; + /// + /// + /// + /// nini config for the bot + public PhysicsBot(IConfig bsconfig) + { + startupConfig = bsconfig; + readconfig(); + talkarray = readexcuses(); + } + + //We do our actions here. This is where one would + //add additional steps and/or things the bot should do + + void m_action_Elapsed(object sender, System.Timers.ElapsedEventArgs e) + { + //client.Throttle.Task = 500000f; + //client.Throttle.Set(); + int walkorrun = somthing.Next(4); // Randomize between walking and running. The greater this number, + // the greater the bot's chances to walk instead of run. + if (walkorrun == 0) + { + client.Self.Movement.AlwaysRun = true; + } + else + { + client.Self.Movement.AlwaysRun = false; + } + + LLVector3 pos = client.Self.SimPosition; + LLVector3 newpos = new LLVector3(somthing.Next(255), somthing.Next(255), somthing.Next(255)); + client.Self.Movement.TurnToward(newpos); + + for (int i = 0; i < 2000; i++) + { + client.Self.Movement.AtPos = true; + Thread.Sleep(somthing.Next(25, 75)); // Makes sure the bots keep walking for this time. + } + client.Self.Jump(); + + string randomf = talkarray[somthing.Next(talkarray.Length)]; + if (talkarray.Length > 1 && randomf.Length > 1) + client.Self.Chat(randomf, 0, ChatType.Normal); + + //Thread.Sleep(somthing.Next(1, 10)); // Apparently its better without it right now. + + } + + /// + /// Read the Nini config and initialize + /// + public void readconfig() + { + firstname = startupConfig.GetString("firstname", "random"); + lastname = startupConfig.GetString("lastname", "random"); + password = startupConfig.GetString("password", "12345"); + loginURI = startupConfig.GetString("loginuri", "http://10.1.1.5:9000"); + + + + } + + /// + /// Tells LibSecondLife to logout and disconnect. Raises the disconnect events once it finishes. + /// + public void shutdown() + { + client.Network.Logout(); + } + + /// + /// This is the bot startup loop. + /// + public void startup() + { + client.Settings.LOGIN_SERVER = loginURI; + client.Network.OnConnected += new NetworkManager.ConnectedCallback(this.Network_OnConnected); + client.Network.OnSimConnected += new NetworkManager.SimConnectedCallback(this.Network_OnConnected); + client.Network.OnDisconnected += new NetworkManager.DisconnectedCallback(this.Network_OnDisconnected); + if (client.Network.Login(firstname, lastname, password, "pCampBot", "Your name")) + { + + if (OnConnected != null) + { + m_action = new Timer(somthing.Next(1000, 10000)); + m_action.Elapsed += new System.Timers.ElapsedEventHandler(m_action_Elapsed); + m_action.Start(); + OnConnected(this, EventType.CONNECTED); + client.Self.Jump(); + + } + } + else + { + MainConsole.Instance.Error(firstname + " " + lastname, "Can't login: " + client.Network.LoginMessage); + if (OnDisconnected != null) + { + OnDisconnected(this, EventType.DISCONNECTED); + } + } + } + + public void Network_OnConnected(object sender) + { + if (OnConnected != null) + { + OnConnected(this, EventType.CONNECTED); + } + } + + public void Simulator_Connected(object sender) + { + } + + public void Network_OnDisconnected(NetworkManager.DisconnectType reason, string message) + { + if (OnDisconnected != null) + { + OnDisconnected(this, EventType.DISCONNECTED); + } + } + + public string[] readexcuses() + { + string allexcuses = ""; + + string file = Path.Combine(Util.configDir(), "pCampBotSentences.txt"); + if (File.Exists(file)) + { + StreamReader csr = File.OpenText(file); + allexcuses = csr.ReadToEnd(); + csr.Close(); + } + + return allexcuses.Split(Environment.NewLine.ToCharArray()); + } + } +} diff --git a/trunk/OpenSim/Tools/pCampBot/README.txt b/trunk/OpenSim/Tools/pCampBot/README.txt new file mode 100644 index 0000000000..7ecbde1ba9 --- /dev/null +++ b/trunk/OpenSim/Tools/pCampBot/README.txt @@ -0,0 +1,44 @@ +This is the PhysicsCamperbot libslBot tester. + +This is designed to be run in standalone mode with authorize accounts +turned off as a way to stress test the simulator. It creates +clients that log in, randomly jump/walk around, and say excuses from +the BOFH. + +*** WARNING *** +Using this bot on a public grid could get you banned permanently, so +just say No! to griefing! + +----- Setup ----- +Linux: To build, in the main opensim directory, run: + ./runprebuild.sh + nant + +Windows: Run the prebuild.bat in the main opensim directory and then +open the created solution and compile it. + +pCampBot.exe will end up in the regular opensim/bin folder + +----- Running the bot ----- + +windows: pCampBot.exe -botcount -loginuri +*nix: mono pCampBot.exe -botcount -loginuri + +The names it produces are random by default, however, you can specify +either a firstname or a lastname in the command line also. + +ex: pCampBot.exe -botcount -loginuri -lastname + +If you specify both a firstname *and* a lastname, you'll likely run +into trouble unless you're only running a single bot. In that case, +there's also a password option. + +pCampBot.exe -botcount 1 -loginuri http://somegrid.com:8002 -firstname SomeDude -lastname SomeDude -password GobbleDeGook + +----- Commands ----- + +The bot has console commands: + help - lists the console commands and what they do + shutdown - gracefully shuts down the bots + quit - forcefully shuts things down leaving stuff unclean + addbots N - adds N number of random bots. (replace 'N' with a number) diff --git a/trunk/OpenSim/Tools/pCampBot/pCampBot.cs b/trunk/OpenSim/Tools/pCampBot/pCampBot.cs new file mode 100644 index 0000000000..704a3f5c9d --- /dev/null +++ b/trunk/OpenSim/Tools/pCampBot/pCampBot.cs @@ -0,0 +1,76 @@ +/* +* 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; +using System.Collections.Generic; +using System.Text; +using libsecondlife; +using libsecondlife.Packets; +using Nini.Config; +using System.Threading; +using OpenSim.Framework.Console; + +namespace pCampBot +{ + /// + /// Event Types from the BOT. Add new events here + /// + public enum EventType:int + { + NONE = 0, + CONNECTED = 1, + DISCONNECTED = 2 + } + + public class pCampBot + { + [STAThread] + public static void Main(string[] args) + { + //Set up our nifty config.. thanks to nini + ArgvConfigSource cs = new ArgvConfigSource(args); + + cs.AddSwitch("Startup", "botcount"); + cs.AddSwitch("Startup", "loginuri"); + cs.AddSwitch("Startup", "firstname"); + cs.AddSwitch("Startup", "lastname"); + cs.AddSwitch("Startup", "password"); + + IConfig ol = cs.Configs["Startup"]; + int botcount = ol.GetInt("botcount", 1); + BotManager bm = new BotManager(); + + //startup specified number of bots. 1 is the default + bm.dobotStartup(botcount, ol); + while (true) + { + MainConsole.Instance.Prompt(); + } + } + } +} diff --git a/trunk/Prebuild/README b/trunk/Prebuild/README new file mode 100644 index 0000000000..4341e42070 --- /dev/null +++ b/trunk/Prebuild/README @@ -0,0 +1,230 @@ +Prebuild Instructions + +Prebuild is an XML-driven pre-build tool allowing developers to easily generate project or make files for major IDE's and .NET development tools including: Visual Studio 2005, Visual Studio 2003, Visual Studio 2002, SharpDevelop, SharpDevelop2, MonoDevelop, and NAnt. + +_________________________________________________________________________________ +Overview + +Prebuild can be either be run from the command line to generate the project and make files or you can execute the included batch (*.bat) and Unix Shell script (*.sh) files. +The Prebuild file + +_________________________________________________________________________________ +The currently supported developement tools and their associated batch and shell script files. + +Visual Studio .NET 2005 (VS2005.bat) +Visual Studio .NET 2003 (VS2003.bat) +Visual Studio .NET 2002 (VS2002.bat) +SharpDevelop (SharpDevelop.bat) - http://www.icsharpcode.net/OpenSource/SD/ +SharpDevelop2 (SharpDevelop.bat) - http://www.icsharpcode.net/OpenSource/SD/ +MonoDevelop (MonoDevelop.sh) - http://www.monodevelop.com/ +NAnt (nant.sh and nant.bat) - http://nant.sourceforge.net/ +Autotools (autotools.bat and autotools.sh) http://www.gnu.org. Only partial support + +Notes: +A Unix Shell script is provided for MonoDevelop, as this is more appropriate than a windows batch file. +Visual Studio .NET 2005 and the Visual Express IDE's can import solutions from older versions of Visual Studio .NET. +Makefiles are not currently supported. + +_________________________________________________________________________________ +Command Line Syntax: + +Example: +>Prebuild /target vs2003 + +This will generate the project files for Visual Studio.NET 2003 and place the redirect the log to a file named PrebuildLog.txt in the parent directory + + +The syntax structure is as below, where commandParameter is optional depending on the command and you can provide several option-value pairs. +Note: The '>' signified the command line, do not actually enter this manually + +>Prebuild /