diff --git a/README.md b/README.md
deleted file mode 100644
index 11b6a19..0000000
--- a/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# RegionImages
-
diff --git a/prebuild.xml b/prebuild.xml
new file mode 100644
index 0000000..4b291a6
--- /dev/null
+++ b/prebuild.xml
@@ -0,0 +1,44 @@
+
+
+
+
+ ../../bin/
+ true
+
+
+
+
+ ../../bin/
+ true
+
+
+
+ ../../bin/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/GetRegionTextures.cs b/src/GetRegionTextures.cs
new file mode 100644
index 0000000..afb6666
--- /dev/null
+++ b/src/GetRegionTextures.cs
@@ -0,0 +1,167 @@
+using MySql.Data.MySqlClient;
+using Nini.Config;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Services.Connectors;
+using OpenSim.Services.Interfaces;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+using static OpenMetaverse.Primitive;
+
+namespace GetRegionTextures
+{
+ class GetRegionTextures
+ {
+ private static MySqlConnection m_mySQLConnection = null;
+ private static String m_assetURL = "http://172.21.0.150:5738/assets/";
+
+ private static List m_assets = new List();
+
+ private static List getAllScenePrims(String regionID)
+ {
+ List returnData = new List();
+
+ MySqlCommand _mysqlCommand = m_mySQLConnection.CreateCommand();
+ _mysqlCommand.CommandTimeout = int.MaxValue;
+ _mysqlCommand.CommandText = "SELECT prims.Name,prims.UUID,primshapes.Texture FROM prims LEFT JOIN primshapes ON prims.UUID = primshapes.UUID WHERE RegionUUID = ?RegionUUID";
+ _mysqlCommand.Parameters.AddWithValue("RegionUUID", regionID);
+
+ MySqlDataReader _commandReader = _mysqlCommand.ExecuteReader();
+
+ while (_commandReader.Read())
+ returnData.Add(new MySQLPrimObject(_commandReader.GetString(0), _commandReader.GetString(1), (byte[])_commandReader["Texture"]));
+
+ _commandReader.Close();
+
+ return returnData;
+ }
+
+ private static List getAllRegionIDsFromStorage()
+ {
+ List returnData = new List();
+
+ MySqlCommand _mysqlCommand = m_mySQLConnection.CreateCommand();
+ _mysqlCommand.CommandTimeout = int.MaxValue;
+ _mysqlCommand.CommandText = "SELECT RegionUUID FROM terrain";
+
+ MySqlDataReader _commandReader = _mysqlCommand.ExecuteReader();
+
+ while (_commandReader.Read())
+ returnData.Add(_commandReader.GetString(0));
+
+ _commandReader.Close();
+
+ return returnData;
+ }
+
+
+ static void Main(string[] args)
+ {
+ if (!File.Exists("config-include/GridCommon.ini"))
+ return;
+
+ IConfigSource source = new IniConfigSource("config-include/GridCommon.ini");
+
+ if (source.Configs["DatabaseService"] == null)
+ return;
+
+ if (source.Configs["DatabaseService"].GetString("ConnectionString", null) == null)
+ return;
+
+ m_mySQLConnection = new MySqlConnection(source.Configs["DatabaseService"].GetString("ConnectionString", null));
+ m_mySQLConnection.Open();
+
+ if (!Directory.Exists("RegionData"))
+ Directory.CreateDirectory("RegionData");
+
+ List allRegionIDs = getAllRegionIDsFromStorage();
+
+ foreach(String regionID in allRegionIDs)
+ {
+ Console.WriteLine("Start with region '" + regionID + "'");
+
+ if (!Directory.Exists("RegionData/" + regionID))
+ Directory.CreateDirectory("RegionData/" + regionID);
+
+ if (!Directory.Exists("RegionData/assets"))
+ Directory.CreateDirectory("RegionData/assets");
+
+ if (!Directory.Exists("RegionData/" + regionID + "/images"))
+ Directory.CreateDirectory("RegionData/" + regionID + "/images");
+
+ List prims = getAllScenePrims(regionID);
+
+ int primCounter = 0;
+ foreach(MySQLPrimObject prim in prims)
+ {
+ Console.WriteLine(" ["+ ++primCounter + " / "+ prims .Count+ "]Start with scene object '" + prim.Name + "'");
+ Primitive.TextureEntry textureEntry = new Primitive.TextureEntry(prim.RawTextueData, 0, prim.RawTextueData.Length);
+
+ foreach (TextureEntryFace faceEntry in textureEntry.FaceTextures)
+ {
+ if (faceEntry != null)
+ {
+ if (faceEntry.TextureID != UUID.Zero)
+ {
+ prim.Texture.Add(faceEntry.TextureID);
+ Console.WriteLine(" Found texture '" + faceEntry.TextureID + "'");
+
+ if (!m_assets.Contains(faceEntry.TextureID))
+ m_assets.Add(faceEntry.TextureID);
+ }
+ }
+ }
+ }
+
+ //Create CSV
+ List entrys = new List();
+ foreach (MySQLPrimObject prim in prims)
+ {
+ String newEntry = prim.Name + ";" + prim.ID.ToString() + ";";
+
+ foreach (UUID texturID in prim.Texture)
+ newEntry += texturID.ToString() + ";";
+
+ entrys.Add(newEntry);
+ }
+
+ File.WriteAllLines("RegionData/" + regionID + "/result.csv", entrys.ToArray());
+
+ //Start Asset Download
+ using (WebClient assetHTTPClient = new WebClient())
+ {
+ int downloadCounter = 0;
+
+ foreach(UUID assetID in m_assets)
+ {
+ try
+ {
+ Console.WriteLine("[" + ++downloadCounter + " / " + m_assets.Count + "] Download asset " + assetID.ToString());
+ if(!File.Exists("RegionData/assets/" + assetID.ToString() + ".jpeg2000"))
+ assetHTTPClient.DownloadFile(m_assetURL + assetID.ToString() + "/data", "RegionData/assets/" + assetID.ToString() + ".jpeg2000");
+
+ if (!File.Exists("RegionData/" + regionID + "/images/" + assetID.ToString() + ".png"))
+ {
+ Process process = new Process();
+ process.StartInfo.FileName = "ffmpeg.exe";
+ process.StartInfo.Arguments = "-i RegionData/assets/" + assetID.ToString() + ".jpeg2000 RegionData/" + regionID + "/images/" + assetID.ToString() + ".png";
+ process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ process.Start();
+ process.WaitForExit();
+ }
+ }catch(Exception error)
+ {
+ Console.WriteLine("[" + downloadCounter + " / " + m_assets.Count + "] Download failed for asset " + assetID.ToString() + ": " + error.Message);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/IDTools.cs b/src/IDTools.cs
new file mode 100644
index 0000000..2a62152
--- /dev/null
+++ b/src/IDTools.cs
@@ -0,0 +1,168 @@
+using OpenMetaverse;
+using OpenMetaverse.Assets;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace GetRegionTextures
+{
+ class IDTools
+ {
+ public static void addToList(ref List _list, List _input)
+ {
+ foreach (String _entry in _input)
+ {
+ addToList(ref _list, _entry);
+ }
+ }
+
+ public static void addToList(ref List _list, List _input)
+ {
+ foreach (TaskInventoryItemElement _entry in _input)
+ {
+ addToList(ref _list, _entry.AssetID.UUID);
+ }
+ }
+
+ public static void addToList(ref List _list, String _input)
+ {
+ if (_input == "00000000-0000-0000-0000-000000000000")
+ return;
+
+ if (_input == null)
+ return;
+
+ if (!_list.Contains(_input))
+ _list.Add(_input);
+ }
+
+ public static List getUUIDListFromTexturEntry(String _base64)
+ {
+ List _ausgabe = new List();
+ try
+ {
+ PrimObject obj = new PrimObject();
+
+ byte[] teData = Convert.FromBase64String(_base64);
+ obj.Textures = new Primitive.TextureEntry(teData, 0, teData.Length);
+
+ foreach (Primitive.TextureEntryFace _face in obj.Textures.FaceTextures)
+ {
+ if (_face != null)
+ {
+ _ausgabe.Add(_face.TextureID.ToString());
+ }
+ }
+ }
+ catch(Exception error)
+ {
+ Console.WriteLine("Cant decode textur data: " + error.Message);
+ }
+ return _ausgabe;
+ }
+
+ public static List getUUIDListFromString(String _xml)
+ {
+ AppDomain.CurrentDomain.SetData("REGEX_DEFAULT_MATCH_TIMEOUT", TimeSpan.FromSeconds(10));
+ List _ausgabe = new List();
+ String _regex = @"[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}";
+
+ try
+ {
+ Regex _suche = new Regex(_regex);
+ MatchCollection _funde = _suche.Matches(_xml);
+
+ foreach (Match _f in _funde)
+ {
+ String _value = _f.Value.ToUpper().Trim();
+ if (_value.Length < 75 && _value.Length > 10)
+ {
+ if (!_ausgabe.Contains(_value))
+ {
+ _ausgabe.Add(_value);
+ }
+ }
+ }
+ }
+ catch (Exception _e)
+ {
+ Console.WriteLine(_e.ToString());
+ Thread.Sleep(1000);
+ }
+
+ return _ausgabe;
+ }
+
+
+ public static List getIDListFromSceneObjectGroup(SceneObjectGroup _group)
+ {
+ List _returnList = new List();
+
+ if (_group.RootPart.SceneObjectPart.CollisionSound != null)
+ {
+ if (_group.RootPart.SceneObjectPart.CollisionSound.UUID != null)
+ addToList(ref _returnList, _group.RootPart.SceneObjectPart.CollisionSound.UUID);
+ }
+
+ if (_group.RootPart.SceneObjectPart.SoundID != null)
+ {
+ if (_group.RootPart.SceneObjectPart.SoundID.UUID != null)
+ addToList(ref _returnList, _group.RootPart.SceneObjectPart.SoundID.UUID);
+ }
+
+ if (_group.RootPart.SceneObjectPart.Shape.SculptTexture != null)
+ {
+ if (_group.RootPart.SceneObjectPart.Shape.SculptTexture.UUID != null)
+ addToList(ref _returnList, _group.RootPart.SceneObjectPart.Shape.SculptTexture.UUID);
+ }
+
+ if (_group.RootPart.SceneObjectPart.Shape != null)
+ {
+ if (_group.RootPart.SceneObjectPart.Shape.TextureEntry != null)
+ addToList(ref _returnList, getUUIDListFromTexturEntry(_group.RootPart.SceneObjectPart.Shape.TextureEntry));
+ }
+
+ if (_group.RootPart.SceneObjectPart.TaskInventory != null)
+ addToList(ref _returnList, _group.RootPart.SceneObjectPart.TaskInventory);
+
+ if (_group.OtherParts != null)
+ {
+ foreach (PartElement _sope in _group.OtherParts)
+ {
+ if (_sope.SceneObjectPart.CollisionSound != null)
+ {
+ if (_sope.SceneObjectPart.CollisionSound.UUID != null)
+ addToList(ref _returnList, _sope.SceneObjectPart.CollisionSound.UUID);
+ }
+
+ if (_sope.SceneObjectPart.SoundID != null)
+ {
+ if (_sope.SceneObjectPart.SoundID.UUID != null)
+ addToList(ref _returnList, _sope.SceneObjectPart.SoundID.UUID);
+ }
+
+ if (_sope.SceneObjectPart.Shape.SculptTexture != null)
+ {
+ if (_sope.SceneObjectPart.Shape.SculptTexture.UUID != null)
+ addToList(ref _returnList, _sope.SceneObjectPart.Shape.SculptTexture.UUID);
+ }
+
+ if (_sope.SceneObjectPart.Shape != null)
+ {
+ if (_sope.SceneObjectPart.Shape.TextureEntry != null)
+ addToList(ref _returnList, getUUIDListFromTexturEntry(_sope.SceneObjectPart.Shape.TextureEntry));
+ }
+
+ if (_sope.SceneObjectPart.TaskInventory != null)
+ addToList(ref _returnList, (_sope.SceneObjectPart.TaskInventory));
+ }
+ }
+
+ return _returnList;
+ }
+ }
+}
diff --git a/src/MySQLPrimObject.cs b/src/MySQLPrimObject.cs
new file mode 100644
index 0000000..7980270
--- /dev/null
+++ b/src/MySQLPrimObject.cs
@@ -0,0 +1,30 @@
+using OpenMetaverse;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace GetRegionTextures
+{
+ class MySQLPrimObject
+ {
+ public String Name = null;
+ public String ID = null;
+ public byte[] RawTextueData = null;
+ public List Texture = new List();
+
+ public MySQLPrimObject(String name, String id)
+ {
+ Name = name;
+ ID = id;
+ }
+
+ public MySQLPrimObject(String name, String id, byte[] texturedata)
+ {
+ Name = name;
+ ID = id;
+ RawTextueData = texturedata;
+ }
+ }
+}
diff --git a/src/SceneObjectGroup.cs b/src/SceneObjectGroup.cs
new file mode 100644
index 0000000..215892a
--- /dev/null
+++ b/src/SceneObjectGroup.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Serialization;
+
+namespace GetRegionTextures
+{
+ [Serializable()]
+ [XmlRoot]
+ public class SceneObjectGroup
+ {
+ [XmlElement("RootPart", typeof(RootPartElement))]
+ public RootPartElement RootPart { get; set; }
+
+ [XmlArray("OtherParts")]
+ [XmlArrayItem("Part")]
+ public PartElement[] OtherParts { get; set; }
+ }
+
+ [XmlRoot]
+ public class RootPartElement
+ {
+ [XmlElement("SceneObjectPart", typeof(SceneObjectPartElement))]
+ public SceneObjectPartElement SceneObjectPart { get; set; }
+ }
+
+ [XmlRoot]
+ public class PartElement
+ {
+ [XmlElement("SceneObjectPart", typeof(SceneObjectPartElement))]
+ public SceneObjectPartElement SceneObjectPart { get; set; }
+ }
+
+ [XmlRoot]
+ public class SceneObjectPartElement
+ {
+ [XmlElement("Name", typeof(String))]
+ public String Name { get; set; }
+
+ [XmlElement("Shape", typeof(ShapeElement))]
+ public ShapeElement Shape { get; set; }
+
+ [XmlElement("CollisionSound", typeof(UUIDEntry))]
+ public UUIDEntry CollisionSound { get; set; }
+
+ [XmlElement("SoundID", typeof(UUIDEntry))]
+ public UUIDEntry SoundID { get; set; }
+
+ [XmlArray("TaskInventory")]
+ [XmlArrayItem("TaskInventoryItem")]
+ public List TaskInventory { get; set; }
+ }
+
+ [XmlRoot]
+ public class TaskInventoryItemElement
+ {
+ [XmlElement("Name", typeof(String))]
+ public String Name { get; set; }
+
+ [XmlElement("AssetID", typeof(UUIDEntry))]
+ public UUIDEntry AssetID { get; set; }
+ }
+
+ [XmlRoot]
+ public class ShapeElement
+ {
+ [XmlElement("TextureEntry", typeof(String))]
+ public String TextureEntry { get; set; }
+
+ [XmlElement("ExtraParams", typeof(String))]
+ public String ExtraParams { get; set; }
+
+ [XmlElement("SculptTexture", typeof(UUIDEntry))]
+ public UUIDEntry SculptTexture { get; set; }
+ }
+
+ [XmlRoot]
+ public class UUIDEntry
+ {
+ [XmlElement("UUID", typeof(String))]
+ public String UUID { get; set; }
+ }
+}