Merge branch 'master' into careminster
commit
9534d5f929
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class ForeignImporter
|
||||||
|
{
|
||||||
|
IUserManagement m_UserManagement;
|
||||||
|
public ForeignImporter(IUserManagement uman)
|
||||||
|
{
|
||||||
|
m_UserManagement = uman;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupMembersData ConvertGroupMembersData(ExtendedGroupMembersData _m)
|
||||||
|
{
|
||||||
|
GroupMembersData m = new GroupMembersData();
|
||||||
|
m.AcceptNotices = _m.AcceptNotices;
|
||||||
|
m.AgentPowers = _m.AgentPowers;
|
||||||
|
m.Contribution = _m.Contribution;
|
||||||
|
m.IsOwner = _m.IsOwner;
|
||||||
|
m.ListInProfile = _m.ListInProfile;
|
||||||
|
m.OnlineStatus = _m.OnlineStatus;
|
||||||
|
m.Title = _m.Title;
|
||||||
|
|
||||||
|
string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
|
||||||
|
Util.ParseUniversalUserIdentifier(_m.AgentID, out m.AgentID, out url, out first, out last, out tmp);
|
||||||
|
if (url != string.Empty)
|
||||||
|
m_UserManagement.AddUser(m.AgentID, first, last, url);
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupRoleMembersData ConvertGroupRoleMembersData(ExtendedGroupRoleMembersData _rm)
|
||||||
|
{
|
||||||
|
GroupRoleMembersData rm = new GroupRoleMembersData();
|
||||||
|
rm.RoleID = _rm.RoleID;
|
||||||
|
|
||||||
|
string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
|
||||||
|
Util.ParseUniversalUserIdentifier(_rm.MemberID, out rm.MemberID, out url, out first, out last, out tmp);
|
||||||
|
if (url != string.Empty)
|
||||||
|
m_UserManagement.AddUser(rm.MemberID, first, last, url);
|
||||||
|
|
||||||
|
return rm;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,509 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class ExtendedGroupRecord : GroupRecord
|
||||||
|
{
|
||||||
|
public int MemberCount;
|
||||||
|
public int RoleCount;
|
||||||
|
public string ServiceLocation;
|
||||||
|
public string FounderUUI;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExtendedGroupMembershipData : GroupMembershipData
|
||||||
|
{
|
||||||
|
public string AccessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExtendedGroupMembersData
|
||||||
|
{
|
||||||
|
// This is the only difference: this is a string
|
||||||
|
public string AgentID;
|
||||||
|
public int Contribution;
|
||||||
|
public string OnlineStatus;
|
||||||
|
public ulong AgentPowers;
|
||||||
|
public string Title;
|
||||||
|
public bool IsOwner;
|
||||||
|
public bool ListInProfile;
|
||||||
|
public bool AcceptNotices;
|
||||||
|
public string AccessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExtendedGroupRoleMembersData
|
||||||
|
{
|
||||||
|
public UUID RoleID;
|
||||||
|
// This is the only difference: this is a string
|
||||||
|
public string MemberID;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ExtendedGroupNoticeData
|
||||||
|
{
|
||||||
|
public UUID NoticeID;
|
||||||
|
public uint Timestamp;
|
||||||
|
public string FromName;
|
||||||
|
public string Subject;
|
||||||
|
public bool HasAttachment;
|
||||||
|
public byte AttachmentType;
|
||||||
|
public string AttachmentName;
|
||||||
|
public UUID AttachmentItemID;
|
||||||
|
public string AttachmentOwnerID;
|
||||||
|
|
||||||
|
public GroupNoticeData ToGroupNoticeData()
|
||||||
|
{
|
||||||
|
GroupNoticeData n = new GroupNoticeData();
|
||||||
|
n.FromName = this.FromName;
|
||||||
|
n.AssetType = this.AttachmentType;
|
||||||
|
n.HasAttachment = this.HasAttachment;
|
||||||
|
n.NoticeID = this.NoticeID;
|
||||||
|
n.Subject = this.Subject;
|
||||||
|
n.Timestamp = this.Timestamp;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GroupsDataUtils
|
||||||
|
{
|
||||||
|
public static string Sanitize(string s)
|
||||||
|
{
|
||||||
|
return s == null ? string.Empty : s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupRecord(ExtendedGroupRecord grec)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
if (grec == null)
|
||||||
|
return dict;
|
||||||
|
|
||||||
|
dict["AllowPublish"] = grec.AllowPublish.ToString();
|
||||||
|
dict["Charter"] = Sanitize(grec.Charter);
|
||||||
|
dict["FounderID"] = grec.FounderID.ToString();
|
||||||
|
dict["FounderUUI"] = Sanitize(grec.FounderUUI);
|
||||||
|
dict["GroupID"] = grec.GroupID.ToString();
|
||||||
|
dict["GroupName"] = Sanitize(grec.GroupName);
|
||||||
|
dict["InsigniaID"] = grec.GroupPicture.ToString();
|
||||||
|
dict["MaturePublish"] = grec.MaturePublish.ToString();
|
||||||
|
dict["MembershipFee"] = grec.MembershipFee.ToString();
|
||||||
|
dict["OpenEnrollment"] = grec.OpenEnrollment.ToString();
|
||||||
|
dict["OwnerRoleID"] = grec.OwnerRoleID.ToString();
|
||||||
|
dict["ServiceLocation"] = Sanitize(grec.ServiceLocation);
|
||||||
|
dict["ShownInList"] = grec.ShowInList.ToString();
|
||||||
|
dict["MemberCount"] = grec.MemberCount.ToString();
|
||||||
|
dict["RoleCount"] = grec.RoleCount.ToString();
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExtendedGroupRecord GroupRecord(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
if (dict == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ExtendedGroupRecord grec = new ExtendedGroupRecord();
|
||||||
|
if (dict.ContainsKey("AllowPublish") && dict["AllowPublish"] != null)
|
||||||
|
grec.AllowPublish = bool.Parse(dict["AllowPublish"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Charter") && dict["Charter"] != null)
|
||||||
|
grec.Charter = dict["Charter"].ToString();
|
||||||
|
else
|
||||||
|
grec.Charter = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("FounderID") && dict["FounderID"] != null)
|
||||||
|
grec.FounderID = UUID.Parse(dict["FounderID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("FounderUUI") && dict["FounderUUI"] != null)
|
||||||
|
grec.FounderUUI = dict["FounderUUI"].ToString();
|
||||||
|
else
|
||||||
|
grec.FounderUUI = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupID") && dict["GroupID"] != null)
|
||||||
|
grec.GroupID = UUID.Parse(dict["GroupID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupName") && dict["GroupName"] != null)
|
||||||
|
grec.GroupName = dict["GroupName"].ToString();
|
||||||
|
else
|
||||||
|
grec.GroupName = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("InsigniaID") && dict["InsigniaID"] != null)
|
||||||
|
grec.GroupPicture = UUID.Parse(dict["InsigniaID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("MaturePublish") && dict["MaturePublish"] != null)
|
||||||
|
grec.MaturePublish = bool.Parse(dict["MaturePublish"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("MembershipFee") && dict["MembershipFee"] != null)
|
||||||
|
grec.MembershipFee = Int32.Parse(dict["MembershipFee"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("OpenEnrollment") && dict["OpenEnrollment"] != null)
|
||||||
|
grec.OpenEnrollment = bool.Parse(dict["OpenEnrollment"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("OwnerRoleID") && dict["OwnerRoleID"] != null)
|
||||||
|
grec.OwnerRoleID = UUID.Parse(dict["OwnerRoleID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("ServiceLocation") && dict["ServiceLocation"] != null)
|
||||||
|
grec.ServiceLocation = dict["ServiceLocation"].ToString();
|
||||||
|
else
|
||||||
|
grec.GroupName = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("ShownInList") && dict["ShownInList"] != null)
|
||||||
|
grec.ShowInList = bool.Parse(dict["ShownInList"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("MemberCount") && dict["MemberCount"] != null)
|
||||||
|
grec.MemberCount = Int32.Parse(dict["MemberCount"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("RoleCount") && dict["RoleCount"] != null)
|
||||||
|
grec.RoleCount = Int32.Parse(dict["RoleCount"].ToString());
|
||||||
|
|
||||||
|
return grec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupMembershipData(ExtendedGroupMembershipData membership)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
if (membership == null)
|
||||||
|
return dict;
|
||||||
|
|
||||||
|
dict["AcceptNotices"] = membership.AcceptNotices.ToString();
|
||||||
|
dict["AccessToken"] = Sanitize(membership.AccessToken);
|
||||||
|
dict["Active"] = membership.Active.ToString();
|
||||||
|
dict["ActiveRole"] = membership.ActiveRole.ToString();
|
||||||
|
dict["AllowPublish"] = membership.AllowPublish.ToString();
|
||||||
|
dict["Charter"] = Sanitize(membership.Charter);
|
||||||
|
dict["Contribution"] = membership.Contribution.ToString();
|
||||||
|
dict["FounderID"] = membership.FounderID.ToString();
|
||||||
|
dict["GroupID"] = membership.GroupID.ToString();
|
||||||
|
dict["GroupName"] = Sanitize(membership.GroupName);
|
||||||
|
dict["GroupPicture"] = membership.GroupPicture.ToString();
|
||||||
|
dict["GroupPowers"] = membership.GroupPowers.ToString();
|
||||||
|
dict["GroupTitle"] = Sanitize(membership.GroupTitle);
|
||||||
|
dict["ListInProfile"] = membership.ListInProfile.ToString();
|
||||||
|
dict["MaturePublish"] = membership.MaturePublish.ToString();
|
||||||
|
dict["MembershipFee"] = membership.MembershipFee.ToString();
|
||||||
|
dict["OpenEnrollment"] = membership.OpenEnrollment.ToString();
|
||||||
|
dict["ShowInList"] = membership.ShowInList.ToString();
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExtendedGroupMembershipData GroupMembershipData(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
if (dict == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ExtendedGroupMembershipData membership = new ExtendedGroupMembershipData();
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AcceptNotices") && dict["AcceptNotices"] != null)
|
||||||
|
membership.AcceptNotices = bool.Parse(dict["AcceptNotices"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AccessToken") && dict["AccessToken"] != null)
|
||||||
|
membership.AccessToken = dict["AccessToken"].ToString();
|
||||||
|
else
|
||||||
|
membership.AccessToken = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Active") && dict["Active"] != null)
|
||||||
|
membership.Active = bool.Parse(dict["Active"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("ActiveRole") && dict["ActiveRole"] != null)
|
||||||
|
membership.ActiveRole = UUID.Parse(dict["ActiveRole"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AllowPublish") && dict["AllowPublish"] != null)
|
||||||
|
membership.AllowPublish = bool.Parse(dict["AllowPublish"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Charter") && dict["Charter"] != null)
|
||||||
|
membership.Charter = dict["Charter"].ToString();
|
||||||
|
else
|
||||||
|
membership.Charter = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Contribution") && dict["Contribution"] != null)
|
||||||
|
membership.Contribution = Int32.Parse(dict["Contribution"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("FounderID") && dict["FounderID"] != null)
|
||||||
|
membership.FounderID = UUID.Parse(dict["FounderID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupID") && dict["GroupID"] != null)
|
||||||
|
membership.GroupID = UUID.Parse(dict["GroupID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupName") && dict["GroupName"] != null)
|
||||||
|
membership.GroupName = dict["GroupName"].ToString();
|
||||||
|
else
|
||||||
|
membership.GroupName = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupPicture") && dict["GroupPicture"] != null)
|
||||||
|
membership.GroupPicture = UUID.Parse(dict["GroupPicture"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupPowers") && dict["GroupPowers"] != null)
|
||||||
|
membership.GroupPowers = UInt64.Parse(dict["GroupPowers"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("GroupTitle") && dict["GroupTitle"] != null)
|
||||||
|
membership.GroupTitle = dict["GroupTitle"].ToString();
|
||||||
|
else
|
||||||
|
membership.GroupTitle = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("ListInProfile") && dict["ListInProfile"] != null)
|
||||||
|
membership.ListInProfile = bool.Parse(dict["ListInProfile"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("MaturePublish") && dict["MaturePublish"] != null)
|
||||||
|
membership.MaturePublish = bool.Parse(dict["MaturePublish"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("MembershipFee") && dict["MembershipFee"] != null)
|
||||||
|
membership.MembershipFee = Int32.Parse(dict["MembershipFee"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("OpenEnrollment") && dict["OpenEnrollment"] != null)
|
||||||
|
membership.OpenEnrollment = bool.Parse(dict["OpenEnrollment"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("ShowInList") && dict["ShowInList"] != null)
|
||||||
|
membership.ShowInList = bool.Parse(dict["ShowInList"].ToString());
|
||||||
|
|
||||||
|
return membership;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupMembersData(ExtendedGroupMembersData member)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
dict["AcceptNotices"] = member.AcceptNotices.ToString();
|
||||||
|
dict["AccessToken"] = Sanitize(member.AccessToken);
|
||||||
|
dict["AgentID"] = Sanitize(member.AgentID);
|
||||||
|
dict["AgentPowers"] = member.AgentPowers.ToString();
|
||||||
|
dict["Contribution"] = member.Contribution.ToString();
|
||||||
|
dict["IsOwner"] = member.IsOwner.ToString();
|
||||||
|
dict["ListInProfile"] = member.ListInProfile.ToString();
|
||||||
|
dict["OnlineStatus"] = Sanitize(member.OnlineStatus);
|
||||||
|
dict["Title"] = Sanitize(member.Title);
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExtendedGroupMembersData GroupMembersData(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembersData member = new ExtendedGroupMembersData();
|
||||||
|
|
||||||
|
if (dict == null)
|
||||||
|
return member;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AcceptNotices") && dict["AcceptNotices"] != null)
|
||||||
|
member.AcceptNotices = bool.Parse(dict["AcceptNotices"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AccessToken") && dict["AccessToken"] != null)
|
||||||
|
member.AccessToken = Sanitize(dict["AccessToken"].ToString());
|
||||||
|
else
|
||||||
|
member.AccessToken = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AgentID") && dict["AgentID"] != null)
|
||||||
|
member.AgentID = Sanitize(dict["AgentID"].ToString());
|
||||||
|
else
|
||||||
|
member.AgentID = UUID.Zero.ToString();
|
||||||
|
|
||||||
|
if (dict.ContainsKey("AgentPowers") && dict["AgentPowers"] != null)
|
||||||
|
member.AgentPowers = UInt64.Parse(dict["AgentPowers"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Contribution") && dict["Contribution"] != null)
|
||||||
|
member.Contribution = Int32.Parse(dict["Contribution"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("IsOwner") && dict["IsOwner"] != null)
|
||||||
|
member.IsOwner = bool.Parse(dict["IsOwner"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("ListInProfile") && dict["ListInProfile"] != null)
|
||||||
|
member.ListInProfile = bool.Parse(dict["ListInProfile"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("OnlineStatus") && dict["OnlineStatus"] != null)
|
||||||
|
member.OnlineStatus = Sanitize(dict["OnlineStatus"].ToString());
|
||||||
|
else
|
||||||
|
member.OnlineStatus = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Title") && dict["Title"] != null)
|
||||||
|
member.Title = Sanitize(dict["Title"].ToString());
|
||||||
|
else
|
||||||
|
member.Title = string.Empty;
|
||||||
|
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupRolesData(GroupRolesData role)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
dict["Description"] = Sanitize(role.Description);
|
||||||
|
dict["Members"] = role.Members.ToString();
|
||||||
|
dict["Name"] = Sanitize(role.Name);
|
||||||
|
dict["Powers"] = role.Powers.ToString();
|
||||||
|
dict["RoleID"] = role.RoleID.ToString();
|
||||||
|
dict["Title"] = Sanitize(role.Title);
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupRolesData GroupRolesData(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
GroupRolesData role = new GroupRolesData();
|
||||||
|
|
||||||
|
if (dict == null)
|
||||||
|
return role;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Description") && dict["Description"] != null)
|
||||||
|
role.Description = Sanitize(dict["Description"].ToString());
|
||||||
|
else
|
||||||
|
role.Description = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Members") && dict["Members"] != null)
|
||||||
|
role.Members = Int32.Parse(dict["Members"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Name") && dict["Name"] != null)
|
||||||
|
role.Name = Sanitize(dict["Name"].ToString());
|
||||||
|
else
|
||||||
|
role.Name = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Powers") && dict["Powers"] != null)
|
||||||
|
role.Powers = UInt64.Parse(dict["Powers"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("Title") && dict["Title"] != null)
|
||||||
|
role.Title = Sanitize(dict["Title"].ToString());
|
||||||
|
else
|
||||||
|
role.Title = string.Empty;
|
||||||
|
|
||||||
|
if (dict.ContainsKey("RoleID") && dict["RoleID"] != null)
|
||||||
|
role.RoleID = UUID.Parse(dict["RoleID"].ToString());
|
||||||
|
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupRoleMembersData(ExtendedGroupRoleMembersData rmember)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
dict["RoleID"] = rmember.RoleID.ToString();
|
||||||
|
dict["MemberID"] = rmember.MemberID;
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExtendedGroupRoleMembersData GroupRoleMembersData(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
ExtendedGroupRoleMembersData rmember = new ExtendedGroupRoleMembersData();
|
||||||
|
|
||||||
|
if (dict.ContainsKey("RoleID") && dict["RoleID"] != null)
|
||||||
|
rmember.RoleID = new UUID(dict["RoleID"].ToString());
|
||||||
|
|
||||||
|
if (dict.ContainsKey("MemberID") && dict["MemberID"] != null)
|
||||||
|
rmember.MemberID = dict["MemberID"].ToString();
|
||||||
|
|
||||||
|
return rmember;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupInviteInfo(GroupInviteInfo invite)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
dict["InviteID"] = invite.InviteID.ToString();
|
||||||
|
dict["GroupID"] = invite.GroupID.ToString();
|
||||||
|
dict["RoleID"] = invite.RoleID.ToString();
|
||||||
|
dict["AgentID"] = invite.AgentID;
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupInviteInfo GroupInviteInfo(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
if (dict == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
GroupInviteInfo invite = new GroupInviteInfo();
|
||||||
|
|
||||||
|
invite.InviteID = new UUID(dict["InviteID"].ToString());
|
||||||
|
invite.GroupID = new UUID(dict["GroupID"].ToString());
|
||||||
|
invite.RoleID = new UUID(dict["RoleID"].ToString());
|
||||||
|
invite.AgentID = Sanitize(dict["AgentID"].ToString());
|
||||||
|
|
||||||
|
return invite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupNoticeData(ExtendedGroupNoticeData notice)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
dict["NoticeID"] = notice.NoticeID.ToString();
|
||||||
|
dict["Timestamp"] = notice.Timestamp.ToString();
|
||||||
|
dict["FromName"] = Sanitize(notice.FromName);
|
||||||
|
dict["Subject"] = Sanitize(notice.Subject);
|
||||||
|
dict["HasAttachment"] = notice.HasAttachment.ToString();
|
||||||
|
dict["AttachmentItemID"] = notice.AttachmentItemID.ToString();
|
||||||
|
dict["AttachmentName"] = Sanitize(notice.AttachmentName);
|
||||||
|
dict["AttachmentType"] = notice.AttachmentType.ToString();
|
||||||
|
dict["AttachmentOwnerID"] = Sanitize(notice.AttachmentOwnerID);
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExtendedGroupNoticeData GroupNoticeData(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
ExtendedGroupNoticeData notice = new ExtendedGroupNoticeData();
|
||||||
|
|
||||||
|
if (dict == null)
|
||||||
|
return notice;
|
||||||
|
|
||||||
|
notice.NoticeID = new UUID(dict["NoticeID"].ToString());
|
||||||
|
notice.Timestamp = UInt32.Parse(dict["Timestamp"].ToString());
|
||||||
|
notice.FromName = Sanitize(dict["FromName"].ToString());
|
||||||
|
notice.Subject = Sanitize(dict["Subject"].ToString());
|
||||||
|
notice.HasAttachment = bool.Parse(dict["HasAttachment"].ToString());
|
||||||
|
notice.AttachmentItemID = new UUID(dict["AttachmentItemID"].ToString());
|
||||||
|
notice.AttachmentName = dict["AttachmentName"].ToString();
|
||||||
|
notice.AttachmentType = byte.Parse(dict["AttachmentType"].ToString());
|
||||||
|
notice.AttachmentOwnerID = dict["AttachmentOwnerID"].ToString();
|
||||||
|
|
||||||
|
return notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, object> GroupNoticeInfo(GroupNoticeInfo notice)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = GroupNoticeData(notice.noticeData);
|
||||||
|
|
||||||
|
dict["GroupID"] = notice.GroupID.ToString();
|
||||||
|
dict["Message"] = Sanitize(notice.Message);
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupNoticeInfo GroupNoticeInfo(Dictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = new GroupNoticeInfo();
|
||||||
|
|
||||||
|
notice.noticeData = GroupNoticeData(dict);
|
||||||
|
notice.GroupID = new UUID(dict["GroupID"].ToString());
|
||||||
|
notice.Message = Sanitize(dict["Message"].ToString());
|
||||||
|
|
||||||
|
return notice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,594 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using log4net;
|
||||||
|
using Mono.Addins;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsMessagingModule")]
|
||||||
|
public class GroupsMessagingModule : ISharedRegionModule, IGroupsMessagingModule
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private List<Scene> m_sceneList = new List<Scene>();
|
||||||
|
private IPresenceService m_presenceService;
|
||||||
|
|
||||||
|
private IMessageTransferModule m_msgTransferModule = null;
|
||||||
|
|
||||||
|
private IGroupsServicesConnector m_groupData = null;
|
||||||
|
|
||||||
|
// Config Options
|
||||||
|
private bool m_groupMessagingEnabled = false;
|
||||||
|
private bool m_debugEnabled = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If enabled, module only tries to send group IMs to online users by querying cached presence information.
|
||||||
|
/// </summary>
|
||||||
|
private bool m_messageOnlineAgentsOnly;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cache for online users.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Group ID is key, presence information for online members is value.
|
||||||
|
/// Will only be non-null if m_messageOnlineAgentsOnly = true
|
||||||
|
/// We cache here so that group messages don't constantly have to re-request the online user list to avoid
|
||||||
|
/// attempted expensive sending of messages to offline users.
|
||||||
|
/// The tradeoff is that a user that comes online will not receive messages consistently from all other users
|
||||||
|
/// until caches have updated.
|
||||||
|
/// Therefore, we set the cache expiry to just 20 seconds.
|
||||||
|
/// </remarks>
|
||||||
|
private ExpiringCache<UUID, PresenceInfo[]> m_usersOnlineCache;
|
||||||
|
|
||||||
|
private int m_usersOnlineCacheExpirySeconds = 20;
|
||||||
|
|
||||||
|
#region Region Module interfaceBase Members
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig groupsConfig = config.Configs["Groups"];
|
||||||
|
|
||||||
|
if (groupsConfig == null)
|
||||||
|
// Do not run this module by default.
|
||||||
|
return;
|
||||||
|
|
||||||
|
// if groups aren't enabled, we're not needed.
|
||||||
|
// if we're not specified as the connector to use, then we're not wanted
|
||||||
|
if ((groupsConfig.GetBoolean("Enabled", false) == false)
|
||||||
|
|| (groupsConfig.GetString("MessagingModule", "") != Name))
|
||||||
|
{
|
||||||
|
m_groupMessagingEnabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_groupMessagingEnabled = groupsConfig.GetBoolean("MessagingEnabled", true);
|
||||||
|
|
||||||
|
if (!m_groupMessagingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false);
|
||||||
|
|
||||||
|
if (m_messageOnlineAgentsOnly)
|
||||||
|
m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>();
|
||||||
|
|
||||||
|
m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true);
|
||||||
|
|
||||||
|
m_log.InfoFormat(
|
||||||
|
"[Groups.Messaging]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}",
|
||||||
|
m_messageOnlineAgentsOnly, m_debugEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_groupMessagingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.RegisterModuleInterface<IGroupsMessagingModule>(this);
|
||||||
|
m_sceneList.Add(scene);
|
||||||
|
|
||||||
|
scene.EventManager.OnNewClient += OnNewClient;
|
||||||
|
scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
|
||||||
|
scene.EventManager.OnClientLogin += OnClientLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_groupMessagingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||||
|
|
||||||
|
m_groupData = scene.RequestModuleInterface<IGroupsServicesConnector>();
|
||||||
|
|
||||||
|
// No groups module, no groups messaging
|
||||||
|
if (m_groupData == null)
|
||||||
|
{
|
||||||
|
m_log.Error("[Groups.Messaging]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled.");
|
||||||
|
RemoveRegion(scene);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_msgTransferModule = scene.RequestModuleInterface<IMessageTransferModule>();
|
||||||
|
|
||||||
|
// No message transfer module, no groups messaging
|
||||||
|
if (m_msgTransferModule == null)
|
||||||
|
{
|
||||||
|
m_log.Error("[Groups.Messaging]: Could not get MessageTransferModule");
|
||||||
|
RemoveRegion(scene);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_presenceService == null)
|
||||||
|
m_presenceService = scene.PresenceService;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_groupMessagingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||||
|
|
||||||
|
m_sceneList.Remove(scene);
|
||||||
|
scene.EventManager.OnNewClient -= OnNewClient;
|
||||||
|
scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
|
||||||
|
scene.EventManager.OnClientLogin -= OnClientLogin;
|
||||||
|
scene.UnregisterModuleInterface<IGroupsMessagingModule>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
if (!m_groupMessagingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_debugEnabled) m_log.Debug("[Groups.Messaging]: Shutting down GroupsMessagingModule module.");
|
||||||
|
|
||||||
|
m_sceneList.Clear();
|
||||||
|
|
||||||
|
m_groupData = null;
|
||||||
|
m_msgTransferModule = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Groups Messaging Module V2"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
// NoOp
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Not really needed, but does confirm that the group exists.
|
||||||
|
/// </summary>
|
||||||
|
public bool StartGroupChatSession(UUID agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled)
|
||||||
|
m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||||
|
|
||||||
|
GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null);
|
||||||
|
|
||||||
|
if (groupInfo != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
|
||||||
|
{
|
||||||
|
List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID).ToString(), groupID);
|
||||||
|
int groupMembersCount = groupMembers.Count;
|
||||||
|
|
||||||
|
if (m_messageOnlineAgentsOnly)
|
||||||
|
{
|
||||||
|
string[] t1 = groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()).ToArray();
|
||||||
|
|
||||||
|
// We cache in order not to overwhlem the presence service on large grids with many groups. This does
|
||||||
|
// mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed.
|
||||||
|
// (assuming this is the same across all grid simulators).
|
||||||
|
PresenceInfo[] onlineAgents;
|
||||||
|
if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents))
|
||||||
|
{
|
||||||
|
onlineAgents = m_presenceService.GetAgents(t1);
|
||||||
|
m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<string> onlineAgentsUuidSet = new HashSet<string>();
|
||||||
|
Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID));
|
||||||
|
|
||||||
|
groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList();
|
||||||
|
|
||||||
|
// if (m_debugEnabled)
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members, {2} online",
|
||||||
|
// groupID, groupMembersCount, groupMembers.Count());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_debugEnabled)
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members",
|
||||||
|
groupID, groupMembers.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int requestStartTick = Environment.TickCount;
|
||||||
|
|
||||||
|
foreach (GroupMembersData member in groupMembers)
|
||||||
|
{
|
||||||
|
if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID))
|
||||||
|
{
|
||||||
|
// Don't deliver messages to people who have dropped this session
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy Message
|
||||||
|
GridInstantMessage msg = new GridInstantMessage();
|
||||||
|
msg.imSessionID = groupID.Guid;
|
||||||
|
msg.fromAgentName = im.fromAgentName;
|
||||||
|
msg.message = im.message;
|
||||||
|
msg.dialog = im.dialog;
|
||||||
|
msg.offline = im.offline;
|
||||||
|
msg.ParentEstateID = im.ParentEstateID;
|
||||||
|
msg.Position = im.Position;
|
||||||
|
msg.RegionID = im.RegionID;
|
||||||
|
msg.binaryBucket = im.binaryBucket;
|
||||||
|
msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
|
||||||
|
|
||||||
|
msg.fromAgentID = im.fromAgentID;
|
||||||
|
msg.fromGroup = true;
|
||||||
|
|
||||||
|
msg.toAgentID = member.AgentID.Guid;
|
||||||
|
|
||||||
|
IClientAPI client = GetActiveClient(member.AgentID);
|
||||||
|
if (client == null)
|
||||||
|
{
|
||||||
|
// If they're not local, forward across the grid
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} via Grid", member.AgentID);
|
||||||
|
m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Deliver locally, directly
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name);
|
||||||
|
ProcessMessageFromGroupSession(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporary for assessing how long it still takes to send messages to large online groups.
|
||||||
|
if (m_messageOnlineAgentsOnly)
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms",
|
||||||
|
groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region SimGridEventHandlers
|
||||||
|
|
||||||
|
void OnClientLogin(IClientAPI client)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNewClient(IClientAPI client)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name);
|
||||||
|
|
||||||
|
client.OnInstantMessage += OnInstantMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGridInstantMessage(GridInstantMessage msg)
|
||||||
|
{
|
||||||
|
// The instant message module will only deliver messages of dialog types:
|
||||||
|
// MessageFromAgent, StartTyping, StopTyping, MessageFromObject
|
||||||
|
//
|
||||||
|
// Any other message type will not be delivered to a client by the
|
||||||
|
// Instant Message Module
|
||||||
|
|
||||||
|
|
||||||
|
if (m_debugEnabled)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||||
|
|
||||||
|
DebugGridInstantMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Incoming message from a group
|
||||||
|
if ((msg.fromGroup == true) &&
|
||||||
|
((msg.dialog == (byte)InstantMessageDialog.SessionSend)
|
||||||
|
|| (msg.dialog == (byte)InstantMessageDialog.SessionAdd)
|
||||||
|
|| (msg.dialog == (byte)InstantMessageDialog.SessionDrop)))
|
||||||
|
{
|
||||||
|
ProcessMessageFromGroupSession(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessMessageFromGroupSession(GridInstantMessage msg)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID);
|
||||||
|
|
||||||
|
UUID AgentID = new UUID(msg.fromAgentID);
|
||||||
|
UUID GroupID = new UUID(msg.imSessionID);
|
||||||
|
|
||||||
|
switch (msg.dialog)
|
||||||
|
{
|
||||||
|
case (byte)InstantMessageDialog.SessionAdd:
|
||||||
|
m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (byte)InstantMessageDialog.SessionDrop:
|
||||||
|
m_groupData.AgentDroppedFromGroupChatSession(AgentID.ToString(), GroupID);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (byte)InstantMessageDialog.SessionSend:
|
||||||
|
if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID)
|
||||||
|
&& !m_groupData.hasAgentBeenInvitedToGroupChatSession(AgentID.ToString(), GroupID)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Agent not in session and hasn't dropped from session
|
||||||
|
// Add them to the session for now, and Invite them
|
||||||
|
m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||||
|
|
||||||
|
UUID toAgentID = new UUID(msg.toAgentID);
|
||||||
|
IClientAPI activeClient = GetActiveClient(toAgentID);
|
||||||
|
if (activeClient != null)
|
||||||
|
{
|
||||||
|
GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null);
|
||||||
|
if (groupInfo != null)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Sending chatterbox invite instant message");
|
||||||
|
|
||||||
|
// Force? open the group session dialog???
|
||||||
|
// and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg);
|
||||||
|
IEventQueue eq = activeClient.Scene.RequestModuleInterface<IEventQueue>();
|
||||||
|
eq.ChatterboxInvitation(
|
||||||
|
GroupID
|
||||||
|
, groupInfo.GroupName
|
||||||
|
, new UUID(msg.fromAgentID)
|
||||||
|
, msg.message
|
||||||
|
, new UUID(msg.toAgentID)
|
||||||
|
, msg.fromAgentName
|
||||||
|
, msg.dialog
|
||||||
|
, msg.timestamp
|
||||||
|
, msg.offline == 1
|
||||||
|
, (int)msg.ParentEstateID
|
||||||
|
, msg.Position
|
||||||
|
, 1
|
||||||
|
, new UUID(msg.imSessionID)
|
||||||
|
, msg.fromGroup
|
||||||
|
, OpenMetaverse.Utils.StringToBytes(groupInfo.GroupName)
|
||||||
|
);
|
||||||
|
|
||||||
|
eq.ChatterBoxSessionAgentListUpdates(
|
||||||
|
new UUID(GroupID)
|
||||||
|
, new UUID(msg.fromAgentID)
|
||||||
|
, new UUID(msg.toAgentID)
|
||||||
|
, false //canVoiceChat
|
||||||
|
, false //isModerator
|
||||||
|
, false //text mute
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID))
|
||||||
|
{
|
||||||
|
// User hasn't dropped, so they're in the session,
|
||||||
|
// maybe we should deliver it.
|
||||||
|
IClientAPI client = GetActiveClient(new UUID(msg.toAgentID));
|
||||||
|
if (client != null)
|
||||||
|
{
|
||||||
|
// Deliver locally, directly
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} locally", client.Name);
|
||||||
|
client.SendInstantMessage(msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: I don't know how to proccess a {0} message.", ((InstantMessageDialog)msg.dialog).ToString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region ClientEvents
|
||||||
|
private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||||
|
|
||||||
|
DebugGridInstantMessage(im);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start group IM session
|
||||||
|
if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart))
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.InfoFormat("[Groups.Messaging]: imSessionID({0}) toAgentID({1})", im.imSessionID, im.toAgentID);
|
||||||
|
|
||||||
|
UUID GroupID = new UUID(im.imSessionID);
|
||||||
|
UUID AgentID = new UUID(im.fromAgentID);
|
||||||
|
|
||||||
|
GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null);
|
||||||
|
|
||||||
|
if (groupInfo != null)
|
||||||
|
{
|
||||||
|
m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||||
|
|
||||||
|
ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID);
|
||||||
|
|
||||||
|
IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
|
||||||
|
queue.ChatterBoxSessionAgentListUpdates(
|
||||||
|
GroupID
|
||||||
|
, AgentID
|
||||||
|
, new UUID(im.toAgentID)
|
||||||
|
, false //canVoiceChat
|
||||||
|
, false //isModerator
|
||||||
|
, false //text mute
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a message from locally connected client to a group
|
||||||
|
if ((im.dialog == (byte)InstantMessageDialog.SessionSend))
|
||||||
|
{
|
||||||
|
UUID GroupID = new UUID(im.imSessionID);
|
||||||
|
UUID AgentID = new UUID(im.fromAgentID);
|
||||||
|
|
||||||
|
if (m_debugEnabled)
|
||||||
|
m_log.DebugFormat("[Groups.Messaging]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString());
|
||||||
|
|
||||||
|
//If this agent is sending a message, then they want to be in the session
|
||||||
|
m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
|
||||||
|
|
||||||
|
SendMessageToGroup(im, GroupID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
void ChatterBoxSessionStartReplyViaCaps(IClientAPI remoteClient, string groupName, UUID groupID)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
|
||||||
|
|
||||||
|
OSDMap moderatedMap = new OSDMap(4);
|
||||||
|
moderatedMap.Add("voice", OSD.FromBoolean(false));
|
||||||
|
|
||||||
|
OSDMap sessionMap = new OSDMap(4);
|
||||||
|
sessionMap.Add("moderated_mode", moderatedMap);
|
||||||
|
sessionMap.Add("session_name", OSD.FromString(groupName));
|
||||||
|
sessionMap.Add("type", OSD.FromInteger(0));
|
||||||
|
sessionMap.Add("voice_enabled", OSD.FromBoolean(false));
|
||||||
|
|
||||||
|
OSDMap bodyMap = new OSDMap(4);
|
||||||
|
bodyMap.Add("session_id", OSD.FromUUID(groupID));
|
||||||
|
bodyMap.Add("temp_session_id", OSD.FromUUID(groupID));
|
||||||
|
bodyMap.Add("success", OSD.FromBoolean(true));
|
||||||
|
bodyMap.Add("session_info", sessionMap);
|
||||||
|
|
||||||
|
IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
|
||||||
|
|
||||||
|
if (queue != null)
|
||||||
|
{
|
||||||
|
queue.Enqueue(queue.BuildEvent("ChatterBoxSessionStartReply", bodyMap), remoteClient.AgentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DebugGridInstantMessage(GridInstantMessage im)
|
||||||
|
{
|
||||||
|
// Don't log any normal IMs (privacy!)
|
||||||
|
if (m_debugEnabled && im.dialog != (byte)InstantMessageDialog.MessageFromAgent)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: fromGroup({0})", im.fromGroup ? "True" : "False");
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: Dialog({0})", ((InstantMessageDialog)im.dialog).ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: fromAgentID({0})", im.fromAgentID.ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: fromAgentName({0})", im.fromAgentName.ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: imSessionID({0})", im.imSessionID.ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: message({0})", im.message.ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: offline({0})", im.offline.ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: toAgentID({0})", im.toAgentID.ToString());
|
||||||
|
m_log.WarnFormat("[Groups.Messaging]: IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Client Tools
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to find an active IClientAPI reference for agentID giving preference to root connections
|
||||||
|
/// </summary>
|
||||||
|
private IClientAPI GetActiveClient(UUID agentID)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Looking for local client {0}", agentID);
|
||||||
|
|
||||||
|
IClientAPI child = null;
|
||||||
|
|
||||||
|
// Try root avatar first
|
||||||
|
foreach (Scene scene in m_sceneList)
|
||||||
|
{
|
||||||
|
ScenePresence sp = scene.GetScenePresence(agentID);
|
||||||
|
if (sp != null)
|
||||||
|
{
|
||||||
|
if (!sp.IsChildAgent)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Found root agent for client : {0}", sp.ControllingClient.Name);
|
||||||
|
return sp.ControllingClient;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Found child agent for client : {0}", sp.ControllingClient.Name);
|
||||||
|
child = sp.ControllingClient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we didn't find a root, then just return whichever child we found, or null if none
|
||||||
|
if (child == null)
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Could not find local client for agent : {0}", agentID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Returning child agent for client : {0}", child.Name);
|
||||||
|
}
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,289 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class GroupsServiceHGConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private string m_ServerURI;
|
||||||
|
private object m_Lock = new object();
|
||||||
|
|
||||||
|
public GroupsServiceHGConnector(string url)
|
||||||
|
{
|
||||||
|
m_ServerURI = url;
|
||||||
|
if (!m_ServerURI.EndsWith("/"))
|
||||||
|
m_ServerURI += "/";
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups.HGConnector]: Groups server at {0}", m_ServerURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CreateProxy(string RequestingAgentID, string AgentID, string accessToken, UUID groupID, string url, string name, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string,object>();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["AccessToken"] = accessToken;
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["Location"] = url;
|
||||||
|
sendData["Name"] = name;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("POSTGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
{
|
||||||
|
reason = ret["REASON"].ToString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string AgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
MakeRequest("REMOVEAGENTFROMGROUP", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName, string token)
|
||||||
|
{
|
||||||
|
if (GroupID == UUID.Zero && (GroupName == null || (GroupName != null && GroupName == string.Empty)))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
if (GroupID != UUID.Zero)
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
if (GroupName != null && GroupName != string.Empty)
|
||||||
|
sendData["Name"] = GroupsDataUtils.Sanitize(GroupName);
|
||||||
|
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> members = new List<ExtendedGroupMembersData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUPMEMBERS", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return members;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return members;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return members;
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary<string, object>)v);
|
||||||
|
members.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
List<GroupRolesData> roles = new List<GroupRolesData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUPROLES", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return roles;
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
|
||||||
|
roles.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> rmembers = new List<ExtendedGroupRoleMembersData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETROLEMEMBERS", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return rmembers;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return rmembers;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return rmembers;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupRoleMembersData m = GroupsDataUtils.GroupRoleMembersData((Dictionary<string, object>)v);
|
||||||
|
rmembers.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rmembers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
|
||||||
|
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["NoticeID"] = noticeID.ToString();
|
||||||
|
sendData["FromName"] = GroupsDataUtils.Sanitize(fromName);
|
||||||
|
sendData["Subject"] = GroupsDataUtils.Sanitize(subject);
|
||||||
|
sendData["Message"] = GroupsDataUtils.Sanitize(message);
|
||||||
|
sendData["HasAttachment"] = hasAttachment.ToString();
|
||||||
|
if (hasAttachment)
|
||||||
|
{
|
||||||
|
sendData["AttachmentType"] = attType.ToString();
|
||||||
|
sendData["AttachmentName"] = attName.ToString();
|
||||||
|
sendData["AttachmentItemID"] = attItemID.ToString();
|
||||||
|
sendData["AttachmentOwnerID"] = attOwnerID;
|
||||||
|
}
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("ADDNOTICE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool VerifyNotice(UUID noticeID, UUID groupID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["NoticeID"] = noticeID.ToString();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
Dictionary<string, object> ret = MakeRequest("VERIFYNOTICE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#region Make Request
|
||||||
|
|
||||||
|
private Dictionary<string, object> MakeRequest(string method, Dictionary<string, object> sendData)
|
||||||
|
{
|
||||||
|
sendData["METHOD"] = method;
|
||||||
|
|
||||||
|
string reply = string.Empty;
|
||||||
|
lock (m_Lock)
|
||||||
|
reply = SynchronousRestFormsRequester.MakeRequest("POST",
|
||||||
|
m_ServerURI + "hg-groups",
|
||||||
|
ServerUtils.BuildQueryString(sendData));
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: reply was {0}", reply);
|
||||||
|
|
||||||
|
if (reply == string.Empty || reply == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
|
||||||
|
reply);
|
||||||
|
|
||||||
|
return replyData;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,717 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using Mono.Addins;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsServiceHGConnectorModule")]
|
||||||
|
public class GroupsServiceHGConnectorModule : ISharedRegionModule, IGroupsServicesConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private bool m_Enabled = false;
|
||||||
|
private IGroupsServicesConnector m_LocalGroupsConnector;
|
||||||
|
private string m_LocalGroupsServiceLocation;
|
||||||
|
private IUserManagement m_UserManagement;
|
||||||
|
private IOfflineIMService m_OfflineIM;
|
||||||
|
private IMessageTransferModule m_Messaging;
|
||||||
|
private List<Scene> m_Scenes;
|
||||||
|
private ForeignImporter m_ForeignImporter;
|
||||||
|
private string m_ServiceLocation;
|
||||||
|
private IConfigSource m_Config;
|
||||||
|
|
||||||
|
private Dictionary<string, GroupsServiceHGConnector> m_NetworkConnectors = new Dictionary<string, GroupsServiceHGConnector>();
|
||||||
|
private RemoteConnectorCacheWrapper m_CacheWrapper; // for caching info of external group services
|
||||||
|
|
||||||
|
#region ISharedRegionModule
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig groupsConfig = config.Configs["Groups"];
|
||||||
|
if (groupsConfig == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((groupsConfig.GetBoolean("Enabled", false) == false)
|
||||||
|
|| (groupsConfig.GetString("ServicesConnectorModule", string.Empty) != Name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Config = config;
|
||||||
|
m_ServiceLocation = groupsConfig.GetString("LocalService", "local"); // local or remote
|
||||||
|
m_LocalGroupsServiceLocation = groupsConfig.GetString("GroupsExternalURI", "http://127.0.0.1");
|
||||||
|
m_Scenes = new List<Scene>();
|
||||||
|
|
||||||
|
m_Enabled = true;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups]: Initializing {0} with LocalService {1}", this.Name, m_ServiceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Groups HG Service Connector"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
|
||||||
|
scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Add(scene);
|
||||||
|
|
||||||
|
scene.EventManager.OnNewClient += OnNewClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Remove(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_UserManagement == null)
|
||||||
|
{
|
||||||
|
m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
|
||||||
|
m_OfflineIM = scene.RequestModuleInterface<IOfflineIMService>();
|
||||||
|
m_Messaging = scene.RequestModuleInterface<IMessageTransferModule>();
|
||||||
|
m_ForeignImporter = new ForeignImporter(m_UserManagement);
|
||||||
|
|
||||||
|
if (m_ServiceLocation.Equals("local"))
|
||||||
|
{
|
||||||
|
m_LocalGroupsConnector = new GroupsServiceLocalConnectorModule(m_Config, m_UserManagement);
|
||||||
|
// Also, if local, create the endpoint for the HGGroupsService
|
||||||
|
new HGGroupsServiceRobustConnector(m_Config, MainServer.Instance, string.Empty,
|
||||||
|
scene.RequestModuleInterface<IOfflineIMService>(), scene.RequestModuleInterface<IUserAccountService>());
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_LocalGroupsConnector = new GroupsServiceRemoteConnectorModule(m_Config, m_UserManagement);
|
||||||
|
|
||||||
|
m_CacheWrapper = new RemoteConnectorCacheWrapper(m_UserManagement);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void OnNewClient(IClientAPI client)
|
||||||
|
{
|
||||||
|
client.OnCompleteMovementToRegion += OnCompleteMovementToRegion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnCompleteMovementToRegion(IClientAPI client, bool arg2)
|
||||||
|
{
|
||||||
|
object sp = null;
|
||||||
|
if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
|
||||||
|
{
|
||||||
|
if (sp is ScenePresence && ((ScenePresence)sp).PresenceType != PresenceType.Npc)
|
||||||
|
{
|
||||||
|
AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId);
|
||||||
|
if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 &&
|
||||||
|
m_OfflineIM != null && m_Messaging != null)
|
||||||
|
{
|
||||||
|
List<GridInstantMessage> ims = m_OfflineIM.GetMessages(aCircuit.AgentID);
|
||||||
|
if (ims != null && ims.Count > 0)
|
||||||
|
foreach (GridInstantMessage im in ims)
|
||||||
|
m_Messaging.SendInstantMessage(im, delegate(bool success) { });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IGroupsServicesConnector
|
||||||
|
|
||||||
|
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
|
||||||
|
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups]: Creating group {0}", name);
|
||||||
|
reason = string.Empty;
|
||||||
|
if (m_UserManagement.IsLocalGridUser(RequestingAgentID))
|
||||||
|
return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID,
|
||||||
|
membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reason = "Only local grid users are allowed to create a new group";
|
||||||
|
return UUID.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
|
||||||
|
bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
string url = string.Empty;
|
||||||
|
string name = string.Empty;
|
||||||
|
if (IsLocal(groupID, out url, out name))
|
||||||
|
return m_LocalGroupsConnector.UpdateGroup(AgentUUI(RequestingAgentID), groupID, charter, showInList, insigniaID, membershipFee,
|
||||||
|
openEnrollment, allowPublish, maturePublish, out reason);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reason = "Changes to remote group not allowed. Please go to the group's original world.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName)
|
||||||
|
{
|
||||||
|
string url = string.Empty;
|
||||||
|
string name = string.Empty;
|
||||||
|
if (IsLocal(GroupID, out url, out name))
|
||||||
|
return m_LocalGroupsConnector.GetGroupRecord(AgentUUI(RequestingAgentID), GroupID, GroupName);
|
||||||
|
else if (url != string.Empty)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, GroupID);
|
||||||
|
string accessToken = string.Empty;
|
||||||
|
if (membership != null)
|
||||||
|
accessToken = membership.AccessToken;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
|
GroupsServiceHGConnector c = GetConnector(url);
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
ExtendedGroupRecord grec = m_CacheWrapper.GetGroupRecord(RequestingAgentID, GroupID, GroupName, delegate
|
||||||
|
{
|
||||||
|
return c.GetGroupRecord(AgentUUIForOutside(RequestingAgentID), GroupID, GroupName, accessToken);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (grec != null)
|
||||||
|
ImportForeigner(grec.FounderUUI);
|
||||||
|
return grec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
|
||||||
|
{
|
||||||
|
return m_LocalGroupsConnector.FindGroups(AgentUUI(RequestingAgentID), search);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.GetGroupMembers(AgentUUI(RequestingAgentID), GroupID);
|
||||||
|
else if (!string.IsNullOrEmpty(url))
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, GroupID);
|
||||||
|
string accessToken = string.Empty;
|
||||||
|
if (membership != null)
|
||||||
|
accessToken = membership.AccessToken;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
|
GroupsServiceHGConnector c = GetConnector(url);
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupMembers(RequestingAgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return c.GetGroupMembers(AgentUUIForOutside(RequestingAgentID), GroupID, accessToken);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new List<GroupMembersData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.AddGroupRole(AgentUUI(RequestingAgentID), groupID, roleID, name, description, title, powers, out reason);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reason = "Operation not allowed outside this group's origin world.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.UpdateGroupRole(AgentUUI(RequestingAgentID), groupID, roleID, name, description, title, powers);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
m_LocalGroupsConnector.RemoveGroupRole(AgentUUI(RequestingAgentID), groupID, roleID);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID groupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.GetGroupRoles(AgentUUI(RequestingAgentID), groupID);
|
||||||
|
else if (!string.IsNullOrEmpty(url))
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, groupID);
|
||||||
|
string accessToken = string.Empty;
|
||||||
|
if (membership != null)
|
||||||
|
accessToken = membership.AccessToken;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
|
GroupsServiceHGConnector c = GetConnector(url);
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupRoles(RequestingAgentID, groupID, delegate
|
||||||
|
{
|
||||||
|
return c.GetGroupRoles(AgentUUIForOutside(RequestingAgentID), groupID, accessToken);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<GroupRolesData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID groupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.GetGroupRoleMembers(AgentUUI(RequestingAgentID), groupID);
|
||||||
|
else if (!string.IsNullOrEmpty(url))
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, groupID);
|
||||||
|
string accessToken = string.Empty;
|
||||||
|
if (membership != null)
|
||||||
|
accessToken = membership.AccessToken;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
|
GroupsServiceHGConnector c = GetConnector(url);
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupRoleMembers(RequestingAgentID, groupID, delegate
|
||||||
|
{
|
||||||
|
return c.GetGroupRoleMembers(AgentUUIForOutside(RequestingAgentID), groupID, accessToken);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<GroupRoleMembersData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
|
||||||
|
{
|
||||||
|
string url = string.Empty;
|
||||||
|
string name = string.Empty;
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
UUID uid = new UUID(AgentID);
|
||||||
|
if (IsLocal(GroupID, out url, out name))
|
||||||
|
{
|
||||||
|
if (m_UserManagement.IsLocalGridUser(uid)) // local user
|
||||||
|
{
|
||||||
|
// normal case: local group, local user
|
||||||
|
return m_LocalGroupsConnector.AddAgentToGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID, token, out reason);
|
||||||
|
}
|
||||||
|
else // local group, foreign user
|
||||||
|
{
|
||||||
|
// the user is accepting the invitation, or joining, where the group resides
|
||||||
|
token = UUID.Random().ToString();
|
||||||
|
bool success = m_LocalGroupsConnector.AddAgentToGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID, token, out reason);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
url = m_UserManagement.GetUserServerURL(uid, "GroupsServerURI");
|
||||||
|
if (url == string.Empty)
|
||||||
|
{
|
||||||
|
reason = "User doesn't have a groups server";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupsServiceHGConnector c = GetConnector(url);
|
||||||
|
if (c != null)
|
||||||
|
return c.CreateProxy(AgentUUI(RequestingAgentID), AgentID, token, GroupID, m_LocalGroupsServiceLocation, name, out reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_UserManagement.IsLocalGridUser(uid)) // local user
|
||||||
|
{
|
||||||
|
// foreign group, local user. She's been added already by the HG service.
|
||||||
|
// Let's just check
|
||||||
|
if (m_LocalGroupsConnector.GetAgentGroupMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID) != null)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
reason = "Operation not allowed outside this group's origin world";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, name = string.Empty;
|
||||||
|
if (!IsLocal(GroupID, out url, out name) && url != string.Empty)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
|
||||||
|
if (membership != null)
|
||||||
|
{
|
||||||
|
GroupsServiceHGConnector c = GetConnector(url);
|
||||||
|
if (c != null)
|
||||||
|
c.RemoveAgentFromGroup(AgentUUIForOutside(AgentID), GroupID, membership.AccessToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove from local service
|
||||||
|
m_LocalGroupsConnector.RemoveAgentFromGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.AddAgentToGroupInvite(AgentUUI(RequestingAgentID), inviteID, groupID, roleID, AgentUUI(agentID));
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
return m_LocalGroupsConnector.GetAgentToGroupInvite(AgentUUI(RequestingAgentID), inviteID); ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
m_LocalGroupsConnector.RemoveAgentToGroupInvite(AgentUUI(RequestingAgentID), inviteID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
m_LocalGroupsConnector.AddAgentToGroupRole(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
m_LocalGroupsConnector.RemoveAgentFromGroupRole(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.GetAgentGroupRoles(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
|
||||||
|
else
|
||||||
|
return new List<GroupRolesData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
m_LocalGroupsConnector.SetAgentActiveGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_LocalGroupsConnector.GetAgentActiveMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
m_LocalGroupsConnector.SetAgentActiveGroupRole(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
|
||||||
|
{
|
||||||
|
m_LocalGroupsConnector.UpdateMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, AcceptNotices, ListInProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(GroupID, out url, out gname))
|
||||||
|
return m_LocalGroupsConnector.GetAgentGroupMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_LocalGroupsConnector.GetAgentGroupMemberships(AgentUUI(RequestingAgentID), AgentUUI(AgentID));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
|
||||||
|
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
|
||||||
|
{
|
||||||
|
string url = string.Empty, gname = string.Empty;
|
||||||
|
|
||||||
|
if (IsLocal(groupID, out url, out gname))
|
||||||
|
{
|
||||||
|
if (m_LocalGroupsConnector.AddGroupNotice(AgentUUI(RequestingAgentID), groupID, noticeID, fromName, subject, message,
|
||||||
|
hasAttachment, attType, attName, attItemID, AgentUUI(attOwnerID)))
|
||||||
|
{
|
||||||
|
// then send the notice to every grid for which there are members in this group
|
||||||
|
List<GroupMembersData> members = m_LocalGroupsConnector.GetGroupMembers(AgentUUI(RequestingAgentID), groupID);
|
||||||
|
List<string> urls = new List<string>();
|
||||||
|
foreach (GroupMembersData m in members)
|
||||||
|
{
|
||||||
|
UUID userID = UUID.Zero;
|
||||||
|
if (!m_UserManagement.IsLocalGridUser(m.AgentID))
|
||||||
|
{
|
||||||
|
string gURL = m_UserManagement.GetUserServerURL(m.AgentID, "GroupsServerURI");
|
||||||
|
if (!urls.Contains(gURL))
|
||||||
|
urls.Add(gURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// so we have the list of urls to send the notice to
|
||||||
|
// this may take a long time...
|
||||||
|
Util.FireAndForget(delegate
|
||||||
|
{
|
||||||
|
foreach (string u in urls)
|
||||||
|
{
|
||||||
|
GroupsServiceHGConnector c = GetConnector(u);
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
c.AddNotice(AgentUUIForOutside(RequestingAgentID), groupID, noticeID, fromName, subject, message,
|
||||||
|
hasAttachment, attType, attName, attItemID, AgentUUIForOutside(attOwnerID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = m_LocalGroupsConnector.GetGroupNotice(AgentUUI(RequestingAgentID), noticeID);
|
||||||
|
|
||||||
|
if (notice != null && notice.noticeData.HasAttachment && notice.noticeData.AttachmentOwnerID != null)
|
||||||
|
ImportForeigner(notice.noticeData.AttachmentOwnerID);
|
||||||
|
|
||||||
|
return notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_LocalGroupsConnector.GetGroupNotices(AgentUUI(RequestingAgentID), GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetAgentGroupChatSessions(string agentID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region hypergrid groups
|
||||||
|
|
||||||
|
private string AgentUUI(string AgentIDStr)
|
||||||
|
{
|
||||||
|
UUID AgentID = UUID.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AgentID = new UUID(AgentIDStr);
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
return AgentID.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_UserManagement.IsLocalGridUser(AgentID))
|
||||||
|
return AgentID.ToString();
|
||||||
|
|
||||||
|
AgentCircuitData agent = null;
|
||||||
|
foreach (Scene scene in m_Scenes)
|
||||||
|
{
|
||||||
|
agent = scene.AuthenticateHandler.GetAgentCircuitData(AgentID);
|
||||||
|
if (agent != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (agent == null) // oops
|
||||||
|
return AgentID.ToString();
|
||||||
|
|
||||||
|
return Util.ProduceUserUniversalIdentifier(agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string AgentUUIForOutside(string AgentIDStr)
|
||||||
|
{
|
||||||
|
UUID AgentID = UUID.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AgentID = new UUID(AgentIDStr);
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
return AgentID.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
AgentCircuitData agent = null;
|
||||||
|
foreach (Scene scene in m_Scenes)
|
||||||
|
{
|
||||||
|
agent = scene.AuthenticateHandler.GetAgentCircuitData(AgentID);
|
||||||
|
if (agent != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (agent == null) // oops
|
||||||
|
return AgentID.ToString();
|
||||||
|
|
||||||
|
return Util.ProduceUserUniversalIdentifier(agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UUID ImportForeigner(string uID)
|
||||||
|
{
|
||||||
|
UUID userID = UUID.Zero;
|
||||||
|
string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
|
||||||
|
if (Util.ParseUniversalUserIdentifier(uID, out userID, out url, out first, out last, out tmp))
|
||||||
|
m_UserManagement.AddUser(userID, first, last, url);
|
||||||
|
|
||||||
|
return userID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsLocal(UUID groupID, out string serviceLocation, out string name)
|
||||||
|
{
|
||||||
|
serviceLocation = string.Empty;
|
||||||
|
name = string.Empty;
|
||||||
|
ExtendedGroupRecord group = m_LocalGroupsConnector.GetGroupRecord(UUID.Zero.ToString(), groupID, string.Empty);
|
||||||
|
if (group == null)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: IsLocal? group {0} not found -- no.", groupID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceLocation = group.ServiceLocation;
|
||||||
|
name = group.GroupName;
|
||||||
|
bool isLocal = (group.ServiceLocation == string.Empty);
|
||||||
|
//m_log.DebugFormat("[XXX]: IsLocal? {0}", isLocal);
|
||||||
|
return isLocal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GroupsServiceHGConnector GetConnector(string url)
|
||||||
|
{
|
||||||
|
lock (m_NetworkConnectors)
|
||||||
|
{
|
||||||
|
if (m_NetworkConnectors.ContainsKey(url))
|
||||||
|
return m_NetworkConnectors[url];
|
||||||
|
|
||||||
|
GroupsServiceHGConnector c = new GroupsServiceHGConnector(url);
|
||||||
|
m_NetworkConnectors[url] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_NetworkConnectors[url];
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,443 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Server.Handlers.Base;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class HGGroupsServiceRobustConnector : ServiceConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private HGGroupsService m_GroupsService;
|
||||||
|
private string m_HomeURI = string.Empty;
|
||||||
|
private string m_ConfigName = "Groups";
|
||||||
|
|
||||||
|
// Called by Robust shell
|
||||||
|
public HGGroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||||
|
this(config, server, configName, null, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by the sim-bound module
|
||||||
|
public HGGroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName, IOfflineIMService im, IUserAccountService users) :
|
||||||
|
base(config, server, configName)
|
||||||
|
{
|
||||||
|
if (configName != String.Empty)
|
||||||
|
m_ConfigName = configName;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName);
|
||||||
|
|
||||||
|
string homeURI = Util.GetConfigVarWithDefaultSection(config, "HomeURI", m_ConfigName); //cnf.GetString("HomeURI", string.Empty);
|
||||||
|
if (homeURI == string.Empty)
|
||||||
|
throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI [Startup] or in section {0}", m_ConfigName));
|
||||||
|
|
||||||
|
IConfig cnf = config.Configs[m_ConfigName];
|
||||||
|
if (cnf == null)
|
||||||
|
throw new Exception(String.Format("[Groups.RobustHGConnector]: {0} section does not exist", m_ConfigName));
|
||||||
|
|
||||||
|
if (im == null)
|
||||||
|
{
|
||||||
|
string imDll = cnf.GetString("OfflineIMService", string.Empty);
|
||||||
|
if (imDll == string.Empty)
|
||||||
|
throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide OfflineIMService in section {0}", m_ConfigName));
|
||||||
|
|
||||||
|
Object[] args = new Object[] { config };
|
||||||
|
im = ServerUtils.LoadPlugin<IOfflineIMService>(imDll, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (users == null)
|
||||||
|
{
|
||||||
|
string usersDll = cnf.GetString("UserAccountService", string.Empty);
|
||||||
|
if (usersDll == string.Empty)
|
||||||
|
throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide UserAccountService in section {0}", m_ConfigName));
|
||||||
|
|
||||||
|
Object[] args = new Object[] { config };
|
||||||
|
users = ServerUtils.LoadPlugin<IUserAccountService>(usersDll, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_GroupsService = new HGGroupsService(config, im, users, homeURI);
|
||||||
|
|
||||||
|
server.AddStreamHandler(new HGGroupsServicePostHandler(m_GroupsService));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HGGroupsServicePostHandler : BaseStreamHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private HGGroupsService m_GroupsService;
|
||||||
|
|
||||||
|
public HGGroupsServicePostHandler(HGGroupsService service) :
|
||||||
|
base("POST", "/hg-groups")
|
||||||
|
{
|
||||||
|
m_GroupsService = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte[] Handle(string path, Stream requestData,
|
||||||
|
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
|
{
|
||||||
|
StreamReader sr = new StreamReader(requestData);
|
||||||
|
string body = sr.ReadToEnd();
|
||||||
|
sr.Close();
|
||||||
|
body = body.Trim();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: query String: {0}", body);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, object> request =
|
||||||
|
ServerUtils.ParseQueryString(body);
|
||||||
|
|
||||||
|
if (!request.ContainsKey("METHOD"))
|
||||||
|
return FailureResult();
|
||||||
|
|
||||||
|
string method = request["METHOD"].ToString();
|
||||||
|
request.Remove("METHOD");
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups.RobustHGConnector]: {0}", method);
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case "POSTGROUP":
|
||||||
|
return HandleAddGroupProxy(request);
|
||||||
|
case "REMOVEAGENTFROMGROUP":
|
||||||
|
return HandleRemoveAgentFromGroup(request);
|
||||||
|
case "GETGROUP":
|
||||||
|
return HandleGetGroup(request);
|
||||||
|
case "ADDNOTICE":
|
||||||
|
return HandleAddNotice(request);
|
||||||
|
case "VERIFYNOTICE":
|
||||||
|
return HandleVerifyNotice(request);
|
||||||
|
case "GETGROUPMEMBERS":
|
||||||
|
return HandleGetGroupMembers(request);
|
||||||
|
case "GETGROUPROLES":
|
||||||
|
return HandleGetGroupRoles(request);
|
||||||
|
case "GETROLEMEMBERS":
|
||||||
|
return HandleGetRoleMembers(request);
|
||||||
|
|
||||||
|
}
|
||||||
|
m_log.DebugFormat("[Groups.RobustHGConnector]: unknown method request: {0}", method);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.RobustHGConnector]: Exception {0}", e.StackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FailureResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleAddGroupProxy(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID")
|
||||||
|
|| !request.ContainsKey("AgentID")
|
||||||
|
|| !request.ContainsKey("AccessToken") || !request.ContainsKey("Location"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string RequestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string agentID = request["AgentID"].ToString();
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string accessToken = request["AccessToken"].ToString();
|
||||||
|
string location = request["Location"].ToString();
|
||||||
|
string name = string.Empty;
|
||||||
|
if (request.ContainsKey("Name"))
|
||||||
|
name = request["Name"].ToString();
|
||||||
|
|
||||||
|
string reason = string.Empty;
|
||||||
|
bool success = m_GroupsService.CreateGroupProxy(RequestingAgentID, agentID, accessToken, groupID, location, name, out reason);
|
||||||
|
result["REASON"] = reason;
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleRemoveAgentFromGroup(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("AccessToken") || !request.ContainsKey("AgentID") ||
|
||||||
|
!request.ContainsKey("GroupID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string agentID = request["AgentID"].ToString();
|
||||||
|
string token = request["AccessToken"].ToString();
|
||||||
|
string reason = string.Empty;
|
||||||
|
|
||||||
|
m_GroupsService.RemoveAgentFromGroup(agentID, agentID, groupID, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
result["RESULT"] = "true";
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetGroup(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AccessToken"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string RequestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string token = request["AccessToken"].ToString();
|
||||||
|
|
||||||
|
UUID groupID = UUID.Zero;
|
||||||
|
string groupName = string.Empty;
|
||||||
|
|
||||||
|
if (request.ContainsKey("GroupID"))
|
||||||
|
groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
if (request.ContainsKey("Name"))
|
||||||
|
groupName = request["Name"].ToString();
|
||||||
|
|
||||||
|
ExtendedGroupRecord grec = m_GroupsService.GetGroupRecord(RequestingAgentID, groupID, groupName, token);
|
||||||
|
if (grec == null)
|
||||||
|
NullResult(result, "Group not found");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetGroupMembers(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AccessToken"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string token = request["AccessToken"].ToString();
|
||||||
|
|
||||||
|
List<ExtendedGroupMembersData> members = m_GroupsService.GetGroupMembers(requestingAgentID, groupID, token);
|
||||||
|
if (members == null || (members != null && members.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (ExtendedGroupMembersData m in members)
|
||||||
|
{
|
||||||
|
dict["m-" + i++] = GroupsDataUtils.GroupMembersData(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetGroupRoles(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AccessToken"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string token = request["AccessToken"].ToString();
|
||||||
|
|
||||||
|
List<GroupRolesData> roles = m_GroupsService.GetGroupRoles(requestingAgentID, groupID, token);
|
||||||
|
if (roles == null || (roles != null && roles.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (GroupRolesData r in roles)
|
||||||
|
dict["r-" + i++] = GroupsDataUtils.GroupRolesData(r);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetRoleMembers(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AccessToken"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string token = request["AccessToken"].ToString();
|
||||||
|
|
||||||
|
List<ExtendedGroupRoleMembersData> rmembers = m_GroupsService.GetGroupRoleMembers(requestingAgentID, groupID, token);
|
||||||
|
if (rmembers == null || (rmembers != null && rmembers.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (ExtendedGroupRoleMembersData rm in rmembers)
|
||||||
|
dict["rm-" + i++] = GroupsDataUtils.GroupRoleMembersData(rm);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleAddNotice(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("NoticeID") ||
|
||||||
|
!request.ContainsKey("FromName") || !request.ContainsKey("Subject") || !request.ContainsKey("Message") ||
|
||||||
|
!request.ContainsKey("HasAttachment"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
bool hasAtt = bool.Parse(request["HasAttachment"].ToString());
|
||||||
|
byte attType = 0;
|
||||||
|
string attName = string.Empty;
|
||||||
|
string attOwner = string.Empty;
|
||||||
|
UUID attItem = UUID.Zero;
|
||||||
|
if (request.ContainsKey("AttachmentType"))
|
||||||
|
attType = byte.Parse(request["AttachmentType"].ToString());
|
||||||
|
if (request.ContainsKey("AttachmentName"))
|
||||||
|
attName = request["AttachmentType"].ToString();
|
||||||
|
if (request.ContainsKey("AttachmentItemID"))
|
||||||
|
attItem = new UUID(request["AttachmentItemID"].ToString());
|
||||||
|
if (request.ContainsKey("AttachmentOwnerID"))
|
||||||
|
attOwner = request["AttachmentOwnerID"].ToString();
|
||||||
|
|
||||||
|
bool success = m_GroupsService.AddNotice(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
|
||||||
|
new UUID(request["NoticeID"].ToString()), request["FromName"].ToString(), request["Subject"].ToString(),
|
||||||
|
request["Message"].ToString(), hasAtt, attType, attName, attItem, attOwner);
|
||||||
|
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleVerifyNotice(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("NoticeID") || !request.ContainsKey("GroupID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID noticeID = new UUID(request["NoticeID"].ToString());
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
|
||||||
|
bool success = m_GroupsService.VerifyNotice(noticeID, groupID);
|
||||||
|
//m_log.DebugFormat("[XXX]: VerifyNotice returned {0}", success);
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#region Helpers
|
||||||
|
|
||||||
|
private void NullResult(Dictionary<string, object> result, string reason)
|
||||||
|
{
|
||||||
|
result["RESULT"] = "NULL";
|
||||||
|
result["REASON"] = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] FailureResult()
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
NullResult(result, "Unknown method");
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public interface IGroupsServicesConnector
|
||||||
|
{
|
||||||
|
UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee,
|
||||||
|
bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason);
|
||||||
|
bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
|
||||||
|
bool openEnrollment, bool allowPublish, bool maturePublish, out string reason);
|
||||||
|
ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName);
|
||||||
|
List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search);
|
||||||
|
List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID);
|
||||||
|
|
||||||
|
bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason);
|
||||||
|
bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers);
|
||||||
|
void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID);
|
||||||
|
List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID);
|
||||||
|
List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID);
|
||||||
|
|
||||||
|
bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason);
|
||||||
|
void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID);
|
||||||
|
|
||||||
|
bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID);
|
||||||
|
GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID);
|
||||||
|
void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID);
|
||||||
|
|
||||||
|
void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID);
|
||||||
|
void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID);
|
||||||
|
List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID);
|
||||||
|
|
||||||
|
void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID);
|
||||||
|
ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID);
|
||||||
|
|
||||||
|
void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID);
|
||||||
|
void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get information about a specific group to which the user belongs.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RequestingAgentID">The agent requesting the information.</param>
|
||||||
|
/// <param name="AgentID">The agent requested.</param>
|
||||||
|
/// <param name="GroupID">The group requested.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the user is a member of the group then the data structure is returned. If not, then null is returned.
|
||||||
|
/// </returns>
|
||||||
|
ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get information about the groups to which a user belongs.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="RequestingAgentID">The agent requesting the information.</param>
|
||||||
|
/// <param name="AgentID">The agent requested.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Information about the groups to which the user belongs. If the user belongs to no groups then an empty
|
||||||
|
/// list is returned.
|
||||||
|
/// </returns>
|
||||||
|
List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID);
|
||||||
|
|
||||||
|
bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
|
||||||
|
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID);
|
||||||
|
GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID);
|
||||||
|
List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID);
|
||||||
|
|
||||||
|
void ResetAgentGroupChatSessions(string agentID);
|
||||||
|
bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID);
|
||||||
|
bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID);
|
||||||
|
void AgentDroppedFromGroupChatSession(string agentID, UUID groupID);
|
||||||
|
void AgentInvitedToGroupChatSession(string agentID, UUID groupID);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GroupInviteInfo
|
||||||
|
{
|
||||||
|
public UUID GroupID = UUID.Zero;
|
||||||
|
public UUID RoleID = UUID.Zero;
|
||||||
|
public string AgentID = string.Empty;
|
||||||
|
public UUID InviteID = UUID.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GroupNoticeInfo
|
||||||
|
{
|
||||||
|
public ExtendedGroupNoticeData noticeData = new ExtendedGroupNoticeData();
|
||||||
|
public UUID GroupID = UUID.Zero;
|
||||||
|
public string Message = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,347 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using Mono.Addins;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsServiceLocalConnectorModule")]
|
||||||
|
public class GroupsServiceLocalConnectorModule : ISharedRegionModule, IGroupsServicesConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private bool m_Enabled = false;
|
||||||
|
private GroupsService m_GroupsService;
|
||||||
|
private IUserManagement m_UserManagement;
|
||||||
|
private List<Scene> m_Scenes;
|
||||||
|
private ForeignImporter m_ForeignImporter;
|
||||||
|
|
||||||
|
#region constructors
|
||||||
|
public GroupsServiceLocalConnectorModule()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupsServiceLocalConnectorModule(IConfigSource config, IUserManagement uman)
|
||||||
|
{
|
||||||
|
Init(config);
|
||||||
|
m_UserManagement = uman;
|
||||||
|
m_ForeignImporter = new ForeignImporter(uman);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void Init(IConfigSource config)
|
||||||
|
{
|
||||||
|
m_GroupsService = new GroupsService(config);
|
||||||
|
m_Scenes = new List<Scene>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ISharedRegionModule
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig groupsConfig = config.Configs["Groups"];
|
||||||
|
if (groupsConfig == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((groupsConfig.GetBoolean("Enabled", false) == false)
|
||||||
|
|| (groupsConfig.GetString("ServicesConnectorModule", string.Empty) != Name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Init(config);
|
||||||
|
m_Enabled = true;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups]: Initializing {0}", this.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Groups Local Service Connector"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
|
||||||
|
scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Add(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Remove(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_UserManagement == null)
|
||||||
|
{
|
||||||
|
m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
|
||||||
|
m_ForeignImporter = new ForeignImporter(m_UserManagement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IGroupsServicesConnector
|
||||||
|
|
||||||
|
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
|
||||||
|
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups]: Creating group {0}", name);
|
||||||
|
reason = string.Empty;
|
||||||
|
return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID,
|
||||||
|
membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
|
||||||
|
bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
m_GroupsService.UpdateGroup(RequestingAgentID, groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName)
|
||||||
|
{
|
||||||
|
if (GroupID != UUID.Zero)
|
||||||
|
return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID);
|
||||||
|
else if (GroupName != null)
|
||||||
|
return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupName);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
|
||||||
|
{
|
||||||
|
return m_GroupsService.FindGroups(RequestingAgentID, search);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> _members = m_GroupsService.GetGroupMembers(RequestingAgentID, GroupID);
|
||||||
|
if (_members != null && _members.Count > 0)
|
||||||
|
{
|
||||||
|
List<GroupMembersData> members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<GroupMembersData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, out reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
|
||||||
|
{
|
||||||
|
return m_GroupsService.UpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveGroupRole(RequestingAgentID, groupID, roleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupRoles(RequestingAgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> _rm = m_GroupsService.GetGroupRoleMembers(RequestingAgentID, GroupID);
|
||||||
|
if (_rm != null && _rm.Count > 0)
|
||||||
|
{
|
||||||
|
List<GroupRoleMembersData> rm = _rm.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData));
|
||||||
|
return rm;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new List<GroupRoleMembersData>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, token, out reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddAgentToGroupInvite(RequestingAgentID, inviteID, groupID, roleID, agentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentToGroupInvite(RequestingAgentID, inviteID); ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveAgentToGroupInvite(RequestingAgentID, inviteID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
m_GroupsService.AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveAgentFromGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentGroupRoles(RequestingAgentID, AgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
m_GroupsService.SetAgentActiveGroup(RequestingAgentID, AgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentActiveMembership(RequestingAgentID, AgentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
m_GroupsService.SetAgentActiveGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
|
||||||
|
{
|
||||||
|
m_GroupsService.UpdateMembership(RequestingAgentID, AgentID, GroupID, AcceptNotices, ListInProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentGroupMembership(RequestingAgentID, AgentID, GroupID); ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentGroupMemberships(RequestingAgentID, AgentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
|
||||||
|
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message,
|
||||||
|
hasAttachment, attType, attName, attItemID, attOwnerID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = m_GroupsService.GetGroupNotice(RequestingAgentID, noticeID);
|
||||||
|
|
||||||
|
//if (notice != null && notice.noticeData.HasAttachment && notice.noticeData.AttachmentOwnerID != null)
|
||||||
|
//{
|
||||||
|
// UUID userID = UUID.Zero;
|
||||||
|
// string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
|
||||||
|
// Util.ParseUniversalUserIdentifier(notice.noticeData.AttachmentOwnerID, out userID, out url, out first, out last, out tmp);
|
||||||
|
// if (url != string.Empty)
|
||||||
|
// m_UserManagement.AddUser(userID, first, last, url);
|
||||||
|
//}
|
||||||
|
|
||||||
|
return notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupNotices(RequestingAgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetAgentGroupChatSessions(string agentID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("OpenSim.Addons.Groups")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("http://opensimulator.org")]
|
||||||
|
[assembly: AssemblyProduct("OpenSim.Addons.Groups")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("313d4865-d179-4735-9b5a-fe74885878b2")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
|
|
||||||
|
[assembly: Addin("OpenSim.Groups", "0.1")]
|
||||||
|
[assembly: AddinDependency("OpenSim", "0.5")]
|
|
@ -0,0 +1,642 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class GroupsServiceRemoteConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private string m_ServerURI;
|
||||||
|
private object m_Lock = new object();
|
||||||
|
|
||||||
|
public GroupsServiceRemoteConnector(string url)
|
||||||
|
{
|
||||||
|
m_ServerURI = url;
|
||||||
|
if (!m_ServerURI.EndsWith("/"))
|
||||||
|
m_ServerURI += "/";
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}", m_ServerURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
|
||||||
|
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
ExtendedGroupRecord rec = new ExtendedGroupRecord();
|
||||||
|
rec.AllowPublish = allowPublish;
|
||||||
|
rec.Charter = charter;
|
||||||
|
rec.FounderID = founderID;
|
||||||
|
rec.GroupName = name;
|
||||||
|
rec.GroupPicture = insigniaID;
|
||||||
|
rec.MaturePublish = maturePublish;
|
||||||
|
rec.MembershipFee = membershipFee;
|
||||||
|
rec.OpenEnrollment = openEnrollment;
|
||||||
|
rec.ShowInList = showInList;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = GroupsDataUtils.GroupRecord(rec);
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ADD";
|
||||||
|
Dictionary<string, object> ret = MakeRequest("PUTGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
{
|
||||||
|
reason = ret["REASON"].ToString();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish)
|
||||||
|
{
|
||||||
|
ExtendedGroupRecord rec = new ExtendedGroupRecord();
|
||||||
|
rec.AllowPublish = allowPublish;
|
||||||
|
rec.Charter = charter;
|
||||||
|
rec.GroupPicture = insigniaID;
|
||||||
|
rec.MaturePublish = maturePublish;
|
||||||
|
rec.GroupID = groupID;
|
||||||
|
rec.MembershipFee = membershipFee;
|
||||||
|
rec.OpenEnrollment = openEnrollment;
|
||||||
|
rec.ShowInList = showInList;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = GroupsDataUtils.GroupRecord(rec);
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "UPDATE";
|
||||||
|
Dictionary<string, object> ret = MakeRequest("PUTGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName)
|
||||||
|
{
|
||||||
|
if (GroupID == UUID.Zero && (GroupName == null || (GroupName != null && GroupName == string.Empty)))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
if (GroupID != UUID.Zero)
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
if (GroupName != null && GroupName != string.Empty)
|
||||||
|
sendData["Name"] = GroupsDataUtils.Sanitize(GroupName);
|
||||||
|
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupMembershipData AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string,object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RoleID"] = RoleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["AccessToken"] = token;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("ADDAGENTTOGROUP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
{
|
||||||
|
reason = ret["REASON"].ToString();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
MakeRequest("REMOVEAGENTFROMGROUP", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetMembership(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
if (GroupID != UUID.Zero)
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETMEMBERSHIP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembershipData> GetMemberships(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
List<GroupMembershipData> memberships = new List<GroupMembershipData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID;
|
||||||
|
sendData["ALL"] = "true";
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETMEMBERSHIP", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return memberships;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return memberships;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return memberships;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GroupMembershipData m = GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)v);
|
||||||
|
memberships.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return memberships;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> members = new List<ExtendedGroupMembersData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUPMEMBERS", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return members;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return members;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return members;
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary<string, object>)v);
|
||||||
|
members.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["RoleID"] = roleID.ToString();
|
||||||
|
sendData["Name"] = GroupsDataUtils.Sanitize(name);
|
||||||
|
sendData["Description"] = GroupsDataUtils.Sanitize(description);
|
||||||
|
sendData["Title"] = GroupsDataUtils.Sanitize(title);
|
||||||
|
sendData["Powers"] = powers.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ADD";
|
||||||
|
Dictionary<string, object> ret = MakeRequest("PUTROLE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
{
|
||||||
|
reason = ret["REASON"].ToString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["RoleID"] = roleID.ToString();
|
||||||
|
sendData["Name"] = GroupsDataUtils.Sanitize(name);
|
||||||
|
sendData["Description"] = GroupsDataUtils.Sanitize(description);
|
||||||
|
sendData["Title"] = GroupsDataUtils.Sanitize(title);
|
||||||
|
sendData["Powers"] = powers.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "UPDATE";
|
||||||
|
Dictionary<string, object> ret = MakeRequest("PUTROLE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["RoleID"] = roleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
MakeRequest("REMOVEROLE", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<GroupRolesData> roles = new List<GroupRolesData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETGROUPROLES", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return roles;
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
|
||||||
|
roles.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> rmembers = new List<ExtendedGroupRoleMembersData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETROLEMEMBERS", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return rmembers;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return rmembers;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return rmembers;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupRoleMembersData m = GroupsDataUtils.GroupRoleMembersData((Dictionary<string, object>)v);
|
||||||
|
rmembers.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rmembers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RoleID"] = RoleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ADD";
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("AGENTROLE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RoleID"] = RoleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "DELETE";
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("AGENTROLE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<GroupRolesData> roles = new List<GroupRolesData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETAGENTROLES", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return roles;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
|
||||||
|
roles.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupMembershipData SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "GROUP";
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("SETACTIVE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RoleID"] = RoleID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ROLE";
|
||||||
|
|
||||||
|
MakeRequest("SETACTIVE", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["AgentID"] = AgentID.ToString();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["AcceptNotices"] = AcceptNotices.ToString();
|
||||||
|
sendData["ListInProfile"] = ListInProfile.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
MakeRequest("UPDATEMEMBERSHIP", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["InviteID"] = inviteID.ToString();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["RoleID"] = roleID.ToString();
|
||||||
|
sendData["AgentID"] = agentID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "ADD";
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("INVITE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true") // it may return "NULL"
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["InviteID"] = inviteID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "GET";
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("INVITE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupInviteInfo((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["InviteID"] = inviteID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
sendData["OP"] = "DELETE";
|
||||||
|
|
||||||
|
MakeRequest("INVITE", sendData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
|
||||||
|
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = groupID.ToString();
|
||||||
|
sendData["NoticeID"] = noticeID.ToString();
|
||||||
|
sendData["FromName"] = GroupsDataUtils.Sanitize(fromName);
|
||||||
|
sendData["Subject"] = GroupsDataUtils.Sanitize(subject);
|
||||||
|
sendData["Message"] = GroupsDataUtils.Sanitize(message);
|
||||||
|
sendData["HasAttachment"] = hasAttachment.ToString();
|
||||||
|
if (hasAttachment)
|
||||||
|
{
|
||||||
|
sendData["AttachmentType"] = attType.ToString();
|
||||||
|
sendData["AttachmentName"] = attName.ToString();
|
||||||
|
sendData["AttachmentItemID"] = attItemID.ToString();
|
||||||
|
sendData["AttachmentOwnerID"] = attOwnerID;
|
||||||
|
}
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("ADDNOTICE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString().ToLower() != "true")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["NoticeID"] = noticeID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETNOTICES", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return GroupsDataUtils.GroupNoticeInfo((Dictionary<string, object>)ret["RESULT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupNoticeData> notices = new List<ExtendedGroupNoticeData>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["GroupID"] = GroupID.ToString();
|
||||||
|
sendData["RequestingAgentID"] = RequestingAgentID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GETNOTICES", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return notices;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return notices;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return notices;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
ExtendedGroupNoticeData m = GroupsDataUtils.GroupNoticeData((Dictionary<string, object>)v);
|
||||||
|
notices.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return notices;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Make Request
|
||||||
|
|
||||||
|
private Dictionary<string, object> MakeRequest(string method, Dictionary<string, object> sendData)
|
||||||
|
{
|
||||||
|
sendData["METHOD"] = method;
|
||||||
|
|
||||||
|
string reply = string.Empty;
|
||||||
|
lock (m_Lock)
|
||||||
|
reply = SynchronousRestFormsRequester.MakeRequest("POST",
|
||||||
|
m_ServerURI + "groups",
|
||||||
|
ServerUtils.BuildQueryString(sendData));
|
||||||
|
|
||||||
|
if (reply == string.Empty)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
|
||||||
|
reply);
|
||||||
|
|
||||||
|
return replyData;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,437 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using Mono.Addins;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsServiceRemoteConnectorModule")]
|
||||||
|
public class GroupsServiceRemoteConnectorModule : ISharedRegionModule, IGroupsServicesConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private bool m_Enabled = false;
|
||||||
|
private GroupsServiceRemoteConnector m_GroupsService;
|
||||||
|
private IUserManagement m_UserManagement;
|
||||||
|
private List<Scene> m_Scenes;
|
||||||
|
|
||||||
|
private RemoteConnectorCacheWrapper m_CacheWrapper;
|
||||||
|
|
||||||
|
#region constructors
|
||||||
|
public GroupsServiceRemoteConnectorModule()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupsServiceRemoteConnectorModule(IConfigSource config, IUserManagement uman)
|
||||||
|
{
|
||||||
|
Init(config);
|
||||||
|
m_UserManagement = uman;
|
||||||
|
m_CacheWrapper = new RemoteConnectorCacheWrapper(m_UserManagement);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void Init(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig groupsConfig = config.Configs["Groups"];
|
||||||
|
string url = groupsConfig.GetString("GroupsServerURI", string.Empty);
|
||||||
|
if (url == string.Empty)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[Groups.RemoteConnector]: Groups server URL not provided. Groups will not work.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_GroupsService = new GroupsServiceRemoteConnector(url);
|
||||||
|
m_Scenes = new List<Scene>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ISharedRegionModule
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig groupsConfig = config.Configs["Groups"];
|
||||||
|
if (groupsConfig == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((groupsConfig.GetBoolean("Enabled", false) == false)
|
||||||
|
|| (groupsConfig.GetString("ServicesConnectorModule", string.Empty) != Name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Init(config);
|
||||||
|
|
||||||
|
m_Enabled = true;
|
||||||
|
m_log.DebugFormat("[Groups.RemoteConnector]: Initializing {0}", this.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Groups Remote Service Connector"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups.RemoteConnector]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
|
||||||
|
scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Add(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
|
||||||
|
m_Scenes.Remove(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_UserManagement == null)
|
||||||
|
{
|
||||||
|
m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
|
||||||
|
m_CacheWrapper = new RemoteConnectorCacheWrapper(m_UserManagement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IGroupsServicesConnector
|
||||||
|
|
||||||
|
public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
|
||||||
|
bool allowPublish, bool maturePublish, UUID founderID, out string reason)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name);
|
||||||
|
string r = string.Empty;
|
||||||
|
|
||||||
|
UUID groupID = m_CacheWrapper.CreateGroup(RequestingAgentID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID,
|
||||||
|
membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out r);
|
||||||
|
});
|
||||||
|
|
||||||
|
reason = r;
|
||||||
|
return groupID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
|
||||||
|
bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
|
||||||
|
{
|
||||||
|
string r = string.Empty;
|
||||||
|
|
||||||
|
bool success = m_CacheWrapper.UpdateGroup(groupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.UpdateGroup(RequestingAgentID, groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish);
|
||||||
|
});
|
||||||
|
|
||||||
|
reason = r;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName)
|
||||||
|
{
|
||||||
|
if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return m_CacheWrapper.GetGroupRecord(RequestingAgentID,GroupID,GroupName, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
|
||||||
|
{
|
||||||
|
// TODO!
|
||||||
|
return new List<DirGroupsReplyData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
|
||||||
|
{
|
||||||
|
string agentFullID = AgentID;
|
||||||
|
m_log.DebugFormat("[Groups.RemoteConnector]: Add agent {0} to group {1}", agentFullID, GroupID);
|
||||||
|
string r = string.Empty;
|
||||||
|
|
||||||
|
bool success = m_CacheWrapper.AddAgentToGroup(RequestingAgentID, AgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddAgentToGroup(RequestingAgentID, agentFullID, GroupID, RoleID, token, out r);
|
||||||
|
});
|
||||||
|
|
||||||
|
reason = r;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.SetAgentActiveGroup(AgentID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.SetAgentActiveGroup(RequestingAgentID, AgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetAgentActiveMembership(AgentID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetMembership(RequestingAgentID, AgentID, UUID.Zero);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetAgentGroupMembership(AgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetMembership(RequestingAgentID, AgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetAgentGroupMemberships(AgentID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetMemberships(RequestingAgentID, AgentID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupMembers(RequestingAgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupMembers(RequestingAgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
|
||||||
|
{
|
||||||
|
string r = string.Empty;
|
||||||
|
bool success = m_CacheWrapper.AddGroupRole(roleID, description, name, powers, title, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, out r);
|
||||||
|
});
|
||||||
|
|
||||||
|
reason = r;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.UpdateGroupRole(groupID, roleID, name, description, title, powers, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.UpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.RemoveGroupRole(RequestingAgentID, groupID, roleID, delegate
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveGroupRole(RequestingAgentID, groupID, roleID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupRoles(RequestingAgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupRoles(RequestingAgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupRoleMembers(RequestingAgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupRoleMembers(RequestingAgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.RemoveAgentFromGroupRole(RequestingAgentID, AgentID, GroupID, RoleID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.RemoveAgentFromGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetAgentGroupRoles(RequestingAgentID, AgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentGroupRoles(RequestingAgentID, AgentID, GroupID); ;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.SetAgentActiveGroupRole(AgentID, GroupID, delegate
|
||||||
|
{
|
||||||
|
m_GroupsService.SetAgentActiveGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
|
||||||
|
{
|
||||||
|
m_CacheWrapper.UpdateMembership(AgentID, GroupID, AcceptNotices, ListInProfile, delegate
|
||||||
|
{
|
||||||
|
m_GroupsService.UpdateMembership(RequestingAgentID, AgentID, GroupID, AcceptNotices, ListInProfile);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddAgentToGroupInvite(RequestingAgentID, inviteID, groupID, roleID, agentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetAgentToGroupInvite(RequestingAgentID, inviteID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveAgentToGroupInvite(RequestingAgentID, inviteID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
|
||||||
|
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = new GroupNoticeInfo();
|
||||||
|
notice.GroupID = groupID;
|
||||||
|
notice.Message = message;
|
||||||
|
notice.noticeData = new ExtendedGroupNoticeData();
|
||||||
|
notice.noticeData.AttachmentItemID = attItemID;
|
||||||
|
notice.noticeData.AttachmentName = attName;
|
||||||
|
notice.noticeData.AttachmentOwnerID = attOwnerID.ToString();
|
||||||
|
notice.noticeData.AttachmentType = attType;
|
||||||
|
notice.noticeData.FromName = fromName;
|
||||||
|
notice.noticeData.HasAttachment = hasAttachment;
|
||||||
|
notice.noticeData.NoticeID = noticeID;
|
||||||
|
notice.noticeData.Subject = subject;
|
||||||
|
notice.noticeData.Timestamp = (uint)Util.UnixTimeSinceEpoch();
|
||||||
|
|
||||||
|
return m_CacheWrapper.AddGroupNotice(groupID, noticeID, notice, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message,
|
||||||
|
hasAttachment, attType, attName, attItemID, attOwnerID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupNotice(noticeID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupNotice(RequestingAgentID, noticeID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
|
||||||
|
{
|
||||||
|
return m_CacheWrapper.GetGroupNotices(GroupID, delegate
|
||||||
|
{
|
||||||
|
return m_GroupsService.GetGroupNotices(RequestingAgentID, GroupID);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetAgentGroupChatSessions(string agentID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,760 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Server.Handlers.Base;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class GroupsServiceRobustConnector : ServiceConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private GroupsService m_GroupsService;
|
||||||
|
private string m_ConfigName = "Groups";
|
||||||
|
|
||||||
|
public GroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||||
|
base(config, server, configName)
|
||||||
|
{
|
||||||
|
if (configName != String.Empty)
|
||||||
|
m_ConfigName = configName;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups.RobustConnector]: Starting with config name {0}", m_ConfigName);
|
||||||
|
|
||||||
|
m_GroupsService = new GroupsService(config);
|
||||||
|
|
||||||
|
server.AddStreamHandler(new GroupsServicePostHandler(m_GroupsService));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GroupsServicePostHandler : BaseStreamHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private GroupsService m_GroupsService;
|
||||||
|
|
||||||
|
public GroupsServicePostHandler(GroupsService service) :
|
||||||
|
base("POST", "/groups")
|
||||||
|
{
|
||||||
|
m_GroupsService = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte[] Handle(string path, Stream requestData,
|
||||||
|
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
|
{
|
||||||
|
StreamReader sr = new StreamReader(requestData);
|
||||||
|
string body = sr.ReadToEnd();
|
||||||
|
sr.Close();
|
||||||
|
body = body.Trim();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: query String: {0}", body);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, object> request =
|
||||||
|
ServerUtils.ParseQueryString(body);
|
||||||
|
|
||||||
|
if (!request.ContainsKey("METHOD"))
|
||||||
|
return FailureResult();
|
||||||
|
|
||||||
|
string method = request["METHOD"].ToString();
|
||||||
|
request.Remove("METHOD");
|
||||||
|
|
||||||
|
m_log.DebugFormat("[Groups.Handler]: {0}", method);
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case "PUTGROUP":
|
||||||
|
return HandleAddOrUpdateGroup(request);
|
||||||
|
case "GETGROUP":
|
||||||
|
return HandleGetGroup(request);
|
||||||
|
case "ADDAGENTTOGROUP":
|
||||||
|
return HandleAddAgentToGroup(request);
|
||||||
|
case "REMOVEAGENTFROMGROUP":
|
||||||
|
return HandleRemoveAgentFromGroup(request);
|
||||||
|
case "GETMEMBERSHIP":
|
||||||
|
return HandleGetMembership(request);
|
||||||
|
case "GETGROUPMEMBERS":
|
||||||
|
return HandleGetGroupMembers(request);
|
||||||
|
case "PUTROLE":
|
||||||
|
return HandlePutRole(request);
|
||||||
|
case "REMOVEROLE":
|
||||||
|
return HandleRemoveRole(request);
|
||||||
|
case "GETGROUPROLES":
|
||||||
|
return HandleGetGroupRoles(request);
|
||||||
|
case "GETROLEMEMBERS":
|
||||||
|
return HandleGetRoleMembers(request);
|
||||||
|
case "AGENTROLE":
|
||||||
|
return HandleAgentRole(request);
|
||||||
|
case "GETAGENTROLES":
|
||||||
|
return HandleGetAgentRoles(request);
|
||||||
|
case "SETACTIVE":
|
||||||
|
return HandleSetActive(request);
|
||||||
|
case "UPDATEMEMBERSHIP":
|
||||||
|
return HandleUpdateMembership(request);
|
||||||
|
case "INVITE":
|
||||||
|
return HandleInvite(request);
|
||||||
|
case "ADDNOTICE":
|
||||||
|
return HandleAddNotice(request);
|
||||||
|
case "GETNOTICES":
|
||||||
|
return HandleGetNotices(request);
|
||||||
|
}
|
||||||
|
m_log.DebugFormat("[GROUPS HANDLER]: unknown method request: {0}", method);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[GROUPS HANDLER]: Exception {0}", e.StackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FailureResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleAddOrUpdateGroup(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
ExtendedGroupRecord grec = GroupsDataUtils.GroupRecord(request);
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("OP"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string RequestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string reason = string.Empty;
|
||||||
|
string op = request["OP"].ToString();
|
||||||
|
if (op == "ADD")
|
||||||
|
{
|
||||||
|
grec.GroupID = m_GroupsService.CreateGroup(RequestingAgentID, grec.GroupName, grec.Charter, grec.ShowInList, grec.GroupPicture, grec.MembershipFee,
|
||||||
|
grec.OpenEnrollment, grec.AllowPublish, grec.MaturePublish, grec.FounderID, out reason);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (op == "UPDATE")
|
||||||
|
{
|
||||||
|
m_GroupsService.UpdateGroup(RequestingAgentID, grec.GroupID, grec.Charter, grec.ShowInList, grec.GroupPicture, grec.MembershipFee,
|
||||||
|
grec.OpenEnrollment, grec.AllowPublish, grec.MaturePublish);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
grec = m_GroupsService.GetGroupRecord(RequestingAgentID, grec.GroupID);
|
||||||
|
if (grec == null)
|
||||||
|
NullResult(result, "Internal Error");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetGroup(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string RequestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
ExtendedGroupRecord grec = null;
|
||||||
|
if (request.ContainsKey("GroupID"))
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
grec = m_GroupsService.GetGroupRecord(RequestingAgentID, groupID);
|
||||||
|
}
|
||||||
|
else if (request.ContainsKey("Name"))
|
||||||
|
{
|
||||||
|
string name = request["Name"].ToString();
|
||||||
|
grec = m_GroupsService.GetGroupRecord(RequestingAgentID, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grec == null)
|
||||||
|
NullResult(result, "Group not found");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleAddAgentToGroup(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID") ||
|
||||||
|
!request.ContainsKey("GroupID") || !request.ContainsKey("RoleID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
UUID roleID = new UUID(request["RoleID"].ToString());
|
||||||
|
string agentID = request["AgentID"].ToString();
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string token = string.Empty;
|
||||||
|
string reason = string.Empty;
|
||||||
|
|
||||||
|
if (request.ContainsKey("AccessToken"))
|
||||||
|
token = request["AccessToken"].ToString();
|
||||||
|
|
||||||
|
if (!m_GroupsService.AddAgentToGroup(requestingAgentID, agentID, groupID, roleID, token, out reason))
|
||||||
|
NullResult(result, reason);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GroupMembershipData membership = m_GroupsService.GetAgentGroupMembership(requestingAgentID, agentID, groupID);
|
||||||
|
if (membership == null)
|
||||||
|
NullResult(result, "Internal error");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupMembershipData((ExtendedGroupMembershipData)membership);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleRemoveAgentFromGroup(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID") || !request.ContainsKey("GroupID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string agentID = request["AgentID"].ToString();
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
string reason = string.Empty;
|
||||||
|
|
||||||
|
m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
result["RESULT"] = "true";
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetMembership(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string agentID = request["AgentID"].ToString();
|
||||||
|
UUID groupID = UUID.Zero;
|
||||||
|
if (request.ContainsKey("GroupID"))
|
||||||
|
groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
bool all = request.ContainsKey("ALL");
|
||||||
|
|
||||||
|
if (!all)
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData membership = null;
|
||||||
|
if (groupID == UUID.Zero)
|
||||||
|
{
|
||||||
|
membership = m_GroupsService.GetAgentActiveMembership(requestingAgentID, agentID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
membership = m_GroupsService.GetAgentGroupMembership(requestingAgentID, agentID, groupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (membership == null)
|
||||||
|
NullResult(result, "No such membership");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupMembershipData(membership);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<GroupMembershipData> memberships = m_GroupsService.GetAgentGroupMemberships(requestingAgentID, agentID);
|
||||||
|
if (memberships == null || (memberships != null && memberships.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No memberships");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (GroupMembershipData m in memberships)
|
||||||
|
dict["m-" + i++] = GroupsDataUtils.GroupMembershipData((ExtendedGroupMembershipData)m);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetGroupMembers(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
|
||||||
|
List<ExtendedGroupMembersData> members = m_GroupsService.GetGroupMembers(requestingAgentID, groupID);
|
||||||
|
if (members == null || (members != null && members.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (ExtendedGroupMembersData m in members)
|
||||||
|
{
|
||||||
|
dict["m-" + i++] = GroupsDataUtils.GroupMembersData(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandlePutRole(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") ||
|
||||||
|
!request.ContainsKey("Name") || !request.ContainsKey("Descrption") || !request.ContainsKey("Title") ||
|
||||||
|
!request.ContainsKey("Powers") || !request.ContainsKey("OP"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string op = request["OP"].ToString();
|
||||||
|
string reason = string.Empty;
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
if (op == "ADD")
|
||||||
|
success = m_GroupsService.AddGroupRole(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
|
||||||
|
new UUID(request["RoleID"].ToString()), request["Name"].ToString(), request["Description"].ToString(),
|
||||||
|
request["Title"].ToString(), UInt64.Parse(request["Powers"].ToString()), out reason);
|
||||||
|
|
||||||
|
else if (op == "UPDATE")
|
||||||
|
success = m_GroupsService.UpdateGroupRole(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
|
||||||
|
new UUID(request["RoleID"].ToString()), request["Name"].ToString(), request["Description"].ToString(),
|
||||||
|
request["Title"].ToString(), UInt64.Parse(request["Powers"].ToString()));
|
||||||
|
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleRemoveRole(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveGroupRole(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
|
||||||
|
new UUID(request["RoleID"].ToString()));
|
||||||
|
result["RESULT"] = "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetGroupRoles(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
|
||||||
|
List<GroupRolesData> roles = m_GroupsService.GetGroupRoles(requestingAgentID, groupID);
|
||||||
|
if (roles == null || (roles != null && roles.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (GroupRolesData r in roles)
|
||||||
|
dict["r-" + i++] = GroupsDataUtils.GroupRolesData(r);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetRoleMembers(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
|
||||||
|
List<ExtendedGroupRoleMembersData> rmembers = m_GroupsService.GetGroupRoleMembers(requestingAgentID, groupID);
|
||||||
|
if (rmembers == null || (rmembers != null && rmembers.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (ExtendedGroupRoleMembersData rm in rmembers)
|
||||||
|
dict["rm-" + i++] = GroupsDataUtils.GroupRoleMembersData(rm);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleAgentRole(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") ||
|
||||||
|
!request.ContainsKey("AgentID") || !request.ContainsKey("OP"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string op = request["OP"].ToString();
|
||||||
|
string reason = string.Empty;
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
if (op == "ADD")
|
||||||
|
success = m_GroupsService.AddAgentToGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
|
||||||
|
new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
|
||||||
|
|
||||||
|
else if (op == "DELETE")
|
||||||
|
success = m_GroupsService.RemoveAgentFromGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
|
||||||
|
new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
|
||||||
|
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetAgentRoles(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AgentID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID groupID = new UUID(request["GroupID"].ToString());
|
||||||
|
string agentID = request["AgentID"].ToString();
|
||||||
|
string requestingAgentID = request["RequestingAgentID"].ToString();
|
||||||
|
|
||||||
|
List<GroupRolesData> roles = m_GroupsService.GetAgentGroupRoles(requestingAgentID, agentID, groupID);
|
||||||
|
if (roles == null || (roles != null && roles.Count == 0))
|
||||||
|
{
|
||||||
|
NullResult(result, "No members");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (GroupRolesData r in roles)
|
||||||
|
dict["r-" + i++] = GroupsDataUtils.GroupRolesData(r);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleSetActive(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") ||
|
||||||
|
!request.ContainsKey("AgentID") || !request.ContainsKey("OP"))
|
||||||
|
{
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string op = request["OP"].ToString();
|
||||||
|
string reason = string.Empty;
|
||||||
|
|
||||||
|
if (op == "GROUP")
|
||||||
|
{
|
||||||
|
ExtendedGroupMembershipData group = m_GroupsService.SetAgentActiveGroup(request["RequestingAgentID"].ToString(),
|
||||||
|
request["AgentID"].ToString(), new UUID(request["GroupID"].ToString()));
|
||||||
|
|
||||||
|
if (group == null)
|
||||||
|
NullResult(result, "Internal error");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupMembershipData(group);
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (op == "ROLE" && request.ContainsKey("RoleID"))
|
||||||
|
{
|
||||||
|
m_GroupsService.SetAgentActiveGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
|
||||||
|
new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
|
||||||
|
result["RESULT"] = "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleUpdateMembership(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID") || !request.ContainsKey("GroupID") ||
|
||||||
|
!request.ContainsKey("AcceptNotices") || !request.ContainsKey("ListInProfile"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_GroupsService.UpdateMembership(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), new UUID(request["GroupID"].ToString()),
|
||||||
|
bool.Parse(request["AcceptNotices"].ToString()), bool.Parse(request["ListInProfile"].ToString()));
|
||||||
|
|
||||||
|
result["RESULT"] = "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleInvite(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("InviteID"))
|
||||||
|
{
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string op = request["OP"].ToString();
|
||||||
|
string reason = string.Empty;
|
||||||
|
|
||||||
|
if (op == "ADD" && request.ContainsKey("GroupID") && request.ContainsKey("RoleID") && request.ContainsKey("AgentID"))
|
||||||
|
{
|
||||||
|
bool success = m_GroupsService.AddAgentToGroupInvite(request["RequestingAgentID"].ToString(),
|
||||||
|
new UUID(request["InviteID"].ToString()), new UUID(request["GroupID"].ToString()),
|
||||||
|
new UUID(request["RoleID"].ToString()), request["AgentID"].ToString());
|
||||||
|
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (op == "DELETE")
|
||||||
|
{
|
||||||
|
m_GroupsService.RemoveAgentToGroupInvite(request["RequestingAgentID"].ToString(), new UUID(request["InviteID"].ToString()));
|
||||||
|
result["RESULT"] = "true";
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
else if (op == "GET")
|
||||||
|
{
|
||||||
|
GroupInviteInfo invite = m_GroupsService.GetAgentToGroupInvite(request["RequestingAgentID"].ToString(),
|
||||||
|
new UUID(request["InviteID"].ToString()));
|
||||||
|
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupInviteInfo(invite);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
NullResult(result, "Bad OP in request");
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleAddNotice(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("NoticeID") ||
|
||||||
|
!request.ContainsKey("FromName") || !request.ContainsKey("Subject") || !request.ContainsKey("Message") ||
|
||||||
|
!request.ContainsKey("HasAttachment"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
bool hasAtt = bool.Parse(request["HasAttachment"].ToString());
|
||||||
|
byte attType = 0;
|
||||||
|
string attName = string.Empty;
|
||||||
|
string attOwner = string.Empty;
|
||||||
|
UUID attItem = UUID.Zero;
|
||||||
|
if (request.ContainsKey("AttachmentType"))
|
||||||
|
attType = byte.Parse(request["AttachmentType"].ToString());
|
||||||
|
if (request.ContainsKey("AttachmentName"))
|
||||||
|
attName = request["AttachmentName"].ToString();
|
||||||
|
if (request.ContainsKey("AttachmentItemID"))
|
||||||
|
attItem = new UUID(request["AttachmentItemID"].ToString());
|
||||||
|
if (request.ContainsKey("AttachmentOwnerID"))
|
||||||
|
attOwner = request["AttachmentOwnerID"].ToString();
|
||||||
|
|
||||||
|
bool success = m_GroupsService.AddGroupNotice(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
|
||||||
|
new UUID(request["NoticeID"].ToString()), request["FromName"].ToString(), request["Subject"].ToString(),
|
||||||
|
request["Message"].ToString(), hasAtt, attType, attName, attItem, attOwner);
|
||||||
|
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGetNotices(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("RequestingAgentID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
|
||||||
|
else if (request.ContainsKey("NoticeID")) // just one
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = m_GroupsService.GetGroupNotice(request["RequestingAgentID"].ToString(), new UUID(request["NoticeID"].ToString()));
|
||||||
|
|
||||||
|
if (notice == null)
|
||||||
|
NullResult(result, "NO such notice");
|
||||||
|
else
|
||||||
|
result["RESULT"] = GroupsDataUtils.GroupNoticeInfo(notice);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (request.ContainsKey("GroupID")) // all notices for group
|
||||||
|
{
|
||||||
|
List<ExtendedGroupNoticeData> notices = m_GroupsService.GetGroupNotices(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()));
|
||||||
|
|
||||||
|
if (notices == null || (notices != null && notices.Count == 0))
|
||||||
|
NullResult(result, "No notices");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (ExtendedGroupNoticeData n in notices)
|
||||||
|
dict["n-" + i++] = GroupsDataUtils.GroupNoticeData(n);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
NullResult(result, "Bad OP in request");
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region Helpers
|
||||||
|
|
||||||
|
private void NullResult(Dictionary<string, object> result, string reason)
|
||||||
|
{
|
||||||
|
result["RESULT"] = "NULL";
|
||||||
|
result["REASON"] = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] FailureResult()
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
NullResult(result, "Unknown method");
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,824 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public delegate ExtendedGroupRecord GroupRecordDelegate();
|
||||||
|
public delegate GroupMembershipData GroupMembershipDelegate();
|
||||||
|
public delegate List<GroupMembershipData> GroupMembershipListDelegate();
|
||||||
|
public delegate List<ExtendedGroupMembersData> GroupMembersListDelegate();
|
||||||
|
public delegate List<GroupRolesData> GroupRolesListDelegate();
|
||||||
|
public delegate List<ExtendedGroupRoleMembersData> RoleMembersListDelegate();
|
||||||
|
public delegate GroupNoticeInfo NoticeDelegate();
|
||||||
|
public delegate List<ExtendedGroupNoticeData> NoticeListDelegate();
|
||||||
|
public delegate void VoidDelegate();
|
||||||
|
public delegate bool BooleanDelegate();
|
||||||
|
|
||||||
|
public class RemoteConnectorCacheWrapper
|
||||||
|
{
|
||||||
|
private ForeignImporter m_ForeignImporter;
|
||||||
|
|
||||||
|
private Dictionary<string, bool> m_ActiveRequests = new Dictionary<string, bool>();
|
||||||
|
private const int GROUPS_CACHE_TIMEOUT = 5 * 60; // 5 minutes
|
||||||
|
|
||||||
|
// This all important cache cahces objects of different types:
|
||||||
|
// group-<GroupID> or group-<Name> => ExtendedGroupRecord
|
||||||
|
// active-<AgentID> => GroupMembershipData
|
||||||
|
// membership-<AgentID>-<GroupID> => GroupMembershipData
|
||||||
|
// memberships-<AgentID> => List<GroupMembershipData>
|
||||||
|
// members-<RequestingAgentID>-<GroupID> => List<ExtendedGroupMembersData>
|
||||||
|
// role-<RoleID> => GroupRolesData
|
||||||
|
// roles-<GroupID> => List<GroupRolesData> ; all roles in the group
|
||||||
|
// roles-<GroupID>-<AgentID> => List<GroupRolesData> ; roles that the agent has
|
||||||
|
// rolemembers-<RequestingAgentID>-<GroupID> => List<ExtendedGroupRoleMembersData>
|
||||||
|
// notice-<noticeID> => GroupNoticeInfo
|
||||||
|
// notices-<GroupID> => List<ExtendedGroupNoticeData>
|
||||||
|
private ExpiringCache<string, object> m_Cache = new ExpiringCache<string, object>();
|
||||||
|
|
||||||
|
public RemoteConnectorCacheWrapper(IUserManagement uman)
|
||||||
|
{
|
||||||
|
m_ForeignImporter = new ForeignImporter(uman);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID CreateGroup(UUID RequestingAgentID, GroupRecordDelegate d)
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name);
|
||||||
|
//reason = string.Empty;
|
||||||
|
|
||||||
|
//ExtendedGroupRecord group = m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID,
|
||||||
|
// membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason);
|
||||||
|
ExtendedGroupRecord group = d();
|
||||||
|
|
||||||
|
if (group == null)
|
||||||
|
return UUID.Zero;
|
||||||
|
|
||||||
|
if (group.GroupID != UUID.Zero)
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.Add("group-" + group.GroupID.ToString(), group, GROUPS_CACHE_TIMEOUT);
|
||||||
|
if (m_Cache.Contains("memberships-" + RequestingAgentID.ToString()))
|
||||||
|
m_Cache.Remove("memberships-" + RequestingAgentID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return group.GroupID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroup(UUID groupID, GroupRecordDelegate d)
|
||||||
|
{
|
||||||
|
//reason = string.Empty;
|
||||||
|
//ExtendedGroupRecord group = m_GroupsService.UpdateGroup(RequestingAgentID, groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish);
|
||||||
|
ExtendedGroupRecord group = d();
|
||||||
|
|
||||||
|
if (group != null && group.GroupID != UUID.Zero)
|
||||||
|
lock (m_Cache)
|
||||||
|
m_Cache.AddOrUpdate("group-" + group.GroupID.ToString(), group, GROUPS_CACHE_TIMEOUT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName, GroupRecordDelegate d)
|
||||||
|
{
|
||||||
|
//if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty))
|
||||||
|
// return null;
|
||||||
|
|
||||||
|
object group = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "group-";
|
||||||
|
if (GroupID != UUID.Zero)
|
||||||
|
cacheKey += GroupID.ToString();
|
||||||
|
else
|
||||||
|
cacheKey += GroupName;
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetGroupRecord {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out group))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: GetGroupRecord {0} cached!", cacheKey);
|
||||||
|
return (ExtendedGroupRecord)group;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
//group = m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
|
||||||
|
group = d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, group, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
return (ExtendedGroupRecord)group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, GroupMembershipDelegate d)
|
||||||
|
{
|
||||||
|
GroupMembershipData membership = d();
|
||||||
|
if (membership == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
// first, remove everything! add a user is a heavy-duty op
|
||||||
|
m_Cache.Clear();
|
||||||
|
|
||||||
|
m_Cache.AddOrUpdate("active-" + AgentID.ToString(), membership, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_Cache.AddOrUpdate("membership-" + AgentID.ToString() + "-" + GroupID.ToString(), membership, GROUPS_CACHE_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, VoidDelegate d)
|
||||||
|
{
|
||||||
|
d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
string cacheKey = "active-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "memberships-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "members-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "roles-" + "-" + GroupID.ToString() + "-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroup(string AgentID, GroupMembershipDelegate d)
|
||||||
|
{
|
||||||
|
GroupMembershipData activeGroup = d();
|
||||||
|
if (activeGroup != null)
|
||||||
|
{
|
||||||
|
string cacheKey = "active-" + AgentID.ToString();
|
||||||
|
lock (m_Cache)
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, activeGroup, GROUPS_CACHE_TIMEOUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentActiveMembership(string AgentID, GroupMembershipDelegate d)
|
||||||
|
{
|
||||||
|
object membership = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "active-" + AgentID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentActiveMembership {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out membership))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentActiveMembership {0} cached!", cacheKey);
|
||||||
|
return (ExtendedGroupMembershipData)membership;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
membership = d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
return (ExtendedGroupMembershipData)membership;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupMembershipData GetAgentGroupMembership(string AgentID, UUID GroupID, GroupMembershipDelegate d)
|
||||||
|
{
|
||||||
|
object membership = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupMembership {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out membership))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupMembership {0}", cacheKey);
|
||||||
|
return (ExtendedGroupMembershipData)membership;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
membership = d();
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
return (ExtendedGroupMembershipData)membership;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembershipData> GetAgentGroupMemberships(string AgentID, GroupMembershipListDelegate d)
|
||||||
|
{
|
||||||
|
object memberships = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "memberships-" + AgentID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupMemberships {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out memberships))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupMemberships {0} cached!", cacheKey);
|
||||||
|
return (List<GroupMembershipData>)memberships;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
memberships = d();
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
return (List<GroupMembershipData>)memberships;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID, GroupMembersListDelegate d)
|
||||||
|
{
|
||||||
|
object members = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
// we need to key in also on the requester, because different ppl have different view privileges
|
||||||
|
string cacheKey = "members-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetGroupMembers {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out members))
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> xx = (List<ExtendedGroupMembersData>)members;
|
||||||
|
return xx.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupMembersData> _members = d();
|
||||||
|
|
||||||
|
if (_members != null && _members.Count > 0)
|
||||||
|
members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
|
||||||
|
else
|
||||||
|
members = new List<GroupMembersData>();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
//m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
|
||||||
|
return (List<GroupMembersData>)members;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupRole(UUID roleID, string description, string name, ulong powers, string title, BooleanDelegate d)
|
||||||
|
{
|
||||||
|
if (d())
|
||||||
|
{
|
||||||
|
GroupRolesData role = new GroupRolesData();
|
||||||
|
role.Description = description;
|
||||||
|
role.Members = 0;
|
||||||
|
role.Name = name;
|
||||||
|
role.Powers = powers;
|
||||||
|
role.RoleID = roleID;
|
||||||
|
role.Title = title;
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
m_Cache.AddOrUpdate("role-" + roleID.ToString(), role, GROUPS_CACHE_TIMEOUT);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateGroupRole(UUID groupID, UUID roleID, string name, string description, string title, ulong powers, BooleanDelegate d)
|
||||||
|
{
|
||||||
|
if (d())
|
||||||
|
{
|
||||||
|
object role;
|
||||||
|
lock (m_Cache)
|
||||||
|
if (m_Cache.TryGetValue("role-" + roleID.ToString(), out role))
|
||||||
|
{
|
||||||
|
GroupRolesData r = (GroupRolesData)role;
|
||||||
|
r.Description = description;
|
||||||
|
r.Name = name;
|
||||||
|
r.Powers = powers;
|
||||||
|
r.Title = title;
|
||||||
|
|
||||||
|
m_Cache.Update("role-" + roleID.ToString(), r, GROUPS_CACHE_TIMEOUT);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.Contains("role-" + roleID.ToString()))
|
||||||
|
m_Cache.Remove("role-" + roleID.ToString());
|
||||||
|
|
||||||
|
// also remove these lists, because they will have an outdated role
|
||||||
|
if (m_Cache.Contains("roles-" + groupID.ToString()))
|
||||||
|
m_Cache.Remove("roles-" + groupID.ToString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, VoidDelegate d)
|
||||||
|
{
|
||||||
|
d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.Contains("role-" + roleID.ToString()))
|
||||||
|
m_Cache.Remove("role-" + roleID.ToString());
|
||||||
|
|
||||||
|
// also remove the list, because it will have an removed role
|
||||||
|
if (m_Cache.Contains("roles-" + groupID.ToString()))
|
||||||
|
m_Cache.Remove("roles-" + groupID.ToString());
|
||||||
|
|
||||||
|
if (m_Cache.Contains("roles-" + groupID.ToString() + "-" + RequestingAgentID.ToString()))
|
||||||
|
m_Cache.Remove("roles-" + groupID.ToString() + "-" + RequestingAgentID.ToString());
|
||||||
|
|
||||||
|
if (m_Cache.Contains("rolemembers-" + RequestingAgentID.ToString() + "-" + groupID.ToString()))
|
||||||
|
m_Cache.Remove("rolemembers-" + RequestingAgentID.ToString() + "-" + groupID.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID, GroupRolesListDelegate d)
|
||||||
|
{
|
||||||
|
object roles = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "roles-" + GroupID.ToString();
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out roles))
|
||||||
|
return (List<GroupRolesData>)roles;
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
roles = d();
|
||||||
|
if (roles != null)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
return (List<GroupRolesData>)roles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, RoleMembersListDelegate d)
|
||||||
|
{
|
||||||
|
object rmembers = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
// we need to key in also on the requester, because different ppl have different view privileges
|
||||||
|
string cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetGroupRoleMembers {0}", cacheKey);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out rmembers))
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> xx = (List<ExtendedGroupRoleMembersData>)rmembers;
|
||||||
|
return xx.ConvertAll<GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
List<ExtendedGroupRoleMembersData> _rmembers = d();
|
||||||
|
|
||||||
|
if (_rmembers != null && _rmembers.Count > 0)
|
||||||
|
rmembers = _rmembers.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData));
|
||||||
|
else
|
||||||
|
rmembers = new List<GroupRoleMembersData>();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
// For some strange reason, when I cache the list of GroupRoleMembersData,
|
||||||
|
// it gets emptied out. The TryGet gets an empty list...
|
||||||
|
//m_Cache.AddOrUpdate(cacheKey, rmembers, GROUPS_CACHE_TIMEOUT);
|
||||||
|
// Caching the list of ExtendedGroupRoleMembersData doesn't show that issue
|
||||||
|
// I don't get it.
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, _rmembers, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
return (List<GroupRoleMembersData>)rmembers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, BooleanDelegate d)
|
||||||
|
{
|
||||||
|
if (d())
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
// update the cached role
|
||||||
|
string cacheKey = "role-" + RoleID.ToString();
|
||||||
|
object obj;
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out obj))
|
||||||
|
{
|
||||||
|
GroupRolesData r = (GroupRolesData)obj;
|
||||||
|
r.Members++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add this agent to the list of role members
|
||||||
|
cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out obj))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// This may throw an exception, in which case the agentID is not a UUID but a full ID
|
||||||
|
// In that case, let's just remove the whoe things from the cache
|
||||||
|
UUID id = new UUID(AgentID);
|
||||||
|
List<ExtendedGroupRoleMembersData> xx = (List<ExtendedGroupRoleMembersData>)obj;
|
||||||
|
List<GroupRoleMembersData> rmlist = xx.ConvertAll<GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData);
|
||||||
|
GroupRoleMembersData rm = new GroupRoleMembersData();
|
||||||
|
rm.MemberID = id;
|
||||||
|
rm.RoleID = RoleID;
|
||||||
|
rmlist.Add(rm);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the cached info about this agent's roles
|
||||||
|
// because we don't have enough local info about the new role
|
||||||
|
cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, BooleanDelegate d)
|
||||||
|
{
|
||||||
|
if (d())
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
// update the cached role
|
||||||
|
string cacheKey = "role-" + RoleID.ToString();
|
||||||
|
object obj;
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out obj))
|
||||||
|
{
|
||||||
|
GroupRolesData r = (GroupRolesData)obj;
|
||||||
|
r.Members--;
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID, GroupRolesListDelegate d)
|
||||||
|
{
|
||||||
|
object roles = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupRoles {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out roles))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupRoles {0} cached!", cacheKey);
|
||||||
|
return (List<GroupRolesData>)roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
roles = d();
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
return (List<GroupRolesData>)roles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAgentActiveGroupRole(string AgentID, UUID GroupID, VoidDelegate d)
|
||||||
|
{
|
||||||
|
d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
// Invalidate cached info, because it has ActiveRoleID and Powers
|
||||||
|
string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "memberships-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMembership(string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile, VoidDelegate d)
|
||||||
|
{
|
||||||
|
d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "memberships-" + AgentID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
cacheKey = "active-" + AgentID.ToString();
|
||||||
|
object m = null;
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out m))
|
||||||
|
{
|
||||||
|
GroupMembershipData membership = (GroupMembershipData)m;
|
||||||
|
membership.ListInProfile = ListInProfile;
|
||||||
|
membership.AcceptNotices = AcceptNotices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddGroupNotice(UUID groupID, UUID noticeID, GroupNoticeInfo notice, BooleanDelegate d)
|
||||||
|
{
|
||||||
|
if (d())
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate("notice-" + noticeID.ToString(), notice, GROUPS_CACHE_TIMEOUT);
|
||||||
|
string cacheKey = "notices-" + groupID.ToString();
|
||||||
|
if (m_Cache.Contains(cacheKey))
|
||||||
|
m_Cache.Remove(cacheKey);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupNoticeInfo GetGroupNotice(UUID noticeID, NoticeDelegate d)
|
||||||
|
{
|
||||||
|
object notice = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "notice-" + noticeID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetAgentGroupRoles {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out notice))
|
||||||
|
{
|
||||||
|
return (GroupNoticeInfo)notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
GroupNoticeInfo _notice = d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
return _notice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupNoticeData> GetGroupNotices(UUID GroupID, NoticeListDelegate d)
|
||||||
|
{
|
||||||
|
object notices = null;
|
||||||
|
bool firstCall = false;
|
||||||
|
string cacheKey = "notices-" + GroupID.ToString();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: GetGroupNotices {0}", cacheKey);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
if (m_Cache.TryGetValue(cacheKey, out notices))
|
||||||
|
{
|
||||||
|
//m_log.DebugFormat("[XXX]: GetGroupNotices {0} cached!", cacheKey);
|
||||||
|
return (List<ExtendedGroupNoticeData>)notices;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not cached
|
||||||
|
if (!m_ActiveRequests.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
m_ActiveRequests.Add(cacheKey, true);
|
||||||
|
firstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCall)
|
||||||
|
{
|
||||||
|
notices = d();
|
||||||
|
|
||||||
|
lock (m_Cache)
|
||||||
|
{
|
||||||
|
m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT);
|
||||||
|
m_ActiveRequests.Remove(cacheKey);
|
||||||
|
return (List<ExtendedGroupNoticeData>)notices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Data;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Services.Base;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class GroupsServiceBase : ServiceBase
|
||||||
|
{
|
||||||
|
protected IGroupsData m_Database = null;
|
||||||
|
|
||||||
|
public GroupsServiceBase(IConfigSource config, string cName)
|
||||||
|
: base(config)
|
||||||
|
{
|
||||||
|
string dllName = String.Empty;
|
||||||
|
string connString = String.Empty;
|
||||||
|
string realm = "os_groups";
|
||||||
|
string configName = (cName == string.Empty) ? "Groups" : cName;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Try reading the [DatabaseService] section, if it exists
|
||||||
|
//
|
||||||
|
IConfig dbConfig = config.Configs["DatabaseService"];
|
||||||
|
if (dbConfig != null)
|
||||||
|
{
|
||||||
|
if (dllName == String.Empty)
|
||||||
|
dllName = dbConfig.GetString("StorageProvider", String.Empty);
|
||||||
|
if (connString == String.Empty)
|
||||||
|
connString = dbConfig.GetString("ConnectionString", String.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// [Groups] section overrides [DatabaseService], if it exists
|
||||||
|
//
|
||||||
|
IConfig groupsConfig = config.Configs[configName];
|
||||||
|
if (groupsConfig != null)
|
||||||
|
{
|
||||||
|
dllName = groupsConfig.GetString("StorageProvider", dllName);
|
||||||
|
connString = groupsConfig.GetString("ConnectionString", connString);
|
||||||
|
realm = groupsConfig.GetString("Realm", realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We tried, but this doesn't exist. We can't proceed.
|
||||||
|
//
|
||||||
|
if (dllName.Equals(String.Empty))
|
||||||
|
throw new Exception("No StorageProvider configured");
|
||||||
|
|
||||||
|
m_Database = LoadPlugin<IGroupsData>(dllName, new Object[] { connString, realm });
|
||||||
|
if (m_Database == null)
|
||||||
|
throw new Exception("Could not find a storage interface in the given module " + dllName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,353 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Timers;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Data;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Groups
|
||||||
|
{
|
||||||
|
public class HGGroupsService : GroupsService
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IOfflineIMService m_OfflineIM;
|
||||||
|
private IUserAccountService m_UserAccounts;
|
||||||
|
private string m_HomeURI;
|
||||||
|
|
||||||
|
public HGGroupsService(IConfigSource config, IOfflineIMService im, IUserAccountService users, string homeURI)
|
||||||
|
: base(config, string.Empty)
|
||||||
|
{
|
||||||
|
m_OfflineIM = im;
|
||||||
|
m_UserAccounts = users;
|
||||||
|
m_HomeURI = homeURI;
|
||||||
|
if (!m_HomeURI.EndsWith("/"))
|
||||||
|
m_HomeURI += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region HG specific operations
|
||||||
|
|
||||||
|
public bool CreateGroupProxy(string RequestingAgentID, string agentID, string accessToken, UUID groupID, string serviceLocation, string name, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
Uri uri = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
uri = new Uri(serviceLocation);
|
||||||
|
}
|
||||||
|
catch (UriFormatException)
|
||||||
|
{
|
||||||
|
reason = "Bad location for group proxy";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it already exists
|
||||||
|
GroupData grec = m_Database.RetrieveGroup(groupID);
|
||||||
|
if (grec == null ||
|
||||||
|
(grec != null && grec.Data["Location"] != string.Empty && grec.Data["Location"].ToLower() != serviceLocation.ToLower()))
|
||||||
|
{
|
||||||
|
// Create the group
|
||||||
|
grec = new GroupData();
|
||||||
|
grec.GroupID = groupID;
|
||||||
|
grec.Data = new Dictionary<string, string>();
|
||||||
|
grec.Data["Name"] = name + " @ " + uri.Authority;
|
||||||
|
grec.Data["Location"] = serviceLocation;
|
||||||
|
grec.Data["Charter"] = string.Empty;
|
||||||
|
grec.Data["InsigniaID"] = UUID.Zero.ToString();
|
||||||
|
grec.Data["FounderID"] = UUID.Zero.ToString();
|
||||||
|
grec.Data["MembershipFee"] = "0";
|
||||||
|
grec.Data["OpenEnrollment"] = "0";
|
||||||
|
grec.Data["ShowInList"] = "0";
|
||||||
|
grec.Data["AllowPublish"] = "0";
|
||||||
|
grec.Data["MaturePublish"] = "0";
|
||||||
|
grec.Data["OwnerRoleID"] = UUID.Zero.ToString();
|
||||||
|
|
||||||
|
|
||||||
|
if (!m_Database.StoreGroup(grec))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grec.Data["Location"] == string.Empty)
|
||||||
|
{
|
||||||
|
reason = "Cannot add proxy membership to non-proxy group";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID uid = UUID.Zero;
|
||||||
|
string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
|
||||||
|
Util.ParseUniversalUserIdentifier(RequestingAgentID, out uid, out url, out first, out last, out tmp);
|
||||||
|
string fromName = first + "." + last + "@" + url;
|
||||||
|
|
||||||
|
// Invite to group again
|
||||||
|
InviteToGroup(fromName, groupID, new UUID(agentID), grec.Data["Name"]);
|
||||||
|
|
||||||
|
// Stick the proxy membership in the DB already
|
||||||
|
// we'll delete it if the agent declines the invitation
|
||||||
|
MembershipData membership = new MembershipData();
|
||||||
|
membership.PrincipalID = agentID;
|
||||||
|
membership.GroupID = groupID;
|
||||||
|
membership.Data = new Dictionary<string, string>();
|
||||||
|
membership.Data["SelectedRoleID"] = UUID.Zero.ToString();
|
||||||
|
membership.Data["Contribution"] = "0";
|
||||||
|
membership.Data["ListInProfile"] = "1";
|
||||||
|
membership.Data["AcceptNotices"] = "1";
|
||||||
|
membership.Data["AccessToken"] = accessToken;
|
||||||
|
|
||||||
|
m_Database.StoreMember(membership);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
// check the token
|
||||||
|
MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID);
|
||||||
|
if (membership != null)
|
||||||
|
{
|
||||||
|
if (token != string.Empty && token.Equals(membership.Data["AccessToken"]))
|
||||||
|
RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
|
||||||
|
else
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", AgentID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string groupName, string token)
|
||||||
|
{
|
||||||
|
// check the token
|
||||||
|
if (!VerifyToken(GroupID, RequestingAgentID, token))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ExtendedGroupRecord grec;
|
||||||
|
if (GroupID == UUID.Zero)
|
||||||
|
grec = GetGroupRecord(RequestingAgentID, groupName);
|
||||||
|
else
|
||||||
|
grec = GetGroupRecord(RequestingAgentID, GroupID);
|
||||||
|
|
||||||
|
if (grec != null)
|
||||||
|
FillFounderUUI(grec);
|
||||||
|
|
||||||
|
return grec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
if (!VerifyToken(GroupID, RequestingAgentID, token))
|
||||||
|
return new List<ExtendedGroupMembersData>();
|
||||||
|
|
||||||
|
List<ExtendedGroupMembersData> members = GetGroupMembers(RequestingAgentID, GroupID);
|
||||||
|
|
||||||
|
// convert UUIDs to UUIs
|
||||||
|
members.ForEach(delegate (ExtendedGroupMembersData m)
|
||||||
|
{
|
||||||
|
if (m.AgentID.ToString().Length == 36) // UUID
|
||||||
|
{
|
||||||
|
UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, new UUID(m.AgentID));
|
||||||
|
if (account != null)
|
||||||
|
m.AgentID = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
if (!VerifyToken(GroupID, RequestingAgentID, token))
|
||||||
|
return new List<GroupRolesData>();
|
||||||
|
|
||||||
|
return GetGroupRoles(RequestingAgentID, GroupID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, string token)
|
||||||
|
{
|
||||||
|
if (!VerifyToken(GroupID, RequestingAgentID, token))
|
||||||
|
return new List<ExtendedGroupRoleMembersData>();
|
||||||
|
|
||||||
|
List<ExtendedGroupRoleMembersData> rolemembers = GetGroupRoleMembers(RequestingAgentID, GroupID);
|
||||||
|
|
||||||
|
// convert UUIDs to UUIs
|
||||||
|
rolemembers.ForEach(delegate(ExtendedGroupRoleMembersData m)
|
||||||
|
{
|
||||||
|
if (m.MemberID.ToString().Length == 36) // UUID
|
||||||
|
{
|
||||||
|
UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, new UUID(m.MemberID));
|
||||||
|
if (account != null)
|
||||||
|
m.MemberID = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return rolemembers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
|
||||||
|
bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
|
||||||
|
{
|
||||||
|
// check that the group proxy exists
|
||||||
|
ExtendedGroupRecord grec = GetGroupRecord(RequestingAgentID, groupID);
|
||||||
|
if (grec == null)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: attempt at adding notice to non-existent group proxy");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that the group is remote
|
||||||
|
if (grec.ServiceLocation == string.Empty)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: attempt at adding notice to local (non-proxy) group");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that there isn't already a notice with the same ID
|
||||||
|
if (GetGroupNotice(RequestingAgentID, noticeID) != null)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: a notice with the same ID already exists", grec.ServiceLocation);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This has good intentions (security) but it will potentially DDS the origin...
|
||||||
|
// We'll need to send a proof along with the message. Maybe encrypt the message
|
||||||
|
// using key pairs
|
||||||
|
//
|
||||||
|
//// check that the notice actually exists in the origin
|
||||||
|
//GroupsServiceHGConnector c = new GroupsServiceHGConnector(grec.ServiceLocation);
|
||||||
|
//if (!c.VerifyNotice(noticeID, groupID))
|
||||||
|
//{
|
||||||
|
// m_log.DebugFormat("[Groups.HGGroupsService]: notice does not exist at origin {0}", grec.ServiceLocation);
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// ok, we're good!
|
||||||
|
return _AddNotice(groupID, noticeID, fromName, subject, message, hasAttachment, attType, attName, attItemID, attOwnerID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool VerifyNotice(UUID noticeID, UUID groupID)
|
||||||
|
{
|
||||||
|
GroupNoticeInfo notice = GetGroupNotice(string.Empty, noticeID);
|
||||||
|
|
||||||
|
if (notice == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (notice.GroupID != groupID)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void InviteToGroup(string fromName, UUID groupID, UUID invitedAgentID, string groupName)
|
||||||
|
{
|
||||||
|
// Todo: Security check, probably also want to send some kind of notification
|
||||||
|
UUID InviteID = UUID.Random();
|
||||||
|
|
||||||
|
if (AddAgentToGroupInvite(InviteID, groupID, invitedAgentID.ToString()))
|
||||||
|
{
|
||||||
|
Guid inviteUUID = InviteID.Guid;
|
||||||
|
|
||||||
|
GridInstantMessage msg = new GridInstantMessage();
|
||||||
|
|
||||||
|
msg.imSessionID = inviteUUID;
|
||||||
|
|
||||||
|
// msg.fromAgentID = agentID.Guid;
|
||||||
|
msg.fromAgentID = groupID.Guid;
|
||||||
|
msg.toAgentID = invitedAgentID.Guid;
|
||||||
|
//msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
|
||||||
|
msg.timestamp = 0;
|
||||||
|
msg.fromAgentName = fromName;
|
||||||
|
msg.message = string.Format("Please confirm your acceptance to join group {0}.", groupName);
|
||||||
|
msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupInvitation;
|
||||||
|
msg.fromGroup = true;
|
||||||
|
msg.offline = (byte)0;
|
||||||
|
msg.ParentEstateID = 0;
|
||||||
|
msg.Position = Vector3.Zero;
|
||||||
|
msg.RegionID = UUID.Zero.Guid;
|
||||||
|
msg.binaryBucket = new byte[20];
|
||||||
|
|
||||||
|
string reason = string.Empty;
|
||||||
|
m_OfflineIM.StoreMessage(msg, out reason);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool AddAgentToGroupInvite(UUID inviteID, UUID groupID, string agentID)
|
||||||
|
{
|
||||||
|
// Check whether the invitee is already a member of the group
|
||||||
|
MembershipData m = m_Database.RetrieveMember(groupID, agentID);
|
||||||
|
if (m != null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check whether there are pending invitations and delete them
|
||||||
|
InvitationData invite = m_Database.RetrieveInvitation(groupID, agentID);
|
||||||
|
if (invite != null)
|
||||||
|
m_Database.DeleteInvite(invite.InviteID);
|
||||||
|
|
||||||
|
invite = new InvitationData();
|
||||||
|
invite.InviteID = inviteID;
|
||||||
|
invite.PrincipalID = agentID;
|
||||||
|
invite.GroupID = groupID;
|
||||||
|
invite.RoleID = UUID.Zero;
|
||||||
|
invite.Data = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
return m_Database.StoreInvitation(invite);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FillFounderUUI(ExtendedGroupRecord grec)
|
||||||
|
{
|
||||||
|
UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, grec.FounderID);
|
||||||
|
if (account != null)
|
||||||
|
grec.FounderUUI = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool VerifyToken(UUID groupID, string agentID, string token)
|
||||||
|
{
|
||||||
|
// check the token
|
||||||
|
MembershipData membership = m_Database.RetrieveMember(groupID, agentID);
|
||||||
|
if (membership != null)
|
||||||
|
{
|
||||||
|
if (token != string.Empty && token.Equals(membership.Data["AccessToken"]))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", agentID);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,267 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using log4net;
|
||||||
|
using Mono.Addins;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
using OpenSim.Framework.Client;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.OfflineIM
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineIMConnectorModule")]
|
||||||
|
public class OfflineIMRegionModule : ISharedRegionModule, IOfflineIMService
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private bool m_Enabled = false;
|
||||||
|
private List<Scene> m_SceneList = new List<Scene>();
|
||||||
|
IMessageTransferModule m_TransferModule = null;
|
||||||
|
private bool m_ForwardOfflineGroupMessages = true;
|
||||||
|
|
||||||
|
private IOfflineIMService m_OfflineIMService;
|
||||||
|
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig cnf = config.Configs["Messaging"];
|
||||||
|
if (cnf == null)
|
||||||
|
return;
|
||||||
|
if (cnf != null && cnf.GetString("OfflineMessageModule", string.Empty) != Name)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_Enabled = true;
|
||||||
|
|
||||||
|
string serviceLocation = cnf.GetString("OfflineMessageURL", string.Empty);
|
||||||
|
if (serviceLocation == string.Empty)
|
||||||
|
m_OfflineIMService = new OfflineIMService(config);
|
||||||
|
else
|
||||||
|
m_OfflineIMService = new OfflineIMServiceRemoteConnector(serviceLocation);
|
||||||
|
|
||||||
|
m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages);
|
||||||
|
m_log.DebugFormat("[OfflineIM.V2]: Offline messages enabled by {0}", Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scene.RegisterModuleInterface<IOfflineIMService>(this);
|
||||||
|
m_SceneList.Add(scene);
|
||||||
|
scene.EventManager.OnNewClient += OnNewClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_TransferModule == null)
|
||||||
|
{
|
||||||
|
m_TransferModule = scene.RequestModuleInterface<IMessageTransferModule>();
|
||||||
|
if (m_TransferModule == null)
|
||||||
|
{
|
||||||
|
scene.EventManager.OnNewClient -= OnNewClient;
|
||||||
|
|
||||||
|
m_SceneList.Clear();
|
||||||
|
|
||||||
|
m_log.Error("[OfflineIM.V2]: No message transfer module is enabled. Disabling offline messages");
|
||||||
|
}
|
||||||
|
m_TransferModule.OnUndeliveredMessage += UndeliveredMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (!m_Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_SceneList.Remove(scene);
|
||||||
|
scene.EventManager.OnNewClient -= OnNewClient;
|
||||||
|
m_TransferModule.OnUndeliveredMessage -= UndeliveredMessage;
|
||||||
|
|
||||||
|
scene.ForEachClient(delegate(IClientAPI client)
|
||||||
|
{
|
||||||
|
client.OnRetrieveInstantMessages -= RetrieveInstantMessages;
|
||||||
|
client.OnMuteListRequest -= OnMuteListRequest;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Offline Message Module V2"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
m_SceneList.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Scene FindScene(UUID agentID)
|
||||||
|
{
|
||||||
|
foreach (Scene s in m_SceneList)
|
||||||
|
{
|
||||||
|
ScenePresence presence = s.GetScenePresence(agentID);
|
||||||
|
if (presence != null && !presence.IsChildAgent)
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IClientAPI FindClient(UUID agentID)
|
||||||
|
{
|
||||||
|
foreach (Scene s in m_SceneList)
|
||||||
|
{
|
||||||
|
ScenePresence presence = s.GetScenePresence(agentID);
|
||||||
|
if (presence != null && !presence.IsChildAgent)
|
||||||
|
return presence.ControllingClient;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNewClient(IClientAPI client)
|
||||||
|
{
|
||||||
|
client.OnRetrieveInstantMessages += RetrieveInstantMessages;
|
||||||
|
client.OnMuteListRequest += OnMuteListRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RetrieveInstantMessages(IClientAPI client)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[OfflineIM.V2]: Retrieving stored messages for {0}", client.AgentId);
|
||||||
|
|
||||||
|
List<GridInstantMessage> msglist = m_OfflineIMService.GetMessages(client.AgentId);
|
||||||
|
|
||||||
|
if (msglist == null)
|
||||||
|
m_log.DebugFormat("[OfflineIM.V2]: WARNING null message list.");
|
||||||
|
|
||||||
|
foreach (GridInstantMessage im in msglist)
|
||||||
|
{
|
||||||
|
if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
|
||||||
|
// send it directly or else the item will be given twice
|
||||||
|
client.SendInstantMessage(im);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Send through scene event manager so all modules get a chance
|
||||||
|
// to look at this message before it gets delivered.
|
||||||
|
//
|
||||||
|
// Needed for proper state management for stored group
|
||||||
|
// invitations
|
||||||
|
//
|
||||||
|
Scene s = FindScene(client.AgentId);
|
||||||
|
if (s != null)
|
||||||
|
s.EventManager.TriggerIncomingInstantMessage(im);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apparently this is needed in order for the viewer to request the IMs.
|
||||||
|
private void OnMuteListRequest(IClientAPI client, uint crc)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[OfflineIM.V2] Got mute list request for crc {0}", crc);
|
||||||
|
string filename = "mutes" + client.AgentId.ToString();
|
||||||
|
|
||||||
|
IXfer xfer = client.Scene.RequestModuleInterface<IXfer>();
|
||||||
|
if (xfer != null)
|
||||||
|
{
|
||||||
|
xfer.AddNewFile(filename, new Byte[0]);
|
||||||
|
client.SendMuteListUpdate(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UndeliveredMessage(GridInstantMessage im)
|
||||||
|
{
|
||||||
|
if (im.dialog != (byte)InstantMessageDialog.MessageFromObject &&
|
||||||
|
im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
|
||||||
|
im.dialog != (byte)InstantMessageDialog.GroupNotice &&
|
||||||
|
im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
|
||||||
|
im.dialog != (byte)InstantMessageDialog.InventoryOffered)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_ForwardOfflineGroupMessages)
|
||||||
|
{
|
||||||
|
if (im.dialog == (byte)InstantMessageDialog.GroupNotice ||
|
||||||
|
im.dialog == (byte)InstantMessageDialog.GroupInvitation)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scene scene = FindScene(new UUID(im.fromAgentID));
|
||||||
|
if (scene == null)
|
||||||
|
scene = m_SceneList[0];
|
||||||
|
|
||||||
|
string reason = string.Empty;
|
||||||
|
bool success = m_OfflineIMService.StoreMessage(im, out reason);
|
||||||
|
|
||||||
|
if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
|
||||||
|
{
|
||||||
|
IClientAPI client = FindClient(new UUID(im.fromAgentID));
|
||||||
|
if (client == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
client.SendInstantMessage(new GridInstantMessage(
|
||||||
|
null, new UUID(im.toAgentID),
|
||||||
|
"System", new UUID(im.fromAgentID),
|
||||||
|
(byte)InstantMessageDialog.MessageFromAgent,
|
||||||
|
"User is not logged in. " +
|
||||||
|
(success ? "Message saved." : "Message not saved: " + reason),
|
||||||
|
false, new Vector3()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IOfflineIM
|
||||||
|
|
||||||
|
public List<GridInstantMessage> GetMessages(UUID principalID)
|
||||||
|
{
|
||||||
|
return m_OfflineIMService.GetMessages(principalID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StoreMessage(GridInstantMessage im, out string reason)
|
||||||
|
{
|
||||||
|
return m_OfflineIMService.StoreMessage(im, out reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Mono.Addins;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("OpenSim.Addons.OfflineIM")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("http://opensimulator.org")]
|
||||||
|
[assembly: AssemblyProduct("OpenSim.Addons.OfflineIM")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("a16a9905-4393-4872-9fca-4c81bedbd9f2")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
|
|
||||||
|
[assembly: Addin("OpenSim.OfflineIM", "0.1")]
|
||||||
|
[assembly: AddinDependency("OpenSim", "0.5")]
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
namespace OpenSim.OfflineIM
|
||||||
|
{
|
||||||
|
public class OfflineIMServiceRemoteConnector : IOfflineIMService
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private string m_ServerURI = string.Empty;
|
||||||
|
private object m_Lock = new object();
|
||||||
|
|
||||||
|
public OfflineIMServiceRemoteConnector(string url)
|
||||||
|
{
|
||||||
|
m_ServerURI = url;
|
||||||
|
m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0}", m_ServerURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OfflineIMServiceRemoteConnector(IConfigSource config)
|
||||||
|
{
|
||||||
|
IConfig cnf = config.Configs["Messaging"];
|
||||||
|
if (cnf == null)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[OfflineIM.V2.RemoteConnector]: Missing Messaging configuration");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ServerURI = cnf.GetString("OfflineMessageURL", string.Empty);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IOfflineIMService
|
||||||
|
public List<GridInstantMessage> GetMessages(UUID principalID)
|
||||||
|
{
|
||||||
|
List<GridInstantMessage> ims = new List<GridInstantMessage>();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
|
sendData["PrincipalID"] = principalID;
|
||||||
|
Dictionary<string, object> ret = MakeRequest("GET", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
return ims;
|
||||||
|
|
||||||
|
if (!ret.ContainsKey("RESULT"))
|
||||||
|
return ims;
|
||||||
|
|
||||||
|
if (ret["RESULT"].ToString() == "NULL")
|
||||||
|
return ims;
|
||||||
|
|
||||||
|
foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
|
||||||
|
{
|
||||||
|
GridInstantMessage m = OfflineIMDataUtils.GridInstantMessage((Dictionary<string, object>)v);
|
||||||
|
ims.Add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ims;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StoreMessage(GridInstantMessage im, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
Dictionary<string, object> sendData = OfflineIMDataUtils.GridInstantMessage(im);
|
||||||
|
|
||||||
|
Dictionary<string, object> ret = MakeRequest("STORE", sendData);
|
||||||
|
|
||||||
|
if (ret == null)
|
||||||
|
{
|
||||||
|
reason = "Bad response from server";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string result = ret["RESULT"].ToString();
|
||||||
|
if (result == "NULL" || result.ToLower() == "false")
|
||||||
|
{
|
||||||
|
reason = ret["REASON"].ToString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Make Request
|
||||||
|
|
||||||
|
private Dictionary<string, object> MakeRequest(string method, Dictionary<string, object> sendData)
|
||||||
|
{
|
||||||
|
sendData["METHOD"] = method;
|
||||||
|
|
||||||
|
string reply = string.Empty;
|
||||||
|
lock (m_Lock)
|
||||||
|
reply = SynchronousRestFormsRequester.MakeRequest("POST",
|
||||||
|
m_ServerURI + "/offlineim",
|
||||||
|
ServerUtils.BuildQueryString(sendData));
|
||||||
|
|
||||||
|
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
|
||||||
|
reply);
|
||||||
|
|
||||||
|
return replyData;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,215 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Server.Base;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
|
using OpenSim.Server.Handlers.Base;
|
||||||
|
using log4net;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.OfflineIM
|
||||||
|
{
|
||||||
|
public class OfflineIMServiceRobustConnector : ServiceConnector
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IOfflineIMService m_OfflineIMService;
|
||||||
|
private string m_ConfigName = "Messaging";
|
||||||
|
|
||||||
|
public OfflineIMServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||||
|
base(config, server, configName)
|
||||||
|
{
|
||||||
|
if (configName != String.Empty)
|
||||||
|
m_ConfigName = configName;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[OfflineIM.V2.RobustConnector]: Starting with config name {0}", m_ConfigName);
|
||||||
|
|
||||||
|
m_OfflineIMService = new OfflineIMService(config);
|
||||||
|
|
||||||
|
server.AddStreamHandler(new OfflineIMServicePostHandler(m_OfflineIMService));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OfflineIMServicePostHandler : BaseStreamHandler
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IOfflineIMService m_OfflineIMService;
|
||||||
|
|
||||||
|
public OfflineIMServicePostHandler(IOfflineIMService service) :
|
||||||
|
base("POST", "/offlineim")
|
||||||
|
{
|
||||||
|
m_OfflineIMService = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte[] Handle(string path, Stream requestData,
|
||||||
|
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
|
||||||
|
{
|
||||||
|
StreamReader sr = new StreamReader(requestData);
|
||||||
|
string body = sr.ReadToEnd();
|
||||||
|
sr.Close();
|
||||||
|
body = body.Trim();
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: query String: {0}", body);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, object> request =
|
||||||
|
ServerUtils.ParseQueryString(body);
|
||||||
|
|
||||||
|
if (!request.ContainsKey("METHOD"))
|
||||||
|
return FailureResult();
|
||||||
|
|
||||||
|
string method = request["METHOD"].ToString();
|
||||||
|
request.Remove("METHOD");
|
||||||
|
|
||||||
|
m_log.DebugFormat("[OfflineIM.V2.Handler]: {0}", method);
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case "GET":
|
||||||
|
return HandleGet(request);
|
||||||
|
case "STORE":
|
||||||
|
return HandleStore(request);
|
||||||
|
}
|
||||||
|
m_log.DebugFormat("[OFFLINE IM HANDLER]: unknown method request: {0}", method);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[OFFLINE IM HANDLER]: Exception {0}", e.StackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FailureResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleStore(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
GridInstantMessage im = OfflineIMDataUtils.GridInstantMessage(request);
|
||||||
|
|
||||||
|
string reason = string.Empty;
|
||||||
|
|
||||||
|
bool success = m_OfflineIMService.StoreMessage(im, out reason);
|
||||||
|
|
||||||
|
result["RESULT"] = success.ToString();
|
||||||
|
if (!success)
|
||||||
|
result["REASON"] = reason;
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] HandleGet(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
if (!request.ContainsKey("PrincipalID"))
|
||||||
|
NullResult(result, "Bad network data");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UUID principalID = new UUID(request["PrincipalID"].ToString());
|
||||||
|
List<GridInstantMessage> ims = m_OfflineIMService.GetMessages(principalID);
|
||||||
|
|
||||||
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
||||||
|
int i = 0;
|
||||||
|
foreach (GridInstantMessage m in ims)
|
||||||
|
dict["im-" + i++] = OfflineIMDataUtils.GridInstantMessage(m);
|
||||||
|
|
||||||
|
result["RESULT"] = dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
string xmlString = ServerUtils.BuildXmlResponse(result);
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
|
||||||
|
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Helpers
|
||||||
|
|
||||||
|
private void NullResult(Dictionary<string, object> result, string reason)
|
||||||
|
{
|
||||||
|
result["RESULT"] = "NULL";
|
||||||
|
result["REASON"] = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] FailureResult()
|
||||||
|
{
|
||||||
|
return BoolResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] SuccessResult()
|
||||||
|
{
|
||||||
|
return BoolResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] BoolResult(bool value)
|
||||||
|
{
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
|
||||||
|
XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
|
||||||
|
"", "");
|
||||||
|
|
||||||
|
doc.AppendChild(xmlnode);
|
||||||
|
|
||||||
|
XmlElement rootElement = doc.CreateElement("", "ServerResponse",
|
||||||
|
"");
|
||||||
|
|
||||||
|
doc.AppendChild(rootElement);
|
||||||
|
|
||||||
|
XmlElement result = doc.CreateElement("", "RESULT", "");
|
||||||
|
result.AppendChild(doc.CreateTextNode(value.ToString()));
|
||||||
|
|
||||||
|
rootElement.AppendChild(result);
|
||||||
|
|
||||||
|
return DocToBytes(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] DocToBytes(XmlDocument doc)
|
||||||
|
{
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
XmlTextWriter xw = new XmlTextWriter(ms, null);
|
||||||
|
xw.Formatting = Formatting.Indented;
|
||||||
|
doc.WriteTo(xw);
|
||||||
|
xw.Flush();
|
||||||
|
|
||||||
|
return ms.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Text;
|
||||||
|
using System.Timers;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Data;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.OfflineIM
|
||||||
|
{
|
||||||
|
public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private const int MAX_IM = 25;
|
||||||
|
|
||||||
|
private XmlSerializer m_serializer;
|
||||||
|
private static bool m_Initialized = false;
|
||||||
|
|
||||||
|
public OfflineIMService(IConfigSource config)
|
||||||
|
: base(config)
|
||||||
|
{
|
||||||
|
m_serializer = new XmlSerializer(typeof(GridInstantMessage));
|
||||||
|
if (!m_Initialized)
|
||||||
|
{
|
||||||
|
m_Database.DeleteOld();
|
||||||
|
m_Initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GridInstantMessage> GetMessages(UUID principalID)
|
||||||
|
{
|
||||||
|
List<GridInstantMessage> ims = new List<GridInstantMessage>();
|
||||||
|
|
||||||
|
OfflineIMData[] messages = m_Database.Get("PrincipalID", principalID.ToString());
|
||||||
|
|
||||||
|
if (messages == null || (messages != null && messages.Length == 0))
|
||||||
|
return ims;
|
||||||
|
|
||||||
|
foreach (OfflineIMData m in messages)
|
||||||
|
{
|
||||||
|
using (MemoryStream mstream = new MemoryStream(Encoding.UTF8.GetBytes(m.Data["Message"])))
|
||||||
|
{
|
||||||
|
GridInstantMessage im = (GridInstantMessage)m_serializer.Deserialize(mstream);
|
||||||
|
ims.Add(im);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then, delete them
|
||||||
|
m_Database.Delete("PrincipalID", principalID.ToString());
|
||||||
|
|
||||||
|
return ims;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StoreMessage(GridInstantMessage im, out string reason)
|
||||||
|
{
|
||||||
|
reason = string.Empty;
|
||||||
|
|
||||||
|
// TODO Check limits
|
||||||
|
UUID principalID = new UUID(im.toAgentID);
|
||||||
|
long count = m_Database.GetCount("PrincipalID", principalID.ToString());
|
||||||
|
if (count >= MAX_IM)
|
||||||
|
{
|
||||||
|
reason = "Number of offline IMs has maxed out";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string imXml = string.Empty;
|
||||||
|
using (MemoryStream mstream = new MemoryStream())
|
||||||
|
{
|
||||||
|
XmlWriterSettings settings = new XmlWriterSettings();
|
||||||
|
settings.Encoding = Encoding.UTF8;
|
||||||
|
|
||||||
|
using (XmlWriter writer = XmlWriter.Create(mstream, settings))
|
||||||
|
{
|
||||||
|
m_serializer.Serialize(writer, im);
|
||||||
|
writer.Flush();
|
||||||
|
|
||||||
|
mstream.Position = 0;
|
||||||
|
using (StreamReader sreader = new StreamReader(mstream))
|
||||||
|
{
|
||||||
|
imXml = sreader.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OfflineIMData data = new OfflineIMData();
|
||||||
|
data.PrincipalID = principalID;
|
||||||
|
data.Data = new Dictionary<string, string>();
|
||||||
|
data.Data["Message"] = imXml;
|
||||||
|
|
||||||
|
return m_Database.Store(data);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Data;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Services.Base;
|
||||||
|
|
||||||
|
namespace OpenSim.OfflineIM
|
||||||
|
{
|
||||||
|
public class OfflineIMServiceBase : ServiceBase
|
||||||
|
{
|
||||||
|
protected IOfflineIMData m_Database = null;
|
||||||
|
|
||||||
|
public OfflineIMServiceBase(IConfigSource config)
|
||||||
|
: base(config)
|
||||||
|
{
|
||||||
|
string dllName = String.Empty;
|
||||||
|
string connString = String.Empty;
|
||||||
|
string realm = "im_offline";
|
||||||
|
|
||||||
|
//
|
||||||
|
// Try reading the [DatabaseService] section, if it exists
|
||||||
|
//
|
||||||
|
IConfig dbConfig = config.Configs["DatabaseService"];
|
||||||
|
if (dbConfig != null)
|
||||||
|
{
|
||||||
|
if (dllName == String.Empty)
|
||||||
|
dllName = dbConfig.GetString("StorageProvider", String.Empty);
|
||||||
|
if (connString == String.Empty)
|
||||||
|
connString = dbConfig.GetString("ConnectionString", String.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// [Messaging] section overrides [DatabaseService], if it exists
|
||||||
|
//
|
||||||
|
IConfig imConfig = config.Configs["Messaging"];
|
||||||
|
if (imConfig != null)
|
||||||
|
{
|
||||||
|
dllName = imConfig.GetString("StorageProvider", dllName);
|
||||||
|
connString = imConfig.GetString("ConnectionString", connString);
|
||||||
|
realm = imConfig.GetString("Realm", realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We tried, but this doesn't exist. We can't proceed.
|
||||||
|
//
|
||||||
|
if (dllName.Equals(String.Empty))
|
||||||
|
throw new Exception("No StorageProvider configured");
|
||||||
|
|
||||||
|
m_Database = LoadPlugin<IOfflineIMData>(dllName, new Object[] { connString, realm });
|
||||||
|
if (m_Database == null)
|
||||||
|
throw new Exception("Could not find a storage interface in the given module " + dllName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -63,4 +63,3 @@ using System.Runtime.InteropServices;
|
||||||
// [assembly: AssemblyVersion("0.7.6.*")]
|
// [assembly: AssemblyVersion("0.7.6.*")]
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.7.6.*")]
|
[assembly : AssemblyVersion("0.7.6.*")]
|
||||||
[assembly : AssemblyFileVersion("0.6.5.0")]
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenSim.Data;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
public class GroupData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MembershipData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public string PrincipalID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RoleData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public UUID RoleID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RoleMembershipData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public UUID RoleID;
|
||||||
|
public string PrincipalID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PrincipalData
|
||||||
|
{
|
||||||
|
public string PrincipalID;
|
||||||
|
public UUID ActiveGroupID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InvitationData
|
||||||
|
{
|
||||||
|
public UUID InviteID;
|
||||||
|
public UUID GroupID;
|
||||||
|
public UUID RoleID;
|
||||||
|
public string PrincipalID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NoticeData
|
||||||
|
{
|
||||||
|
public UUID GroupID;
|
||||||
|
public UUID NoticeID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface IGroupsData
|
||||||
|
{
|
||||||
|
// groups table
|
||||||
|
bool StoreGroup(GroupData data);
|
||||||
|
GroupData RetrieveGroup(UUID groupID);
|
||||||
|
GroupData RetrieveGroup(string name);
|
||||||
|
GroupData[] RetrieveGroups(string pattern);
|
||||||
|
bool DeleteGroup(UUID groupID);
|
||||||
|
int GroupsCount();
|
||||||
|
|
||||||
|
// membership table
|
||||||
|
MembershipData RetrieveMember(UUID groupID, string pricipalID);
|
||||||
|
MembershipData[] RetrieveMembers(UUID groupID);
|
||||||
|
MembershipData[] RetrieveMemberships(string pricipalID);
|
||||||
|
bool StoreMember(MembershipData data);
|
||||||
|
bool DeleteMember(UUID groupID, string pricipalID);
|
||||||
|
int MemberCount(UUID groupID);
|
||||||
|
|
||||||
|
// roles table
|
||||||
|
bool StoreRole(RoleData data);
|
||||||
|
RoleData RetrieveRole(UUID groupID, UUID roleID);
|
||||||
|
RoleData[] RetrieveRoles(UUID groupID);
|
||||||
|
bool DeleteRole(UUID groupID, UUID roleID);
|
||||||
|
int RoleCount(UUID groupID);
|
||||||
|
|
||||||
|
// rolememberhip table
|
||||||
|
RoleMembershipData[] RetrieveRolesMembers(UUID groupID);
|
||||||
|
RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID);
|
||||||
|
RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID);
|
||||||
|
RoleMembershipData RetrieveRoleMember(UUID groupID, UUID roleID, string principalID);
|
||||||
|
int RoleMemberCount(UUID groupID, UUID roleID);
|
||||||
|
bool StoreRoleMember(RoleMembershipData data);
|
||||||
|
bool DeleteRoleMember(RoleMembershipData data);
|
||||||
|
bool DeleteMemberAllRoles(UUID groupID, string principalID);
|
||||||
|
|
||||||
|
// principals table
|
||||||
|
bool StorePrincipal(PrincipalData data);
|
||||||
|
PrincipalData RetrievePrincipal(string principalID);
|
||||||
|
bool DeletePrincipal(string principalID);
|
||||||
|
|
||||||
|
// invites table
|
||||||
|
bool StoreInvitation(InvitationData data);
|
||||||
|
InvitationData RetrieveInvitation(UUID inviteID);
|
||||||
|
InvitationData RetrieveInvitation(UUID groupID, string principalID);
|
||||||
|
bool DeleteInvite(UUID inviteID);
|
||||||
|
void DeleteOldInvites();
|
||||||
|
|
||||||
|
// notices table
|
||||||
|
bool StoreNotice(NoticeData data);
|
||||||
|
NoticeData RetrieveNotice(UUID noticeID);
|
||||||
|
NoticeData[] RetrieveNotices(UUID groupID);
|
||||||
|
bool DeleteNotice(UUID noticeID);
|
||||||
|
void DeleteOldNotices();
|
||||||
|
|
||||||
|
// combinations
|
||||||
|
MembershipData RetrievePrincipalGroupMembership(string principalID, UUID groupID);
|
||||||
|
MembershipData[] RetrievePrincipalGroupMemberships(string principalID);
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenSim.Data;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Data
|
||||||
|
{
|
||||||
|
public class OfflineIMData
|
||||||
|
{
|
||||||
|
public UUID PrincipalID;
|
||||||
|
public Dictionary<string, string> Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface IOfflineIMData
|
||||||
|
{
|
||||||
|
OfflineIMData[] Get(string field, string val);
|
||||||
|
long GetCount(string field, string key);
|
||||||
|
bool Store(OfflineIMData data);
|
||||||
|
bool Delete(string field, string val);
|
||||||
|
void DeleteOld();
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.7.6.*")]
|
[assembly : AssemblyVersion("0.7.6.*")]
|
||||||
[assembly : AssemblyFileVersion("0.6.5.0")]
|
|
||||||
|
|
|
@ -306,5 +306,65 @@ namespace OpenSim.Data.MySQL
|
||||||
return ExecuteNonQuery(cmd) > 0;
|
return ExecuteNonQuery(cmd) > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long GetCount(string field, string key)
|
||||||
|
{
|
||||||
|
return GetCount(new string[] { field }, new string[] { key });
|
||||||
|
}
|
||||||
|
|
||||||
|
public long GetCount(string[] fields, string[] keys)
|
||||||
|
{
|
||||||
|
if (fields.Length != keys.Length)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
List<string> terms = new List<string>();
|
||||||
|
|
||||||
|
using (MySqlCommand cmd = new MySqlCommand())
|
||||||
|
{
|
||||||
|
for (int i = 0; i < fields.Length; i++)
|
||||||
|
{
|
||||||
|
cmd.Parameters.AddWithValue(fields[i], keys[i]);
|
||||||
|
terms.Add("`" + fields[i] + "` = ?" + fields[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
string where = String.Join(" and ", terms.ToArray());
|
||||||
|
|
||||||
|
string query = String.Format("select count(*) from {0} where {1}",
|
||||||
|
m_Realm, where);
|
||||||
|
|
||||||
|
cmd.CommandText = query;
|
||||||
|
|
||||||
|
Object result = DoQueryScalar(cmd);
|
||||||
|
|
||||||
|
return Convert.ToInt64(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long GetCount(string where)
|
||||||
|
{
|
||||||
|
using (MySqlCommand cmd = new MySqlCommand())
|
||||||
|
{
|
||||||
|
string query = String.Format("select count(*) from {0} where {1}",
|
||||||
|
m_Realm, where);
|
||||||
|
|
||||||
|
cmd.CommandText = query;
|
||||||
|
|
||||||
|
object result = DoQueryScalar(cmd);
|
||||||
|
|
||||||
|
return Convert.ToInt64(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object DoQueryScalar(MySqlCommand cmd)
|
||||||
|
{
|
||||||
|
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
|
||||||
|
{
|
||||||
|
dbcon.Open();
|
||||||
|
cmd.Connection = dbcon;
|
||||||
|
|
||||||
|
return cmd.ExecuteScalar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,484 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Data.MySQL;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
namespace OpenSim.Data.MySQL
|
||||||
|
{
|
||||||
|
public class MySQLGroupsData : IGroupsData
|
||||||
|
{
|
||||||
|
private MySqlGroupsGroupsHandler m_Groups;
|
||||||
|
private MySqlGroupsMembershipHandler m_Membership;
|
||||||
|
private MySqlGroupsRolesHandler m_Roles;
|
||||||
|
private MySqlGroupsRoleMembershipHandler m_RoleMembership;
|
||||||
|
private MySqlGroupsInvitesHandler m_Invites;
|
||||||
|
private MySqlGroupsNoticesHandler m_Notices;
|
||||||
|
private MySqlGroupsPrincipalsHandler m_Principals;
|
||||||
|
|
||||||
|
public MySQLGroupsData(string connectionString, string realm)
|
||||||
|
{
|
||||||
|
m_Groups = new MySqlGroupsGroupsHandler(connectionString, realm + "_groups", realm + "_Store");
|
||||||
|
m_Membership = new MySqlGroupsMembershipHandler(connectionString, realm + "_membership");
|
||||||
|
m_Roles = new MySqlGroupsRolesHandler(connectionString, realm + "_roles");
|
||||||
|
m_RoleMembership = new MySqlGroupsRoleMembershipHandler(connectionString, realm + "_rolemembership");
|
||||||
|
m_Invites = new MySqlGroupsInvitesHandler(connectionString, realm + "_invites");
|
||||||
|
m_Notices = new MySqlGroupsNoticesHandler(connectionString, realm + "_notices");
|
||||||
|
m_Principals = new MySqlGroupsPrincipalsHandler(connectionString, realm + "_principals");
|
||||||
|
}
|
||||||
|
|
||||||
|
#region groups table
|
||||||
|
public bool StoreGroup(GroupData data)
|
||||||
|
{
|
||||||
|
return m_Groups.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupData RetrieveGroup(UUID groupID)
|
||||||
|
{
|
||||||
|
GroupData[] groups = m_Groups.Get("GroupID", groupID.ToString());
|
||||||
|
if (groups.Length > 0)
|
||||||
|
return groups[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupData RetrieveGroup(string name)
|
||||||
|
{
|
||||||
|
GroupData[] groups = m_Groups.Get("Name", name);
|
||||||
|
if (groups.Length > 0)
|
||||||
|
return groups[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupData[] RetrieveGroups(string pattern)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(pattern))
|
||||||
|
pattern = "1 ORDER BY Name LIMIT 100";
|
||||||
|
else
|
||||||
|
pattern = string.Format("Name LIKE %{0}% ORDER BY Name LIMIT 100", pattern);
|
||||||
|
|
||||||
|
return m_Groups.Get(pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteGroup(UUID groupID)
|
||||||
|
{
|
||||||
|
return m_Groups.Delete("GroupID", groupID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GroupsCount()
|
||||||
|
{
|
||||||
|
return (int)m_Groups.GetCount("Location=\"\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region membership table
|
||||||
|
public MembershipData[] RetrieveMembers(UUID groupID)
|
||||||
|
{
|
||||||
|
return m_Membership.Get("GroupID", groupID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MembershipData RetrieveMember(UUID groupID, string pricipalID)
|
||||||
|
{
|
||||||
|
MembershipData[] m = m_Membership.Get(new string[] { "GroupID", "PrincipalID" },
|
||||||
|
new string[] { groupID.ToString(), pricipalID });
|
||||||
|
if (m != null && m.Length > 0)
|
||||||
|
return m[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MembershipData[] RetrieveMemberships(string pricipalID)
|
||||||
|
{
|
||||||
|
return m_Membership.Get("PrincipalID", pricipalID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StoreMember(MembershipData data)
|
||||||
|
{
|
||||||
|
return m_Membership.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteMember(UUID groupID, string pricipalID)
|
||||||
|
{
|
||||||
|
return m_Membership.Delete(new string[] { "GroupID", "PrincipalID" },
|
||||||
|
new string[] { groupID.ToString(), pricipalID });
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MemberCount(UUID groupID)
|
||||||
|
{
|
||||||
|
return (int)m_Membership.GetCount("GroupID", groupID.ToString());
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region roles table
|
||||||
|
public bool StoreRole(RoleData data)
|
||||||
|
{
|
||||||
|
return m_Roles.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleData RetrieveRole(UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
RoleData[] data = m_Roles.Get(new string[] { "GroupID", "RoleID" },
|
||||||
|
new string[] { groupID.ToString(), roleID.ToString() });
|
||||||
|
|
||||||
|
if (data != null && data.Length > 0)
|
||||||
|
return data[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleData[] RetrieveRoles(UUID groupID)
|
||||||
|
{
|
||||||
|
//return m_Roles.RetrieveRoles(groupID);
|
||||||
|
return m_Roles.Get("GroupID", groupID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteRole(UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
return m_Roles.Delete(new string[] { "GroupID", "RoleID" },
|
||||||
|
new string[] { groupID.ToString(), roleID.ToString() });
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RoleCount(UUID groupID)
|
||||||
|
{
|
||||||
|
return (int)m_Roles.GetCount("GroupID", groupID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region rolememberhip table
|
||||||
|
public RoleMembershipData[] RetrieveRolesMembers(UUID groupID)
|
||||||
|
{
|
||||||
|
RoleMembershipData[] data = m_RoleMembership.Get("GroupID", groupID.ToString());
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "RoleID" },
|
||||||
|
new string[] { groupID.ToString(), roleID.ToString() });
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID)
|
||||||
|
{
|
||||||
|
RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "PrincipalID" },
|
||||||
|
new string[] { groupID.ToString(), principalID.ToString() });
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleMembershipData RetrieveRoleMember(UUID groupID, UUID roleID, string principalID)
|
||||||
|
{
|
||||||
|
RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "RoleID", "PrincipalID" },
|
||||||
|
new string[] { groupID.ToString(), roleID.ToString(), principalID.ToString() });
|
||||||
|
|
||||||
|
if (data != null && data.Length > 0)
|
||||||
|
return data[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RoleMemberCount(UUID groupID, UUID roleID)
|
||||||
|
{
|
||||||
|
return (int)m_RoleMembership.GetCount(new string[] { "GroupID", "RoleID" },
|
||||||
|
new string[] { groupID.ToString(), roleID.ToString() });
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StoreRoleMember(RoleMembershipData data)
|
||||||
|
{
|
||||||
|
return m_RoleMembership.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteRoleMember(RoleMembershipData data)
|
||||||
|
{
|
||||||
|
return m_RoleMembership.Delete(new string[] { "GroupID", "RoleID", "PrincipalID"},
|
||||||
|
new string[] { data.GroupID.ToString(), data.RoleID.ToString(), data.PrincipalID });
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteMemberAllRoles(UUID groupID, string principalID)
|
||||||
|
{
|
||||||
|
return m_RoleMembership.Delete(new string[] { "GroupID", "PrincipalID" },
|
||||||
|
new string[] { groupID.ToString(), principalID });
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region principals table
|
||||||
|
public bool StorePrincipal(PrincipalData data)
|
||||||
|
{
|
||||||
|
return m_Principals.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrincipalData RetrievePrincipal(string principalID)
|
||||||
|
{
|
||||||
|
PrincipalData[] p = m_Principals.Get("PrincipalID", principalID);
|
||||||
|
if (p != null && p.Length > 0)
|
||||||
|
return p[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeletePrincipal(string principalID)
|
||||||
|
{
|
||||||
|
return m_Principals.Delete("PrincipalID", principalID);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region invites table
|
||||||
|
|
||||||
|
public bool StoreInvitation(InvitationData data)
|
||||||
|
{
|
||||||
|
return m_Invites.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvitationData RetrieveInvitation(UUID inviteID)
|
||||||
|
{
|
||||||
|
InvitationData[] invites = m_Invites.Get("InviteID", inviteID.ToString());
|
||||||
|
|
||||||
|
if (invites != null && invites.Length > 0)
|
||||||
|
return invites[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvitationData RetrieveInvitation(UUID groupID, string principalID)
|
||||||
|
{
|
||||||
|
InvitationData[] invites = m_Invites.Get(new string[] { "GroupID", "PrincipalID" },
|
||||||
|
new string[] { groupID.ToString(), principalID });
|
||||||
|
|
||||||
|
if (invites != null && invites.Length > 0)
|
||||||
|
return invites[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteInvite(UUID inviteID)
|
||||||
|
{
|
||||||
|
return m_Invites.Delete("InviteID", inviteID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteOldInvites()
|
||||||
|
{
|
||||||
|
m_Invites.DeleteOld();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region notices table
|
||||||
|
|
||||||
|
public bool StoreNotice(NoticeData data)
|
||||||
|
{
|
||||||
|
return m_Notices.Store(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoticeData RetrieveNotice(UUID noticeID)
|
||||||
|
{
|
||||||
|
NoticeData[] notices = m_Notices.Get("NoticeID", noticeID.ToString());
|
||||||
|
|
||||||
|
if (notices != null && notices.Length > 0)
|
||||||
|
return notices[0];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoticeData[] RetrieveNotices(UUID groupID)
|
||||||
|
{
|
||||||
|
NoticeData[] notices = m_Notices.Get("GroupID", groupID.ToString());
|
||||||
|
|
||||||
|
return notices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteNotice(UUID noticeID)
|
||||||
|
{
|
||||||
|
return m_Notices.Delete("NoticeID", noticeID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteOldNotices()
|
||||||
|
{
|
||||||
|
m_Notices.DeleteOld();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region combinations
|
||||||
|
public MembershipData RetrievePrincipalGroupMembership(string principalID, UUID groupID)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public MembershipData[] RetrievePrincipalGroupMemberships(string principalID)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsGroupsHandler : MySQLGenericTableHandler<GroupData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsGroupsHandler(string connectionString, string realm, string store)
|
||||||
|
: base(connectionString, realm, store)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsMembershipHandler : MySQLGenericTableHandler<MembershipData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsMembershipHandler(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsRolesHandler : MySQLGenericTableHandler<RoleData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsRolesHandler(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsRoleMembershipHandler : MySQLGenericTableHandler<RoleMembershipData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsRoleMembershipHandler(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsInvitesHandler : MySQLGenericTableHandler<InvitationData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsInvitesHandler(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteOld()
|
||||||
|
{
|
||||||
|
uint now = (uint)Util.UnixTimeSinceEpoch();
|
||||||
|
|
||||||
|
using (MySqlCommand cmd = new MySqlCommand())
|
||||||
|
{
|
||||||
|
cmd.CommandText = String.Format("delete from {0} where TMStamp < ?tstamp", m_Realm);
|
||||||
|
cmd.Parameters.AddWithValue("?tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
|
||||||
|
|
||||||
|
ExecuteNonQuery(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsNoticesHandler : MySQLGenericTableHandler<NoticeData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsNoticesHandler(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteOld()
|
||||||
|
{
|
||||||
|
uint now = (uint)Util.UnixTimeSinceEpoch();
|
||||||
|
|
||||||
|
using (MySqlCommand cmd = new MySqlCommand())
|
||||||
|
{
|
||||||
|
cmd.CommandText = String.Format("delete from {0} where TMStamp < ?tstamp", m_Realm);
|
||||||
|
cmd.Parameters.AddWithValue("?tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
|
||||||
|
|
||||||
|
ExecuteNonQuery(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MySqlGroupsPrincipalsHandler : MySQLGenericTableHandler<PrincipalData>
|
||||||
|
{
|
||||||
|
protected override Assembly Assembly
|
||||||
|
{
|
||||||
|
// WARNING! Moving migrations to this assembly!!!
|
||||||
|
get { return GetType().Assembly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlGroupsPrincipalsHandler(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Data.MySQL;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
namespace OpenSim.Data.MySQL
|
||||||
|
{
|
||||||
|
public class MySQLOfflineIMData : MySQLGenericTableHandler<OfflineIMData>, IOfflineIMData
|
||||||
|
{
|
||||||
|
public MySQLOfflineIMData(string connectionString, string realm)
|
||||||
|
: base(connectionString, realm, "IM_Store")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteOld()
|
||||||
|
{
|
||||||
|
uint now = (uint)Util.UnixTimeSinceEpoch();
|
||||||
|
|
||||||
|
using (MySqlCommand cmd = new MySqlCommand())
|
||||||
|
{
|
||||||
|
cmd.CommandText = String.Format("delete from {0} where TMStamp < ?tstamp", m_Realm);
|
||||||
|
cmd.Parameters.AddWithValue("?tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
|
||||||
|
|
||||||
|
ExecuteNonQuery(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.7.6.*")]
|
[assembly : AssemblyVersion("0.7.6.*")]
|
||||||
[assembly : AssemblyFileVersion("0.6.5.0")]
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
:VERSION 1 # --------------------------
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE `im_offline` (
|
||||||
|
`ID` MEDIUMINT NOT NULL AUTO_INCREMENT,
|
||||||
|
`PrincipalID` char(36) NOT NULL default '',
|
||||||
|
`Message` text NOT NULL,
|
||||||
|
`TMStamp` timestamp NOT NULL,
|
||||||
|
PRIMARY KEY (`ID`),
|
||||||
|
KEY `PrincipalID` (`PrincipalID`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
:VERSION 2 # --------------------------
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
INSERT INTO `im_offline` SELECT * from `diva_im_offline`;
|
||||||
|
DROP TABLE `diva_im_offline`;
|
||||||
|
DELETE FROM `migrations` WHERE name='diva_im_Store';
|
||||||
|
|
||||||
|
COMMIT;
|
|
@ -0,0 +1,115 @@
|
||||||
|
:VERSION 1 # --------------------------
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_groups` (
|
||||||
|
`GroupID` char(36) NOT NULL default '',
|
||||||
|
`Location` varchar(255) NOT NULL default '',
|
||||||
|
`Name` varchar(255) NOT NULL default '',
|
||||||
|
`Charter` text NOT NULL,
|
||||||
|
`InsigniaID` char(36) NOT NULL default '',
|
||||||
|
`FounderID` char(36) NOT NULL default '',
|
||||||
|
`MembershipFee` int(11) NOT NULL default '0',
|
||||||
|
`OpenEnrollment` varchar(255) NOT NULL default '',
|
||||||
|
`ShowInList` int(4) NOT NULL default '0',
|
||||||
|
`AllowPublish` int(4) NOT NULL default '0',
|
||||||
|
`MaturePublish` int(4) NOT NULL default '0',
|
||||||
|
`OwnerRoleID` char(36) NOT NULL default '',
|
||||||
|
PRIMARY KEY (`GroupID`),
|
||||||
|
UNIQUE KEY `Name` (`Name`),
|
||||||
|
FULLTEXT KEY `Name_2` (`Name`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_membership` (
|
||||||
|
`GroupID`char(36) NOT NULL default '',
|
||||||
|
`PrincipalID` VARCHAR(255) NOT NULL default '',
|
||||||
|
`SelectedRoleID` char(36) NOT NULL default '',
|
||||||
|
`Contribution` int(11) NOT NULL default '0',
|
||||||
|
`ListInProfile` int(4) NOT NULL default '1',
|
||||||
|
`AcceptNotices` int(4) NOT NULL default '1',
|
||||||
|
`AccessToken` char(36) NOT NULL default '',
|
||||||
|
PRIMARY KEY (`GroupID`,`PrincipalID`),
|
||||||
|
KEY `PrincipalID` (`PrincipalID`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_roles` (
|
||||||
|
`GroupID` char(36) NOT NULL default '',
|
||||||
|
`RoleID` char(36) NOT NULL default '',
|
||||||
|
`Name` varchar(255) NOT NULL default '',
|
||||||
|
`Description` varchar(255) NOT NULL default '',
|
||||||
|
`Title` varchar(255) NOT NULL default '',
|
||||||
|
`Powers` bigint(20) unsigned NOT NULL default '0',
|
||||||
|
PRIMARY KEY (`GroupID`,`RoleID`),
|
||||||
|
KEY `GroupID` (`GroupID`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_rolemembership` (
|
||||||
|
`GroupID` char(36) NOT NULL default '',
|
||||||
|
`RoleID` char(36) NOT NULL default '',
|
||||||
|
`PrincipalID` VARCHAR(255) NOT NULL default '',
|
||||||
|
PRIMARY KEY (`GroupID`,`RoleID`,`PrincipalID`),
|
||||||
|
KEY `PrincipalID` (`PrincipalID`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_invites` (
|
||||||
|
`InviteID` char(36) NOT NULL default '',
|
||||||
|
`GroupID` char(36) NOT NULL default '',
|
||||||
|
`RoleID` char(36) NOT NULL default '',
|
||||||
|
`PrincipalID` VARCHAR(255) NOT NULL default '',
|
||||||
|
`TMStamp` timestamp NOT NULL,
|
||||||
|
PRIMARY KEY (`InviteID`),
|
||||||
|
UNIQUE KEY `PrincipalGroup` (`GroupID`,`PrincipalID`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_notices` (
|
||||||
|
`GroupID` char(36) NOT NULL default '',
|
||||||
|
`NoticeID` char(36) NOT NULL default '',
|
||||||
|
`TMStamp` int(10) unsigned NOT NULL default '0',
|
||||||
|
`FromName` varchar(255) NOT NULL default '',
|
||||||
|
`Subject` varchar(255) NOT NULL default '',
|
||||||
|
`Message` text NOT NULL,
|
||||||
|
`HasAttachment` int(4) NOT NULL default '0',
|
||||||
|
`AttachmentType` int(4) NOT NULL default '0',
|
||||||
|
`AttachmentName` varchar(128) NOT NULL default '',
|
||||||
|
`AttachmentItemID` char(36) NOT NULL default '',
|
||||||
|
`AttachmentOwnerID` varchar(255) NOT NULL default '',
|
||||||
|
PRIMARY KEY (`NoticeID`),
|
||||||
|
KEY `GroupID` (`GroupID`),
|
||||||
|
KEY `TMStamp` (`TMStamp`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
CREATE TABLE `os_groups_principals` (
|
||||||
|
`PrincipalID` VARCHAR(255) NOT NULL default '',
|
||||||
|
`ActiveGroupID` char(36) NOT NULL default '',
|
||||||
|
PRIMARY KEY (`PrincipalID`)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
:VERSION 2 # --------------------------
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
INSERT INTO `os_groups_groups` SELECT * from `diva_groups_groups`;
|
||||||
|
DROP TABLE `diva_groups_groups`;
|
||||||
|
INSERT INTO `os_groups_membership` SELECT * from `diva_groups_membership`;
|
||||||
|
DROP TABLE `diva_groups_membership`;
|
||||||
|
INSERT INTO `os_groups_roles` SELECT * from `diva_groups_roles`;
|
||||||
|
DROP TABLE `diva_groups_roles`;
|
||||||
|
INSERT INTO `os_groups_rolemembership` SELECT * from `diva_groups_rolemembership`;
|
||||||
|
DROP TABLE `diva_groups_rolemembership`;
|
||||||
|
INSERT INTO `os_groups_invites` SELECT * from `diva_groups_invites`;
|
||||||
|
DROP TABLE `diva_groups_invites`;
|
||||||
|
INSERT INTO `os_groups_notices` SELECT * from `diva_groups_notices`;
|
||||||
|
DROP TABLE `diva_groups_notices`;
|
||||||
|
INSERT INTO `os_groups_principals` SELECT * from `diva_groups_principals`;
|
||||||
|
DROP TABLE `diva_groups_principals`;
|
||||||
|
|
||||||
|
DELETE FROM `migrations` WHERE name='diva_im_Store';
|
||||||
|
|
||||||
|
COMMIT;
|
|
@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.7.6.*")]
|
[assembly : AssemblyVersion("0.7.6.*")]
|
||||||
[assembly : AssemblyFileVersion("0.6.5.0")]
|
|
||||||
|
|
|
@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.7.6.*")]
|
[assembly : AssemblyVersion("0.7.6.*")]
|
||||||
[assembly : AssemblyFileVersion("0.6.5.0")]
|
|
||||||
|
|
|
@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.7.6.*")]
|
[assembly : AssemblyVersion("0.7.6.*")]
|
||||||
[assembly : AssemblyFileVersion("0.6.5.0")]
|
|
||||||
|
|
|
@ -60,4 +60,3 @@ using System.Runtime.InteropServices;
|
||||||
//
|
//
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.7.6.*")]
|
[assembly : AssemblyVersion("0.7.6.*")]
|
||||||
[assembly : AssemblyFileVersion("0.6.5.0")]
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
[assembly : AssemblyVersion("0.7.6.*")]
|
[assembly : AssemblyVersion("0.7.6.*")]
|
||||||
[assembly : AssemblyFileVersion("0.6.5.0")]
|
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -49,14 +49,14 @@ namespace OpenSim.Framework.Console
|
||||||
= @"Each component of the coord is comma separated. There must be no spaces between the commas.
|
= @"Each component of the coord is comma separated. There must be no spaces between the commas.
|
||||||
If you don't care about the z component you can simply omit it.
|
If you don't care about the z component you can simply omit it.
|
||||||
If you don't care about the x or y components then you can leave them blank (though a comma is still required)
|
If you don't care about the x or y components then you can leave them blank (though a comma is still required)
|
||||||
If you want to specify the maxmimum value of a component then you can use ~ instead of a number
|
If you want to specify the maximum value of a component then you can use ~ instead of a number
|
||||||
If you want to specify the minimum value of a component then you can use -~ instead of a number
|
If you want to specify the minimum value of a component then you can use -~ instead of a number
|
||||||
e.g.
|
e.g.
|
||||||
delete object pos 20,20,20 to 40,40,40
|
show object pos 20,20,20 to 40,40,40
|
||||||
delete object pos 20,20 to 40,40
|
delete object pos 20,20 to 40,40
|
||||||
delete object pos ,20,20 to ,40,40
|
show object pos ,20,20 to ,40,40
|
||||||
delete object pos ,,30 to ,,~
|
delete object pos ,,30 to ,,~
|
||||||
delete object pos ,,-~ to ,,30";
|
show object pos ,,-~ to ,,30";
|
||||||
|
|
||||||
public const string MinRawConsoleVectorValue = "-~";
|
public const string MinRawConsoleVectorValue = "-~";
|
||||||
public const string MaxRawConsoleVectorValue = "~";
|
public const string MaxRawConsoleVectorValue = "~";
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
|
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
|
||||||
namespace OpenSim.Framework.Monitoring
|
namespace OpenSim.Framework.Monitoring
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -100,5 +102,29 @@ Asset requests yesterday : {3} ({4} per hour) of which {5} were not found",
|
||||||
AssetRequestsToday, assetRequestsTodayPerHour, AssetRequestsNotFoundToday,
|
AssetRequestsToday, assetRequestsTodayPerHour, AssetRequestsNotFoundToday,
|
||||||
AssetRequestsYesterday, assetRequestsYesterdayPerHour, AssetRequestsNotFoundYesterday);
|
AssetRequestsYesterday, assetRequestsYesterdayPerHour, AssetRequestsNotFoundYesterday);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string XReport(string uptime, string version)
|
||||||
|
{
|
||||||
|
return OSDParser.SerializeJsonString(OReport(uptime, version));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override OSDMap OReport(string uptime, string version)
|
||||||
|
{
|
||||||
|
double elapsedHours = (DateTime.Now - startTime).TotalHours;
|
||||||
|
if (elapsedHours <= 0) { elapsedHours = 1; } // prevent divide by zero
|
||||||
|
|
||||||
|
long assetRequestsTodayPerHour = (long)Math.Round(AssetRequestsToday / elapsedHours);
|
||||||
|
long assetRequestsYesterdayPerHour = (long)Math.Round(AssetRequestsYesterday / 24.0);
|
||||||
|
|
||||||
|
OSDMap ret = new OSDMap();
|
||||||
|
ret.Add("AssetRequestsToday", OSD.FromLong(AssetRequestsToday));
|
||||||
|
ret.Add("AssetRequestsTodayPerHour", OSD.FromLong(assetRequestsTodayPerHour));
|
||||||
|
ret.Add("AssetRequestsNotFoundToday", OSD.FromLong(AssetRequestsNotFoundToday));
|
||||||
|
ret.Add("AssetRequestsYesterday", OSD.FromLong(AssetRequestsYesterday));
|
||||||
|
ret.Add("AssetRequestsYesterdayPerHour", OSD.FromLong(assetRequestsYesterdayPerHour));
|
||||||
|
ret.Add("AssetRequestsNotFoundYesterday", OSD.FromLong(assetRequestsNotFoundYesterday));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,5 +80,12 @@ namespace OpenSim.Framework.Monitoring
|
||||||
{
|
{
|
||||||
return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ;
|
return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual OSDMap OReport(string uptime, string version)
|
||||||
|
{
|
||||||
|
OSDMap ret = new OSDMap();
|
||||||
|
ret.Add("TotalMemory", new OSDReal(Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
|
||||||
namespace OpenSim.Framework.Monitoring
|
namespace OpenSim.Framework.Monitoring
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -45,5 +47,12 @@ namespace OpenSim.Framework.Monitoring
|
||||||
/// A <see cref="System.String"/>
|
/// A <see cref="System.String"/>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
string XReport(string uptime, string version);
|
string XReport(string uptime, string version);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Report back collected statistical information as an OSDMap of key/values
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// </returns>
|
||||||
|
OSDMap OReport(string uptime, string version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -404,6 +404,15 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public override string XReport(string uptime, string version)
|
public override string XReport(string uptime, string version)
|
||||||
|
{
|
||||||
|
return OSDParser.SerializeJsonString(OReport(uptime, version));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Report back collected statistical information as an OSDMap
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override OSDMap OReport(string uptime, string version)
|
||||||
{
|
{
|
||||||
OSDMap args = new OSDMap(30);
|
OSDMap args = new OSDMap(30);
|
||||||
// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache));
|
// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache));
|
||||||
|
@ -442,12 +451,10 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||||
args["Uptime"] = OSD.FromString (uptime);
|
args["Uptime"] = OSD.FromString (uptime);
|
||||||
args["Version"] = OSD.FromString (version);
|
args["Version"] = OSD.FromString (version);
|
||||||
|
|
||||||
string strBuffer = "";
|
return args;
|
||||||
strBuffer = OSDParser.SerializeJsonString(args);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return strBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pull packet queue stats from packet queues and report
|
/// Pull packet queue stats from packet queues and report
|
||||||
|
@ -474,5 +481,11 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OSDMap OReport(string uptime, string version)
|
||||||
|
{
|
||||||
|
OSDMap ret = new OSDMap();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
|
||||||
|
namespace OpenSim.Framework.Monitoring
|
||||||
|
{
|
||||||
|
// Create a time histogram of events. The histogram is built in a wrap-around
|
||||||
|
// array of equally distributed buckets.
|
||||||
|
// For instance, a minute long histogram of second sized buckets would be:
|
||||||
|
// new EventHistogram(60, 1000)
|
||||||
|
public class EventHistogram
|
||||||
|
{
|
||||||
|
private int m_timeBase;
|
||||||
|
private int m_numBuckets;
|
||||||
|
private int m_bucketMilliseconds;
|
||||||
|
private int m_lastBucket;
|
||||||
|
private int m_totalHistogramMilliseconds;
|
||||||
|
private long[] m_histogram;
|
||||||
|
private object histoLock = new object();
|
||||||
|
|
||||||
|
public EventHistogram(int numberOfBuckets, int millisecondsPerBucket)
|
||||||
|
{
|
||||||
|
m_numBuckets = numberOfBuckets;
|
||||||
|
m_bucketMilliseconds = millisecondsPerBucket;
|
||||||
|
m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds;
|
||||||
|
|
||||||
|
m_histogram = new long[m_numBuckets];
|
||||||
|
Zero();
|
||||||
|
m_lastBucket = 0;
|
||||||
|
m_timeBase = Util.EnvironmentTickCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Event()
|
||||||
|
{
|
||||||
|
this.Event(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record an event at time 'now' in the histogram.
|
||||||
|
public void Event(int cnt)
|
||||||
|
{
|
||||||
|
lock (histoLock)
|
||||||
|
{
|
||||||
|
// The time as displaced from the base of the histogram
|
||||||
|
int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase);
|
||||||
|
|
||||||
|
// If more than the total time of the histogram, we just start over
|
||||||
|
if (bucketTime > m_totalHistogramMilliseconds)
|
||||||
|
{
|
||||||
|
Zero();
|
||||||
|
m_lastBucket = 0;
|
||||||
|
m_timeBase = Util.EnvironmentTickCount();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// To which bucket should we add this event?
|
||||||
|
int bucket = bucketTime / m_bucketMilliseconds;
|
||||||
|
|
||||||
|
// Advance m_lastBucket to the new bucket. Zero any buckets skipped over.
|
||||||
|
while (bucket != m_lastBucket)
|
||||||
|
{
|
||||||
|
// Zero from just after the last bucket to the new bucket or the end
|
||||||
|
for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++)
|
||||||
|
{
|
||||||
|
m_histogram[jj] = 0;
|
||||||
|
}
|
||||||
|
m_lastBucket = bucket;
|
||||||
|
// If the new bucket is off the end, wrap around to the beginning
|
||||||
|
if (bucket > m_numBuckets)
|
||||||
|
{
|
||||||
|
bucket -= m_numBuckets;
|
||||||
|
m_lastBucket = 0;
|
||||||
|
m_histogram[m_lastBucket] = 0;
|
||||||
|
m_timeBase += m_totalHistogramMilliseconds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_histogram[m_lastBucket] += cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a copy of the current histogram
|
||||||
|
public long[] GetHistogram()
|
||||||
|
{
|
||||||
|
long[] ret = new long[m_numBuckets];
|
||||||
|
lock (histoLock)
|
||||||
|
{
|
||||||
|
int indx = m_lastBucket + 1;
|
||||||
|
for (int ii = 0; ii < m_numBuckets; ii++, indx++)
|
||||||
|
{
|
||||||
|
if (indx >= m_numBuckets)
|
||||||
|
indx = 0;
|
||||||
|
ret[ii] = m_histogram[indx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a copy of the current histogram
|
||||||
|
public OSDArray GetHistogramAsOSDArray()
|
||||||
|
{
|
||||||
|
OSDArray ret = new OSDArray(m_numBuckets);
|
||||||
|
lock (histoLock)
|
||||||
|
{
|
||||||
|
int indx = m_lastBucket + 1;
|
||||||
|
for (int ii = 0; ii < m_numBuckets; ii++, indx++)
|
||||||
|
{
|
||||||
|
if (indx >= m_numBuckets)
|
||||||
|
indx = 0;
|
||||||
|
ret[ii] = OSD.FromLong(m_histogram[indx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zero out the histogram
|
||||||
|
public void Zero()
|
||||||
|
{
|
||||||
|
lock (histoLock)
|
||||||
|
{
|
||||||
|
for (int ii = 0; ii < m_numBuckets; ii++)
|
||||||
|
m_histogram[ii] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A statistic that wraps a counter.
|
||||||
|
// Built this way mostly so histograms and history can be created.
|
||||||
|
public class CounterStat : Stat
|
||||||
|
{
|
||||||
|
private SortedDictionary<string, EventHistogram> m_histograms;
|
||||||
|
private object counterLock = new object();
|
||||||
|
|
||||||
|
public CounterStat(
|
||||||
|
string shortName,
|
||||||
|
string name,
|
||||||
|
string description,
|
||||||
|
string unitName,
|
||||||
|
string category,
|
||||||
|
string container,
|
||||||
|
StatVerbosity verbosity)
|
||||||
|
: base(shortName, name, description, unitName, category, container, StatType.Push, null, verbosity)
|
||||||
|
{
|
||||||
|
m_histograms = new SortedDictionary<string, EventHistogram>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Histograms are presumably added at intialization time and the list does not change thereafter.
|
||||||
|
// Thus no locking of the histogram list.
|
||||||
|
public void AddHistogram(string histoName, EventHistogram histo)
|
||||||
|
{
|
||||||
|
m_histograms.Add(histoName, histo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void ProcessHistogram(string name, EventHistogram histo);
|
||||||
|
public void ForEachHistogram(ProcessHistogram process)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, EventHistogram> kvp in m_histograms)
|
||||||
|
{
|
||||||
|
process(kvp.Key, kvp.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Event()
|
||||||
|
{
|
||||||
|
this.Event(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the underlying counter.
|
||||||
|
public void Event(int cnt)
|
||||||
|
{
|
||||||
|
lock (counterLock)
|
||||||
|
{
|
||||||
|
base.Value += cnt;
|
||||||
|
|
||||||
|
foreach (EventHistogram histo in m_histograms.Values)
|
||||||
|
{
|
||||||
|
histo.Event(cnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,12 +29,14 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
|
||||||
namespace OpenSim.Framework.Monitoring
|
namespace OpenSim.Framework.Monitoring
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Holds individual statistic details
|
/// Holds individual statistic details
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Stat
|
public class Stat : IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Category of this stat (e.g. cache, scene, etc).
|
/// Category of this stat (e.g. cache, scene, etc).
|
||||||
|
@ -181,6 +183,12 @@ namespace OpenSim.Framework.Monitoring
|
||||||
Verbosity = verbosity;
|
Verbosity = verbosity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IDisposable.Dispose()
|
||||||
|
public virtual void Dispose()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Record a value in the sample set.
|
/// Record a value in the sample set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -210,6 +218,20 @@ namespace OpenSim.Framework.Monitoring
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual OSDMap ToOSDMap()
|
||||||
|
{
|
||||||
|
OSDMap ret = new OSDMap();
|
||||||
|
ret.Add("Category", OSD.FromString(Category));
|
||||||
|
ret.Add("Container", OSD.FromString(Container));
|
||||||
|
ret.Add("ShortName", OSD.FromString(ShortName));
|
||||||
|
ret.Add("Name", OSD.FromString(Name));
|
||||||
|
ret.Add("Description", OSD.FromString(Description));
|
||||||
|
ret.Add("UnitName", OSD.FromString(UnitName));
|
||||||
|
ret.Add("Value", OSD.FromReal(Value));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
protected void AppendMeasuresOfInterest(StringBuilder sb)
|
protected void AppendMeasuresOfInterest(StringBuilder sb)
|
||||||
{
|
{
|
||||||
if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime)
|
if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime)
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
|
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
|
||||||
namespace OpenSim.Framework.Monitoring
|
namespace OpenSim.Framework.Monitoring
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -88,5 +90,21 @@ namespace OpenSim.Framework.Monitoring
|
||||||
Logouts total : {3}",
|
Logouts total : {3}",
|
||||||
SuccessfulLogins, SuccessfulLoginsToday, SuccessfulLoginsYesterday, Logouts);
|
SuccessfulLogins, SuccessfulLoginsToday, SuccessfulLoginsYesterday, Logouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string XReport(string uptime, string version)
|
||||||
|
{
|
||||||
|
return OSDParser.SerializeJsonString(OReport(uptime, version));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override OSDMap OReport(string uptime, string version)
|
||||||
|
{
|
||||||
|
OSDMap ret = new OSDMap();
|
||||||
|
ret.Add("SuccessfulLogins", OSD.FromInteger(SuccessfulLogins));
|
||||||
|
ret.Add("SuccessfulLoginsToday", OSD.FromInteger(SuccessfulLoginsToday));
|
||||||
|
ret.Add("SuccessfulLoginsYesterday", OSD.FromInteger(SuccessfulLoginsYesterday));
|
||||||
|
ret.Add("Logouts", OSD.FromInteger(Logouts));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -875,7 +875,7 @@ namespace OpenSim.Framework
|
||||||
return FileName;
|
return FileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nini (config) related Methods
|
#region Nini (config) related Methods
|
||||||
public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName)
|
public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName)
|
||||||
{
|
{
|
||||||
if (!File.Exists(fileName))
|
if (!File.Exists(fileName))
|
||||||
|
@ -898,6 +898,26 @@ namespace OpenSim.Framework
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetConfigVarWithDefaultSection(IConfigSource config, string varname, string section)
|
||||||
|
{
|
||||||
|
// First, check the Startup section, the default section
|
||||||
|
IConfig cnf = config.Configs["Startup"];
|
||||||
|
if (cnf == null)
|
||||||
|
return string.Empty;
|
||||||
|
string val = cnf.GetString(varname, string.Empty);
|
||||||
|
|
||||||
|
// Then check for an overwrite of the default in the given section
|
||||||
|
if (!string.IsNullOrEmpty(section))
|
||||||
|
{
|
||||||
|
cnf = config.Configs[section];
|
||||||
|
if (cnf != null)
|
||||||
|
val = cnf.GetString(varname, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
public static float Clip(float x, float min, float max)
|
public static float Clip(float x, float min, float max)
|
||||||
{
|
{
|
||||||
return Math.Min(Math.Max(x, min), max);
|
return Math.Min(Math.Max(x, min), max);
|
||||||
|
|
|
@ -1445,7 +1445,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
string param, IOSHttpRequest httpRequest,
|
string param, IOSHttpRequest httpRequest,
|
||||||
IOSHttpResponse httpResponse)
|
IOSHttpResponse httpResponse)
|
||||||
{
|
{
|
||||||
OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
|
// OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
|
||||||
OSDMap resp = new OSDMap();
|
OSDMap resp = new OSDMap();
|
||||||
|
|
||||||
OSDMap accessPrefs = new OSDMap();
|
OSDMap accessPrefs = new OSDMap();
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -56,8 +56,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionConsoleModule")]
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionConsoleModule")]
|
||||||
public class RegionConsoleModule : INonSharedRegionModule, IRegionConsole
|
public class RegionConsoleModule : INonSharedRegionModule, IRegionConsole
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log =
|
// private static readonly ILog m_log =
|
||||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
private IEventQueue m_eventQueue;
|
private IEventQueue m_eventQueue;
|
||||||
|
@ -164,8 +164,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
|
|
||||||
public class ConsoleHandler : BaseStreamHandler
|
public class ConsoleHandler : BaseStreamHandler
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log =
|
// private static readonly ILog m_log =
|
||||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private RegionConsoleModule m_consoleModule;
|
private RegionConsoleModule m_consoleModule;
|
||||||
private UUID m_agentID;
|
private UUID m_agentID;
|
||||||
|
|
|
@ -3892,6 +3892,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
part.Shape.LightEntry = false;
|
part.Shape.LightEntry = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh))
|
||||||
|
{
|
||||||
|
// Ensure that mesh has at least 8 valid faces
|
||||||
|
part.Shape.ProfileBegin = 12500;
|
||||||
|
part.Shape.ProfileEnd = 0;
|
||||||
|
part.Shape.ProfileHollow = 27500;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12448,6 +12456,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
return String.Empty;
|
return String.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OSDMap OReport(string uptime, string version)
|
||||||
|
{
|
||||||
|
return new OSDMap();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Make an asset request to the asset service in response to a client request.
|
/// Make an asset request to the asset service in response to a client request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -1090,7 +1090,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp);
|
bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp);
|
||||||
outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt");
|
outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "incomplete");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
|
||||||
{
|
{
|
||||||
m_Enabled = true;
|
m_Enabled = true;
|
||||||
|
|
||||||
m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", string.Empty);
|
m_ThisGridURL = Util.GetConfigVarWithDefaultSection(config, "GatekeeperURI", "Messaging");
|
||||||
|
// Legacy. Remove soon!
|
||||||
|
m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", m_ThisGridURL);
|
||||||
m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name);
|
m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,12 +88,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"];
|
IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"];
|
||||||
if (thisModuleConfig != null)
|
if (thisModuleConfig != null)
|
||||||
{
|
{
|
||||||
// legacy configuration [obsolete]
|
m_HomeURI = Util.GetConfigVarWithDefaultSection(source, "HomeURI", "HGInventoryAccessModule");
|
||||||
m_HomeURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty);
|
|
||||||
// preferred
|
|
||||||
m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI);
|
|
||||||
m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true);
|
m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true);
|
||||||
m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty);
|
m_ThisGatekeeper = Util.GetConfigVarWithDefaultSection(source, "GatekeeperURI", "HGInventoryAccessModule");
|
||||||
|
// Legacy. Renove soon!
|
||||||
|
m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", m_ThisGatekeeper);
|
||||||
m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true);
|
m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -52,6 +52,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
|
||||||
private TimeSpan m_logFileLife;
|
private TimeSpan m_logFileLife;
|
||||||
private DateTime m_logFileEndTime;
|
private DateTime m_logFileEndTime;
|
||||||
private Object m_logFileWriteLock = new Object();
|
private Object m_logFileWriteLock = new Object();
|
||||||
|
private bool m_flushWrite;
|
||||||
|
|
||||||
// set externally when debugging. If let 'null', this does not write any error messages.
|
// set externally when debugging. If let 'null', this does not write any error messages.
|
||||||
public ILog ErrorLogger = null;
|
public ILog ErrorLogger = null;
|
||||||
|
@ -73,7 +74,9 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
|
||||||
/// <param name="dir">The directory to create the log file in. May be 'null' for default.</param>
|
/// <param name="dir">The directory to create the log file in. May be 'null' for default.</param>
|
||||||
/// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param>
|
/// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param>
|
||||||
/// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param>
|
/// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param>
|
||||||
public LogWriter(string dir, string headr, int maxFileTime)
|
/// <param name="flushWrite">Whether to do a flush after every log write. Best left off but
|
||||||
|
/// if one is looking for a crash, this is a good thing to turn on.</param>
|
||||||
|
public LogWriter(string dir, string headr, int maxFileTime, bool flushWrite)
|
||||||
{
|
{
|
||||||
m_logDirectory = dir == null ? "." : dir;
|
m_logDirectory = dir == null ? "." : dir;
|
||||||
|
|
||||||
|
@ -86,8 +89,14 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
|
||||||
m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0);
|
m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0);
|
||||||
m_logFileEndTime = DateTime.Now + m_logFileLife;
|
m_logFileEndTime = DateTime.Now + m_logFileLife;
|
||||||
|
|
||||||
|
m_flushWrite = flushWrite;
|
||||||
|
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
}
|
}
|
||||||
|
// Constructor that assumes flushWrite is off.
|
||||||
|
public LogWriter(string dir, string headr, int maxFileTime) : this(dir, headr, maxFileTime, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
@ -153,6 +162,8 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
|
||||||
buff.Append(line);
|
buff.Append(line);
|
||||||
buff.Append("\r\n");
|
buff.Append("\r\n");
|
||||||
m_logFile.Write(buff.ToString());
|
m_logFile.Write(buff.ToString());
|
||||||
|
if (m_flushWrite)
|
||||||
|
m_logFile.Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ using Mono.Addins;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
||||||
[assembly: Addin("OpenSim.Region.CoreModules", "0.1")]
|
[assembly: Addin("OpenSim.Region.CoreModules", "0.1")]
|
||||||
[assembly: AddinDependency("OpenSim", "0.5")]
|
[assembly: AddinDependency("OpenSim", "0.5")]
|
||||||
|
|
|
@ -416,7 +416,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
|
|
||||||
if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
|
if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
|
||||||
{
|
{
|
||||||
m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector);
|
m_console.OutputFormat("Error: Start vector '{0}' does not have a valid format", rawConsoleStartVector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,7 +425,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
|
|
||||||
if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
|
if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
|
||||||
{
|
{
|
||||||
m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector);
|
m_console.OutputFormat("Error: End vector '{0}' does not have a valid format", rawConsoleEndVector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -896,17 +896,17 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
|
|
||||||
if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
|
if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
|
||||||
{
|
{
|
||||||
m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector);
|
m_console.OutputFormat("Error: Start vector '{0}' does not have a valid format", rawConsoleStartVector);
|
||||||
endVector = Vector3.Zero;
|
endVector = Vector3.Zero;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single();
|
string rawConsoleEndVector = rawComponents.Skip(2).Take(1).Single();
|
||||||
|
|
||||||
if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
|
if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
|
||||||
{
|
{
|
||||||
m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector);
|
m_console.OutputFormat("Error: End vector '{0}' does not have a valid format", rawConsoleEndVector);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,9 +113,16 @@ namespace OpenSim.Region.DataSnapshot
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_enabled = config.Configs["DataSnapshot"].GetBoolean("index_sims", m_enabled);
|
m_enabled = config.Configs["DataSnapshot"].GetBoolean("index_sims", m_enabled);
|
||||||
|
string gatekeeper = Util.GetConfigVarWithDefaultSection(config, "GatekeeperURI", "GridService");
|
||||||
|
// Legacy. Remove soon!
|
||||||
|
if (string.IsNullOrEmpty(gatekeeper))
|
||||||
|
{
|
||||||
IConfig conf = config.Configs["GridService"];
|
IConfig conf = config.Configs["GridService"];
|
||||||
if (conf != null)
|
if (conf != null)
|
||||||
m_gridinfo.Add("gatekeeperURL", conf.GetString("Gatekeeper", String.Empty));
|
gatekeeper = conf.GetString("Gatekeeper", gatekeeper);
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(gatekeeper))
|
||||||
|
m_gridinfo.Add("gatekeeperURL", gatekeeper);
|
||||||
|
|
||||||
m_gridinfo.Add(
|
m_gridinfo.Add(
|
||||||
"name", config.Configs["DataSnapshot"].GetString("gridname", "the lost continent of hippo"));
|
"name", config.Configs["DataSnapshot"].GetString("gridname", "the lost continent of hippo"));
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -51,7 +51,6 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
|
|
||||||
JsonStoreNodeType GetPathType(UUID storeID, string path);
|
JsonStoreNodeType GetPathType(UUID storeID, string path);
|
||||||
bool TestStore(UUID storeID);
|
bool TestStore(UUID storeID);
|
||||||
bool TestPath(UUID storeID, string path, bool useJson);
|
|
||||||
|
|
||||||
bool SetValue(UUID storeID, string path, string value, bool useJson);
|
bool SetValue(UUID storeID, string path, string value, bool useJson);
|
||||||
bool RemoveValue(UUID storeID, string path);
|
bool RemoveValue(UUID storeID, string path);
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -2075,7 +2075,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// Get terrain height for sub-region in a megaregion if necessary
|
// Get terrain height for sub-region in a megaregion if necessary
|
||||||
int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X);
|
int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X);
|
||||||
int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y);
|
int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y);
|
||||||
UUID target_regionID = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y).RegionID;
|
GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
|
||||||
|
// If X and Y is NaN, target_region will be null
|
||||||
|
if (target_region == null)
|
||||||
|
return;
|
||||||
|
UUID target_regionID = target_region.RegionID;
|
||||||
Scene targetScene = m_scene;
|
Scene targetScene = m_scene;
|
||||||
|
|
||||||
if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
|
if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
|
||||||
|
|
|
@ -222,7 +222,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
|
||||||
{
|
{
|
||||||
bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(sp);
|
bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(sp);
|
||||||
MainConsole.Instance.OutputFormat(
|
MainConsole.Instance.OutputFormat(
|
||||||
"{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt");
|
"{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "incomplete");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ using Mono.Addins;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
||||||
[assembly: Addin("OpenSim.Region.OptionalModules", "0.1")]
|
[assembly: Addin("OpenSim.Region.OptionalModules", "0.1")]
|
||||||
[assembly: AddinDependency("OpenSim", "0.5")]
|
[assembly: AddinDependency("OpenSim", "0.5")]
|
||||||
|
|
|
@ -84,11 +84,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])");
|
protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])");
|
||||||
|
|
||||||
// extract the internals of an array reference
|
// extract the internals of an array reference
|
||||||
protected static Regex m_SimpleArrayPattern = new Regex("\\[([0-9]+)\\]");
|
protected static Regex m_SimpleArrayPattern = new Regex("^\\[([0-9]+)\\]$");
|
||||||
protected static Regex m_ArrayPattern = new Regex("\\[([0-9]+|\\+)\\]");
|
protected static Regex m_ArrayPattern = new Regex("^\\[([0-9]+|\\+)\\]$");
|
||||||
|
|
||||||
// extract the internals of a has reference
|
// extract the internals of a has reference
|
||||||
protected static Regex m_HashPattern = new Regex("{([^}]+)}");
|
protected static Regex m_HashPattern = new Regex("^{([^}]+)}$");
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -168,28 +168,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
return JsonStoreNodeType.Undefined;
|
return JsonStoreNodeType.Undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
// -----------------------------------------------------------------
|
|
||||||
public bool TestPath(string expr, bool useJson)
|
|
||||||
{
|
|
||||||
Stack<string> path;
|
|
||||||
if (! ParsePathExpression(expr,out path))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
OSD result = ProcessPathExpression(ValueStore,path);
|
|
||||||
|
|
||||||
if (result == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (useJson || OSDBaseType(result.Type))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|
|
@ -297,38 +297,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
return JsonStoreNodeType.Undefined;
|
return JsonStoreNodeType.Undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
// -----------------------------------------------------------------
|
|
||||||
public bool TestPath(UUID storeID, string path, bool useJson)
|
|
||||||
{
|
|
||||||
if (! m_enabled) return false;
|
|
||||||
|
|
||||||
JsonStore map = null;
|
|
||||||
lock (m_JsonValueStore)
|
|
||||||
{
|
|
||||||
if (! m_JsonValueStore.TryGetValue(storeID,out map))
|
|
||||||
{
|
|
||||||
m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
lock (map)
|
|
||||||
return map.TestPath(path,useJson);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
m_log.Error(string.Format("[JsonStore]: Path test failed for {0} in {1}", path, storeID), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|
|
@ -168,32 +168,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
{
|
{
|
||||||
m_comms.RegisterScriptInvocations(this);
|
m_comms.RegisterScriptInvocations(this);
|
||||||
m_comms.RegisterConstants(this);
|
m_comms.RegisterConstants(this);
|
||||||
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonCreateStore");
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonAttachObjectStore");
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonDestroyStore");
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonTestStore");
|
|
||||||
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonReadNotecard");
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonWriteNotecard");
|
|
||||||
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonTestPathList");
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonTestPath");
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonTestPathJson");
|
|
||||||
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonGetValue");
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonGetValueJson");
|
|
||||||
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonTakeValue");
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonTakeValueJson");
|
|
||||||
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonReadValue");
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonReadValueJson");
|
|
||||||
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonSetValue");
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonSetValueJson");
|
|
||||||
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonRemoveValue");
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -341,18 +315,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
return (int)m_store.GetPathType(storeID,path);
|
return (int)m_store.GetPathType(storeID,path);
|
||||||
}
|
}
|
||||||
|
|
||||||
[ScriptInvocation]
|
|
||||||
public int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path)
|
|
||||||
{
|
|
||||||
return m_store.TestPath(storeID,path,false) ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ScriptInvocation]
|
|
||||||
public int JsonTestPathJson(UUID hostID, UUID scriptID, UUID storeID, string path)
|
|
||||||
{
|
|
||||||
return m_store.TestPath(storeID,path,true) ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|
|
@ -158,8 +158,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
|
|
||||||
Assert.That(dsrv, Is.EqualTo(1));
|
Assert.That(dsrv, Is.EqualTo(1));
|
||||||
|
|
||||||
int tprv = (int)InvokeOp("JsonTestPath", storeId, "Hello");
|
int tprv = (int)InvokeOp("JsonGetPathType", storeId, "Hello");
|
||||||
Assert.That(tprv, Is.EqualTo(0));
|
Assert.That(tprv, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -277,8 +277,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
|
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
|
||||||
Assert.That(returnValue, Is.EqualTo(1));
|
Assert.That(returnValue, Is.EqualTo(1));
|
||||||
|
|
||||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
|
int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello");
|
||||||
Assert.That(result, Is.EqualTo(0));
|
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
|
||||||
|
|
||||||
string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
|
string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
|
||||||
Assert.That(returnValue2, Is.EqualTo(""));
|
Assert.That(returnValue2, Is.EqualTo(""));
|
||||||
|
@ -291,8 +291,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
|
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
|
||||||
Assert.That(returnValue, Is.EqualTo(1));
|
Assert.That(returnValue, Is.EqualTo(1));
|
||||||
|
|
||||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
|
int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello");
|
||||||
Assert.That(result, Is.EqualTo(0));
|
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
|
||||||
|
|
||||||
string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello");
|
string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello");
|
||||||
Assert.That(returnValue2, Is.EqualTo(""));
|
Assert.That(returnValue2, Is.EqualTo(""));
|
||||||
|
@ -306,11 +306,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]");
|
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]");
|
||||||
Assert.That(returnValue, Is.EqualTo(1));
|
Assert.That(returnValue, Is.EqualTo(1));
|
||||||
|
|
||||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello[0]");
|
int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello[0]");
|
||||||
Assert.That(result, Is.EqualTo(1));
|
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_VALUE));
|
||||||
|
|
||||||
result = (int)InvokeOp("JsonTestPath", storeId, "Hello[1]");
|
result = (int)InvokeOp("JsonGetPathType", storeId, "Hello[1]");
|
||||||
Assert.That(result, Is.EqualTo(0));
|
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
|
||||||
|
|
||||||
string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]");
|
string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]");
|
||||||
Assert.That(stringReturnValue, Is.EqualTo("value2"));
|
Assert.That(stringReturnValue, Is.EqualTo("value2"));
|
||||||
|
@ -400,7 +400,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
// }
|
// }
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestGetArrayLength()
|
public void TestJsonGetArrayLength()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// TestHelpers.EnableLogging();
|
// TestHelpers.EnableLogging();
|
||||||
|
|
|
@ -438,6 +438,28 @@ public override BulletConstraint Create6DofConstraintToPoint(BulletWorld world,
|
||||||
joinPoint, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
|
joinPoint, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1,
|
||||||
|
Vector3 frameInBloc, Quaternion frameInBrot,
|
||||||
|
bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies)
|
||||||
|
{
|
||||||
|
BulletWorldUnman worldu = world as BulletWorldUnman;
|
||||||
|
BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
|
||||||
|
return new BulletConstraintUnman(BSAPICPP.Create6DofConstraintFixed2(worldu.ptr, bodyu1.ptr,
|
||||||
|
frameInBloc, frameInBrot, useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
|
Vector3 frame1loc, Quaternion frame1rot,
|
||||||
|
Vector3 frame2loc, Quaternion frame2rot,
|
||||||
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
|
||||||
|
{
|
||||||
|
BulletWorldUnman worldu = world as BulletWorldUnman;
|
||||||
|
BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
|
||||||
|
BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
|
||||||
|
return new BulletConstraintUnman(BSAPICPP.Create6DofSpringConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, frame1loc, frame1rot,
|
||||||
|
frame2loc, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
|
||||||
|
}
|
||||||
|
|
||||||
public override BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
public override BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
Vector3 pivotinA, Vector3 pivotinB,
|
Vector3 pivotinA, Vector3 pivotinB,
|
||||||
Vector3 axisInA, Vector3 axisInB,
|
Vector3 axisInA, Vector3 axisInB,
|
||||||
|
@ -450,6 +472,52 @@ public override BulletConstraint CreateHingeConstraint(BulletWorld world, Bullet
|
||||||
pivotinA, pivotinB, axisInA, axisInB, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
|
pivotinA, pivotinB, axisInA, axisInB, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override BulletConstraint CreateSliderConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
|
Vector3 frame1loc, Quaternion frame1rot,
|
||||||
|
Vector3 frame2loc, Quaternion frame2rot,
|
||||||
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
|
||||||
|
{
|
||||||
|
BulletWorldUnman worldu = world as BulletWorldUnman;
|
||||||
|
BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
|
||||||
|
BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
|
||||||
|
return new BulletConstraintUnman(BSAPICPP.CreateSliderConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, frame1loc, frame1rot,
|
||||||
|
frame2loc, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BulletConstraint CreateConeTwistConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
|
Vector3 frame1loc, Quaternion frame1rot,
|
||||||
|
Vector3 frame2loc, Quaternion frame2rot,
|
||||||
|
bool disableCollisionsBetweenLinkedBodies)
|
||||||
|
{
|
||||||
|
BulletWorldUnman worldu = world as BulletWorldUnman;
|
||||||
|
BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
|
||||||
|
BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
|
||||||
|
return new BulletConstraintUnman(BSAPICPP.CreateConeTwistConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, frame1loc, frame1rot,
|
||||||
|
frame2loc, frame2rot, disableCollisionsBetweenLinkedBodies));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BulletConstraint CreateGearConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
|
Vector3 axisInA, Vector3 axisInB,
|
||||||
|
float ratio, bool disableCollisionsBetweenLinkedBodies)
|
||||||
|
{
|
||||||
|
BulletWorldUnman worldu = world as BulletWorldUnman;
|
||||||
|
BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
|
||||||
|
BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
|
||||||
|
return new BulletConstraintUnman(BSAPICPP.CreateGearConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, axisInA, axisInB,
|
||||||
|
ratio, disableCollisionsBetweenLinkedBodies));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BulletConstraint CreatePoint2PointConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
|
Vector3 pivotInA, Vector3 pivotInB,
|
||||||
|
bool disableCollisionsBetweenLinkedBodies)
|
||||||
|
{
|
||||||
|
BulletWorldUnman worldu = world as BulletWorldUnman;
|
||||||
|
BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
|
||||||
|
BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
|
||||||
|
return new BulletConstraintUnman(BSAPICPP.CreatePoint2PointConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, pivotInA, pivotInB,
|
||||||
|
disableCollisionsBetweenLinkedBodies));
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse)
|
public override void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse)
|
||||||
{
|
{
|
||||||
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
|
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
|
||||||
|
@ -1425,12 +1493,46 @@ public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr ob
|
||||||
Vector3 joinPoint,
|
Vector3 joinPoint,
|
||||||
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr Create6DofConstraintFixed2(IntPtr world, IntPtr obj1,
|
||||||
|
Vector3 frameInBloc, Quaternion frameInBrot,
|
||||||
|
bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr Create6DofSpringConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||||
|
Vector3 frame1loc, Quaternion frame1rot,
|
||||||
|
Vector3 frame2loc, Quaternion frame2rot,
|
||||||
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||||
Vector3 pivotinA, Vector3 pivotinB,
|
Vector3 pivotinA, Vector3 pivotinB,
|
||||||
Vector3 axisInA, Vector3 axisInB,
|
Vector3 axisInA, Vector3 axisInB,
|
||||||
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr CreateSliderConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||||
|
Vector3 frameInAloc, Quaternion frameInArot,
|
||||||
|
Vector3 frameInBloc, Quaternion frameInBrot,
|
||||||
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr CreateConeTwistConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||||
|
Vector3 frameInAloc, Quaternion frameInArot,
|
||||||
|
Vector3 frameInBloc, Quaternion frameInBrot,
|
||||||
|
bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr CreateGearConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||||
|
Vector3 axisInA, Vector3 axisInB,
|
||||||
|
float ratio, bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr CreatePoint2PointConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||||
|
Vector3 pivotInA, Vector3 pivotInB,
|
||||||
|
bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse);
|
public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse);
|
||||||
|
|
||||||
|
|
|
@ -559,8 +559,9 @@ private sealed class BulletConstraintXNA : BulletConstraint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//BulletSimAPI.Create6DofConstraint(m_world.ptr, m_body1.ptr, m_body2.ptr,frame1, frame1rot,frame2, frame2rot,useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
|
public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
|
||||||
public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
|
Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
|
||||||
|
bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
|
||||||
|
|
||||||
{
|
{
|
||||||
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
|
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
|
||||||
|
@ -584,6 +585,23 @@ private sealed class BulletConstraintXNA : BulletConstraint
|
||||||
return new BulletConstraintXNA(consttr);
|
return new BulletConstraintXNA(consttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override BulletConstraint Create6DofConstraintFixed(BulletWorld pWorld, BulletBody pBody1,
|
||||||
|
Vector3 pframe1, Quaternion pframe1rot,
|
||||||
|
bool pUseLinearReferenceFrameB, bool pdisableCollisionsBetweenLinkedBodies)
|
||||||
|
{
|
||||||
|
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
|
||||||
|
RigidBody body1 = (pBody1 as BulletBodyXNA).rigidBody;
|
||||||
|
IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z);
|
||||||
|
IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W);
|
||||||
|
IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot);
|
||||||
|
frame1._origin = frame1v;
|
||||||
|
|
||||||
|
Generic6DofConstraint consttr = new Generic6DofConstraint(body1, ref frame1, pUseLinearReferenceFrameB);
|
||||||
|
consttr.CalculateTransforms();
|
||||||
|
world.AddConstraint(consttr,pdisableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
return new BulletConstraintXNA(consttr);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
@ -1133,8 +1151,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
|
||||||
p.numberOfSolverIterations = o[0].numberOfSolverIterations;
|
p.numberOfSolverIterations = o[0].numberOfSolverIterations;
|
||||||
|
|
||||||
p.linksetImplementation = BSParam.LinksetImplementation;
|
p.linksetImplementation = BSParam.LinksetImplementation;
|
||||||
p.linkConstraintUseFrameOffset = BSParam.LinkConstraintUseFrameOffset;
|
p.linkConstraintUseFrameOffset = BSParam.NumericBool(BSParam.LinkConstraintUseFrameOffset);
|
||||||
p.linkConstraintEnableTransMotor = BSParam.LinkConstraintEnableTransMotor;
|
p.linkConstraintEnableTransMotor = BSParam.NumericBool(BSParam.LinkConstraintEnableTransMotor);
|
||||||
p.linkConstraintTransMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel;
|
p.linkConstraintTransMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel;
|
||||||
p.linkConstraintTransMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce;
|
p.linkConstraintTransMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce;
|
||||||
p.linkConstraintERP = BSParam.LinkConstraintERP;
|
p.linkConstraintERP = BSParam.LinkConstraintERP;
|
||||||
|
@ -1443,129 +1461,130 @@ private sealed class BulletConstraintXNA : BulletConstraint
|
||||||
|
|
||||||
public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin)
|
public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin)
|
||||||
{
|
{
|
||||||
|
BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
switch (pin)
|
switch (pin)
|
||||||
{
|
{
|
||||||
case BroadphaseNativeTypes.BOX_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.BOX_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_BOX;
|
ret = BSPhysicsShapeType.SHAPE_BOX;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.TRIANGLE_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.TRIANGLE_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BroadphaseNativeTypes.TETRAHEDRAL_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.TETRAHEDRAL_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_MESH;
|
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_HULL;
|
ret = BSPhysicsShapeType.SHAPE_HULL;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.CUSTOM_POLYHEDRAL_SHAPE_TYPE:
|
case BroadphaseNativeTypes.CUSTOM_POLYHEDRAL_SHAPE_TYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
//implicit convex shapes
|
//implicit convex shapes
|
||||||
case BroadphaseNativeTypes.IMPLICIT_CONVEX_SHAPES_START_HERE:
|
case BroadphaseNativeTypes.IMPLICIT_CONVEX_SHAPES_START_HERE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.SPHERE_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.SPHERE_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_SPHERE;
|
ret = BSPhysicsShapeType.SHAPE_SPHERE;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.MULTI_SPHERE_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.MULTI_SPHERE_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.CAPSULE_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.CAPSULE_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_CAPSULE;
|
ret = BSPhysicsShapeType.SHAPE_CAPSULE;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.CONE_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.CONE_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_CONE;
|
ret = BSPhysicsShapeType.SHAPE_CONE;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_CYLINDER;
|
ret = BSPhysicsShapeType.SHAPE_CYLINDER;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.UNIFORM_SCALING_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.UNIFORM_SCALING_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.MINKOWSKI_SUM_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.MINKOWSKI_SUM_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.BOX_2D_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.BOX_2D_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.CONVEX_2D_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.CONVEX_2D_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.CUSTOM_CONVEX_SHAPE_TYPE:
|
case BroadphaseNativeTypes.CUSTOM_CONVEX_SHAPE_TYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
//concave shape
|
//concave shape
|
||||||
case BroadphaseNativeTypes.CONCAVE_SHAPES_START_HERE:
|
case BroadphaseNativeTypes.CONCAVE_SHAPES_START_HERE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
|
//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
|
||||||
case BroadphaseNativeTypes.TRIANGLE_MESH_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.TRIANGLE_MESH_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_MESH;
|
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_MESH;
|
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||||
break;
|
break;
|
||||||
///used for demo integration FAST/Swift collision library and Bullet
|
///used for demo integration FAST/Swift collision library and Bullet
|
||||||
case BroadphaseNativeTypes.FAST_CONCAVE_MESH_PROXYTYPE:
|
case BroadphaseNativeTypes.FAST_CONCAVE_MESH_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_MESH;
|
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||||
break;
|
break;
|
||||||
//terrain
|
//terrain
|
||||||
case BroadphaseNativeTypes.TERRAIN_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.TERRAIN_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_HEIGHTMAP;
|
ret = BSPhysicsShapeType.SHAPE_HEIGHTMAP;
|
||||||
break;
|
break;
|
||||||
///Used for GIMPACT Trimesh integration
|
///Used for GIMPACT Trimesh integration
|
||||||
case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_MESH;
|
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||||
break;
|
break;
|
||||||
///Multimaterial mesh
|
///Multimaterial mesh
|
||||||
case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE:
|
case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_MESH;
|
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BroadphaseNativeTypes.EMPTY_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.EMPTY_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.STATIC_PLANE_PROXYTYPE:
|
case BroadphaseNativeTypes.STATIC_PLANE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_GROUNDPLANE;
|
ret = BSPhysicsShapeType.SHAPE_GROUNDPLANE;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.CUSTOM_CONCAVE_SHAPE_TYPE:
|
case BroadphaseNativeTypes.CUSTOM_CONCAVE_SHAPE_TYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.CONCAVE_SHAPES_END_HERE:
|
case BroadphaseNativeTypes.CONCAVE_SHAPES_END_HERE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BroadphaseNativeTypes.COMPOUND_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.COMPOUND_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_COMPOUND;
|
ret = BSPhysicsShapeType.SHAPE_COMPOUND;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BroadphaseNativeTypes.SOFTBODY_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.SOFTBODY_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_MESH;
|
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.HFFLUID_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.HFFLUID_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case BroadphaseNativeTypes.INVALID_SHAPE_PROXYTYPE:
|
case BroadphaseNativeTypes.INVALID_SHAPE_PROXYTYPE:
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ }
|
public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ }
|
||||||
|
@ -1579,7 +1598,39 @@ private sealed class BulletConstraintXNA : BulletConstraint
|
||||||
return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE);
|
return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BulletConstraint CreateHingeConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, Vector3 ppivotInA, Vector3 ppivotInB, Vector3 paxisInA, Vector3 paxisInB, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
|
public override BulletConstraint Create6DofSpringConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
|
||||||
|
Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
|
||||||
|
bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
|
||||||
|
|
||||||
|
{
|
||||||
|
Generic6DofSpringConstraint constrain = null;
|
||||||
|
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
|
||||||
|
RigidBody body1 = (pBody1 as BulletBodyXNA).rigidBody;
|
||||||
|
RigidBody body2 = (pBody2 as BulletBodyXNA).rigidBody;
|
||||||
|
if (body1 != null && body2 != null)
|
||||||
|
{
|
||||||
|
IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z);
|
||||||
|
IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W);
|
||||||
|
IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot);
|
||||||
|
frame1._origin = frame1v;
|
||||||
|
|
||||||
|
IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z);
|
||||||
|
IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W);
|
||||||
|
IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot);
|
||||||
|
frame2._origin = frame1v;
|
||||||
|
|
||||||
|
constrain = new Generic6DofSpringConstraint(body1, body2, ref frame1, ref frame2, puseLinearReferenceFrameA);
|
||||||
|
world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
constrain.CalculateTransforms();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BulletConstraintXNA(constrain);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BulletConstraint CreateHingeConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
|
||||||
|
Vector3 ppivotInA, Vector3 ppivotInB, Vector3 paxisInA, Vector3 paxisInB,
|
||||||
|
bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
|
||||||
{
|
{
|
||||||
HingeConstraint constrain = null;
|
HingeConstraint constrain = null;
|
||||||
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
|
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
|
||||||
|
@ -1591,6 +1642,100 @@ private sealed class BulletConstraintXNA : BulletConstraint
|
||||||
IndexedVector3 pivotInB = new IndexedVector3(ppivotInB.X, ppivotInB.Y, ppivotInB.Z);
|
IndexedVector3 pivotInB = new IndexedVector3(ppivotInB.X, ppivotInB.Y, ppivotInB.Z);
|
||||||
IndexedVector3 axisInA = new IndexedVector3(paxisInA.X, paxisInA.Y, paxisInA.Z);
|
IndexedVector3 axisInA = new IndexedVector3(paxisInA.X, paxisInA.Y, paxisInA.Z);
|
||||||
IndexedVector3 axisInB = new IndexedVector3(paxisInB.X, paxisInB.Y, paxisInB.Z);
|
IndexedVector3 axisInB = new IndexedVector3(paxisInB.X, paxisInB.Y, paxisInB.Z);
|
||||||
|
constrain = new HingeConstraint(rb1, rb2, ref pivotInA, ref pivotInB, ref axisInA, ref axisInB, puseLinearReferenceFrameA);
|
||||||
|
world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
|
||||||
|
}
|
||||||
|
return new BulletConstraintXNA(constrain);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BulletConstraint CreateSliderConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
|
||||||
|
Vector3 pframe1, Quaternion pframe1rot,
|
||||||
|
Vector3 pframe2, Quaternion pframe2rot,
|
||||||
|
bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
|
||||||
|
{
|
||||||
|
SliderConstraint constrain = null;
|
||||||
|
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
|
||||||
|
RigidBody rb1 = (pBody1 as BulletBodyXNA).rigidBody;
|
||||||
|
RigidBody rb2 = (pBody2 as BulletBodyXNA).rigidBody;
|
||||||
|
if (rb1 != null && rb2 != null)
|
||||||
|
{
|
||||||
|
IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z);
|
||||||
|
IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W);
|
||||||
|
IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot);
|
||||||
|
frame1._origin = frame1v;
|
||||||
|
|
||||||
|
IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z);
|
||||||
|
IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W);
|
||||||
|
IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot);
|
||||||
|
frame2._origin = frame1v;
|
||||||
|
|
||||||
|
constrain = new SliderConstraint(rb1, rb2, ref frame1, ref frame2, puseLinearReferenceFrameA);
|
||||||
|
world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
|
||||||
|
}
|
||||||
|
return new BulletConstraintXNA(constrain);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BulletConstraint CreateConeTwistConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
|
||||||
|
Vector3 pframe1, Quaternion pframe1rot,
|
||||||
|
Vector3 pframe2, Quaternion pframe2rot,
|
||||||
|
bool pdisableCollisionsBetweenLinkedBodies)
|
||||||
|
{
|
||||||
|
ConeTwistConstraint constrain = null;
|
||||||
|
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
|
||||||
|
RigidBody rb1 = (pBody1 as BulletBodyXNA).rigidBody;
|
||||||
|
RigidBody rb2 = (pBody2 as BulletBodyXNA).rigidBody;
|
||||||
|
if (rb1 != null && rb2 != null)
|
||||||
|
{
|
||||||
|
IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z);
|
||||||
|
IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W);
|
||||||
|
IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot);
|
||||||
|
frame1._origin = frame1v;
|
||||||
|
|
||||||
|
IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z);
|
||||||
|
IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W);
|
||||||
|
IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot);
|
||||||
|
frame2._origin = frame1v;
|
||||||
|
|
||||||
|
constrain = new ConeTwistConstraint(rb1, rb2, ref frame1, ref frame2);
|
||||||
|
world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
|
||||||
|
}
|
||||||
|
return new BulletConstraintXNA(constrain);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BulletConstraint CreateGearConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
|
||||||
|
Vector3 paxisInA, Vector3 paxisInB,
|
||||||
|
float pratio, bool pdisableCollisionsBetweenLinkedBodies)
|
||||||
|
{
|
||||||
|
Generic6DofConstraint constrain = null;
|
||||||
|
/* BulletXNA does not have a gear constraint
|
||||||
|
GearConstraint constrain = null;
|
||||||
|
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
|
||||||
|
RigidBody rb1 = (pBody1 as BulletBodyXNA).rigidBody;
|
||||||
|
RigidBody rb2 = (pBody2 as BulletBodyXNA).rigidBody;
|
||||||
|
if (rb1 != null && rb2 != null)
|
||||||
|
{
|
||||||
|
IndexedVector3 axis1 = new IndexedVector3(paxisInA.X, paxisInA.Y, paxisInA.Z);
|
||||||
|
IndexedVector3 axis2 = new IndexedVector3(paxisInB.X, paxisInB.Y, paxisInB.Z);
|
||||||
|
constrain = new GearConstraint(rb1, rb2, ref axis1, ref axis2, pratio);
|
||||||
|
world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return new BulletConstraintXNA(constrain);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BulletConstraint CreatePoint2PointConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
|
||||||
|
Vector3 ppivotInA, Vector3 ppivotInB,
|
||||||
|
bool pdisableCollisionsBetweenLinkedBodies)
|
||||||
|
{
|
||||||
|
Point2PointConstraint constrain = null;
|
||||||
|
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
|
||||||
|
RigidBody rb1 = (pBody1 as BulletBodyXNA).rigidBody;
|
||||||
|
RigidBody rb2 = (pBody2 as BulletBodyXNA).rigidBody;
|
||||||
|
if (rb1 != null && rb2 != null)
|
||||||
|
{
|
||||||
|
IndexedVector3 pivotInA = new IndexedVector3(ppivotInA.X, ppivotInA.Y, ppivotInA.Z);
|
||||||
|
IndexedVector3 pivotInB = new IndexedVector3(ppivotInB.X, ppivotInB.Y, ppivotInB.Z);
|
||||||
|
constrain = new Point2PointConstraint(rb1, rb2, ref pivotInA, ref pivotInB);
|
||||||
world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
|
world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
|
||||||
}
|
}
|
||||||
return new BulletConstraintXNA(constrain);
|
return new BulletConstraintXNA(constrain);
|
||||||
|
|
|
@ -365,11 +365,38 @@ public abstract BulletConstraint Create6DofConstraintToPoint(BulletWorld world,
|
||||||
Vector3 joinPoint,
|
Vector3 joinPoint,
|
||||||
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
public abstract BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1,
|
||||||
|
Vector3 frameInBloc, Quaternion frameInBrot,
|
||||||
|
bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
public abstract BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
|
Vector3 frame1loc, Quaternion frame1rot,
|
||||||
|
Vector3 frame2loc, Quaternion frame2rot,
|
||||||
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
public abstract BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
public abstract BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
Vector3 pivotinA, Vector3 pivotinB,
|
Vector3 pivotinA, Vector3 pivotinB,
|
||||||
Vector3 axisInA, Vector3 axisInB,
|
Vector3 axisInA, Vector3 axisInB,
|
||||||
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
public abstract BulletConstraint CreateSliderConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
|
Vector3 frameInAloc, Quaternion frameInArot,
|
||||||
|
Vector3 frameInBloc, Quaternion frameInBrot,
|
||||||
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
public abstract BulletConstraint CreateConeTwistConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
|
Vector3 frameInAloc, Quaternion frameInArot,
|
||||||
|
Vector3 frameInBloc, Quaternion frameInBrot,
|
||||||
|
bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
public abstract BulletConstraint CreateGearConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
|
Vector3 axisInA, Vector3 axisInB,
|
||||||
|
float ratio, bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
|
public abstract BulletConstraint CreatePoint2PointConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
|
Vector3 pivotInA, Vector3 pivotInB,
|
||||||
|
bool disableCollisionsBetweenLinkedBodies);
|
||||||
|
|
||||||
public abstract void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse);
|
public abstract void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse);
|
||||||
|
|
||||||
public abstract void SetConstraintNumSolverIterations(BulletConstraint constrain, float iterations);
|
public abstract void SetConstraintNumSolverIterations(BulletConstraint constrain, float iterations);
|
||||||
|
|
|
@ -443,6 +443,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
|
PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||||
|
PositionSanityCheck();
|
||||||
ForcePosition = _position;
|
ForcePosition = _position;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -456,7 +457,6 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
_position = value;
|
_position = value;
|
||||||
if (PhysBody.HasPhysicalBody)
|
if (PhysBody.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
PositionSanityCheck();
|
|
||||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -513,8 +513,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
|
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||||
if (PhysBody.HasPhysicalBody)
|
ForcePosition = _position;
|
||||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
|
||||||
});
|
});
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ public sealed class BSConstraint6Dof : BSConstraint
|
||||||
obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
|
obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 6 Dof constraint based on a midpoint between the two constrained bodies
|
||||||
public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
|
||||||
Vector3 joinPoint,
|
Vector3 joinPoint,
|
||||||
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
|
||||||
|
@ -94,6 +95,21 @@ public sealed class BSConstraint6Dof : BSConstraint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A 6 Dof constraint that is fixed in the world and constrained to a on-the-fly created static object
|
||||||
|
public BSConstraint6Dof(BulletWorld world, BulletBody obj1, Vector3 frameInBloc, Quaternion frameInBrot,
|
||||||
|
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
|
||||||
|
: base(world)
|
||||||
|
{
|
||||||
|
m_body1 = obj1;
|
||||||
|
m_body2 = obj1; // Look out for confusion down the road
|
||||||
|
m_constraint = PhysicsScene.PE.Create6DofConstraintFixed(m_world, m_body1,
|
||||||
|
frameInBloc, frameInBrot,
|
||||||
|
useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
|
||||||
|
m_enabled = true;
|
||||||
|
world.physicsScene.DetailLog("{0},BS6DofConstraint,createFixed,wID={1},rID={2},rBody={3}",
|
||||||
|
BSScene.DetailLogZero, world.worldID, obj1.ID, obj1.AddrString);
|
||||||
|
}
|
||||||
|
|
||||||
public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
|
public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
|
@ -117,8 +117,7 @@ public sealed class BSConstraintCollection : IDisposable
|
||||||
if (this.TryGetConstraint(body1, body2, out constrain))
|
if (this.TryGetConstraint(body1, body2, out constrain))
|
||||||
{
|
{
|
||||||
// remove the constraint from our collection
|
// remove the constraint from our collection
|
||||||
RemoveAndDestroyConstraint(constrain);
|
ret = RemoveAndDestroyConstraint(constrain);
|
||||||
ret = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,17 +125,19 @@ public sealed class BSConstraintCollection : IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
// The constraint MUST exist in the collection
|
// The constraint MUST exist in the collection
|
||||||
|
// Could be called if the constraint was previously removed.
|
||||||
|
// Return 'true' if the constraint was actually removed and disposed.
|
||||||
public bool RemoveAndDestroyConstraint(BSConstraint constrain)
|
public bool RemoveAndDestroyConstraint(BSConstraint constrain)
|
||||||
{
|
{
|
||||||
|
bool removed = false;
|
||||||
lock (m_constraints)
|
lock (m_constraints)
|
||||||
{
|
{
|
||||||
// remove the constraint from our collection
|
// remove the constraint from our collection
|
||||||
m_constraints.Remove(constrain);
|
removed = m_constraints.Remove(constrain);
|
||||||
}
|
}
|
||||||
// tell the engine that all its structures need to be freed
|
// Dispose() is safe to call multiple times
|
||||||
constrain.Dispose();
|
constrain.Dispose();
|
||||||
// we destroyed something
|
return removed;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all constraints that reference the passed body.
|
// Remove all constraints that reference the passed body.
|
||||||
|
|
|
@ -144,7 +144,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
enableAngularVerticalAttraction = true;
|
enableAngularVerticalAttraction = true;
|
||||||
enableAngularDeflection = false;
|
enableAngularDeflection = false;
|
||||||
enableAngularBanking = false;
|
enableAngularBanking = false;
|
||||||
if (BSParam.VehicleDebuggingEnabled != ConfigurationParameters.numericFalse)
|
if (BSParam.VehicleDebuggingEnabled)
|
||||||
{
|
{
|
||||||
enableAngularVerticalAttraction = true;
|
enableAngularVerticalAttraction = true;
|
||||||
enableAngularDeflection = false;
|
enableAngularDeflection = false;
|
||||||
|
@ -607,8 +607,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
|
// TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
|
||||||
// Maybe compute linear and angular factor and damping from params.
|
// Maybe compute linear and angular factor and damping from params.
|
||||||
PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, BSParam.VehicleAngularDamping);
|
PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, BSParam.VehicleAngularDamping);
|
||||||
PhysicsScene.PE.SetLinearFactor(Prim.PhysBody, BSParam.VehicleLinearFactorV);
|
PhysicsScene.PE.SetLinearFactor(Prim.PhysBody, BSParam.VehicleLinearFactor);
|
||||||
PhysicsScene.PE.SetAngularFactorV(Prim.PhysBody, BSParam.VehicleAngularFactorV);
|
PhysicsScene.PE.SetAngularFactorV(Prim.PhysBody, BSParam.VehicleAngularFactor);
|
||||||
|
|
||||||
// Vehicles report collision events so we know when it's on the ground
|
// Vehicles report collision events so we know when it's on the ground
|
||||||
PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
|
PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
|
||||||
|
|
|
@ -223,8 +223,8 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
|
constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||||
|
|
||||||
// tweek the constraint to increase stability
|
// tweek the constraint to increase stability
|
||||||
constrain.UseFrameOffset(BSParam.BoolNumeric(BSParam.LinkConstraintUseFrameOffset));
|
constrain.UseFrameOffset(BSParam.LinkConstraintUseFrameOffset);
|
||||||
constrain.TranslationalLimitMotor(BSParam.BoolNumeric(BSParam.LinkConstraintEnableTransMotor),
|
constrain.TranslationalLimitMotor(BSParam.LinkConstraintEnableTransMotor,
|
||||||
BSParam.LinkConstraintTransMotorMaxVel,
|
BSParam.LinkConstraintTransMotorMaxVel,
|
||||||
BSParam.LinkConstraintTransMotorMaxForce);
|
BSParam.LinkConstraintTransMotorMaxForce);
|
||||||
constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
|
constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
|
||||||
|
|
|
@ -37,6 +37,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
public static class BSParam
|
public static class BSParam
|
||||||
{
|
{
|
||||||
|
private static string LogHeader = "[BULLETSIM PARAMETERS]";
|
||||||
|
|
||||||
// Level of Detail values kept as float because that's what the Meshmerizer wants
|
// Level of Detail values kept as float because that's what the Meshmerizer wants
|
||||||
public static float MeshLOD { get; private set; }
|
public static float MeshLOD { get; private set; }
|
||||||
public static float MeshCircularLOD { get; private set; }
|
public static float MeshCircularLOD { get; private set; }
|
||||||
|
@ -44,6 +46,8 @@ public static class BSParam
|
||||||
public static float MeshMegaPrimThreshold { get; private set; }
|
public static float MeshMegaPrimThreshold { get; private set; }
|
||||||
public static float SculptLOD { get; private set; }
|
public static float SculptLOD { get; private set; }
|
||||||
|
|
||||||
|
public static int CrossingFailuresBeforeOutOfBounds { get; private set; }
|
||||||
|
|
||||||
public static float MinimumObjectMass { get; private set; }
|
public static float MinimumObjectMass { get; private set; }
|
||||||
public static float MaximumObjectMass { get; private set; }
|
public static float MaximumObjectMass { get; private set; }
|
||||||
public static float MaxLinearVelocity { get; private set; }
|
public static float MaxLinearVelocity { get; private set; }
|
||||||
|
@ -71,24 +75,23 @@ public static class BSParam
|
||||||
public static float TerrainRestitution { get; private set; }
|
public static float TerrainRestitution { get; private set; }
|
||||||
public static float TerrainCollisionMargin { get; private set; }
|
public static float TerrainCollisionMargin { get; private set; }
|
||||||
|
|
||||||
public static float DefaultFriction;
|
public static float DefaultFriction { get; private set; }
|
||||||
public static float DefaultDensity;
|
public static float DefaultDensity { get; private set; }
|
||||||
public static float DefaultRestitution;
|
public static float DefaultRestitution { get; private set; }
|
||||||
public static float CollisionMargin;
|
public static float CollisionMargin { get; private set; }
|
||||||
public static float Gravity;
|
public static float Gravity { get; private set; }
|
||||||
|
|
||||||
// Physics Engine operation
|
// Physics Engine operation
|
||||||
public static float MaxPersistantManifoldPoolSize;
|
public static float MaxPersistantManifoldPoolSize { get; private set; }
|
||||||
public static float MaxCollisionAlgorithmPoolSize;
|
public static float MaxCollisionAlgorithmPoolSize { get; private set; }
|
||||||
public static float ShouldDisableContactPoolDynamicAllocation;
|
public static bool ShouldDisableContactPoolDynamicAllocation { get; private set; }
|
||||||
public static float ShouldForceUpdateAllAabbs;
|
public static bool ShouldForceUpdateAllAabbs { get; private set; }
|
||||||
public static float ShouldRandomizeSolverOrder;
|
public static bool ShouldRandomizeSolverOrder { get; private set; }
|
||||||
public static float ShouldSplitSimulationIslands;
|
public static bool ShouldSplitSimulationIslands { get; private set; }
|
||||||
public static float ShouldEnableFrictionCaching;
|
public static bool ShouldEnableFrictionCaching { get; private set; }
|
||||||
public static float NumberOfSolverIterations;
|
public static float NumberOfSolverIterations { get; private set; }
|
||||||
public static bool UseSingleSidedMeshes { get { return UseSingleSidedMeshesF != ConfigurationParameters.numericFalse; } }
|
public static bool UseSingleSidedMeshes { get; private set; }
|
||||||
public static float UseSingleSidedMeshesF;
|
public static float GlobalContactBreakingThreshold { get; private set; }
|
||||||
public static float GlobalContactBreakingThreshold;
|
|
||||||
|
|
||||||
// Avatar parameters
|
// Avatar parameters
|
||||||
public static float AvatarFriction { get; private set; }
|
public static float AvatarFriction { get; private set; }
|
||||||
|
@ -112,16 +115,15 @@ public static class BSParam
|
||||||
public static float VehicleAngularDamping { get; private set; }
|
public static float VehicleAngularDamping { get; private set; }
|
||||||
public static float VehicleFriction { get; private set; }
|
public static float VehicleFriction { get; private set; }
|
||||||
public static float VehicleRestitution { get; private set; }
|
public static float VehicleRestitution { get; private set; }
|
||||||
public static float VehicleLinearFactor { get; private set; }
|
public static Vector3 VehicleLinearFactor { get; private set; }
|
||||||
public static Vector3 VehicleLinearFactorV { get; private set; }
|
public static Vector3 VehicleAngularFactor { get; private set; }
|
||||||
public static float VehicleAngularFactor { get; private set; }
|
|
||||||
public static Vector3 VehicleAngularFactorV { get; private set; }
|
|
||||||
public static float VehicleGroundGravityFudge { get; private set; }
|
public static float VehicleGroundGravityFudge { get; private set; }
|
||||||
public static float VehicleDebuggingEnabled { get; private set; }
|
public static bool VehicleDebuggingEnabled { get; private set; }
|
||||||
|
|
||||||
|
// Linkset implementation parameters
|
||||||
public static float LinksetImplementation { get; private set; }
|
public static float LinksetImplementation { get; private set; }
|
||||||
public static float LinkConstraintUseFrameOffset { get; private set; }
|
public static bool LinkConstraintUseFrameOffset { get; private set; }
|
||||||
public static float LinkConstraintEnableTransMotor { get; private set; }
|
public static bool LinkConstraintEnableTransMotor { get; private set; }
|
||||||
public static float LinkConstraintTransMotorMaxVel { get; private set; }
|
public static float LinkConstraintTransMotorMaxVel { get; private set; }
|
||||||
public static float LinkConstraintTransMotorMaxForce { get; private set; }
|
public static float LinkConstraintTransMotorMaxForce { get; private set; }
|
||||||
public static float LinkConstraintERP { get; private set; }
|
public static float LinkConstraintERP { get; private set; }
|
||||||
|
@ -141,40 +143,106 @@ public static class BSParam
|
||||||
public const float MinRestitution = 0f;
|
public const float MinRestitution = 0f;
|
||||||
public const float MaxRestitution = 1f;
|
public const float MaxRestitution = 1f;
|
||||||
|
|
||||||
// ===========================================================================
|
// =====================================================================================
|
||||||
public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
|
// =====================================================================================
|
||||||
public delegate float ParamGet(BSScene scene);
|
|
||||||
public delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
|
|
||||||
public delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
|
|
||||||
|
|
||||||
public struct ParameterDefn
|
// Base parameter definition that gets and sets parameter values via a string
|
||||||
|
public abstract class ParameterDefnBase
|
||||||
{
|
{
|
||||||
public string name; // string name of the parameter
|
public string name; // string name of the parameter
|
||||||
public string desc; // a short description of what the parameter means
|
public string desc; // a short description of what the parameter means
|
||||||
public float defaultValue; // default value if not specified anywhere else
|
public ParameterDefnBase(string pName, string pDesc)
|
||||||
public ParamUser userParam; // get the value from the configuration file
|
|
||||||
public ParamGet getter; // return the current value stored for this parameter
|
|
||||||
public ParamSet setter; // set the current value for this parameter
|
|
||||||
public SetOnObject onObject; // set the value on an object in the physical domain
|
|
||||||
public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
|
|
||||||
{
|
{
|
||||||
name = n;
|
name = pName;
|
||||||
desc = d;
|
desc = pDesc;
|
||||||
defaultValue = v;
|
|
||||||
userParam = u;
|
|
||||||
getter = g;
|
|
||||||
setter = s;
|
|
||||||
onObject = null;
|
|
||||||
}
|
}
|
||||||
public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
|
// Set the parameter value to the default
|
||||||
|
public abstract void AssignDefault(BSScene s);
|
||||||
|
// Get the value as a string
|
||||||
|
public abstract string GetValue(BSScene s);
|
||||||
|
// Set the value to this string value
|
||||||
|
public abstract void SetValue(BSScene s, string valAsString);
|
||||||
|
// set the value on a particular object (usually sets in physics engine)
|
||||||
|
public abstract void SetOnObject(BSScene s, BSPhysObject obj);
|
||||||
|
public abstract bool HasSetOnObject { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specific parameter definition for a parameter of a specific type.
|
||||||
|
public delegate T PGetValue<T>(BSScene s);
|
||||||
|
public delegate void PSetValue<T>(BSScene s, T val);
|
||||||
|
public delegate void PSetOnObject<T>(BSScene scene, BSPhysObject obj);
|
||||||
|
public sealed class ParameterDefn<T> : ParameterDefnBase
|
||||||
{
|
{
|
||||||
name = n;
|
T defaultValue;
|
||||||
desc = d;
|
PSetValue<T> setter;
|
||||||
defaultValue = v;
|
PGetValue<T> getter;
|
||||||
userParam = u;
|
PSetOnObject<T> objectSet;
|
||||||
getter = g;
|
public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter)
|
||||||
setter = s;
|
: base(pName, pDesc)
|
||||||
onObject = o;
|
{
|
||||||
|
defaultValue = pDefault;
|
||||||
|
setter = pSetter;
|
||||||
|
getter = pGetter;
|
||||||
|
objectSet = null;
|
||||||
|
}
|
||||||
|
public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter, PSetOnObject<T> pObjSetter)
|
||||||
|
: base(pName, pDesc)
|
||||||
|
{
|
||||||
|
defaultValue = pDefault;
|
||||||
|
setter = pSetter;
|
||||||
|
getter = pGetter;
|
||||||
|
objectSet = pObjSetter;
|
||||||
|
}
|
||||||
|
public override void AssignDefault(BSScene s)
|
||||||
|
{
|
||||||
|
setter(s, defaultValue);
|
||||||
|
}
|
||||||
|
public override string GetValue(BSScene s)
|
||||||
|
{
|
||||||
|
return String.Format("{0}", getter(s));
|
||||||
|
}
|
||||||
|
public override void SetValue(BSScene s, string valAsString)
|
||||||
|
{
|
||||||
|
// Get the generic type of the setter
|
||||||
|
Type genericType = setter.GetType().GetGenericArguments()[0];
|
||||||
|
// Find the 'Parse' method on that type
|
||||||
|
System.Reflection.MethodInfo parser = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parser = genericType.GetMethod("Parse", new Type[] { typeof(String) } );
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
s.Logger.ErrorFormat("{0} Exception getting parser for type '{1}': {2}", LogHeader, genericType, e);
|
||||||
|
parser = null;
|
||||||
|
}
|
||||||
|
if (parser != null)
|
||||||
|
{
|
||||||
|
// Parse the input string
|
||||||
|
try
|
||||||
|
{
|
||||||
|
T setValue = (T)parser.Invoke(genericType, new Object[] { valAsString });
|
||||||
|
setter(s, setValue);
|
||||||
|
// s.Logger.DebugFormat("{0} Parameter {1} = {2}", LogHeader, name, setValue);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
s.Logger.ErrorFormat("{0} Failed parsing parameter value '{1}' as type '{2}'", LogHeader, valAsString, genericType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.Logger.ErrorFormat("{0} Could not find parameter parser for type '{1}'", LogHeader, genericType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool HasSetOnObject
|
||||||
|
{
|
||||||
|
get { return objectSet != null; }
|
||||||
|
}
|
||||||
|
public override void SetOnObject(BSScene s, BSPhysObject obj)
|
||||||
|
{
|
||||||
|
if (objectSet != null)
|
||||||
|
objectSet(s, obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,462 +252,380 @@ public static class BSParam
|
||||||
// location somewhere in the program and make an entry in this table with the
|
// location somewhere in the program and make an entry in this table with the
|
||||||
// getters and setters.
|
// getters and setters.
|
||||||
// It is easiest to find an existing definition and copy it.
|
// It is easiest to find an existing definition and copy it.
|
||||||
// Parameter values are floats. Booleans are converted to a floating value.
|
|
||||||
//
|
//
|
||||||
// A ParameterDefn() takes the following parameters:
|
// A ParameterDefn<T>() takes the following parameters:
|
||||||
// -- the text name of the parameter. This is used for console input and ini file.
|
// -- the text name of the parameter. This is used for console input and ini file.
|
||||||
// -- a short text description of the parameter. This shows up in the console listing.
|
// -- a short text description of the parameter. This shows up in the console listing.
|
||||||
// -- a default value (float)
|
// -- a default value
|
||||||
// -- a delegate for fetching the parameter from the ini file.
|
// -- a delegate for getting the value
|
||||||
// Should handle fetching the right type from the ini file and converting it.
|
// -- a delegate for setting the value
|
||||||
// -- a delegate for getting the value as a float
|
|
||||||
// -- a delegate for setting the value from a float
|
|
||||||
// -- an optional delegate to update the value in the world. Most often used to
|
// -- an optional delegate to update the value in the world. Most often used to
|
||||||
// push the new value to an in-world object.
|
// push the new value to an in-world object.
|
||||||
//
|
//
|
||||||
// The single letter parameters for the delegates are:
|
// The single letter parameters for the delegates are:
|
||||||
// s = BSScene
|
// s = BSScene
|
||||||
// o = BSPhysObject
|
// o = BSPhysObject
|
||||||
// p = string parameter name
|
|
||||||
// l = localID of referenced object
|
|
||||||
// v = value (float)
|
// v = value (float)
|
||||||
// cf = parameter configuration class (for fetching values from ini file)
|
private static ParameterDefnBase[] ParameterDefinitions =
|
||||||
private static ParameterDefn[] ParameterDefinitions =
|
|
||||||
{
|
{
|
||||||
new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
|
new ParameterDefn<bool>("MeshSculptedPrim", "Whether to create meshes for sculpties",
|
||||||
ConfigurationParameters.numericTrue,
|
true,
|
||||||
(s,cf,p,v) => { ShouldMeshSculptedPrim = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
|
(s) => { return ShouldMeshSculptedPrim; },
|
||||||
(s) => { return BSParam.NumericBool(ShouldMeshSculptedPrim); },
|
(s,v) => { ShouldMeshSculptedPrim = v; } ),
|
||||||
(s,p,l,v) => { ShouldMeshSculptedPrim = BSParam.BoolNumeric(v); } ),
|
new ParameterDefn<bool>("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
|
||||||
new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
|
false,
|
||||||
ConfigurationParameters.numericFalse,
|
(s) => { return ShouldForceSimplePrimMeshing; },
|
||||||
(s,cf,p,v) => { ShouldForceSimplePrimMeshing = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
|
(s,v) => { ShouldForceSimplePrimMeshing = v; } ),
|
||||||
(s) => { return BSParam.NumericBool(ShouldForceSimplePrimMeshing); },
|
new ParameterDefn<bool>("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
|
||||||
(s,p,l,v) => { ShouldForceSimplePrimMeshing = BSParam.BoolNumeric(v); } ),
|
true,
|
||||||
new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
|
(s) => { return ShouldUseHullsForPhysicalObjects; },
|
||||||
ConfigurationParameters.numericTrue,
|
(s,v) => { ShouldUseHullsForPhysicalObjects = v; } ),
|
||||||
(s,cf,p,v) => { ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
|
new ParameterDefn<bool>("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes",
|
||||||
(s) => { return BSParam.NumericBool(ShouldUseHullsForPhysicalObjects); },
|
true,
|
||||||
(s,p,l,v) => { ShouldUseHullsForPhysicalObjects = BSParam.BoolNumeric(v); } ),
|
(s) => { return ShouldRemoveZeroWidthTriangles; },
|
||||||
new ParameterDefn("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes",
|
(s,v) => { ShouldRemoveZeroWidthTriangles = v; } ),
|
||||||
ConfigurationParameters.numericTrue,
|
|
||||||
(s,cf,p,v) => { ShouldRemoveZeroWidthTriangles = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
|
|
||||||
(s) => { return BSParam.NumericBool(ShouldRemoveZeroWidthTriangles); },
|
|
||||||
(s,p,l,v) => { ShouldRemoveZeroWidthTriangles = BSParam.BoolNumeric(v); } ),
|
|
||||||
|
|
||||||
new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
|
new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
|
||||||
|
5,
|
||||||
|
(s) => { return CrossingFailuresBeforeOutOfBounds; },
|
||||||
|
(s,v) => { CrossingFailuresBeforeOutOfBounds = v; } ),
|
||||||
|
|
||||||
|
new ParameterDefn<float>("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
|
||||||
32f,
|
32f,
|
||||||
(s,cf,p,v) => { MeshLOD = (float)cf.GetInt(p, (int)v); },
|
|
||||||
(s) => { return MeshLOD; },
|
(s) => { return MeshLOD; },
|
||||||
(s,p,l,v) => { MeshLOD = v; } ),
|
(s,v) => { MeshLOD = v; } ),
|
||||||
new ParameterDefn("MeshLevelOfDetailCircular", "Level of detail for prims with circular cuts or shapes",
|
new ParameterDefn<float>("MeshLevelOfDetailCircular", "Level of detail for prims with circular cuts or shapes",
|
||||||
32f,
|
32f,
|
||||||
(s,cf,p,v) => { MeshCircularLOD = (float)cf.GetInt(p, (int)v); },
|
|
||||||
(s) => { return MeshCircularLOD; },
|
(s) => { return MeshCircularLOD; },
|
||||||
(s,p,l,v) => { MeshCircularLOD = v; } ),
|
(s,v) => { MeshCircularLOD = v; } ),
|
||||||
new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
|
new ParameterDefn<float>("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
|
||||||
10f,
|
10f,
|
||||||
(s,cf,p,v) => { MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
|
|
||||||
(s) => { return MeshMegaPrimThreshold; },
|
(s) => { return MeshMegaPrimThreshold; },
|
||||||
(s,p,l,v) => { MeshMegaPrimThreshold = v; } ),
|
(s,v) => { MeshMegaPrimThreshold = v; } ),
|
||||||
new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
|
new ParameterDefn<float>("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
|
||||||
32f,
|
32f,
|
||||||
(s,cf,p,v) => { MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
|
|
||||||
(s) => { return MeshMegaPrimLOD; },
|
(s) => { return MeshMegaPrimLOD; },
|
||||||
(s,p,l,v) => { MeshMegaPrimLOD = v; } ),
|
(s,v) => { MeshMegaPrimLOD = v; } ),
|
||||||
new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
|
new ParameterDefn<float>("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
|
||||||
32f,
|
32f,
|
||||||
(s,cf,p,v) => { SculptLOD = (float)cf.GetInt(p, (int)v); },
|
|
||||||
(s) => { return SculptLOD; },
|
(s) => { return SculptLOD; },
|
||||||
(s,p,l,v) => { SculptLOD = v; } ),
|
(s,v) => { SculptLOD = v; } ),
|
||||||
|
|
||||||
new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
|
new ParameterDefn<int>("MaxSubStep", "In simulation step, maximum number of substeps",
|
||||||
10f,
|
10,
|
||||||
(s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
|
(s) => { return s.m_maxSubSteps; },
|
||||||
(s) => { return (float)s.m_maxSubSteps; },
|
(s,v) => { s.m_maxSubSteps = (int)v; } ),
|
||||||
(s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
|
new ParameterDefn<float>("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
|
||||||
new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
|
|
||||||
1f / 60f,
|
1f / 60f,
|
||||||
(s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
|
(s) => { return s.m_fixedTimeStep; },
|
||||||
(s) => { return (float)s.m_fixedTimeStep; },
|
(s,v) => { s.m_fixedTimeStep = v; } ),
|
||||||
(s,p,l,v) => { s.m_fixedTimeStep = v; } ),
|
new ParameterDefn<float>("NominalFrameRate", "The base frame rate we claim",
|
||||||
new ParameterDefn("NominalFrameRate", "The base frame rate we claim",
|
|
||||||
55f,
|
55f,
|
||||||
(s,cf,p,v) => { s.NominalFrameRate = cf.GetInt(p, (int)v); },
|
(s) => { return s.NominalFrameRate; },
|
||||||
(s) => { return (float)s.NominalFrameRate; },
|
(s,v) => { s.NominalFrameRate = (int)v; } ),
|
||||||
(s,p,l,v) => { s.NominalFrameRate = (int)v; } ),
|
new ParameterDefn<int>("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
|
||||||
new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
|
2048,
|
||||||
2048f,
|
(s) => { return s.m_maxCollisionsPerFrame; },
|
||||||
(s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
|
(s,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
|
||||||
(s) => { return (float)s.m_maxCollisionsPerFrame; },
|
new ParameterDefn<int>("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
|
||||||
(s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
|
8000,
|
||||||
new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
|
(s) => { return s.m_maxUpdatesPerFrame; },
|
||||||
8000f,
|
(s,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
|
||||||
(s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
|
|
||||||
(s) => { return (float)s.m_maxUpdatesPerFrame; },
|
|
||||||
(s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
|
|
||||||
|
|
||||||
new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)",
|
new ParameterDefn<float>("MinObjectMass", "Minimum object mass (0.0001)",
|
||||||
0.0001f,
|
0.0001f,
|
||||||
(s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return MinimumObjectMass; },
|
(s) => { return MinimumObjectMass; },
|
||||||
(s,p,l,v) => { MinimumObjectMass = v; } ),
|
(s,v) => { MinimumObjectMass = v; } ),
|
||||||
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
|
new ParameterDefn<float>("MaxObjectMass", "Maximum object mass (10000.01)",
|
||||||
10000.01f,
|
10000.01f,
|
||||||
(s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return MaximumObjectMass; },
|
(s) => { return MaximumObjectMass; },
|
||||||
(s,p,l,v) => { MaximumObjectMass = v; } ),
|
(s,v) => { MaximumObjectMass = v; } ),
|
||||||
new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
|
new ParameterDefn<float>("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
|
||||||
1000.0f,
|
1000.0f,
|
||||||
(s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return MaxLinearVelocity; },
|
(s) => { return MaxLinearVelocity; },
|
||||||
(s,p,l,v) => { MaxLinearVelocity = v; } ),
|
(s,v) => { MaxLinearVelocity = v; } ),
|
||||||
new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
|
new ParameterDefn<float>("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
|
||||||
1000.0f,
|
1000.0f,
|
||||||
(s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return MaxAngularVelocity; },
|
(s) => { return MaxAngularVelocity; },
|
||||||
(s,p,l,v) => { MaxAngularVelocity = v; } ),
|
(s,v) => { MaxAngularVelocity = v; } ),
|
||||||
// LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject
|
// LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject
|
||||||
new ParameterDefn("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)",
|
new ParameterDefn<float>("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)",
|
||||||
20000.0f,
|
20000.0f,
|
||||||
(s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return MaxAddForceMagnitude; },
|
(s) => { return MaxAddForceMagnitude; },
|
||||||
(s,p,l,v) => { MaxAddForceMagnitude = v; } ),
|
(s,v) => { MaxAddForceMagnitude = v; } ),
|
||||||
// Density is passed around as 100kg/m3. This scales that to 1kg/m3.
|
// Density is passed around as 100kg/m3. This scales that to 1kg/m3.
|
||||||
new ParameterDefn("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)",
|
new ParameterDefn<float>("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)",
|
||||||
0.01f,
|
0.01f,
|
||||||
(s,cf,p,v) => { DensityScaleFactor = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return DensityScaleFactor; },
|
(s) => { return DensityScaleFactor; },
|
||||||
(s,p,l,v) => { DensityScaleFactor = v; } ),
|
(s,v) => { DensityScaleFactor = v; } ),
|
||||||
|
|
||||||
new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
|
new ParameterDefn<float>("PID_D", "Derivitive factor for motion smoothing",
|
||||||
2200f,
|
2200f,
|
||||||
(s,cf,p,v) => { PID_D = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return (float)PID_D; },
|
(s) => { return (float)PID_D; },
|
||||||
(s,p,l,v) => { PID_D = v; } ),
|
(s,v) => { PID_D = v; } ),
|
||||||
new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
|
new ParameterDefn<float>("PID_P", "Parameteric factor for motion smoothing",
|
||||||
900f,
|
900f,
|
||||||
(s,cf,p,v) => { PID_P = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return (float)PID_P; },
|
(s) => { return (float)PID_P; },
|
||||||
(s,p,l,v) => { PID_P = v; } ),
|
(s,v) => { PID_P = v; } ),
|
||||||
|
|
||||||
new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
|
new ParameterDefn<float>("DefaultFriction", "Friction factor used on new objects",
|
||||||
0.2f,
|
0.2f,
|
||||||
(s,cf,p,v) => { DefaultFriction = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return DefaultFriction; },
|
(s) => { return DefaultFriction; },
|
||||||
(s,p,l,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ),
|
(s,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ),
|
||||||
new ParameterDefn("DefaultDensity", "Density for new objects" ,
|
new ParameterDefn<float>("DefaultDensity", "Density for new objects" ,
|
||||||
10.000006836f, // Aluminum g/cm3
|
10.000006836f, // Aluminum g/cm3
|
||||||
(s,cf,p,v) => { DefaultDensity = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return DefaultDensity; },
|
(s) => { return DefaultDensity; },
|
||||||
(s,p,l,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ),
|
(s,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ),
|
||||||
new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
|
new ParameterDefn<float>("DefaultRestitution", "Bouncyness of an object" ,
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { DefaultRestitution = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return DefaultRestitution; },
|
(s) => { return DefaultRestitution; },
|
||||||
(s,p,l,v) => { DefaultRestitution = v; s.UnmanagedParams[0].defaultRestitution = v; } ),
|
(s,v) => { DefaultRestitution = v; s.UnmanagedParams[0].defaultRestitution = v; } ),
|
||||||
new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
|
new ParameterDefn<float>("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
|
||||||
0.04f,
|
0.04f,
|
||||||
(s,cf,p,v) => { CollisionMargin = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return CollisionMargin; },
|
(s) => { return CollisionMargin; },
|
||||||
(s,p,l,v) => { CollisionMargin = v; s.UnmanagedParams[0].collisionMargin = v; } ),
|
(s,v) => { CollisionMargin = v; s.UnmanagedParams[0].collisionMargin = v; } ),
|
||||||
new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
|
new ParameterDefn<float>("Gravity", "Vertical force of gravity (negative means down)",
|
||||||
-9.80665f,
|
-9.80665f,
|
||||||
(s,cf,p,v) => { Gravity = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return Gravity; },
|
(s) => { return Gravity; },
|
||||||
(s,p,l,v) => { Gravity = v; s.UnmanagedParams[0].gravity = v; },
|
(s,v) => { Gravity = v; s.UnmanagedParams[0].gravity = v; },
|
||||||
(s,o,v) => { s.PE.SetGravity(o.PhysBody, new Vector3(0f,0f,v)); } ),
|
(s,o) => { s.PE.SetGravity(o.PhysBody, new Vector3(0f,0f,Gravity)); } ),
|
||||||
|
|
||||||
|
|
||||||
new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
|
new ParameterDefn<float>("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { LinearDamping = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return LinearDamping; },
|
(s) => { return LinearDamping; },
|
||||||
(s,p,l,v) => { LinearDamping = v; },
|
(s,v) => { LinearDamping = v; },
|
||||||
(s,o,v) => { s.PE.SetDamping(o.PhysBody, v, AngularDamping); } ),
|
(s,o) => { s.PE.SetDamping(o.PhysBody, LinearDamping, AngularDamping); } ),
|
||||||
new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
|
new ParameterDefn<float>("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { AngularDamping = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AngularDamping; },
|
(s) => { return AngularDamping; },
|
||||||
(s,p,l,v) => { AngularDamping = v; },
|
(s,v) => { AngularDamping = v; },
|
||||||
(s,o,v) => { s.PE.SetDamping(o.PhysBody, LinearDamping, v); } ),
|
(s,o) => { s.PE.SetDamping(o.PhysBody, LinearDamping, AngularDamping); } ),
|
||||||
new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
|
new ParameterDefn<float>("DeactivationTime", "Seconds before considering an object potentially static",
|
||||||
0.2f,
|
0.2f,
|
||||||
(s,cf,p,v) => { DeactivationTime = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return DeactivationTime; },
|
(s) => { return DeactivationTime; },
|
||||||
(s,p,l,v) => { DeactivationTime = v; },
|
(s,v) => { DeactivationTime = v; },
|
||||||
(s,o,v) => { s.PE.SetDeactivationTime(o.PhysBody, v); } ),
|
(s,o) => { s.PE.SetDeactivationTime(o.PhysBody, DeactivationTime); } ),
|
||||||
new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
|
new ParameterDefn<float>("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
|
||||||
0.8f,
|
0.8f,
|
||||||
(s,cf,p,v) => { LinearSleepingThreshold = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return LinearSleepingThreshold; },
|
(s) => { return LinearSleepingThreshold; },
|
||||||
(s,p,l,v) => { LinearSleepingThreshold = v;},
|
(s,v) => { LinearSleepingThreshold = v;},
|
||||||
(s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ),
|
(s,o) => { s.PE.SetSleepingThresholds(o.PhysBody, LinearSleepingThreshold, AngularSleepingThreshold); } ),
|
||||||
new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
|
new ParameterDefn<float>("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
|
||||||
1.0f,
|
1.0f,
|
||||||
(s,cf,p,v) => { AngularSleepingThreshold = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AngularSleepingThreshold; },
|
(s) => { return AngularSleepingThreshold; },
|
||||||
(s,p,l,v) => { AngularSleepingThreshold = v;},
|
(s,v) => { AngularSleepingThreshold = v;},
|
||||||
(s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ),
|
(s,o) => { s.PE.SetSleepingThresholds(o.PhysBody, LinearSleepingThreshold, AngularSleepingThreshold); } ),
|
||||||
new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
|
new ParameterDefn<float>("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
|
||||||
0.0f, // set to zero to disable
|
0.0f, // set to zero to disable
|
||||||
(s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return CcdMotionThreshold; },
|
(s) => { return CcdMotionThreshold; },
|
||||||
(s,p,l,v) => { CcdMotionThreshold = v;},
|
(s,v) => { CcdMotionThreshold = v;},
|
||||||
(s,o,v) => { s.PE.SetCcdMotionThreshold(o.PhysBody, v); } ),
|
(s,o) => { s.PE.SetCcdMotionThreshold(o.PhysBody, CcdMotionThreshold); } ),
|
||||||
new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
|
new ParameterDefn<float>("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
|
||||||
0.2f,
|
0.2f,
|
||||||
(s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return CcdSweptSphereRadius; },
|
(s) => { return CcdSweptSphereRadius; },
|
||||||
(s,p,l,v) => { CcdSweptSphereRadius = v;},
|
(s,v) => { CcdSweptSphereRadius = v;},
|
||||||
(s,o,v) => { s.PE.SetCcdSweptSphereRadius(o.PhysBody, v); } ),
|
(s,o) => { s.PE.SetCcdSweptSphereRadius(o.PhysBody, CcdSweptSphereRadius); } ),
|
||||||
new ParameterDefn("ContactProcessingThreshold", "Distance above which contacts can be discarded (0 means no discard)" ,
|
new ParameterDefn<float>("ContactProcessingThreshold", "Distance above which contacts can be discarded (0 means no discard)" ,
|
||||||
0.0f,
|
0.0f,
|
||||||
(s,cf,p,v) => { ContactProcessingThreshold = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return ContactProcessingThreshold; },
|
(s) => { return ContactProcessingThreshold; },
|
||||||
(s,p,l,v) => { ContactProcessingThreshold = v;},
|
(s,v) => { ContactProcessingThreshold = v;},
|
||||||
(s,o,v) => { s.PE.SetContactProcessingThreshold(o.PhysBody, v); } ),
|
(s,o) => { s.PE.SetContactProcessingThreshold(o.PhysBody, ContactProcessingThreshold); } ),
|
||||||
|
|
||||||
new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
|
new ParameterDefn<float>("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
|
||||||
(float)BSTerrainPhys.TerrainImplementation.Mesh,
|
(float)BSTerrainPhys.TerrainImplementation.Mesh,
|
||||||
(s,cf,p,v) => { TerrainImplementation = cf.GetFloat(p,v); },
|
|
||||||
(s) => { return TerrainImplementation; },
|
(s) => { return TerrainImplementation; },
|
||||||
(s,p,l,v) => { TerrainImplementation = v; } ),
|
(s,v) => { TerrainImplementation = v; } ),
|
||||||
new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
||||||
0.3f,
|
0.3f,
|
||||||
(s,cf,p,v) => { TerrainFriction = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return TerrainFriction; },
|
(s) => { return TerrainFriction; },
|
||||||
(s,p,l,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ),
|
(s,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ),
|
||||||
new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
|
new ParameterDefn<float>("TerrainHitFraction", "Distance to measure hit collisions" ,
|
||||||
0.8f,
|
0.8f,
|
||||||
(s,cf,p,v) => { TerrainHitFraction = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return TerrainHitFraction; },
|
(s) => { return TerrainHitFraction; },
|
||||||
(s,p,l,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ),
|
(s,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ),
|
||||||
new ParameterDefn("TerrainRestitution", "Bouncyness" ,
|
new ParameterDefn<float>("TerrainRestitution", "Bouncyness" ,
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { TerrainRestitution = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return TerrainRestitution; },
|
(s) => { return TerrainRestitution; },
|
||||||
(s,p,l,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
|
(s,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
|
||||||
new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" ,
|
new ParameterDefn<float>("TerrainCollisionMargin", "Margin where collision checking starts" ,
|
||||||
0.08f,
|
0.08f,
|
||||||
(s,cf,p,v) => { TerrainCollisionMargin = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return TerrainCollisionMargin; },
|
(s) => { return TerrainCollisionMargin; },
|
||||||
(s,p,l,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
|
(s,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
|
||||||
|
|
||||||
new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
|
new ParameterDefn<float>("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
|
||||||
0.2f,
|
0.2f,
|
||||||
(s,cf,p,v) => { AvatarFriction = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AvatarFriction; },
|
(s) => { return AvatarFriction; },
|
||||||
(s,p,l,v) => { AvatarFriction = v; } ),
|
(s,v) => { AvatarFriction = v; } ),
|
||||||
new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
|
new ParameterDefn<float>("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
|
||||||
0.95f,
|
0.95f,
|
||||||
(s,cf,p,v) => { AvatarStandingFriction = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AvatarStandingFriction; },
|
(s) => { return AvatarStandingFriction; },
|
||||||
(s,p,l,v) => { AvatarStandingFriction = v; } ),
|
(s,v) => { AvatarStandingFriction = v; } ),
|
||||||
new ParameterDefn("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
|
new ParameterDefn<float>("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
|
||||||
1.3f,
|
1.3f,
|
||||||
(s,cf,p,v) => { AvatarAlwaysRunFactor = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AvatarAlwaysRunFactor; },
|
(s) => { return AvatarAlwaysRunFactor; },
|
||||||
(s,p,l,v) => { AvatarAlwaysRunFactor = v; } ),
|
(s,v) => { AvatarAlwaysRunFactor = v; } ),
|
||||||
new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
|
new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
|
||||||
3.5f,
|
3.5f,
|
||||||
(s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AvatarDensity; },
|
(s) => { return AvatarDensity; },
|
||||||
(s,p,l,v) => { AvatarDensity = v; } ),
|
(s,v) => { AvatarDensity = v; } ),
|
||||||
new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
|
new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { AvatarRestitution = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AvatarRestitution; },
|
(s) => { return AvatarRestitution; },
|
||||||
(s,p,l,v) => { AvatarRestitution = v; } ),
|
(s,v) => { AvatarRestitution = v; } ),
|
||||||
new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
|
new ParameterDefn<float>("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
|
||||||
0.6f,
|
0.6f,
|
||||||
(s,cf,p,v) => { AvatarCapsuleWidth = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AvatarCapsuleWidth; },
|
(s) => { return AvatarCapsuleWidth; },
|
||||||
(s,p,l,v) => { AvatarCapsuleWidth = v; } ),
|
(s,v) => { AvatarCapsuleWidth = v; } ),
|
||||||
new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
|
new ParameterDefn<float>("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
|
||||||
0.45f,
|
0.45f,
|
||||||
(s,cf,p,v) => { AvatarCapsuleDepth = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AvatarCapsuleDepth; },
|
(s) => { return AvatarCapsuleDepth; },
|
||||||
(s,p,l,v) => { AvatarCapsuleDepth = v; } ),
|
(s,v) => { AvatarCapsuleDepth = v; } ),
|
||||||
new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
|
new ParameterDefn<float>("AvatarCapsuleHeight", "Default height of space around avatar",
|
||||||
1.5f,
|
1.5f,
|
||||||
(s,cf,p,v) => { AvatarCapsuleHeight = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AvatarCapsuleHeight; },
|
(s) => { return AvatarCapsuleHeight; },
|
||||||
(s,p,l,v) => { AvatarCapsuleHeight = v; } ),
|
(s,v) => { AvatarCapsuleHeight = v; } ),
|
||||||
new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
|
new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
|
||||||
0.1f,
|
0.1f,
|
||||||
(s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AvatarContactProcessingThreshold; },
|
(s) => { return AvatarContactProcessingThreshold; },
|
||||||
(s,p,l,v) => { AvatarContactProcessingThreshold = v; } ),
|
(s,v) => { AvatarContactProcessingThreshold = v; } ),
|
||||||
new ParameterDefn("AvatarStepHeight", "Height of a step obstacle to consider step correction",
|
new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction",
|
||||||
0.3f,
|
0.3f,
|
||||||
(s,cf,p,v) => { AvatarStepHeight = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AvatarStepHeight; },
|
(s) => { return AvatarStepHeight; },
|
||||||
(s,p,l,v) => { AvatarStepHeight = v; } ),
|
(s,v) => { AvatarStepHeight = v; } ),
|
||||||
new ParameterDefn("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
|
new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
|
||||||
0.6f,
|
0.6f,
|
||||||
(s,cf,p,v) => { AvatarStepApproachFactor = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AvatarStepApproachFactor; },
|
(s) => { return AvatarStepApproachFactor; },
|
||||||
(s,p,l,v) => { AvatarStepApproachFactor = v; } ),
|
(s,v) => { AvatarStepApproachFactor = v; } ),
|
||||||
new ParameterDefn("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
|
new ParameterDefn<float>("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
|
||||||
2.0f,
|
2.0f,
|
||||||
(s,cf,p,v) => { AvatarStepForceFactor = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return AvatarStepForceFactor; },
|
(s) => { return AvatarStepForceFactor; },
|
||||||
(s,p,l,v) => { AvatarStepForceFactor = v; } ),
|
(s,v) => { AvatarStepForceFactor = v; } ),
|
||||||
|
|
||||||
new ParameterDefn("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle",
|
new ParameterDefn<float>("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle",
|
||||||
1000.0f,
|
1000.0f,
|
||||||
(s,cf,p,v) => { VehicleMaxLinearVelocity = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return (float)VehicleMaxLinearVelocity; },
|
(s) => { return (float)VehicleMaxLinearVelocity; },
|
||||||
(s,p,l,v) => { VehicleMaxLinearVelocity = v; VehicleMaxLinearVelocitySq = v * v; } ),
|
(s,v) => { VehicleMaxLinearVelocity = v; VehicleMaxLinearVelocitySq = v * v; } ),
|
||||||
new ParameterDefn("VehicleMaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to a vehicle",
|
new ParameterDefn<float>("VehicleMaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to a vehicle",
|
||||||
12.0f,
|
12.0f,
|
||||||
(s,cf,p,v) => { VehicleMaxAngularVelocity = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return (float)VehicleMaxAngularVelocity; },
|
(s) => { return (float)VehicleMaxAngularVelocity; },
|
||||||
(s,p,l,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ),
|
(s,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ),
|
||||||
new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
|
new ParameterDefn<float>("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
|
||||||
0.0f,
|
0.0f,
|
||||||
(s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return VehicleAngularDamping; },
|
(s) => { return VehicleAngularDamping; },
|
||||||
(s,p,l,v) => { VehicleAngularDamping = v; } ),
|
(s,v) => { VehicleAngularDamping = v; } ),
|
||||||
new ParameterDefn("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (0.0 - 1.0)",
|
new ParameterDefn<Vector3>("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (<0,0,0> to <1,1,1>)",
|
||||||
1.0f,
|
new Vector3(1f, 1f, 1f),
|
||||||
(s,cf,p,v) => { VehicleLinearFactor = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return VehicleLinearFactor; },
|
(s) => { return VehicleLinearFactor; },
|
||||||
(s,p,l,v) => { VehicleLinearFactor = v; VehicleLinearFactorV = new Vector3(v, v, v); } ),
|
(s,v) => { VehicleLinearFactor = v; } ),
|
||||||
new ParameterDefn("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (0.0 - 1.0)",
|
new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)",
|
||||||
1.0f,
|
new Vector3(1f, 1f, 1f),
|
||||||
(s,cf,p,v) => { VehicleAngularFactor = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return VehicleAngularFactor; },
|
(s) => { return VehicleAngularFactor; },
|
||||||
(s,p,l,v) => { VehicleAngularFactor = v; VehicleAngularFactorV = new Vector3(v, v, v); } ),
|
(s,v) => { VehicleAngularFactor = v; } ),
|
||||||
new ParameterDefn("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
|
new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
|
||||||
0.0f,
|
0.0f,
|
||||||
(s,cf,p,v) => { VehicleFriction = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return VehicleFriction; },
|
(s) => { return VehicleFriction; },
|
||||||
(s,p,l,v) => { VehicleFriction = v; } ),
|
(s,v) => { VehicleFriction = v; } ),
|
||||||
new ParameterDefn("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
|
new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
|
||||||
0.0f,
|
0.0f,
|
||||||
(s,cf,p,v) => { VehicleRestitution = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return VehicleRestitution; },
|
(s) => { return VehicleRestitution; },
|
||||||
(s,p,l,v) => { VehicleRestitution = v; } ),
|
(s,v) => { VehicleRestitution = v; } ),
|
||||||
new ParameterDefn("VehicleGroundGravityFudge", "Factor to multiple gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
|
new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiple gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
|
||||||
0.2f,
|
0.2f,
|
||||||
(s,cf,p,v) => { VehicleGroundGravityFudge = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return VehicleGroundGravityFudge; },
|
(s) => { return VehicleGroundGravityFudge; },
|
||||||
(s,p,l,v) => { VehicleGroundGravityFudge = v; } ),
|
(s,v) => { VehicleGroundGravityFudge = v; } ),
|
||||||
new ParameterDefn("VehicleDebuggingEnable", "Turn on/off vehicle debugging",
|
new ParameterDefn<bool>("VehicleDebuggingEnable", "Turn on/off vehicle debugging",
|
||||||
ConfigurationParameters.numericFalse,
|
false,
|
||||||
(s,cf,p,v) => { VehicleDebuggingEnabled = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
|
||||||
(s) => { return VehicleDebuggingEnabled; },
|
(s) => { return VehicleDebuggingEnabled; },
|
||||||
(s,p,l,v) => { VehicleDebuggingEnabled = v; } ),
|
(s,v) => { VehicleDebuggingEnabled = v; } ),
|
||||||
|
|
||||||
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
|
new ParameterDefn<float>("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { MaxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return MaxPersistantManifoldPoolSize; },
|
(s) => { return MaxPersistantManifoldPoolSize; },
|
||||||
(s,p,l,v) => { MaxPersistantManifoldPoolSize = v; s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ),
|
(s,v) => { MaxPersistantManifoldPoolSize = v; s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ),
|
||||||
new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
|
new ParameterDefn<float>("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { MaxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return MaxCollisionAlgorithmPoolSize; },
|
(s) => { return MaxCollisionAlgorithmPoolSize; },
|
||||||
(s,p,l,v) => { MaxCollisionAlgorithmPoolSize = v; s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ),
|
(s,v) => { MaxCollisionAlgorithmPoolSize = v; s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ),
|
||||||
new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
|
new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
|
||||||
ConfigurationParameters.numericFalse,
|
false,
|
||||||
(s,cf,p,v) => { ShouldDisableContactPoolDynamicAllocation = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
|
||||||
(s) => { return ShouldDisableContactPoolDynamicAllocation; },
|
(s) => { return ShouldDisableContactPoolDynamicAllocation; },
|
||||||
(s,p,l,v) => { ShouldDisableContactPoolDynamicAllocation = v; s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = v; } ),
|
(s,v) => { ShouldDisableContactPoolDynamicAllocation = v;
|
||||||
new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
|
s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ),
|
||||||
ConfigurationParameters.numericFalse,
|
new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
|
||||||
(s,cf,p,v) => { ShouldForceUpdateAllAabbs = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
false,
|
||||||
(s) => { return ShouldForceUpdateAllAabbs; },
|
(s) => { return ShouldForceUpdateAllAabbs; },
|
||||||
(s,p,l,v) => { ShouldForceUpdateAllAabbs = v; s.UnmanagedParams[0].shouldForceUpdateAllAabbs = v; } ),
|
(s,v) => { ShouldForceUpdateAllAabbs = v; s.UnmanagedParams[0].shouldForceUpdateAllAabbs = NumericBool(v); } ),
|
||||||
new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
|
new ParameterDefn<bool>("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
|
||||||
ConfigurationParameters.numericTrue,
|
true,
|
||||||
(s,cf,p,v) => { ShouldRandomizeSolverOrder = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
|
||||||
(s) => { return ShouldRandomizeSolverOrder; },
|
(s) => { return ShouldRandomizeSolverOrder; },
|
||||||
(s,p,l,v) => { ShouldRandomizeSolverOrder = v; s.UnmanagedParams[0].shouldRandomizeSolverOrder = v; } ),
|
(s,v) => { ShouldRandomizeSolverOrder = v; s.UnmanagedParams[0].shouldRandomizeSolverOrder = NumericBool(v); } ),
|
||||||
new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
|
new ParameterDefn<bool>("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
|
||||||
ConfigurationParameters.numericTrue,
|
true,
|
||||||
(s,cf,p,v) => { ShouldSplitSimulationIslands = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
|
||||||
(s) => { return ShouldSplitSimulationIslands; },
|
(s) => { return ShouldSplitSimulationIslands; },
|
||||||
(s,p,l,v) => { ShouldSplitSimulationIslands = v; s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ),
|
(s,v) => { ShouldSplitSimulationIslands = v; s.UnmanagedParams[0].shouldSplitSimulationIslands = NumericBool(v); } ),
|
||||||
new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
|
new ParameterDefn<bool>("ShouldEnableFrictionCaching", "Enable friction computation caching",
|
||||||
ConfigurationParameters.numericTrue,
|
true,
|
||||||
(s,cf,p,v) => { ShouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
|
||||||
(s) => { return ShouldEnableFrictionCaching; },
|
(s) => { return ShouldEnableFrictionCaching; },
|
||||||
(s,p,l,v) => { ShouldEnableFrictionCaching = v; s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ),
|
(s,v) => { ShouldEnableFrictionCaching = v; s.UnmanagedParams[0].shouldEnableFrictionCaching = NumericBool(v); } ),
|
||||||
new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
|
new ParameterDefn<float>("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
|
||||||
0f, // zero says use Bullet default
|
0f, // zero says use Bullet default
|
||||||
(s,cf,p,v) => { NumberOfSolverIterations = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return NumberOfSolverIterations; },
|
(s) => { return NumberOfSolverIterations; },
|
||||||
(s,p,l,v) => { NumberOfSolverIterations = v; s.UnmanagedParams[0].numberOfSolverIterations = v; } ),
|
(s,v) => { NumberOfSolverIterations = v; s.UnmanagedParams[0].numberOfSolverIterations = v; } ),
|
||||||
new ParameterDefn("UseSingleSidedMeshes", "Whether to compute collisions based on single sided meshes.",
|
new ParameterDefn<bool>("UseSingleSidedMeshes", "Whether to compute collisions based on single sided meshes.",
|
||||||
ConfigurationParameters.numericTrue,
|
true,
|
||||||
(s,cf,p,v) => { UseSingleSidedMeshesF = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
(s) => { return UseSingleSidedMeshes; },
|
||||||
(s) => { return UseSingleSidedMeshesF; },
|
(s,v) => { UseSingleSidedMeshes = v; s.UnmanagedParams[0].useSingleSidedMeshes = NumericBool(v); } ),
|
||||||
(s,p,l,v) => { UseSingleSidedMeshesF = v; s.UnmanagedParams[0].useSingleSidedMeshes = v; } ),
|
new ParameterDefn<float>("GlobalContactBreakingThreshold", "Amount of shape radius before breaking a collision contact (0 says Bullet default (0.2))",
|
||||||
new ParameterDefn("GlobalContactBreakingThreshold", "Amount of shape radius before breaking a collision contact (0 says Bullet default (0.2))",
|
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { GlobalContactBreakingThreshold = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return GlobalContactBreakingThreshold; },
|
(s) => { return GlobalContactBreakingThreshold; },
|
||||||
(s,p,l,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ),
|
(s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ),
|
||||||
|
|
||||||
new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
|
new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
|
||||||
(float)BSLinkset.LinksetImplementation.Compound,
|
(float)BSLinkset.LinksetImplementation.Compound,
|
||||||
(s,cf,p,v) => { LinksetImplementation = cf.GetFloat(p,v); },
|
|
||||||
(s) => { return LinksetImplementation; },
|
(s) => { return LinksetImplementation; },
|
||||||
(s,p,l,v) => { LinksetImplementation = v; } ),
|
(s,v) => { LinksetImplementation = v; } ),
|
||||||
new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
|
new ParameterDefn<bool>("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
|
||||||
ConfigurationParameters.numericFalse,
|
false,
|
||||||
(s,cf,p,v) => { LinkConstraintUseFrameOffset = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
|
||||||
(s) => { return LinkConstraintUseFrameOffset; },
|
(s) => { return LinkConstraintUseFrameOffset; },
|
||||||
(s,p,l,v) => { LinkConstraintUseFrameOffset = v; } ),
|
(s,v) => { LinkConstraintUseFrameOffset = v; } ),
|
||||||
new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
|
new ParameterDefn<bool>("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
|
||||||
ConfigurationParameters.numericTrue,
|
true,
|
||||||
(s,cf,p,v) => { LinkConstraintEnableTransMotor = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
|
||||||
(s) => { return LinkConstraintEnableTransMotor; },
|
(s) => { return LinkConstraintEnableTransMotor; },
|
||||||
(s,p,l,v) => { LinkConstraintEnableTransMotor = v; } ),
|
(s,v) => { LinkConstraintEnableTransMotor = v; } ),
|
||||||
new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
|
new ParameterDefn<float>("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
|
||||||
5.0f,
|
5.0f,
|
||||||
(s,cf,p,v) => { LinkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return LinkConstraintTransMotorMaxVel; },
|
(s) => { return LinkConstraintTransMotorMaxVel; },
|
||||||
(s,p,l,v) => { LinkConstraintTransMotorMaxVel = v; } ),
|
(s,v) => { LinkConstraintTransMotorMaxVel = v; } ),
|
||||||
new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
|
new ParameterDefn<float>("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
|
||||||
0.1f,
|
0.1f,
|
||||||
(s,cf,p,v) => { LinkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return LinkConstraintTransMotorMaxForce; },
|
(s) => { return LinkConstraintTransMotorMaxForce; },
|
||||||
(s,p,l,v) => { LinkConstraintTransMotorMaxForce = v; } ),
|
(s,v) => { LinkConstraintTransMotorMaxForce = v; } ),
|
||||||
new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
|
new ParameterDefn<float>("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
|
||||||
0.1f,
|
0.1f,
|
||||||
(s,cf,p,v) => { LinkConstraintCFM = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return LinkConstraintCFM; },
|
(s) => { return LinkConstraintCFM; },
|
||||||
(s,p,l,v) => { LinkConstraintCFM = v; } ),
|
(s,v) => { LinkConstraintCFM = v; } ),
|
||||||
new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
|
new ParameterDefn<float>("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
|
||||||
0.1f,
|
0.1f,
|
||||||
(s,cf,p,v) => { LinkConstraintERP = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return LinkConstraintERP; },
|
(s) => { return LinkConstraintERP; },
|
||||||
(s,p,l,v) => { LinkConstraintERP = v; } ),
|
(s,v) => { LinkConstraintERP = v; } ),
|
||||||
new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
|
new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
|
||||||
40,
|
40,
|
||||||
(s,cf,p,v) => { LinkConstraintSolverIterations = cf.GetFloat(p, v); },
|
|
||||||
(s) => { return LinkConstraintSolverIterations; },
|
(s) => { return LinkConstraintSolverIterations; },
|
||||||
(s,p,l,v) => { LinkConstraintSolverIterations = v; } ),
|
(s,v) => { LinkConstraintSolverIterations = v; } ),
|
||||||
|
|
||||||
new ParameterDefn("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)",
|
new ParameterDefn<int>("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)",
|
||||||
|
0,
|
||||||
|
(s) => { return s.PhysicsMetricDumpFrames; },
|
||||||
|
(s,v) => { s.PhysicsMetricDumpFrames = v; } ),
|
||||||
|
new ParameterDefn<float>("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool",
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { s.PhysicsMetricDumpFrames = cf.GetFloat(p, (int)v); },
|
|
||||||
(s) => { return (float)s.PhysicsMetricDumpFrames; },
|
|
||||||
(s,p,l,v) => { s.PhysicsMetricDumpFrames = (int)v; } ),
|
|
||||||
new ParameterDefn("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool",
|
|
||||||
0f,
|
|
||||||
(s,cf,p,v) => { ; },
|
|
||||||
(s) => { return 0f; },
|
(s) => { return 0f; },
|
||||||
(s,p,l,v) => { BSParam.ResetBroadphasePoolTainted(s, v); } ),
|
(s,v) => { BSParam.ResetBroadphasePoolTainted(s, v); } ),
|
||||||
new ParameterDefn("ResetConstraintSolver", "Setting this is any value resets the constraint solver",
|
new ParameterDefn<float>("ResetConstraintSolver", "Setting this is any value resets the constraint solver",
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { ; },
|
|
||||||
(s) => { return 0f; },
|
(s) => { return 0f; },
|
||||||
(s,p,l,v) => { BSParam.ResetConstraintSolverTainted(s, v); } ),
|
(s,v) => { BSParam.ResetConstraintSolverTainted(s, v); } ),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert a boolean to our numeric true and false values
|
// Convert a boolean to our numeric true and false values
|
||||||
|
@ -658,13 +644,13 @@ public static class BSParam
|
||||||
// ParameterDefn structure.
|
// ParameterDefn structure.
|
||||||
// Case does not matter as names are compared after converting to lower case.
|
// Case does not matter as names are compared after converting to lower case.
|
||||||
// Returns 'false' if the parameter is not found.
|
// Returns 'false' if the parameter is not found.
|
||||||
internal static bool TryGetParameter(string paramName, out ParameterDefn defn)
|
internal static bool TryGetParameter(string paramName, out ParameterDefnBase defn)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
ParameterDefn foundDefn = new ParameterDefn();
|
ParameterDefnBase foundDefn = null;
|
||||||
string pName = paramName.ToLower();
|
string pName = paramName.ToLower();
|
||||||
|
|
||||||
foreach (ParameterDefn parm in ParameterDefinitions)
|
foreach (ParameterDefnBase parm in ParameterDefinitions)
|
||||||
{
|
{
|
||||||
if (pName == parm.name.ToLower())
|
if (pName == parm.name.ToLower())
|
||||||
{
|
{
|
||||||
|
@ -680,18 +666,18 @@ public static class BSParam
|
||||||
// Pass through the settable parameters and set the default values
|
// Pass through the settable parameters and set the default values
|
||||||
internal static void SetParameterDefaultValues(BSScene physicsScene)
|
internal static void SetParameterDefaultValues(BSScene physicsScene)
|
||||||
{
|
{
|
||||||
foreach (ParameterDefn parm in ParameterDefinitions)
|
foreach (ParameterDefnBase parm in ParameterDefinitions)
|
||||||
{
|
{
|
||||||
parm.setter(physicsScene, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
|
parm.AssignDefault(physicsScene);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get user set values out of the ini file.
|
// Get user set values out of the ini file.
|
||||||
internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg)
|
internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg)
|
||||||
{
|
{
|
||||||
foreach (ParameterDefn parm in ParameterDefinitions)
|
foreach (ParameterDefnBase parm in ParameterDefinitions)
|
||||||
{
|
{
|
||||||
parm.userParam(physicsScene, cfg, parm.name, parm.defaultValue);
|
parm.SetValue(physicsScene, cfg.GetString(parm.name, parm.GetValue(physicsScene)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,17 +692,21 @@ public static class BSParam
|
||||||
List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
|
List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
|
||||||
for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
|
for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
|
||||||
{
|
{
|
||||||
ParameterDefn pd = ParameterDefinitions[ii];
|
ParameterDefnBase pd = ParameterDefinitions[ii];
|
||||||
entries.Add(new PhysParameterEntry(pd.name, pd.desc));
|
entries.Add(new PhysParameterEntry(pd.name, pd.desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
// make the list alphabetical for estetic reasons
|
// make the list alphabetical for ease of finding anything
|
||||||
entries.Sort((ppe1, ppe2) => { return ppe1.name.CompareTo(ppe2.name); });
|
entries.Sort((ppe1, ppe2) => { return ppe1.name.CompareTo(ppe2.name); });
|
||||||
|
|
||||||
SettableParameters = entries.ToArray();
|
SettableParameters = entries.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =====================================================================
|
||||||
|
// =====================================================================
|
||||||
|
// There are parameters that, when set, cause things to happen in the physics engine.
|
||||||
|
// This causes the broadphase collision cache to be cleared.
|
||||||
private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v)
|
private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v)
|
||||||
{
|
{
|
||||||
BSScene physScene = pPhysScene;
|
BSScene physScene = pPhysScene;
|
||||||
|
@ -726,6 +716,7 @@ public static class BSParam
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This causes the constraint solver cache to be cleared and reset.
|
||||||
private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v)
|
private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v)
|
||||||
{
|
{
|
||||||
BSScene physScene = pPhysScene;
|
BSScene physScene = pPhysScene;
|
||||||
|
|
|
@ -70,6 +70,8 @@ public class BSPrim : BSPhysObject
|
||||||
private bool _kinematic;
|
private bool _kinematic;
|
||||||
private float _buoyancy;
|
private float _buoyancy;
|
||||||
|
|
||||||
|
private int CrossingFailures { get; set; }
|
||||||
|
|
||||||
public BSDynamics VehicleController { get; private set; }
|
public BSDynamics VehicleController { get; private set; }
|
||||||
|
|
||||||
private BSVMotor _targetMotor;
|
private BSVMotor _targetMotor;
|
||||||
|
@ -197,7 +199,20 @@ public class BSPrim : BSPhysObject
|
||||||
{
|
{
|
||||||
get { return _isSelected; }
|
get { return _isSelected; }
|
||||||
}
|
}
|
||||||
public override void CrossingFailure() { return; }
|
|
||||||
|
public override void CrossingFailure()
|
||||||
|
{
|
||||||
|
CrossingFailures++;
|
||||||
|
if (CrossingFailures > BSParam.CrossingFailuresBeforeOutOfBounds)
|
||||||
|
{
|
||||||
|
base.RaiseOutOfBounds(RawPosition);
|
||||||
|
}
|
||||||
|
else if (CrossingFailures == BSParam.CrossingFailuresBeforeOutOfBounds)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("{0} Too many crossing failures for {1}", LogHeader, Name);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// link me to the specified parent
|
// link me to the specified parent
|
||||||
public override void link(PhysicsActor obj) {
|
public override void link(PhysicsActor obj) {
|
||||||
|
@ -239,50 +254,98 @@ public class BSPrim : BSPhysObject
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TryExperimentalLockAxisCode = false;
|
||||||
|
BSConstraint LockAxisConstraint = null;
|
||||||
public override void LockAngularMotion(OMV.Vector3 axis)
|
public override void LockAngularMotion(OMV.Vector3 axis)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
|
DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
|
||||||
|
|
||||||
|
// "1" means free, "0" means locked
|
||||||
OMV.Vector3 locking = new OMV.Vector3(1f, 1f, 1f);
|
OMV.Vector3 locking = new OMV.Vector3(1f, 1f, 1f);
|
||||||
if (axis.X != 1) locking.X = 0f;
|
if (axis.X != 1) locking.X = 0f;
|
||||||
if (axis.Y != 1) locking.Y = 0f;
|
if (axis.Y != 1) locking.Y = 0f;
|
||||||
if (axis.Z != 1) locking.Z = 0f;
|
if (axis.Z != 1) locking.Z = 0f;
|
||||||
LockedAxis = locking;
|
LockedAxis = locking;
|
||||||
|
|
||||||
/* Not implemented yet
|
if (TryExperimentalLockAxisCode && LockedAxis != LockedAxisFree)
|
||||||
if (LockedAxis != LockedAxisFree)
|
|
||||||
{
|
{
|
||||||
// Something is locked so start the thingy that keeps that axis from changing
|
// Lock that axis by creating a 6DOF constraint that has one end in the world and
|
||||||
RegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion", delegate(ref EntityProperties entprop)
|
// the other in the object.
|
||||||
{
|
// http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817
|
||||||
if (LockedAxis != LockedAxisFree)
|
// http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380
|
||||||
{
|
|
||||||
if (IsPhysicallyActive)
|
|
||||||
{
|
|
||||||
// Bullet can lock axis but it only works for global axis.
|
|
||||||
// Check if this prim is aligned on global axis and use Bullet's
|
|
||||||
// system if so.
|
|
||||||
|
|
||||||
ForceOrientation = entprop.Rotation;
|
PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
|
||||||
ForceRotationalVelocity = entprop.RotationalVelocity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion");
|
CleanUpLockAxisPhysicals(true /* inTaintTime */);
|
||||||
}
|
|
||||||
|
|
||||||
|
BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(PhysicsScene.World, PhysBody,
|
||||||
|
OMV.Vector3.Zero, OMV.Quaternion.Inverse(RawOrientation),
|
||||||
|
true /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */);
|
||||||
|
LockAxisConstraint = axisConstrainer;
|
||||||
|
PhysicsScene.Constraints.AddConstraint(LockAxisConstraint);
|
||||||
|
|
||||||
|
// The constraint is tied to the world and oriented to the prim.
|
||||||
|
|
||||||
|
// Free to move linearly
|
||||||
|
OMV.Vector3 linearLow = OMV.Vector3.Zero;
|
||||||
|
OMV.Vector3 linearHigh = PhysicsScene.TerrainManager.DefaultRegionSize;
|
||||||
|
axisConstrainer.SetLinearLimits(linearLow, linearHigh);
|
||||||
|
|
||||||
|
// Angular with some axis locked
|
||||||
|
float f2PI = (float)Math.PI * 2f;
|
||||||
|
OMV.Vector3 angularLow = new OMV.Vector3(-f2PI, -f2PI, -f2PI);
|
||||||
|
OMV.Vector3 angularHigh = new OMV.Vector3(f2PI, f2PI, f2PI);
|
||||||
|
if (LockedAxis.X != 1f)
|
||||||
|
{
|
||||||
|
angularLow.X = 0f;
|
||||||
|
angularHigh.X = 0f;
|
||||||
|
}
|
||||||
|
if (LockedAxis.Y != 1f)
|
||||||
|
{
|
||||||
|
angularLow.Y = 0f;
|
||||||
|
angularHigh.Y = 0f;
|
||||||
|
}
|
||||||
|
if (LockedAxis.Z != 1f)
|
||||||
|
{
|
||||||
|
angularLow.Z = 0f;
|
||||||
|
angularHigh.Z = 0f;
|
||||||
|
}
|
||||||
|
axisConstrainer.SetAngularLimits(angularLow, angularHigh);
|
||||||
|
|
||||||
|
DetailLog("{0},BSPrim.LockAngularMotion,create,linLow={1},linHi={2},angLow={3},angHi={4}",
|
||||||
|
LocalID, linearLow, linearHigh, angularLow, angularHigh);
|
||||||
|
|
||||||
|
// Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo.
|
||||||
|
axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f);
|
||||||
|
|
||||||
|
axisConstrainer.RecomputeConstraintVariables(RawMass);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Everything seems unlocked
|
// Everything seems unlocked
|
||||||
UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion");
|
CleanUpLockAxisPhysicals(false /* inTaintTime */);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Get rid of any constraint built for LockAxis
|
||||||
|
// Most often the constraint is removed when the constraint collection is cleaned for this prim.
|
||||||
|
private void CleanUpLockAxisPhysicals(bool inTaintTime)
|
||||||
|
{
|
||||||
|
if (LockAxisConstraint != null)
|
||||||
|
{
|
||||||
|
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.CleanUpLockAxisPhysicals", delegate()
|
||||||
|
{
|
||||||
|
if (LockAxisConstraint != null)
|
||||||
|
{
|
||||||
|
PhysicsScene.Constraints.RemoveAndDestroyConstraint(LockAxisConstraint);
|
||||||
|
LockAxisConstraint = null;
|
||||||
|
DetailLog("{0},BSPrim.CleanUpLockAxisPhysicals,destroyingConstraint", LocalID);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override OMV.Vector3 RawPosition
|
public override OMV.Vector3 RawPosition
|
||||||
{
|
{
|
||||||
|
@ -762,6 +825,7 @@ public class BSPrim : BSPhysObject
|
||||||
SetObjectDynamic(true);
|
SetObjectDynamic(true);
|
||||||
// whether phys-to-static or static-to-phys, the object is not moving.
|
// whether phys-to-static or static-to-phys, the object is not moving.
|
||||||
ZeroMotion(true);
|
ZeroMotion(true);
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -885,6 +949,8 @@ public class BSPrim : BSPhysObject
|
||||||
|
|
||||||
// For good measure, make sure the transform is set through to the motion state
|
// For good measure, make sure the transform is set through to the motion state
|
||||||
ForcePosition = _position;
|
ForcePosition = _position;
|
||||||
|
ForceVelocity = _velocity;
|
||||||
|
ForceRotationalVelocity = _rotationalVelocity;
|
||||||
|
|
||||||
// A dynamic object has mass
|
// A dynamic object has mass
|
||||||
UpdatePhysicalMassProperties(RawMass, false);
|
UpdatePhysicalMassProperties(RawMass, false);
|
||||||
|
@ -1064,15 +1130,19 @@ public class BSPrim : BSPhysObject
|
||||||
_buoyancy = value;
|
_buoyancy = value;
|
||||||
// DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
// DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
||||||
// Force the recalculation of the various inertia,etc variables in the object
|
// Force the recalculation of the various inertia,etc variables in the object
|
||||||
DetailLog("{0},BSPrim.ForceBuoyancy,buoy={1},mass={2}", LocalID, _buoyancy, _mass);
|
UpdatePhysicalMassProperties(RawMass, true);
|
||||||
UpdatePhysicalMassProperties(_mass, true);
|
DetailLog("{0},BSPrim.ForceBuoyancy,buoy={1},mass={2},grav={3}", LocalID, _buoyancy, RawMass, Gravity);
|
||||||
ActivateIfPhysical(false);
|
ActivateIfPhysical(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for MoveTo
|
// Used for MoveTo
|
||||||
public override OMV.Vector3 PIDTarget {
|
public override OMV.Vector3 PIDTarget {
|
||||||
set { _PIDTarget = value; }
|
set
|
||||||
|
{
|
||||||
|
// TODO: add a sanity check -- don't move more than a region or something like that.
|
||||||
|
_PIDTarget = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public override float PIDTau {
|
public override float PIDTau {
|
||||||
set { _PIDTau = value; }
|
set { _PIDTau = value; }
|
||||||
|
@ -1126,7 +1196,9 @@ public class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ForcePosition = movePosition;
|
_position = movePosition;
|
||||||
|
PositionSanityCheck(true /* intaintTime */);
|
||||||
|
ForcePosition = _position;
|
||||||
}
|
}
|
||||||
DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition);
|
DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition);
|
||||||
});
|
});
|
||||||
|
@ -1303,6 +1375,7 @@ public class BSPrim : BSPhysObject
|
||||||
{
|
{
|
||||||
if (PhysBody.HasPhysicalBody)
|
if (PhysBody.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
|
DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce);
|
||||||
PhysicsScene.PE.ApplyTorque(PhysBody, angForce);
|
PhysicsScene.PE.ApplyTorque(PhysBody, angForce);
|
||||||
ActivateIfPhysical(false);
|
ActivateIfPhysical(false);
|
||||||
}
|
}
|
||||||
|
@ -1667,7 +1740,7 @@ public class BSPrim : BSPhysObject
|
||||||
// _velocity = entprop.Velocity;
|
// _velocity = entprop.Velocity;
|
||||||
// DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
|
// DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
|
||||||
// very sensitive to velocity changes.
|
// very sensitive to velocity changes.
|
||||||
if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f))
|
if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(_velocity, 0.1f))
|
||||||
_velocity = entprop.Velocity;
|
_velocity = entprop.Velocity;
|
||||||
_acceleration = entprop.Acceleration;
|
_acceleration = entprop.Acceleration;
|
||||||
_rotationalVelocity = entprop.RotationalVelocity;
|
_rotationalVelocity = entprop.RotationalVelocity;
|
||||||
|
|
|
@ -161,7 +161,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
private int m_physicsLoggingFileMinutes;
|
private int m_physicsLoggingFileMinutes;
|
||||||
private bool m_physicsLoggingDoFlush;
|
private bool m_physicsLoggingDoFlush;
|
||||||
private bool m_physicsPhysicalDumpEnabled;
|
private bool m_physicsPhysicalDumpEnabled;
|
||||||
public float PhysicsMetricDumpFrames { get; set; }
|
public int PhysicsMetricDumpFrames { get; set; }
|
||||||
// 'true' of the vehicle code is to log lots of details
|
// 'true' of the vehicle code is to log lots of details
|
||||||
public bool VehicleLoggingEnabled { get; private set; }
|
public bool VehicleLoggingEnabled { get; private set; }
|
||||||
public bool VehiclePhysicalLoggingEnabled { get; private set; }
|
public bool VehiclePhysicalLoggingEnabled { get; private set; }
|
||||||
|
@ -542,7 +542,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
collidersCount = 0;
|
collidersCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_simulationStep % PhysicsMetricDumpFrames) == 0)
|
if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0))
|
||||||
PE.DumpPhysicsStatistics(World);
|
PE.DumpPhysicsStatistics(World);
|
||||||
|
|
||||||
// Get a value for 'now' so all the collision and update routines don't have to get their own.
|
// Get a value for 'now' so all the collision and update routines don't have to get their own.
|
||||||
|
@ -880,38 +880,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
float valf = 0f;
|
BSParam.ParameterDefnBase theParam;
|
||||||
if (val.ToLower() == "true")
|
|
||||||
{
|
|
||||||
valf = PhysParameterEntry.NUMERIC_TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (val.ToLower() == "false")
|
|
||||||
{
|
|
||||||
valf = PhysParameterEntry.NUMERIC_FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
valf = float.Parse(val);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
valf = 0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BSParam.ParameterDefn theParam;
|
|
||||||
if (BSParam.TryGetParameter(parm, out theParam))
|
if (BSParam.TryGetParameter(parm, out theParam))
|
||||||
{
|
{
|
||||||
// Set the value in the C# code
|
// Set the value in the C# code
|
||||||
theParam.setter(this, parm, localID, valf);
|
theParam.SetValue(this, val);
|
||||||
|
|
||||||
// Optionally set the parameter in the unmanaged code
|
// Optionally set the parameter in the unmanaged code
|
||||||
if (theParam.onObject != null)
|
if (theParam.HasSetOnObject)
|
||||||
{
|
{
|
||||||
// update all the localIDs specified
|
// update all the localIDs specified
|
||||||
// If the local ID is APPLY_TO_NONE, just change the default value
|
// If the local ID is APPLY_TO_NONE, just change the default value
|
||||||
|
@ -923,16 +899,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
case PhysParameterEntry.APPLY_TO_NONE:
|
case PhysParameterEntry.APPLY_TO_NONE:
|
||||||
// This will cause a call into the physical world if some operation is specified (SetOnObject).
|
// This will cause a call into the physical world if some operation is specified (SetOnObject).
|
||||||
objectIDs.Add(TERRAIN_ID);
|
objectIDs.Add(TERRAIN_ID);
|
||||||
TaintedUpdateParameter(parm, objectIDs, valf);
|
TaintedUpdateParameter(parm, objectIDs, val);
|
||||||
break;
|
break;
|
||||||
case PhysParameterEntry.APPLY_TO_ALL:
|
case PhysParameterEntry.APPLY_TO_ALL:
|
||||||
lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
|
lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
|
||||||
TaintedUpdateParameter(parm, objectIDs, valf);
|
TaintedUpdateParameter(parm, objectIDs, val);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// setting only one localID
|
// setting only one localID
|
||||||
objectIDs.Add(localID);
|
objectIDs.Add(localID);
|
||||||
TaintedUpdateParameter(parm, objectIDs, valf);
|
TaintedUpdateParameter(parm, objectIDs, val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -943,22 +919,22 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
// schedule the actual updating of the paramter to when the phys engine is not busy
|
// schedule the actual updating of the paramter to when the phys engine is not busy
|
||||||
private void TaintedUpdateParameter(string parm, List<uint> lIDs, float val)
|
private void TaintedUpdateParameter(string parm, List<uint> lIDs, string val)
|
||||||
{
|
{
|
||||||
float xval = val;
|
string xval = val;
|
||||||
List<uint> xlIDs = lIDs;
|
List<uint> xlIDs = lIDs;
|
||||||
string xparm = parm;
|
string xparm = parm;
|
||||||
TaintedObject("BSScene.UpdateParameterSet", delegate() {
|
TaintedObject("BSScene.UpdateParameterSet", delegate() {
|
||||||
BSParam.ParameterDefn thisParam;
|
BSParam.ParameterDefnBase thisParam;
|
||||||
if (BSParam.TryGetParameter(xparm, out thisParam))
|
if (BSParam.TryGetParameter(xparm, out thisParam))
|
||||||
{
|
{
|
||||||
if (thisParam.onObject != null)
|
if (thisParam.HasSetOnObject)
|
||||||
{
|
{
|
||||||
foreach (uint lID in xlIDs)
|
foreach (uint lID in xlIDs)
|
||||||
{
|
{
|
||||||
BSPhysObject theObject = null;
|
BSPhysObject theObject = null;
|
||||||
if (PhysObjects.TryGetValue(lID, out theObject))
|
if (PhysObjects.TryGetValue(lID, out theObject))
|
||||||
thisParam.onObject(this, theObject, xval);
|
thisParam.SetOnObject(this, theObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -971,10 +947,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
{
|
{
|
||||||
string val = String.Empty;
|
string val = String.Empty;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
BSParam.ParameterDefn theParam;
|
BSParam.ParameterDefnBase theParam;
|
||||||
if (BSParam.TryGetParameter(parm, out theParam))
|
if (BSParam.TryGetParameter(parm, out theParam))
|
||||||
{
|
{
|
||||||
val = theParam.getter(this).ToString();
|
val = theParam.GetValue(this);
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
value = val;
|
value = val;
|
||||||
|
|
|
@ -568,7 +568,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
{
|
{
|
||||||
|
|
||||||
newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale);
|
newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale);
|
||||||
if (DDetail) DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
|
if (DDetail) DetailLog("{0},BSShapeCollection.BuildPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
CURRENT PRIORITIES
|
CURRENT PRIORITIES
|
||||||
=================================================
|
=================================================
|
||||||
One sided meshes? Should terrain be built into a closed shape?
|
|
||||||
When meshes get partially wedged into the terrain, they cannot push themselves out.
|
|
||||||
It is possible that Bullet processes collisions whether entering or leaving a mesh.
|
|
||||||
Ref: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4869
|
|
||||||
Deleting a linkset while standing on the root will leave the physical shape of the root behind.
|
Deleting a linkset while standing on the root will leave the physical shape of the root behind.
|
||||||
Not sure if it is because standing on it. Done with large prim linksets.
|
Not sure if it is because standing on it. Done with large prim linksets.
|
||||||
Terrain detail: double terrain mesh detail
|
|
||||||
Vehicle angular vertical attraction
|
Vehicle angular vertical attraction
|
||||||
vehicle angular banking
|
vehicle angular banking
|
||||||
Center-of-gravity
|
Center-of-gravity
|
||||||
Vehicle angular deflection
|
Vehicle angular deflection
|
||||||
Preferred orientation angular correction fix
|
Preferred orientation angular correction fix
|
||||||
|
Enable vehicle border crossings (at least as poorly as ODE)
|
||||||
|
Terrain skirts
|
||||||
|
Avatar created in previous region and not new region when crossing border
|
||||||
|
Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
|
||||||
when should angular and linear motor targets be zeroed? when selected?
|
when should angular and linear motor targets be zeroed? when selected?
|
||||||
Need a vehicle.clear()? Or an 'else' in prestep if not physical.
|
Need a vehicle.clear()? Or an 'else' in prestep if not physical.
|
||||||
Teravus llMoveToTarget script debug
|
Teravus llMoveToTarget script debug
|
||||||
|
@ -26,14 +25,16 @@ Avatar movement
|
||||||
flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
|
flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
|
||||||
walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
|
walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
|
||||||
avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution)
|
avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution)
|
||||||
Enable vehicle border crossings (at least as poorly as ODE)
|
|
||||||
Terrain skirts
|
|
||||||
Avatar created in previous region and not new region when crossing border
|
|
||||||
Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
|
|
||||||
Vehicle script tuning/debugging
|
Vehicle script tuning/debugging
|
||||||
Avanti speed script
|
Avanti speed script
|
||||||
Weapon shooter script
|
Weapon shooter script
|
||||||
Add material densities to the material types
|
Move material definitions (friction, ...) into simulator.
|
||||||
|
Add material densities to the material types.
|
||||||
|
Terrain detail: double terrain mesh detail
|
||||||
|
One sided meshes? Should terrain be built into a closed shape?
|
||||||
|
When meshes get partially wedged into the terrain, they cannot push themselves out.
|
||||||
|
It is possible that Bullet processes collisions whether entering or leaving a mesh.
|
||||||
|
Ref: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4869
|
||||||
|
|
||||||
VEHICLES TODO LIST:
|
VEHICLES TODO LIST:
|
||||||
=================================================
|
=================================================
|
||||||
|
@ -65,6 +66,7 @@ Vehicle attributes are not restored when a vehicle is rezzed on region creation
|
||||||
|
|
||||||
GENERAL TODO LIST:
|
GENERAL TODO LIST:
|
||||||
=================================================
|
=================================================
|
||||||
|
Add a sanity check for PIDTarget location.
|
||||||
Level-of-detail for mesh creation. Prims with circular interiors require lod of 32.
|
Level-of-detail for mesh creation. Prims with circular interiors require lod of 32.
|
||||||
Is much saved with lower LODs? At the moment, all set to 32.
|
Is much saved with lower LODs? At the moment, all set to 32.
|
||||||
Collisions are inconsistant: arrows are supposed to hit and report collision. Often don't.
|
Collisions are inconsistant: arrows are supposed to hit and report collision. Often don't.
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -33,4 +33,4 @@ using System.Runtime.InteropServices;
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -2172,9 +2172,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
CheckThreatLevel(ThreatLevel.Moderate, "osGetGridHomeURI");
|
CheckThreatLevel(ThreatLevel.Moderate, "osGetGridHomeURI");
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
|
|
||||||
string HomeURI = String.Empty;
|
|
||||||
IConfigSource config = m_ScriptEngine.ConfigSource;
|
IConfigSource config = m_ScriptEngine.ConfigSource;
|
||||||
|
string HomeURI = Util.GetConfigVarWithDefaultSection(config, "HomeURI", string.Empty);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(HomeURI))
|
||||||
|
return HomeURI;
|
||||||
|
|
||||||
|
// Legacy. Remove soon!
|
||||||
if (config.Configs["LoginService"] != null)
|
if (config.Configs["LoginService"] != null)
|
||||||
HomeURI = config.Configs["LoginService"].GetString("SRV_HomeURI", HomeURI);
|
HomeURI = config.Configs["LoginService"].GetString("SRV_HomeURI", HomeURI);
|
||||||
|
|
||||||
|
@ -2189,9 +2193,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
CheckThreatLevel(ThreatLevel.Moderate, "osGetGridGatekeeperURI");
|
CheckThreatLevel(ThreatLevel.Moderate, "osGetGridGatekeeperURI");
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
|
|
||||||
string gatekeeperURI = String.Empty;
|
|
||||||
IConfigSource config = m_ScriptEngine.ConfigSource;
|
IConfigSource config = m_ScriptEngine.ConfigSource;
|
||||||
|
string gatekeeperURI = Util.GetConfigVarWithDefaultSection(config, "GatekeeperURI", string.Empty);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(gatekeeperURI))
|
||||||
|
return gatekeeperURI;
|
||||||
|
|
||||||
|
// Legacy. Remove soon!
|
||||||
if (config.Configs["GridService"] != null)
|
if (config.Configs["GridService"] != null)
|
||||||
gatekeeperURI = config.Configs["GridService"].GetString("Gatekeeper", gatekeeperURI);
|
gatekeeperURI = config.Configs["GridService"].GetString("Gatekeeper", gatekeeperURI);
|
||||||
|
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.6.*")]
|
[assembly: AssemblyVersion("0.7.6.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue