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 : AssemblyFileVersion("0.6.5.0")]
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[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:
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
[assembly : AssemblyFileVersion("0.6.5.0")]
|
||||
|
||||
|
|
|
@ -306,5 +306,65 @@ namespace OpenSim.Data.MySQL
|
|||
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:
|
||||
|
||||
[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:
|
||||
|
||||
[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:
|
||||
|
||||
[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:
|
||||
|
||||
[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 : AssemblyFileVersion("0.6.5.0")]
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[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:
|
||||
|
||||
[assembly : AssemblyVersion("0.7.6.*")]
|
||||
[assembly : AssemblyFileVersion("0.6.5.0")]
|
||||
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[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.
|
||||
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 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
|
||||
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
|
||||
show object pos ,20,20 to ,40,40
|
||||
delete object pos ,,30 to ,,~
|
||||
delete object pos ,,-~ to ,,30";
|
||||
show object pos ,,-~ to ,,30";
|
||||
|
||||
public const string MinRawConsoleVectorValue = "-~";
|
||||
public const string MaxRawConsoleVectorValue = "~";
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
using System;
|
||||
using System.Timers;
|
||||
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -100,5 +102,29 @@ Asset requests yesterday : {3} ({4} per hour) of which {5} were not found",
|
|||
AssetRequestsToday, assetRequestsTodayPerHour, AssetRequestsNotFoundToday,
|
||||
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() ;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -45,5 +47,12 @@ namespace OpenSim.Framework.Monitoring
|
|||
/// A <see cref="System.String"/>
|
||||
/// </returns>
|
||||
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
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
|
|
@ -404,6 +404,15 @@ Asset service request failures: {3}" + Environment.NewLine,
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
// 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["Version"] = OSD.FromString (version);
|
||||
|
||||
string strBuffer = "";
|
||||
strBuffer = OSDParser.SerializeJsonString(args);
|
||||
return args;
|
||||
}
|
||||
}
|
||||
|
||||
return strBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pull packet queue stats from packet queues and report
|
||||
|
@ -474,5 +481,11 @@ Asset service request failures: {3}" + Environment.NewLine,
|
|||
{
|
||||
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.Text;
|
||||
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds individual statistic details
|
||||
/// </summary>
|
||||
public class Stat
|
||||
public class Stat : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Category of this stat (e.g. cache, scene, etc).
|
||||
|
@ -181,6 +183,12 @@ namespace OpenSim.Framework.Monitoring
|
|||
Verbosity = verbosity;
|
||||
}
|
||||
|
||||
// IDisposable.Dispose()
|
||||
public virtual void Dispose()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record a value in the sample set.
|
||||
/// </summary>
|
||||
|
@ -210,6 +218,20 @@ namespace OpenSim.Framework.Monitoring
|
|||
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)
|
||||
{
|
||||
if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime)
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
using System.Timers;
|
||||
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -88,5 +90,21 @@ namespace OpenSim.Framework.Monitoring
|
|||
Logouts total : {3}",
|
||||
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
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
|
|
@ -875,7 +875,7 @@ namespace OpenSim.Framework
|
|||
return FileName;
|
||||
}
|
||||
|
||||
// Nini (config) related Methods
|
||||
#region Nini (config) related Methods
|
||||
public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string 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)
|
||||
{
|
||||
return Math.Min(Math.Max(x, min), max);
|
||||
|
|
|
@ -1445,7 +1445,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
string param, IOSHttpRequest httpRequest,
|
||||
IOSHttpResponse httpResponse)
|
||||
{
|
||||
OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
|
||||
// OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
|
||||
OSDMap resp = new OSDMap();
|
||||
|
||||
OSDMap accessPrefs = new OSDMap();
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[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")]
|
||||
public class RegionConsoleModule : INonSharedRegionModule, IRegionConsole
|
||||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log =
|
||||
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private Scene m_scene;
|
||||
private IEventQueue m_eventQueue;
|
||||
|
@ -164,8 +164,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
|
||||
public class ConsoleHandler : BaseStreamHandler
|
||||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log =
|
||||
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private RegionConsoleModule m_consoleModule;
|
||||
private UUID m_agentID;
|
||||
|
|
|
@ -3892,6 +3892,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
||||
public OSDMap OReport(string uptime, string version)
|
||||
{
|
||||
return new OSDMap();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make an asset request to the asset service in response to a client request.
|
||||
/// </summary>
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[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);
|
||||
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_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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,12 +88,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"];
|
||||
if (thisModuleConfig != null)
|
||||
{
|
||||
// legacy configuration [obsolete]
|
||||
m_HomeURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty);
|
||||
// preferred
|
||||
m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI);
|
||||
m_HomeURI = Util.GetConfigVarWithDefaultSection(source, "HomeURI", "HGInventoryAccessModule");
|
||||
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);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
|
|||
private TimeSpan m_logFileLife;
|
||||
private DateTime m_logFileEndTime;
|
||||
private Object m_logFileWriteLock = new Object();
|
||||
private bool m_flushWrite;
|
||||
|
||||
// set externally when debugging. If let 'null', this does not write any error messages.
|
||||
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="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>
|
||||
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;
|
||||
|
||||
|
@ -86,8 +89,14 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
|
|||
m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0);
|
||||
m_logFileEndTime = DateTime.Now + m_logFileLife;
|
||||
|
||||
m_flushWrite = flushWrite;
|
||||
|
||||
Enabled = true;
|
||||
}
|
||||
// Constructor that assumes flushWrite is off.
|
||||
public LogWriter(string dir, string headr, int maxFileTime) : this(dir, headr, maxFileTime, false)
|
||||
{
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
@ -153,6 +162,8 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
|
|||
buff.Append(line);
|
||||
buff.Append("\r\n");
|
||||
m_logFile.Write(buff.ToString());
|
||||
if (m_flushWrite)
|
||||
m_logFile.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ using Mono.Addins;
|
|||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
||||
[assembly: Addin("OpenSim.Region.CoreModules", "0.1")]
|
||||
[assembly: AddinDependency("OpenSim", "0.5")]
|
||||
|
|
|
@ -416,7 +416,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -425,7 +425,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -896,17 +896,17 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
|||
|
||||
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;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single();
|
||||
string rawConsoleEndVector = rawComponents.Skip(2).Take(1).Single();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -113,9 +113,16 @@ namespace OpenSim.Region.DataSnapshot
|
|||
try
|
||||
{
|
||||
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"];
|
||||
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(
|
||||
"name", config.Configs["DataSnapshot"].GetString("gridname", "the lost continent of hippo"));
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[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);
|
||||
bool TestStore(UUID storeID);
|
||||
bool TestPath(UUID storeID, string path, bool useJson);
|
||||
|
||||
bool SetValue(UUID storeID, string path, string value, bool useJson);
|
||||
bool RemoveValue(UUID storeID, string path);
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[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
|
||||
int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X);
|
||||
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;
|
||||
|
||||
if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
|
||||
|
|
|
@ -222,7 +222,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
|
|||
{
|
||||
bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(sp);
|
||||
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
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
||||
[assembly: Addin("OpenSim.Region.OptionalModules", "0.1")]
|
||||
[assembly: AddinDependency("OpenSim", "0.5")]
|
||||
|
|
|
@ -84,11 +84,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
|||
protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])");
|
||||
|
||||
// extract the internals of an array reference
|
||||
protected static Regex m_SimpleArrayPattern = new Regex("\\[([0-9]+)\\]");
|
||||
protected static Regex m_ArrayPattern = new Regex("\\[([0-9]+|\\+)\\]");
|
||||
protected static Regex m_SimpleArrayPattern = new Regex("^\\[([0-9]+)\\]$");
|
||||
protected static Regex m_ArrayPattern = new Regex("^\\[([0-9]+|\\+)\\]$");
|
||||
|
||||
// extract the internals of a has reference
|
||||
protected static Regex m_HashPattern = new Regex("{([^}]+)}");
|
||||
protected static Regex m_HashPattern = new Regex("^{([^}]+)}$");
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
|
@ -168,28 +168,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
|||
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>
|
||||
///
|
||||
|
|
|
@ -297,38 +297,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
|||
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>
|
||||
///
|
||||
|
|
|
@ -168,32 +168,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
|||
{
|
||||
m_comms.RegisterScriptInvocations(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)
|
||||
{
|
||||
|
@ -341,18 +315,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
|||
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>
|
||||
///
|
||||
|
|
|
@ -158,8 +158,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
|||
|
||||
Assert.That(dsrv, Is.EqualTo(1));
|
||||
|
||||
int tprv = (int)InvokeOp("JsonTestPath", storeId, "Hello");
|
||||
Assert.That(tprv, Is.EqualTo(0));
|
||||
int tprv = (int)InvokeOp("JsonGetPathType", storeId, "Hello");
|
||||
Assert.That(tprv, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -277,8 +277,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
|||
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
|
||||
Assert.That(returnValue, Is.EqualTo(1));
|
||||
|
||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello");
|
||||
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
|
||||
|
||||
string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
|
||||
Assert.That(returnValue2, Is.EqualTo(""));
|
||||
|
@ -291,8 +291,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
|||
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
|
||||
Assert.That(returnValue, Is.EqualTo(1));
|
||||
|
||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello");
|
||||
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
|
||||
|
||||
string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello");
|
||||
Assert.That(returnValue2, Is.EqualTo(""));
|
||||
|
@ -306,11 +306,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
|||
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]");
|
||||
Assert.That(returnValue, Is.EqualTo(1));
|
||||
|
||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello[0]");
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello[0]");
|
||||
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_VALUE));
|
||||
|
||||
result = (int)InvokeOp("JsonTestPath", storeId, "Hello[1]");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
result = (int)InvokeOp("JsonGetPathType", storeId, "Hello[1]");
|
||||
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
|
||||
|
||||
string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]");
|
||||
Assert.That(stringReturnValue, Is.EqualTo("value2"));
|
||||
|
@ -400,7 +400,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
|||
// }
|
||||
|
||||
[Test]
|
||||
public void TestGetArrayLength()
|
||||
public void TestJsonGetArrayLength()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
|
|
@ -438,6 +438,28 @@ public override BulletConstraint Create6DofConstraintToPoint(BulletWorld world,
|
|||
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,
|
||||
Vector3 pivotinA, Vector3 pivotinB,
|
||||
Vector3 axisInA, Vector3 axisInB,
|
||||
|
@ -450,6 +472,52 @@ public override BulletConstraint CreateHingeConstraint(BulletWorld world, Bullet
|
|||
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)
|
||||
{
|
||||
BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
|
||||
|
@ -1425,12 +1493,46 @@ public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr ob
|
|||
Vector3 joinPoint,
|
||||
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]
|
||||
public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||
Vector3 pivotinA, Vector3 pivotinB,
|
||||
Vector3 axisInA, Vector3 axisInB,
|
||||
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]
|
||||
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, Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
|
||||
public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
|
||||
Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
|
||||
bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
|
||||
|
||||
{
|
||||
DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
|
||||
|
@ -584,6 +585,23 @@ private sealed class BulletConstraintXNA : BulletConstraint
|
|||
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>
|
||||
///
|
||||
|
@ -1133,8 +1151,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
|
|||
p.numberOfSolverIterations = o[0].numberOfSolverIterations;
|
||||
|
||||
p.linksetImplementation = BSParam.LinksetImplementation;
|
||||
p.linkConstraintUseFrameOffset = BSParam.LinkConstraintUseFrameOffset;
|
||||
p.linkConstraintEnableTransMotor = BSParam.LinkConstraintEnableTransMotor;
|
||||
p.linkConstraintUseFrameOffset = BSParam.NumericBool(BSParam.LinkConstraintUseFrameOffset);
|
||||
p.linkConstraintEnableTransMotor = BSParam.NumericBool(BSParam.LinkConstraintEnableTransMotor);
|
||||
p.linkConstraintTransMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel;
|
||||
p.linkConstraintTransMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce;
|
||||
p.linkConstraintERP = BSParam.LinkConstraintERP;
|
||||
|
@ -1443,129 +1461,130 @@ private sealed class BulletConstraintXNA : BulletConstraint
|
|||
|
||||
public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin)
|
||||
{
|
||||
BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
switch (pin)
|
||||
{
|
||||
case BroadphaseNativeTypes.BOX_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_BOX;
|
||||
ret = BSPhysicsShapeType.SHAPE_BOX;
|
||||
break;
|
||||
case BroadphaseNativeTypes.TRIANGLE_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
|
||||
case BroadphaseNativeTypes.TETRAHEDRAL_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_MESH;
|
||||
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||
break;
|
||||
case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_HULL;
|
||||
ret = BSPhysicsShapeType.SHAPE_HULL;
|
||||
break;
|
||||
case BroadphaseNativeTypes.CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.CUSTOM_POLYHEDRAL_SHAPE_TYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
//implicit convex shapes
|
||||
case BroadphaseNativeTypes.IMPLICIT_CONVEX_SHAPES_START_HERE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.SPHERE_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_SPHERE;
|
||||
ret = BSPhysicsShapeType.SHAPE_SPHERE;
|
||||
break;
|
||||
case BroadphaseNativeTypes.MULTI_SPHERE_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.CAPSULE_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_CAPSULE;
|
||||
ret = BSPhysicsShapeType.SHAPE_CAPSULE;
|
||||
break;
|
||||
case BroadphaseNativeTypes.CONE_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_CONE;
|
||||
ret = BSPhysicsShapeType.SHAPE_CONE;
|
||||
break;
|
||||
case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_CYLINDER;
|
||||
ret = BSPhysicsShapeType.SHAPE_CYLINDER;
|
||||
break;
|
||||
case BroadphaseNativeTypes.UNIFORM_SCALING_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.MINKOWSKI_SUM_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.BOX_2D_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.CONVEX_2D_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.CUSTOM_CONVEX_SHAPE_TYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
//concave shape
|
||||
case BroadphaseNativeTypes.CONCAVE_SHAPES_START_HERE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
|
||||
case BroadphaseNativeTypes.TRIANGLE_MESH_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_MESH;
|
||||
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||
break;
|
||||
case BroadphaseNativeTypes.SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_MESH;
|
||||
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||
break;
|
||||
///used for demo integration FAST/Swift collision library and Bullet
|
||||
case BroadphaseNativeTypes.FAST_CONCAVE_MESH_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_MESH;
|
||||
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||
break;
|
||||
//terrain
|
||||
case BroadphaseNativeTypes.TERRAIN_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_HEIGHTMAP;
|
||||
ret = BSPhysicsShapeType.SHAPE_HEIGHTMAP;
|
||||
break;
|
||||
///Used for GIMPACT Trimesh integration
|
||||
case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_MESH;
|
||||
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||
break;
|
||||
///Multimaterial mesh
|
||||
case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_MESH;
|
||||
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||
break;
|
||||
|
||||
case BroadphaseNativeTypes.EMPTY_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.STATIC_PLANE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_GROUNDPLANE;
|
||||
ret = BSPhysicsShapeType.SHAPE_GROUNDPLANE;
|
||||
break;
|
||||
case BroadphaseNativeTypes.CUSTOM_CONCAVE_SHAPE_TYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.CONCAVE_SHAPES_END_HERE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
|
||||
case BroadphaseNativeTypes.COMPOUND_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_COMPOUND;
|
||||
ret = BSPhysicsShapeType.SHAPE_COMPOUND;
|
||||
break;
|
||||
|
||||
case BroadphaseNativeTypes.SOFTBODY_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_MESH;
|
||||
ret = BSPhysicsShapeType.SHAPE_MESH;
|
||||
break;
|
||||
case BroadphaseNativeTypes.HFFLUID_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
case BroadphaseNativeTypes.INVALID_SHAPE_PROXYTYPE:
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
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 axisInA = new IndexedVector3(paxisInA.X, paxisInA.Y, paxisInA.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);
|
||||
}
|
||||
return new BulletConstraintXNA(constrain);
|
||||
|
|
|
@ -365,11 +365,38 @@ public abstract BulletConstraint Create6DofConstraintToPoint(BulletWorld world,
|
|||
Vector3 joinPoint,
|
||||
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,
|
||||
Vector3 pivotinA, Vector3 pivotinB,
|
||||
Vector3 axisInA, Vector3 axisInB,
|
||||
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 SetConstraintNumSolverIterations(BulletConstraint constrain, float iterations);
|
||||
|
|
|
@ -443,6 +443,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
PositionSanityCheck();
|
||||
ForcePosition = _position;
|
||||
});
|
||||
}
|
||||
|
@ -456,7 +457,6 @@ public sealed class BSCharacter : BSPhysObject
|
|||
_position = value;
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
PositionSanityCheck();
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
||||
}
|
||||
}
|
||||
|
@ -513,8 +513,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
||||
ForcePosition = _position;
|
||||
});
|
||||
ret = true;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ public sealed class BSConstraint6Dof : BSConstraint
|
|||
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,
|
||||
Vector3 joinPoint,
|
||||
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)
|
||||
{
|
||||
bool ret = false;
|
||||
|
|
|
@ -117,8 +117,7 @@ public sealed class BSConstraintCollection : IDisposable
|
|||
if (this.TryGetConstraint(body1, body2, out constrain))
|
||||
{
|
||||
// remove the constraint from our collection
|
||||
RemoveAndDestroyConstraint(constrain);
|
||||
ret = true;
|
||||
ret = RemoveAndDestroyConstraint(constrain);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,17 +125,19 @@ public sealed class BSConstraintCollection : IDisposable
|
|||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
bool removed = false;
|
||||
lock (m_constraints)
|
||||
{
|
||||
// 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();
|
||||
// we destroyed something
|
||||
return true;
|
||||
return removed;
|
||||
}
|
||||
|
||||
// Remove all constraints that reference the passed body.
|
||||
|
|
|
@ -144,7 +144,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
enableAngularVerticalAttraction = true;
|
||||
enableAngularDeflection = false;
|
||||
enableAngularBanking = false;
|
||||
if (BSParam.VehicleDebuggingEnabled != ConfigurationParameters.numericFalse)
|
||||
if (BSParam.VehicleDebuggingEnabled)
|
||||
{
|
||||
enableAngularVerticalAttraction = true;
|
||||
enableAngularDeflection = false;
|
||||
|
@ -607,8 +607,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
// TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
|
||||
// Maybe compute linear and angular factor and damping from params.
|
||||
PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, BSParam.VehicleAngularDamping);
|
||||
PhysicsScene.PE.SetLinearFactor(Prim.PhysBody, BSParam.VehicleLinearFactorV);
|
||||
PhysicsScene.PE.SetAngularFactorV(Prim.PhysBody, BSParam.VehicleAngularFactorV);
|
||||
PhysicsScene.PE.SetLinearFactor(Prim.PhysBody, BSParam.VehicleLinearFactor);
|
||||
PhysicsScene.PE.SetAngularFactorV(Prim.PhysBody, BSParam.VehicleAngularFactor);
|
||||
|
||||
// Vehicles report collision events so we know when it's on the ground
|
||||
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);
|
||||
|
||||
// tweek the constraint to increase stability
|
||||
constrain.UseFrameOffset(BSParam.BoolNumeric(BSParam.LinkConstraintUseFrameOffset));
|
||||
constrain.TranslationalLimitMotor(BSParam.BoolNumeric(BSParam.LinkConstraintEnableTransMotor),
|
||||
constrain.UseFrameOffset(BSParam.LinkConstraintUseFrameOffset);
|
||||
constrain.TranslationalLimitMotor(BSParam.LinkConstraintEnableTransMotor,
|
||||
BSParam.LinkConstraintTransMotorMaxVel,
|
||||
BSParam.LinkConstraintTransMotorMaxForce);
|
||||
constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
|
||||
|
|
|
@ -37,6 +37,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
{
|
||||
public static class BSParam
|
||||
{
|
||||
private static string LogHeader = "[BULLETSIM PARAMETERS]";
|
||||
|
||||
// Level of Detail values kept as float because that's what the Meshmerizer wants
|
||||
public static float MeshLOD { 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 SculptLOD { get; private set; }
|
||||
|
||||
public static int CrossingFailuresBeforeOutOfBounds { get; private set; }
|
||||
|
||||
public static float MinimumObjectMass { get; private set; }
|
||||
public static float MaximumObjectMass { 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 TerrainCollisionMargin { get; private set; }
|
||||
|
||||
public static float DefaultFriction;
|
||||
public static float DefaultDensity;
|
||||
public static float DefaultRestitution;
|
||||
public static float CollisionMargin;
|
||||
public static float Gravity;
|
||||
public static float DefaultFriction { get; private set; }
|
||||
public static float DefaultDensity { get; private set; }
|
||||
public static float DefaultRestitution { get; private set; }
|
||||
public static float CollisionMargin { get; private set; }
|
||||
public static float Gravity { get; private set; }
|
||||
|
||||
// Physics Engine operation
|
||||
public static float MaxPersistantManifoldPoolSize;
|
||||
public static float MaxCollisionAlgorithmPoolSize;
|
||||
public static float ShouldDisableContactPoolDynamicAllocation;
|
||||
public static float ShouldForceUpdateAllAabbs;
|
||||
public static float ShouldRandomizeSolverOrder;
|
||||
public static float ShouldSplitSimulationIslands;
|
||||
public static float ShouldEnableFrictionCaching;
|
||||
public static float NumberOfSolverIterations;
|
||||
public static bool UseSingleSidedMeshes { get { return UseSingleSidedMeshesF != ConfigurationParameters.numericFalse; } }
|
||||
public static float UseSingleSidedMeshesF;
|
||||
public static float GlobalContactBreakingThreshold;
|
||||
public static float MaxPersistantManifoldPoolSize { get; private set; }
|
||||
public static float MaxCollisionAlgorithmPoolSize { get; private set; }
|
||||
public static bool ShouldDisableContactPoolDynamicAllocation { get; private set; }
|
||||
public static bool ShouldForceUpdateAllAabbs { get; private set; }
|
||||
public static bool ShouldRandomizeSolverOrder { get; private set; }
|
||||
public static bool ShouldSplitSimulationIslands { get; private set; }
|
||||
public static bool ShouldEnableFrictionCaching { get; private set; }
|
||||
public static float NumberOfSolverIterations { get; private set; }
|
||||
public static bool UseSingleSidedMeshes { get; private set; }
|
||||
public static float GlobalContactBreakingThreshold { get; private set; }
|
||||
|
||||
// Avatar parameters
|
||||
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 VehicleFriction { get; private set; }
|
||||
public static float VehicleRestitution { get; private set; }
|
||||
public static float VehicleLinearFactor { get; private set; }
|
||||
public static Vector3 VehicleLinearFactorV { get; private set; }
|
||||
public static float VehicleAngularFactor { get; private set; }
|
||||
public static Vector3 VehicleAngularFactorV { get; private set; }
|
||||
public static Vector3 VehicleLinearFactor { get; private set; }
|
||||
public static Vector3 VehicleAngularFactor { 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 LinkConstraintUseFrameOffset { get; private set; }
|
||||
public static float LinkConstraintEnableTransMotor { get; private set; }
|
||||
public static bool LinkConstraintUseFrameOffset { get; private set; }
|
||||
public static bool LinkConstraintEnableTransMotor { get; private set; }
|
||||
public static float LinkConstraintTransMotorMaxVel { get; private set; }
|
||||
public static float LinkConstraintTransMotorMaxForce { 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 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 desc; // a short description of what the parameter means
|
||||
public float defaultValue; // default value if not specified anywhere else
|
||||
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)
|
||||
public ParameterDefnBase(string pName, string pDesc)
|
||||
{
|
||||
name = n;
|
||||
desc = d;
|
||||
defaultValue = v;
|
||||
userParam = u;
|
||||
getter = g;
|
||||
setter = s;
|
||||
onObject = null;
|
||||
name = pName;
|
||||
desc = pDesc;
|
||||
}
|
||||
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;
|
||||
desc = d;
|
||||
defaultValue = v;
|
||||
userParam = u;
|
||||
getter = g;
|
||||
setter = s;
|
||||
onObject = o;
|
||||
T defaultValue;
|
||||
PSetValue<T> setter;
|
||||
PGetValue<T> getter;
|
||||
PSetOnObject<T> objectSet;
|
||||
public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter)
|
||||
: base(pName, pDesc)
|
||||
{
|
||||
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
|
||||
// getters and setters.
|
||||
// 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.
|
||||
// -- a short text description of the parameter. This shows up in the console listing.
|
||||
// -- a default value (float)
|
||||
// -- a delegate for fetching the parameter from the ini file.
|
||||
// Should handle fetching the right type from the ini file and converting it.
|
||||
// -- a delegate for getting the value as a float
|
||||
// -- a delegate for setting the value from a float
|
||||
// -- a default value
|
||||
// -- a delegate for getting the value
|
||||
// -- a delegate for setting the value
|
||||
// -- an optional delegate to update the value in the world. Most often used to
|
||||
// push the new value to an in-world object.
|
||||
//
|
||||
// The single letter parameters for the delegates are:
|
||||
// s = BSScene
|
||||
// o = BSPhysObject
|
||||
// p = string parameter name
|
||||
// l = localID of referenced object
|
||||
// v = value (float)
|
||||
// cf = parameter configuration class (for fetching values from ini file)
|
||||
private static ParameterDefn[] ParameterDefinitions =
|
||||
private static ParameterDefnBase[] ParameterDefinitions =
|
||||
{
|
||||
new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
|
||||
ConfigurationParameters.numericTrue,
|
||||
(s,cf,p,v) => { ShouldMeshSculptedPrim = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
|
||||
(s) => { return BSParam.NumericBool(ShouldMeshSculptedPrim); },
|
||||
(s,p,l,v) => { ShouldMeshSculptedPrim = BSParam.BoolNumeric(v); } ),
|
||||
new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
|
||||
ConfigurationParameters.numericFalse,
|
||||
(s,cf,p,v) => { ShouldForceSimplePrimMeshing = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
|
||||
(s) => { return BSParam.NumericBool(ShouldForceSimplePrimMeshing); },
|
||||
(s,p,l,v) => { ShouldForceSimplePrimMeshing = BSParam.BoolNumeric(v); } ),
|
||||
new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
|
||||
ConfigurationParameters.numericTrue,
|
||||
(s,cf,p,v) => { ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
|
||||
(s) => { return BSParam.NumericBool(ShouldUseHullsForPhysicalObjects); },
|
||||
(s,p,l,v) => { ShouldUseHullsForPhysicalObjects = BSParam.BoolNumeric(v); } ),
|
||||
new ParameterDefn("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes",
|
||||
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<bool>("MeshSculptedPrim", "Whether to create meshes for sculpties",
|
||||
true,
|
||||
(s) => { return ShouldMeshSculptedPrim; },
|
||||
(s,v) => { ShouldMeshSculptedPrim = v; } ),
|
||||
new ParameterDefn<bool>("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
|
||||
false,
|
||||
(s) => { return ShouldForceSimplePrimMeshing; },
|
||||
(s,v) => { ShouldForceSimplePrimMeshing = v; } ),
|
||||
new ParameterDefn<bool>("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
|
||||
true,
|
||||
(s) => { return ShouldUseHullsForPhysicalObjects; },
|
||||
(s,v) => { ShouldUseHullsForPhysicalObjects = v; } ),
|
||||
new ParameterDefn<bool>("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes",
|
||||
true,
|
||||
(s) => { return ShouldRemoveZeroWidthTriangles; },
|
||||
(s,v) => { ShouldRemoveZeroWidthTriangles = 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,
|
||||
(s,cf,p,v) => { MeshLOD = (float)cf.GetInt(p, (int)v); },
|
||||
(s) => { return MeshLOD; },
|
||||
(s,p,l,v) => { MeshLOD = v; } ),
|
||||
new ParameterDefn("MeshLevelOfDetailCircular", "Level of detail for prims with circular cuts or shapes",
|
||||
(s,v) => { MeshLOD = v; } ),
|
||||
new ParameterDefn<float>("MeshLevelOfDetailCircular", "Level of detail for prims with circular cuts or shapes",
|
||||
32f,
|
||||
(s,cf,p,v) => { MeshCircularLOD = (float)cf.GetInt(p, (int)v); },
|
||||
(s) => { return MeshCircularLOD; },
|
||||
(s,p,l,v) => { MeshCircularLOD = v; } ),
|
||||
new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
|
||||
(s,v) => { MeshCircularLOD = v; } ),
|
||||
new ParameterDefn<float>("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
|
||||
10f,
|
||||
(s,cf,p,v) => { MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
|
||||
(s) => { return MeshMegaPrimThreshold; },
|
||||
(s,p,l,v) => { MeshMegaPrimThreshold = v; } ),
|
||||
new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
|
||||
(s,v) => { MeshMegaPrimThreshold = v; } ),
|
||||
new ParameterDefn<float>("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
|
||||
32f,
|
||||
(s,cf,p,v) => { MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
|
||||
(s) => { return MeshMegaPrimLOD; },
|
||||
(s,p,l,v) => { MeshMegaPrimLOD = v; } ),
|
||||
new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
|
||||
(s,v) => { MeshMegaPrimLOD = v; } ),
|
||||
new ParameterDefn<float>("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
|
||||
32f,
|
||||
(s,cf,p,v) => { SculptLOD = (float)cf.GetInt(p, (int)v); },
|
||||
(s) => { return SculptLOD; },
|
||||
(s,p,l,v) => { SculptLOD = v; } ),
|
||||
(s,v) => { SculptLOD = v; } ),
|
||||
|
||||
new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
|
||||
10f,
|
||||
(s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
|
||||
(s) => { return (float)s.m_maxSubSteps; },
|
||||
(s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
|
||||
new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
|
||||
new ParameterDefn<int>("MaxSubStep", "In simulation step, maximum number of substeps",
|
||||
10,
|
||||
(s) => { return s.m_maxSubSteps; },
|
||||
(s,v) => { s.m_maxSubSteps = (int)v; } ),
|
||||
new ParameterDefn<float>("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
|
||||
1f / 60f,
|
||||
(s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)s.m_fixedTimeStep; },
|
||||
(s,p,l,v) => { s.m_fixedTimeStep = v; } ),
|
||||
new ParameterDefn("NominalFrameRate", "The base frame rate we claim",
|
||||
(s) => { return s.m_fixedTimeStep; },
|
||||
(s,v) => { s.m_fixedTimeStep = v; } ),
|
||||
new ParameterDefn<float>("NominalFrameRate", "The base frame rate we claim",
|
||||
55f,
|
||||
(s,cf,p,v) => { s.NominalFrameRate = cf.GetInt(p, (int)v); },
|
||||
(s) => { return (float)s.NominalFrameRate; },
|
||||
(s,p,l,v) => { s.NominalFrameRate = (int)v; } ),
|
||||
new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
|
||||
2048f,
|
||||
(s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
|
||||
(s) => { return (float)s.m_maxCollisionsPerFrame; },
|
||||
(s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
|
||||
new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
|
||||
8000f,
|
||||
(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; } ),
|
||||
(s) => { return s.NominalFrameRate; },
|
||||
(s,v) => { s.NominalFrameRate = (int)v; } ),
|
||||
new ParameterDefn<int>("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
|
||||
2048,
|
||||
(s) => { return s.m_maxCollisionsPerFrame; },
|
||||
(s,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
|
||||
new ParameterDefn<int>("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
|
||||
8000,
|
||||
(s) => { return s.m_maxUpdatesPerFrame; },
|
||||
(s,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,
|
||||
(s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); },
|
||||
(s) => { return MinimumObjectMass; },
|
||||
(s,p,l,v) => { MinimumObjectMass = v; } ),
|
||||
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
|
||||
(s,v) => { MinimumObjectMass = v; } ),
|
||||
new ParameterDefn<float>("MaxObjectMass", "Maximum object mass (10000.01)",
|
||||
10000.01f,
|
||||
(s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
|
||||
(s) => { return MaximumObjectMass; },
|
||||
(s,p,l,v) => { MaximumObjectMass = v; } ),
|
||||
new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
|
||||
(s,v) => { MaximumObjectMass = v; } ),
|
||||
new ParameterDefn<float>("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
|
||||
1000.0f,
|
||||
(s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); },
|
||||
(s) => { return MaxLinearVelocity; },
|
||||
(s,p,l,v) => { MaxLinearVelocity = v; } ),
|
||||
new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
|
||||
(s,v) => { MaxLinearVelocity = v; } ),
|
||||
new ParameterDefn<float>("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
|
||||
1000.0f,
|
||||
(s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); },
|
||||
(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
|
||||
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,
|
||||
(s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); },
|
||||
(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.
|
||||
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,
|
||||
(s,cf,p,v) => { DensityScaleFactor = cf.GetFloat(p, v); },
|
||||
(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,
|
||||
(s,cf,p,v) => { PID_D = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)PID_D; },
|
||||
(s,p,l,v) => { PID_D = v; } ),
|
||||
new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
|
||||
(s,v) => { PID_D = v; } ),
|
||||
new ParameterDefn<float>("PID_P", "Parameteric factor for motion smoothing",
|
||||
900f,
|
||||
(s,cf,p,v) => { PID_P = cf.GetFloat(p, v); },
|
||||
(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,
|
||||
(s,cf,p,v) => { DefaultFriction = cf.GetFloat(p, v); },
|
||||
(s) => { return DefaultFriction; },
|
||||
(s,p,l,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ),
|
||||
new ParameterDefn("DefaultDensity", "Density for new objects" ,
|
||||
(s,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ),
|
||||
new ParameterDefn<float>("DefaultDensity", "Density for new objects" ,
|
||||
10.000006836f, // Aluminum g/cm3
|
||||
(s,cf,p,v) => { DefaultDensity = cf.GetFloat(p, v); },
|
||||
(s) => { return DefaultDensity; },
|
||||
(s,p,l,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ),
|
||||
new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
|
||||
(s,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ),
|
||||
new ParameterDefn<float>("DefaultRestitution", "Bouncyness of an object" ,
|
||||
0f,
|
||||
(s,cf,p,v) => { DefaultRestitution = cf.GetFloat(p, v); },
|
||||
(s) => { return DefaultRestitution; },
|
||||
(s,p,l,v) => { DefaultRestitution = v; s.UnmanagedParams[0].defaultRestitution = v; } ),
|
||||
new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
|
||||
(s,v) => { DefaultRestitution = v; s.UnmanagedParams[0].defaultRestitution = v; } ),
|
||||
new ParameterDefn<float>("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
|
||||
0.04f,
|
||||
(s,cf,p,v) => { CollisionMargin = cf.GetFloat(p, v); },
|
||||
(s) => { return CollisionMargin; },
|
||||
(s,p,l,v) => { CollisionMargin = v; s.UnmanagedParams[0].collisionMargin = v; } ),
|
||||
new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
|
||||
(s,v) => { CollisionMargin = v; s.UnmanagedParams[0].collisionMargin = v; } ),
|
||||
new ParameterDefn<float>("Gravity", "Vertical force of gravity (negative means down)",
|
||||
-9.80665f,
|
||||
(s,cf,p,v) => { Gravity = cf.GetFloat(p, v); },
|
||||
(s) => { return Gravity; },
|
||||
(s,p,l,v) => { Gravity = v; s.UnmanagedParams[0].gravity = v; },
|
||||
(s,o,v) => { s.PE.SetGravity(o.PhysBody, new Vector3(0f,0f,v)); } ),
|
||||
(s,v) => { Gravity = v; s.UnmanagedParams[0].gravity = 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,
|
||||
(s,cf,p,v) => { LinearDamping = cf.GetFloat(p, v); },
|
||||
(s) => { return LinearDamping; },
|
||||
(s,p,l,v) => { LinearDamping = v; },
|
||||
(s,o,v) => { s.PE.SetDamping(o.PhysBody, v, AngularDamping); } ),
|
||||
new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
|
||||
(s,v) => { LinearDamping = v; },
|
||||
(s,o) => { s.PE.SetDamping(o.PhysBody, LinearDamping, AngularDamping); } ),
|
||||
new ParameterDefn<float>("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
|
||||
0f,
|
||||
(s,cf,p,v) => { AngularDamping = cf.GetFloat(p, v); },
|
||||
(s) => { return AngularDamping; },
|
||||
(s,p,l,v) => { AngularDamping = v; },
|
||||
(s,o,v) => { s.PE.SetDamping(o.PhysBody, LinearDamping, v); } ),
|
||||
new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
|
||||
(s,v) => { AngularDamping = v; },
|
||||
(s,o) => { s.PE.SetDamping(o.PhysBody, LinearDamping, AngularDamping); } ),
|
||||
new ParameterDefn<float>("DeactivationTime", "Seconds before considering an object potentially static",
|
||||
0.2f,
|
||||
(s,cf,p,v) => { DeactivationTime = cf.GetFloat(p, v); },
|
||||
(s) => { return DeactivationTime; },
|
||||
(s,p,l,v) => { DeactivationTime = v; },
|
||||
(s,o,v) => { s.PE.SetDeactivationTime(o.PhysBody, v); } ),
|
||||
new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
|
||||
(s,v) => { DeactivationTime = v; },
|
||||
(s,o) => { s.PE.SetDeactivationTime(o.PhysBody, DeactivationTime); } ),
|
||||
new ParameterDefn<float>("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
|
||||
0.8f,
|
||||
(s,cf,p,v) => { LinearSleepingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return LinearSleepingThreshold; },
|
||||
(s,p,l,v) => { LinearSleepingThreshold = v;},
|
||||
(s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ),
|
||||
new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
|
||||
(s,v) => { LinearSleepingThreshold = v;},
|
||||
(s,o) => { s.PE.SetSleepingThresholds(o.PhysBody, LinearSleepingThreshold, AngularSleepingThreshold); } ),
|
||||
new ParameterDefn<float>("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
|
||||
1.0f,
|
||||
(s,cf,p,v) => { AngularSleepingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return AngularSleepingThreshold; },
|
||||
(s,p,l,v) => { AngularSleepingThreshold = v;},
|
||||
(s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ),
|
||||
new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
|
||||
(s,v) => { AngularSleepingThreshold = v;},
|
||||
(s,o) => { s.PE.SetSleepingThresholds(o.PhysBody, LinearSleepingThreshold, AngularSleepingThreshold); } ),
|
||||
new ParameterDefn<float>("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
|
||||
0.0f, // set to zero to disable
|
||||
(s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return CcdMotionThreshold; },
|
||||
(s,p,l,v) => { CcdMotionThreshold = v;},
|
||||
(s,o,v) => { s.PE.SetCcdMotionThreshold(o.PhysBody, v); } ),
|
||||
new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
|
||||
(s,v) => { CcdMotionThreshold = v;},
|
||||
(s,o) => { s.PE.SetCcdMotionThreshold(o.PhysBody, CcdMotionThreshold); } ),
|
||||
new ParameterDefn<float>("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
|
||||
0.2f,
|
||||
(s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); },
|
||||
(s) => { return CcdSweptSphereRadius; },
|
||||
(s,p,l,v) => { CcdSweptSphereRadius = v;},
|
||||
(s,o,v) => { s.PE.SetCcdSweptSphereRadius(o.PhysBody, v); } ),
|
||||
new ParameterDefn("ContactProcessingThreshold", "Distance above which contacts can be discarded (0 means no discard)" ,
|
||||
(s,v) => { CcdSweptSphereRadius = v;},
|
||||
(s,o) => { s.PE.SetCcdSweptSphereRadius(o.PhysBody, CcdSweptSphereRadius); } ),
|
||||
new ParameterDefn<float>("ContactProcessingThreshold", "Distance above which contacts can be discarded (0 means no discard)" ,
|
||||
0.0f,
|
||||
(s,cf,p,v) => { ContactProcessingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return ContactProcessingThreshold; },
|
||||
(s,p,l,v) => { ContactProcessingThreshold = v;},
|
||||
(s,o,v) => { s.PE.SetContactProcessingThreshold(o.PhysBody, v); } ),
|
||||
(s,v) => { ContactProcessingThreshold = 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,
|
||||
(s,cf,p,v) => { TerrainImplementation = cf.GetFloat(p,v); },
|
||||
(s) => { return TerrainImplementation; },
|
||||
(s,p,l,v) => { TerrainImplementation = v; } ),
|
||||
new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
||||
(s,v) => { TerrainImplementation = v; } ),
|
||||
new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
||||
0.3f,
|
||||
(s,cf,p,v) => { TerrainFriction = cf.GetFloat(p, v); },
|
||||
(s) => { return TerrainFriction; },
|
||||
(s,p,l,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ),
|
||||
new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
|
||||
(s,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ),
|
||||
new ParameterDefn<float>("TerrainHitFraction", "Distance to measure hit collisions" ,
|
||||
0.8f,
|
||||
(s,cf,p,v) => { TerrainHitFraction = cf.GetFloat(p, v); },
|
||||
(s) => { return TerrainHitFraction; },
|
||||
(s,p,l,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ),
|
||||
new ParameterDefn("TerrainRestitution", "Bouncyness" ,
|
||||
(s,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ),
|
||||
new ParameterDefn<float>("TerrainRestitution", "Bouncyness" ,
|
||||
0f,
|
||||
(s,cf,p,v) => { TerrainRestitution = cf.GetFloat(p, v); },
|
||||
(s) => { return TerrainRestitution; },
|
||||
(s,p,l,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
|
||||
new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" ,
|
||||
(s,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
|
||||
new ParameterDefn<float>("TerrainCollisionMargin", "Margin where collision checking starts" ,
|
||||
0.08f,
|
||||
(s,cf,p,v) => { TerrainCollisionMargin = cf.GetFloat(p, v); },
|
||||
(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,
|
||||
(s,cf,p,v) => { AvatarFriction = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarFriction; },
|
||||
(s,p,l,v) => { AvatarFriction = v; } ),
|
||||
new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
|
||||
(s,v) => { AvatarFriction = v; } ),
|
||||
new ParameterDefn<float>("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
|
||||
0.95f,
|
||||
(s,cf,p,v) => { AvatarStandingFriction = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarStandingFriction; },
|
||||
(s,p,l,v) => { AvatarStandingFriction = v; } ),
|
||||
new ParameterDefn("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
|
||||
(s,v) => { AvatarStandingFriction = v; } ),
|
||||
new ParameterDefn<float>("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
|
||||
1.3f,
|
||||
(s,cf,p,v) => { AvatarAlwaysRunFactor = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarAlwaysRunFactor; },
|
||||
(s,p,l,v) => { AvatarAlwaysRunFactor = v; } ),
|
||||
new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
|
||||
(s,v) => { AvatarAlwaysRunFactor = v; } ),
|
||||
new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
|
||||
3.5f,
|
||||
(s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarDensity; },
|
||||
(s,p,l,v) => { AvatarDensity = v; } ),
|
||||
new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
|
||||
(s,v) => { AvatarDensity = v; } ),
|
||||
new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
|
||||
0f,
|
||||
(s,cf,p,v) => { AvatarRestitution = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarRestitution; },
|
||||
(s,p,l,v) => { AvatarRestitution = v; } ),
|
||||
new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
|
||||
(s,v) => { AvatarRestitution = v; } ),
|
||||
new ParameterDefn<float>("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
|
||||
0.6f,
|
||||
(s,cf,p,v) => { AvatarCapsuleWidth = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarCapsuleWidth; },
|
||||
(s,p,l,v) => { AvatarCapsuleWidth = v; } ),
|
||||
new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
|
||||
(s,v) => { AvatarCapsuleWidth = v; } ),
|
||||
new ParameterDefn<float>("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
|
||||
0.45f,
|
||||
(s,cf,p,v) => { AvatarCapsuleDepth = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarCapsuleDepth; },
|
||||
(s,p,l,v) => { AvatarCapsuleDepth = v; } ),
|
||||
new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
|
||||
(s,v) => { AvatarCapsuleDepth = v; } ),
|
||||
new ParameterDefn<float>("AvatarCapsuleHeight", "Default height of space around avatar",
|
||||
1.5f,
|
||||
(s,cf,p,v) => { AvatarCapsuleHeight = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarCapsuleHeight; },
|
||||
(s,p,l,v) => { AvatarCapsuleHeight = v; } ),
|
||||
new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
|
||||
(s,v) => { AvatarCapsuleHeight = v; } ),
|
||||
new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
|
||||
0.1f,
|
||||
(s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarContactProcessingThreshold; },
|
||||
(s,p,l,v) => { AvatarContactProcessingThreshold = v; } ),
|
||||
new ParameterDefn("AvatarStepHeight", "Height of a step obstacle to consider step correction",
|
||||
(s,v) => { AvatarContactProcessingThreshold = v; } ),
|
||||
new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction",
|
||||
0.3f,
|
||||
(s,cf,p,v) => { AvatarStepHeight = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarStepHeight; },
|
||||
(s,p,l,v) => { AvatarStepHeight = v; } ),
|
||||
new ParameterDefn("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
|
||||
(s,v) => { AvatarStepHeight = v; } ),
|
||||
new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
|
||||
0.6f,
|
||||
(s,cf,p,v) => { AvatarStepApproachFactor = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarStepApproachFactor; },
|
||||
(s,p,l,v) => { AvatarStepApproachFactor = v; } ),
|
||||
new ParameterDefn("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
|
||||
(s,v) => { AvatarStepApproachFactor = v; } ),
|
||||
new ParameterDefn<float>("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
|
||||
2.0f,
|
||||
(s,cf,p,v) => { AvatarStepForceFactor = cf.GetFloat(p, v); },
|
||||
(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,
|
||||
(s,cf,p,v) => { VehicleMaxLinearVelocity = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)VehicleMaxLinearVelocity; },
|
||||
(s,p,l,v) => { VehicleMaxLinearVelocity = v; VehicleMaxLinearVelocitySq = v * v; } ),
|
||||
new ParameterDefn("VehicleMaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to a vehicle",
|
||||
(s,v) => { VehicleMaxLinearVelocity = v; VehicleMaxLinearVelocitySq = v * v; } ),
|
||||
new ParameterDefn<float>("VehicleMaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to a vehicle",
|
||||
12.0f,
|
||||
(s,cf,p,v) => { VehicleMaxAngularVelocity = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)VehicleMaxAngularVelocity; },
|
||||
(s,p,l,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ),
|
||||
new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
|
||||
(s,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ),
|
||||
new ParameterDefn<float>("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
|
||||
0.0f,
|
||||
(s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
|
||||
(s) => { return VehicleAngularDamping; },
|
||||
(s,p,l,v) => { VehicleAngularDamping = v; } ),
|
||||
new ParameterDefn("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (0.0 - 1.0)",
|
||||
1.0f,
|
||||
(s,cf,p,v) => { VehicleLinearFactor = cf.GetFloat(p, v); },
|
||||
(s,v) => { VehicleAngularDamping = v; } ),
|
||||
new ParameterDefn<Vector3>("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (<0,0,0> to <1,1,1>)",
|
||||
new Vector3(1f, 1f, 1f),
|
||||
(s) => { return VehicleLinearFactor; },
|
||||
(s,p,l,v) => { VehicleLinearFactor = v; VehicleLinearFactorV = new Vector3(v, v, v); } ),
|
||||
new ParameterDefn("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (0.0 - 1.0)",
|
||||
1.0f,
|
||||
(s,cf,p,v) => { VehicleAngularFactor = cf.GetFloat(p, v); },
|
||||
(s,v) => { VehicleLinearFactor = v; } ),
|
||||
new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)",
|
||||
new Vector3(1f, 1f, 1f),
|
||||
(s) => { return VehicleAngularFactor; },
|
||||
(s,p,l,v) => { VehicleAngularFactor = v; VehicleAngularFactorV = new Vector3(v, v, v); } ),
|
||||
new ParameterDefn("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
|
||||
(s,v) => { VehicleAngularFactor = v; } ),
|
||||
new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
|
||||
0.0f,
|
||||
(s,cf,p,v) => { VehicleFriction = cf.GetFloat(p, v); },
|
||||
(s) => { return VehicleFriction; },
|
||||
(s,p,l,v) => { VehicleFriction = v; } ),
|
||||
new ParameterDefn("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
|
||||
(s,v) => { VehicleFriction = v; } ),
|
||||
new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
|
||||
0.0f,
|
||||
(s,cf,p,v) => { VehicleRestitution = cf.GetFloat(p, v); },
|
||||
(s) => { return VehicleRestitution; },
|
||||
(s,p,l,v) => { VehicleRestitution = v; } ),
|
||||
new ParameterDefn("VehicleGroundGravityFudge", "Factor to multiple gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
|
||||
(s,v) => { VehicleRestitution = v; } ),
|
||||
new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiple gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
|
||||
0.2f,
|
||||
(s,cf,p,v) => { VehicleGroundGravityFudge = cf.GetFloat(p, v); },
|
||||
(s) => { return VehicleGroundGravityFudge; },
|
||||
(s,p,l,v) => { VehicleGroundGravityFudge = v; } ),
|
||||
new ParameterDefn("VehicleDebuggingEnable", "Turn on/off vehicle debugging",
|
||||
ConfigurationParameters.numericFalse,
|
||||
(s,cf,p,v) => { VehicleDebuggingEnabled = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
||||
(s,v) => { VehicleGroundGravityFudge = v; } ),
|
||||
new ParameterDefn<bool>("VehicleDebuggingEnable", "Turn on/off vehicle debugging",
|
||||
false,
|
||||
(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,
|
||||
(s,cf,p,v) => { MaxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
|
||||
(s) => { return MaxPersistantManifoldPoolSize; },
|
||||
(s,p,l,v) => { MaxPersistantManifoldPoolSize = v; s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ),
|
||||
new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
|
||||
(s,v) => { MaxPersistantManifoldPoolSize = v; s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ),
|
||||
new ParameterDefn<float>("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
|
||||
0f,
|
||||
(s,cf,p,v) => { MaxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
|
||||
(s) => { return MaxCollisionAlgorithmPoolSize; },
|
||||
(s,p,l,v) => { MaxCollisionAlgorithmPoolSize = v; s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ),
|
||||
new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
|
||||
ConfigurationParameters.numericFalse,
|
||||
(s,cf,p,v) => { ShouldDisableContactPoolDynamicAllocation = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
||||
(s,v) => { MaxCollisionAlgorithmPoolSize = v; s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ),
|
||||
new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
|
||||
false,
|
||||
(s) => { return ShouldDisableContactPoolDynamicAllocation; },
|
||||
(s,p,l,v) => { ShouldDisableContactPoolDynamicAllocation = v; s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = v; } ),
|
||||
new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
|
||||
ConfigurationParameters.numericFalse,
|
||||
(s,cf,p,v) => { ShouldForceUpdateAllAabbs = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
||||
(s,v) => { ShouldDisableContactPoolDynamicAllocation = v;
|
||||
s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ),
|
||||
new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
|
||||
false,
|
||||
(s) => { return ShouldForceUpdateAllAabbs; },
|
||||
(s,p,l,v) => { ShouldForceUpdateAllAabbs = v; s.UnmanagedParams[0].shouldForceUpdateAllAabbs = v; } ),
|
||||
new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
|
||||
ConfigurationParameters.numericTrue,
|
||||
(s,cf,p,v) => { ShouldRandomizeSolverOrder = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
||||
(s,v) => { ShouldForceUpdateAllAabbs = v; s.UnmanagedParams[0].shouldForceUpdateAllAabbs = NumericBool(v); } ),
|
||||
new ParameterDefn<bool>("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
|
||||
true,
|
||||
(s) => { return ShouldRandomizeSolverOrder; },
|
||||
(s,p,l,v) => { ShouldRandomizeSolverOrder = v; s.UnmanagedParams[0].shouldRandomizeSolverOrder = v; } ),
|
||||
new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
|
||||
ConfigurationParameters.numericTrue,
|
||||
(s,cf,p,v) => { ShouldSplitSimulationIslands = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
||||
(s,v) => { ShouldRandomizeSolverOrder = v; s.UnmanagedParams[0].shouldRandomizeSolverOrder = NumericBool(v); } ),
|
||||
new ParameterDefn<bool>("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
|
||||
true,
|
||||
(s) => { return ShouldSplitSimulationIslands; },
|
||||
(s,p,l,v) => { ShouldSplitSimulationIslands = v; s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ),
|
||||
new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
|
||||
ConfigurationParameters.numericTrue,
|
||||
(s,cf,p,v) => { ShouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
||||
(s,v) => { ShouldSplitSimulationIslands = v; s.UnmanagedParams[0].shouldSplitSimulationIslands = NumericBool(v); } ),
|
||||
new ParameterDefn<bool>("ShouldEnableFrictionCaching", "Enable friction computation caching",
|
||||
true,
|
||||
(s) => { return ShouldEnableFrictionCaching; },
|
||||
(s,p,l,v) => { ShouldEnableFrictionCaching = v; s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ),
|
||||
new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
|
||||
(s,v) => { ShouldEnableFrictionCaching = v; s.UnmanagedParams[0].shouldEnableFrictionCaching = NumericBool(v); } ),
|
||||
new ParameterDefn<float>("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
|
||||
0f, // zero says use Bullet default
|
||||
(s,cf,p,v) => { NumberOfSolverIterations = cf.GetFloat(p, v); },
|
||||
(s) => { return NumberOfSolverIterations; },
|
||||
(s,p,l,v) => { NumberOfSolverIterations = v; s.UnmanagedParams[0].numberOfSolverIterations = v; } ),
|
||||
new ParameterDefn("UseSingleSidedMeshes", "Whether to compute collisions based on single sided meshes.",
|
||||
ConfigurationParameters.numericTrue,
|
||||
(s,cf,p,v) => { UseSingleSidedMeshesF = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
||||
(s) => { return UseSingleSidedMeshesF; },
|
||||
(s,p,l,v) => { UseSingleSidedMeshesF = v; s.UnmanagedParams[0].useSingleSidedMeshes = v; } ),
|
||||
new ParameterDefn("GlobalContactBreakingThreshold", "Amount of shape radius before breaking a collision contact (0 says Bullet default (0.2))",
|
||||
(s,v) => { NumberOfSolverIterations = v; s.UnmanagedParams[0].numberOfSolverIterations = v; } ),
|
||||
new ParameterDefn<bool>("UseSingleSidedMeshes", "Whether to compute collisions based on single sided meshes.",
|
||||
true,
|
||||
(s) => { return UseSingleSidedMeshes; },
|
||||
(s,v) => { UseSingleSidedMeshes = v; s.UnmanagedParams[0].useSingleSidedMeshes = NumericBool(v); } ),
|
||||
new ParameterDefn<float>("GlobalContactBreakingThreshold", "Amount of shape radius before breaking a collision contact (0 says Bullet default (0.2))",
|
||||
0f,
|
||||
(s,cf,p,v) => { GlobalContactBreakingThreshold = cf.GetFloat(p, v); },
|
||||
(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,
|
||||
(s,cf,p,v) => { LinksetImplementation = cf.GetFloat(p,v); },
|
||||
(s) => { return LinksetImplementation; },
|
||||
(s,p,l,v) => { LinksetImplementation = v; } ),
|
||||
new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
|
||||
ConfigurationParameters.numericFalse,
|
||||
(s,cf,p,v) => { LinkConstraintUseFrameOffset = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
||||
(s,v) => { LinksetImplementation = v; } ),
|
||||
new ParameterDefn<bool>("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
|
||||
false,
|
||||
(s) => { return LinkConstraintUseFrameOffset; },
|
||||
(s,p,l,v) => { LinkConstraintUseFrameOffset = v; } ),
|
||||
new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
|
||||
ConfigurationParameters.numericTrue,
|
||||
(s,cf,p,v) => { LinkConstraintEnableTransMotor = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
||||
(s,v) => { LinkConstraintUseFrameOffset = v; } ),
|
||||
new ParameterDefn<bool>("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
|
||||
true,
|
||||
(s) => { return LinkConstraintEnableTransMotor; },
|
||||
(s,p,l,v) => { LinkConstraintEnableTransMotor = v; } ),
|
||||
new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
|
||||
(s,v) => { LinkConstraintEnableTransMotor = v; } ),
|
||||
new ParameterDefn<float>("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
|
||||
5.0f,
|
||||
(s,cf,p,v) => { LinkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
|
||||
(s) => { return LinkConstraintTransMotorMaxVel; },
|
||||
(s,p,l,v) => { LinkConstraintTransMotorMaxVel = v; } ),
|
||||
new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
|
||||
(s,v) => { LinkConstraintTransMotorMaxVel = v; } ),
|
||||
new ParameterDefn<float>("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
|
||||
0.1f,
|
||||
(s,cf,p,v) => { LinkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
|
||||
(s) => { return LinkConstraintTransMotorMaxForce; },
|
||||
(s,p,l,v) => { LinkConstraintTransMotorMaxForce = v; } ),
|
||||
new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
|
||||
(s,v) => { LinkConstraintTransMotorMaxForce = v; } ),
|
||||
new ParameterDefn<float>("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
|
||||
0.1f,
|
||||
(s,cf,p,v) => { LinkConstraintCFM = cf.GetFloat(p, v); },
|
||||
(s) => { return LinkConstraintCFM; },
|
||||
(s,p,l,v) => { LinkConstraintCFM = v; } ),
|
||||
new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
|
||||
(s,v) => { LinkConstraintCFM = v; } ),
|
||||
new ParameterDefn<float>("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
|
||||
0.1f,
|
||||
(s,cf,p,v) => { LinkConstraintERP = cf.GetFloat(p, v); },
|
||||
(s) => { return LinkConstraintERP; },
|
||||
(s,p,l,v) => { LinkConstraintERP = v; } ),
|
||||
new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
|
||||
(s,v) => { LinkConstraintERP = v; } ),
|
||||
new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
|
||||
40,
|
||||
(s,cf,p,v) => { LinkConstraintSolverIterations = cf.GetFloat(p, v); },
|
||||
(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,
|
||||
(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,p,l,v) => { BSParam.ResetBroadphasePoolTainted(s, v); } ),
|
||||
new ParameterDefn("ResetConstraintSolver", "Setting this is any value resets the constraint solver",
|
||||
(s,v) => { BSParam.ResetBroadphasePoolTainted(s, v); } ),
|
||||
new ParameterDefn<float>("ResetConstraintSolver", "Setting this is any value resets the constraint solver",
|
||||
0f,
|
||||
(s,cf,p,v) => { ; },
|
||||
(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
|
||||
|
@ -658,13 +644,13 @@ public static class BSParam
|
|||
// ParameterDefn structure.
|
||||
// Case does not matter as names are compared after converting to lower case.
|
||||
// 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;
|
||||
ParameterDefn foundDefn = new ParameterDefn();
|
||||
ParameterDefnBase foundDefn = null;
|
||||
string pName = paramName.ToLower();
|
||||
|
||||
foreach (ParameterDefn parm in ParameterDefinitions)
|
||||
foreach (ParameterDefnBase parm in ParameterDefinitions)
|
||||
{
|
||||
if (pName == parm.name.ToLower())
|
||||
{
|
||||
|
@ -680,18 +666,18 @@ public static class BSParam
|
|||
// Pass through the settable parameters and set the default values
|
||||
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.
|
||||
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>();
|
||||
for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
|
||||
{
|
||||
ParameterDefn pd = ParameterDefinitions[ii];
|
||||
ParameterDefnBase pd = ParameterDefinitions[ii];
|
||||
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); });
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
BSScene physScene = pPhysScene;
|
||||
|
|
|
@ -70,6 +70,8 @@ public class BSPrim : BSPhysObject
|
|||
private bool _kinematic;
|
||||
private float _buoyancy;
|
||||
|
||||
private int CrossingFailures { get; set; }
|
||||
|
||||
public BSDynamics VehicleController { get; private set; }
|
||||
|
||||
private BSVMotor _targetMotor;
|
||||
|
@ -197,7 +199,20 @@ public class BSPrim : BSPhysObject
|
|||
{
|
||||
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
|
||||
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)
|
||||
{
|
||||
DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
|
||||
|
||||
// "1" means free, "0" means locked
|
||||
OMV.Vector3 locking = new OMV.Vector3(1f, 1f, 1f);
|
||||
if (axis.X != 1) locking.X = 0f;
|
||||
if (axis.Y != 1) locking.Y = 0f;
|
||||
if (axis.Z != 1) locking.Z = 0f;
|
||||
LockedAxis = locking;
|
||||
|
||||
/* Not implemented yet
|
||||
if (LockedAxis != LockedAxisFree)
|
||||
if (TryExperimentalLockAxisCode && LockedAxis != LockedAxisFree)
|
||||
{
|
||||
// Something is locked so start the thingy that keeps that axis from changing
|
||||
RegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion", delegate(ref EntityProperties entprop)
|
||||
{
|
||||
if (LockedAxis != LockedAxisFree)
|
||||
{
|
||||
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.
|
||||
// Lock that axis by creating a 6DOF constraint that has one end in the world and
|
||||
// the other in the object.
|
||||
// http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817
|
||||
// http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380
|
||||
|
||||
ForceOrientation = entprop.Rotation;
|
||||
ForceRotationalVelocity = entprop.RotationalVelocity;
|
||||
}
|
||||
}
|
||||
else
|
||||
PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
|
||||
{
|
||||
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
|
||||
{
|
||||
// Everything seems unlocked
|
||||
UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion");
|
||||
CleanUpLockAxisPhysicals(false /* inTaintTime */);
|
||||
}
|
||||
*/
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -762,6 +825,7 @@ public class BSPrim : BSPhysObject
|
|||
SetObjectDynamic(true);
|
||||
// whether phys-to-static or static-to-phys, the object is not moving.
|
||||
ZeroMotion(true);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -885,6 +949,8 @@ public class BSPrim : BSPhysObject
|
|||
|
||||
// For good measure, make sure the transform is set through to the motion state
|
||||
ForcePosition = _position;
|
||||
ForceVelocity = _velocity;
|
||||
ForceRotationalVelocity = _rotationalVelocity;
|
||||
|
||||
// A dynamic object has mass
|
||||
UpdatePhysicalMassProperties(RawMass, false);
|
||||
|
@ -1064,15 +1130,19 @@ public class BSPrim : BSPhysObject
|
|||
_buoyancy = value;
|
||||
// DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
||||
// Force the recalculation of the various inertia,etc variables in the object
|
||||
DetailLog("{0},BSPrim.ForceBuoyancy,buoy={1},mass={2}", LocalID, _buoyancy, _mass);
|
||||
UpdatePhysicalMassProperties(_mass, true);
|
||||
UpdatePhysicalMassProperties(RawMass, true);
|
||||
DetailLog("{0},BSPrim.ForceBuoyancy,buoy={1},mass={2},grav={3}", LocalID, _buoyancy, RawMass, Gravity);
|
||||
ActivateIfPhysical(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Used for MoveTo
|
||||
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 {
|
||||
set { _PIDTau = value; }
|
||||
|
@ -1126,7 +1196,9 @@ public class BSPrim : BSPhysObject
|
|||
}
|
||||
else
|
||||
{
|
||||
ForcePosition = movePosition;
|
||||
_position = movePosition;
|
||||
PositionSanityCheck(true /* intaintTime */);
|
||||
ForcePosition = _position;
|
||||
}
|
||||
DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition);
|
||||
});
|
||||
|
@ -1303,6 +1375,7 @@ public class BSPrim : BSPhysObject
|
|||
{
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce);
|
||||
PhysicsScene.PE.ApplyTorque(PhysBody, angForce);
|
||||
ActivateIfPhysical(false);
|
||||
}
|
||||
|
@ -1667,7 +1740,7 @@ public class BSPrim : BSPhysObject
|
|||
// _velocity = entprop.Velocity;
|
||||
// DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
|
||||
// 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;
|
||||
_acceleration = entprop.Acceleration;
|
||||
_rotationalVelocity = entprop.RotationalVelocity;
|
||||
|
|
|
@ -161,7 +161,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
private int m_physicsLoggingFileMinutes;
|
||||
private bool m_physicsLoggingDoFlush;
|
||||
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
|
||||
public bool VehicleLoggingEnabled { get; private set; }
|
||||
public bool VehiclePhysicalLoggingEnabled { get; private set; }
|
||||
|
@ -542,7 +542,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
|||
collidersCount = 0;
|
||||
}
|
||||
|
||||
if ((m_simulationStep % PhysicsMetricDumpFrames) == 0)
|
||||
if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0))
|
||||
PE.DumpPhysicsStatistics(World);
|
||||
|
||||
// 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;
|
||||
|
||||
float valf = 0f;
|
||||
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;
|
||||
BSParam.ParameterDefnBase theParam;
|
||||
if (BSParam.TryGetParameter(parm, out theParam))
|
||||
{
|
||||
// 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
|
||||
if (theParam.onObject != null)
|
||||
if (theParam.HasSetOnObject)
|
||||
{
|
||||
// update all the localIDs specified
|
||||
// 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:
|
||||
// This will cause a call into the physical world if some operation is specified (SetOnObject).
|
||||
objectIDs.Add(TERRAIN_ID);
|
||||
TaintedUpdateParameter(parm, objectIDs, valf);
|
||||
TaintedUpdateParameter(parm, objectIDs, val);
|
||||
break;
|
||||
case PhysParameterEntry.APPLY_TO_ALL:
|
||||
lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
|
||||
TaintedUpdateParameter(parm, objectIDs, valf);
|
||||
TaintedUpdateParameter(parm, objectIDs, val);
|
||||
break;
|
||||
default:
|
||||
// setting only one localID
|
||||
objectIDs.Add(localID);
|
||||
TaintedUpdateParameter(parm, objectIDs, valf);
|
||||
TaintedUpdateParameter(parm, objectIDs, val);
|
||||
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
|
||||
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;
|
||||
string xparm = parm;
|
||||
TaintedObject("BSScene.UpdateParameterSet", delegate() {
|
||||
BSParam.ParameterDefn thisParam;
|
||||
BSParam.ParameterDefnBase thisParam;
|
||||
if (BSParam.TryGetParameter(xparm, out thisParam))
|
||||
{
|
||||
if (thisParam.onObject != null)
|
||||
if (thisParam.HasSetOnObject)
|
||||
{
|
||||
foreach (uint lID in xlIDs)
|
||||
{
|
||||
BSPhysObject theObject = null;
|
||||
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;
|
||||
bool ret = false;
|
||||
BSParam.ParameterDefn theParam;
|
||||
BSParam.ParameterDefnBase theParam;
|
||||
if (BSParam.TryGetParameter(parm, out theParam))
|
||||
{
|
||||
val = theParam.getter(this).ToString();
|
||||
val = theParam.GetValue(this);
|
||||
ret = true;
|
||||
}
|
||||
value = val;
|
||||
|
|
|
@ -568,7 +568,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
{
|
||||
|
||||
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
|
||||
{
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
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.
|
||||
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 banking
|
||||
Center-of-gravity
|
||||
Vehicle angular deflection
|
||||
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?
|
||||
Need a vehicle.clear()? Or an 'else' in prestep if not physical.
|
||||
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)
|
||||
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)
|
||||
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
|
||||
Avanti speed 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:
|
||||
=================================================
|
||||
|
@ -65,6 +66,7 @@ Vehicle attributes are not restored when a vehicle is rezzed on region creation
|
|||
|
||||
GENERAL TODO LIST:
|
||||
=================================================
|
||||
Add a sanity check for PIDTarget location.
|
||||
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.
|
||||
Collisions are inconsistant: arrows are supposed to hit and report collision. Often don't.
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[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:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[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");
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
string HomeURI = String.Empty;
|
||||
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)
|
||||
HomeURI = config.Configs["LoginService"].GetString("SRV_HomeURI", HomeURI);
|
||||
|
||||
|
@ -2189,9 +2193,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
CheckThreatLevel(ThreatLevel.Moderate, "osGetGridGatekeeperURI");
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
string gatekeeperURI = String.Empty;
|
||||
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)
|
||||
gatekeeperURI = config.Configs["GridService"].GetString("Gatekeeper", gatekeeperURI);
|
||||
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("0.7.6.*")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
|
|
|
@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
|
|||
// Revision
|
||||
//
|
||||
[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