diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs index a54b182174f..b8e5ae40b66 100644 --- a/OpenSim/Addons/Groups/Service/GroupsService.cs +++ b/OpenSim/Addons/Groups/Service/GroupsService.cs @@ -1058,13 +1058,24 @@ ExtendedGroupNoticeData _NoticeDataToData(NoticeData data) private bool HasPower(string agentID, UUID groupID, GroupPowers power) { RoleMembershipData[] rmembership = m_Database.RetrieveMemberRoles(groupID, agentID); - if (rmembership == null || (rmembership != null && rmembership.Length == 0)) + if (rmembership is null || rmembership.Length == 0) return false; foreach (RoleMembershipData rdata in rmembership) { + if(rdata is null) + { + m_log.Warn($"[GROUPSERVICE] null membership data entry in group {groupID} for agent {agentID}"); + continue; + } RoleData role = m_Database.RetrieveRole(groupID, rdata.RoleID); - if ( (UInt64.Parse(role.Data["Powers"]) & (ulong)power) != 0 ) + if (role is null) + { + m_log.Warn($"[GROUPSERVICE] role with id {rdata.RoleID} is null"); + continue; + } + + if ((UInt64.Parse(role.Data["Powers"]) & (ulong)power) != 0) return true; } return false; @@ -1073,14 +1084,14 @@ private bool HasPower(string agentID, UUID groupID, GroupPowers power) private bool IsOwner(string agentID, UUID groupID) { GroupData group = m_Database.RetrieveGroup(groupID); - if (group == null) + if (group is null) return false; - RoleMembershipData rmembership = m_Database.RetrieveRoleMember(groupID, new UUID(group.Data["OwnerRoleID"]), agentID); - if (rmembership == null) + if(!UUID.TryParse(group.Data["OwnerRoleID"], out UUID ownerRoleID)) return false; - return true; + RoleMembershipData rmembership = m_Database.RetrieveRoleMember(groupID, ownerRoleID, agentID); + return rmembership is not null; } #endregion diff --git a/OpenSim/ConsoleClient/ConsoleClient.cs b/OpenSim/ConsoleClient/ConsoleClient.cs index 9ab53b891b9..283fd1e1cd3 100644 --- a/OpenSim/ConsoleClient/ConsoleClient.cs +++ b/OpenSim/ConsoleClient/ConsoleClient.cs @@ -75,7 +75,6 @@ static int Main(string[] args) Requester.MakeRequest("http://"+m_Host+":"+m_Port.ToString()+"/StartSession/", String.Format("USER={0}&PASS={1}", m_User, m_Pass), LoginReply); - string pidFile = serverConfig.GetString("PIDFile", String.Empty); while (m_Server.Running) { @@ -83,7 +82,8 @@ static int Main(string[] args) MainConsole.Instance.Prompt(); } - if (pidFile != String.Empty) + string pidFile = serverConfig.GetString("PIDFile", string.Empty); + if (pidFile.Length > 0) File.Delete(pidFile); Environment.Exit(0); diff --git a/OpenSim/Data/MySQL/MySQLAuthenticationData.cs b/OpenSim/Data/MySQL/MySQLAuthenticationData.cs index fef582e8091..7fd3689125e 100644 --- a/OpenSim/Data/MySQL/MySQLAuthenticationData.cs +++ b/OpenSim/Data/MySQL/MySQLAuthenticationData.cs @@ -122,8 +122,7 @@ private void CheckColumnNames(IDataReader result) public bool Store(AuthenticationData data) { - if (data.Data.ContainsKey("UUID")) - data.Data.Remove("UUID"); + data.Data.Remove("UUID"); string[] fields = new List(data.Data.Keys).ToArray(); diff --git a/OpenSim/Data/MySQL/MySQLGroupsData.cs b/OpenSim/Data/MySQL/MySQLGroupsData.cs index 77cb2f4db41..6d886166067 100644 --- a/OpenSim/Data/MySQL/MySQLGroupsData.cs +++ b/OpenSim/Data/MySQL/MySQLGroupsData.cs @@ -199,7 +199,7 @@ public RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID) public RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID) { RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "PrincipalID" }, - new string[] { groupID.ToString(), principalID.ToString() }); + new string[] { groupID.ToString(), principalID }); return data; } diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index b3e39811b3c..94c5f332144 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -171,7 +171,7 @@ public virtual void StoreObject(SceneObjectGroup obj, UUID regionUUID) "PhysicsShapeType, Density, GravityModifier, " + "Friction, Restitution, Vehicle, PhysInertia, DynAttrs, " + "RotationAxisLocks, sopanims, sitactrange, pseudocrc, " + - "lnkstBinData" + + "lnkstBinData, StartStr" + ") values (" + "?UUID, " + "?CreationDate, ?Name, ?Text, " + "?Description, ?SitName, ?TouchName, " + @@ -207,7 +207,7 @@ public virtual void StoreObject(SceneObjectGroup obj, UUID regionUUID) "?PhysicsShapeType, ?Density, ?GravityModifier, " + "?Friction, ?Restitution, ?Vehicle, ?PhysInertia, ?DynAttrs, " + "?RotationAxisLocks, ?sopanims, ?sitactrange, ?pseudocrc, " + - "?lnkstBinData)"; + "?lnkstBinData, ?StartStr)"; FillPrimCommand(cmd, prim, obj.UUID, regionUUID); @@ -362,6 +362,10 @@ public virtual List LoadObjects(UUID regionID) byte[] data = (byte[])reader["lnkstBinData"]; newSog.LinksetData = LinksetData.FromBin(data); } + if(reader["StartStr"] is not DBNull) + { + newSog.RezStringParameter = (string)reader["StartStr"]; + } } else m_log.Warn($"[REGION DB]: duplicated SOG with root prim \"{prim.Name}\" {prim.UUID} in region {regionID}"); @@ -1623,6 +1627,11 @@ private void FillPrimCommand(MySqlCommand cmd, SceneObjectPart prim, UUID sceneG cmd.Parameters.AddWithValue("lnkstBinData", prim.ParentGroup.LinksetData.ToBin()); else cmd.Parameters.AddWithValue("lnkstBinData", null); + + if(prim.IsRoot) + cmd.Parameters.AddWithValue("StartStr", prim.ParentGroup.RezStringParameter); + else + cmd.Parameters.AddWithValue("StartStr", null); } /// diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations index b2c3357c6d6..9def74c4a2b 100644 --- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations @@ -567,3 +567,8 @@ ALTER TABLE `regionsettings` ADD COLUMN `TerrainPBR2` varchar(36) NOT NULL DEFAU ALTER TABLE `regionsettings` ADD COLUMN `TerrainPBR3` varchar(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; ALTER TABLE `regionsettings` ADD COLUMN `TerrainPBR4` varchar(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; COMMIT; + +:VERSION 67 #----- add rez start string param column +BEGIN; +ALTER TABLE `prims` ADD COLUMN `StartStr` text default NULL; +COMMIT; diff --git a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs index 931459aa747..54eb932878c 100755 --- a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs +++ b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs @@ -163,6 +163,10 @@ FROM prims byte[] data = (byte[])reader["lnkstBinData"]; grp.LinksetData = LinksetData.FromBin(data); } + if(reader["StartStr"] is not DBNull) + { + grp.RezStringParameter = (string)reader["StartStr"]; + } } else { @@ -352,7 +356,7 @@ UPDATE prims SET ""ClickAction"" = :ClickAction, ""Material"" = :Material, ""CollisionSound"" = :CollisionSound, ""CollisionSoundVolume"" = :CollisionSoundVolume, ""PassTouches"" = :PassTouches, ""LinkNumber"" = :LinkNumber, ""MediaURL"" = :MediaURL, ""DynAttrs"" = :DynAttrs, ""Vehicle"" = :Vehicle, ""PhysInertia"" = :PhysInertia, ""standtargetx"" =:standtargetx, ""standtargety"" =:standtargety, ""standtargetz"" =:standtargetz, - ""sitactrange"" =:sitactrange, ""pseudocrc"" = :pseudocrc, ""sopanims"" = :sopanims, ""lnkstBinData"" = :lnkstBinData + ""sitactrange"" =:sitactrange, ""pseudocrc"" = :pseudocrc, ""sopanims"" = :sopanims, ""lnkstBinData"" = :lnkstBinData, ""StartStr"" = :StartStr WHERE ""UUID"" = :UUID ; @@ -368,7 +372,7 @@ INSERT INTO ""ForceMouselook"", ""ScriptAccessPin"", ""AllowedDrop"", ""DieAtEdge"", ""SalePrice"", ""SaleType"", ""ColorR"", ""ColorG"", ""ColorB"", ""ColorA"", ""ParticleSystem"", ""ClickAction"", ""Material"", ""CollisionSound"", ""CollisionSoundVolume"", ""PassTouches"", ""LinkNumber"", ""MediaURL"", ""DynAttrs"", ""PhysicsShapeType"", ""Density"", ""GravityModifier"", ""Friction"", ""Restitution"", ""PassCollisions"", ""RotationAxisLocks"", ""RezzerID"" , ""Vehicle"", ""PhysInertia"", - ""standtargetx"", ""standtargety"", ""standtargetz"", ""sitactrange"", ""pseudocrc"",""sopanims"",""lnkstBinData"" + ""standtargetx"", ""standtargety"", ""standtargetz"", ""sitactrange"", ""pseudocrc"",""sopanims"",""lnkstBinData"", ""StartStr"" ) Select :UUID, :CreationDate, :Name, :Text, :Description, :SitName, :TouchName, :ObjectFlags, :OwnerMask, :NextOwnerMask, :GroupMask, :EveryoneMask, :BaseMask, :PositionX, :PositionY, :PositionZ, :GroupPositionX, :GroupPositionY, :GroupPositionZ, :VelocityX, @@ -380,7 +384,7 @@ INSERT INTO :ForceMouselook, :ScriptAccessPin, :AllowedDrop, :DieAtEdge, :SalePrice, :SaleType, :ColorR, :ColorG, :ColorB, :ColorA, :ParticleSystem, :ClickAction, :Material, :CollisionSound, :CollisionSoundVolume, :PassTouches, :LinkNumber, :MediaURL, :DynAttrs, :PhysicsShapeType, :Density, :GravityModifier, :Friction, :Restitution, :PassCollisions, :RotationAxisLocks, :RezzerID, :Vehicle, :PhysInertia, - :standtargetx, :standtargety, :standtargetz,:sitactrange, :pseudocrc, :sopanims, :lnkstBinData + :standtargetx, :standtargety, :standtargetz,:sitactrange, :pseudocrc, :sopanims, :lnkstBinData, :StartStr where not EXISTS (SELECT ""UUID"" FROM prims WHERE ""UUID"" = :UUID); "; @@ -1883,6 +1887,11 @@ private NpgsqlParameter[] CreatePrimParameters(SceneObjectPart prim, UUID sceneG else parameters.Add(_Database.CreateParameterNullBytea("lnkstBinData")); + if(prim.IsRoot) + parameters.Add(_Database.CreateParameter("StartStr", prim.ParentGroup.RezStringParameter)); + else + parameters.Add(_Database.CreateParameter("StartStr", null)); + return parameters.ToArray(); } diff --git a/OpenSim/Data/PGSQL/Resources/RegionStore.migrations b/OpenSim/Data/PGSQL/Resources/RegionStore.migrations index bde59a7c29c..b5653bd8783 100644 --- a/OpenSim/Data/PGSQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/PGSQL/Resources/RegionStore.migrations @@ -1304,3 +1304,8 @@ CREATE TABLE "regionextra" PRIMARY KEY ("RegionID", "Name") ); COMMIT; + +:VERSION 58 #----- add rez start string param column +BEGIN; +ALTER TABLE `prims` ADD COLUMN `StartStr` TEXT; +COMMIT; diff --git a/OpenSim/Data/SQLite/Resources/RegionStore.migrations b/OpenSim/Data/SQLite/Resources/RegionStore.migrations index 11a09e570c2..c3164ea119b 100644 --- a/OpenSim/Data/SQLite/Resources/RegionStore.migrations +++ b/OpenSim/Data/SQLite/Resources/RegionStore.migrations @@ -419,3 +419,8 @@ ALTER TABLE regionsettings ADD COLUMN TerrainPBR2 char(36) NOT NULL DEFAULT '000 ALTER TABLE regionsettings ADD COLUMN TerrainPBR3 char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; ALTER TABLE regionsettings ADD COLUMN TerrainPBR4 char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; COMMIT; + +:VERSION 43 #----- add rez start string param column +BEGIN; +ALTER TABLE `prims` ADD COLUMN `StartStr` TEXT; +COMMIT; diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs index 7ca7d1fd3c0..697876301e0 100644 --- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs +++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs @@ -662,7 +662,10 @@ public List LoadObjects(UUID regionUUID) byte[] data = (byte[])primRow["lnkstBinData"]; group.LinksetData = LinksetData.FromBin(data); } - + if(primRow["StartStr"] is not DBNull) + { + group.RezStringParameter = (string)primRow["StartStr"]; + } createdObjects.Add(group.UUID, group); retvals.Add(group); LoadItems(prim); @@ -1251,6 +1254,7 @@ private static DataTable createPrimTable() createCol(prims, "sopanims", typeof(byte[])); createCol(prims, "lnkstBinData", typeof(byte[])); + createCol(prims, "StartStr", typeof(string)); // Add in contraints prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] }; @@ -2217,6 +2221,11 @@ private static void fillPrimRow(DataRow row, SceneObjectPart prim, UUID sceneGro row["lnkstBinData"] = prim.ParentGroup.LinksetData.ToBin(); else row["lnkstBinData"] = null; + + if (prim.IsRoot) + row["StartStr"] = prim.ParentGroup.RezStringParameter; + else + row["StartStr"] = null; } /// diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index d90b5e0b888..999eb6adca4 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -372,7 +372,7 @@ public void AddWebSocketHandler(string servicepath, WebSocketRequestDelegate han public void RemoveWebSocketHandler(string servicepath) { - m_WebSocketHandlers.TryRemove(servicepath, out WebSocketRequestDelegate dummy); + m_WebSocketHandlers.TryRemove(servicepath, out _); } public List GetStreamHandlerKeys() @@ -526,7 +526,7 @@ public void AddIndexPHPMethodHandler(string key, SimpleStreamMethod sh) public void RemoveIndexPHPMethodHandler(string key) { - m_indexPHPmethods.TryRemove(key, out SimpleStreamMethod sh); + m_indexPHPmethods.TryRemove(key, out _); } public SimpleStreamMethod TryGetIndexPHPMethodHandler(string key) @@ -543,7 +543,7 @@ public void AddGloblaMethodHandler(string key, SimpleStreamMethod sh) public void RemoveGlobalPMethodHandler(string key) { - m_globalMethods.TryRemove(key, out SimpleStreamMethod sh); + m_globalMethods.TryRemove(key, out _); } public bool TryGetGlobalMethodHandler(string key, out SimpleStreamMethod sh) @@ -2299,7 +2299,7 @@ protected override void ProcessRequest(IOSHttpRequest httpRequest, IOSHttpRespon } if (httpRequest.QueryFlags.Contains("about")) { - httpResponse.Redirect("http://opensimulator.org/wiki/0.9.3.0_Release"); + httpResponse.Redirect("http://opensimulator.org/wiki/0.9.3.1_Release"); return; } if (!httpRequest.QueryAsDictionary.TryGetValue("method", out string method) || string.IsNullOrWhiteSpace(method)) diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpContextFactory.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpContextFactory.cs index eed59510aaa..72d4f4eff37 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpContextFactory.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpContextFactory.cs @@ -61,12 +61,11 @@ private void OnRequestReceived(object sender, RequestEventArgs e) private void OnFreeContext(object sender, DisconnectedEventArgs e) { - var imp = sender as HttpClientContext; - if (imp == null || imp.contextID < 0) - return; - - m_activeContexts.TryRemove(imp.contextID, out HttpClientContext dummy); - imp.Close(); + if (sender is HttpClientContext imp && imp.contextID >= 0) + { + m_activeContexts.TryRemove(imp.contextID, out _); + imp.Close(); + } } diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index 87eeb136b09..60a99890d5b 100755 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -86,7 +86,7 @@ protected void CreatePIDFile(string path) try { - string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(); + string pidstring = Environment.ProcessId.ToString(); using (FileStream fs = File.Create(path)) { diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs index 68e2babe2d0..26e7f3bd0ee 100644 --- a/OpenSim/Framework/TaskInventoryItem.cs +++ b/OpenSim/Framework/TaskInventoryItem.cs @@ -172,7 +172,7 @@ public void ResetIDs(UUID partID) public TaskInventoryItem() { ScriptRunning = true; - CreationDate = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; + CreationDate = (uint)Util.UnixTimeSinceEpoch(); } } } diff --git a/OpenSim/Framework/VersionInfo.cs b/OpenSim/Framework/VersionInfo.cs index 6afaad3a4f6..b81cf2bb87a 100644 --- a/OpenSim/Framework/VersionInfo.cs +++ b/OpenSim/Framework/VersionInfo.cs @@ -29,8 +29,8 @@ namespace OpenSim { public class VersionInfo { - public const string VersionNumber = "0.9.3.0"; - public const string AssemblyVersionNumber = "0.9.3.0"; + public const string VersionNumber = "0.9.3.1"; + public const string AssemblyVersionNumber = "0.9.3.1"; public const Flavour VERSION_FLAVOUR = Flavour.Dev; diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index cb46b02b6d8..c54e747929b 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -73,37 +73,26 @@ public static void Main(string[] args) // First line, hook the appdomain to the crash reporter AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); - System.AppContext.SetSwitch("System.Drawing.EnableUnixSupport", true); - Culture.SetCurrentCulture(); Culture.SetDefaultCurrentCulture(); - ServicePointManager.DefaultConnectionLimit = 32; - ServicePointManager.MaxServicePointIdleTime = 30000; - - try { ServicePointManager.DnsRefreshTimeout = 5000; } catch { } - ServicePointManager.Expect100Continue = false; - ServicePointManager.UseNagleAlgorithm = false; - - // Add the arguments supplied when running the application to the configuration - ArgvConfigSource configSource = new ArgvConfigSource(args); + AppContext.SetSwitch("System.Drawing.EnableUnixSupport", true); - // Configure Log4Net - configSource.AddSwitch("Startup", "logconfig"); - string logConfigFile = configSource.Configs["Startup"].GetString("logconfig", String.Empty); - if (!string.IsNullOrEmpty(logConfigFile)) + /* + // pre load System.Drawing.Common.dll for the platform + // this will fail if a newer version is present on GAC, bin folder, etc, since LoadFrom only accepts the path, if it cannot find it elsewhere + string targetdll = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),"lib", + (Util.IsWindows() ? "win" : "linux"), "System.Drawing.Common.dll"); + try { - XmlConfigurator.Configure(new System.IO.FileInfo(logConfigFile)); - m_log.InfoFormat("[OPENSIM MAIN]: configured log4net using \"{0}\" as configuration file", - logConfigFile); + Assembly asmb = Assembly.LoadFrom(targetdll); } - else + catch (Exception e) { - XmlConfigurator.Configure(new System.IO.FileInfo("OpenSim.exe.config")); - m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config"); + m_log.Error("Failed to load System.Drawing.Common.dll for current platform" + e.Message); + throw; } - - // temporay set the platform dependent System.Drawing.Common.dll + */ string targetdll = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "System.Drawing.Common.dll"); string src = targetdll + (Util.IsWindows() ? ".win" : ".linux"); @@ -125,44 +114,53 @@ public static void Main(string[] args) throw; } - m_log.InfoFormat( - "[OPENSIM MAIN]: System Locale is {0}", System.Threading.Thread.CurrentThread.CurrentCulture); - if(!Util.IsWindows()) + ServicePointManager.DefaultConnectionLimit = 32; + ServicePointManager.MaxServicePointIdleTime = 30000; + + try { ServicePointManager.DnsRefreshTimeout = 5000; } catch { } + ServicePointManager.Expect100Continue = false; + ServicePointManager.UseNagleAlgorithm = false; + + // Add the arguments supplied when running the application to the configuration + ArgvConfigSource configSource = new ArgvConfigSource(args); + + // Configure Log4Net + configSource.AddSwitch("Startup", "logconfig"); + string logConfigFile = configSource.Configs["Startup"].GetString("logconfig", String.Empty); + if (!string.IsNullOrEmpty(logConfigFile)) { - string monoThreadsPerCpu = System.Environment.GetEnvironmentVariable("MONO_THREADS_PER_CPU"); - m_log.InfoFormat( - "[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset"); + XmlConfigurator.Configure(new System.IO.FileInfo(logConfigFile)); + m_log.Info($"[OPENSIM MAIN]: configured log4net using \"{logConfigFile}\" as configuration file"); + } + else + { + XmlConfigurator.Configure(new System.IO.FileInfo("OpenSim.exe.config")); + m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config"); } - // Verify the Threadpool allocates or uses enough worker and IO completion threads - // .NET 2.0, workerthreads default to 50 * numcores - // .NET 3.0, workerthreads defaults to 250 * numcores - // .NET 4.0, workerthreads are dynamic based on bitness and OS resources - // Max IO Completion threads are 1000 on all 3 CLRs - // - // Mono 2.10.9 to at least Mono 3.1, workerthreads default to 100 * numcores, iocp threads to 4 * numcores + m_log.Info($"[OPENSIM MAIN]: System Locale is {System.Threading.Thread.CurrentThread.CurrentCulture}"); + int workerThreadsMin = 500; - int workerThreadsMax = 1000; // may need further adjustment to match other CLR + int workerThreadsMax = 1000; int iocpThreadsMin = 1000; - int iocpThreadsMax = 2000; // may need further adjustment to match other CLR + int iocpThreadsMax = 2000; System.Threading.ThreadPool.GetMinThreads(out int currentMinWorkerThreads, out int currentMinIocpThreads); - m_log.InfoFormat( - "[OPENSIM MAIN]: Runtime gave us {0} min worker threads and {1} min IOCP threads", - currentMinWorkerThreads, currentMinIocpThreads); + m_log.Info( + $"[OPENSIM MAIN]: Runtime gave us {currentMinWorkerThreads} min worker threads and {currentMinIocpThreads} min IOCP threads"); System.Threading.ThreadPool.GetMaxThreads(out int workerThreads, out int iocpThreads); - m_log.InfoFormat("[OPENSIM MAIN]: Runtime gave us {0} max worker threads and {1} max IOCP threads", workerThreads, iocpThreads); + m_log.Info($"[OPENSIM MAIN]: Runtime gave us {workerThreads} max worker threads and {iocpThreads} max IOCP threads"); if (workerThreads < workerThreadsMin) { workerThreads = workerThreadsMin; - m_log.InfoFormat("[OPENSIM MAIN]: Bumping up max worker threads to {0}",workerThreads); + m_log.Info($"[OPENSIM MAIN]: Bumping up max worker threads to {workerThreads}"); } if (workerThreads > workerThreadsMax) { workerThreads = workerThreadsMax; - m_log.InfoFormat("[OPENSIM MAIN]: Limiting max worker threads to {0}",workerThreads); + m_log.Info($"[OPENSIM MAIN]: Limiting max worker threads to {workerThreads}"); } // Increase the number of IOCP threads available. @@ -170,20 +168,19 @@ public static void Main(string[] args) if (iocpThreads < iocpThreadsMin) { iocpThreads = iocpThreadsMin; - m_log.InfoFormat("[OPENSIM MAIN]: Bumping up max IOCP threads to {0}",iocpThreads); + m_log.Info($"[OPENSIM MAIN]: Bumping up max IOCP threads to {iocpThreads}"); } // Make sure we don't overallocate IOCP threads and thrash system resources if ( iocpThreads > iocpThreadsMax ) { iocpThreads = iocpThreadsMax; - m_log.InfoFormat("[OPENSIM MAIN]: Limiting max IOCP completion threads to {0}",iocpThreads); + m_log.Info($"[OPENSIM MAIN]: Limiting max IOCP completion threads to {iocpThreads}"); } // set the resulting worker and IO completion thread counts back to ThreadPool if ( System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads) ) { - m_log.InfoFormat( - "[OPENSIM MAIN]: Threadpool set to {0} max worker threads and {1} max IOCP threads", - workerThreads, iocpThreads); + m_log.Info( + $"[OPENSIM MAIN]: Threadpool set to {workerThreads} max worker threads and {iocpThreads} max IOCP threads"); } else { @@ -192,17 +189,17 @@ public static void Main(string[] args) // Check if the system is compatible with OpenSimulator. // Ensures that the minimum system requirements are met - string supported = String.Empty; - if (Util.IsEnvironmentSupported(ref supported)) + string error = string.Empty; + if (Util.IsEnvironmentSupported(ref error)) { m_log.Info("[OPENSIM MAIN]: Environment is supported by OpenSimulator."); } else { - m_log.Warn("[OPENSIM MAIN]: Environment is not supported by OpenSimulator (" + supported + ")\n"); + m_log.Warn($"[OPENSIM MAIN]: Environment is not supported by OpenSimulator: {error}\n"); } - m_log.InfoFormat("Default culture changed to {0}",Culture.GetDefaultCurrentCulture().DisplayName); + m_log.Info($"Default culture changed to {Culture.GetDefaultCurrentCulture().DisplayName}"); // Configure nIni aliases and localles @@ -362,7 +359,7 @@ public static void Main(string[] args) } catch (Exception e) { - m_log.ErrorFormat("Command error: {0}", e); + m_log.Error($"Command error: {e}"); } } } @@ -386,22 +383,19 @@ private static void CurrentDomain_UnhandledException(object sender, UnhandledExc // 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"; + string msg = $"\r\nAPPLICATION EXCEPTION DETECTED: {e}\r\n\r\n"; + + Exception ex = (Exception)e.ExceptionObject; - msg += "Exception: " + e.ExceptionObject.ToString() + "\r\n"; - Exception ex = (Exception) e.ExceptionObject; + msg += $"Exception: {ex}\r\n"; if (ex.InnerException != null) { - msg += "InnerException: " + ex.InnerException.ToString() + "\r\n"; + msg += $"InnerException: {ex.InnerException}\r\n"; } - msg += "\r\n"; - msg += "Application is terminating: " + e.IsTerminating.ToString() + "\r\n"; + msg += $"\r\nApplication is terminating: {e.IsTerminating}\r\n"; - m_log.ErrorFormat("[APPLICATION]: {0}", msg); + m_log.Error("[APPLICATION]: + msg"); if (m_saveCrashDumps) { @@ -422,7 +416,7 @@ private static void CurrentDomain_UnhandledException(object sender, UnhandledExc } catch (Exception e2) { - m_log.ErrorFormat("[CRASH LOGGER CRASHED]: {0}", e2); + m_log.Error($"[CRASH LOGGER CRASHED]: {e2}"); } } diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index ae38fb644e5..17b9cee2a9a 100755 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -226,11 +226,11 @@ protected override void StartupSpecific() throw new Exception("CombineContiguousRegions not suported"); } - string pidFile = startupConfig.GetString("PIDFile", String.Empty); - if (pidFile != String.Empty) + string pidFile = startupConfig.GetString("PIDFile", string.Empty); + if (pidFile.Length > 0) CreatePIDFile(pidFile); - userStatsURI = startupConfig.GetString("Stats_URI", String.Empty); + userStatsURI = startupConfig.GetString("Stats_URI", string.Empty); m_securePermissionsLoading = startupConfig.GetBoolean("SecurePermissionsLoading", true); @@ -355,7 +355,7 @@ protected override void Initialize() // Sure is not the right place for this but do the job... // Must always be called before (all) / the HTTP servers starting for the Certs creation or renewals. - if(startupConfig.GetBoolean("EnableSelfsignedCertSupport", false)) + if (startupConfig.GetBoolean("EnableSelfsignedCertSupport", false)) { if(!File.Exists("SSL\\ssl\\"+ startupConfig.GetString("CertFileName") +".p12") || startupConfig.GetBoolean("CertRenewOnStartup")) { diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 13ef265e2b8..953cc0f1e62 100755 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -215,6 +215,7 @@ public void Initialise(IConfigSource source) MainConsole.Instance.Commands.AddCommand("Assets", true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand); MainConsole.Instance.Commands.AddCommand("Assets", true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the cache. If file or memory is specified then only this cache is cleared.", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand("Assets", true, "fcache clearnegatives", "fcache clearnegatives", "Remove cache of assets previously not found in services.", HandleConsoleCommand); MainConsole.Instance.Commands.AddCommand("Assets", true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand); MainConsole.Instance.Commands.AddCommand("Assets", true, "fcache expire", "fcache expire ", "Purge cached assets older than the specified date/time", HandleConsoleCommand); if (!string.IsNullOrWhiteSpace(m_assetLoader)) @@ -1438,7 +1439,19 @@ private void HandleConsoleCommand(string module, string[] cmdparams) con.Output("File cache not enabled."); } } + if(m_negativeCacheEnabled) + m_negativeCache.Clear(); + break; + case "clearnegatives": + if(m_negativeCacheEnabled) + { + int nsz = m_negativeCache.Count; + m_negativeCache.Clear(); + con.Output($"Flotsam cache of negatives cleared ({nsz} entries)"); + } + else + con.Output("Flotsam cache of negatives not enabled"); break; case "assets": diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 47a47cc107c..9d77e265430 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -620,7 +620,7 @@ protected void LoadInventoryFile(string path, TarArchiveReader.TarEntryType entr // Trim off the file portion if we aren't already dealing with a directory path if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) - path = path.Remove(path.LastIndexOf("/") + 1); + path = path.Remove(path.LastIndexOf('/') + 1); InventoryFolderBase foundFolder = ReplicateArchivePathToUserInventory( diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs index 795e0e64eb1..92b10f709c4 100644 --- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs @@ -97,10 +97,8 @@ private void ProcessRequests() { ScenePresence p = req.presence; - bool ok = true; bool foreign = GetUserProfileServerURI(req.agent, out string serverURI); - if(serverURI.Length == 0) - ok = false; + bool ok = serverURI.Length > 0; Byte[] membershipType = new Byte[1]; string born = string.Empty; diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index a389f548c11..12c4a9996ac 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -1093,6 +1093,8 @@ public virtual SceneObjectGroup RezObject( group.SetGroup(groupID, remoteClient); + group.RezStringParameter = null; + // If we're rezzing an attachment then don't ask // AddNewSceneObject() to update the client since // we'll be doing that later on. Scheduling more than diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index ed1ddc7b709..057992b72a7 100755 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -1228,8 +1228,6 @@ public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attem for (int y = start_y; y < end_y; y++) { ILandObject tempLandObject = GetLandObject(x, y); - if (tempLandObject is null) - return; if (tempLandObject != startLandObject) return; area++; diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index a5a133688c0..7d32db8a66e 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -253,6 +253,8 @@ public interface IEntityInventory bool GetRezReadySceneObjects(TaskInventoryItem item, out List objlist, out List veclist, out Vector3 bbox, out float offsetHeight); bool GetRezReadySceneObjects(TaskInventoryItem item, UUID newOwner, UUID NewGroup, out List objlist, out List veclist, out Vector3 bbox, out float offsetHeight); + SceneObjectGroup GetSingleRezReadySceneObject(TaskInventoryItem item, UUID NewOwner, UUID NewGroup); + /// /// Update an existing inventory item. /// diff --git a/OpenSim/Region/Framework/Scenes/GodController.cs b/OpenSim/Region/Framework/Scenes/GodController.cs index 159f9c504a8..e1fa4a84173 100644 --- a/OpenSim/Region/Framework/Scenes/GodController.cs +++ b/OpenSim/Region/Framework/Scenes/GodController.cs @@ -242,8 +242,8 @@ public void SetState(OSD state) OSDMap s = (OSDMap)state; if (s.TryGetValue("ViewerUiIsGod", out OSD tmp)) newstate = tmp.AsBoolean(); - m_lastLevelToViewer = m_viewergodlevel; // we are not changing viewer level by default - } + m_lastLevelToViewer = newstate && m_viewergodlevel < 200 ? 200 : m_viewergodlevel; + } UpdateGodLevels(newstate); } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 572aaa37779..1ed820521f7 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2590,6 +2590,31 @@ public bool GetObjectsToRez( return true; } + public SceneObjectGroup GetSingleObjectToRez(byte[] assetData) + { + string xmlData = string.Empty; + try + { + xmlData = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(assetData)); + using XmlTextReader wrappedReader = new(xmlData, XmlNodeType.Element, null); + using XmlReader reader = XmlReader.Create(wrappedReader, Util.SharedXmlReaderSettings); + reader.Read(); + + if (!"CoalescedObject".Equals(reader.Name)) + { + SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(reader); + return g; + } + } + catch (Exception e) + { + m_log.Error("[AGENT INVENTORY]: single object xml deserialization failed" + e.Message); + Util.LogFailedXML("[AGENT INVENTORY]:", xmlData); + } + + return null; + } + /// /// Event Handler Rez an object into a scene /// Calls the non-void event handler @@ -2781,6 +2806,7 @@ public virtual List RezObject(SceneObjectPart sourcePart, Task } group.RezzerID = rezzerID; + group.RezStringParameter = null; if (rezSelected) { @@ -2813,6 +2839,65 @@ public virtual List RezObject(SceneObjectPart sourcePart, Task return objlist; } + public SceneObjectGroup ScriptRezObject(SceneObjectPart sourcePart, TaskInventoryItem item, + UUID newSOGID, + Vector3 pos, Quaternion? rot, Vector3 vel, int param, bool atRoot) + { + if (item is null) + return null; + + if(TryGetSceneObjectGroup(newSOGID, out _)) + return null; + + SceneObjectGroup sog = sourcePart.Inventory.GetSingleRezReadySceneObject(item, sourcePart.OwnerID, sourcePart.GroupID); + if(sog is null) + return null; + + int totalPrims = sog.PrimCount; + + if (!Permissions.CanRezObject(totalPrims, sourcePart.OwnerID, pos)) + return null; + + if (!Permissions.BypassPermissions()) + { + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + sourcePart.Inventory.RemoveInventoryItem(item.ItemID); + } + + // position adjust + if (totalPrims > 1) // nothing to do on a single prim + { + // current object position is root position + if(!atRoot) + { + Quaternion orot = rot ?? sog.RootPart.GetWorldRotation(); + // possible should be bbox, but geometric center looks better + Vector3 off = sog.GetGeometricCenter(); + off *= orot; + pos -= off; + } + } + + if (sog.IsAttachment == false && sog.RootPart.Shape.State != 0) + { + sog.RootPart.AttachedPos = sog.AbsolutePosition; + sog.RootPart.Shape.LastAttachPoint = (byte)sog.AttachmentPoint; + } + + sog.RezzerID = sourcePart.UUID; + + AddNewSceneObject(sog, true, pos, rot, vel); + + // We can only call this after adding the scene object, since the scene object references the scene + // to find out if scripts should be activated at all. + sog.InvalidateEffectivePerms(); + sog.CreateScriptInstances(param, true, DefaultScriptEngine, 3); + + sog.ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdatewithAnimMatOvr); + + return sog; + } + public virtual bool returnObjects(SceneObjectGroup[] returnobjects, IClientAPI client) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 38b7e7a02f9..ddff39f1a36 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1694,7 +1694,7 @@ public override void Update(int frames) terrainMS = (float)(nowMS - lastMS); lastMS = nowMS; - if (PhysicsEnabled && Frame % m_update_physics == 0) + if (m_physicsEnabled && Frame % m_update_physics == 0) m_sceneGraph.UpdatePreparePhysics(); nowMS = Util.GetTimeStampMS(); @@ -1731,10 +1731,9 @@ public override void Update(int frames) // Perform the main physics update. This will do the actual work of moving objects and avatars according to their // velocity - if (Frame % m_update_physics == 0) + if (m_physicsEnabled && Frame % m_update_physics == 0) { - if (PhysicsEnabled) - physicsFPS = m_sceneGraph.UpdatePhysics(FrameTime); + physicsFPS = m_sceneGraph.UpdatePhysics(FrameTime); } nowMS = Util.GetTimeStampMS(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 88605ac4330..82352d45592 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -26,7 +26,6 @@ */ using System; -using System.IO; using System.Reflection; using OpenMetaverse; using log4net; @@ -135,19 +134,17 @@ public void RemoveScriptsPermissions(ScenePresence sp, int permissions) /// public bool AddInventoryItem(UUID agentID, uint localID, InventoryItemBase item, UUID copyItemID, bool withModRights = true) { -// m_log.DebugFormat( -// "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}", -// item.Name, remoteClient.Name, localID); + //m_log.DebugFormat( + // "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}", + // item.Name, remoteClient.Name, localID); UUID newItemId = copyItemID.IsZero() ? item.ID : copyItemID; SceneObjectPart part = GetPart(localID); if (part is null) { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Couldn't find prim local ID {0} in group {1}, {2} to add inventory item ID {3}", - localID, Name, UUID, newItemId); + m_log.Error( + $"[PRIM INVENTORY]: Couldn't find prim local ID {localID} in group {Name}, {UUID} to add inventory item ID {newItemId}"); return false; } @@ -156,6 +153,7 @@ public bool AddInventoryItem(UUID agentID, uint localID, InventoryItemBase item, ItemID = newItemId, AssetID = item.AssetID, Name = item.Name, + //CreationDate = (uint)Util.UnixTimeSinceEpoch(), Description = item.Description, OwnerID = part.OwnerID, // Transfer ownership CreatorID = item.CreatorIdAsUuid, @@ -193,8 +191,7 @@ public bool AddInventoryItem(UUID agentID, uint localID, InventoryItemBase item, // TODO: These are pending addition of those fields to TaskInventoryItem // taskItem.SalePrice = item.SalePrice; // taskItem.SaleType = item.SaleType; - taskItem.CreationDate = (uint)item.CreationDate; - + bool addFromAllowedDrop; if(withModRights) addFromAllowedDrop = false; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 93ac79bd123..8f8afc1b68d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -444,6 +444,7 @@ public Dictionary RotTargets public bool m_dupeInProgress = false; internal Dictionary m_savedScriptState; + public string RezStringParameter = null; public UUID MonitoringObject { get; set; } #region Properties diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index c0dad7ac423..170a197350d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -28,17 +28,13 @@ using System; using System.Text; using System.Xml; -using System.IO; using System.Collections.Generic; using System.Collections; using System.Reflection; -using System.Threading; using OpenMetaverse; using log4net; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes.Scripting; -using OpenSim.Region.Framework.Scenes.Serialization; using PermissionMask = OpenSim.Framework.PermissionMask; namespace OpenSim.Region.Framework.Scenes @@ -51,7 +47,7 @@ public class SceneObjectPartInventory : IEntityInventory , IDisposable private byte[] m_inventoryFileNameBytes = Array.Empty(); private string m_inventoryFileName = ""; private uint m_inventoryFileNameSerial = 0; - private bool m_inventoryPrivileged = false; + private int m_inventoryPrivileged = 0; private object m_inventoryFileLock = new object(); private Dictionary m_scriptErrors = new Dictionary(); @@ -1222,6 +1218,72 @@ public bool GetRezReadySceneObjects(TaskInventoryItem item, UUID NewOwner, UUID return true; } + public SceneObjectGroup GetSingleRezReadySceneObject(TaskInventoryItem item, UUID NewOwner, UUID NewGroup) + { + AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); + if (rezAsset is null) + { + m_log.Warn($"[PRIM INVENTORY]: Could not find asset {item.AssetID} for inventory item {item.Name} in {m_part.Name}"); + return null; + } + + SceneObjectGroup group = m_part.ParentGroup.Scene.GetSingleObjectToRez(rezAsset.Data); + if (group == null) + return null; + + group.ResetIDs(); + + SceneObjectPart rootPart = group.RootPart; + + rootPart.Name = item.Name; + rootPart.Description = item.Description; + + group.SetGroup(NewGroup, null); + SceneObjectPart[] partList = group.Parts; + + bool slamThings = (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0; + if (slamThings || rootPart.OwnerID.NotEqual(NewOwner)) + { + if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) + { + foreach (SceneObjectPart part in partList) + { + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) + part.EveryoneMask = item.EveryonePermissions; + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) + part.NextOwnerMask = item.NextPermissions; + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) + part.GroupMask = item.GroupPermissions; + } + + group.ApplyNextOwnerPermissions(); + } + } + + foreach (SceneObjectPart part in partList) + { + if (part.OwnerID.NotEqual(NewOwner)) + { + if(part.GroupID.NotEqual(part.OwnerID)) + part.LastOwnerID = part.OwnerID; + part.OwnerID = NewOwner; + part.Inventory.ChangeInventoryOwner(NewOwner); + } + + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) + part.EveryoneMask = item.EveryonePermissions; + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) + part.NextOwnerMask = item.NextPermissions; + if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) + part.GroupMask = item.GroupPermissions; + } + + rootPart.TrimPermissions(); + group.InvalidateDeepEffectivePerms(); + + return group; + } + /// /// Update an existing inventory item. /// @@ -1388,11 +1450,22 @@ public void RequestInventoryFile(IClientAPI client, IXfer xferManager) if (m_inventoryFileData.Length < 2) changed = true; - bool includeAssets = false; - if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId)) + int privilegedmask = 0; + bool includeAssets; + bool isVGod = client.SceneAgent is ScenePresence sp && sp.IsViewerUIGod; + if (isVGod) + { + privilegedmask = 3; includeAssets = true; + } + else + { + includeAssets = m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId); + if(includeAssets) + privilegedmask = 1; + } - if (m_inventoryPrivileged != includeAssets) + if(m_inventoryPrivileged != privilegedmask) changed = true; if (!changed) @@ -1404,55 +1477,69 @@ public void RequestInventoryFile(IClientAPI client, IXfer xferManager) return; } - m_inventoryPrivileged = includeAssets; + m_inventoryPrivileged = privilegedmask; - InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); + InventoryStringBuilder invString = new(m_part.UUID, UUID.Zero); m_items.LockItemsForRead(true); foreach (TaskInventoryItem item in m_items.Values) { - UUID ownerID = item.OwnerID; - UUID groupID = item.GroupID; - uint everyoneMask = item.EveryonePermissions; - uint baseMask = item.BasePermissions; - uint ownerMask = item.CurrentPermissions; - uint groupMask = item.GroupPermissions; - invString.AddItemStart(); invString.AddNameValueLine("item_id", item.ItemID.ToString()); invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); invString.AddPermissionsStart(); - invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); - invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); - invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); - invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); + invString.AddNameValueLine("base_mask", Utils.UIntToHexString(item.BasePermissions)); + invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(item.CurrentPermissions)); + invString.AddNameValueLine("group_mask", Utils.UIntToHexString(item.GroupPermissions)); + invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(item.EveryonePermissions)); invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); - invString.AddNameValueLine("group_id",groupID.ToString()); - if(!groupID.IsZero() && ownerID.Equals(groupID)) + invString.AddNameValueLine("group_id", item.GroupID.ToString()); + if(item.GroupID.IsNotZero() && item.OwnerID.Equals(item.GroupID)) { invString.AddNameValueLine("owner_id", UUID.ZeroString); invString.AddNameValueLine("group_owned","1"); } else { - invString.AddNameValueLine("owner_id", ownerID.ToString()); + invString.AddNameValueLine("owner_id", item.OwnerID.ToString()); invString.AddNameValueLine("group_owned","0"); } invString.AddSectionEnd(); if (includeAssets) - invString.AddNameValueLine("asset_id", item.AssetID.ToString()); + { + if(isVGod) + invString.AddNameValueLine("asset_id", item.AssetID.ToString()); + else + { + bool allow = item.InvType switch + { + //(int)InventoryType.Sound => (item.CurrentPermissions & (uint)PermissionMask.Modify) != 0, + (int)InventoryType.Notecard => (item.CurrentPermissions & (uint)(PermissionMask.Modify | PermissionMask.Copy)) != 0, + (int)InventoryType.LSL => (item.CurrentPermissions & (uint)(PermissionMask.Modify | PermissionMask.Copy)) == + (uint)(PermissionMask.Modify | PermissionMask.Copy), + //(int)InventoryType.Animation => (item.CurrentPermissions & (uint)PermissionMask.Modify) != 0, + //(int)InventoryType.Gesture => (item.CurrentPermissions & (uint)PermissionMask.Modify) != 0, + (int)InventoryType.Settings => (item.CurrentPermissions & (uint)(PermissionMask.Modify | PermissionMask.Copy)) == + (uint)(PermissionMask.Modify | PermissionMask.Copy), + (int)InventoryType.Material => (item.CurrentPermissions & (uint)(PermissionMask.Modify | PermissionMask.Copy)) == + (uint)(PermissionMask.Modify | PermissionMask.Copy), + _ => true + }; + invString.AddNameValueLine("asset_id", allow ? item.AssetID.ToString() : UUID.ZeroString); + } + } else - invString.AddNameValueLine("asset_id", UUID.Zero.ToString()); + invString.AddNameValueLine("asset_id", UUID.ZeroString); invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type)); invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType)); invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); @@ -1478,7 +1565,7 @@ public void RequestInventoryFile(IClientAPI client, IXfer xferManager) m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; m_inventoryFileNameBytes = Util.StringToBytes256(m_inventoryFileName); xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); - client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,m_inventoryFileNameBytes); + client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial, m_inventoryFileNameBytes); return; } @@ -1492,13 +1579,13 @@ public void RequestInventoryFile(IClientAPI client, IXfer xferManager) /// public void ProcessInventoryBackup(ISimulationDataService datastore) { -// Removed this because linking will cause an immediate delete of the new -// child prim from the database and the subsequent storing of the prim sees -// the inventory of it as unchanged and doesn't store it at all. The overhead -// of storing prim inventory needlessly is much less than the aggravation -// of prim inventory loss. -// if (HasInventoryChanged) -// { + // Removed this because linking will cause an immediate delete of the new + // child prim from the database and the subsequent storing of the prim sees + // the inventory of it as unchanged and doesn't store it at all. The overhead + // of storing prim inventory needlessly is much less than the aggravation + // of prim inventory loss. + //if (HasInventoryChanged) + // { m_items.LockItemsForRead(true); ICollection itemsvalues = m_items.Values; HasInventoryChanged = false; @@ -1508,7 +1595,7 @@ public void ProcessInventoryBackup(ISimulationDataService datastore) datastore.StorePrimInventory(m_part.UUID, itemsvalues); } catch {} -// } + // } } public class InventoryStringBuilder @@ -1554,13 +1641,13 @@ public void AddLine(string addLine) BuildString.Append(addLine); } - public void AddNameValueLine(string name, string value) + public void AddNameValueLine(ReadOnlySpan name, ReadOnlySpan value) { BuildString.Append("\t\t"); BuildString.Append(name); - BuildString.Append("\t"); + BuildString.Append('\t'); BuildString.Append(value); - BuildString.Append("\n"); + BuildString.Append('\n'); } public String GetString() diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index c9193274d25..b03c38f4457 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1143,20 +1143,20 @@ public ScenePresence(IClientAPI client, Scene world, AvatarAppearance appearance IsInLocalTransit = true; UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); - if (account != null) + if (account is not null) + { m_userFlags = account.UserFlags; + GodController = new GodController(world, this, account.UserLevel); + } else + { m_userFlags = 0; + GodController = new GodController(world, this, 0); + } - int userlevel = 0; - if (account != null) - userlevel = account.UserLevel; - - GodController = new GodController(world, this, userlevel); - - // IGroupsModule gm = m_scene.RequestModuleInterface(); - // if (gm != null) - // Grouptitle = gm.GetGroupTitle(m_uuid); + //IGroupsModule gm = m_scene.RequestModuleInterface(); + //if (gm != null) + // Grouptitle = gm.GetGroupTitle(m_uuid); m_scriptEngines = m_scene.RequestModuleInterfaces(); diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index d4f9f1635bc..fc52889754d 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -151,6 +151,11 @@ public static SceneObjectGroup FromOriginalXmlFormat(XmlReader reader) sceneObject.LinksetData = LinksetData.FromXML(innerlnkstdttxt.AsSpan()); } + if (reader.Name == "StartStr" && reader.NodeType == XmlNodeType.Element) + { + sceneObject.RezStringParameter = reader.ReadElementContentAsString(); + } + // Script state may, or may not, exist. Not having any, is NOT // ever a problem. sceneObject.LoadScriptState(reader); @@ -260,6 +265,9 @@ public static void ToOriginalXmlFormat( writer.WriteEndElement(); } + if(sceneObject.RezStringParameter is not null) + writer.WriteElementString("StartStr", sceneObject.RezStringParameter); + sceneObject.LinksetData?.ToXML(writer); if (doScriptStates) @@ -337,6 +345,10 @@ public static SceneObjectGroup FromXml2Format(string xmlData) if (keylinksetdata.Count > 0) sceneObject.LinksetData = LinksetData.FromXML(keylinksetdata[0].InnerText.AsSpan()); + XmlNodeList StartStr = doc.GetElementsByTagName("StartStr"); + if (StartStr.Count > 0) + sceneObject.RezStringParameter = StartStr[0].InnerText; + // Script state may, or may not, exist. Not having any, is NOT // ever a problem. sceneObject.LoadScriptState(doc); @@ -1519,6 +1531,9 @@ public static void SOGToXml2(XmlTextWriter writer, SceneObjectGroup sog, Diction writer.WriteEndElement(); } + if(sog.RezStringParameter is not null) + writer.WriteElementString("StartStr", sog.RezStringParameter); + sog.LinksetData?.ToXML(writer); writer.WriteEndElement(); diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs index 94b6f8b6807..8de67fec107 100644 --- a/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs +++ b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs @@ -1174,12 +1174,12 @@ public void Move() else if (_position.X < 0.0f) { fixbody = true; - _position.X = 0.1f; + _position.X = 0.01f; } - else if (_position.X > m_parent_scene.WorldExtents.X - 0.1f) + else if (_position.X > m_parent_scene.WorldExtents.X - 0.01f) { fixbody = true; - _position.X = m_parent_scene.WorldExtents.X - 0.1f; + _position.X = m_parent_scene.WorldExtents.X - 0.01f; } if ((Single.IsNaN(_position.Y) || Single.IsInfinity(_position.Y))) @@ -1190,12 +1190,12 @@ public void Move() else if (_position.Y < 0.0f) { fixbody = true; - _position.Y = 0.1f; + _position.Y = 0.01f; } - else if (_position.Y > m_parent_scene.WorldExtents.Y - 0.1f) + else if (_position.Y > m_parent_scene.WorldExtents.Y - 0.01f) { fixbody = true; - _position.Y = m_parent_scene.WorldExtents.Y - 0.1f; + _position.Y = m_parent_scene.WorldExtents.Y - 0.01f; } if ((Single.IsNaN(_position.Z) || Single.IsInfinity(_position.Z))) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1d914d3770f..5bc0417c02d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -58,6 +58,7 @@ using System.Threading; using AssetLandmark = OpenSim.Framework.AssetLandmark; using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using MappingType = OpenMetaverse.MappingType; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; @@ -116,7 +117,7 @@ public int LlRequestAgentDataCacheTimeoutMs protected float m_recoilScaleFactor = 0.0f; protected bool m_AllowGodFunctions; - protected double m_timer = Util.GetTimeStampMS(); + protected double m_timer = Util.GetTimeStamp(); protected bool m_waitingForScriptAnswer = false; protected bool m_automaticLinkPermission = false; protected int m_notecardLineReadCharsMax = 255; @@ -723,7 +724,7 @@ public static ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum) { if (linknum == ScriptBaseClass.LINK_THIS) return part; - + if (linknum <= part.ParentGroup.PrimCount) return part.ParentGroup.GetLinkNumPart(linknum); @@ -2351,38 +2352,29 @@ public LSL_String llGetTexture(int face) protected static LSL_String GetTexture(SceneObjectPart part, int face) { + if (face == ScriptBaseClass.ALL_SIDES) + face = 0; + if (face < 0) + return ScriptBaseClass.NULL_KEY; + Primitive.TextureEntry tex = part.Shape.Textures; int nsides = GetNumberOfSides(part); + if (face >= nsides) + return ScriptBaseClass.NULL_KEY; - if (face == ScriptBaseClass.ALL_SIDES) - { - face = 0; - } + Primitive.TextureEntryFace texface; + texface = tex.GetFace((uint)face); - if (face >= 0 && face < nsides) + lock (part.TaskInventory) { - Primitive.TextureEntryFace texface; - texface = tex.GetFace((uint)face); - string texture = texface.TextureID.ToString(); - - lock (part.TaskInventory) + foreach (KeyValuePair inv in part.TaskInventory) { - foreach (KeyValuePair inv in part.TaskInventory) - { - if (inv.Value.AssetID.Equals(texface.TextureID)) - { - texture = inv.Value.Name.ToString(); - break; - } - } + if (inv.Value.AssetID.Equals(texface.TextureID)) + return inv.Value.Name.ToString(); } - - return texture; - } - else - { - return ScriptBaseClass.NULL_KEY; } + + return texface.TextureID.ToString(); } public void llSetPos(LSL_Vector pos) @@ -2829,21 +2821,21 @@ public LSL_Float llGetWallclock() public LSL_Float llGetTime() { - double ScriptTime = Util.GetTimeStampMS() - m_timer; - return (float)Math.Round((ScriptTime / 1000.0), 3); + double ScriptTime = Util.GetTimeStamp() - m_timer; + return Math.Round(ScriptTime, 3); } public void llResetTime() { - m_timer = Util.GetTimeStampMS(); + m_timer = Util.GetTimeStamp(); } public LSL_Float llGetAndResetTime() { - double now = Util.GetTimeStampMS(); + double now = Util.GetTimeStamp(); double ScriptTime = now - m_timer; m_timer = now; - return (float)Math.Round((ScriptTime / 1000.0), 3); + return Math.Round(ScriptTime, 3); } public void llSound(string sound, double volume, int queue, int loop) @@ -3330,7 +3322,7 @@ public void doObjectRez(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Ro List new_groups = World.RezObject(m_host, item, pos, wrot, vel, param, atRoot); // If either of these are null, then there was an unknown error. - if (new_groups == null) + if (new_groups == null || new_groups.Count == 0) return; bool notAttachment = !m_host.ParentGroup.IsAttachment; @@ -3350,14 +3342,12 @@ public void doObjectRez(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Ro if (notAttachment) { - float groupmass = group.GetMass(); - PhysicsActor pa = group.RootPart.PhysActor; //Recoil. if (pa != null && pa.IsPhysical && !((Vector3)vel).IsZero()) { - Vector3 recoil = -vel * groupmass * m_recoilScaleFactor; + Vector3 recoil = -vel * group.GetMass() * m_recoilScaleFactor; if (!recoil.IsZero()) { llApplyImpulse(recoil, 0); @@ -3376,6 +3366,514 @@ public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Ro doObjectRez(inventory, pos, vel, rot, param, false); } + public LSL_Key llRezObjectWithParams(string inventory, LSL_List lparam) + { + /* flags not supported + * REZ_FLAG_DIE_ON_NOENTRY + * REZ_FLAG_NO_COLLIDE_OWNER + * REZ_FLAG_NO_COLLIDE_FAMILY + * + * parameters not supported + * REZ_ACCEL + * REZ_DAMAGE + * REZ_DAMAGE_TYPE + * REZ_OMEGA only does viewer side lltargetomega + */ + + if (string.IsNullOrEmpty(inventory)) + return LSL_Key.NullKey; + + TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory); + if (item == null) + { + Error("llRezObjectWithParams", "Can't find object '" + inventory + "'"); + return LSL_Key.NullKey; + } + + if (item.InvType != (int)InventoryType.Object) + { + Error("llRezObjectWithParams", "Can't create requested object; object is missing from database"); + return LSL_Key.NullKey; + } + + int flags = 0; + Vector3 pos = Vector3.Zero; + Vector3 vel = Vector3.Zero; + Quaternion rot = Quaternion.Identity; + Vector3 acel = Vector3.Zero; + Vector3 omega = Vector3.Zero; + float omegaSpin = 0; + float omegaGain = 0; + + float damage = 0; + + string sound = null; + float soundVol = 0; + bool soundLoop = false; + + string collisionSound = null; + float CollisionSoundVol = 0; + + int param = 0; + + Vector3 lockAxis = Vector3.Zero; + + string stringparam = null; + bool atRoot = false; + + if(lparam != null && lparam.Length > 0) + { + try + { + int idx = 0; + while (idx < lparam.Length) + { + int rezrelative = 0; + int code = lparam.GetIntegerItem(idx++); + switch(code) + { + case ScriptBaseClass.REZ_PARAM: + try + { + param = lparam.GetIntegerItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must a integer"); + } + break; + + case ScriptBaseClass.REZ_FLAGS: + try + { + flags = lparam.GetIntegerItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must a integer"); + } + break; + + case ScriptBaseClass.REZ_POS: + try + { + pos = lparam.GetVector3Item(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be vector"); + } + + idx++; + try + { + rezrelative = lparam.GetIntegerItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be integer"); + } + + idx++; + int rezAtRot = 0; + try + { + rezAtRot = lparam.GetIntegerItem(idx); + atRoot = rezAtRot != 0; + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be integer"); + } + + if(rezrelative != 0) + { + if(pos.LengthSquared() > m_Script10mDistanceSquare) + return LSL_Key.NullKey; + pos += m_host.GetWorldPosition(); + } + else if ((pos - m_host.GetWorldPosition()).LengthSquared() > m_Script10mDistanceSquare) + return LSL_Key.NullKey; + + break; + + case ScriptBaseClass.REZ_ROT: + try + { + rot = lparam.GetQuaternionItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be rotation"); + } + + idx++; + try + { + rezrelative = lparam.GetIntegerItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be integer"); + } + + if(rezrelative > 0) + rot *= m_host.GetWorldRotation(); + + rot.Normalize(); + break; + + case ScriptBaseClass.REZ_VEL: + try + { + vel = lparam.GetVector3Item(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be vector"); + } + + idx++; + try + { + rezrelative = lparam.GetIntegerItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be integer"); + } + + idx++; + int addVel = 0; + try + { + addVel = lparam.GetIntegerItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be integer"); + } + + if(rezrelative > 0) + vel *= m_host.GetWorldRotation(); + if(addVel > 0) + vel += m_host.ParentGroup.Velocity; + + break; + + case ScriptBaseClass.REZ_ACCEL: + try + { + acel = lparam.GetVector3Item(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be vector"); + } + + idx++; + try + { + rezrelative = lparam.GetIntegerItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be integer"); + } + + break; + + case ScriptBaseClass.REZ_OMEGA: + try + { + omega = lparam.GetVector3Item(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be vector"); + } + + idx++; + try + { + rezrelative = lparam.GetIntegerItem(idx); + if(rezrelative > 0) + omega *= m_host.GetWorldRotation(); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be integer"); + } + + idx++; + try + { + omegaSpin = lparam.GetFloatItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be float"); + } + + idx++; + try + { + omegaGain = lparam.GetFloatItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be float"); + } + + break; + + case ScriptBaseClass.REZ_DAMAGE: + try + { + damage = lparam.GetFloatItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be float"); + } + break; + + case ScriptBaseClass.REZ_SOUND: + try + { + sound = lparam.GetStringItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be string"); + } + + idx++; + try + { + soundVol = lparam.GetFloatItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be float"); + } + + idx++; + try + { + soundLoop = lparam.GetIntegerItem(idx) > 0; + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be integer"); + } + break; + + case ScriptBaseClass.REZ_SOUND_COLLIDE: + try + { + collisionSound = lparam.GetStringItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be string"); + } + + idx++; + try + { + CollisionSoundVol = lparam.GetFloatItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be float"); + } + break; + + case ScriptBaseClass.REZ_LOCK_AXES: + try + { + lockAxis = lparam.GetVector3Item(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be vector"); + } + break; + case ScriptBaseClass.REZ_DAMAGE_TYPE: + try + { + int damageType = lparam.GetIntegerItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be integer"); + } + break; + + case ScriptBaseClass.REZ_PARAM_STRING: + try + { + stringparam = lparam.GetStringItem(idx); + } + catch (InvalidCastException) + { + throw new InvalidCastException($"arg #{idx} must be string"); + } + + _ = Utils.osUTF8GetBytesCount(stringparam, 1024, out int maxsourcelen); + if(maxsourcelen < stringparam.Length) + stringparam = stringparam[..maxsourcelen]; + break; + + default: + Error("llRezObjectWithParams", $"Unknown parameter {code} at {idx}"); + return LSL_Key.NullKey; + } + idx++; + } + } + catch (Exception e) + { + Error("llRezObjectWithParams", "error " + e.Message); + return LSL_Key.NullKey; + } + } + + UUID newID = UUID.Random(); + + Util.FireAndForget(x => + { + SceneObjectGroup sog = m_host.Inventory.GetSingleRezReadySceneObject(item, m_host.OwnerID, m_host.GroupID); + if(sog is null) + return; + + int totalPrims = sog.PrimCount; + + if (!World.Permissions.CanRezObject(totalPrims, m_host.OwnerID, pos)) + return; + + if (!World.Permissions.BypassPermissions()) + { + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + m_host.Inventory.RemoveInventoryItem(item.ItemID); + } + + // position adjust + if (!atRoot && totalPrims > 1) // nothing to do on a single prim + { + pos -= sog.GetGeometricCenter() * rot; + } + + if (sog.IsAttachment == false && sog.RootPart.Shape.State != 0) + { + sog.RootPart.AttachedPos = sog.AbsolutePosition; + sog.RootPart.Shape.LastAttachPoint = (byte)sog.AttachmentPoint; + } + + sog.RezzerID = m_host.ParentGroup.RootPart.UUID; + sog.UUID = newID; + + // We can only call this after adding the scene object, since the scene object references the scene + // to find out if scripts should be activated at all. + + SceneObjectPart groot = sog.RootPart; + + if(groot.PhysActor != null) + groot.PhysActor.Building = true; + + // objects rezzed with this method are die_at_edge by default. + groot.SetDieAtEdge(true); + + if((flags & ScriptBaseClass.REZ_FLAG_TEMP) != 0) + groot.AddFlag(PrimFlags.TemporaryOnRez); + else + groot.RemFlag(PrimFlags.TemporaryOnRez); + + if(!sog.IsVolumeDetect && (flags & ScriptBaseClass.REZ_FLAG_PHYSICAL) != 0) + { + groot.KeyframeMotion?.Stop(); + groot.KeyframeMotion = null; + groot.AddFlag(PrimFlags.Physics); + } + else + groot.RemFlag(PrimFlags.Physics); + + if((flags & ScriptBaseClass.REZ_FLAG_PHANTOM) != 0) + groot.AddFlag(PrimFlags.Phantom); + else if (!sog.IsVolumeDetect) + groot.RemFlag(PrimFlags.Phantom); + + sog.BlockGrabOverride = (flags & ScriptBaseClass.REZ_FLAG_BLOCK_GRAB_OBJECT) != 0; + + if(groot.PhysActor != null) + groot.PhysActor.Building = false; + + sog.RezStringParameter = stringparam; + + sog.InvalidateEffectivePerms(); + if(omegaGain > 1e-6) + { + groot.UpdateAngularVelocity(omega * omegaSpin); + } + + if(lockAxis.IsNotZero()) + { + byte axislock = 0; + if(lockAxis.X != 0) + axislock = 2; + if(lockAxis.Y != 0) + axislock |= 4; + if(lockAxis.X != 0) + axislock |= 8; + groot.RotationAxisLocks = axislock; + } + + if(collisionSound != null) + { + UUID soundID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, collisionSound, AssetType.Sound); + if(soundID.IsNotZero()) + { + groot.CollisionSoundType = 1; + groot.CollisionSoundVolume = CollisionSoundVol; + groot.CollisionSound = soundID; + } + else + groot.CollisionSoundType = -1; + } + + World.AddNewSceneObject(sog, true, pos, rot, vel); + + sog.CreateScriptInstances(param, true, m_ScriptEngine.ScriptEngineName, 3); + sog.ResumeScripts(); + + sog.ScheduleGroupForUpdate(PrimUpdateFlags.FullUpdatewithAnimMatOvr); + + m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( + "object_rez", + [ + new LSL_String(groot.UUID.ToString()) + ], + Array.Empty())); + + if(soundVol > 0 && !string.IsNullOrEmpty(sound) && m_SoundModule is not null) + { + UUID soundID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound); + if(soundID.IsNotZero()) + { + if(soundLoop) + m_SoundModule.LoopSound(groot, soundID, soundVol, false, false); + else + m_SoundModule.SendSound(groot, soundID, soundVol, false, 0, false, false); + } + } + + }, null, "LSL_Api.ObjectRezWithParam"); + + ScriptSleep(m_sleepMsOnRezAtRoot); + return new(newID.ToString()); + } + public void llLookAt(LSL_Vector target, double strength, double damping) { SceneObjectGroup sog = m_host.ParentGroup; @@ -3974,6 +4472,13 @@ public LSL_Integer llGetStartParameter() return m_ScriptEngine.GetStartParameter(m_item.ItemID); } + public LSL_String llGetStartString() + { + if(string.IsNullOrEmpty(m_host.ParentGroup.RezStringParameter)) + return LSL_String.Empty; + return new(m_host.ParentGroup.RezStringParameter); + } + public void llRequestPermissions(string agent, int perm) { if (!UUID.TryParse(agent, out UUID agentID) || agentID.IsZero()) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 2bfa6c047d2..eaf2ba583b2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -4106,33 +4106,29 @@ public LSL_Integer osEjectFromGroup(LSL_Key agentId) } /// - /// Sets terrain estate texture + /// Sets terrain texture /// /// /// /// public void osSetTerrainTexture(int level, LSL_Key texture) { + if (level < 0 || level > 3) + return; + if (!UUID.TryParse(texture, out UUID textureID)) + return; + CheckThreatLevel(ThreatLevel.High, "osSetTerrainTexture"); - //Check to make sure that the script's owner is the estate manager/master - //World.Permissions.GenericEstatePermission( if (World.Permissions.IsGod(m_host.OwnerID)) { - if (level < 0 || level > 3) - return; - - if (!UUID.TryParse(texture, out UUID textureID)) - return; - - // estate module is required IEstateModule estate = World.RequestModuleInterface(); estate?.setEstateTerrainBaseTexture(level, textureID); } } /// - /// Sets terrain heights of estate + /// Sets terrain textures heights /// /// /// @@ -4140,16 +4136,13 @@ public void osSetTerrainTexture(int level, LSL_Key texture) /// public void osSetTerrainTextureHeight(int corner, double low, double high) { + if (corner < 0 || corner > 3) + return; + CheckThreatLevel(ThreatLevel.High, "osSetTerrainTextureHeight"); - //Check to make sure that the script's owner is the estate manager/master - //World.Permissions.GenericEstatePermission( if (World.Permissions.IsGod(m_host.OwnerID)) { - if (corner < 0 || corner > 3) - return; - - // estate module is required IEstateModule estate = World.RequestModuleInterface(); estate?.setEstateTerrainTextureHeights(corner, (float)low, (float)high); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 9061624d065..5ae734c701b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -523,5 +523,9 @@ public interface ILSL_Api LSL_Integer llIsFriend(LSL_Key agent_id); LSL_Integer llDerezObject(LSL_Key objectUUID, LSL_Integer flag); + + LSL_Key llRezObjectWithParams(string inventory, LSL_List lparam); + LSL_String llGetStartString(); + } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 74f19eab1c0..d112195b3fb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -221,6 +221,7 @@ public partial class ScriptBaseClass public const int INVENTORY_ANIMATION = 20; public const int INVENTORY_GESTURE = 21; public const int INVENTORY_SETTING = 56; + public const int INVENTORY_MATERIAL = 57; public const int ATTACH_CHEST = 1; public const int ATTACH_HEAD = 2; @@ -379,6 +380,8 @@ public partial class ScriptBaseClass public const int CHANGED_REGION_RESTART = 1024; public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART public const int CHANGED_MEDIA = 2048; + public const int CHANGED_RENDER_MATERIAL = 0x1000; //4096 + //ApiDesc opensim specific public const int CHANGED_ANIMATION = 16384; //ApiDesc opensim specific @@ -539,6 +542,7 @@ public partial class ScriptBaseClass // PRIM_REFLECTION_PROBE flags public const int PRIM_REFLECTION_PROBE_BOX = 1; // 1 public const int PRIM_REFLECTION_PROBE_DYNAMIC = 2; // 2 + public const int PRIM_REFLECTION_PROBE_MIRROR = 4; // 2 public const int PROFILE_NONE = 0; public const int PROFILE_SCRIPT_MEMORY = 1; @@ -1045,5 +1049,31 @@ public partial class ScriptBaseClass public const int SOUND_LOOP = 1; public const int SOUND_TRIGGER = 2; public const int SOUND_SYNC = 4; + + //llRezObjectWithParams Parameters + public const int REZ_PARAM = 0; + public const int REZ_FLAGS = 1; + + //rez flags vlaues + public const int REZ_FLAG_TEMP = 0x0001; + public const int REZ_FLAG_PHYSICAL = 0x0002; + public const int REZ_FLAG_PHANTOM = 0x0004; + public const int REZ_FLAG_DIE_ON_COLLIDE = 0x0008; + public const int REZ_FLAG_DIE_ON_NOENTRY = 0x0010; + public const int REZ_FLAG_NO_COLLIDE_OWNER = 0x0020; + public const int REZ_FLAG_NO_COLLIDE_FAMILY = 0x0040; + public const int REZ_FLAG_BLOCK_GRAB_OBJECT = 0x0080; + + public const int REZ_POS = 2; + public const int REZ_ROT = 3; + public const int REZ_VEL = 4; + public const int REZ_ACCEL = 5; + public const int REZ_OMEGA = 7; + public const int REZ_DAMAGE = 8; + public const int REZ_SOUND = 9; + public const int REZ_SOUND_COLLIDE = 10; + public const int REZ_LOCK_AXES = 11; + public const int REZ_DAMAGE_TYPE = 12; + public const int REZ_PARAM_STRING = 13; } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index e84e664cf5e..53f46f369e6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs @@ -2814,5 +2814,18 @@ public LSL_Integer llDerezObject(LSL_Key objectUUID, LSL_Integer flag) { return m_LSL_Functions.llDerezObject(objectUUID, flag); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public LSL_Key llRezObjectWithParams(string inventory, LSL_List lparam) + { + return m_LSL_Functions.llRezObjectWithParams(inventory, lparam); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public LSL_String llGetStartString() + { + return m_LSL_Functions.llGetStartString(); + } + } } diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs index 1e5cadce7a7..10293f86d38 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs @@ -2835,7 +2835,8 @@ private void GenerateStmtSwitchStr(CompValu testRVal, TokenStmtSwitch switchStmt // Output compare and branch instructions in a tree-like fashion so we do O(log2 n) comparisons. defaultLabel ??= ilGen.DefineLabel("default"); - OutputStrCase(testRVal, caseTreeTop, defaultLabel); + if(caseTreeTop is not null) + OutputStrCase(testRVal, caseTreeTop, defaultLabel); // Output code for the cases themselves, in the order given by the programmer, // so they fall through as programmer wants. This includes the default case, if any. diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptReduce.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptReduce.cs index e1276c69bf4..52fc96f94a4 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptReduce.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptReduce.cs @@ -3092,7 +3092,7 @@ private TokenStmtSwitch ParseStmtSwitch(ref Token token) tokenStmtSwitch.testRVal = ParseRValParen(ref token); if(tokenStmtSwitch.testRVal == null) return null; - if(!(token is TokenKwBrcOpen)) + if(token is not TokenKwBrcOpen) { ErrorMsg(token, "expecting open brace"); token = SkipPastSemi(token); @@ -3101,7 +3101,7 @@ private TokenStmtSwitch ParseStmtSwitch(ref Token token) token = token.nextToken; TokenSwitchCase tokenSwitchCase = null; bool haveComplained = false; - while(!(token is TokenKwBrcClose)) + while(token is not TokenEnd && token is not TokenKwBrcClose) { if(token is TokenKwCase) { @@ -3178,11 +3178,14 @@ private TokenStmtSwitch ParseStmtSwitch(ref Token token) } else if(!haveComplained) { - ErrorMsg(token, "expecting case or default label"); + ErrorMsg(token, "expecting switch case or default"); token = SkipPastSemi(token); haveComplained = true; } } + if(tokenSwitchCase is null) + ErrorMsg(token, "expecting switch case or default"); + token = token.nextToken; return tokenStmtSwitch; } @@ -4329,7 +4332,7 @@ private Token SkipPastSemi(Token token) { int braceLevel = 0; - while(!(token is TokenEnd)) + while(token is not TokenEnd) { if((token is TokenKwSemi) && (braceLevel == 0)) { diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs index 992783f2fde..99335a22853 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs @@ -78,14 +78,14 @@ public override void llDie() inst.Die(); } - public void SetLSLTimer(double time) + public void SetLSLTimerMS(double timeMS) { - m_timer = time; + m_timer = 0.001 * timeMS; } - public double getLSLTimer() + public double getLSLTimerMS() { - return(m_timer); + return m_timer * 1000.0; } /** diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs index d2c86ecac33..67cae3d6dc8 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCapture.cs @@ -115,7 +115,7 @@ public XmlElement GetExecutionState(XmlDocument doc) if(m_XMRLSLApi is not null) { - double scriptTime = Util.GetTimeStampMS() - m_XMRLSLApi.getLSLTimer(); + double scriptTime = Util.GetTimeStampMS() - m_XMRLSLApi.getLSLTimerMS(); XmlElement scriptTimeN = doc.CreateElement("", "scrpTime", ""); scriptTimeN.AppendChild(doc.CreateTextNode(scriptTime.ToString())); scriptStateN.AppendChild(scriptTimeN); diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs index 0b749a36ee1..3f311903c6c 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstCtor.cs @@ -514,7 +514,7 @@ private void LoadScriptState(XmlDocument doc) XmlElement scpttimeN = (XmlElement)scriptStateN.SelectSingleNode("scrpTime"); if (scpttimeN != null && Double.TryParse(scpttimeN.InnerText, out double t)) { - m_XMRLSLApi.SetLSLTimer(Util.GetTimeStampMS() - t); + m_XMRLSLApi.SetLSLTimerMS(Util.GetTimeStampMS() - t); } } diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs index 368dc36660c..152018e6d51 100755 --- a/OpenSim/Server/Base/ServicesServerBase.cs +++ b/OpenSim/Server/Base/ServicesServerBase.cs @@ -180,9 +180,10 @@ public ServicesServerBase(string prompt, string[] args) : base() RegisterCommonAppenders(startupConfig); LogEnvironmentInformation(); - if (startupConfig.GetString("PIDFile", String.Empty) != String.Empty) + string pidfile = startupConfig.GetString("PIDFile", string.Empty); + if (pidfile.Length > 0) { - CreatePIDFile(startupConfig.GetString("PIDFile")); + CreatePIDFile(pidfile); } RegisterCommonCommands(); diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 3da8fe1dd64..0419b4018f3 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -2223,7 +2223,7 @@ [ServerReleaseNotes] ;; Comment or set to "" to disable - ServerReleaseNotesURL = "http://opensimulator.org/wiki/0.9.3.0_Release" + ServerReleaseNotesURL = "http://opensimulator.org/wiki/0.9.3.1_Release" [Modules] Include-modules = "addon-modules/*/config/*.ini"