Merge branch 'master' into careminster

Conflicts:
	OpenSim/Region/CoreModules/World/Region/RestartModule.cs
	OpenSim/Region/Framework/Scenes/SceneGraph.cs
	OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
avinationmerge
Melanie 2013-09-01 22:49:31 +01:00
commit 008c98a974
25 changed files with 945 additions and 299 deletions

View File

@ -179,8 +179,8 @@ namespace OpenSim.Framework.Console
/// Convert a console integer to an int, automatically complaining if a console is given. /// Convert a console integer to an int, automatically complaining if a console is given.
/// </summary> /// </summary>
/// <param name='console'>Can be null if no console is available.</param> /// <param name='console'>Can be null if no console is available.</param>
/// <param name='rawConsoleVector'>/param> /// <param name='rawConsoleInt'>/param>
/// <param name='vector'></param> /// <param name='i'></param>
/// <returns></returns> /// <returns></returns>
public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i) public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i)
{ {
@ -195,6 +195,31 @@ namespace OpenSim.Framework.Console
return true; return true;
} }
/// <summary>
/// Convert a console integer to a natural int, automatically complaining if a console is given.
/// </summary>
/// <param name='console'>Can be null if no console is available.</param>
/// <param name='rawConsoleInt'>/param>
/// <param name='i'></param>
/// <returns></returns>
public static bool TryParseConsoleNaturalInt(ICommandConsole console, string rawConsoleInt, out int i)
{
if (TryParseConsoleInt(console, rawConsoleInt, out i))
{
if (i < 0)
{
if (console != null)
console.OutputFormat("ERROR: {0} is not a positive integer", rawConsoleInt);
return false;
}
return true;
}
return false;
}
/// <summary> /// <summary>
/// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
/// </summary> /// </summary>

View File

@ -67,7 +67,7 @@ namespace OpenSim.Framework.Monitoring
if (cmd[3] == "start") if (cmd[3] == "start")
{ {
Start(); Start();
con.OutputFormat("Now recording all stats very {0}ms to file", m_statsLogIntervalMs); con.OutputFormat("Now recording all stats to file every {0}ms", m_statsLogIntervalMs);
} }
else if (cmd[3] == "stop") else if (cmd[3] == "stop")
{ {

View File

@ -201,12 +201,12 @@ namespace OpenSim
envConfigSource.LoadEnv(); envConfigSource.LoadEnv();
m_config.Source.Merge(envConfigSource); m_config.Source.Merge(envConfigSource);
m_config.Source.ExpandKeyValues();
} }
ReadConfigSettings(); ReadConfigSettings();
m_config.Source.ExpandKeyValues();
return m_config; return m_config;
} }

View File

@ -6777,6 +6777,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
#endregion #endregion
if (SceneAgent.IsChildAgent)
{
SendCantSitBecauseChildAgentResponse();
return true;
}
AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
if (handlerAgentRequestSit != null) if (handlerAgentRequestSit != null)
@ -6801,6 +6807,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
#endregion #endregion
if (SceneAgent.IsChildAgent)
{
SendCantSitBecauseChildAgentResponse();
return true;
}
AgentSit handlerAgentSit = OnAgentSit; AgentSit handlerAgentSit = OnAgentSit;
if (handlerAgentSit != null) if (handlerAgentSit != null)
{ {
@ -6810,6 +6822,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return true; return true;
} }
/// <summary>
/// Used when a child agent gets a sit response which should not be fulfilled.
/// </summary>
private void SendCantSitBecauseChildAgentResponse()
{
SendAlertMessage("Try moving closer. Can't sit on object because it is not in the same region as you.");
}
private bool HandleSoundTrigger(IClientAPI sender, Packet Pack) private bool HandleSoundTrigger(IClientAPI sender, Packet Pack)
{ {
SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack;
@ -12934,7 +12954,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
if (p is ScenePresence) if (p is ScenePresence)
{ {
ScenePresence presence = p as ScenePresence;
// It turns out to get the agent to stop flying, you have to feed it stop flying velocities // It turns out to get the agent to stop flying, you have to feed it stop flying velocities
// There's no explicit message to send the client to tell it to stop flying.. it relies on the // There's no explicit message to send the client to tell it to stop flying.. it relies on the
// velocity, collision plane and avatar height // velocity, collision plane and avatar height
@ -12942,15 +12961,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Add 1/6 the avatar's height to it's position so it doesn't shoot into the air // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air
// when the avatar stands up // when the avatar stands up
Vector3 pos = presence.AbsolutePosition;
ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = ImprovedTerseObjectUpdatePacket.ObjectDataBlock block =
CreateImprovedTerseBlock(p, false); CreateImprovedTerseBlock(p, false);
const float TIME_DILATION = 1.0f; const float TIME_DILATION = 1.0f;
ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
ImprovedTerseObjectUpdatePacket packet ImprovedTerseObjectUpdatePacket packet
= (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
PacketType.ImprovedTerseObjectUpdate); PacketType.ImprovedTerseObjectUpdate);

View File

@ -538,7 +538,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e.Message); m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e);
return null; return null;
} }
*/ */

View File

@ -309,6 +309,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
string serverURI = string.Empty; string serverURI = string.Empty;
GetUserProfileServerURI(targetID, out serverURI); GetUserProfileServerURI(targetID, out serverURI);
UUID creatorId = UUID.Zero; UUID creatorId = UUID.Zero;
Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
OSDMap parameters= new OSDMap(); OSDMap parameters= new OSDMap();
UUID.TryParse(args[0], out creatorId); UUID.TryParse(args[0], out creatorId);
@ -316,15 +317,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
OSD Params = (OSD)parameters; OSD Params = (OSD)parameters;
if(!JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString())) if(!JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
{ {
// Error Handling here! remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds);
// if(parameters.ContainsKey("message") return;
} }
parameters = (OSDMap)Params; parameters = (OSDMap)Params;
OSDArray list = (OSDArray)parameters["result"]; OSDArray list = (OSDArray)parameters["result"];
Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
foreach(OSD map in list) foreach(OSD map in list)
{ {
@ -441,7 +441,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
Vector3 pos = remoteClient.SceneAgent.AbsolutePosition; Vector3 pos = remoteClient.SceneAgent.AbsolutePosition;
ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y); ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y);
ScenePresence p = FindPresence(remoteClient.AgentId); ScenePresence p = FindPresence(remoteClient.AgentId);
// Vector3 avaPos = p.AbsolutePosition;
string serverURI = string.Empty; string serverURI = string.Empty;
GetUserProfileServerURI(remoteClient.AgentId, out serverURI); GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
@ -543,13 +542,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
string serverURI = string.Empty; string serverURI = string.Empty;
GetUserProfileServerURI(targetId, out serverURI); GetUserProfileServerURI(targetId, out serverURI);
Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
OSDMap parameters= new OSDMap(); OSDMap parameters= new OSDMap();
parameters.Add("creatorId", OSD.FromUUID(targetId)); parameters.Add("creatorId", OSD.FromUUID(targetId));
OSD Params = (OSD)parameters; OSD Params = (OSD)parameters;
if(!JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString())) if(!JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString()))
{ {
remoteClient.SendAgentAlertMessage( remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
"Error requesting picks", false);
return; return;
} }
@ -557,8 +557,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
OSDArray list = (OSDArray)parameters["result"]; OSDArray list = (OSDArray)parameters["result"];
Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
foreach(OSD map in list) foreach(OSD map in list)
{ {
OSDMap m = (OSDMap)map; OSDMap m = (OSDMap)map;
@ -762,8 +760,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
object Note = (object)note; object Note = (object)note;
if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString())) if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))
{ {
remoteClient.SendAgentAlertMessage( remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
"Error requesting note", false); return;
} }
note = (UserProfileNotes) Note; note = (UserProfileNotes) Note;
@ -796,8 +794,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
object Note = note; object Note = note;
if(!JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString())) if(!JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString()))
{ {
remoteClient.SendAgentAlertMessage( return;
"Error updating note", false);
} }
} }
#endregion Notes #endregion Notes
@ -1033,8 +1030,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
OSD Params = (OSD)parameters; OSD Params = (OSD)parameters;
if(!JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString())) if(!JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString()))
{ {
// Error Handling here!
// if(parameters.ContainsKey("message")
return false; return false;
} }
@ -1224,7 +1219,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
byte[] content = Encoding.UTF8.GetBytes(jsonRequestData); byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri); HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
// webRequest.Credentials = new NetworkCredential(rpcUser, rpcPass);
webRequest.ContentType = "application/json-rpc"; webRequest.ContentType = "application/json-rpc";
webRequest.Method = "POST"; webRequest.Method = "POST";
@ -1245,7 +1240,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
} }
Stream rstream = webResponse.GetResponseStream(); Stream rstream = webResponse.GetResponseStream();
OSDMap mret = (OSDMap)OSDParser.DeserializeJson(rstream); if (rstream.Length < 1)
return false;
OSDMap mret = new OSDMap();
try
{
mret = (OSDMap)OSDParser.DeserializeJson(rstream);
}
catch (Exception e)
{
m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
return false;
}
if (mret.ContainsKey("error")) if (mret.ContainsKey("error"))
return false; return false;
@ -1310,6 +1318,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
} }
Stream rstream = webResponse.GetResponseStream(); Stream rstream = webResponse.GetResponseStream();
if (rstream.Length < 1)
return false;
OSDMap response = new OSDMap(); OSDMap response = new OSDMap();
try try

View File

@ -837,8 +837,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
} }
m_log.WarnFormat( m_log.WarnFormat(
"[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); sp.Name, finalDestination.RegionName, sp.Scene.Name);
Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
return; return;
@ -1058,8 +1058,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
} }
m_log.WarnFormat( m_log.WarnFormat(
"[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); sp.Name, finalDestination.RegionName, sp.Scene.Name);
Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
return; return;

View File

@ -48,8 +48,8 @@ namespace OpenSim.Region.CoreModules.World.Region
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")] [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")]
public class RestartModule : INonSharedRegionModule, IRestartModule public class RestartModule : INonSharedRegionModule, IRestartModule
{ {
// private static readonly ILog m_log = private static readonly ILog m_log =
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected Scene m_Scene; protected Scene m_Scene;
protected Timer m_CountdownTimer = null; protected Timer m_CountdownTimer = null;
@ -223,11 +223,25 @@ namespace OpenSim.Region.CoreModules.World.Region
public void SetTimer(int intervalSeconds) public void SetTimer(int intervalSeconds)
{ {
m_CountdownTimer = new Timer(); if (intervalSeconds > 0)
m_CountdownTimer.AutoReset = false; {
m_CountdownTimer.Interval = intervalSeconds * 1000; m_CountdownTimer = new Timer();
m_CountdownTimer.Elapsed += OnTimer; m_CountdownTimer.AutoReset = false;
m_CountdownTimer.Start(); m_CountdownTimer.Interval = intervalSeconds * 1000;
m_CountdownTimer.Elapsed += OnTimer;
m_CountdownTimer.Start();
}
else if (m_CountdownTimer != null)
{
m_CountdownTimer.Stop();
m_CountdownTimer = null;
}
else
{
m_log.WarnFormat(
"[RESTART MODULE]: Tried to set restart timer to {0} in {1}, which is not a valid interval",
intervalSeconds, m_Scene.Name);
}
} }
private void OnTimer(object source, ElapsedEventArgs e) private void OnTimer(object source, ElapsedEventArgs e)

View File

@ -3986,7 +3986,7 @@ namespace OpenSim.Region.Framework.Scenes
try try
{ {
if (!AuthorizeUser(acd, SeeIntoRegion, out reason)) if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason))
{ {
m_authenticateHandler.RemoveCircuit(acd.circuitcode); m_authenticateHandler.RemoveCircuit(acd.circuitcode);
return false; return false;
@ -4596,10 +4596,27 @@ namespace OpenSim.Region.Framework.Scenes
// Check that the auth_token is valid // Check that the auth_token is valid
AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID); AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID);
if (acd != null && acd.SessionID.ToString() == auth_token)
if (acd == null)
{
m_log.DebugFormat(
"[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
agentID, Name);
return false;
}
if (acd.SessionID.ToString() == auth_token)
{
return IncomingCloseAgent(agentID, force); return IncomingCloseAgent(agentID, force);
}
else else
m_log.ErrorFormat("[SCENE]: Request to close agent {0} with invalid authorization token {1}", agentID, auth_token); {
m_log.WarnFormat(
"[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
agentID, auth_token, Name);
}
return false; return false;
} }

View File

@ -631,40 +631,16 @@ namespace OpenSim.Region.Framework.Scenes
protected internal ScenePresence CreateAndAddChildScenePresence( protected internal ScenePresence CreateAndAddChildScenePresence(
IClientAPI client, AvatarAppearance appearance, PresenceType type) IClientAPI client, AvatarAppearance appearance, PresenceType type)
{ {
ScenePresence newAvatar = null;
// ScenePresence always defaults to child agent // ScenePresence always defaults to child agent
newAvatar = new ScenePresence(client, m_parentScene, appearance, type); ScenePresence presence = new ScenePresence(client, m_parentScene, appearance, type);
AddScenePresence(newAvatar);
return newAvatar;
}
/// <summary>
/// Add a presence to the scene
/// </summary>
/// <param name="presence"></param>
protected internal void AddScenePresence(ScenePresence presence)
{
// Always a child when added to the scene
bool child = presence.IsChildAgent;
if (child)
{
m_numChildAgents++;
}
else
{
m_numRootAgents++;
presence.AddToPhysicalScene(false);
}
Entities[presence.UUID] = presence; Entities[presence.UUID] = presence;
m_scenePresencesLock.EnterWriteLock(); m_scenePresencesLock.EnterWriteLock();
try try
{ {
m_numChildAgents++;
Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@ -675,7 +651,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
else else
{ {
// Remember the old presene reference from the dictionary // Remember the old presence reference from the dictionary
ScenePresence oldref = newmap[presence.UUID]; ScenePresence oldref = newmap[presence.UUID];
// Replace the presence reference in the dictionary with the new value // Replace the presence reference in the dictionary with the new value
newmap[presence.UUID] = presence; newmap[presence.UUID] = presence;
@ -691,6 +667,8 @@ namespace OpenSim.Region.Framework.Scenes
{ {
m_scenePresencesLock.ExitWriteLock(); m_scenePresencesLock.ExitWriteLock();
} }
return presence;
} }
/// <summary> /// <summary>

View File

@ -4522,7 +4522,7 @@ namespace OpenSim.Region.Framework.Scenes
// For now, we use the NINJA naming scheme for identifying joints. // For now, we use the NINJA naming scheme for identifying joints.
// In the future, we can support other joint specification schemes such as a // In the future, we can support other joint specification schemes such as a
// custom checkbox in the viewer GUI. // custom checkbox in the viewer GUI.
if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
{ {
return IsHingeJoint() || IsBallJoint(); return IsHingeJoint() || IsBallJoint();
} }

View File

@ -2707,6 +2707,9 @@ namespace OpenSim.Region.Framework.Scenes
public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
{ {
if (IsChildAgent)
return;
SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
if (part != null) if (part != null)
@ -2793,6 +2796,9 @@ namespace OpenSim.Region.Framework.Scenes
public void HandleAgentSitOnGround() public void HandleAgentSitOnGround()
{ {
if (IsChildAgent)
return;
// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. // m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
m_AngularVelocity = Vector3.Zero; m_AngularVelocity = Vector3.Zero;
Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
@ -3451,11 +3457,6 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public void RestoreInCurrentScene()
{
AddToPhysicalScene(false); // not exactly false
}
public void Reset() public void Reset()
{ {
// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);

View File

@ -0,0 +1,220 @@
/*
* 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 System.Text.RegularExpressions;
using log4net;
using Mono.Addins;
using NDesk.Options;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.OptionalModules.Avatar.SitStand
{
/// <summary>
/// A module that just holds commands for changing avatar sitting and standing states.
/// </summary>
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AnimationsCommandModule")]
public class SitStandCommandModule : INonSharedRegionModule
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;
public string Name { get { return "SitStand Command Module"; } }
public Type ReplaceableInterface { get { return null; } }
public void Initialise(IConfigSource source)
{
// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: INITIALIZED MODULE");
}
public void PostInitialise()
{
// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: POST INITIALIZED MODULE");
}
public void Close()
{
// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: CLOSED MODULE");
}
public void AddRegion(Scene scene)
{
// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
}
public void RemoveRegion(Scene scene)
{
// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
}
public void RegionLoaded(Scene scene)
{
// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
m_scene = scene;
scene.AddCommand(
"Users", this, "sit user name",
"sit user name [--regex] <first-name> <last-name>",
"Sit the named user on an unoccupied object with a sit target.",
"If there are no such objects then nothing happens.\n"
+ "If --regex is specified then the names are treated as regular expressions.",
HandleSitUserNameCommand);
scene.AddCommand(
"Users", this, "stand user name",
"stand user name [--regex] <first-name> <last-name>",
"Stand the named user.",
"If --regex is specified then the names are treated as regular expressions.",
HandleStandUserNameCommand);
}
private void HandleSitUserNameCommand(string module, string[] cmd)
{
if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
return;
if (cmd.Length < 5)
{
MainConsole.Instance.Output("Usage: sit user name [--regex] <first-name> <last-name>");
return;
}
List<ScenePresence> scenePresences = GetScenePresences(cmd);
foreach (ScenePresence sp in scenePresences)
{
if (sp.SitGround || sp.IsSatOnObject)
continue;
SceneObjectPart sitPart = null;
List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups();
foreach (SceneObjectGroup sceneObject in sceneObjects)
{
if (sceneObject.IsAttachment)
continue;
foreach (SceneObjectPart part in sceneObject.Parts)
{
if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
{
sitPart = part;
break;
}
}
}
if (sitPart != null)
{
MainConsole.Instance.OutputFormat(
"Sitting {0} on {1} {2} in {3}",
sp.Name, sitPart.ParentGroup.Name, sitPart.ParentGroup.UUID, m_scene.Name);
sp.HandleAgentRequestSit(sp.ControllingClient, sp.UUID, sitPart.UUID, Vector3.Zero);
sp.HandleAgentSit(sp.ControllingClient, sp.UUID);
}
else
{
MainConsole.Instance.OutputFormat(
"Could not find any unoccupied set seat on which to sit {0} in {1}. Aborting",
sp.Name, m_scene.Name);
break;
}
}
}
private void HandleStandUserNameCommand(string module, string[] cmd)
{
if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
return;
if (cmd.Length < 5)
{
MainConsole.Instance.Output("Usage: stand user name [--regex] <first-name> <last-name>");
return;
}
List<ScenePresence> scenePresences = GetScenePresences(cmd);
foreach (ScenePresence sp in scenePresences)
{
if (sp.SitGround || sp.IsSatOnObject)
{
MainConsole.Instance.OutputFormat("Standing {0} in {1}", sp.Name, m_scene.Name);
sp.StandUp();
}
}
}
private List<ScenePresence> GetScenePresences(string[] cmdParams)
{
bool useRegex = false;
OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
List<string> mainParams = options.Parse(cmdParams);
string firstName = mainParams[3];
string lastName = mainParams[4];
List<ScenePresence> scenePresencesMatched = new List<ScenePresence>();
if (useRegex)
{
Regex nameRegex = new Regex(string.Format("{0} {1}", firstName, lastName));
List<ScenePresence> scenePresences = m_scene.GetScenePresences();
foreach (ScenePresence sp in scenePresences)
{
if (!sp.IsChildAgent && nameRegex.IsMatch(sp.Name))
scenePresencesMatched.Add(sp);
}
}
else
{
ScenePresence sp = m_scene.GetScenePresence(firstName, lastName);
if (sp != null && !sp.IsChildAgent)
scenePresencesMatched.Add(sp);
}
return scenePresencesMatched;
}
}
}

View File

@ -1221,6 +1221,50 @@ private sealed class BulletConstraintXNA : BulletConstraint
//BSParam.TerrainImplementation = 0; //BSParam.TerrainImplementation = 0;
world.SetGravity(new IndexedVector3(0,0,p.gravity)); world.SetGravity(new IndexedVector3(0,0,p.gravity));
// Turn off Pooling since globals and pooling are bad for threading.
BulletGlobals.VoronoiSimplexSolverPool.SetPoolingEnabled(false);
BulletGlobals.SubSimplexConvexCastPool.SetPoolingEnabled(false);
BulletGlobals.ManifoldPointPool.SetPoolingEnabled(false);
BulletGlobals.CastResultPool.SetPoolingEnabled(false);
BulletGlobals.SphereShapePool.SetPoolingEnabled(false);
BulletGlobals.DbvtNodePool.SetPoolingEnabled(false);
BulletGlobals.SingleRayCallbackPool.SetPoolingEnabled(false);
BulletGlobals.SubSimplexClosestResultPool.SetPoolingEnabled(false);
BulletGlobals.GjkPairDetectorPool.SetPoolingEnabled(false);
BulletGlobals.DbvtTreeColliderPool.SetPoolingEnabled(false);
BulletGlobals.SingleSweepCallbackPool.SetPoolingEnabled(false);
BulletGlobals.BroadphaseRayTesterPool.SetPoolingEnabled(false);
BulletGlobals.ClosestNotMeConvexResultCallbackPool.SetPoolingEnabled(false);
BulletGlobals.GjkEpaPenetrationDepthSolverPool.SetPoolingEnabled(false);
BulletGlobals.ContinuousConvexCollisionPool.SetPoolingEnabled(false);
BulletGlobals.DbvtStackDataBlockPool.SetPoolingEnabled(false);
BulletGlobals.BoxBoxCollisionAlgorithmPool.SetPoolingEnabled(false);
BulletGlobals.CompoundCollisionAlgorithmPool.SetPoolingEnabled(false);
BulletGlobals.ConvexConcaveCollisionAlgorithmPool.SetPoolingEnabled(false);
BulletGlobals.ConvexConvexAlgorithmPool.SetPoolingEnabled(false);
BulletGlobals.ConvexPlaneAlgorithmPool.SetPoolingEnabled(false);
BulletGlobals.SphereBoxCollisionAlgorithmPool.SetPoolingEnabled(false);
BulletGlobals.SphereSphereCollisionAlgorithmPool.SetPoolingEnabled(false);
BulletGlobals.SphereTriangleCollisionAlgorithmPool.SetPoolingEnabled(false);
BulletGlobals.GImpactCollisionAlgorithmPool.SetPoolingEnabled(false);
BulletGlobals.GjkEpaSolver2MinkowskiDiffPool.SetPoolingEnabled(false);
BulletGlobals.PersistentManifoldPool.SetPoolingEnabled(false);
BulletGlobals.ManifoldResultPool.SetPoolingEnabled(false);
BulletGlobals.GJKPool.SetPoolingEnabled(false);
BulletGlobals.GIM_ShapeRetrieverPool.SetPoolingEnabled(false);
BulletGlobals.TriangleShapePool.SetPoolingEnabled(false);
BulletGlobals.SphereTriangleDetectorPool.SetPoolingEnabled(false);
BulletGlobals.CompoundLeafCallbackPool.SetPoolingEnabled(false);
BulletGlobals.GjkConvexCastPool.SetPoolingEnabled(false);
BulletGlobals.LocalTriangleSphereCastCallbackPool.SetPoolingEnabled(false);
BulletGlobals.BridgeTriangleRaycastCallbackPool.SetPoolingEnabled(false);
BulletGlobals.BridgeTriangleConcaveRaycastCallbackPool.SetPoolingEnabled(false);
BulletGlobals.BridgeTriangleConvexcastCallbackPool.SetPoolingEnabled(false);
BulletGlobals.MyNodeOverlapCallbackPool.SetPoolingEnabled(false);
BulletGlobals.ClosestRayResultCallbackPool.SetPoolingEnabled(false);
BulletGlobals.DebugDrawcallbackPool.SetPoolingEnabled(false);
return world; return world;
} }
//m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL //m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL
@ -1914,7 +1958,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
heightMap, scaleFactor, heightMap, scaleFactor,
minHeight, maxHeight, upAxis, minHeight, maxHeight, upAxis,
false); false);
terrainShape.SetMargin(collisionMargin + 0.5f); terrainShape.SetMargin(collisionMargin);
terrainShape.SetUseDiamondSubdivision(true); terrainShape.SetUseDiamondSubdivision(true);
terrainShape.SetUserPointer(id); terrainShape.SetUserPointer(id);
return new BulletShapeXNA(terrainShape, BSPhysicsShapeType.SHAPE_TERRAIN); return new BulletShapeXNA(terrainShape, BSPhysicsShapeType.SHAPE_TERRAIN);

View File

@ -946,7 +946,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
private void ProcessRegularTaints() private void ProcessRegularTaints()
{ {
if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process if (m_initialized && _taintOperations.Count > 0) // save allocating new list if there is nothing to process
{ {
// swizzle a new list into the list location so we can process what's there // swizzle a new list into the list location so we can process what's there
List<TaintCallbackEntry> oldList; List<TaintCallbackEntry> oldList;
@ -989,7 +989,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// Taints that happen after the normal taint processing but before the simulation step. // Taints that happen after the normal taint processing but before the simulation step.
private void ProcessPostTaintTaints() private void ProcessPostTaintTaints()
{ {
if (_postTaintOperations.Count > 0) if (m_initialized && _postTaintOperations.Count > 0)
{ {
Dictionary<string, TaintCallbackEntry> oldList; Dictionary<string, TaintCallbackEntry> oldList;
lock (_taintLock) lock (_taintLock)

View File

@ -86,7 +86,7 @@ namespace OpenSim.Services.GridService
{ {
MainConsole.Instance.Commands.AddCommand("Regions", true, MainConsole.Instance.Commands.AddCommand("Regions", true,
"deregister region id", "deregister region id",
"deregister region id <Region UUID>", "deregister region id <region-id>+",
"Deregister a region manually.", "Deregister a region manually.",
String.Empty, String.Empty,
HandleDeregisterRegion); HandleDeregisterRegion);
@ -526,40 +526,41 @@ namespace OpenSim.Services.GridService
private void HandleDeregisterRegion(string module, string[] cmd) private void HandleDeregisterRegion(string module, string[] cmd)
{ {
if (cmd.Length != 4) if (cmd.Length < 4)
{ {
MainConsole.Instance.Output("Syntax: degregister region id <Region UUID>"); MainConsole.Instance.Output("Usage: degregister region id <region-id>+");
return; return;
} }
string rawRegionUuid = cmd[3]; for (int i = 3; i < cmd.Length; i++)
UUID regionUuid;
if (!UUID.TryParse(rawRegionUuid, out regionUuid))
{ {
MainConsole.Instance.OutputFormat("{0} is not a valid region uuid", rawRegionUuid); string rawRegionUuid = cmd[i];
return; UUID regionUuid;
}
GridRegion region = GetRegionByUUID(UUID.Zero, regionUuid); if (!UUID.TryParse(rawRegionUuid, out regionUuid))
{
MainConsole.Instance.OutputFormat("{0} is not a valid region uuid", rawRegionUuid);
return;
}
if (region == null) GridRegion region = GetRegionByUUID(UUID.Zero, regionUuid);
{
MainConsole.Instance.OutputFormat("No region with UUID {0}", regionUuid);
return;
}
if (DeregisterRegion(regionUuid)) if (region == null)
{ {
MainConsole.Instance.OutputFormat("Deregistered {0} {1}", region.RegionName, regionUuid); MainConsole.Instance.OutputFormat("No region with UUID {0}", regionUuid);
} return;
else }
{
// I don't think this can ever occur if we know that the region exists.
MainConsole.Instance.OutputFormat("Error deregistering {0} {1}", region.RegionName, regionUuid);
}
return; if (DeregisterRegion(regionUuid))
{
MainConsole.Instance.OutputFormat("Deregistered {0} {1}", region.RegionName, regionUuid);
}
else
{
// I don't think this can ever occur if we know that the region exists.
MainConsole.Instance.OutputFormat("Error deregistering {0} {1}", region.RegionName, regionUuid);
}
}
} }
private void HandleShowRegions(string module, string[] cmd) private void HandleShowRegions(string module, string[] cmd)

View File

@ -326,7 +326,7 @@ namespace OpenSim.Services.HypergridService
return false; return false;
} }
m_log.DebugFormat("[GATEKEEPER SERVICE]: User is OK"); m_log.DebugFormat("[GATEKEEPER SERVICE]: User {0} is ok", aCircuit.Name);
bool isFirstLogin = false; bool isFirstLogin = false;
// //
@ -345,7 +345,8 @@ namespace OpenSim.Services.HypergridService
aCircuit.firstname, aCircuit.lastname); aCircuit.firstname, aCircuit.lastname);
return false; return false;
} }
m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence ok");
m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence {0} is ok", aCircuit.Name);
// Also login foreigners with GridUser service // Also login foreigners with GridUser service
if (m_GridUserService != null && account == null) if (m_GridUserService != null && account == null)
@ -376,7 +377,9 @@ namespace OpenSim.Services.HypergridService
reason = "Destination region not found"; reason = "Destination region not found";
return false; return false;
} }
m_log.DebugFormat("[GATEKEEPER SERVICE]: destination ok: {0}", destination.RegionName);
m_log.DebugFormat(
"[GATEKEEPER SERVICE]: Destination {0} is ok for {1}", destination.RegionName, aCircuit.Name);
// //
// Adjust the visible name // Adjust the visible name
@ -410,7 +413,8 @@ namespace OpenSim.Services.HypergridService
// Preserve our TeleportFlags we have gathered so-far // Preserve our TeleportFlags we have gathered so-far
loginFlag |= (Constants.TeleportFlags) aCircuit.teleportFlags; loginFlag |= (Constants.TeleportFlags) aCircuit.teleportFlags;
m_log.DebugFormat("[GATEKEEPER SERVICE]: launching agent {0}", loginFlag); m_log.DebugFormat("[GATEKEEPER SERVICE]: Launching {0} {1}", aCircuit.Name, loginFlag);
return m_SimulationService.CreateAgent(destination, aCircuit, (uint)loginFlag, out reason); return m_SimulationService.CreateAgent(destination, aCircuit, (uint)loginFlag, out reason);
} }

View File

@ -137,7 +137,10 @@ namespace OpenSim.Services.Interfaces
if ( m_serverURI != string.Empty ) { if ( m_serverURI != string.Empty ) {
return m_serverURI; return m_serverURI;
} else { } else {
return "http://" + m_externalHostName + ":" + m_httpPort + "/"; if (m_httpPort == 0)
return "http://" + m_externalHostName + "/";
else
return "http://" + m_externalHostName + ":" + m_httpPort + "/";
} }
} }
set { set {

View File

@ -97,6 +97,28 @@ namespace pCampBot
/// </summary> /// </summary>
public ConnectionState ConnectionState { get; private set; } public ConnectionState ConnectionState { get; private set; }
public List<Simulator> Simulators
{
get
{
lock (Client.Network.Simulators)
return new List<Simulator>(Client.Network.Simulators);
}
}
/// <summary>
/// The number of connections that this bot has to different simulators.
/// </summary>
/// <value>Includes both root and child connections.</value>
public int SimulatorsCount
{
get
{
lock (Client.Network.Simulators)
return Client.Network.Simulators.Count;
}
}
public string FirstName { get; private set; } public string FirstName { get; private set; }
public string LastName { get; private set; } public string LastName { get; private set; }
public string Name { get; private set; } public string Name { get; private set; }
@ -145,8 +167,6 @@ namespace pCampBot
behaviours.ForEach(b => b.Initialize(this)); behaviours.ForEach(b => b.Initialize(this));
Client = new GridClient();
Random = new Random(Environment.TickCount);// We do stuff randomly here Random = new Random(Environment.TickCount);// We do stuff randomly here
FirstName = firstName; FirstName = firstName;
LastName = lastName; LastName = lastName;
@ -157,6 +177,59 @@ namespace pCampBot
Manager = bm; Manager = bm;
Behaviours = behaviours; Behaviours = behaviours;
// Only calling for use as a template.
CreateLibOmvClient();
}
private void CreateLibOmvClient()
{
GridClient newClient = new GridClient();
if (Client != null)
{
newClient.Settings.LOGIN_SERVER = Client.Settings.LOGIN_SERVER;
newClient.Settings.ALWAYS_DECODE_OBJECTS = Client.Settings.ALWAYS_DECODE_OBJECTS;
newClient.Settings.AVATAR_TRACKING = Client.Settings.AVATAR_TRACKING;
newClient.Settings.OBJECT_TRACKING = Client.Settings.OBJECT_TRACKING;
newClient.Settings.SEND_AGENT_THROTTLE = Client.Settings.SEND_AGENT_THROTTLE;
newClient.Settings.SEND_AGENT_UPDATES = Client.Settings.SEND_AGENT_UPDATES;
newClient.Settings.SEND_PINGS = Client.Settings.SEND_PINGS;
newClient.Settings.STORE_LAND_PATCHES = Client.Settings.STORE_LAND_PATCHES;
newClient.Settings.USE_ASSET_CACHE = Client.Settings.USE_ASSET_CACHE;
newClient.Settings.MULTIPLE_SIMS = Client.Settings.MULTIPLE_SIMS;
newClient.Throttle.Asset = Client.Throttle.Asset;
newClient.Throttle.Land = Client.Throttle.Land;
newClient.Throttle.Task = Client.Throttle.Task;
newClient.Throttle.Texture = Client.Throttle.Texture;
newClient.Throttle.Wind = Client.Throttle.Wind;
newClient.Throttle.Total = Client.Throttle.Total;
}
else
{
newClient.Settings.LOGIN_SERVER = LoginUri;
newClient.Settings.ALWAYS_DECODE_OBJECTS = false;
newClient.Settings.AVATAR_TRACKING = false;
newClient.Settings.OBJECT_TRACKING = false;
newClient.Settings.SEND_AGENT_THROTTLE = true;
newClient.Settings.SEND_PINGS = true;
newClient.Settings.STORE_LAND_PATCHES = false;
newClient.Settings.USE_ASSET_CACHE = false;
newClient.Settings.MULTIPLE_SIMS = true;
newClient.Throttle.Asset = 100000;
newClient.Throttle.Land = 100000;
newClient.Throttle.Task = 100000;
newClient.Throttle.Texture = 100000;
newClient.Throttle.Wind = 100000;
newClient.Throttle.Total = 400000;
}
newClient.Network.LoginProgress += this.Network_LoginProgress;
newClient.Network.SimConnected += this.Network_SimConnected;
newClient.Network.Disconnected += this.Network_OnDisconnected;
newClient.Objects.ObjectUpdate += Objects_NewPrim;
Client = newClient;
} }
//We do our actions here. This is where one would //We do our actions here. This is where one would
@ -179,7 +252,7 @@ namespace pCampBot
/// <summary> /// <summary>
/// Tells LibSecondLife to logout and disconnect. Raises the disconnect events once it finishes. /// Tells LibSecondLife to logout and disconnect. Raises the disconnect events once it finishes.
/// </summary> /// </summary>
public void shutdown() public void Disconnect()
{ {
ConnectionState = ConnectionState.Disconnecting; ConnectionState = ConnectionState.Disconnecting;
@ -189,34 +262,27 @@ namespace pCampBot
Client.Network.Logout(); Client.Network.Logout();
} }
public void Connect()
{
Thread connectThread = new Thread(ConnectInternal);
connectThread.Name = Name;
connectThread.IsBackground = true;
connectThread.Start();
}
/// <summary> /// <summary>
/// This is the bot startup loop. /// This is the bot startup loop.
/// </summary> /// </summary>
public void startup() private void ConnectInternal()
{ {
Client.Settings.LOGIN_SERVER = LoginUri;
Client.Settings.ALWAYS_DECODE_OBJECTS = false;
Client.Settings.AVATAR_TRACKING = false;
Client.Settings.OBJECT_TRACKING = false;
Client.Settings.SEND_AGENT_THROTTLE = true;
Client.Settings.SEND_AGENT_UPDATES = false;
Client.Settings.SEND_PINGS = true;
Client.Settings.STORE_LAND_PATCHES = false;
Client.Settings.USE_ASSET_CACHE = false;
Client.Settings.MULTIPLE_SIMS = true;
Client.Throttle.Asset = 100000;
Client.Throttle.Land = 100000;
Client.Throttle.Task = 100000;
Client.Throttle.Texture = 100000;
Client.Throttle.Wind = 100000;
Client.Throttle.Total = 400000;
Client.Network.LoginProgress += this.Network_LoginProgress;
Client.Network.SimConnected += this.Network_SimConnected;
Client.Network.Disconnected += this.Network_OnDisconnected;
Client.Objects.ObjectUpdate += Objects_NewPrim;
ConnectionState = ConnectionState.Connecting; ConnectionState = ConnectionState.Connecting;
// Current create a new client on each connect. libomv doesn't seem to process new sim
// information (e.g. EstablishAgentCommunication events) if connecting after a disceonnect with the same
// client
CreateLibOmvClient();
if (Client.Network.Login(FirstName, LastName, Password, "pCampBot", StartLocation, "Your name")) if (Client.Network.Login(FirstName, LastName, Password, "pCampBot", StartLocation, "Your name"))
{ {
ConnectionState = ConnectionState.Connected; ConnectionState = ConnectionState.Connected;
@ -261,6 +327,30 @@ namespace pCampBot
} }
} }
/// <summary>
/// Sit this bot on the ground.
/// </summary>
public void SitOnGround()
{
if (ConnectionState == ConnectionState.Connected)
Client.Self.SitOnGround();
}
/// <summary>
/// Stand this bot
/// </summary>
public void Stand()
{
if (ConnectionState == ConnectionState.Connected)
{
// Unlike sit on ground, here libomv checks whether we have SEND_AGENT_UPDATES enabled.
bool prevUpdatesSetting = Client.Settings.SEND_AGENT_UPDATES;
Client.Settings.SEND_AGENT_UPDATES = true;
Client.Self.Stand();
Client.Settings.SEND_AGENT_UPDATES = prevUpdatesSetting;
}
}
public void SaveDefaultAppearance() public void SaveDefaultAppearance()
{ {
saveDir = "MyAppearance/" + FirstName + "_" + LastName; saveDir = "MyAppearance/" + FirstName + "_" + LastName;
@ -461,6 +551,8 @@ namespace pCampBot
// || args.Reason == NetworkManager.DisconnectType.NetworkTimeout) // || args.Reason == NetworkManager.DisconnectType.NetworkTimeout)
// && OnDisconnected != null) // && OnDisconnected != null)
if ( if (
(args.Reason == NetworkManager.DisconnectType.ClientInitiated (args.Reason == NetworkManager.DisconnectType.ClientInitiated
|| args.Reason == NetworkManager.DisconnectType.ServerInitiated || args.Reason == NetworkManager.DisconnectType.ServerInitiated

View File

@ -52,9 +52,14 @@ namespace pCampBot
public const int DefaultLoginDelay = 5000; public const int DefaultLoginDelay = 5000;
/// <summary> /// <summary>
/// True if pCampbot is in the process of shutting down. /// Is pCampbot in the process of connecting bots?
/// </summary> /// </summary>
public bool ShuttingDown { get; private set; } public bool ConnectingBots { get; private set; }
/// <summary>
/// Is pCampbot in the process of disconnecting bots?
/// </summary>
public bool DisconnectingBots { get; private set; }
/// <summary> /// <summary>
/// Delay between logins of multiple bots. /// Delay between logins of multiple bots.
@ -80,7 +85,7 @@ namespace pCampBot
/// <summary> /// <summary>
/// Created bots, whether active or inactive. /// Created bots, whether active or inactive.
/// </summary> /// </summary>
protected List<Bot> m_lBot; protected List<Bot> m_bots;
/// <summary> /// <summary>
/// Random number generator. /// Random number generator.
@ -97,6 +102,46 @@ namespace pCampBot
/// </summary> /// </summary>
public Dictionary<ulong, GridRegion> RegionsKnown { get; private set; } public Dictionary<ulong, GridRegion> RegionsKnown { get; private set; }
/// <summary>
/// First name for bots
/// </summary>
private string m_firstName;
/// <summary>
/// Last name stem for bots
/// </summary>
private string m_lastNameStem;
/// <summary>
/// Password for bots
/// </summary>
private string m_password;
/// <summary>
/// Login URI for bots.
/// </summary>
private string m_loginUri;
/// <summary>
/// Start location for bots.
/// </summary>
private string m_startUri;
/// <summary>
/// Postfix bot number at which bot sequence starts.
/// </summary>
private int m_fromBotNumber;
/// <summary>
/// Wear setting for bots.
/// </summary>
private string m_wearSetting;
/// <summary>
/// Behaviour switches for bots.
/// </summary>
private HashSet<string> m_behaviourSwitches = new HashSet<string>();
/// <summary> /// <summary>
/// Constructor Creates MainConsole.Instance to take commands and provide the place to write data /// Constructor Creates MainConsole.Instance to take commands and provide the place to write data
/// </summary> /// </summary>
@ -130,30 +175,47 @@ namespace pCampBot
} }
} }
m_console.Commands.AddCommand("bot", false, "shutdown", m_console.Commands.AddCommand(
"shutdown", "bot", false, "shutdown", "shutdown", "Shutdown bots and exit", HandleShutdown);
"Shutdown bots and exit", HandleShutdown);
m_console.Commands.AddCommand("bot", false, "quit", m_console.Commands.AddCommand(
"quit", "bot", false, "quit", "quit", "Shutdown bots and exit", HandleShutdown);
"Shutdown bots and exit",
HandleShutdown);
m_console.Commands.AddCommand("bot", false, "show regions", m_console.Commands.AddCommand(
"show regions", "bot", false, "connect", "connect [<n>]", "Connect bots",
"Show regions known to bots", "If an <n> is given, then the first <n> disconnected bots by postfix number are connected.\n"
HandleShowRegions); + "If no <n> is given, then all currently disconnected bots are connected.",
HandleConnect);
m_console.Commands.AddCommand("bot", false, "show bots", m_console.Commands.AddCommand(
"show bots", "bot", false, "disconnect", "disconnect [<n>]", "Disconnect bots",
"Shows the status of all bots", "Disconnecting bots will interupt any bot connection process, including connection on startup.\n"
HandleShowStatus); + "If an <n> is given, then the last <n> connected bots by postfix number are disconnected.\n"
+ "If no <n> is given, then all currently connected bots are disconnected.",
HandleDisconnect);
// m_console.Commands.AddCommand("bot", false, "add bots", m_console.Commands.AddCommand(
// "add bots <number>", "bot", false, "sit", "sit", "Sit all bots on the ground.",
// "Add more bots", HandleAddBots); HandleSit);
m_lBot = new List<Bot>(); m_console.Commands.AddCommand(
"bot", false, "stand", "stand", "Stand all bots.",
HandleStand);
m_console.Commands.AddCommand(
"bot", false, "set bots", "set bots <key> <value>", "Set a setting for all bots.", HandleSetBots);
m_console.Commands.AddCommand(
"bot", false, "show regions", "show regions", "Show regions known to bots", HandleShowRegions);
m_console.Commands.AddCommand(
"bot", false, "show bots", "show bots", "Shows the status of all bots", HandleShowBotsStatus);
m_console.Commands.AddCommand(
"bot", false, "show bot", "show bot <n>",
"Shows the detailed status and settings of a particular bot.", HandleShowBotStatus);
m_bots = new List<Bot>();
} }
/// <summary> /// <summary>
@ -161,62 +223,102 @@ namespace pCampBot
/// </summary> /// </summary>
/// <param name="botcount">How many bots to start up</param> /// <param name="botcount">How many bots to start up</param>
/// <param name="cs">The configuration for the bots to use</param> /// <param name="cs">The configuration for the bots to use</param>
public void dobotStartup(int botcount, IConfig startupConfig) public void CreateBots(int botcount, IConfig startupConfig)
{ {
string firstName = startupConfig.GetString("firstname"); m_firstName = startupConfig.GetString("firstname");
string lastNameStem = startupConfig.GetString("lastname"); m_lastNameStem = startupConfig.GetString("lastname");
string password = startupConfig.GetString("password"); m_password = startupConfig.GetString("password");
string loginUri = startupConfig.GetString("loginuri"); m_loginUri = startupConfig.GetString("loginuri");
string startLocation = startupConfig.GetString("start", "last"); m_fromBotNumber = startupConfig.GetInt("from", 0);
int fromBotNumber = startupConfig.GetInt("from", 0); m_wearSetting = startupConfig.GetString("wear", "no");
string wearSetting = startupConfig.GetString("wear", "no");
string startUri = ParseInputStartLocationToUri(startLocation); m_startUri = ParseInputStartLocationToUri(startupConfig.GetString("start", "last"));
HashSet<string> behaviourSwitches = new HashSet<string>();
Array.ForEach<string>( Array.ForEach<string>(
startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => behaviourSwitches.Add(b)); startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_behaviourSwitches.Add(b));
for (int i = 0; i < botcount; i++)
{
lock (m_bots)
{
string lastName = string.Format("{0}_{1}", m_lastNameStem, i + m_fromBotNumber);
// We must give each bot its own list of instantiated behaviours since they store state.
List<IBehaviour> behaviours = new List<IBehaviour>();
// Hard-coded for now
if (m_behaviourSwitches.Contains("c"))
behaviours.Add(new CrossBehaviour());
if (m_behaviourSwitches.Contains("g"))
behaviours.Add(new GrabbingBehaviour());
if (m_behaviourSwitches.Contains("n"))
behaviours.Add(new NoneBehaviour());
if (m_behaviourSwitches.Contains("p"))
behaviours.Add(new PhysicsBehaviour());
if (m_behaviourSwitches.Contains("t"))
behaviours.Add(new TeleportBehaviour());
CreateBot(this, behaviours, m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting);
}
}
}
public void ConnectBots(int botcount)
{
ConnectingBots = true;
Thread connectBotThread = new Thread(o => ConnectBotsInternal(botcount));
connectBotThread.Name = "Bots connection thread";
connectBotThread.Start();
}
private void ConnectBotsInternal(int botCount)
{
MainConsole.Instance.OutputFormat( MainConsole.Instance.OutputFormat(
"[BOT MANAGER]: Starting {0} bots connecting to {1}, location {2}, named {3} {4}_<n>", "[BOT MANAGER]: Starting {0} bots connecting to {1}, location {2}, named {3} {4}_<n>",
botcount, botCount,
loginUri, m_loginUri,
startUri, m_startUri,
firstName, m_firstName,
lastNameStem); m_lastNameStem);
MainConsole.Instance.OutputFormat("[BOT MANAGER]: Delay between logins is {0}ms", LoginDelay); MainConsole.Instance.OutputFormat("[BOT MANAGER]: Delay between logins is {0}ms", LoginDelay);
MainConsole.Instance.OutputFormat("[BOT MANAGER]: BotsSendAgentUpdates is {0}", InitBotSendAgentUpdates); MainConsole.Instance.OutputFormat("[BOT MANAGER]: BotsSendAgentUpdates is {0}", InitBotSendAgentUpdates);
MainConsole.Instance.OutputFormat("[BOT MANAGER]: InitBotRequestObjectTextures is {0}", InitBotRequestObjectTextures); MainConsole.Instance.OutputFormat("[BOT MANAGER]: InitBotRequestObjectTextures is {0}", InitBotRequestObjectTextures);
for (int i = 0; i < botcount; i++) int connectedBots = 0;
for (int i = 0; i < m_bots.Count; i++)
{ {
if (ShuttingDown) lock (m_bots)
break; {
if (DisconnectingBots)
{
MainConsole.Instance.Output(
"[BOT MANAGER]: Aborting bot connection due to user-initiated disconnection");
break;
}
string lastName = string.Format("{0}_{1}", lastNameStem, i + fromBotNumber); if (m_bots[i].ConnectionState == ConnectionState.Disconnected)
{
m_bots[i].Connect();
connectedBots++;
// We must give each bot its own list of instantiated behaviours since they store state. if (connectedBots >= botCount)
List<IBehaviour> behaviours = new List<IBehaviour>(); break;
// Hard-coded for now // Stagger logins
if (behaviourSwitches.Contains("c")) Thread.Sleep(LoginDelay);
behaviours.Add(new CrossBehaviour()); }
}
if (behaviourSwitches.Contains("g"))
behaviours.Add(new GrabbingBehaviour());
if (behaviourSwitches.Contains("n"))
behaviours.Add(new NoneBehaviour());
if (behaviourSwitches.Contains("p"))
behaviours.Add(new PhysicsBehaviour());
if (behaviourSwitches.Contains("t"))
behaviours.Add(new TeleportBehaviour());
StartBot(this, behaviours, firstName, lastName, password, loginUri, startUri, wearSetting);
} }
ConnectingBots = false;
} }
/// <summary> /// <summary>
@ -258,28 +360,8 @@ namespace pCampBot
return string.Format("uri:{0}&{1}&{2}&{3}", regionName, startPos.X, startPos.Y, startPos.Z); return string.Format("uri:{0}&{1}&{2}&{3}", regionName, startPos.X, startPos.Y, startPos.Z);
} }
// /// <summary>
// /// Add additional bots (and threads) to our bot pool
// /// </summary>
// /// <param name="botcount">How Many of them to add</param>
// public void addbots(int botcount)
// {
// int len = m_td.Length;
// Thread[] m_td2 = new Thread[len + botcount];
// for (int i = 0; i < len; i++)
// {
// m_td2[i] = m_td[i];
// }
// m_td = m_td2;
// int newlen = len + botcount;
// for (int i = len; i < newlen; i++)
// {
// startupBot(Config);
// }
// }
/// <summary> /// <summary>
/// This starts up the bot and stores the thread for the bot in the thread array /// This creates a bot but does not start it.
/// </summary> /// </summary>
/// <param name="bm"></param> /// <param name="bm"></param>
/// <param name="behaviours">Behaviours for this bot to perform.</param> /// <param name="behaviours">Behaviours for this bot to perform.</param>
@ -289,12 +371,12 @@ namespace pCampBot
/// <param name="loginUri">Login URI</param> /// <param name="loginUri">Login URI</param>
/// <param name="startLocation">Location to start the bot. Can be "last", "home" or a specific sim name.</param> /// <param name="startLocation">Location to start the bot. Can be "last", "home" or a specific sim name.</param>
/// <param name="wearSetting"></param> /// <param name="wearSetting"></param>
public void StartBot( public void CreateBot(
BotManager bm, List<IBehaviour> behaviours, BotManager bm, List<IBehaviour> behaviours,
string firstName, string lastName, string password, string loginUri, string startLocation, string wearSetting) string firstName, string lastName, string password, string loginUri, string startLocation, string wearSetting)
{ {
MainConsole.Instance.OutputFormat( MainConsole.Instance.OutputFormat(
"[BOT MANAGER]: Starting bot {0} {1}, behaviours are {2}", "[BOT MANAGER]: Creating bot {0} {1}, behaviours are {2}",
firstName, lastName, string.Join(",", behaviours.ConvertAll<string>(b => b.Name).ToArray())); firstName, lastName, string.Join(",", behaviours.ConvertAll<string>(b => b.Name).ToArray()));
Bot pb = new Bot(bm, behaviours, firstName, lastName, password, startLocation, loginUri); Bot pb = new Bot(bm, behaviours, firstName, lastName, password, startLocation, loginUri);
@ -305,17 +387,7 @@ namespace pCampBot
pb.OnConnected += handlebotEvent; pb.OnConnected += handlebotEvent;
pb.OnDisconnected += handlebotEvent; pb.OnDisconnected += handlebotEvent;
lock (m_lBot) m_bots.Add(pb);
m_lBot.Add(pb);
Thread pbThread = new Thread(pb.startup);
pbThread.Name = pb.Name;
pbThread.IsBackground = true;
pbThread.Start();
// Stagger logins
Thread.Sleep(LoginDelay);
} }
/// <summary> /// <summary>
@ -328,35 +400,15 @@ namespace pCampBot
switch (eventt) switch (eventt)
{ {
case EventType.CONNECTED: case EventType.CONNECTED:
{
m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Connected"); m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Connected");
break; break;
}
case EventType.DISCONNECTED: case EventType.DISCONNECTED:
m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Disconnected");
lock (m_lBot)
{
if (m_lBot.TrueForAll(b => b.ConnectionState == ConnectionState.Disconnected))
Environment.Exit(0);
break;
}
}
}
/// <summary>
/// Shut down all bots
/// </summary>
/// <remarks>
/// We launch each shutdown on its own thread so that a slow shutting down bot doesn't hold up all the others.
/// </remarks>
public void doBotShutdown()
{
lock (m_lBot)
{
foreach (Bot bot in m_lBot)
{ {
Bot thisBot = bot; m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Disconnected");
Util.FireAndForget(o => thisBot.shutdown()); break;
} }
} }
} }
@ -370,12 +422,136 @@ namespace pCampBot
return new LocalConsole("pCampbot"); return new LocalConsole("pCampbot");
} }
private void HandleConnect(string module, string[] cmd)
{
if (ConnectingBots)
{
MainConsole.Instance.Output("Still connecting bots. Please wait for previous process to complete.");
return;
}
lock (m_bots)
{
int botsToConnect;
int disconnectedBots = m_bots.Count(b => b.ConnectionState == ConnectionState.Disconnected);
if (cmd.Length == 1)
{
botsToConnect = disconnectedBots;
}
else
{
if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[1], out botsToConnect))
return;
botsToConnect = Math.Min(botsToConnect, disconnectedBots);
}
MainConsole.Instance.OutputFormat("Connecting {0} bots", botsToConnect);
ConnectBots(botsToConnect);
}
}
private void HandleDisconnect(string module, string[] cmd)
{
lock (m_bots)
{
int botsToDisconnect;
int connectedBots = m_bots.Count(b => b.ConnectionState == ConnectionState.Connected);
if (cmd.Length == 1)
{
botsToDisconnect = connectedBots;
}
else
{
if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[1], out botsToDisconnect))
return;
botsToDisconnect = Math.Min(botsToDisconnect, connectedBots);
}
DisconnectingBots = true;
MainConsole.Instance.OutputFormat("Disconnecting {0} bots", botsToDisconnect);
int disconnectedBots = 0;
for (int i = m_bots.Count - 1; i >= 0; i--)
{
if (disconnectedBots >= botsToDisconnect)
break;
Bot thisBot = m_bots[i];
if (thisBot.ConnectionState == ConnectionState.Connected)
{
Util.FireAndForget(o => thisBot.Disconnect());
disconnectedBots++;
}
}
DisconnectingBots = false;
}
}
private void HandleSit(string module, string[] cmd)
{
lock (m_bots)
{
m_bots.ForEach(b => b.SitOnGround());
}
}
private void HandleStand(string module, string[] cmd)
{
lock (m_bots)
{
m_bots.ForEach(b => b.Stand());
}
}
private void HandleShutdown(string module, string[] cmd) private void HandleShutdown(string module, string[] cmd)
{ {
lock (m_bots)
{
int connectedBots = m_bots.Count(b => b.ConnectionState == ConnectionState.Connected);
if (connectedBots > 0)
{
MainConsole.Instance.OutputFormat("Please disconnect {0} connected bots first", connectedBots);
return;
}
}
MainConsole.Instance.Output("Shutting down"); MainConsole.Instance.Output("Shutting down");
ShuttingDown = true; Environment.Exit(0);
doBotShutdown(); }
private void HandleSetBots(string module, string[] cmd)
{
string key = cmd[2];
string rawValue = cmd[3];
if (key == "SEND_AGENT_UPDATES")
{
bool newSendAgentUpdatesSetting;
if (!ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, rawValue, out newSendAgentUpdatesSetting))
return;
MainConsole.Instance.OutputFormat(
"Setting SEND_AGENT_UPDATES to {0} for all bots", newSendAgentUpdatesSetting);
lock (m_bots)
m_bots.ForEach(b => b.Client.Settings.SEND_AGENT_UPDATES = newSendAgentUpdatesSetting);
}
else
{
MainConsole.Instance.Output("Error: Only setting currently available is SEND_AGENT_UPDATES");
}
} }
private void HandleShowRegions(string module, string[] cmd) private void HandleShowRegions(string module, string[] cmd)
@ -393,56 +569,87 @@ namespace pCampBot
} }
} }
private void HandleShowStatus(string module, string[] cmd) private void HandleShowBotsStatus(string module, string[] cmd)
{ {
string outputFormat = "{0,-30} {1, -30} {2,-14}"; ConsoleDisplayTable cdt = new ConsoleDisplayTable();
MainConsole.Instance.OutputFormat(outputFormat, "Name", "Region", "Status"); cdt.AddColumn("Name", 30);
cdt.AddColumn("Region", 30);
cdt.AddColumn("Status", 14);
cdt.AddColumn("Connections", 11);
Dictionary<ConnectionState, int> totals = new Dictionary<ConnectionState, int>(); Dictionary<ConnectionState, int> totals = new Dictionary<ConnectionState, int>();
foreach (object o in Enum.GetValues(typeof(ConnectionState))) foreach (object o in Enum.GetValues(typeof(ConnectionState)))
totals[(ConnectionState)o] = 0; totals[(ConnectionState)o] = 0;
lock (m_lBot) lock (m_bots)
{ {
foreach (Bot pb in m_lBot) foreach (Bot pb in m_bots)
{ {
Simulator currentSim = pb.Client.Network.CurrentSim; Simulator currentSim = pb.Client.Network.CurrentSim;
totals[pb.ConnectionState]++; totals[pb.ConnectionState]++;
MainConsole.Instance.OutputFormat( cdt.AddRow(
outputFormat, pb.Name, currentSim != null ? currentSim.Name : "(none)", pb.ConnectionState, pb.SimulatorsCount);
pb.Name, currentSim != null ? currentSim.Name : "(none)", pb.ConnectionState);
} }
} }
MainConsole.Instance.Output(cdt.ToString());
ConsoleDisplayList cdl = new ConsoleDisplayList(); ConsoleDisplayList cdl = new ConsoleDisplayList();
foreach (KeyValuePair<ConnectionState, int> kvp in totals) foreach (KeyValuePair<ConnectionState, int> kvp in totals)
cdl.AddRow(kvp.Key, kvp.Value); cdl.AddRow(kvp.Key, kvp.Value);
MainConsole.Instance.Output(cdl.ToString());
MainConsole.Instance.OutputFormat("\n{0}", cdl.ToString());
} }
/* private void HandleShowBotStatus(string module, string[] cmd)
private void HandleQuit(string module, string[] cmd)
{ {
m_console.Warn("DANGER", "This should only be used to quit the program if you've already used the shutdown command and the program hasn't quit"); if (cmd.Length != 3)
Environment.Exit(0); {
MainConsole.Instance.Output("Usage: show bot <n>");
return;
}
int botNumber;
if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, cmd[2], out botNumber))
return;
string name = string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber);
Bot bot;
lock (m_bots)
bot = m_bots.Find(b => b.Name == name);
if (bot == null)
{
MainConsole.Instance.Output("No bot found with name {0}", name);
return;
}
ConsoleDisplayList cdl = new ConsoleDisplayList();
cdl.AddRow("Name", bot.Name);
cdl.AddRow("Status", bot.ConnectionState);
Simulator currentSim = bot.Client.Network.CurrentSim;
cdl.AddRow("Region", currentSim != null ? currentSim.Name : "(none)");
List<Simulator> connectedSimulators = bot.Simulators;
List<string> simulatorNames = connectedSimulators.ConvertAll<string>(cs => cs.Name);
cdl.AddRow("Connections", string.Join(", ", simulatorNames.ToArray()));
MainConsole.Instance.Output(cdl.ToString());
MainConsole.Instance.Output("Settings");
ConsoleDisplayList statusCdl = new ConsoleDisplayList();
GridClient botClient = bot.Client;
statusCdl.AddRow("SEND_AGENT_UPDATES", botClient.Settings.SEND_AGENT_UPDATES);
MainConsole.Instance.Output(statusCdl.ToString());
} }
*/
//
// private void HandleAddBots(string module, string[] cmd)
// {
// int newbots = 0;
//
// if (cmd.Length > 2)
// {
// Int32.TryParse(cmd[2], out newbots);
// }
// if (newbots > 0)
// addbots(newbots);
// }
internal void Grid_GridRegion(object o, GridRegionEventArgs args) internal void Grid_GridRegion(object o, GridRegionEventArgs args)
{ {

View File

@ -51,7 +51,7 @@ namespace pCampBot
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public const string ConfigFileName = "pCampbot.ini"; public const string ConfigFileName = "pCampBot.ini";
[STAThread] [STAThread]
public static void Main(string[] args) public static void Main(string[] args)
@ -82,6 +82,13 @@ namespace pCampBot
IConfigSource configSource = new IniConfigSource(iniFilePath); IConfigSource configSource = new IniConfigSource(iniFilePath);
IConfig botManagerConfig = configSource.Configs["BotManager"];
if (botManagerConfig != null)
{
bm.LoginDelay = botManagerConfig.GetInt("LoginDelay", bm.LoginDelay);
}
IConfig botConfig = configSource.Configs["Bot"]; IConfig botConfig = configSource.Configs["Bot"];
if (botConfig != null) if (botConfig != null)
@ -94,11 +101,12 @@ namespace pCampBot
} }
int botcount = commandLineConfig.GetInt("botcount", 1); int botcount = commandLineConfig.GetInt("botcount", 1);
bool startConnected = commandLineConfig.Get("connect") != null;
//startup specified number of bots. 1 is the default bm.CreateBots(botcount, commandLineConfig);
Thread startBotThread = new Thread(o => bm.dobotStartup(botcount, commandLineConfig));
startBotThread.Name = "Initial start bots thread"; if (startConnected)
startBotThread.Start(); bm.ConnectBots(botcount);
while (true) while (true)
{ {
@ -119,6 +127,7 @@ namespace pCampBot
//Set up our nifty config.. thanks to nini //Set up our nifty config.. thanks to nini
ArgvConfigSource cs = new ArgvConfigSource(args); ArgvConfigSource cs = new ArgvConfigSource(args);
cs.AddSwitch("Startup", "connect", "c");
cs.AddSwitch("Startup", "botcount", "n"); cs.AddSwitch("Startup", "botcount", "n");
cs.AddSwitch("Startup", "from", "f"); cs.AddSwitch("Startup", "from", "f");
cs.AddSwitch("Startup", "loginuri", "l"); cs.AddSwitch("Startup", "loginuri", "l");
@ -145,20 +154,21 @@ namespace pCampBot
"usage: pCampBot <-loginuri loginuri> [OPTIONS]\n" "usage: pCampBot <-loginuri loginuri> [OPTIONS]\n"
+ "Spawns a set of bots to test an OpenSim region\n\n" + "Spawns a set of bots to test an OpenSim region\n\n"
+ " -l, -loginuri loginuri for grid/standalone (required)\n" + " -l, -loginuri loginuri for grid/standalone (required)\n"
+ " -s, -start optional start location for bots. Can be \"last\", \"home\" or a specific location with or without co-ords (e.g. \"region1\" or \"region2/50/30/90\"\n" + " -s, -start start location for bots (optional). Can be \"last\", \"home\" or a specific location with or without co-ords (e.g. \"region1\" or \"region2/50/30/90\"\n"
+ " -firstname first name for the bots\n" + " -firstname first name for the bots (required)\n"
+ " -lastname lastname for the bots. Each lastname will have _<bot-number> appended, e.g. Ima Bot_0\n" + " -lastname lastname for the bots (required). Each lastname will have _<bot-number> appended, e.g. Ima Bot_0\n"
+ " -password password for the bots\n" + " -password password for the bots (required)\n"
+ " -n, -botcount optional number of bots to start (default: 1)\n" + " -n, -botcount number of bots to start (default: 1) (optional)\n"
+ " -f, -from optional starting number for login bot names, e.g. 25 will login Ima Bot_25, Ima Bot_26, etc. (default: 0)" + " -f, -from starting number for login bot names, e.g. 25 will login Ima Bot_25, Ima Bot_26, etc. (default: 0) (optional)\n"
+ " -b, behaviours behaviours for bots. Comma separated, e.g. p,g. Default is p\n" + " -c, -connect connect all bots at startup (optional)\n"
+ " -b, behaviours behaviours for bots. Comma separated, e.g. p,g. Default is p (required)\n"
+ " current options are:\n" + " current options are:\n"
+ " p (physics - bots constantly move and jump around)\n" + " p (physics - bots constantly move and jump around)\n"
+ " g (grab - bots randomly click prims whether set clickable or not)\n" + " g (grab - bots randomly click prims whether set clickable or not)\n"
+ " n (none - bots do nothing)\n" + " n (none - bots do nothing)\n"
+ " t (teleport - bots regularly teleport between regions on the grid)\n" + " t (teleport - bots regularly teleport between regions on the grid)\n"
// " c (cross)" + // " c (cross)\n" +
+ " -wear optional folder from which to load appearance data, \"no\" if there is no such folder (default: no)\n" + " -wear folder from which to load appearance data, \"no\" if there is no such folder (default: no) (optional)\n"
+ " -h, -help show this message.\n"); + " -h, -help show this message.\n");
} }
} }

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,10 @@
; This is the example config file for pCampbot ; This is the example config file for pCampbot
; To use it, copy this file to pCampbot.ini and change settings if required ; To use it, copy this file to pCampbot.ini and change settings if required
[BotManager]
; Number of milliseconds to wait between bot logins
LoginDelay = 5000
[Bot] [Bot]
; Control whether bots should regularly send agent updates ; Control whether bots should regularly send agent updates
; Not doing this will reduce CPU requirements for pCampbot but greatly ; Not doing this will reduce CPU requirements for pCampbot but greatly