Display Names (#94)
Some checks failed
CodeQL / Analyze (push) Has been cancelled
dotnet package / build (8.0.x) (push) Has been cancelled
dotnet package / build (9.0.x) (push) Has been cancelled

Authored-by: StolenRuby <26614880+StolenRuby@users.noreply.github.com>
Reviewed-by: Michael Dickson
This commit is contained in:
Mike Dickson 2024-09-17 21:04:58 -04:00 committed by GitHub
parent 4bb0209eea
commit 0e0953667c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 495 additions and 31 deletions

View file

@ -66,15 +66,16 @@ namespace OpenSim.Data.MySQL
{
if (words.Length == 1)
{
cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?search or LastName like ?search) and active=1", m_Realm);
cmd.CommandText = string.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?search or LastName like ?search or DisplayName like ?search) and active=1", m_Realm);
cmd.Parameters.AddWithValue("?search", "%" + words[0] + "%");
cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
}
else
{
cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?searchFirst and LastName like ?searchLast) and active=1", m_Realm);
cmd.CommandText = string.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?searchFirst and LastName like ?searchLast or DisplayName like ?searchDisplay) and active=1", m_Realm);
cmd.Parameters.AddWithValue("?searchFirst", "%" + words[0] + "%");
cmd.Parameters.AddWithValue("?searchLast", "%" + words[1] + "%");
cmd.Parameters.AddWithValue("?searchDisplay", "%" + query + "%");
cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
}

View file

@ -29,3 +29,13 @@ BEGIN;
ALTER TABLE `UserAccounts` ADD `active` INT NOT NULL DEFAULT '1';
COMMIT;
:VERSION 7 # -------------------------
BEGIN;
ALTER TABLE `useraccounts`
ADD COLUMN `DisplayName` VARCHAR(31) NULL AFTER `active`,
ADD COLUMN `NameChanged` INT NULL DEFAULT 0 AFTER `DisplayName`;
COMMIT;

View file

@ -42,6 +42,56 @@ namespace OpenSim.Framework
public bool HasGridUserTried;
public bool IsLocal;
public double LastWebFail = -1;
public string DisplayName;
public DateTime NameChanged;
public bool IsNameDefault
{
get
{
return string.IsNullOrWhiteSpace(DisplayName);
}
}
public string LegacyName
{
get
{
if (LastName.ToLower() == "resident")
return FirstName;
else return $"{FirstName} {LastName}";
}
}
public string Username
{
get
{
if (LastName.ToLower() == "resident")
return FirstName;
else if(LastName.StartsWith("@"))
return $"{FirstName}{LastName}";
else return $"{FirstName}.{LastName}";
}
}
public string LowerUsername
{
get
{
return Username.ToLower();
}
}
public string ViewerDisplayName
{
get
{
if (IsNameDefault)
return LegacyName;
else return DisplayName;
}
}
}
public interface IPeople

View file

@ -179,13 +179,10 @@ namespace OpenSim.Region.ClientStack.Linden
LLSDPerson p = new LLSDPerson();
p.legacy_first_name = user.FirstName;
p.legacy_last_name = user.LastName;
p.display_name = user.FirstName + " " + user.LastName;
if (user.LastName.StartsWith("@"))
p.username = user.FirstName.ToLower() + user.LastName.ToLower();
else
p.username = user.FirstName.ToLower() + "." + user.LastName.ToLower();
p.display_name = user.ViewerDisplayName;
p.username = user.LowerUsername;
p.id = user.Id;
p.is_display_name_default = false;
p.is_display_name_default = user.IsNameDefault;
return p;
}
}

View file

@ -2234,16 +2234,15 @@ namespace OpenSim.Region.ClientStack.Linden
if (string.IsNullOrEmpty(ud.FirstName) || ud.FirstName.Equals("Unkown"))
continue;
string fullname = ud.FirstName + " " + ud.LastName;
LLSDxmlEncode2.AddMap(lsl);
LLSDxmlEncode2.AddElem("username", fullname, lsl);
LLSDxmlEncode2.AddElem("display_name", fullname, lsl);
LLSDxmlEncode2.AddElem("display_name_next_update", DateTime.UtcNow.AddDays(8), lsl);
LLSDxmlEncode2.AddElem("display_name_expires", DateTime.UtcNow.AddMonths(1), lsl);
LLSDxmlEncode2.AddElem("username", ud.LowerUsername, lsl);
LLSDxmlEncode2.AddElem("display_name", ud.ViewerDisplayName, lsl);
LLSDxmlEncode2.AddElem("display_name_next_update", ud.NameChanged.AddDays(7), lsl);
LLSDxmlEncode2.AddElem("display_name_expires", DateTime.UtcNow.AddDays(1), lsl);
LLSDxmlEncode2.AddElem("legacy_first_name", ud.FirstName, lsl);
LLSDxmlEncode2.AddElem("legacy_last_name", ud.LastName, lsl);
LLSDxmlEncode2.AddElem("id", ud.Id, lsl);
LLSDxmlEncode2.AddElem("is_display_name_default", true, lsl);
LLSDxmlEncode2.AddElem("is_display_name_default", ud.IsNameDefault, lsl);
LLSDxmlEncode2.AddEndMap(lsl);
}
LLSDxmlEncode2.AddEndArray(lsl);

View file

@ -0,0 +1,238 @@
using System.Reflection;
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using Caps = OpenSim.Framework.Capabilities.Caps;
using OpenSim.Framework;
using System.Net;
namespace OpenSim.Region.ClientStack.LindenCaps
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DisplayNameModule")]
public class DisplayNameModule : IDisplayNameModule, INonSharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IEventQueue m_EventQueue = null;
protected Scene m_Scene = null;
private bool m_Enabled = false;
#region ISharedRegionModule
public void Initialise(IConfigSource source)
{
IConfig config = source.Configs["ClientStack.LindenCaps"];
if (config == null)
return;
string url = config.GetString("Cap_SetDisplayName", string.Empty);
if (url == "localhost")
m_Enabled = true;
if (!m_Enabled)
return;
m_log.Info("[DISPLAY NAMES] Plugin enabled!");
}
public void AddRegion(Scene scene)
{
if (!m_Enabled)
return;
m_Scene = scene;
scene.RegisterModuleInterface<IDisplayNameModule>(this);
}
public void RemoveRegion(Scene scene)
{
if (!m_Enabled)
return;
m_Scene = null;
}
public void RegionLoaded(Scene scene)
{
if (!m_Enabled)
return;
m_EventQueue = scene.RequestModuleInterface<IEventQueue>();
if (m_EventQueue is null)
{
m_log.Info("[DISPLAY NAMES]: Module disabled becuase IEventQueue was not found!");
return;
}
scene.EventManager.OnRegisterCaps += OnRegisterCaps;
}
public void PostInitialise() { }
public void Close() { }
public string Name { get { return "DisplayNamesModule"; } }
public Type ReplaceableInterface
{
get { return null; }
}
#endregion
#region IDisplayNameModule
public string GetDisplayName(UUID avatar)
{
var user = m_Scene.UserManagementModule.GetUserData(avatar);
if (user is not null)
{
return user.ViewerDisplayName;
}
return string.Empty;
}
#endregion
private void OnRegisterCaps(UUID agentID, Caps caps)
{
if (m_Scene.UserManagementModule.IsLocalGridUser(agentID))
{
caps.RegisterSimpleHandler("SetDisplayName", new SimpleStreamHandler($"/{UUID.Random()}", (req, resp) => SetDisplayName(agentID, req, resp)));
return;
}
}
private void SetDisplayName(UUID agent_id, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
if (httpRequest.HttpMethod != "POST")
{
httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
ScenePresence sp = m_Scene.GetScenePresence(agent_id);
if (sp == null || sp.IsDeleted)
{
httpResponse.StatusCode = (int)HttpStatusCode.Gone;
return;
}
if (sp.IsInTransit && !sp.IsInLocalTransit)
{
httpResponse.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
httpResponse.AddHeader("Retry-After", "30");
return;
}
var userData = m_Scene.UserManagementModule.GetUserData(agent_id);
if (userData.NameChanged.AddDays(7) > DateTime.UtcNow)
{
m_Scene.GetScenePresence(agent_id).ControllingClient.SendAlertMessage("You can only change your display name once a week!");
return;
}
OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(httpRequest.InputStream);
if (req.ContainsKey("display_name"))
{
OSDArray name = req["display_name"] as OSDArray;
string oldName = name[0].AsString();
string newName = name[1].AsString();
bool resetting = string.IsNullOrWhiteSpace(newName);
if (resetting) newName = string.Empty;
bool success = m_Scene.UserManagementModule.SetDisplayName(agent_id, newName);
if (success)
{
// Update the current object
userData.DisplayName = newName;
userData.NameChanged = DateTime.UtcNow;
if (resetting)
m_log.InfoFormat("[DISPLAY NAMES] {0} {1} reset their display name", userData.FirstName, userData.LastName);
else
m_log.InfoFormat("[DISPLAY NAMES] {0} {1} changed their display name to {2}", userData.FirstName, userData.LastName, userData.DisplayName);
DateTime next_update = DateTime.UtcNow.AddDays(7);
OSD update = FormatDisplayNameUpdate(oldName, userData, next_update);
m_Scene.ForEachClient(x => {
m_EventQueue.Enqueue(update, x.AgentId);
});
SendSetDisplayNameReply(newName, oldName, userData, next_update);
}
else
{
m_Scene.GetScenePresence(agent_id).ControllingClient.SendAlertMessage("Failed to update display name.");
httpResponse.StatusCode = (int)HttpStatusCode.InternalServerError;
return;
}
}
httpResponse.ContentType = "application/llsd+xml";
httpResponse.RawBuffer = Utils.StringToBytes("<llsd><undef/></llsd>");
httpResponse.StatusCode = (int)HttpStatusCode.OK;
}
public OSD FormatDisplayNameUpdate(string oldName, UserData userData, DateTime nextUpdate)
{
var agentData = new OSDMap();
agentData["display_name"] = OSD.FromString(userData.ViewerDisplayName);
agentData["id"] = OSD.FromUUID(userData.Id);
agentData["is_display_name_default"] = OSD.FromBoolean(userData.IsNameDefault);
agentData["legacy_first_name"] = OSD.FromString(userData.FirstName);
agentData["legacy_last_name"] = OSD.FromString(userData.LastName);
agentData["username"] = OSD.FromString(userData.Username);
agentData["display_name_next_update"] = OSD.FromDate(nextUpdate);
var body = new OSDMap();
body["agent"] = agentData;
body["agent_id"] = OSD.FromString(userData.Id.ToString());
body["old_display_name"] = OSD.FromString(oldName);
var nameReply = new OSDMap();
nameReply["body"] = body;
nameReply["message"] = OSD.FromString("DisplayNameUpdate");
return nameReply;
}
public void SendSetDisplayNameReply(string newDisplayName, string oldDisplayName, UserData nameInfo, DateTime nextUpdate)
{
var content = new OSDMap();
content["display_name"] = OSD.FromString(nameInfo.ViewerDisplayName);
content["display_name_next_update"] = OSD.FromDate(nextUpdate);
content["id"] = OSD.FromUUID(nameInfo.Id);
content["is_display_name_default"] = OSD.FromBoolean(nameInfo.IsNameDefault);
content["legacy_first_name"] = OSD.FromString(nameInfo.FirstName);
content["legacy_last_name"] = OSD.FromString(nameInfo.LastName);
content["username"] = OSD.FromString(nameInfo.LowerUsername);
var body = new OSDMap();
body["content"] = content;
body["reason"] = OSD.FromString("OK");
body["status"] = OSD.FromInteger(200);
var nameReply = new OSDMap();
nameReply["body"] = body;
nameReply["message"] = OSD.FromString("SetDisplayNameReply");
m_EventQueue.Enqueue((OSD)nameReply, nameInfo.Id);
}
}
}

View file

@ -304,6 +304,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
ud.HasGridUserTried = true;
ud.IsUnknownUser = false;
ud.IsLocal = acc.LocalToGrid;
ud.DisplayName = acc.DisplayName;
ud.NameChanged = Utils.UnixTimeToDateTime(acc.NameChanged);
users.Add(ud);
found.Add(id);
}
@ -468,6 +470,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
userdata.IsUnknownUser = false;
userdata.IsLocal = true;
userdata.HasGridUserTried = true;
userdata.DisplayName = uac.DisplayName;
userdata.NameChanged = Utils.UnixTimeToDateTime(uac.NameChanged);
m_userCacheByID.Add(id, userdata, 1800000);
ret[id] = uac.FirstName + " " + uac.LastName;
@ -599,6 +603,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
userdata.IsUnknownUser = false;
userdata.IsLocal = true;
userdata.HasGridUserTried = true;
userdata.DisplayName = uac.DisplayName;
userdata.NameChanged = Utils.UnixTimeToDateTime(uac.NameChanged);
m_userCacheByID.Add(id, userdata, 1800000);
ret[id] = uac.FirstName + " " + uac.LastName;
@ -716,6 +722,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
userdata.IsUnknownUser = false;
userdata.IsLocal = true;
userdata.HasGridUserTried = true;
userdata.DisplayName = uac.DisplayName;
userdata.NameChanged = Utils.UnixTimeToDateTime(uac.NameChanged);
m_userCacheByID.Add(id, userdata, 1800000);
ret.Add(userdata);
@ -1017,6 +1025,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
userdata.IsUnknownUser = false;
userdata.IsLocal = true;
userdata.HasGridUserTried = true;
userdata.DisplayName = account.DisplayName;
userdata.NameChanged = Utils.UnixTimeToDateTime(account.NameChanged);
}
}
@ -1281,6 +1291,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
return true;
}
public bool SetDisplayName(UUID agentID, string displayName)
{
return m_userAccountService.SetDisplayName(agentID, displayName);
}
#endregion IUserManagement
protected virtual void Init(IConfigSource config)

View file

@ -248,6 +248,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
m_Cache.Invalidate(userID);
}
public bool SetDisplayName(UUID agentID, string displayName)
{
return UserAccountService.SetDisplayName(agentID, displayName);
}
#endregion
}
}

View file

@ -0,0 +1,15 @@
using OpenMetaverse;
using OpenSim.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenSim.Region.Framework.Interfaces
{
public interface IDisplayNameModule
{
public string GetDisplayName(UUID avatar);
}
}

View file

@ -15444,6 +15444,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
ScenePresence presence = World.GetScenePresence(key);
if (presence != null)
{
var dnm = World.RequestModuleInterface<IDisplayNameModule>();
if(dnm is not null)
{
return dnm.GetDisplayName(key);
}
return presence.Name;
}
}
@ -15455,26 +15462,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (!UUID.TryParse(id, out UUID key) || key.IsZero())
return string.Empty;
ScenePresence lpresence = World.GetScenePresence(key);
if (lpresence != null)
{
string lname = lpresence.Name;
string ftid = m_AsyncCommands.DataserverPlugin.RequestWithImediatePost(m_host.LocalId,
m_item.ItemID, lname);
return ftid;
}
void act(string eventID)
{
string name = String.Empty;
ScenePresence presence = World.GetScenePresence(key);
if (presence is not null)
var dnm = World.RequestModuleInterface<IDisplayNameModule>();
if (dnm is not null)
{
name = presence.Name;
}
else if (World.TryGetSceneObjectPart(key, out SceneObjectPart sop))
{
name = sop.Name;
name = dnm.GetDisplayName(key);
}
else
{

View file

@ -104,6 +104,8 @@ namespace OpenSim.Server.Handlers.UserAccounts
return GetAccounts(request);
case "getmultiaccounts":
return GetMultiAccounts(request);
case "setdisplayname":
return SetDisplayName(request);
case "setaccount":
if (m_AllowSetAccount)
return StoreAccount(request);
@ -256,6 +258,28 @@ namespace OpenSim.Server.Handlers.UserAccounts
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
}
byte[] SetDisplayName(Dictionary<string, object> request)
{
object otmp;
UUID principalID = UUID.Zero;
if (request.TryGetValue("PrincipalID", out otmp) && !UUID.TryParse(otmp.ToString(), out principalID))
return FailureResult();
UserAccount existingAccount = m_UserAccountService.GetUserAccount(UUID.Zero, principalID);
if (existingAccount == null)
return FailureResult();
if (!request.TryGetValue("DisplayName", out otmp))
return FailureResult();
if (!m_UserAccountService.SetDisplayName(principalID, otmp.ToString()))
return FailureResult();
Dictionary<string, object> result = new Dictionary<string, object>();
result["result"] = "success";
return ResultToBytes(result);
}
byte[] StoreAccount(Dictionary<string, object> request)
{
object otmp;

View file

@ -294,6 +294,20 @@ namespace OpenSim.Services.Connectors
{
}
public bool SetDisplayName(UUID agentID, string displayName)
{
//m_log.DebugFormat("[ACCOUNTS CONNECTOR]: SetDisplayName {0}", agentID);
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
sendData["METHOD"] = "setdisplayname";
sendData["PrincipalID"] = agentID.ToString();
sendData["DisplayName"] = displayName;
return SendAndGetBoolReply(sendData);
}
public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string where)
{
return null; // Not implemented for regions

View file

@ -114,6 +114,11 @@ namespace OpenSim.Services.HypergridService
{
return false;
}
public bool SetDisplayName(UUID agentID, string displayName)
{
return false;
}
#endregion
}

View file

@ -98,11 +98,32 @@ namespace OpenSim.Services.Interfaces
public int Created;
public string DisplayName;
public uint NameChanged;
public string Name
{
get { return FirstName + " " + LastName; }
}
public string FormattedName
{
get
{
bool is_resident = LastName.ToLower() == "resident";
if (string.IsNullOrWhiteSpace(DisplayName))
{
return is_resident ? FirstName : $"{FirstName} {LastName}";
}
else
{
var username = is_resident ? FirstName : $"{FirstName}.{LastName}";
return $"{DisplayName} ({username.ToLower()})";
}
}
}
public UserAccount(Dictionary<string, object> kvp)
{
if (kvp.ContainsKey("FirstName"))
@ -125,6 +146,10 @@ namespace OpenSim.Services.Interfaces
UserCountry = kvp["UserCountry"].ToString();
if (kvp.ContainsKey("LocalToGrid"))
Boolean.TryParse(kvp["LocalToGrid"].ToString(), out LocalToGrid);
if (kvp.ContainsKey("DisplayName"))
DisplayName = kvp["DisplayName"].ToString();
if (kvp.ContainsKey("NameChanged"))
NameChanged = Convert.ToUInt32(kvp["NameChanged"].ToString());
if (kvp.ContainsKey("Created"))
Created = Convert.ToInt32(kvp["Created"].ToString());
@ -160,6 +185,8 @@ namespace OpenSim.Services.Interfaces
result["UserTitle"] = UserTitle;
result["UserCountry"] = UserCountry;
result["LocalToGrid"] = LocalToGrid.ToString();
result["DisplayName"] = DisplayName;
result["NameChanged"] = NameChanged.ToString();
string str = string.Empty;
foreach (KeyValuePair<string, object> kvp in ServiceURLs)
@ -179,6 +206,8 @@ namespace OpenSim.Services.Interfaces
UserAccount GetUserAccount(UUID scopeID, string FirstName, string LastName);
UserAccount GetUserAccount(UUID scopeID, string Email);
bool SetDisplayName(UUID agentID, string displayName);
/// <summary>
/// Returns the list of avatars that matches both the search criterion and the scope ID passed
/// </summary>

View file

@ -92,5 +92,7 @@ namespace OpenSim.Framework
void AddUser(UUID uuid, string firstName, string lastName, string homeURL);
bool RemoveUser(UUID uuid);
bool IsLocalGridUser(UUID uuid);
bool SetDisplayName(UUID agentID, string displayName);
}
}

View file

@ -141,6 +141,11 @@ namespace OpenSim.Services.UserAccountService
"show account",
"show account <first> <last>",
"Show account details for the given user", HandleShowAccount);
MainConsole.Instance.Commands.AddCommand("Users", false,
"set display name",
"set display name <first> <last> <new display name>",
"Sets the display name for the given user", HandleSetDisplayName);
}
}
}
@ -227,6 +232,14 @@ namespace OpenSim.Services.UserAccountService
else
u.ServiceURLs = new Dictionary<string, object>();
if (d.Data.ContainsKey("DisplayName") && d.Data["DisplayName"] != null)
u.DisplayName = d.Data["DisplayName"].ToString();
else
u.DisplayName = string.Empty;
if (d.Data.ContainsKey("NameChanged") && d.Data["NameChanged"] != null)
uint.TryParse(d.Data["NameChanged"], out u.NameChanged);
return u;
}
@ -334,6 +347,9 @@ namespace OpenSim.Services.UserAccountService
d.Data["ServiceURLs"] = string.Join(" ", parts.ToArray());
d.Data["DisplayName"] = data.DisplayName;
d.Data["NameChanged"] = data.NameChanged.ToString();
return m_Database.Store(d);
}
@ -367,6 +383,19 @@ namespace OpenSim.Services.UserAccountService
return ret;
}
public bool SetDisplayName(UUID agentID, string displayName)
{
var account = GetUserAccount(UUID.Zero, agentID);
if (account is null)
return false;
account.DisplayName = displayName;
account.NameChanged = Utils.GetUnixTime();
return StoreUserAccount(account);
}
#endregion
#region Console commands
@ -455,7 +484,7 @@ namespace OpenSim.Services.UserAccountService
return;
}
MainConsole.Instance.Output("Name: {0}", ua.Name);
MainConsole.Instance.Output("Name: {0}", ua.FormattedName);
MainConsole.Instance.Output("ID: {0}", ua.PrincipalID);
MainConsole.Instance.Output("Title: {0}", ua.UserTitle);
MainConsole.Instance.Output("E-mail: {0}", ua.Email);
@ -577,6 +606,40 @@ namespace OpenSim.Services.UserAccountService
MainConsole.Instance.Output("User level set for user {0} {1} to {2}", firstName, lastName, level);
}
protected void HandleSetDisplayName(string module, string[] cmdparams)
{
string firstName;
string lastName;
string displayName;
if (cmdparams.Length < 4)
firstName = MainConsole.Instance.Prompt("First name");
else firstName = cmdparams[3];
if (cmdparams.Length < 5)
lastName = MainConsole.Instance.Prompt("Last name");
else lastName = cmdparams[4];
if (cmdparams.Length < 6)
displayName = MainConsole.Instance.Prompt("Display name");
else displayName = cmdparams[5];
UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName);
if (account == null)
{
MainConsole.Instance.Output("No such user as {0} {1}", firstName, lastName);
return;
}
account.DisplayName = displayName;
account.NameChanged = Utils.GetUnixTime();
if (StoreUserAccount(account))
MainConsole.Instance.Output("Display name updated!");
else
MainConsole.Instance.Output("Unable to set DisplayName for account {0} {1}.", firstName, lastName);
}
#endregion
/// <summary>

View file

@ -751,6 +751,7 @@
Cap_GetMesh = "localhost"
Cap_AvatarPickerSearch = "localhost"
Cap_GetDisplayNames = "localhost"
Cap_SetDisplayName = "localhost"
[SimulatorFeatures]