diff options
Diffstat (limited to '')
14 files changed, 510 insertions, 435 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index caf74cf..28f9481 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs | |||
@@ -971,8 +971,7 @@ namespace OpenSim | |||
971 | if (showParams.Length > 1 && showParams[1] == "full") | 971 | if (showParams.Length > 1 && showParams[1] == "full") |
972 | { | 972 | { |
973 | agents = m_sceneManager.GetCurrentScenePresences(); | 973 | agents = m_sceneManager.GetCurrentScenePresences(); |
974 | } | 974 | } else |
975 | else | ||
976 | { | 975 | { |
977 | agents = m_sceneManager.GetCurrentSceneAvatars(); | 976 | agents = m_sceneManager.GetCurrentSceneAvatars(); |
978 | } | 977 | } |
@@ -981,7 +980,8 @@ namespace OpenSim | |||
981 | 980 | ||
982 | MainConsole.Instance.Output( | 981 | MainConsole.Instance.Output( |
983 | String.Format("{0,-16} {1,-16} {2,-37} {3,-11} {4,-16} {5,-30}", "Firstname", "Lastname", | 982 | String.Format("{0,-16} {1,-16} {2,-37} {3,-11} {4,-16} {5,-30}", "Firstname", "Lastname", |
984 | "Agent ID", "Root/Child", "Region", "Position")); | 983 | "Agent ID", "Root/Child", "Region", "Position") |
984 | ); | ||
985 | 985 | ||
986 | foreach (ScenePresence presence in agents) | 986 | foreach (ScenePresence presence in agents) |
987 | { | 987 | { |
@@ -991,8 +991,7 @@ namespace OpenSim | |||
991 | if (regionInfo == null) | 991 | if (regionInfo == null) |
992 | { | 992 | { |
993 | regionName = "Unresolvable"; | 993 | regionName = "Unresolvable"; |
994 | } | 994 | } else |
995 | else | ||
996 | { | 995 | { |
997 | regionName = regionInfo.RegionName; | 996 | regionName = regionInfo.RegionName; |
998 | } | 997 | } |
@@ -1005,7 +1004,8 @@ namespace OpenSim | |||
1005 | presence.UUID, | 1004 | presence.UUID, |
1006 | presence.IsChildAgent ? "Child" : "Root", | 1005 | presence.IsChildAgent ? "Child" : "Root", |
1007 | regionName, | 1006 | regionName, |
1008 | presence.AbsolutePosition.ToString())); | 1007 | presence.AbsolutePosition.ToString()) |
1008 | ); | ||
1009 | } | 1009 | } |
1010 | 1010 | ||
1011 | MainConsole.Instance.Output(String.Empty); | 1011 | MainConsole.Instance.Output(String.Empty); |
@@ -1014,16 +1014,20 @@ namespace OpenSim | |||
1014 | case "connections": | 1014 | case "connections": |
1015 | System.Text.StringBuilder connections = new System.Text.StringBuilder("Connections:\n"); | 1015 | System.Text.StringBuilder connections = new System.Text.StringBuilder("Connections:\n"); |
1016 | m_sceneManager.ForEachScene( | 1016 | m_sceneManager.ForEachScene( |
1017 | delegate(Scene scene) | 1017 | delegate(Scene scene) { |
1018 | { | 1018 | scene.ForEachClient( |
1019 | scene.ForEachClient( | 1019 | delegate(IClientAPI client) { |
1020 | delegate(IClientAPI client) | 1020 | connections.AppendFormat( |
1021 | { | 1021 | "{0}: {1} ({2}) from {3} on circuit {4}\n", |
1022 | connections.AppendFormat("{0}: {1} ({2}) from {3} on circuit {4}\n", | 1022 | scene.RegionInfo.RegionName, |
1023 | scene.RegionInfo.RegionName, client.Name, client.AgentId, client.RemoteEndPoint, client.CircuitCode); | 1023 | client.Name, |
1024 | } | 1024 | client.AgentId, |
1025 | client.RemoteEndPoint, | ||
1026 | client.CircuitCode | ||
1025 | ); | 1027 | ); |
1026 | } | 1028 | } |
1029 | ); | ||
1030 | } | ||
1027 | ); | 1031 | ); |
1028 | 1032 | ||
1029 | MainConsole.Instance.Output(connections.ToString()); | 1033 | MainConsole.Instance.Output(connections.ToString()); |
@@ -1032,13 +1036,17 @@ namespace OpenSim | |||
1032 | case "circuits": | 1036 | case "circuits": |
1033 | System.Text.StringBuilder acd = new System.Text.StringBuilder("Agent Circuits:\n"); | 1037 | System.Text.StringBuilder acd = new System.Text.StringBuilder("Agent Circuits:\n"); |
1034 | m_sceneManager.ForEachScene( | 1038 | m_sceneManager.ForEachScene( |
1035 | delegate(Scene scene) | 1039 | delegate(Scene scene) { |
1036 | { | 1040 | //this.HttpServer. |
1037 | //this.HttpServer. | 1041 | acd.AppendFormat("{0}:\n", scene.RegionInfo.RegionName); |
1038 | acd.AppendFormat("{0}:\n", scene.RegionInfo.RegionName); | 1042 | foreach (AgentCircuitData aCircuit in scene.AuthenticateHandler.GetAgentCircuits().Values) |
1039 | foreach (AgentCircuitData aCircuit in scene.AuthenticateHandler.GetAgentCircuits().Values) | 1043 | acd.AppendFormat( |
1040 | acd.AppendFormat("\t{0} {1} ({2})\n", aCircuit.firstname, aCircuit.lastname, (aCircuit.child ? "Child" : "Root")); | 1044 | "\t{0} {1} ({2})\n", |
1041 | } | 1045 | aCircuit.firstname, |
1046 | aCircuit.lastname, | ||
1047 | (aCircuit.child ? "Child" : "Root") | ||
1048 | ); | ||
1049 | } | ||
1042 | ); | 1050 | ); |
1043 | 1051 | ||
1044 | MainConsole.Instance.Output(acd.ToString()); | 1052 | MainConsole.Instance.Output(acd.ToString()); |
@@ -1079,17 +1087,29 @@ namespace OpenSim | |||
1079 | } | 1087 | } |
1080 | 1088 | ||
1081 | m_sceneManager.ForEachScene( | 1089 | m_sceneManager.ForEachScene( |
1082 | delegate(Scene scene) | 1090 | delegate(Scene scene) { |
1091 | m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:"); | ||
1092 | foreach (IRegionModule module in scene.Modules.Values) | ||
1083 | { | 1093 | { |
1084 | m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:"); | 1094 | if (!module.IsSharedModule) |
1085 | foreach (IRegionModule module in scene.Modules.Values) | ||
1086 | { | 1095 | { |
1087 | if (!module.IsSharedModule) | 1096 | m_log.Error("Region Module: " + module.Name); |
1088 | { | ||
1089 | m_log.Error("Region Module: " + module.Name); | ||
1090 | } | ||
1091 | } | 1097 | } |
1092 | }); | 1098 | } |
1099 | } | ||
1100 | ); | ||
1101 | |||
1102 | m_sceneManager.ForEachScene( | ||
1103 | delegate(Scene scene) { | ||
1104 | MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:"); | ||
1105 | foreach (IRegionModuleBase module in scene.RegionModules.Values) | ||
1106 | { | ||
1107 | Type type = module.GetType().GetInterface("ISharedRegionModule"); | ||
1108 | string module_type = type != null ? "Shared" : "Non-Shared"; | ||
1109 | MainConsole.Instance.OutputFormat("New Region Module ({0}): {1}", module_type, module.Name); | ||
1110 | } | ||
1111 | } | ||
1112 | ); | ||
1093 | 1113 | ||
1094 | MainConsole.Instance.Output(""); | 1114 | MainConsole.Instance.Output(""); |
1095 | break; | 1115 | break; |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index dda4444..d310d65 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -155,7 +155,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
155 | 155 | ||
156 | private int m_defaultRTO = 0; | 156 | private int m_defaultRTO = 0; |
157 | private int m_maxRTO = 0; | 157 | private int m_maxRTO = 0; |
158 | 158 | private int m_ackTimeout = 0; | |
159 | private int m_pausedAckTimeout = 0; | ||
159 | private bool m_disableFacelights = false; | 160 | private bool m_disableFacelights = false; |
160 | 161 | ||
161 | public Socket Server { get { return null; } } | 162 | public Socket Server { get { return null; } } |
@@ -198,11 +199,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
198 | m_defaultRTO = config.GetInt("DefaultRTO", 0); | 199 | m_defaultRTO = config.GetInt("DefaultRTO", 0); |
199 | m_maxRTO = config.GetInt("MaxRTO", 0); | 200 | m_maxRTO = config.GetInt("MaxRTO", 0); |
200 | m_disableFacelights = config.GetBoolean("DisableFacelights", false); | 201 | m_disableFacelights = config.GetBoolean("DisableFacelights", false); |
202 | m_ackTimeout = 1000 * config.GetInt("AckTimeout", 60); | ||
203 | m_pausedAckTimeout = 1000 * config.GetInt("PausedAckTimeout", 300); | ||
201 | } | 204 | } |
202 | else | 205 | else |
203 | { | 206 | { |
204 | PrimUpdatesPerCallback = 100; | 207 | PrimUpdatesPerCallback = 100; |
205 | TextureSendLimit = 20; | 208 | TextureSendLimit = 20; |
209 | m_ackTimeout = 1000 * 60; // 1 minute | ||
210 | m_pausedAckTimeout = 1000 * 300; // 5 minutes | ||
206 | } | 211 | } |
207 | 212 | ||
208 | #region BinaryStats | 213 | #region BinaryStats |
@@ -491,8 +496,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
491 | return; | 496 | return; |
492 | 497 | ||
493 | // Disconnect an agent if no packets are received for some time | 498 | // Disconnect an agent if no packets are received for some time |
494 | //FIXME: Make 60 an .ini setting | 499 | int timeoutTicks = m_ackTimeout; |
495 | if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60) | 500 | |
501 | // Allow more slack if the client is "paused" eg file upload dialogue is open | ||
502 | // Some sort of limit is needed in case the client crashes, loses its network connection | ||
503 | // or some other disaster prevents it from sendung the AgentResume | ||
504 | if (udpClient.IsPaused) | ||
505 | timeoutTicks = m_pausedAckTimeout; | ||
506 | |||
507 | if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks) | ||
496 | { | 508 | { |
497 | m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID); | 509 | m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID); |
498 | StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); | 510 | StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); |
diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs index 8101ca2..87ca327 100644 --- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs | |||
@@ -57,14 +57,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile | |||
57 | 57 | ||
58 | public void Initialise(IConfigSource config) | 58 | public void Initialise(IConfigSource config) |
59 | { | 59 | { |
60 | // This can be reduced later as the loader will determine | ||
61 | // whether we are needed | ||
62 | if (config.Configs["Profile"] != null) | ||
63 | { | ||
64 | if (config.Configs["Profile"].GetString("Module", string.Empty) != "BasicProfileModule") | ||
65 | return; | ||
66 | } | ||
67 | |||
68 | m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled"); | 60 | m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled"); |
69 | m_Enabled = true; | 61 | m_Enabled = true; |
70 | } | 62 | } |
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs index d2bbea3..3b84d57 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs | |||
@@ -73,7 +73,7 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
73 | "set terrain heights <corner> <min> <max> [<x>] [<y>]", | 73 | "set terrain heights <corner> <min> <max> [<x>] [<y>]", |
74 | "Sets the terrain texture heights on corner #<corner> to <min>/<max>, if <x> or <y> are specified, it will only " + | 74 | "Sets the terrain texture heights on corner #<corner> to <min>/<max>, if <x> or <y> are specified, it will only " + |
75 | "set it on regions with a matching coordinate. Specify -1 in <x> or <y> to wildcard" + | 75 | "set it on regions with a matching coordinate. Specify -1 in <x> or <y> to wildcard" + |
76 | " that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3.", | 76 | " that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.", |
77 | consoleSetTerrainHeights); | 77 | consoleSetTerrainHeights); |
78 | 78 | ||
79 | m_module.Scene.AddCommand( | 79 | m_module.Scene.AddCommand( |
@@ -143,6 +143,16 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
143 | 143 | ||
144 | switch (corner) | 144 | switch (corner) |
145 | { | 145 | { |
146 | case -1: | ||
147 | m_module.Scene.RegionInfo.RegionSettings.Elevation1SW = lowValue; | ||
148 | m_module.Scene.RegionInfo.RegionSettings.Elevation2SW = highValue; | ||
149 | m_module.Scene.RegionInfo.RegionSettings.Elevation1NW = lowValue; | ||
150 | m_module.Scene.RegionInfo.RegionSettings.Elevation2NW = highValue; | ||
151 | m_module.Scene.RegionInfo.RegionSettings.Elevation1SE = lowValue; | ||
152 | m_module.Scene.RegionInfo.RegionSettings.Elevation2SE = highValue; | ||
153 | m_module.Scene.RegionInfo.RegionSettings.Elevation1NE = lowValue; | ||
154 | m_module.Scene.RegionInfo.RegionSettings.Elevation2NE = highValue; | ||
155 | break; | ||
146 | case 0: | 156 | case 0: |
147 | m_module.Scene.RegionInfo.RegionSettings.Elevation1SW = lowValue; | 157 | m_module.Scene.RegionInfo.RegionSettings.Elevation1SW = lowValue; |
148 | m_module.Scene.RegionInfo.RegionSettings.Elevation2SW = highValue; | 158 | m_module.Scene.RegionInfo.RegionSettings.Elevation2SW = highValue; |
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs index 71c71e6..7a0db26 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs | |||
@@ -180,8 +180,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders | |||
180 | // fileHeight = sztmp; | 180 | // fileHeight = sztmp; |
181 | bs.ReadInt16(); | 181 | bs.ReadInt16(); |
182 | bs.ReadInt16(); | 182 | bs.ReadInt16(); |
183 | bs.ReadInt16(); | ||
184 | bs.ReadInt16(); | ||
185 | break; | 183 | break; |
186 | case "XPTS": | 184 | case "XPTS": |
187 | // fileWidth = bs.ReadInt16(); | 185 | // fileWidth = bs.ReadInt16(); |
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs index 7bf675d..91252f7 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs | |||
@@ -84,218 +84,234 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
84 | Debug.Assert(heightRanges.Length == 4); | 84 | Debug.Assert(heightRanges.Length == 4); |
85 | 85 | ||
86 | Bitmap[] detailTexture = new Bitmap[4]; | 86 | Bitmap[] detailTexture = new Bitmap[4]; |
87 | Bitmap output = null; | ||
88 | BitmapData outputData = null; | ||
87 | 89 | ||
88 | if (textureTerrain) | 90 | try |
89 | { | 91 | { |
90 | // Swap empty terrain textureIDs with default IDs | 92 | if (textureTerrain) |
91 | for (int i = 0; i < textureIDs.Length; i++) | ||
92 | { | 93 | { |
93 | if (textureIDs[i] == UUID.Zero) | 94 | // Swap empty terrain textureIDs with default IDs |
94 | textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; | 95 | for (int i = 0; i < textureIDs.Length; i++) |
95 | } | ||
96 | |||
97 | #region Texture Fetching | ||
98 | |||
99 | if (assetService != null) | ||
100 | { | ||
101 | for (int i = 0; i < 4; i++) | ||
102 | { | 96 | { |
103 | AssetBase asset; | 97 | if (textureIDs[i] == UUID.Zero) |
104 | UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); | 98 | textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; |
105 | 99 | } | |
106 | // Try to fetch a cached copy of the decoded/resized version of this texture | 100 | |
107 | asset = assetService.GetCached(cacheID.ToString()); | 101 | #region Texture Fetching |
108 | if (asset != null) | 102 | |
109 | { | 103 | if (assetService != null) |
110 | try | 104 | { |
111 | { | 105 | for (int i = 0; i < 4; i++) |
112 | using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) | ||
113 | detailTexture[i] = (Bitmap)Image.FromStream(stream); | ||
114 | } | ||
115 | catch (Exception ex) | ||
116 | { | ||
117 | m_log.Warn("Failed to decode cached terrain texture " + cacheID + | ||
118 | " (textureID: " + textureIDs[i] + "): " + ex.Message); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | if (detailTexture[i] == null) | ||
123 | { | 106 | { |
124 | // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG | 107 | AssetBase asset; |
125 | asset = assetService.Get(textureIDs[i].ToString()); | 108 | UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); |
109 | |||
110 | // Try to fetch a cached copy of the decoded/resized version of this texture | ||
111 | asset = assetService.GetCached(cacheID.ToString()); | ||
126 | if (asset != null) | 112 | if (asset != null) |
127 | { | 113 | { |
128 | try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } | 114 | try |
115 | { | ||
116 | using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) | ||
117 | detailTexture[i] = (Bitmap)Image.FromStream(stream); | ||
118 | } | ||
129 | catch (Exception ex) | 119 | catch (Exception ex) |
130 | { | 120 | { |
131 | m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); | 121 | m_log.Warn("Failed to decode cached terrain texture " + cacheID + |
122 | " (textureID: " + textureIDs[i] + "): " + ex.Message); | ||
132 | } | 123 | } |
133 | } | 124 | } |
134 | 125 | ||
135 | if (detailTexture[i] != null) | 126 | if (detailTexture[i] == null) |
136 | { | 127 | { |
137 | Bitmap bitmap = detailTexture[i]; | 128 | // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG |
138 | 129 | asset = assetService.Get(textureIDs[i].ToString()); | |
139 | // Make sure this texture is the correct size, otherwise resize | 130 | if (asset != null) |
140 | if (bitmap.Width != 256 || bitmap.Height != 256) | ||
141 | bitmap = ImageUtils.ResizeImage(bitmap, 256, 256); | ||
142 | |||
143 | // Save the decoded and resized texture to the cache | ||
144 | byte[] data; | ||
145 | using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) | ||
146 | { | 131 | { |
147 | bitmap.Save(stream, ImageFormat.Png); | 132 | try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } |
148 | data = stream.ToArray(); | 133 | catch (Exception ex) |
134 | { | ||
135 | m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); | ||
136 | } | ||
149 | } | 137 | } |
150 | 138 | ||
151 | // Cache a PNG copy of this terrain texture | 139 | if (detailTexture[i] != null) |
152 | AssetBase newAsset = new AssetBase | ||
153 | { | 140 | { |
154 | Data = data, | 141 | Bitmap bitmap = detailTexture[i]; |
155 | Description = "PNG", | 142 | |
156 | Flags = AssetFlags.Collectable, | 143 | // Make sure this texture is the correct size, otherwise resize |
157 | FullID = cacheID, | 144 | if (bitmap.Width != 256 || bitmap.Height != 256) |
158 | ID = cacheID.ToString(), | 145 | { |
159 | Local = true, | 146 | using (Bitmap origBitmap = bitmap) |
160 | Name = String.Empty, | 147 | { |
161 | Temporary = true, | 148 | bitmap = ImageUtils.ResizeImage(origBitmap, 256, 256); |
162 | Type = (sbyte)AssetType.Unknown | 149 | } |
163 | }; | 150 | } |
164 | newAsset.Metadata.ContentType = "image/png"; | 151 | |
165 | assetService.Store(newAsset); | 152 | // Save the decoded and resized texture to the cache |
153 | byte[] data; | ||
154 | using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) | ||
155 | { | ||
156 | bitmap.Save(stream, ImageFormat.Png); | ||
157 | data = stream.ToArray(); | ||
158 | } | ||
159 | |||
160 | // Cache a PNG copy of this terrain texture | ||
161 | AssetBase newAsset = new AssetBase | ||
162 | { | ||
163 | Data = data, | ||
164 | Description = "PNG", | ||
165 | Flags = AssetFlags.Collectable, | ||
166 | FullID = cacheID, | ||
167 | ID = cacheID.ToString(), | ||
168 | Local = true, | ||
169 | Name = String.Empty, | ||
170 | Temporary = true, | ||
171 | Type = (sbyte)AssetType.Unknown | ||
172 | }; | ||
173 | newAsset.Metadata.ContentType = "image/png"; | ||
174 | assetService.Store(newAsset); | ||
175 | } | ||
166 | } | 176 | } |
167 | } | 177 | } |
168 | } | 178 | } |
179 | |||
180 | #endregion Texture Fetching | ||
169 | } | 181 | } |
170 | 182 | ||
171 | #endregion Texture Fetching | 183 | // Fill in any missing textures with a solid color |
172 | } | 184 | for (int i = 0; i < 4; i++) |
173 | |||
174 | // Fill in any missing textures with a solid color | ||
175 | for (int i = 0; i < 4; i++) | ||
176 | { | ||
177 | if (detailTexture[i] == null) | ||
178 | { | 185 | { |
179 | // Create a solid color texture for this layer | 186 | if (detailTexture[i] == null) |
180 | detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb); | ||
181 | using (Graphics gfx = Graphics.FromImage(detailTexture[i])) | ||
182 | { | 187 | { |
183 | using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) | 188 | // Create a solid color texture for this layer |
184 | gfx.FillRectangle(brush, 0, 0, 256, 256); | 189 | detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb); |
190 | using (Graphics gfx = Graphics.FromImage(detailTexture[i])) | ||
191 | { | ||
192 | using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) | ||
193 | gfx.FillRectangle(brush, 0, 0, 256, 256); | ||
194 | } | ||
185 | } | 195 | } |
186 | } | 196 | } |
187 | } | 197 | |
188 | 198 | #region Layer Map | |
189 | #region Layer Map | 199 | |
190 | 200 | float[] layermap = new float[256 * 256]; | |
191 | float[] layermap = new float[256 * 256]; | 201 | |
192 | |||
193 | for (int y = 0; y < 256; y++) | ||
194 | { | ||
195 | for (int x = 0; x < 256; x++) | ||
196 | { | ||
197 | float height = heightmap[y * 256 + x]; | ||
198 | |||
199 | float pctX = (float)x / 255f; | ||
200 | float pctY = (float)y / 255f; | ||
201 | |||
202 | // Use bilinear interpolation between the four corners of start height and | ||
203 | // height range to select the current values at this position | ||
204 | float startHeight = ImageUtils.Bilinear( | ||
205 | startHeights[0], | ||
206 | startHeights[2], | ||
207 | startHeights[1], | ||
208 | startHeights[3], | ||
209 | pctX, pctY); | ||
210 | startHeight = Utils.Clamp(startHeight, 0f, 255f); | ||
211 | |||
212 | float heightRange = ImageUtils.Bilinear( | ||
213 | heightRanges[0], | ||
214 | heightRanges[2], | ||
215 | heightRanges[1], | ||
216 | heightRanges[3], | ||
217 | pctX, pctY); | ||
218 | heightRange = Utils.Clamp(heightRange, 0f, 255f); | ||
219 | |||
220 | // Generate two frequencies of perlin noise based on our global position | ||
221 | // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting | ||
222 | Vector3 vec = new Vector3 | ||
223 | ( | ||
224 | ((float)regionPosition.X + x) * 0.20319f, | ||
225 | ((float)regionPosition.Y + y) * 0.20319f, | ||
226 | height * 0.25f | ||
227 | ); | ||
228 | |||
229 | float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f; | ||
230 | float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f; | ||
231 | float noise = (lowFreq + highFreq) * 2f; | ||
232 | |||
233 | // Combine the current height, generated noise, start height, and height range parameters, then scale all of it | ||
234 | float layer = ((height + noise - startHeight) / heightRange) * 4f; | ||
235 | if (Single.IsNaN(layer)) layer = 0f; | ||
236 | layermap[y * 256 + x] = Utils.Clamp(layer, 0f, 3f); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | #endregion Layer Map | ||
241 | |||
242 | #region Texture Compositing | ||
243 | |||
244 | Bitmap output = new Bitmap(256, 256, PixelFormat.Format24bppRgb); | ||
245 | BitmapData outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); | ||
246 | |||
247 | unsafe | ||
248 | { | ||
249 | // Get handles to all of the texture data arrays | ||
250 | BitmapData[] datas = new BitmapData[] | ||
251 | { | ||
252 | detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), | ||
253 | detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat), | ||
254 | detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat), | ||
255 | detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat) | ||
256 | }; | ||
257 | |||
258 | int[] comps = new int[] | ||
259 | { | ||
260 | (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, | ||
261 | (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, | ||
262 | (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, | ||
263 | (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3 | ||
264 | }; | ||
265 | |||
266 | for (int y = 0; y < 256; y++) | 202 | for (int y = 0; y < 256; y++) |
267 | { | 203 | { |
268 | for (int x = 0; x < 256; x++) | 204 | for (int x = 0; x < 256; x++) |
269 | { | 205 | { |
270 | float layer = layermap[y * 256 + x]; | 206 | float height = heightmap[y * 256 + x]; |
271 | 207 | ||
272 | // Select two textures | 208 | float pctX = (float)x / 255f; |
273 | int l0 = (int)Math.Floor(layer); | 209 | float pctY = (float)y / 255f; |
274 | int l1 = Math.Min(l0 + 1, 3); | 210 | |
275 | 211 | // Use bilinear interpolation between the four corners of start height and | |
276 | byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0]; | 212 | // height range to select the current values at this position |
277 | byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; | 213 | float startHeight = ImageUtils.Bilinear( |
278 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; | 214 | startHeights[0], |
279 | 215 | startHeights[2], | |
280 | float aB = *(ptrA + 0); | 216 | startHeights[1], |
281 | float aG = *(ptrA + 1); | 217 | startHeights[3], |
282 | float aR = *(ptrA + 2); | 218 | pctX, pctY); |
283 | 219 | startHeight = Utils.Clamp(startHeight, 0f, 255f); | |
284 | float bB = *(ptrB + 0); | 220 | |
285 | float bG = *(ptrB + 1); | 221 | float heightRange = ImageUtils.Bilinear( |
286 | float bR = *(ptrB + 2); | 222 | heightRanges[0], |
287 | 223 | heightRanges[2], | |
288 | float layerDiff = layer - l0; | 224 | heightRanges[1], |
289 | 225 | heightRanges[3], | |
290 | // Interpolate between the two selected textures | 226 | pctX, pctY); |
291 | *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB)); | 227 | heightRange = Utils.Clamp(heightRange, 0f, 255f); |
292 | *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG)); | 228 | |
293 | *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR)); | 229 | // Generate two frequencies of perlin noise based on our global position |
230 | // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting | ||
231 | Vector3 vec = new Vector3 | ||
232 | ( | ||
233 | ((float)regionPosition.X + x) * 0.20319f, | ||
234 | ((float)regionPosition.Y + y) * 0.20319f, | ||
235 | height * 0.25f | ||
236 | ); | ||
237 | |||
238 | float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f; | ||
239 | float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f; | ||
240 | float noise = (lowFreq + highFreq) * 2f; | ||
241 | |||
242 | // Combine the current height, generated noise, start height, and height range parameters, then scale all of it | ||
243 | float layer = ((height + noise - startHeight) / heightRange) * 4f; | ||
244 | if (Single.IsNaN(layer)) layer = 0f; | ||
245 | layermap[y * 256 + x] = Utils.Clamp(layer, 0f, 3f); | ||
294 | } | 246 | } |
295 | } | 247 | } |
296 | 248 | ||
249 | #endregion Layer Map | ||
250 | |||
251 | #region Texture Compositing | ||
252 | |||
253 | output = new Bitmap(256, 256, PixelFormat.Format24bppRgb); | ||
254 | outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); | ||
255 | |||
256 | unsafe | ||
257 | { | ||
258 | // Get handles to all of the texture data arrays | ||
259 | BitmapData[] datas = new BitmapData[] | ||
260 | { | ||
261 | detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), | ||
262 | detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat), | ||
263 | detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat), | ||
264 | detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat) | ||
265 | }; | ||
266 | |||
267 | int[] comps = new int[] | ||
268 | { | ||
269 | (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, | ||
270 | (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, | ||
271 | (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, | ||
272 | (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3 | ||
273 | }; | ||
274 | |||
275 | for (int y = 0; y < 256; y++) | ||
276 | { | ||
277 | for (int x = 0; x < 256; x++) | ||
278 | { | ||
279 | float layer = layermap[y * 256 + x]; | ||
280 | |||
281 | // Select two textures | ||
282 | int l0 = (int)Math.Floor(layer); | ||
283 | int l1 = Math.Min(l0 + 1, 3); | ||
284 | |||
285 | byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0]; | ||
286 | byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; | ||
287 | byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; | ||
288 | |||
289 | float aB = *(ptrA + 0); | ||
290 | float aG = *(ptrA + 1); | ||
291 | float aR = *(ptrA + 2); | ||
292 | |||
293 | float bB = *(ptrB + 0); | ||
294 | float bG = *(ptrB + 1); | ||
295 | float bR = *(ptrB + 2); | ||
296 | |||
297 | float layerDiff = layer - l0; | ||
298 | |||
299 | // Interpolate between the two selected textures | ||
300 | *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB)); | ||
301 | *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG)); | ||
302 | *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR)); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | for (int i = 0; i < 4; i++) | ||
307 | detailTexture[i].UnlockBits(datas[i]); | ||
308 | } | ||
309 | } | ||
310 | finally | ||
311 | { | ||
297 | for (int i = 0; i < 4; i++) | 312 | for (int i = 0; i < 4; i++) |
298 | detailTexture[i].UnlockBits(datas[i]); | 313 | if (detailTexture[i] != null) |
314 | detailTexture[i].Dispose(); | ||
299 | } | 315 | } |
300 | 316 | ||
301 | output.UnlockBits(outputData); | 317 | output.UnlockBits(outputData); |
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs index e6f2855..3c48d07 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs | |||
@@ -54,8 +54,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
54 | private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3"); | 54 | private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3"); |
55 | private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216); | 55 | private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216); |
56 | 56 | ||
57 | private static readonly ILog m_log = | 57 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
58 | LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
59 | 58 | ||
60 | private Scene m_scene; | 59 | private Scene m_scene; |
61 | private IRendering m_primMesher; | 60 | private IRendering m_primMesher; |
@@ -164,7 +163,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
164 | } | 163 | } |
165 | catch | 164 | catch |
166 | { | 165 | { |
167 | m_log.Warn("[MAPTILE]: Failed to load StartupConfig"); | 166 | m_log.Warn("[WARP 3D IMAGE MODULE]: Failed to load StartupConfig"); |
168 | } | 167 | } |
169 | 168 | ||
170 | m_colors.Clear(); | 169 | m_colors.Clear(); |
@@ -218,7 +217,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
218 | Bitmap bitmap = renderer.Scene.getImage(); | 217 | Bitmap bitmap = renderer.Scene.getImage(); |
219 | 218 | ||
220 | if (m_useAntiAliasing) | 219 | if (m_useAntiAliasing) |
221 | bitmap = ImageUtils.ResizeImage(bitmap, viewport.Width, viewport.Height); | 220 | { |
221 | using (Bitmap origBitmap = bitmap) | ||
222 | bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height); | ||
223 | } | ||
222 | 224 | ||
223 | return bitmap; | 225 | return bitmap; |
224 | } | 226 | } |
@@ -233,7 +235,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
233 | catch (Exception e) | 235 | catch (Exception e) |
234 | { | 236 | { |
235 | // JPEG2000 encoder failed | 237 | // JPEG2000 encoder failed |
236 | m_log.Error("[MAPTILE]: Failed generating terrain map: " + e); | 238 | m_log.Error("[WARP 3D IMAGE MODULE]: Failed generating terrain map: ", e); |
237 | } | 239 | } |
238 | 240 | ||
239 | return null; | 241 | return null; |
@@ -332,8 +334,17 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
332 | uint globalX, globalY; | 334 | uint globalX, globalY; |
333 | Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY); | 335 | Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY); |
334 | 336 | ||
335 | Bitmap image = TerrainSplat.Splat(heightmap, textureIDs, startHeights, heightRanges, new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain); | 337 | warp_Texture texture; |
336 | warp_Texture texture = new warp_Texture(image); | 338 | |
339 | using ( | ||
340 | Bitmap image | ||
341 | = TerrainSplat.Splat( | ||
342 | heightmap, textureIDs, startHeights, heightRanges, | ||
343 | new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain)) | ||
344 | { | ||
345 | texture = new warp_Texture(image); | ||
346 | } | ||
347 | |||
337 | warp_Material material = new warp_Material(texture); | 348 | warp_Material material = new warp_Material(texture); |
338 | material.setReflectivity(50); | 349 | material.setReflectivity(50); |
339 | renderer.Scene.addMaterial("TerrainColor", material); | 350 | renderer.Scene.addMaterial("TerrainColor", material); |
@@ -560,42 +571,46 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
560 | { | 571 | { |
561 | try | 572 | try |
562 | { | 573 | { |
563 | Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream); | 574 | int pixelBytes; |
564 | width = bitmap.Width; | ||
565 | height = bitmap.Height; | ||
566 | 575 | ||
567 | BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat); | 576 | using (Bitmap bitmap = (Bitmap)J2kImage.FromStream(stream)) |
568 | int pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; | ||
569 | |||
570 | // Sum up the individual channels | ||
571 | unsafe | ||
572 | { | 577 | { |
573 | if (pixelBytes == 4) | 578 | width = bitmap.Width; |
579 | height = bitmap.Height; | ||
580 | |||
581 | BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat); | ||
582 | pixelBytes = (bitmap.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; | ||
583 | |||
584 | // Sum up the individual channels | ||
585 | unsafe | ||
574 | { | 586 | { |
575 | for (int y = 0; y < height; y++) | 587 | if (pixelBytes == 4) |
576 | { | 588 | { |
577 | byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); | 589 | for (int y = 0; y < height; y++) |
578 | |||
579 | for (int x = 0; x < width; x++) | ||
580 | { | 590 | { |
581 | b += row[x * pixelBytes + 0]; | 591 | byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); |
582 | g += row[x * pixelBytes + 1]; | 592 | |
583 | r += row[x * pixelBytes + 2]; | 593 | for (int x = 0; x < width; x++) |
584 | a += row[x * pixelBytes + 3]; | 594 | { |
595 | b += row[x * pixelBytes + 0]; | ||
596 | g += row[x * pixelBytes + 1]; | ||
597 | r += row[x * pixelBytes + 2]; | ||
598 | a += row[x * pixelBytes + 3]; | ||
599 | } | ||
585 | } | 600 | } |
586 | } | 601 | } |
587 | } | 602 | else |
588 | else | ||
589 | { | ||
590 | for (int y = 0; y < height; y++) | ||
591 | { | 603 | { |
592 | byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); | 604 | for (int y = 0; y < height; y++) |
593 | |||
594 | for (int x = 0; x < width; x++) | ||
595 | { | 605 | { |
596 | b += row[x * pixelBytes + 0]; | 606 | byte* row = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride); |
597 | g += row[x * pixelBytes + 1]; | 607 | |
598 | r += row[x * pixelBytes + 2]; | 608 | for (int x = 0; x < width; x++) |
609 | { | ||
610 | b += row[x * pixelBytes + 0]; | ||
611 | g += row[x * pixelBytes + 1]; | ||
612 | r += row[x * pixelBytes + 2]; | ||
613 | } | ||
599 | } | 614 | } |
600 | } | 615 | } |
601 | } | 616 | } |
@@ -617,7 +632,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
617 | } | 632 | } |
618 | catch (Exception ex) | 633 | catch (Exception ex) |
619 | { | 634 | { |
620 | m_log.WarnFormat("[MAPTILE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}", textureID, j2kData.Length, ex.Message); | 635 | m_log.WarnFormat( |
636 | "[WARP 3D IMAGE MODULE]: Error decoding JPEG2000 texture {0} ({1} bytes): {2}", | ||
637 | textureID, j2kData.Length, ex.Message); | ||
638 | |||
621 | width = 0; | 639 | width = 0; |
622 | height = 0; | 640 | height = 0; |
623 | return new Color4(0.5f, 0.5f, 0.5f, 1.0f); | 641 | return new Color4(0.5f, 0.5f, 0.5f, 1.0f); |
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index be6b240..724bb4c 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | |||
@@ -1343,14 +1343,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1343 | if (terrain == null) | 1343 | if (terrain == null) |
1344 | return; | 1344 | return; |
1345 | 1345 | ||
1346 | m_log.DebugFormat("[WORLDMAP]: Generating map image for {0}", m_scene.RegionInfo.RegionName); | ||
1347 | |||
1346 | byte[] data = terrain.WriteJpeg2000Image(); | 1348 | byte[] data = terrain.WriteJpeg2000Image(); |
1347 | if (data == null) | 1349 | if (data == null) |
1348 | return; | 1350 | return; |
1349 | 1351 | ||
1350 | byte[] overlay = GenerateOverlay(); | 1352 | byte[] overlay = GenerateOverlay(); |
1351 | 1353 | ||
1352 | m_log.Debug("[WORLDMAP]: STORING MAPTILE IMAGE"); | ||
1353 | |||
1354 | UUID terrainImageID = UUID.Random(); | 1354 | UUID terrainImageID = UUID.Random(); |
1355 | UUID parcelImageID = UUID.Zero; | 1355 | UUID parcelImageID = UUID.Zero; |
1356 | 1356 | ||
@@ -1365,7 +1365,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1365 | asset.Flags = AssetFlags.Maptile; | 1365 | asset.Flags = AssetFlags.Maptile; |
1366 | 1366 | ||
1367 | // Store the new one | 1367 | // Store the new one |
1368 | m_log.DebugFormat("[WORLDMAP]: Storing map tile {0}", asset.ID); | 1368 | m_log.DebugFormat("[WORLDMAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName); |
1369 | |||
1369 | m_scene.AssetService.Store(asset); | 1370 | m_scene.AssetService.Store(asset); |
1370 | 1371 | ||
1371 | if (overlay != null) | 1372 | if (overlay != null) |
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 7688cf8..76a952b 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs | |||
@@ -947,7 +947,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
947 | OnTerrainTaintedDelegate handlerTerrainTainted = OnTerrainTainted; | 947 | OnTerrainTaintedDelegate handlerTerrainTainted = OnTerrainTainted; |
948 | if (handlerTerrainTainted != null) | 948 | if (handlerTerrainTainted != null) |
949 | { | 949 | { |
950 | foreach (OnTerrainTickDelegate d in handlerTerrainTainted.GetInvocationList()) | 950 | foreach (OnTerrainTaintedDelegate d in handlerTerrainTainted.GetInvocationList()) |
951 | { | 951 | { |
952 | try | 952 | try |
953 | { | 953 | { |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b79892d..315b340 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -222,6 +222,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
222 | private int backupMS; | 222 | private int backupMS; |
223 | private int terrainMS; | 223 | private int terrainMS; |
224 | private int landMS; | 224 | private int landMS; |
225 | private int spareMS; | ||
225 | 226 | ||
226 | /// <summary> | 227 | /// <summary> |
227 | /// Tick at which the last frame was processed. | 228 | /// Tick at which the last frame was processed. |
@@ -1408,45 +1409,41 @@ namespace OpenSim.Region.Framework.Scenes | |||
1408 | endFrame = Frame + frames; | 1409 | endFrame = Frame + frames; |
1409 | 1410 | ||
1410 | float physicsFPS = 0f; | 1411 | float physicsFPS = 0f; |
1411 | int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS; | 1412 | int previousFrameTick, tmpMS; |
1412 | int previousFrameTick; | 1413 | int maintc = Util.EnvironmentTickCount(); |
1413 | int maintc; | ||
1414 | int sleepMS; | ||
1415 | int framestart; | ||
1416 | 1414 | ||
1417 | while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) | 1415 | while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) |
1418 | { | 1416 | { |
1419 | framestart = Util.EnvironmentTickCount(); | ||
1420 | ++Frame; | 1417 | ++Frame; |
1421 | 1418 | ||
1422 | // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); | 1419 | // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); |
1423 | 1420 | ||
1424 | agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0; | 1421 | agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; |
1425 | 1422 | ||
1426 | try | 1423 | try |
1427 | { | 1424 | { |
1428 | // Apply taints in terrain module to terrain in physics scene | 1425 | // Apply taints in terrain module to terrain in physics scene |
1429 | if (Frame % m_update_terrain == 0) | 1426 | if (Frame % m_update_terrain == 0) |
1430 | { | 1427 | { |
1431 | terMS = Util.EnvironmentTickCount(); | 1428 | tmpMS = Util.EnvironmentTickCount(); |
1432 | UpdateTerrain(); | 1429 | UpdateTerrain(); |
1433 | terrainMS = Util.EnvironmentTickCountSubtract(terMS); | 1430 | terrainMS = Util.EnvironmentTickCountSubtract(tmpMS); |
1434 | } | 1431 | } |
1435 | 1432 | ||
1436 | tmpPhysicsMS2 = Util.EnvironmentTickCount(); | 1433 | tmpMS = Util.EnvironmentTickCount(); |
1437 | if ((Frame % m_update_physics == 0) && m_physics_enabled) | 1434 | if ((Frame % m_update_physics == 0) && m_physics_enabled) |
1438 | m_sceneGraph.UpdatePreparePhysics(); | 1435 | m_sceneGraph.UpdatePreparePhysics(); |
1439 | physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2); | 1436 | physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS); |
1440 | 1437 | ||
1441 | // Apply any pending avatar force input to the avatar's velocity | 1438 | // Apply any pending avatar force input to the avatar's velocity |
1442 | tmpAgentMS = Util.EnvironmentTickCount(); | 1439 | tmpMS = Util.EnvironmentTickCount(); |
1443 | if (Frame % m_update_entitymovement == 0) | 1440 | if (Frame % m_update_entitymovement == 0) |
1444 | m_sceneGraph.UpdateScenePresenceMovement(); | 1441 | m_sceneGraph.UpdateScenePresenceMovement(); |
1445 | agentMS = Util.EnvironmentTickCountSubtract(tmpAgentMS); | 1442 | agentMS = Util.EnvironmentTickCountSubtract(tmpMS); |
1446 | 1443 | ||
1447 | // Perform the main physics update. This will do the actual work of moving objects and avatars according to their | 1444 | // Perform the main physics update. This will do the actual work of moving objects and avatars according to their |
1448 | // velocity | 1445 | // velocity |
1449 | tmpPhysicsMS = Util.EnvironmentTickCount(); | 1446 | tmpMS = Util.EnvironmentTickCount(); |
1450 | if (Frame % m_update_physics == 0) | 1447 | if (Frame % m_update_physics == 0) |
1451 | { | 1448 | { |
1452 | if (m_physics_enabled) | 1449 | if (m_physics_enabled) |
@@ -1455,9 +1452,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1455 | if (SynchronizeScene != null) | 1452 | if (SynchronizeScene != null) |
1456 | SynchronizeScene(this); | 1453 | SynchronizeScene(this); |
1457 | } | 1454 | } |
1458 | physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); | 1455 | physicsMS = Util.EnvironmentTickCountSubtract(tmpMS); |
1459 | 1456 | ||
1460 | tmpAgentMS = Util.EnvironmentTickCount(); | 1457 | tmpMS = Util.EnvironmentTickCount(); |
1461 | 1458 | ||
1462 | // Check if any objects have reached their targets | 1459 | // Check if any objects have reached their targets |
1463 | CheckAtTargets(); | 1460 | CheckAtTargets(); |
@@ -1472,29 +1469,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
1472 | if (Frame % m_update_presences == 0) | 1469 | if (Frame % m_update_presences == 0) |
1473 | m_sceneGraph.UpdatePresences(); | 1470 | m_sceneGraph.UpdatePresences(); |
1474 | 1471 | ||
1475 | agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS); | 1472 | agentMS += Util.EnvironmentTickCountSubtract(tmpMS); |
1476 | 1473 | ||
1477 | // Delete temp-on-rez stuff | 1474 | // Delete temp-on-rez stuff |
1478 | if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps) | 1475 | if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps) |
1479 | { | 1476 | { |
1480 | tmpTempOnRezMS = Util.EnvironmentTickCount(); | 1477 | tmpMS = Util.EnvironmentTickCount(); |
1481 | m_cleaningTemps = true; | 1478 | m_cleaningTemps = true; |
1482 | Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); | 1479 | Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); |
1483 | tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS); | 1480 | tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS); |
1484 | } | 1481 | } |
1485 | 1482 | ||
1486 | if (Frame % m_update_events == 0) | 1483 | if (Frame % m_update_events == 0) |
1487 | { | 1484 | { |
1488 | evMS = Util.EnvironmentTickCount(); | 1485 | tmpMS = Util.EnvironmentTickCount(); |
1489 | UpdateEvents(); | 1486 | UpdateEvents(); |
1490 | eventMS = Util.EnvironmentTickCountSubtract(evMS); | 1487 | eventMS = Util.EnvironmentTickCountSubtract(tmpMS); |
1491 | } | 1488 | } |
1492 | 1489 | ||
1493 | if (Frame % m_update_backup == 0) | 1490 | if (Frame % m_update_backup == 0) |
1494 | { | 1491 | { |
1495 | backMS = Util.EnvironmentTickCount(); | 1492 | tmpMS = Util.EnvironmentTickCount(); |
1496 | UpdateStorageBackup(); | 1493 | UpdateStorageBackup(); |
1497 | backupMS = Util.EnvironmentTickCountSubtract(backMS); | 1494 | backupMS = Util.EnvironmentTickCountSubtract(tmpMS); |
1498 | } | 1495 | } |
1499 | 1496 | ||
1500 | //if (Frame % m_update_land == 0) | 1497 | //if (Frame % m_update_land == 0) |
@@ -1503,24 +1500,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1503 | // UpdateLand(); | 1500 | // UpdateLand(); |
1504 | // landMS = Util.EnvironmentTickCountSubtract(ldMS); | 1501 | // landMS = Util.EnvironmentTickCountSubtract(ldMS); |
1505 | //} | 1502 | //} |
1506 | |||
1507 | // frameMS = Util.EnvironmentTickCountSubtract(maintc); | ||
1508 | otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; | ||
1509 | |||
1510 | // if (Frame%m_update_avatars == 0) | ||
1511 | // UpdateInWorldTime(); | ||
1512 | StatsReporter.AddPhysicsFPS(physicsFPS); | ||
1513 | StatsReporter.AddTimeDilation(TimeDilation); | ||
1514 | StatsReporter.AddFPS(1); | ||
1515 | |||
1516 | // frameMS currently records work frame times, not total frame times (work + any required sleep to | ||
1517 | // reach min frame time. | ||
1518 | // StatsReporter.addFrameMS(frameMS); | ||
1519 | |||
1520 | StatsReporter.addAgentMS(agentMS); | ||
1521 | StatsReporter.addPhysicsMS(physicsMS + physicsMS2); | ||
1522 | StatsReporter.addOtherMS(otherMS); | ||
1523 | StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); | ||
1524 | 1503 | ||
1525 | if (LoginsDisabled && Frame == 20) | 1504 | if (LoginsDisabled && Frame == 20) |
1526 | { | 1505 | { |
@@ -1571,23 +1550,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
1571 | 1550 | ||
1572 | previousFrameTick = m_lastFrameTick; | 1551 | previousFrameTick = m_lastFrameTick; |
1573 | m_lastFrameTick = Util.EnvironmentTickCount(); | 1552 | m_lastFrameTick = Util.EnvironmentTickCount(); |
1574 | maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, framestart); | 1553 | tmpMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); |
1575 | maintc = (int)(MinFrameTime * 1000) - maintc; | 1554 | tmpMS = (int)(MinFrameTime * 1000) - tmpMS; |
1576 | 1555 | ||
1577 | m_firstHeartbeat = false; | 1556 | m_firstHeartbeat = false; |
1578 | 1557 | ||
1558 | if (tmpMS > 0) | ||
1559 | { | ||
1560 | Thread.Sleep(tmpMS); | ||
1561 | spareMS += tmpMS; | ||
1562 | } | ||
1563 | |||
1564 | frameMS = Util.EnvironmentTickCountSubtract(maintc); | ||
1565 | maintc = Util.EnvironmentTickCount(); | ||
1579 | 1566 | ||
1580 | sleepMS = Util.EnvironmentTickCount(); | 1567 | otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; |
1581 | 1568 | ||
1582 | if (maintc > 0) | 1569 | // if (Frame%m_update_avatars == 0) |
1583 | Thread.Sleep(maintc); | 1570 | // UpdateInWorldTime(); |
1571 | StatsReporter.AddPhysicsFPS(physicsFPS); | ||
1572 | StatsReporter.AddTimeDilation(TimeDilation); | ||
1573 | StatsReporter.AddFPS(1); | ||
1584 | 1574 | ||
1585 | sleepMS = Util.EnvironmentTickCountSubtract(sleepMS); | ||
1586 | frameMS = Util.EnvironmentTickCountSubtract(framestart); | ||
1587 | StatsReporter.addSleepMS(sleepMS); | ||
1588 | StatsReporter.addFrameMS(frameMS); | 1575 | StatsReporter.addFrameMS(frameMS); |
1589 | 1576 | StatsReporter.addAgentMS(agentMS); | |
1590 | // Optionally warn if a frame takes double the amount of time that it should. | 1577 | StatsReporter.addPhysicsMS(physicsMS + physicsMS2); |
1578 | StatsReporter.addOtherMS(otherMS); | ||
1579 | StatsReporter.AddSpareMS(spareMS); | ||
1580 | StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); | ||
1581 | |||
1582 | // Optionally warn if a frame takes double the amount of time that it should. | ||
1591 | if (DebugUpdates | 1583 | if (DebugUpdates |
1592 | && Util.EnvironmentTickCountSubtract( | 1584 | && Util.EnvironmentTickCountSubtract( |
1593 | m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2)) | 1585 | m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2)) |
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 0efe4c4..18e6ece 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | |||
@@ -56,10 +56,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
56 | 56 | ||
57 | public event YourStatsAreWrong OnStatsIncorrect; | 57 | public event YourStatsAreWrong OnStatsIncorrect; |
58 | 58 | ||
59 | private SendStatResult handlerSendStatResult = null; | 59 | private SendStatResult handlerSendStatResult; |
60 | 60 | ||
61 | private YourStatsAreWrong handlerStatsIncorrect = null; | 61 | private YourStatsAreWrong handlerStatsIncorrect; |
62 | 62 | ||
63 | /// <summary> | ||
64 | /// These are the IDs of stats sent in the StatsPacket to the viewer. | ||
65 | /// </summary> | ||
66 | /// <remarks> | ||
67 | /// Some of these are not relevant to OpenSimulator since it is architected differently to other simulators | ||
68 | /// (e.g. script instructions aren't executed as part of the frame loop so 'script time' is tricky). | ||
69 | /// </remarks> | ||
63 | public enum Stats : uint | 70 | public enum Stats : uint |
64 | { | 71 | { |
65 | TimeDilation = 0, | 72 | TimeDilation = 0, |
@@ -83,20 +90,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
83 | OutPacketsPerSecond = 18, | 90 | OutPacketsPerSecond = 18, |
84 | PendingDownloads = 19, | 91 | PendingDownloads = 19, |
85 | PendingUploads = 20, | 92 | PendingUploads = 20, |
86 | VirtualSizeKB = 21, | 93 | VirtualSizeKb = 21, |
87 | ResidentSizeKB = 22, | 94 | ResidentSizeKb = 22, |
88 | PendingLocalUploads = 23, | 95 | PendingLocalUploads = 23, |
89 | UnAckedBytes = 24, | 96 | UnAckedBytes = 24, |
90 | PhysicsPinnedTasks = 25, | 97 | PhysicsPinnedTasks = 25, |
91 | PhysicsLODTasks = 26, | 98 | PhysicsLodTasks = 26, |
92 | PhysicsStepMS = 27, | 99 | SimPhysicsStepMs = 27, |
93 | PhysicsShapeMS = 28, | 100 | SimPhysicsShapeMs = 28, |
94 | PhysicsOtherMS = 29, | 101 | SimPhysicsOtherMs = 29, |
95 | PhysicsMemory = 30, | 102 | SimPhysicsMemory = 30, |
96 | ScriptEPS = 31, | 103 | ScriptEps = 31, |
97 | SimSpareTime = 32, | 104 | SimSpareMs = 32, |
98 | SimSleepTime = 33, | 105 | SimSleepMs = 33, |
99 | IOPumpTime = 34 | 106 | SimIoPumpTime = 34 |
100 | } | 107 | } |
101 | 108 | ||
102 | /// <summary> | 109 | /// <summary> |
@@ -130,10 +137,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
130 | private Dictionary<string, float> m_lastReportedExtraSimStats = new Dictionary<string, float>(); | 137 | private Dictionary<string, float> m_lastReportedExtraSimStats = new Dictionary<string, float>(); |
131 | 138 | ||
132 | // Sending a stats update every 3 seconds- | 139 | // Sending a stats update every 3 seconds- |
133 | private int statsUpdatesEveryMS = 3000; | 140 | private int m_statsUpdatesEveryMS = 3000; |
134 | private float statsUpdateFactor = 0; | 141 | private float m_statsUpdateFactor; |
135 | private float m_timeDilation = 0; | 142 | private float m_timeDilation; |
136 | private int m_fps = 0; | 143 | private int m_fps; |
144 | |||
145 | /// <summary> | ||
146 | /// Number of the last frame on which we processed a stats udpate. | ||
147 | /// </summary> | ||
148 | private uint m_lastUpdateFrame; | ||
137 | 149 | ||
138 | /// <summary> | 150 | /// <summary> |
139 | /// Our nominal fps target, as expected in fps stats when a sim is running normally. | 151 | /// Our nominal fps target, as expected in fps stats when a sim is running normally. |
@@ -151,43 +163,42 @@ namespace OpenSim.Region.Framework.Scenes | |||
151 | private float m_reportedFpsCorrectionFactor = 5; | 163 | private float m_reportedFpsCorrectionFactor = 5; |
152 | 164 | ||
153 | // saved last reported value so there is something available for llGetRegionFPS | 165 | // saved last reported value so there is something available for llGetRegionFPS |
154 | private float lastReportedSimFPS = 0; | 166 | private float lastReportedSimFPS; |
155 | private float[] lastReportedSimStats = new float[23]; | 167 | private float[] lastReportedSimStats = new float[22]; |
156 | private float m_pfps = 0; | 168 | private float m_pfps; |
157 | 169 | ||
158 | /// <summary> | 170 | /// <summary> |
159 | /// Number of agent updates requested in this stats cycle | 171 | /// Number of agent updates requested in this stats cycle |
160 | /// </summary> | 172 | /// </summary> |
161 | private int m_agentUpdates = 0; | 173 | private int m_agentUpdates; |
162 | 174 | ||
163 | /// <summary> | 175 | /// <summary> |
164 | /// Number of object updates requested in this stats cycle | 176 | /// Number of object updates requested in this stats cycle |
165 | /// </summary> | 177 | /// </summary> |
166 | private int m_objectUpdates; | 178 | private int m_objectUpdates; |
167 | 179 | ||
168 | private int m_frameMS = 0; | 180 | private int m_frameMS; |
169 | private int m_netMS = 0; | 181 | private int m_spareMS; |
170 | private int m_agentMS = 0; | 182 | private int m_netMS; |
171 | private int m_physicsMS = 0; | 183 | private int m_agentMS; |
172 | private int m_imageMS = 0; | 184 | private int m_physicsMS; |
173 | private int m_otherMS = 0; | 185 | private int m_imageMS; |
174 | private int m_sleeptimeMS = 0; | 186 | private int m_otherMS; |
175 | |||
176 | 187 | ||
177 | //Ckrinke: (3-21-08) Comment out to remove a compiler warning. Bring back into play when needed. | 188 | //Ckrinke: (3-21-08) Comment out to remove a compiler warning. Bring back into play when needed. |
178 | //Ckrinke private int m_scriptMS = 0; | 189 | //Ckrinke private int m_scriptMS = 0; |
179 | 190 | ||
180 | private int m_rootAgents = 0; | 191 | private int m_rootAgents; |
181 | private int m_childAgents = 0; | 192 | private int m_childAgents; |
182 | private int m_numPrim = 0; | 193 | private int m_numPrim; |
183 | private int m_inPacketsPerSecond = 0; | 194 | private int m_inPacketsPerSecond; |
184 | private int m_outPacketsPerSecond = 0; | 195 | private int m_outPacketsPerSecond; |
185 | private int m_activePrim = 0; | 196 | private int m_activePrim; |
186 | private int m_unAckedBytes = 0; | 197 | private int m_unAckedBytes; |
187 | private int m_pendingDownloads = 0; | 198 | private int m_pendingDownloads; |
188 | private int m_pendingUploads = 0; | 199 | private int m_pendingUploads = 0; // FIXME: Not currently filled in |
189 | private int m_activeScripts = 0; | 200 | private int m_activeScripts; |
190 | private int m_scriptLinesPerSecond = 0; | 201 | private int m_scriptLinesPerSecond; |
191 | 202 | ||
192 | private int m_objectCapacity = 45000; | 203 | private int m_objectCapacity = 45000; |
193 | 204 | ||
@@ -203,13 +214,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
203 | { | 214 | { |
204 | m_scene = scene; | 215 | m_scene = scene; |
205 | m_reportedFpsCorrectionFactor = scene.MinFrameTime * m_nominalReportedFps; | 216 | m_reportedFpsCorrectionFactor = scene.MinFrameTime * m_nominalReportedFps; |
206 | statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000); | 217 | m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000); |
207 | ReportingRegion = scene.RegionInfo; | 218 | ReportingRegion = scene.RegionInfo; |
208 | 219 | ||
209 | m_objectCapacity = scene.RegionInfo.ObjectCapacity; | 220 | m_objectCapacity = scene.RegionInfo.ObjectCapacity; |
210 | m_report.AutoReset = true; | 221 | m_report.AutoReset = true; |
211 | m_report.Interval = statsUpdatesEveryMS; | 222 | m_report.Interval = m_statsUpdatesEveryMS; |
212 | m_report.Elapsed += statsHeartBeat; | 223 | m_report.Elapsed += TriggerStatsHeartbeat; |
213 | m_report.Enabled = true; | 224 | m_report.Enabled = true; |
214 | 225 | ||
215 | if (StatsManager.SimExtraStats != null) | 226 | if (StatsManager.SimExtraStats != null) |
@@ -218,7 +229,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
218 | 229 | ||
219 | public void Close() | 230 | public void Close() |
220 | { | 231 | { |
221 | m_report.Elapsed -= statsHeartBeat; | 232 | m_report.Elapsed -= TriggerStatsHeartbeat; |
222 | m_report.Close(); | 233 | m_report.Close(); |
223 | } | 234 | } |
224 | 235 | ||
@@ -228,14 +239,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
228 | /// <param name='ms'></param> | 239 | /// <param name='ms'></param> |
229 | public void SetUpdateMS(int ms) | 240 | public void SetUpdateMS(int ms) |
230 | { | 241 | { |
231 | statsUpdatesEveryMS = ms; | 242 | m_statsUpdatesEveryMS = ms; |
232 | statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000); | 243 | m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000); |
233 | m_report.Interval = statsUpdatesEveryMS; | 244 | m_report.Interval = m_statsUpdatesEveryMS; |
245 | } | ||
246 | |||
247 | private void TriggerStatsHeartbeat(object sender, EventArgs args) | ||
248 | { | ||
249 | try | ||
250 | { | ||
251 | statsHeartBeat(sender, args); | ||
252 | } | ||
253 | catch (Exception e) | ||
254 | { | ||
255 | m_log.Warn(string.Format( | ||
256 | "[SIM STATS REPORTER] Update for {0} failed with exception ", | ||
257 | m_scene.RegionInfo.RegionName), e); | ||
258 | } | ||
234 | } | 259 | } |
235 | 260 | ||
236 | private void statsHeartBeat(object sender, EventArgs e) | 261 | private void statsHeartBeat(object sender, EventArgs e) |
237 | { | 262 | { |
238 | SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23]; | 263 | SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[22]; |
239 | SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); | 264 | SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); |
240 | 265 | ||
241 | // Know what's not thread safe in Mono... modifying timers. | 266 | // Know what's not thread safe in Mono... modifying timers. |
@@ -262,7 +287,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
262 | int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor); | 287 | int reportedFPS = (int)(m_fps * m_reportedFpsCorrectionFactor); |
263 | 288 | ||
264 | // save the reported value so there is something available for llGetRegionFPS | 289 | // save the reported value so there is something available for llGetRegionFPS |
265 | lastReportedSimFPS = reportedFPS / statsUpdateFactor; | 290 | lastReportedSimFPS = reportedFPS / m_statsUpdateFactor; |
266 | 291 | ||
267 | float physfps = ((m_pfps / 1000)); | 292 | float physfps = ((m_pfps / 1000)); |
268 | 293 | ||
@@ -273,7 +298,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
273 | physfps = 0; | 298 | physfps = 0; |
274 | 299 | ||
275 | #endregion | 300 | #endregion |
276 | float factor = 1 / statsUpdateFactor; | ||
277 | if (reportedFPS <= 0) | 301 | if (reportedFPS <= 0) |
278 | reportedFPS = 1; | 302 | reportedFPS = 1; |
279 | 303 | ||
@@ -284,21 +308,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
284 | float targetframetime = 1100.0f / (float)m_nominalReportedFps; | 308 | float targetframetime = 1100.0f / (float)m_nominalReportedFps; |
285 | 309 | ||
286 | float sparetime; | 310 | float sparetime; |
287 | float sleeptime; | ||
288 | if (TotalFrameTime > targetframetime) | 311 | if (TotalFrameTime > targetframetime) |
289 | { | 312 | { |
290 | sparetime = 0; | 313 | sparetime = 0; |
291 | sleeptime = 0; | ||
292 | } | ||
293 | else | ||
294 | { | ||
295 | sparetime = m_frameMS - m_physicsMS - m_agentMS; | ||
296 | sparetime *= perframe; | ||
297 | if (sparetime < 0) | ||
298 | sparetime = 0; | ||
299 | else if (sparetime > TotalFrameTime) | ||
300 | sparetime = TotalFrameTime; | ||
301 | sleeptime = m_sleeptimeMS * perframe; | ||
302 | } | 314 | } |
303 | 315 | ||
304 | m_rootAgents = m_scene.SceneGraph.GetRootAgentCount(); | 316 | m_rootAgents = m_scene.SceneGraph.GetRootAgentCount(); |
@@ -315,11 +327,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
315 | // m_otherMS = m_frameMS - m_physicsMS - m_imageMS - m_netMS - m_agentMS; | 327 | // m_otherMS = m_frameMS - m_physicsMS - m_imageMS - m_netMS - m_agentMS; |
316 | // m_imageMS m_netMS are not included in m_frameMS | 328 | // m_imageMS m_netMS are not included in m_frameMS |
317 | 329 | ||
318 | m_otherMS = m_frameMS - m_physicsMS - m_agentMS - m_sleeptimeMS; | 330 | m_otherMS = m_frameMS - m_physicsMS - m_agentMS; |
319 | if (m_otherMS < 0) | 331 | if (m_otherMS < 0) |
320 | m_otherMS = 0; | 332 | m_otherMS = 0; |
321 | 333 | ||
322 | for (int i = 0; i < 23; i++) | 334 | uint thisFrame = m_scene.Frame; |
335 | float framesUpdated = (float)(thisFrame - m_lastUpdateFrame) * m_reportedFpsCorrectionFactor; | ||
336 | m_lastUpdateFrame = thisFrame; | ||
337 | |||
338 | // Avoid div-by-zero if somehow we've not updated any frames. | ||
339 | if (framesUpdated == 0) | ||
340 | framesUpdated = 1; | ||
341 | |||
342 | for (int i = 0; i < 22; i++) | ||
323 | { | 343 | { |
324 | sb[i] = new SimStatsPacket.StatBlock(); | 344 | sb[i] = new SimStatsPacket.StatBlock(); |
325 | } | 345 | } |
@@ -328,13 +348,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
328 | sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); | 348 | sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); |
329 | 349 | ||
330 | sb[1].StatID = (uint) Stats.SimFPS; | 350 | sb[1].StatID = (uint) Stats.SimFPS; |
331 | sb[1].StatValue = reportedFPS / statsUpdateFactor; | 351 | sb[1].StatValue = reportedFPS / m_statsUpdateFactor; |
332 | 352 | ||
333 | sb[2].StatID = (uint) Stats.PhysicsFPS; | 353 | sb[2].StatID = (uint) Stats.PhysicsFPS; |
334 | sb[2].StatValue = physfps / statsUpdateFactor; | 354 | sb[2].StatValue = physfps / m_statsUpdateFactor; |
335 | 355 | ||
336 | sb[3].StatID = (uint) Stats.AgentUpdates; | 356 | sb[3].StatID = (uint) Stats.AgentUpdates; |
337 | sb[3].StatValue = (m_agentUpdates / statsUpdateFactor); | 357 | sb[3].StatValue = (m_agentUpdates / m_statsUpdateFactor); |
338 | 358 | ||
339 | sb[4].StatID = (uint) Stats.Agents; | 359 | sb[4].StatID = (uint) Stats.Agents; |
340 | sb[4].StatValue = m_rootAgents; | 360 | sb[4].StatValue = m_rootAgents; |
@@ -349,38 +369,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
349 | sb[7].StatValue = m_activePrim; | 369 | sb[7].StatValue = m_activePrim; |
350 | 370 | ||
351 | sb[8].StatID = (uint)Stats.FrameMS; | 371 | sb[8].StatID = (uint)Stats.FrameMS; |
352 | // sb[8].StatValue = m_frameMS / statsUpdateFactor; | 372 | sb[8].StatValue = m_frameMS / framesUpdated; |
353 | sb[8].StatValue = TotalFrameTime; | ||
354 | 373 | ||
355 | sb[9].StatID = (uint)Stats.NetMS; | 374 | sb[9].StatID = (uint)Stats.NetMS; |
356 | // sb[9].StatValue = m_netMS / statsUpdateFactor; | 375 | sb[9].StatValue = m_netMS / framesUpdated; |
357 | sb[9].StatValue = m_netMS * perframe; | ||
358 | 376 | ||
359 | sb[10].StatID = (uint)Stats.PhysicsMS; | 377 | sb[10].StatID = (uint)Stats.PhysicsMS; |
360 | // sb[10].StatValue = m_physicsMS / statsUpdateFactor; | 378 | sb[10].StatValue = m_physicsMS / framesUpdated; |
361 | sb[10].StatValue = m_physicsMS * perframe; | ||
362 | 379 | ||
363 | sb[11].StatID = (uint)Stats.ImageMS ; | 380 | sb[11].StatID = (uint)Stats.ImageMS ; |
364 | // sb[11].StatValue = m_imageMS / statsUpdateFactor; | 381 | sb[11].StatValue = m_imageMS / framesUpdated; |
365 | sb[11].StatValue = m_imageMS * perframe; | ||
366 | 382 | ||
367 | sb[12].StatID = (uint)Stats.OtherMS; | 383 | sb[12].StatID = (uint)Stats.OtherMS; |
368 | // sb[12].StatValue = m_otherMS / statsUpdateFactor; | 384 | sb[12].StatValue = m_otherMS / framesUpdated; |
369 | sb[12].StatValue = m_otherMS * perframe; | ||
370 | |||
371 | 385 | ||
372 | sb[13].StatID = (uint)Stats.InPacketsPerSecond; | 386 | sb[13].StatID = (uint)Stats.InPacketsPerSecond; |
373 | sb[13].StatValue = (m_inPacketsPerSecond / statsUpdateFactor); | 387 | sb[13].StatValue = (m_inPacketsPerSecond / m_statsUpdateFactor); |
374 | 388 | ||
375 | sb[14].StatID = (uint)Stats.OutPacketsPerSecond; | 389 | sb[14].StatID = (uint)Stats.OutPacketsPerSecond; |
376 | sb[14].StatValue = (m_outPacketsPerSecond / statsUpdateFactor); | 390 | sb[14].StatValue = (m_outPacketsPerSecond / m_statsUpdateFactor); |
377 | 391 | ||
378 | sb[15].StatID = (uint)Stats.UnAckedBytes; | 392 | sb[15].StatID = (uint)Stats.UnAckedBytes; |
379 | sb[15].StatValue = m_unAckedBytes; | 393 | sb[15].StatValue = m_unAckedBytes; |
380 | 394 | ||
381 | sb[16].StatID = (uint)Stats.AgentMS; | 395 | sb[16].StatID = (uint)Stats.AgentMS; |
382 | // sb[16].StatValue = m_agentMS / statsUpdateFactor; | 396 | sb[16].StatValue = m_agentMS / framesUpdated; |
383 | sb[16].StatValue = m_agentMS * perframe; | ||
384 | 397 | ||
385 | sb[17].StatID = (uint)Stats.PendingDownloads; | 398 | sb[17].StatID = (uint)Stats.PendingDownloads; |
386 | sb[17].StatValue = m_pendingDownloads; | 399 | sb[17].StatValue = m_pendingDownloads; |
@@ -392,15 +405,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
392 | sb[19].StatValue = m_activeScripts; | 405 | sb[19].StatValue = m_activeScripts; |
393 | 406 | ||
394 | sb[20].StatID = (uint)Stats.ScriptLinesPerSecond; | 407 | sb[20].StatID = (uint)Stats.ScriptLinesPerSecond; |
395 | sb[20].StatValue = m_scriptLinesPerSecond / statsUpdateFactor; | 408 | sb[20].StatValue = m_scriptLinesPerSecond / m_statsUpdateFactor; |
396 | 409 | ||
397 | sb[21].StatID = (uint)Stats.SimSpareTime; | 410 | sb[21].StatID = (uint)Stats.SimSpareMs; |
398 | sb[21].StatValue = sparetime; | 411 | sb[21].StatValue = m_spareMS / framesUpdated; |
399 | 412 | ||
400 | sb[22].StatID = (uint)Stats.SimSleepTime; | 413 | for (int i = 0; i < 22; i++) |
401 | sb[22].StatValue = sleeptime; | ||
402 | |||
403 | for (int i = 0; i < 23; i++) | ||
404 | { | 414 | { |
405 | lastReportedSimStats[i] = sb[i].StatValue; | 415 | lastReportedSimStats[i] = sb[i].StatValue; |
406 | } | 416 | } |
@@ -419,7 +429,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
419 | // Extra statistics that aren't currently sent to clients | 429 | // Extra statistics that aren't currently sent to clients |
420 | lock (m_lastReportedExtraSimStats) | 430 | lock (m_lastReportedExtraSimStats) |
421 | { | 431 | { |
422 | m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / statsUpdateFactor; | 432 | m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; |
423 | 433 | ||
424 | Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); | 434 | Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); |
425 | 435 | ||
@@ -427,16 +437,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
427 | { | 437 | { |
428 | foreach (KeyValuePair<string, float> tuple in physicsStats) | 438 | foreach (KeyValuePair<string, float> tuple in physicsStats) |
429 | { | 439 | { |
430 | m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / statsUpdateFactor; | 440 | // FIXME: An extremely dirty hack to divide MS stats per frame rather than per second |
441 | // Need to change things so that stats source can indicate whether they are per second or | ||
442 | // per frame. | ||
443 | if (tuple.Key.EndsWith("MS")) | ||
444 | m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / framesUpdated; | ||
445 | else | ||
446 | m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / m_statsUpdateFactor; | ||
431 | } | 447 | } |
432 | } | 448 | } |
433 | } | 449 | } |
434 | 450 | ||
435 | resetvalues(); | 451 | ResetValues(); |
436 | } | 452 | } |
437 | } | 453 | } |
438 | 454 | ||
439 | private void resetvalues() | 455 | private void ResetValues() |
440 | { | 456 | { |
441 | m_timeDilation = 0; | 457 | m_timeDilation = 0; |
442 | m_fps = 0; | 458 | m_fps = 0; |
@@ -454,7 +470,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
454 | m_physicsMS = 0; | 470 | m_physicsMS = 0; |
455 | m_imageMS = 0; | 471 | m_imageMS = 0; |
456 | m_otherMS = 0; | 472 | m_otherMS = 0; |
457 | m_sleeptimeMS = 0; | 473 | m_spareMS = 0; |
458 | 474 | ||
459 | //Ckrinke This variable is not used, so comment to remove compiler warning until it is used. | 475 | //Ckrinke This variable is not used, so comment to remove compiler warning until it is used. |
460 | //Ckrinke m_scriptMS = 0; | 476 | //Ckrinke m_scriptMS = 0; |
@@ -533,6 +549,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
533 | m_frameMS += ms; | 549 | m_frameMS += ms; |
534 | } | 550 | } |
535 | 551 | ||
552 | public void AddSpareMS(int ms) | ||
553 | { | ||
554 | m_spareMS += ms; | ||
555 | } | ||
556 | |||
536 | public void addNetMS(int ms) | 557 | public void addNetMS(int ms) |
537 | { | 558 | { |
538 | m_netMS += ms; | 559 | m_netMS += ms; |
@@ -558,11 +579,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
558 | m_otherMS += ms; | 579 | m_otherMS += ms; |
559 | } | 580 | } |
560 | 581 | ||
561 | public void addSleepMS(int ms) | ||
562 | { | ||
563 | m_sleeptimeMS += ms; | ||
564 | } | ||
565 | |||
566 | public void AddPendingDownloads(int count) | 582 | public void AddPendingDownloads(int count) |
567 | { | 583 | { |
568 | m_pendingDownloads += count; | 584 | m_pendingDownloads += count; |
diff --git a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs index 48c242d..1aee39a 100644 --- a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs +++ b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs | |||
@@ -113,14 +113,15 @@ namespace OpenSim.Region.OptionalModules.World.WorldView | |||
113 | if (!m_Enabled) | 113 | if (!m_Enabled) |
114 | return new Byte[0]; | 114 | return new Byte[0]; |
115 | 115 | ||
116 | Bitmap bmp = m_Generator.CreateViewImage(pos, rot, fov, width, | 116 | using (Bitmap bmp = m_Generator.CreateViewImage(pos, rot, fov, width, height, usetex)) |
117 | height, usetex); | 117 | { |
118 | 118 | using (MemoryStream str = new MemoryStream()) | |
119 | MemoryStream str = new MemoryStream(); | 119 | { |
120 | 120 | bmp.Save(str, ImageFormat.Jpeg); | |
121 | bmp.Save(str, ImageFormat.Jpeg); | ||
122 | 121 | ||
123 | return str.ToArray(); | 122 | return str.ToArray(); |
123 | } | ||
124 | } | ||
124 | } | 125 | } |
125 | } | 126 | } |
126 | } | 127 | } |
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 40daf13..204c4ff 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs | |||
@@ -61,7 +61,7 @@ namespace OpenSim.Region.RegionCombinerModule | |||
61 | /// <summary> | 61 | /// <summary> |
62 | /// Is this module enabled? | 62 | /// Is this module enabled? |
63 | /// </summary> | 63 | /// </summary> |
64 | private bool enabledYN = false; | 64 | private bool m_combineContiguousRegions = false; |
65 | 65 | ||
66 | /// <summary> | 66 | /// <summary> |
67 | /// This holds the root regions for the megaregions. | 67 | /// This holds the root regions for the megaregions. |
@@ -79,14 +79,12 @@ namespace OpenSim.Region.RegionCombinerModule | |||
79 | public void Initialise(IConfigSource source) | 79 | public void Initialise(IConfigSource source) |
80 | { | 80 | { |
81 | IConfig myConfig = source.Configs["Startup"]; | 81 | IConfig myConfig = source.Configs["Startup"]; |
82 | enabledYN = myConfig.GetBoolean("CombineContiguousRegions", false); | 82 | m_combineContiguousRegions = myConfig.GetBoolean("CombineContiguousRegions", false); |
83 | 83 | ||
84 | if (enabledYN) | 84 | MainConsole.Instance.Commands.AddCommand( |
85 | { | 85 | "RegionCombinerModule", false, "fix-phantoms", "fix-phantoms", |
86 | MainConsole.Instance.Commands.AddCommand( | 86 | "Fixes phantom objects after an import to a megaregion or a change from a megaregion back to normal regions", |
87 | "RegionCombinerModule", false, "fix-phantoms", "fix-phantoms", | 87 | FixPhantoms); |
88 | "Fixes phantom objects after an import to megaregions", FixPhantoms); | ||
89 | } | ||
90 | } | 88 | } |
91 | 89 | ||
92 | public void Close() | 90 | public void Close() |
@@ -95,7 +93,7 @@ namespace OpenSim.Region.RegionCombinerModule | |||
95 | 93 | ||
96 | public void AddRegion(Scene scene) | 94 | public void AddRegion(Scene scene) |
97 | { | 95 | { |
98 | if (enabledYN) | 96 | if (m_combineContiguousRegions) |
99 | scene.RegisterModuleInterface<IRegionCombinerModule>(this); | 97 | scene.RegisterModuleInterface<IRegionCombinerModule>(this); |
100 | } | 98 | } |
101 | 99 | ||
@@ -105,7 +103,10 @@ namespace OpenSim.Region.RegionCombinerModule | |||
105 | 103 | ||
106 | public void RegionLoaded(Scene scene) | 104 | public void RegionLoaded(Scene scene) |
107 | { | 105 | { |
108 | if (enabledYN) | 106 | lock (m_startingScenes) |
107 | m_startingScenes.Add(scene.RegionInfo.originRegionID, scene); | ||
108 | |||
109 | if (m_combineContiguousRegions) | ||
109 | { | 110 | { |
110 | RegionLoadedDoWork(scene); | 111 | RegionLoadedDoWork(scene); |
111 | 112 | ||
@@ -208,7 +209,6 @@ namespace OpenSim.Region.RegionCombinerModule | |||
208 | { | 209 | { |
209 | return; | 210 | return; |
210 | } | 211 | } |
211 | |||
212 | } | 212 | } |
213 | } | 213 | } |
214 | 214 | ||
@@ -220,8 +220,6 @@ namespace OpenSim.Region.RegionCombinerModule | |||
220 | return; | 220 | return; |
221 | // | 221 | // |
222 | */ | 222 | */ |
223 | lock (m_startingScenes) | ||
224 | m_startingScenes.Add(scene.RegionInfo.originRegionID, scene); | ||
225 | 223 | ||
226 | // Give each region a standard set of non-infinite borders | 224 | // Give each region a standard set of non-infinite borders |
227 | Border northBorder = new Border(); | 225 | Border northBorder = new Border(); |
@@ -1068,6 +1066,8 @@ namespace OpenSim.Region.RegionCombinerModule | |||
1068 | 1066 | ||
1069 | foreach (Scene s in scenes) | 1067 | foreach (Scene s in scenes) |
1070 | { | 1068 | { |
1069 | MainConsole.Instance.OutputFormat("Fixing phantoms for {0}", s.RegionInfo.RegionName); | ||
1070 | |||
1071 | s.ForEachSOG(so => so.AbsolutePosition = so.AbsolutePosition); | 1071 | s.ForEachSOG(so => so.AbsolutePosition = so.AbsolutePosition); |
1072 | } | 1072 | } |
1073 | } | 1073 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 3b8efd5..9595d48 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -6038,7 +6038,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6038 | } | 6038 | } |
6039 | } | 6039 | } |
6040 | } | 6040 | } |
6041 | List<UUID> presenceIds = new List<UUID>(); | ||
6042 | 6041 | ||
6043 | World.ForEachRootScenePresence( | 6042 | World.ForEachRootScenePresence( |
6044 | delegate (ScenePresence ssp) | 6043 | delegate (ScenePresence ssp) |