Updates to the athome system and avstorage

This commit is contained in:
Madpeterz 2021-01-03 09:48:13 +00:00
parent 39710f9e82
commit 93499e4be3
3 changed files with 303 additions and 393 deletions

View file

@ -20,7 +20,8 @@ namespace BSB.bottypes
protected Dictionary<string, KeyValuePair<long, int>> PendingAvatarFinds_vianame = new Dictionary<string, KeyValuePair<long, int>>();
protected Dictionary<UUID, KeyValuePair<long, int>> PendingAvatarFinds_viauuid = new Dictionary<UUID, KeyValuePair<long, int>>();
protected long max_db_storage_age = 240; // how long should we keep an avatar in memory before clearing (in secs) [now - last accessed]
protected long max_db_storage_age = 2240; // how long should we keep an avatar in memory before clearing (in secs) [now - last accessed]
protected int max_retry_attempts = 2;
protected bool show_av_storage_info_in_status = true;
protected string AVstorageBot_laststatus = "";
@ -28,6 +29,7 @@ namespace BSB.bottypes
{
cleanupAvatarStorage();
ReTriggerAvLookups();
UpdateStorageWithAroundMe();
string reply = "";
if (show_av_storage_info_in_status == true)
{
@ -61,6 +63,18 @@ namespace BSB.bottypes
return base.GetStatus();
}
protected void UpdateStorageWithAroundMe()
{
if(Client.Network.CurrentSim != null)
{
Dictionary<uint,Avatar> avcopy = Client.Network.CurrentSim.ObjectsAvatars.Copy();
foreach (Avatar av in avcopy.Values)
{
AddAvatarToDB(av.ID, av.Name);
}
}
}
protected void ReTriggerUUIDtoName()
{
long now = helpers.UnixTimeNow();
@ -68,7 +82,18 @@ namespace BSB.bottypes
List<UUID> giveup_key2name = new List<UUID>();
foreach (KeyValuePair<UUID, KeyValuePair<long, int>> pair in PendingAvatarFinds_viauuid)
{
giveup_key2name.Add(pair.Key);
long dif = now - pair.Value.Key;
if (dif > 30)
{
if (pair.Value.Value < max_retry_attempts)
{
retrigger_key2name.Add(pair.Key);
}
else
{
giveup_key2name.Add(pair.Key);
}
}
}
if(retrigger_key2name.Count > 0)
{
@ -91,13 +116,25 @@ namespace BSB.bottypes
List<string> giveup_name2key = new List<string>();
foreach (KeyValuePair<string, KeyValuePair<long, int>> pair in PendingAvatarFinds_vianame)
{
giveup_name2key.Add(pair.Key);
long dif = now - pair.Value.Key;
if (dif > 30)
{
if (pair.Value.Value < max_retry_attempts)
{
retrigger_name2key.Add(pair.Key);
}
else
{
giveup_name2key.Add(pair.Key);
}
}
}
foreach (string avname in retrigger_name2key)
{
{
int retry_counter = PendingAvatarFinds_vianame[avname].Value + 1;
PendingAvatarFinds_vianame[avname] = new KeyValuePair<long, int>(now, retry_counter);
Client.Directory.StartPeopleSearch(avname, 0);
PendingAvatarFinds_vianame[avname] = new KeyValuePair<long, int>(now, PendingAvatarFinds_vianame[avname].Value + 1);
}
foreach (string avname in giveup_name2key)
@ -153,16 +190,16 @@ namespace BSB.bottypes
protected override void AfterBotLoginHandler()
{
base.AfterBotLoginHandler();
if (reconnect == false)
{
Client.Avatars.UUIDNameReply += Key2NameEvent;
Client.Directory.DirPeopleReply += Name2KeyEvent;
if(helpers.notempty(myconfig.Security_MasterUsername) == true)
if (helpers.notempty(myconfig.Security_MasterUsername) == true)
{
FindAvatarName2Key(myconfig.Security_MasterUsername);
}
}
base.AfterBotLoginHandler();
}
protected void Key2NameEvent(object sender,UUIDNameReplyEventArgs e)
@ -201,6 +238,10 @@ namespace BSB.bottypes
}
}
}
else
{
AvatarStorageLastUsed[av_name] = helpers.UnixTimeNow();
}
if (helpers.notempty(myconfig.Security_MasterUsername) == true)
{
if(myconfig.Security_MasterUsername == av_name)
@ -215,126 +256,137 @@ namespace BSB.bottypes
}
}
}
protected string httpLookupKey(string avatar_name)
{
if (myconfig.Name2Key_Enable == true)
{
var client = new RestClient(myconfig.Name2Key_Url);
var request = new RestRequest("name2key/" + avatar_name + "/" + myconfig.Name2Key_Key + "", Method.GET);
client.Timeout = 3000; // ? does this even do anything
request.Timeout = 3000;
IRestResponse endpoint_checks = client.Get(request);
if (endpoint_checks.StatusCode == System.Net.HttpStatusCode.OK)
{
try
{
namekeyservicereply server_reply = JsonConvert.DeserializeObject<namekeyservicereply>(endpoint_checks.Content);
if (server_reply.status == true)
{
if (server_reply.found == true)
{
AddAvatarToDB((UUID)server_reply.uuid, server_reply.name);
return server_reply.uuid;
}
}
}
catch
{
}
}
}
return "";
}
protected string FindAvatarUUIDInStorage(string avatar_name)
{
if (AvatarStorageLastUsed.ContainsKey(avatar_name) == true)
{
AvatarStorageLastUsed[avatar_name] = helpers.UnixTimeNow();
return AvatarName2Key[avatar_name].ToString();
}
return "";
}
public string FindAvatarName2Key(string avatar_name)
{
return FindAvatarName2Key(avatar_name, false);
}
public string FindAvatarName2Key(string avatar_name,bool skip_http)
{
if (myconfig.Name2Key_Enable == false)
{
skip_http = true;
}
List<string> bits = avatar_name.Split(' ').ToList();
if(bits.Count() == 1)
{
bits.Add("Resident");
}
avatar_name = bits[0].FirstCharToUpper() + " " + bits[1].FirstCharToUpper();
long now = helpers.UnixTimeNow();
if (AvatarStorageLastUsed.ContainsKey(avatar_name) == true)
avatar_name = bits[0].FirstCharToUpper() + " " + bits[1].FirstCharToUpper();
string uuid = FindAvatarUUIDInStorage(avatar_name);
if (uuid != "")
{
AvatarStorageLastUsed[avatar_name] = now;
return AvatarName2Key[avatar_name].ToString();
return uuid;
}
else
uuid = httpLookupKey(avatar_name);
if (uuid != "")
{
if(PendingAvatarFinds_vianame.ContainsKey(avatar_name) == false)
{
if (skip_http == false)
{
var client = new RestClient(myconfig.Name2Key_Url);
var request = new RestRequest("name2key/" + avatar_name + "/" + myconfig.Name2Key_Key + "", Method.GET);
client.Timeout = 3000; // ? does this even do anything
request.Timeout = 3000;
IRestResponse endpoint_checks = client.Get(request);
if (endpoint_checks.StatusCode == System.Net.HttpStatusCode.OK)
{
try
{
namekeyservicereply server_reply = JsonConvert.DeserializeObject<namekeyservicereply>(endpoint_checks.Content);
if (server_reply.status == true)
{
if (server_reply.found == true)
{
AddAvatarToDB((UUID)server_reply.uuid, server_reply.name);
return server_reply.uuid;
}
}
}
catch
{
}
}
return FindAvatarName2Key(avatar_name, true);
}
else
{
PendingAvatarFinds_vianame.Add(avatar_name, new KeyValuePair<long, int>(now, 0));
Client.Directory.StartPeopleSearch(avatar_name, 0);
}
}
return uuid;
}
if (PendingAvatarFinds_vianame.ContainsKey(avatar_name) == false)
{
PendingAvatarFinds_vianame.Add(avatar_name, new KeyValuePair<long, int>(helpers.UnixTimeNow(), 0));
Client.Directory.StartPeopleSearch(avatar_name, 0);
}
return "lookup";
}
public string FindAvatarKey2Name(UUID avatar_uuid)
{
return FindAvatarKey2Name(avatar_uuid, false);
}
public string FindAvatarKey2Name(UUID avatar_uuid, bool skip_http)
{
if (myconfig.Name2Key_Enable == false)
{
skip_http = true;
}
long now = helpers.UnixTimeNow();
protected string FindAvatarNameInStorage(UUID avatar_uuid)
{
if (AvatarKey2Name.ContainsKey(avatar_uuid) == true)
{
AvatarStorageLastUsed[AvatarKey2Name[avatar_uuid]] = now;
AvatarStorageLastUsed[AvatarKey2Name[avatar_uuid]] = helpers.UnixTimeNow();
return AvatarKey2Name[avatar_uuid];
}
else
{
if (skip_http == false)
{
var client = new RestClient(myconfig.Name2Key_Url);
var request = new RestRequest("key2name/" + avatar_uuid.ToString() + "/" + myconfig.Name2Key_Key + "", Method.GET);
client.Timeout = 3000; // ? does this even do anything
request.Timeout = 3000;
IRestResponse endpoint_checks = client.Get(request);
if (endpoint_checks.StatusCode == System.Net.HttpStatusCode.OK)
{
try
{
namekeyservicereply server_reply = JsonConvert.DeserializeObject<namekeyservicereply>(endpoint_checks.Content);
if (server_reply.status == true)
{
if(server_reply.found == true)
{
AddAvatarToDB((UUID)server_reply.uuid, server_reply.name);
return server_reply.name;
}
}
}
catch
{
}
return "";
}
}
}
return FindAvatarKey2Name(avatar_uuid, true);
}
else
{
if (PendingAvatarFinds_viauuid.ContainsKey(avatar_uuid) == false)
{
PendingAvatarFinds_viauuid.Add(avatar_uuid, new KeyValuePair<long, int>(now, 0));
Client.Avatars.RequestAvatarName(avatar_uuid);
}
}
return "lookup";
protected string httpLookupName(UUID avatar_uuid)
{
if (myconfig.Name2Key_Enable == true)
{
var client = new RestClient(myconfig.Name2Key_Url);
var request = new RestRequest("key2name/" + avatar_uuid.ToString() + "/" + myconfig.Name2Key_Key + "", Method.GET);
client.Timeout = 3000; // ? does this even do anything
request.Timeout = 3000;
IRestResponse endpoint_checks = client.Get(request);
if (endpoint_checks.StatusCode == System.Net.HttpStatusCode.OK)
{
try
{
namekeyservicereply server_reply = JsonConvert.DeserializeObject<namekeyservicereply>(endpoint_checks.Content);
if (server_reply.status == true)
{
if (server_reply.found == true)
{
AddAvatarToDB((UUID)server_reply.uuid, server_reply.name);
return server_reply.name;
}
}
}
catch
{
}
}
}
return "";
}
public string FindAvatarKey2Name(UUID avatar_uuid)
{
string avatar_name = FindAvatarNameInStorage(avatar_uuid);
if (avatar_name != "")
{
return avatar_name;
}
avatar_name = httpLookupName(avatar_uuid);
if (avatar_name != "")
{
return avatar_name;
}
if (PendingAvatarFinds_viauuid.ContainsKey(avatar_uuid) == false)
{
PendingAvatarFinds_viauuid.Add(avatar_uuid, new KeyValuePair<long, int>(helpers.UnixTimeNow(), 0));
Client.Avatars.RequestAvatarName(avatar_uuid);
}
return "lookup";
}
protected virtual void FoundMasterAvatar()

View file

@ -9,165 +9,52 @@ namespace BSB.bottypes
{
public abstract class AtHome : MessageSwitcherBot
{
protected long ConnectionLostAt = 0;
protected long last_tp_attempt_unixtime;
protected string last_attempted_teleport_region = "";
protected bool after_login_fired;
protected int last_tested_home_id = -1;
protected Dictionary<string, long> avoid_sims = new Dictionary<string, long>();
protected bool teleport_lockout;
protected override void AfterBotLoginHandler()
{
base.AfterBotLoginHandler();
Info("Home regions count: " + myconfig.Basic_HomeRegions.Length.ToString() + "");
last_tested_home_id = -1;
last_tp_attempt_unixtime = helpers.UnixTimeNow() + 30;
if (reconnect == true)
{
ResetAtHome();
}
else
{
Client.Self.AlertMessage += AlertEvent;
Client.Network.SimChanged += ChangeSim;
}
if (Client.Network.Connected == true)
if (after_login_fired == false)
{
if (Client.Network.CurrentSim != null)
{
if (IsSimHome(Client.Network.CurrentSim.Name) == true)
{
if (UUID.TryParse(myconfig.Setting_DefaultSit_UUID, out UUID sit_UUID) == true)
{
Client.Self.RequestSit(sit_UUID, Vector3.Zero);
}
}
}
Info("Home regions count: " + myconfig.Basic_HomeRegions.Length.ToString() + "");
Client.Self.AlertMessage += AlertEvent;
Client.Network.SimChanged += ChangeSim;
after_login_fired = true;
reconnect = true;
}
after_login_fired = true;
}
protected string FirstLoginStage()
{
long dif = helpers.UnixTimeNow() - last_reconnect_attempt;
if (login_auto_logout == true)
{
if (last_reconnect_attempt == 0)
{
last_reconnect_attempt = helpers.UnixTimeNow();
return login_status;
}
else
{
if (auto_logout_login_recover == false)
{
auto_logout_login_recover = true;
last_reconnect_attempt = helpers.UnixTimeNow();
return "W4>" + login_status + " (20 secs)";
}
else if (dif >= 20)
{
login_auto_logout = false;
auto_logout_login_recover = false;
last_reconnect_attempt = helpers.UnixTimeNow();
Start(true);
return "Restarting first login [Using Alt locations]";
}
return "Waiting for cooldown";
}
}
else
{
return login_status;
}
}
protected string LoggedInConnectionLost()
{
long dif = helpers.UnixTimeNow() - last_reconnect_attempt;
if (reconnect_mode == true)
{
last_tested_home_id = -1;
last_tp_attempt_unixtime = 0;
after_login_fired = false;
teleported = false;
reconnect_mode = false;
last_reconnect_attempt = helpers.UnixTimeNow();
return "Connection lost - switching to recovery mode";
}
else
{
if (dif <= 60)
{
return "W4> Network reset timeout [60 secs]";
}
else
{
if (last_reconnect_attempt == 0)
{
last_reconnect_attempt = helpers.UnixTimeNow();
return "First connection failed";
}
else
{
last_reconnect_attempt = helpers.UnixTimeNow();
if (after_login_fired == true)
{
reconnect = true;
}
login_failed = false;
login_auto_logout = false;
Start(true);
if (reconnect == true)
{
return "Attempting reconnect";
}
return "Trying to connect again";
}
}
}
}
protected string LoggedOutNextAction()
{
if (login_failed == true)
{
return LoggedInConnectionLost();
}
else if (login_auto_logout == true)
{
return FirstLoginStage();
}
return "";
}
protected int last_tested_home_id = -1;
protected long last_tp_attempt_unixtime;
protected bool after_login_fired;
protected long last_reconnect_attempt;
protected bool reconnect_mode;
protected string last_attempted_teleport_region = "";
protected Dictionary<string, long> avoid_sims = new Dictionary<string, long>();
protected bool SimShutdownAvoid;
protected long SimShutdownAvoidCooldown = 0;
protected bool auto_logout_login_recover;
protected void ChangeSim(object sender,SimChangedEventArgs e)
{
if (Client.Network.CurrentSim.Name != last_attempted_teleport_region)
{
if (IsSimHome(Client.Network.CurrentSim.Name) == false)
{
SetTeleported();
}
else
{
if (UUID.TryParse(myconfig.Setting_DefaultSit_UUID, out UUID sit_UUID) == true)
{
Client.Self.RequestSit(sit_UUID, Vector3.Zero);
if (teleport_lockout == false)
{
if (last_attempted_teleport_region != "")
{
if (last_attempted_teleport_region != Client.Network.CurrentSim.Name)
{
teleport_lockout = true;
Info("Teleport by script/master detected - @home lock out enabled");
}
}
else
{
last_attempted_teleport_region = Client.Network.CurrentSim.Name;
Info("Connected to region");
}
}
else
if (IsSimHome(Client.Network.CurrentSim.Name) == true)
{
if (SimShutdownAvoid == true)
if (UUID.TryParse(myconfig.Setting_DefaultSit_UUID, out UUID sit_UUID) == true)
{
Status("Avoided sim shutdown will attempt to go home in 4 mins");
SimShutdownAvoid = false;
Client.Self.RequestSit(sit_UUID, Vector3.Zero);
}
}
}
@ -177,11 +64,8 @@ namespace BSB.bottypes
{
// oh snap region is dead run away
Info("--- Sim Restarting ---");
if (avoid_sims.ContainsKey(Client.Network.CurrentSim.Name) == false)
{
avoid_sims.Add(Client.Network.CurrentSim.Name, helpers.UnixTimeNow() + (10 * 60));
}
GotoNextHomeRegion(true);
AvoidSim(Client.Network.CurrentSim.Name);
GotoNextHomeRegion();
}
}
@ -189,11 +73,10 @@ namespace BSB.bottypes
{
Debug("@home / ResetAtHome");
last_tested_home_id = -1;
after_login_fired = false;
teleported = false;
reconnect_mode = false;
last_tp_attempt_unixtime = 0;
teleport_lockout = false;
last_attempted_teleport_region = "";
avoid_sims = new Dictionary<string, long>();
last_tp_attempt_unixtime = helpers.UnixTimeNow() + 30;
}
@ -202,7 +85,7 @@ namespace BSB.bottypes
{
if (avoid_sims.ContainsKey(simname) == false)
{
Debug("@home / AvoidSim: " + simname);
Debug("@home / Avoiding sim: " + simname);
avoid_sims.Add(simname, helpers.UnixTimeNow() + 240); // @home will avoid that sim for the next 4 mins
}
}
@ -213,10 +96,6 @@ namespace BSB.bottypes
{
List<string> remove_keys = new List<string>();
long now = helpers.UnixTimeNow();
if (GetClient.Network.Connected == false)
{
now -= 240; // when logged out, add 240s to all sims we are avoiding
}
foreach (KeyValuePair<string,long> avoids in avoid_sims)
{
if(avoids.Value < now)
@ -270,68 +149,72 @@ namespace BSB.bottypes
public string LoggedinAthome()
{
string addon = "";
if(IsSimHome(Client.Network.CurrentSim.Name) == true)
{
addon = "Home region";
string addon = "Waiting for action";
if (teleport_lockout == false)
{
if (IsSimHome(Client.Network.CurrentSim.Name) == true)
{
addon = "Home region";
}
else
{
long dif = last_tp_attempt_unixtime - helpers.UnixTimeNow();
if (dif > 0)
{
addon = "Waiting for TP cooldown";
}
else
{
GotoNextHomeRegion();
}
}
}
else
{
if (SimShutdownAvoid == false)
{
long dif = SimShutdownAvoidCooldown - helpers.UnixTimeNow();
if (dif < 0)
{
dif = helpers.UnixTimeNow() - last_tp_attempt_unixtime;
if (dif > 30)
{
if (teleported == false)
{
addon = GotoNextHomeRegion(false);
}
else
{
addon = "- Teleported by script/master -";
}
}
else
{
addon = "Busy with TP cooldown";
}
}
else
{
if (avoid_sims.Keys.Contains(Client.Network.CurrentSim.Name) == true)
{
dif = helpers.UnixTimeNow() - last_tp_attempt_unixtime;
if (dif > 45)
{
addon = GotoNextHomeRegion(true);
}
else
{
addon = "Avoid teleport underway";
}
}
else
{
double mins = Math.Round((double)dif / 60);
int min = (int)mins;
addon = "Hiding from the storm ("+min.ToString()+" mins remain)";
}
}
}
else
{
addon = "Avoiding sim shutdown [TP underway]";
}
else
{
addon = "Lockout";
}
return addon;
}
public string GotoNextHomeRegion()
{
return GotoNextHomeRegion(false);
}
protected long login_failed_retry_at = 0;
public string AtHomeReconnect()
{
if (attempted_first_login == true)
{
if (login_failed == false)
{
return login_status;
}
else
{
if(login_failed_retry_at == 0)
{
login_failed_retry_at = helpers.UnixTimeNow() + 40;
return login_status + " Retrying in 40 secs";
}
else
{
long dif = login_failed_retry_at - helpers.UnixTimeNow();
if(dif > 0)
{
login_failed_retry_at = 0;
attempted_first_login = false;
Start(true);
return "Attempting reconnect";
}
else
{
return "Waiting for reconnect - " + dif.ToString() + " secs";
}
}
}
}
else
{
return "Waiting";
}
}
protected override string[] getNextHomeArgs()
@ -357,71 +240,45 @@ namespace BSB.bottypes
return new string[] { };
}
protected string GotoNextHomeRegion(bool panic_mode)
{
if (panic_mode == false)
{
if (myconfig.Basic_HomeRegions.Length > 0)
{
last_tp_attempt_unixtime = helpers.UnixTimeNow();
string UseSLurl = "";
foreach (string Slurl in myconfig.Basic_HomeRegions)
public string GotoNextHomeRegion()
{
if (myconfig.Basic_HomeRegions.Length > 0)
{
last_tp_attempt_unixtime = helpers.UnixTimeNow();
List<string> tested_sims = new List<string>();
string UseSLurl = "";
string simname = "";
while ((tested_sims.Count() != myconfig.Basic_HomeRegions.Length) && (UseSLurl == ""))
{
last_tested_home_id++;
if (last_tested_home_id > myconfig.Basic_HomeRegions.Length)
{
string simname = helpers.RegionnameFromSLurl(Slurl);
if (avoid_sims.Keys.Contains(simname) == false)
last_tested_home_id = 0;
}
UseSLurl = myconfig.Basic_HomeRegions[last_tested_home_id];
simname = helpers.RegionnameFromSLurl(UseSLurl);
if (simname != last_attempted_teleport_region)
{
if (avoid_sims.ContainsKey(simname) == true)
{
UseSLurl = Slurl;
break;
UseSLurl = "";
}
}
if (UseSLurl != "")
}
}
if (UseSLurl != "")
{
string whyrejected = TeleportWithSLurl(UseSLurl);
if (whyrejected == "ok")
{
string simname = helpers.RegionnameFromSLurl(UseSLurl);
if (simname != last_attempted_teleport_region)
{
string whyrejected = TeleportWithSLurl(UseSLurl);
if (whyrejected == "ok")
{
AvoidSim(simname);
return "**** active teleport: " + last_attempted_teleport_region + "***";
}
AvoidSim(simname);
return "TP to " + simname + " rejected - " + whyrejected;
}
}
return "No other sims found to teleport to [Maybe only 1 home region?]";
}
return "No home regions";
}
else
{
SimShutdownAvoid = true;
SimShutdownAvoidCooldown = helpers.UnixTimeNow() + (60 * 10);
string UseSLurl = "";
foreach (string Slurl in myconfig.Basic_HomeRegions)
{
string simname = helpers.RegionnameFromSLurl(Slurl);
if (avoid_sims.Keys.Contains(simname) == false)
{
UseSLurl = Slurl;
break;
}
}
if (UseSLurl != "")
{
TeleportWithSLurl(UseSLurl);
Status("Attempting panic evac to: "+ last_attempted_teleport_region+"");
AvoidSim(UseSLurl); // black list that region so we dont try to go back there if we get a shutdown notice again
}
else
{
Status("No vaild SLurl found, Teleporting to backup hub");
string[] Hubs = new[] { "https://maps.secondlife.com/secondlife/Morris/28/228/40/", "https://maps.secondlife.com/secondlife/Ahern/28/28/40/",
"https://maps.secondlife.com/secondlife/Bonifacio/228/228/40/","https://maps.secondlife.com/secondlife/Dore/228/28/40/" };
TeleportWithSLurl(Hubs[new Random().Next(0, Hubs.Length - 1)]);
}
return "Panic mode";
}
AvoidSim(simname);
return "**** active teleport: " + last_attempted_teleport_region + "***";
}
AvoidSim(simname);
return "TP to " + simname + " rejected - " + whyrejected;
}
return "No other sims found to teleport to";
}
return "No home regions";
}
@ -434,7 +291,7 @@ namespace BSB.bottypes
public override string GetStatus()
{
ExpireOldAvoidSims();
string reply;
string reply = "Disconnected: No action";
if (Client.Network.Connected == true)
{
if (Client.Network.CurrentSim != null)
@ -443,17 +300,18 @@ namespace BSB.bottypes
{
AfterBotLoginHandler();
}
reply = AtHomeStatus(LoggedinAthome());
reply = LoggedinAthome();
}
else
{
reply = AtHomeStatus("No Sim");
reply = "Connected: No Sim";
}
}
else
{
reply = AtHomeStatus(LoggedOutNextAction());
{
reply = AtHomeReconnect();
}
reply = AtHomeStatus(reply);
if (reply != AtHome_laststatus)
{
AtHome_laststatus = reply;

View file

@ -1142,7 +1142,7 @@ namespace OpenMetaverse
if (string.IsNullOrEmpty(loginParams.LoginLocation) == false)
{
string[] bits = loginParams.LoginLocation.Split("/");
string[] bits = loginParams.LoginLocation.Split('/');
if(bits.Count() == 4)
{
if(int.TryParse(bits[1],out int X) == true)