Merge branch 'avination' into careminster

avinationmerge
Melanie 2013-01-23 19:31:27 +00:00
commit fc1c77b42d
10 changed files with 181 additions and 83 deletions

View File

@ -99,12 +99,23 @@ namespace OpenSim.Capabilities.Handlers
} }
// OK, we have an array with preferred formats, possibly with only one entry // OK, we have an array with preferred formats, possibly with only one entry
bool foundtexture = false;
foreach (string f in formats) foreach (string f in formats)
{ {
if (FetchTexture(request, ret, textureID, f)) foundtexture = FetchTexture(request, ret, textureID, f);
if (foundtexture)
break; break;
} }
if (!foundtexture)
{
ret["int_response_code"] = 404;
ret["error_status_text"] = "not found";
ret["str_response_string"] = "not found";
ret["content_type"] = "text/plain";
ret["keepalive"] = false;
ret["reusecontext"] = false;
ret["int_bytes"] = 0;
}
} }
else else
{ {
@ -176,9 +187,13 @@ namespace OpenSim.Capabilities.Handlers
return true; return true;
} }
//response = new Hashtable();
//WriteTextureData(request,response,null,format);
// not found // not found
// m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); //m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
return true; return false;
} }
private void WriteTextureData(Hashtable request, Hashtable response, AssetBase texture, string format) private void WriteTextureData(Hashtable request, Hashtable response, AssetBase texture, string format)

View File

@ -150,6 +150,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{ {
client.OnTeleportHomeRequest += TriggerTeleportHome; client.OnTeleportHomeRequest += TriggerTeleportHome;
client.OnTeleportLandmarkRequest += RequestTeleportLandmark; client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
client.OnTeleportCancel += TeleportCancel;
} }
public virtual void Close() {} public virtual void Close() {}
@ -401,14 +402,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{ {
// Record that this agent is in transit so that we can prevent simultaneous requests and do later detection // Record that this agent is in transit so that we can prevent simultaneous requests and do later detection
// of whether the destination region completes the teleport. // of whether the destination region completes the teleport.
if (!m_entityTransferStateMachine.SetInTransit(sp.UUID)) m_entityTransferStateMachine.SetInTransit(sp.UUID);
{ // if (!m_entityTransferStateMachine.SetInTransit(sp.UUID))
m_log.DebugFormat( // {
"[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.", // m_log.DebugFormat(
sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); // "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.",
// sp.Name, sp.UUID, reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position);
return; //
} // return;
// }
if (reg == null || finalDestination == null) if (reg == null || finalDestination == null)
{ {
@ -993,6 +995,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return neighbourRegion; return neighbourRegion;
} }
private void TeleportCancel(IClientAPI remoteClient)
{
m_entityTransferStateMachine.ResetFromTransit(remoteClient.AgentId);
}
public bool Cross(ScenePresence agent, bool isFlying) public bool Cross(ScenePresence agent, bool isFlying)
{ {
uint x; uint x;

View File

@ -42,6 +42,7 @@ using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using Mono.Addins; using Mono.Addins;
using Amib.Threading;
/***************************************************** /*****************************************************
* *
@ -102,6 +103,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
private Dictionary<UUID, HttpRequestClass> m_pendingRequests; private Dictionary<UUID, HttpRequestClass> m_pendingRequests;
private Scene m_scene; private Scene m_scene;
// private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>();
public static SmartThreadPool ThreadPool = null;
public HttpRequestModule() public HttpRequestModule()
{ {
@ -279,7 +281,30 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
int maxThreads = 50;
IConfig httpConfig = config.Configs["HttpRequestModule"];
if (httpConfig != null)
{
maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads);
}
m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
// First instance sets this up for all sims
if (ThreadPool == null)
{
STPStartInfo startInfo = new STPStartInfo();
startInfo.IdleTimeout = 20000;
startInfo.MaxWorkerThreads = maxThreads;
startInfo.MinWorkerThreads = 5;
startInfo.ThreadPriority = ThreadPriority.BelowNormal;
startInfo.StartSuspended = true;
ThreadPool = new SmartThreadPool(startInfo);
ThreadPool.Start();
}
} }
public void AddRegion(Scene scene) public void AddRegion(Scene scene)
@ -340,7 +365,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
public string HttpMIMEType = "text/plain;charset=utf-8"; public string HttpMIMEType = "text/plain;charset=utf-8";
public int HttpTimeout; public int HttpTimeout;
public bool HttpVerifyCert = true; public bool HttpVerifyCert = true;
private Thread httpThread; public IWorkItemResult WorkItem = null;
// Request info // Request info
private UUID _itemID; private UUID _itemID;
@ -374,12 +399,16 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
public void Process() public void Process()
{ {
httpThread = new Thread(SendRequest);
httpThread.Name = "HttpRequestThread";
httpThread.Priority = ThreadPriority.BelowNormal;
httpThread.IsBackground = true;
_finished = false; _finished = false;
httpThread.Start();
lock (HttpRequestModule.ThreadPool)
WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null);
}
private object StpSendWrapper(object o)
{
SendRequest();
return null;
} }
/* /*
@ -409,13 +438,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
{ {
// We could hijack Connection Group Name to identify // We could hijack Connection Group Name to identify
// a desired security exception. But at the moment we'll use a dummy header instead. // a desired security exception. But at the moment we'll use a dummy header instead.
// Request.ConnectionGroupName = "NoVerify";
Request.Headers.Add("NoVerifyCert", "true"); Request.Headers.Add("NoVerifyCert", "true");
} }
// else
// {
// Request.ConnectionGroupName="Verify";
// }
if (proxyurl != null && proxyurl.Length > 0) if (proxyurl != null && proxyurl.Length > 0)
{ {
if (proxyexcepts != null && proxyexcepts.Length > 0) if (proxyexcepts != null && proxyexcepts.Length > 0)
@ -485,9 +509,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
ResponseBody = sb.ToString().Replace("\r", ""); ResponseBody = sb.ToString().Replace("\r", "");
} }
catch (Exception e) catch (WebException e)
{ {
if (e is WebException && ((WebException)e).Status == WebExceptionStatus.ProtocolError) if (e.Status == WebExceptionStatus.ProtocolError)
{ {
HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response; HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response;
Status = (int)webRsp.StatusCode; Status = (int)webRsp.StatusCode;
@ -512,6 +536,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
_finished = true; _finished = true;
return; return;
} }
catch (Exception e)
{
// Don't crash on anything else
}
finally finally
{ {
if (response != null) if (response != null)
@ -525,7 +553,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
{ {
try try
{ {
httpThread.Abort(); if (!WorkItem.Cancel())
{
WorkItem.Abort();
}
} }
catch (Exception) catch (Exception)
{ {

View File

@ -352,7 +352,7 @@ namespace OpenSim.Region.Framework.Scenes
private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
private volatile bool m_backingup; private volatile bool m_backingup;
private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>(); private Dictionary<UUID, int> m_groupsWithTargets = new Dictionary<UUID, int>();
private string m_defaultScriptEngine; private string m_defaultScriptEngine;
@ -1723,7 +1723,7 @@ namespace OpenSim.Region.Framework.Scenes
public void AddGroupTarget(SceneObjectGroup grp) public void AddGroupTarget(SceneObjectGroup grp)
{ {
lock (m_groupsWithTargets) lock (m_groupsWithTargets)
m_groupsWithTargets[grp.UUID] = grp; m_groupsWithTargets[grp.UUID] = 0;
} }
public void RemoveGroupTarget(SceneObjectGroup grp) public void RemoveGroupTarget(SceneObjectGroup grp)
@ -1734,18 +1734,24 @@ namespace OpenSim.Region.Framework.Scenes
private void CheckAtTargets() private void CheckAtTargets()
{ {
List<SceneObjectGroup> objs = null; List<UUID> objs = null;
lock (m_groupsWithTargets) lock (m_groupsWithTargets)
{ {
if (m_groupsWithTargets.Count != 0) if (m_groupsWithTargets.Count != 0)
objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values); objs = new List<UUID>(m_groupsWithTargets.Keys);
} }
if (objs != null) if (objs != null)
{ {
foreach (SceneObjectGroup entry in objs) foreach (UUID entry in objs)
entry.checkAtTargets(); {
SceneObjectGroup grp = GetSceneObjectGroup(entry);
if (grp == null)
m_groupsWithTargets.Remove(entry);
else
grp.checkAtTargets();
}
} }
} }

View File

@ -79,14 +79,14 @@ namespace OpenSim.Region.Framework.Scenes
object_rez = 4194304 object_rez = 4194304
} }
struct scriptPosTarget public struct scriptPosTarget
{ {
public Vector3 targetPos; public Vector3 targetPos;
public float tolerance; public float tolerance;
public uint handle; public uint handle;
} }
struct scriptRotTarget public struct scriptRotTarget
{ {
public Quaternion targetRot; public Quaternion targetRot;
public float tolerance; public float tolerance;
@ -329,8 +329,18 @@ namespace OpenSim.Region.Framework.Scenes
protected SceneObjectPart m_rootPart; protected SceneObjectPart m_rootPart;
// private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>(); // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>(); private SortedDictionary<uint, scriptPosTarget> m_targets = new SortedDictionary<uint, scriptPosTarget>();
private Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>(); private SortedDictionary<uint, scriptRotTarget> m_rotTargets = new SortedDictionary<uint, scriptRotTarget>();
public SortedDictionary<uint, scriptPosTarget> AtTargets
{
get { return m_targets; }
}
public SortedDictionary<uint, scriptRotTarget> RotTargets
{
get { return m_rotTargets; }
}
private bool m_scriptListens_atTarget; private bool m_scriptListens_atTarget;
private bool m_scriptListens_notAtTarget; private bool m_scriptListens_notAtTarget;
@ -4141,6 +4151,8 @@ namespace OpenSim.Region.Framework.Scenes
waypoint.handle = handle; waypoint.handle = handle;
lock (m_rotTargets) lock (m_rotTargets)
{ {
if (m_rotTargets.Count >= 8)
m_rotTargets.Remove(m_rotTargets.ElementAt(0).Key);
m_rotTargets.Add(handle, waypoint); m_rotTargets.Add(handle, waypoint);
} }
m_scene.AddGroupTarget(this); m_scene.AddGroupTarget(this);
@ -4166,6 +4178,8 @@ namespace OpenSim.Region.Framework.Scenes
waypoint.handle = handle; waypoint.handle = handle;
lock (m_targets) lock (m_targets)
{ {
if (m_targets.Count >= 8)
m_targets.Remove(m_targets.ElementAt(0).Key);
m_targets.Add(handle, waypoint); m_targets.Add(handle, waypoint);
} }
m_scene.AddGroupTarget(this); m_scene.AddGroupTarget(this);

View File

@ -3039,42 +3039,40 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return src.ToLower(); return src.ToLower();
} }
public LSL_Integer llGiveMoney(string destination, int amount) public void llGiveMoney(string destination, int amount)
{ {
m_host.AddScriptLPS(1); Util.FireAndForget(x =>
if (m_item.PermsGranter == UUID.Zero)
return 0;
if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
{ {
LSLError("No permissions to give money"); m_host.AddScriptLPS(1);
return 0;
}
UUID toID = new UUID(); if (m_item.PermsGranter == UUID.Zero)
return;
if (!UUID.TryParse(destination, out toID)) if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
{ {
LSLError("Bad key in llGiveMoney"); LSLError("No permissions to give money");
return 0; return;
} }
IMoneyModule money = World.RequestModuleInterface<IMoneyModule>(); UUID toID = new UUID();
if (money == null) if (!UUID.TryParse(destination, out toID))
{ {
NotImplemented("llGiveMoney"); LSLError("Bad key in llGiveMoney");
return 0; return;
} }
bool result = money.ObjectGiveMoney( IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero);
if (result) if (money == null)
return 1; {
NotImplemented("llGiveMoney");
return;
}
return 0; money.ObjectGiveMoney(
m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero);
});
} }
public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
@ -7330,7 +7328,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
if (xmlrpcMod.IsEnabled()) if (xmlrpcMod != null && xmlrpcMod.IsEnabled())
{ {
UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero); UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero);
IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>(); IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
@ -7362,6 +7360,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
ScriptSleep(3000); ScriptSleep(3000);
if (xmlrpcMod == null)
return "";
return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString(); return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString();
} }
@ -7369,7 +7369,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); if (xmlrpcMod != null)
xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
ScriptSleep(3000); ScriptSleep(3000);
} }
@ -7384,7 +7385,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
xmlrpcMod.CloseXMLRPCChannel((UUID)channel); if (xmlrpcMod != null)
xmlrpcMod.CloseXMLRPCChannel((UUID)channel);
ScriptSleep(1000); ScriptSleep(1000);
} }
@ -7797,8 +7799,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
ScriptSleep(200);
} }
private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
@ -12677,7 +12677,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
bool result = money.ObjectGiveMoney( bool result = money.ObjectGiveMoney(
m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero); m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount, txn);
if (result) if (result)
{ {

View File

@ -1857,17 +1857,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
UUID assetID = UUID.Zero; UUID assetID = UUID.Zero;
if (!UUID.TryParse(notecardNameOrUuid, out assetID)) bool notecardNameIsUUID = UUID.TryParse(notecardNameOrUuid, out assetID);
if (!notecardNameIsUUID)
{ {
m_host.TaskInventory.LockItemsForRead(true); assetID = SearchTaskInventoryForAssetId(notecardNameOrUuid);
foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
{
if (item.Type == 7 && item.Name == notecardNameOrUuid)
{
assetID = item.AssetID;
}
}
m_host.TaskInventory.LockItemsForRead(false);
} }
if (assetID == UUID.Zero) if (assetID == UUID.Zero)
@ -1878,7 +1872,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
AssetBase a = World.AssetService.Get(assetID.ToString()); AssetBase a = World.AssetService.Get(assetID.ToString());
if (a == null) if (a == null)
return UUID.Zero; {
// Whoops, it's still possible here that the notecard name was properly
// formatted like a UUID but isn't an asset UUID so lets look it up by name after all
assetID = SearchTaskInventoryForAssetId(notecardNameOrUuid);
if (assetID == UUID.Zero)
return UUID.Zero;
if (!NotecardCache.IsCached(assetID))
{
a = World.AssetService.Get(assetID.ToString());
if (a == null)
{
return UUID.Zero;
}
}
}
string data = Encoding.UTF8.GetString(a.Data); string data = Encoding.UTF8.GetString(a.Data);
NotecardCache.Cache(assetID, data); NotecardCache.Cache(assetID, data);
@ -1886,6 +1896,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return assetID; return assetID;
} }
protected UUID SearchTaskInventoryForAssetId(string name)
{
UUID assetId = UUID.Zero;
m_host.TaskInventory.LockItemsForRead(true);
foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
{
if (item.Type == 7 && item.Name == name)
{
assetId = item.AssetID;
}
}
m_host.TaskInventory.LockItemsForRead(false);
return assetId;
}
/// <summary> /// <summary>
/// Directly get an entire notecard at once. /// Directly get an entire notecard at once.

View File

@ -208,7 +208,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
LSL_Float llGetWallclock(); LSL_Float llGetWallclock();
void llGiveInventory(string destination, string inventory); void llGiveInventory(string destination, string inventory);
void llGiveInventoryList(string destination, string category, LSL_List inventory); void llGiveInventoryList(string destination, string category, LSL_List inventory);
LSL_Integer llGiveMoney(string destination, int amount); void llGiveMoney(string destination, int amount);
LSL_String llTransferLindenDollars(string destination, int amount); LSL_String llTransferLindenDollars(string destination, int amount);
void llGodLikeRezObject(string inventory, LSL_Vector pos); void llGodLikeRezObject(string inventory, LSL_Vector pos);
LSL_Float llGround(LSL_Vector offset); LSL_Float llGround(LSL_Vector offset);

View File

@ -876,9 +876,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
m_LSL_Functions.llGiveInventoryList(destination, category, inventory); m_LSL_Functions.llGiveInventoryList(destination, category, inventory);
} }
public LSL_Integer llGiveMoney(string destination, int amount) public void llGiveMoney(string destination, int amount)
{ {
return m_LSL_Functions.llGiveMoney(destination, amount); m_LSL_Functions.llGiveMoney(destination, amount);
} }
public LSL_String llTransferLindenDollars(string destination, int amount) public LSL_String llTransferLindenDollars(string destination, int amount)

View File

@ -1688,6 +1688,7 @@
<!-- To allow regions to have mono addins --> <!-- To allow regions to have mono addins -->
<Reference name="Mono.Addins" path="../../../bin/"/> <Reference name="Mono.Addins" path="../../../bin/"/>
<Reference name="SmartThreadPool"/>
<Files> <Files>
<Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/> <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>