From 94ab683fe13e833def72c4c41a6b570608a6427a Mon Sep 17 00:00:00 2001
From: Homer Horwitz
Date: Sat, 25 Apr 2009 20:55:55 +0000
Subject: Thanks, Ewe Loon for a patch that provides persistent
AvatarAppearance for SQLite. Fixes Mantis #3296.
---
CONTRIBUTORS.txt | 1 +
OpenSim/Data/SQLite/Resources/010_UserStore.sql | 37 ++++
OpenSim/Data/SQLite/SQLiteUserData.cs | 256 ++++++++++++++++++++++--
3 files changed, 279 insertions(+), 15 deletions(-)
create mode 100644 OpenSim/Data/SQLite/Resources/010_UserStore.sql
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index df34bbb..e774812 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -70,6 +70,7 @@ what it is today.
* Gerhard
* Godfrey
* Grumly57
+* Ewe Loon
* Fly-Man
* Flyte Xevious
* Intimidated
diff --git a/OpenSim/Data/SQLite/Resources/010_UserStore.sql b/OpenSim/Data/SQLite/Resources/010_UserStore.sql
new file mode 100644
index 0000000..5f956da
--- /dev/null
+++ b/OpenSim/Data/SQLite/Resources/010_UserStore.sql
@@ -0,0 +1,37 @@
+BEGIN TRANSACTION;
+
+CREATE TABLE IF NOT EXISTS avatarappearance(
+ Owner varchar(36) NOT NULL primary key,
+ BodyItem varchar(36) DEFAULT NULL,
+ BodyAsset varchar(36) DEFAULT NULL,
+ SkinItem varchar(36) DEFAULT NULL,
+ SkinAsset varchar(36) DEFAULT NULL,
+ HairItem varchar(36) DEFAULT NULL,
+ HairAsset varchar(36) DEFAULT NULL,
+ EyesItem varchar(36) DEFAULT NULL,
+ EyesAsset varchar(36) DEFAULT NULL,
+ ShirtItem varchar(36) DEFAULT NULL,
+ ShirtAsset varchar(36) DEFAULT NULL,
+ PantsItem varchar(36) DEFAULT NULL,
+ PantsAsset varchar(36) DEFAULT NULL,
+ ShoesItem varchar(36) DEFAULT NULL,
+ ShoesAsset varchar(36) DEFAULT NULL,
+ SocksItem varchar(36) DEFAULT NULL,
+ SocksAsset varchar(36) DEFAULT NULL,
+ JacketItem varchar(36) DEFAULT NULL,
+ JacketAsset varchar(36) DEFAULT NULL,
+ GlovesItem varchar(36) DEFAULT NULL,
+ GlovesAsset varchar(36) DEFAULT NULL,
+ UnderShirtItem varchar(36) DEFAULT NULL,
+ UnderShirtAsset varchar(36) DEFAULT NULL,
+ UnderPantsItem varchar(36) DEFAULT NULL,
+ UnderPantsAsset varchar(36) DEFAULT NULL,
+ SkirtItem varchar(36) DEFAULT NULL,
+ SkirtAsset varchar(36) DEFAULT NULL,
+ Texture blob,
+ VisualParams blob,
+ Serial int DEFAULT NULL,
+ AvatarHeight float DEFAULT NULL
+);
+
+COMMIT;
diff --git a/OpenSim/Data/SQLite/SQLiteUserData.cs b/OpenSim/Data/SQLite/SQLiteUserData.cs
index 5f9f979..9485340 100644
--- a/OpenSim/Data/SQLite/SQLiteUserData.cs
+++ b/OpenSim/Data/SQLite/SQLiteUserData.cs
@@ -56,6 +56,7 @@ namespace OpenSim.Data.SQLite
private const string userSelect = "select * from users";
private const string userFriendsSelect = "select a.ownerID as ownerID,a.friendID as friendID,a.friendPerms as friendPerms,b.friendPerms as ownerperms, b.ownerID as fownerID, b.friendID as ffriendID from userfriends as a, userfriends as b";
private const string userAgentSelect = "select * from useragents";
+ private const string AvatarAppearanceSelect = "select * from avatarappearance";
private const string AvatarPickerAndSQL = "select * from users where username like :username and surname like :surname";
private const string AvatarPickerOrSQL = "select * from users where username like :username or surname like :surname";
@@ -65,6 +66,7 @@ namespace OpenSim.Data.SQLite
private SqliteDataAdapter da;
private SqliteDataAdapter daf;
private SqliteDataAdapter dua;
+ private SqliteDataAdapter daa;
SqliteConnection g_conn;
public override void Initialise()
@@ -102,12 +104,15 @@ namespace OpenSim.Data.SQLite
da = new SqliteDataAdapter(new SqliteCommand(userSelect, conn));
dua = new SqliteDataAdapter(new SqliteCommand(userAgentSelect, conn));
daf = new SqliteDataAdapter(new SqliteCommand(userFriendsSelect, conn));
+ daa = new SqliteDataAdapter(new SqliteCommand(AvatarAppearanceSelect, conn));
+ //if (daa == null) m_log.Info("[SQLiteUserData]: daa = null");
lock (ds)
{
ds.Tables.Add(createUsersTable());
ds.Tables.Add(createUserAgentsTable());
ds.Tables.Add(createUserFriendsTable());
+ ds.Tables.Add(createAvatarAppearanceTable());
setupUserCommands(da, conn);
da.Fill(ds.Tables["users"]);
@@ -117,6 +122,9 @@ namespace OpenSim.Data.SQLite
setupUserFriendsCommands(daf, conn);
daf.Fill(ds.Tables["userfriends"]);
+
+ setupAvatarAppearanceCommands(daa, conn);
+ daa.Fill(ds.Tables["avatarappearance"]);
}
return;
@@ -149,6 +157,11 @@ namespace OpenSim.Data.SQLite
dua.Dispose();
dua = null;
}
+ if (daa != null)
+ {
+ daa.Dispose();
+ daa = null;
+ }
aplist = null;
}
@@ -199,9 +212,9 @@ namespace OpenSim.Data.SQLite
}
}
}
-
+
#region User Friends List Data
-
+
private bool ExistsFriend(UUID owner, UUID friend)
{
string FindFriends = "select * from userfriends where (ownerID=:ownerID and friendID=:friendID) or (ownerID=:friendID and friendID=:ownerID)";
@@ -242,7 +255,7 @@ namespace OpenSim.Data.SQLite
{
if (ExistsFriend(friendlistowner, friend))
return;
-
+
string InsertFriends = "insert into userfriends(ownerID, friendID, friendPerms) values(:ownerID, :friendID, :perms)";
using (SqliteCommand cmd = new SqliteCommand(InsertFriends, g_conn))
{
@@ -528,7 +541,7 @@ namespace OpenSim.Data.SQLite
UUID zero = UUID.Zero;
if (ExistsFirstLastName(user.FirstName, user.SurName) || user.ID == zero)
return;
-
+
lock (ds)
{
DataRow row = users.Rows.Find(user.ID.ToString());
@@ -537,9 +550,9 @@ namespace OpenSim.Data.SQLite
row = users.NewRow();
fillUserRow(row, user);
users.Rows.Add(row);
-
+
m_log.Debug("[USER DB]: Syncing user database: " + ds.Tables["users"].Rows.Count + " users stored");
-
+
// save changes off to disk
da.Update(ds, "users");
}
@@ -571,7 +584,7 @@ namespace OpenSim.Data.SQLite
da.Update(ds, "users");
}
}
-
+
//AddNewUserProfile(user);
return true;
}
@@ -641,13 +654,83 @@ namespace OpenSim.Data.SQLite
/// Avatar Appearence
override public AvatarAppearance GetUserAppearance(UUID user)
{
- AvatarAppearance aa = null;
- try {
- aa = aplist[user];
- m_log.Info("[APPEARANCE] Found appearance for " + user.ToString() + aa.ToString());
- } catch (KeyNotFoundException) {
- m_log.InfoFormat("[APPEARANCE] No appearance found for {0}", user.ToString());
+ m_log.Info("[APPEARANCE] GetUserAppearance " + user.ToString());
+
+ AvatarAppearance aa = new AvatarAppearance(user);
+ //try {
+ aa.Owner = user;
+ //aplist[user] = appearance;
+
+ DataTable aap = ds.Tables["avatarappearance"];
+ lock (ds)
+ {
+ DataRow row = aap.Rows.Find(Util.ToRawUuidString(user));
+ if (row == null)
+ {
+ m_log.Info("[APPEARANCE] Could not find appearance for " + user.ToString());
+
+ //m_log.Debug("[USER DB]: Creating avatarappearance For: " + user.ToString());
+
+ //row = aap.NewRow();
+ //fillAvatarAppearanceRow(row, user, appearance);
+ //aap.Rows.Add(row);
+ // m_log.Debug("[USER DB]: Syncing user database: " + ds.Tables["users"].Rows.Count + " users stored");
+ // save changes off to disk
+ //daa.Update(ds, "avatarappearance");
+ }
+ else
+ {
+ m_log.InfoFormat("[APPEARANCE] appearance found for {0}", user.ToString());
+
+ aa.BodyAsset = new UUID((String)row["BodyAsset"]);
+ aa.BodyItem = new UUID((String)row["BodyItem"]);
+ aa.SkinItem = new UUID((String)row["SkinItem"]);
+ aa.SkinAsset = new UUID((String)row["SkinAsset"]);
+ aa.HairItem = new UUID((String)row["HairItem"]);
+ aa.HairAsset = new UUID((String)row["HairAsset"]);
+ aa.EyesItem = new UUID((String)row["EyesItem"]);
+ aa.EyesAsset = new UUID((String)row["EyesAsset"]);
+ aa.ShirtItem = new UUID((String)row["ShirtItem"]);
+ aa.ShirtAsset = new UUID((String)row["ShirtAsset"]);
+ aa.PantsItem = new UUID((String)row["PantsItem"]);
+ aa.PantsAsset = new UUID((String)row["PantsAsset"]);
+ aa.ShoesItem = new UUID((String)row["ShoesItem"]);
+ aa.ShoesAsset = new UUID((String)row["ShoesAsset"]);
+ aa.SocksItem = new UUID((String)row["SocksItem"]);
+ aa.SocksAsset = new UUID((String)row["SocksAsset"]);
+ aa.JacketItem = new UUID((String)row["JacketItem"]);
+ aa.JacketAsset = new UUID((String)row["JacketAsset"]);
+ aa.GlovesItem = new UUID((String)row["GlovesItem"]);
+ aa.GlovesAsset = new UUID((String)row["GlovesAsset"]);
+ aa.UnderShirtItem = new UUID((String)row["UnderShirtItem"]);
+ aa.UnderShirtAsset = new UUID((String)row["UnderShirtAsset"]);
+ aa.UnderPantsItem = new UUID((String)row["UnderPantsItem"]);
+ aa.UnderPantsAsset = new UUID((String)row["UnderPantsAsset"]);
+ aa.SkirtItem = new UUID((String)row["SkirtItem"]);
+ aa.SkirtAsset = new UUID((String)row["SkirtAsset"]);
+
+ // Ewe Loon
+ // Used Base64String because for some reason it wont accept using Byte[] (which works in Region date)
+
+ String str = (String)row["Texture"];
+ byte[] texture = Convert.FromBase64String(str);
+ aa.Texture = new Primitive.TextureEntry(texture, 0, texture.Length);
+
+ str = (String)row["VisualParams"];
+ byte[] VisualParams = Convert.FromBase64String(str);
+ aa.VisualParams = VisualParams;
+
+ aa.Serial = Convert.ToInt32(row["Serial"]);
+ aa.AvatarHeight = Convert.ToSingle(row["AvatarHeight"]);
+ m_log.InfoFormat("[APPEARANCE] appearance set for {0}", user.ToString());
+ }
}
+
+ // aa = aplist[user];
+ // m_log.Info("[APPEARANCE] Found appearance for " + user.ToString() + aa.ToString());
+ // } catch (KeyNotFoundException) {
+ // m_log.InfoFormat("[APPEARANCE] No appearance found for {0}", user.ToString());
+ // }
return aa;
}
@@ -659,7 +742,29 @@ namespace OpenSim.Data.SQLite
override public void UpdateUserAppearance(UUID user, AvatarAppearance appearance)
{
appearance.Owner = user;
- aplist[user] = appearance;
+ //aplist[user] = appearance;
+ DataTable aap = ds.Tables["avatarappearance"];
+ lock (ds)
+ {
+ DataRow row = aap.Rows.Find(Util.ToRawUuidString(user));
+ if (row == null)
+ {
+ m_log.Debug("[USER DB]: Creating UserAppearance For: " + user.ToString());
+
+ row = aap.NewRow();
+ fillAvatarAppearanceRow(row, user, appearance);
+ aap.Rows.Add(row);
+ // m_log.Debug("[USER DB]: Syncing user database: " + ds.Tables["users"].Rows.Count + " users stored");
+ // save changes off to disk
+ daa.Update(ds, "avatarappearance");
+ }
+ else
+ {
+ m_log.Debug("[USER DB]: Updating UserAppearance For: " + user.ToString());
+ fillAvatarAppearanceRow(row, user, appearance);
+ daa.Update(ds, "avatarappearance");
+ }
+ }
}
///
@@ -784,6 +889,55 @@ namespace OpenSim.Data.SQLite
return ua;
}
+ ///
+ /// Create the "avatarappearance" table
+ ///
+ /// Data Table
+ private static DataTable createAvatarAppearanceTable()
+ {
+ DataTable aa = new DataTable("avatarappearance");
+ // table contains user appearance items
+
+ SQLiteUtil.createCol(aa, "Owner", typeof(String));
+ SQLiteUtil.createCol(aa, "BodyItem", typeof(String));
+ SQLiteUtil.createCol(aa, "BodyAsset", typeof(String));
+ SQLiteUtil.createCol(aa, "SkinItem", typeof(String));
+ SQLiteUtil.createCol(aa, "SkinAsset", typeof(String));
+ SQLiteUtil.createCol(aa, "HairItem", typeof(String));
+ SQLiteUtil.createCol(aa, "HairAsset", typeof(String));
+ SQLiteUtil.createCol(aa, "EyesItem", typeof(String));
+ SQLiteUtil.createCol(aa, "EyesAsset", typeof(String));
+ SQLiteUtil.createCol(aa, "ShirtItem", typeof(String));
+ SQLiteUtil.createCol(aa, "ShirtAsset", typeof(String));
+ SQLiteUtil.createCol(aa, "PantsItem", typeof(String));
+ SQLiteUtil.createCol(aa, "PantsAsset", typeof(String));
+ SQLiteUtil.createCol(aa, "ShoesItem", typeof(String));
+ SQLiteUtil.createCol(aa, "ShoesAsset", typeof(String));
+ SQLiteUtil.createCol(aa, "SocksItem", typeof(String));
+ SQLiteUtil.createCol(aa, "SocksAsset", typeof(String));
+ SQLiteUtil.createCol(aa, "JacketItem", typeof(String));
+ SQLiteUtil.createCol(aa, "JacketAsset", typeof(String));
+ SQLiteUtil.createCol(aa, "GlovesItem", typeof(String));
+ SQLiteUtil.createCol(aa, "GlovesAsset", typeof(String));
+ SQLiteUtil.createCol(aa, "UnderShirtItem", typeof(String));
+ SQLiteUtil.createCol(aa, "UnderShirtAsset", typeof(String));
+ SQLiteUtil.createCol(aa, "UnderPantsItem", typeof(String));
+ SQLiteUtil.createCol(aa, "UnderPantsAsset", typeof(String));
+ SQLiteUtil.createCol(aa, "SkirtItem", typeof(String));
+ SQLiteUtil.createCol(aa, "SkirtAsset", typeof(String));
+
+ // Used Base64String because for some reason it wont accept using Byte[] (which works in Region date)
+ SQLiteUtil.createCol(aa, "Texture", typeof (String));
+ SQLiteUtil.createCol(aa, "VisualParams", typeof (String));
+
+ SQLiteUtil.createCol(aa, "Serial", typeof(Int32));
+ SQLiteUtil.createCol(aa, "AvatarHeight", typeof(Double));
+
+ aa.PrimaryKey = new DataColumn[] { aa.Columns["Owner"] };
+
+ return aa;
+ }
+
/***********************************************************************
*
* Convert between ADO.NET <=> OpenSim Objects
@@ -906,6 +1060,58 @@ namespace OpenSim.Data.SQLite
///
///
///
+ ///
+ private void fillAvatarAppearanceRow(DataRow row, UUID user, AvatarAppearance appearance)
+ {
+ row["Owner"] = Util.ToRawUuidString(user);
+ row["BodyItem"] = appearance.BodyItem.ToString();
+ row["BodyAsset"] = appearance.BodyAsset.ToString();
+ row["SkinItem"] = appearance.SkinItem.ToString();
+ row["SkinAsset"] = appearance.SkinAsset.ToString();
+ row["HairItem"] = appearance.HairItem.ToString();
+ row["HairAsset"] = appearance.HairAsset.ToString();
+ row["EyesItem"] = appearance.EyesItem.ToString();
+ row["EyesAsset"] = appearance.EyesAsset.ToString();
+ row["ShirtItem"] = appearance.ShirtItem.ToString();
+ row["ShirtAsset"] = appearance.ShirtAsset.ToString();
+ row["PantsItem"] = appearance.PantsItem.ToString();
+ row["PantsAsset"] = appearance.PantsAsset.ToString();
+ row["ShoesItem"] = appearance.ShoesItem.ToString();
+ row["ShoesAsset"] = appearance.ShoesAsset.ToString();
+ row["SocksItem"] = appearance.SocksItem.ToString();
+ row["SocksAsset"] = appearance.SocksAsset.ToString();
+ row["JacketItem"] = appearance.JacketItem.ToString();
+ row["JacketAsset"] = appearance.JacketAsset.ToString();
+ row["GlovesItem"] = appearance.GlovesItem.ToString();
+ row["GlovesAsset"] = appearance.GlovesAsset.ToString();
+ row["UnderShirtItem"] = appearance.UnderShirtItem.ToString();
+ row["UnderShirtAsset"] = appearance.UnderShirtAsset.ToString();
+ row["UnderPantsItem"] = appearance.UnderPantsItem.ToString();
+ row["UnderPantsAsset"] = appearance.UnderPantsAsset.ToString();
+ row["SkirtItem"] = appearance.SkirtItem.ToString();
+ row["SkirtAsset"] = appearance.SkirtAsset.ToString();
+
+ // Used Base64String because for some reason it wont accept using Byte[] (which works in Region date)
+ row["Texture"] = Convert.ToBase64String(appearance.Texture.GetBytes());
+ row["VisualParams"] = Convert.ToBase64String(appearance.VisualParams);
+
+ row["Serial"] = appearance.Serial;
+ row["AvatarHeight"] = appearance.AvatarHeight;
+
+ // ADO.NET doesn't handle NULL very well
+ foreach (DataColumn col in ds.Tables["avatarappearance"].Columns)
+ {
+ if (row[col] == null)
+ {
+ row[col] = String.Empty;
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
///
private static UserAgentData buildUserAgent(DataRow row)
{
@@ -996,7 +1202,7 @@ namespace OpenSim.Data.SQLite
{
da.InsertCommand = SQLiteUtil.createInsertCommand( "useragents", ds.Tables["useragents"]);
da.InsertCommand.Connection = conn;
-
+
da.UpdateCommand = SQLiteUtil.createUpdateCommand( "useragents", "UUID=:UUID", ds.Tables["useragents"]);
da.UpdateCommand.Connection = conn;
@@ -1027,6 +1233,26 @@ namespace OpenSim.Data.SQLite
}
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void setupAvatarAppearanceCommands(SqliteDataAdapter daa, SqliteConnection conn)
+ {
+ daa.InsertCommand = SQLiteUtil.createInsertCommand("avatarappearance", ds.Tables["avatarappearance"]);
+ daa.InsertCommand.Connection = conn;
+
+ daa.UpdateCommand = SQLiteUtil.createUpdateCommand("avatarappearance", "Owner=:Owner", ds.Tables["avatarappearance"]);
+ daa.UpdateCommand.Connection = conn;
+
+ SqliteCommand delete = new SqliteCommand("delete from avatarappearance where Owner=:Owner");
+ delete.Parameters.Add(SQLiteUtil.createSqliteParameter("Owner", typeof(String)));
+ delete.Connection = conn;
+ daa.DeleteCommand = delete;
+ }
+
+
override public void ResetAttachments(UUID userID)
{
}
--
cgit v1.1