<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://opensimulator.org/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://opensimulator.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Rknop</id>
		<title>OpenSimulator - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://opensimulator.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Rknop"/>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Special:Contributions/Rknop"/>
		<updated>2026-05-15T17:13:13Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.19.9</generator>

	<entry>
		<id>http://opensimulator.org/wiki/Dependencies</id>
		<title>Dependencies</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Dependencies"/>
				<updated>2013-04-10T03:38:05Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* Linux and Mac OSX */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Quicklinks}}&lt;br /&gt;
&lt;br /&gt;
In addition to the OpenSimulator code itself, certain other packages need to be installed on different platforms in order to get OpenSimulator binaries to run. &lt;br /&gt;
&lt;br /&gt;
As well as the information on this page (which should be expanded), you may find more information on dependencies in [[Build Instructions]] though this will also contain dependencies required only for building. This are also more hints in [[Troubleshooting]].&lt;br /&gt;
&lt;br /&gt;
After solving dependencies, you may need to configure the firewall installed in your system by default so that the viewers outside can access to OpenSimulator inside it. See [[Firewall Settings]] for more informations.&lt;br /&gt;
&lt;br /&gt;
[[NAT Loopback Routers]] Router and Nat Loopback Information to help you configure your Router / Modem.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Windows =&lt;br /&gt;
&lt;br /&gt;
OpenSimulator now requires '''.NET Framework 3.5''' when running under Windows.  If you run OpenSimulator on '''Windows 7''' or '''Windows Server 2008 R2''', it is already bundled so you can run OpenSimulator 0.7.1 out-of-the-box. On '''Windows Vista''', '''Windows Server 2008''', '''Windows Server 2003''' or '''Windows XP''', you'll need to upgrade it to 3.5(or later, but NET Framework 4.0 not officially supported by OpenSimulator yet), downloading from [http://msdn.microsoft.com/en-us/netframework/cc378097 Microsoft .NET Framework Download Page@.NET Framework Developer Center]. Note that prior versions of Windows(ex. NT or 2000) are NOT supported.&lt;br /&gt;
&lt;br /&gt;
If you run on Windows XP ensure it is updated to at least Service Pack 2 (SP2). &lt;br /&gt;
&lt;br /&gt;
Double-click or execute on command prompt:&lt;br /&gt;
*32-bit version of Windows: '''OpenSim.exe'''&lt;br /&gt;
*64-bit version of Windows: '''OpenSim.32BitLaunch.exe'''&lt;br /&gt;
Depending on your installation, you may have to run the program as administrator(right click -&amp;gt; 'Run as administrator'). It will pop up a window asking permission, select &amp;quot;Allow&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Linux and Mac OSX =&lt;br /&gt;
&lt;br /&gt;
OpenSimulator requires Mono 2.4.3 or later. '''WARNING:''' OpenSimulator is known to have significant performance and scalability problems with Mono versions 2.8.x, 2.10.0 and 2.10.1. As of Mono 2.10.2, the scalability problems appear to have been resolved. Mono 2.6.x also appears to be fine, though the mono VM does seem to have some issues (crashing with a native stacktrace) on simulators running many regions or lots of users/prims.  Therefore you should either use Mono 2.6.x or Mono 2.10.2 or later. You can also use Mono 2.4.3, but it is fairly old now.&lt;br /&gt;
&lt;br /&gt;
There are also reports that anything between Mono 2.10.9 and 3.0.3 has major issues; 3.0.7 is supposedly OK.&lt;br /&gt;
&lt;br /&gt;
To run OpenSimulator with mono, execute &lt;br /&gt;
&lt;br /&gt;
 mono --debug OpenSim.exe&lt;br /&gt;
&lt;br /&gt;
This is the same for 32 bit and 64 bit systems.  The --debug switch isn't strictly necessary, but it will insert line numbers for stack traces if you ever need to make a bug report, and the overhead of using it is very small.&lt;br /&gt;
&lt;br /&gt;
== Ubuntu ==&lt;br /&gt;
&lt;br /&gt;
 sudo apt-get install mono-complete&lt;br /&gt;
&lt;br /&gt;
{{anchor|CentOS}}{{anchor|RedHat}}{{anchor|RHEL}}{{anchor|Fedora}}&lt;br /&gt;
== RHEL, Fedora, CentOS or Any Other RedHat-based Distributions ==&lt;br /&gt;
&lt;br /&gt;
First, run &amp;quot;yum info mono-core&amp;quot; to see the version of the mono packages in the core repository for your distribution. If it shows '''2.4.3''' or later, proceed to [[#Installing from Core Repository]]. If not, skip to [[#Installing from Mono Repository]]. Note that the current version you can get from yum repository for some distributions is lower than requirement (ex. '''1.2.4''' on CentOS). Unlike Ubuntu, RedHat-based distributions should be always conservative, therefore it is natural that they don't so often update their repository. What you can do to manage this problem is to add an extra repository for mono.&lt;br /&gt;
&lt;br /&gt;
=== Installing from Core Repository ===&lt;br /&gt;
&lt;br /&gt;
Just type:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo yum install  mono-core mono-data-sqlite mono-extras libgdiplus&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
It will also install dependent modules. After that you can launch OpenSim.exe with mono out-of-the-box.&lt;br /&gt;
&lt;br /&gt;
=== Installing from Mono Repository ===&lt;br /&gt;
&lt;br /&gt;
This procedure is tested on CentOS 5.5 &amp;amp; 5.6 box with OpenSimulator 0.7.1.&lt;br /&gt;
&lt;br /&gt;
Go to yum config file folder and create new one for mono.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /etc/yum.repos.d&lt;br /&gt;
sudo vi mono.repo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then in mono.repo :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[mono]&lt;br /&gt;
name = novell-mono&lt;br /&gt;
baseurl=http://ftp.novell.com/pub/mono/download-stable/RHEL_5/&lt;br /&gt;
enabled=1&lt;br /&gt;
gpgcheck=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can yum install the later version of mono from this repository. Additional note that make sure all of mono packages are i386(not IA64 build). If your box is 32bit, don't care and you can even install properly without &amp;quot;.i386&amp;quot; suffix.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo yum install mono-addon-core.i386 mono-addon-data.i386 mono-addon-data-sqlite.i386  \&lt;br /&gt;
      mono-addon-extras.i386 mono-addon-web.i386 mono-addon-winforms.i386 mono-addon-libgdiplus0.i386&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yum will install mono into /opt/novell/mono, so you can create a symbolic link to /usr/bin :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo ln -s /opt/novell/mono/bin/mono /usr/bin/mono&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After that, you should be able to launch OpenSim.exe without any errors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Debian ==&lt;br /&gt;
&lt;br /&gt;
Debian 4 (Etch) is no longer supported by debian.org. Update at least to 5 (Lenny) before running OpenSimulator. See [http://www.debian.org/releases/lenny/i386/release-notes/ch-upgrading.html Upgrades from previous release@debian.org] for detail.&lt;br /&gt;
&lt;br /&gt;
For Debian 5 (Lenny) or later, just Type:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo aptitude install mono-gmcs libmono-microsoft8.0-cil \&lt;br /&gt;
    libmono-system-runtime2.0-cil libmono-i18n2.0-cil&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can even use apt-get instead of aptitude. They both will also install dependent packages.&lt;br /&gt;
&lt;br /&gt;
Tested on Debian 5(Lenny), Debian 6(Squeeze) and Debian 7(Wheezy) unstable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== openSuSE ==&lt;br /&gt;
&lt;br /&gt;
Just type:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo zypper install  mono-core mono-data-sqlite mono-extras libgdiplus&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
It will also install dependent modules. After that you can launch OpenSim.exe with mono out-of-the-box.&lt;br /&gt;
&lt;br /&gt;
== Mac OS X ==&lt;br /&gt;
&lt;br /&gt;
All you have to do is to fetch Mono '''Runtime''' package from [http://www.go-mono.com/mono-downloads/download.html Mono Download Page] and install it.  Alternatively, you can install mono with [http://mxcl.github.com/homebrew/ homebrew] with:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
brew install mono&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using OS X 10.4, you should also install X11 from the OS X install CDs. In OS X 10.5, this is not required.&lt;br /&gt;
&lt;br /&gt;
= Locales and Regional Settings =&lt;br /&gt;
OpenSimulator will only work properly when you run it with an English locale or regional setting. With other settings than English, you are likely to see a variety of issues, ranging from misbehaving scripts to crashes.&lt;br /&gt;
&lt;br /&gt;
== Linux ==&lt;br /&gt;
In Linux, you can easily use the standard &amp;quot;C&amp;quot; locale just for running OpenSim.exe, as explained in [[Troubleshooting#ScriptEngine Issues]]:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
env LANG=C mono OpenSim.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For information about changing your locale in a more general way, see [[Troubleshooting#Locales Issues]]&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
If you are not using an English regional setting in Windows by default, then there is not a solution as easy as for Linux, unfortunately. I did it with an additional user account that I created just for OpenSimulator in which I set the regional setting to &amp;quot;English (US)&amp;quot;. I run OpenSim.exe from my normal user account with &amp;quot;Run as...&amp;quot; (or check &amp;quot;Run with different credentials&amp;quot; in a shortcut's advanced properties) and specify the OpenSimulator account as the one to be used.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Additional Resources =&lt;br /&gt;
&lt;br /&gt;
OSGrid Technical Support Forum with many installation tutorials:&amp;amp;nbsp; [http://osgrid.org/forums/viewforum.php?f=14 osgrid.org/forums/viewforum.php] &lt;br /&gt;
&lt;br /&gt;
MONO&amp;amp;nbsp;Project:&amp;amp;nbsp; [http://www.mono-project.com/Main_Page www.mono-project.com/Main_Page]&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Codebase_overview</id>
		<title>Codebase overview</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Codebase_overview"/>
				<updated>2011-08-09T23:41:27Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* Codebase overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==Coding restrictions==&lt;br /&gt;
&lt;br /&gt;
Because OpenSim has to run on both Windows and Mono (usually on Linux or Mac), we are limited to the parts of .net that [http://en.wikipedia.org/wiki/Mono_(software) Mono] supports.&lt;br /&gt;
&lt;br /&gt;
==Codebase overview==&lt;br /&gt;
&lt;br /&gt;
(This is probably quite out of date.  On 2011-08-08, a few edits were made to bring pieces of it up to date, but the editor doesn't have enough of an overview in head to remove all the parts that aren't current.  Edits will continue.)&lt;br /&gt;
&lt;br /&gt;
OpenSim is already a fairly large and intricate project, so patience is required to start understanding it.&lt;br /&gt;
&lt;br /&gt;
At the top level, OpenSim code is broken up into seven sections.  There's also a bit more detail on the most significant packages within those sections.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim'''.  This contains the classes which launch the OpenSim region server and handle the console&lt;br /&gt;
** Startup&lt;br /&gt;
*** The Main() for &amp;lt;tt&amp;gt;OpenSim.exe&amp;lt;/tt&amp;gt; can be found in the file &amp;lt;tt&amp;gt;OpenSim/Region/Application/Application.cs&amp;lt;/tt&amp;gt;.  It does a bunch of configuration checks, but the meat of it is the instantiation of an '''OpenSim''' object, calling its Startup() method (which gets things rolling in separate threads), and then blocking the initial thread by prompting on the main console (using the Prompt() method MainConsole.Instance)&lt;br /&gt;
*** OpenSim.OpenSim.Startup() comes from an ancestor, OpenSim.Framework.Servers.BaseOpenSimServer; it calls StartupSpecific()&lt;br /&gt;
*** OpenSim.OpenSim.StartupSpecific() exists.  It creates a console, registers the region console commands, makes a couple of status stream handlers, runs startup commands if any are specified in config, and hooks up its WatchdogTimeoutHandler to Watchdog.  It then calls its base class' StartupSpecific(), and each base class calls ''its'' base class' StartupSpecific() (all the way back up to OpenSim.Framework.Servers.BaseOpenSimServer.StartupSpecific()).&lt;br /&gt;
*** ancestor OpenSim.OpenSimBase starts up simulation and estate data services; creates a ModuleLoader (in field &amp;lt;tt&amp;gt;m_moduleLoader&amp;lt;/tt&amp;gt;); and loads plugins of type IApplicationPlugin at extension point (&amp;quot;/OpenSim/Startup&amp;quot;) (I have to admit to not fully knowing what that means...), and initializes each one of them.&lt;br /&gt;
*** ancestor OpenSim.Region.ClientStack.RegionApplicationBase starts up an http server in its StartupSpecific()&lt;br /&gt;
*** ancestor OpenSim.Framework.Servers.BaseOpenSimServer starts up (something to do with) the console in its StartupSpecific()&lt;br /&gt;
*** I have yet to figure out where in all of this the region heartbeat actually gets going....  It may actually be inside a Plugin (LoadRegionsPlugin)&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.ApplicationPlugins'''.  Each package is an individual application plugin - an application plugin is a modular piece of code that has an effect on the entire region server.  See [[RegionModules]] for more details or one of [http://justincc.wordpress.com/2008/05/08/opensim-tech-basics-my-god-its-full-of-modules/ justincc's blogposts] for a higher level overview (which should really be in this wiki).&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Data'''.  This is all the low level database manipulation stuff.  In here, you'll see packages for SQLite, MySQL and MSSQL (which tends to lag), as well as code for [http://www.hibernate.org/ NHibernate] which will hopefully reduce our reliance on manipulation code for specific databases.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Framework'''.  General framework code used by the rest of OpenSim which is felt to be not specific to a region.  &lt;br /&gt;
** ''OpenSim.Framework.Communications''.  Contains asset and inventory caching code (to cut down on communication with a remote asset or inventory service), and contains CAPS code, a Linden approach to splitting some aspects of the Second Life protocol into independent, secured services.  See a [http://mrtopf.de/blog/secondlife/slga-capabilities-explained-technical/ blog post] from Tao for more background on this.&lt;br /&gt;
** ''OpenSim.Framework.Servers''.  Contains generic server code, such as the base OpenSim server and http servers.&lt;br /&gt;
** ''OpenSim.Framework.Stats''.  Collects statistical information on OpenSim operations.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Server''': these are things that are part of the R.O.B.U.S.T. services, including grid servers, avatar servers, asset servers, inventory servers, and the like.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Region'''.  Contains most of the meaty code that it specifically concerned with region manipulation.&lt;br /&gt;
** ''OpenSim.Region.ClientStack.LindenUDP''.  The code necessary for communicating with clients using the Second Life protocol.&lt;br /&gt;
** ''OpenSim.Region.Communications.Local''.  Code used for communicating with non-region services (user, asset, grid, etc.) when OpenSim is running in standalone mode.&lt;br /&gt;
** ''OpenSim.Region.Communications.OGS1''.  Code for communicating with remote UGAI services using the Open Grid Services 1 protocol.&lt;br /&gt;
** ''OpenSim.Region.Environment''.  A large package containing both the vast majority of the region modules (categorized under modules) and the central scene manipulation code (under Scenes, appropriately enough).  Modules here do everything from handling region chat to loading and saving terrain.&lt;br /&gt;
** ''OpenSim.Region.Modules''.  More region module code.  Actually, I'm not too sure why these aren't in the OpenSim.Region.Environment package.&lt;br /&gt;
** ''OpenSim.Region.Physics''.  General physics framework code and plugins for specific engines (BulletX, ODE, etc).  The ODE code is by far the most reliable and stable.&lt;br /&gt;
** ''OpenSim.Region.ScriptEngine''.  Script engine code that powers the scripts run within OpenSim.  Currently there are two engines, the classic [[DotNetEngine]] and the relatively new [[XEngine]].&lt;br /&gt;
** ''[[Overview of How RegionsWork|OpenSim.Region.Framework.Scenes.Scene]]'' is the &amp;quot;heart&amp;quot; of OpenSim functionality.  It has the &amp;quot;main loop&amp;quot; for a region, in the method &amp;lt;tt&amp;gt;Update()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Tests'''.  Test code.  Really, we don't actually have much of this (yet).&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Codebase_overview</id>
		<title>Codebase overview</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Codebase_overview"/>
				<updated>2011-08-09T22:50:03Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* Codebase overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==Coding restrictions==&lt;br /&gt;
&lt;br /&gt;
Because OpenSim has to run on both Windows and Mono (usually on Linux or Mac), we are limited to the parts of .net that [http://en.wikipedia.org/wiki/Mono_(software) Mono] supports.&lt;br /&gt;
&lt;br /&gt;
==Codebase overview==&lt;br /&gt;
&lt;br /&gt;
(This is probably quite out of date.  On 2011-08-08, a few edits were made to bring pieces of it up to date, but the editor doesn't have enough of an overview in head to remove all the parts that aren't current.  Edits will continue.)&lt;br /&gt;
&lt;br /&gt;
OpenSim is already a fairly large and intricate project, so patience is required to start understanding it.&lt;br /&gt;
&lt;br /&gt;
At the top level, OpenSim code is broken up into seven sections.  There's also a bit more detail on the most significant packages within those sections.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim'''.  This contains the classes which launch the OpenSim region server and handle the console&lt;br /&gt;
** Startup&lt;br /&gt;
*** The Main() for &amp;lt;tt&amp;gt;OpenSim.exe&amp;lt;/tt&amp;gt; can be found in the file &amp;lt;tt&amp;gt;OpenSim/Region/Application/Application.cs&amp;lt;/tt&amp;gt;.  It does a bunch of configuration checks, but the meat of it is the instantiation of an '''OpenSim''' object, calling its Startup() method (which gets things rolling in separate threads), and then blocking the initial thread by prompting on the main console (using the Prompt() method MainConsole.Instance)&lt;br /&gt;
*** OpenSim.OpenSim.Startup() comes from an ancestor, OpenSim.Framework.Servers.BaseOpenSimServer; it calls StartupSpecific()&lt;br /&gt;
*** OpenSim.OpenSim.StartupSpecific() exists, but much of the meat of really getting a region running is found in the base class' method OpenSim.OpenSimBase.StartupSpecific() (and in other versions of StartupSpecific() on up the inheritance hierarchy).&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.ApplicationPlugins'''.  Each package is an individual application plugin - an application plugin is a modular piece of code that has an effect on the entire region server.  See [[RegionModules]] for more details or one of [http://justincc.wordpress.com/2008/05/08/opensim-tech-basics-my-god-its-full-of-modules/ justincc's blogposts] for a higher level overview (which should really be in this wiki).&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Data'''.  This is all the low level database manipulation stuff.  In here, you'll see packages for SQLite, MySQL and MSSQL (which tends to lag), as well as code for [http://www.hibernate.org/ NHibernate] which will hopefully reduce our reliance on manipulation code for specific databases.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Framework'''.  General framework code used by the rest of OpenSim which is felt to be not specific to a region.  &lt;br /&gt;
** ''OpenSim.Framework.Communications''.  Contains asset and inventory caching code (to cut down on communication with a remote asset or inventory service), and contains CAPS code, a Linden approach to splitting some aspects of the Second Life protocol into independent, secured services.  See a [http://mrtopf.de/blog/secondlife/slga-capabilities-explained-technical/ blog post] from Tao for more background on this.&lt;br /&gt;
** ''OpenSim.Framework.Servers''.  Contains generic server code, such as the base OpenSim server and http servers.&lt;br /&gt;
** ''OpenSim.Framework.Stats''.  Collects statistical information on OpenSim operations.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Server''': these are things that are part of the R.O.B.U.S.T. services, including grid servers, avatar servers, asset servers, inventory servers, and the like.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Region'''.  Contains most of the meaty code that it specifically concerned with region manipulation.&lt;br /&gt;
** ''OpenSim.Region.ClientStack.LindenUDP''.  The code necessary for communicating with clients using the Second Life protocol.&lt;br /&gt;
** ''OpenSim.Region.Communications.Local''.  Code used for communicating with non-region services (user, asset, grid, etc.) when OpenSim is running in standalone mode.&lt;br /&gt;
** ''OpenSim.Region.Communications.OGS1''.  Code for communicating with remote UGAI services using the Open Grid Services 1 protocol.&lt;br /&gt;
** ''OpenSim.Region.Environment''.  A large package containing both the vast majority of the region modules (categorized under modules) and the central scene manipulation code (under Scenes, appropriately enough).  Modules here do everything from handling region chat to loading and saving terrain.&lt;br /&gt;
** ''OpenSim.Region.Modules''.  More region module code.  Actually, I'm not too sure why these aren't in the OpenSim.Region.Environment package.&lt;br /&gt;
** ''OpenSim.Region.Physics''.  General physics framework code and plugins for specific engines (BulletX, ODE, etc).  The ODE code is by far the most reliable and stable.&lt;br /&gt;
** ''OpenSim.Region.ScriptEngine''.  Script engine code that powers the scripts run within OpenSim.  Currently there are two engines, the classic [[DotNetEngine]] and the relatively new [[XEngine]].&lt;br /&gt;
** ''[[Overview of How RegionsWork|OpenSim.Region.Framework.Scenes.Scene]]'' is the &amp;quot;heart&amp;quot; of OpenSim functionality.  It has the &amp;quot;main loop&amp;quot; for a region, in the method &amp;lt;tt&amp;gt;Update()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Tests'''.  Test code.  Really, we don't actually have much of this (yet).&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Codebase_overview</id>
		<title>Codebase overview</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Codebase_overview"/>
				<updated>2011-08-09T22:49:31Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==Coding restrictions==&lt;br /&gt;
&lt;br /&gt;
Because OpenSim has to run on both Windows and Mono (usually on Linux or Mac), we are limited to the parts of .net that [http://en.wikipedia.org/wiki/Mono_(software) Mono] supports.&lt;br /&gt;
&lt;br /&gt;
==Codebase overview==&lt;br /&gt;
&lt;br /&gt;
(This is probably quite out of date.  On 2011-08-08, a few edits were made to bring pieces of it up to date, but the editor doesn't have enough of an overview in head to remove all the parts that aren't current.  Edits will continue.)&lt;br /&gt;
&lt;br /&gt;
OpenSim is already a fairly large and intricate project, so patience is required to start understanding it.&lt;br /&gt;
&lt;br /&gt;
At the top level, OpenSim code is broken up into seven sections.  There's also a bit more detail on the most significant packages within those sections.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim'''.  This contains the classes which launch the OpenSim region server and handle the console&lt;br /&gt;
** Startup&lt;br /&gt;
*** The Main() for &amp;lt;tt&amp;gt;OpenSim.exe&amp;lt;/tt&amp;gt; can be found in the file &amp;lt;tt&amp;gt;OpenSim/Region/Application/Application.cs&amp;lt;/tt&amp;gt;.  It does a bunch of configuration checks, but the meat of it is the instantiation of an '''OpenSim''' object, calling its Startup() method (which gets things rolling in separate threads), and then blocking the initial thread by prompting on the main console (using the Prompt() method MainConsole.Instance)&lt;br /&gt;
*** OpenSim.OpenSim.Startup() comes from an ancestor, OpenSim.Framework.Servers.BaseOpenSimServer; it calls StartupSpecific()&lt;br /&gt;
*** OpenSim.OpenSim.StartupSpecific() exists, but much of the meat of really getting a region running is found in the base class' method OpenSim.OpenSimBase.StartupSpecific() (and in other versions of StartupSpecific() on up the inheritance hierarchy).&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.ApplicationPlugins'''.  Each package is an individual application plugin - an application plugin is a modular piece of code that has an effect on the entire region server.  See [[RegionModules]] for more details or one of [http://justincc.wordpress.com/2008/05/08/opensim-tech-basics-my-god-its-full-of-modules/ justincc's blogposts] for a higher level overview (which should really be in this wiki).&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Data'''.  This is all the low level database manipulation stuff.  In here, you'll see packages for SQLite, MySQL and MSSQL (which tends to lag), as well as code for [http://www.hibernate.org/ NHibernate] which will hopefully reduce our reliance on manipulation code for specific databases.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Framework'''.  General framework code used by the rest of OpenSim which is felt to be not specific to a region.  &lt;br /&gt;
** ''OpenSim.Framework.Communications''.  Contains asset and inventory caching code (to cut down on communication with a remote asset or inventory service), and contains CAPS code, a Linden approach to splitting some aspects of the Second Life protocol into independent, secured services.  See a [http://mrtopf.de/blog/secondlife/slga-capabilities-explained-technical/ blog post] from Tao for more background on this.&lt;br /&gt;
** ''OpenSim.Framework.Servers''.  Contains generic server code, such as the base OpenSim server and http servers.&lt;br /&gt;
** ''OpenSim.Framework.Stats''.  Collects statistical information on OpenSim operations.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Server''': these are things that are part of the R.O.B.U.S.T. services, including grid servers, avatar servers, asset servers, inventory servers, and the like.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Region'''.  Contains most of the meaty code that it specifically concerned with region manipulation.&lt;br /&gt;
** ''OpenSim.Region.ClientStack.LindenUDP''.  The code necessary for communicating with clients using the Second Life protocol.&lt;br /&gt;
** ''OpenSim.Region.Communications.Local''.  Code used for communicating with non-region services (user, asset, grid, etc.) when OpenSim is running in standalone mode.&lt;br /&gt;
** ''OpenSim.Region.Communications.OGS1''.  Code for communicating with remote UGAI services using the Open Grid Services 1 protocol.&lt;br /&gt;
** ''OpenSim.Region.Environment''.  A large package containing both the vast majority of the region modules (categorized under modules) and the central scene manipulation code (under Scenes, appropriately enough).  Modules here do everything from handling region chat to loading and saving terrain.&lt;br /&gt;
** ''OpenSim.Region.Modules''.  More region module code.  Actually, I'm not too sure why these aren't in the OpenSim.Region.Environment package.&lt;br /&gt;
** ''OpenSim.Region.Physics''.  General physics framework code and plugins for specific engines (BulletX, ODE, etc).  The ODE code is by far the most reliable and stable.&lt;br /&gt;
** ''OpenSim.Region.ScriptEngine''.  Script engine code that powers the scripts run within OpenSim.  Currently there are two engines, the classic [[DotNetEngine]] and the relatively new [[XEngine]].&lt;br /&gt;
** ''[[Overview of How RegionsWork|OpenSim.Region.Framework.Scene.Scene]]'' is the &amp;quot;heart&amp;quot; of OpenSim functionality.  It has the &amp;quot;main loop&amp;quot; for a region, in the method &amp;lt;tt&amp;gt;Update()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Tests'''.  Test code.  Really, we don't actually have much of this (yet).&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Codebase_overview</id>
		<title>Codebase overview</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Codebase_overview"/>
				<updated>2011-08-09T22:43:23Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* Codebase overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==Coding restrictions==&lt;br /&gt;
&lt;br /&gt;
Because OpenSim has to run on both Windows and Mono (usually on Linux or Mac), we are limited to the parts of .net that [http://en.wikipedia.org/wiki/Mono_(software) Mono] supports.&lt;br /&gt;
&lt;br /&gt;
==Codebase overview==&lt;br /&gt;
&lt;br /&gt;
(This is probably quite out of date.  On 2011-08-08, a few edits were made to bring pieces of it up to date, but the editor doesn't have enough of an overview in head to remove all the parts that aren't current.  Edits will continue.)&lt;br /&gt;
&lt;br /&gt;
OpenSim is already a fairly large and intricate project, so patience is required to start understanding it.&lt;br /&gt;
&lt;br /&gt;
At the top level, OpenSim code is broken up into seven sections.  There's also a bit more detail on the most significant packages within those sections.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim'''.  This contains the classes which launch the OpenSim region server and handle the console&lt;br /&gt;
** The Main() for &amp;lt;tt&amp;gt;OpenSim.exe&amp;lt;/tt&amp;gt; can be found in the file &amp;lt;tt&amp;gt;OpenSim/Region/Application/Application.cs&amp;lt;/tt&amp;gt;.  It does a bunch of configuration checks, but the meat of it is the instantiation of an '''OpenSim''' object, calling its Startup() method (which gets things rolling in separate threads), and then blocking the initial thread by prompting on the main console (using the Prompt() method MainConsole.Instance)&lt;br /&gt;
** OpenSim.OpenSim.Startup() comes from an ancestor, OpenSim.Framework.Servers.BaseOpenSimServer; it calls StartupSpecific()&lt;br /&gt;
** OpenSim.OpenSim.StartupSpecific() exists, but much of the meat of really getting a region running is found in the base class' method OpenSim.OpenSimBase.StartupSpecific() (and in other versions of StartupSpecific() on up the inheritance hierarchy).&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.ApplicationPlugins'''.  Each package is an individual application plugin - an application plugin is a modular piece of code that has an effect on the entire region server.  See [[RegionModules]] for more details or one of [http://justincc.wordpress.com/2008/05/08/opensim-tech-basics-my-god-its-full-of-modules/ justincc's blogposts] for a higher level overview (which should really be in this wiki).&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Data'''.  This is all the low level database manipulation stuff.  In here, you'll see packages for SQLite, MySQL and MSSQL (which tends to lag), as well as code for [http://www.hibernate.org/ NHibernate] which will hopefully reduce our reliance on manipulation code for specific databases.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Framework'''.  General framework code used by the rest of OpenSim which is felt to be not specific to a region.  &lt;br /&gt;
** ''OpenSim.Framework.Communications''.  Contains asset and inventory caching code (to cut down on communication with a remote asset or inventory service), and contains CAPS code, a Linden approach to splitting some aspects of the Second Life protocol into independent, secured services.  See a [http://mrtopf.de/blog/secondlife/slga-capabilities-explained-technical/ blog post] from Tao for more background on this.&lt;br /&gt;
** ''OpenSim.Framework.Servers''.  Contains generic server code, such as the base OpenSim server and http servers.&lt;br /&gt;
** ''OpenSim.Framework.Stats''.  Collects statistical information on OpenSim operations.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Server''': these are things that are part of the R.O.B.U.S.T. services, including grid servers, avatar servers, asset servers, inventory servers, and the like.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Region'''.  Contains most of the meaty code that it specifically concerned with region manipulation.&lt;br /&gt;
** ''OpenSim.Region.ClientStack.LindenUDP''.  The code necessary for communicating with clients using the Second Life protocol.&lt;br /&gt;
** ''OpenSim.Region.Communications.Local''.  Code used for communicating with non-region services (user, asset, grid, etc.) when OpenSim is running in standalone mode.&lt;br /&gt;
** ''OpenSim.Region.Communications.OGS1''.  Code for communicating with remote UGAI services using the Open Grid Services 1 protocol.&lt;br /&gt;
** ''OpenSim.Region.Environment''.  A large package containing both the vast majority of the region modules (categorized under modules) and the central scene manipulation code (under Scenes, appropriately enough).  Modules here do everything from handling region chat to loading and saving terrain.&lt;br /&gt;
** ''OpenSim.Region.Modules''.  More region module code.  Actually, I'm not too sure why these aren't in the OpenSim.Region.Environment package.&lt;br /&gt;
** ''OpenSim.Region.Physics''.  General physics framework code and plugins for specific engines (BulletX, ODE, etc).  The ODE code is by far the most reliable and stable.&lt;br /&gt;
** ''OpenSim.Region.ScriptEngine''.  Script engine code that powers the scripts run within OpenSim.  Currently there are two engines, the classic [[DotNetEngine]] and the relatively new [[XEngine]].&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim.Tests'''.  Test code.  Really, we don't actually have much of this (yet).&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Codebase_overview</id>
		<title>Codebase overview</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Codebase_overview"/>
				<updated>2011-08-09T00:58:00Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* Codebase overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==Coding restrictions==&lt;br /&gt;
&lt;br /&gt;
Because OpenSim has to run on both Windows and Mono (usually on Linux or Mac), we are limited to the parts of .net that [http://en.wikipedia.org/wiki/Mono_(software) Mono] supports.&lt;br /&gt;
&lt;br /&gt;
==Codebase overview==&lt;br /&gt;
&lt;br /&gt;
(This is probably quite out of date.  On 2011-08-08, a few edits were made to bring pieces of it up to date, but the editor doesn't have enough of an overview in head to remove all the parts that aren't current.  Edits will continue.)&lt;br /&gt;
&lt;br /&gt;
OpenSim is already a fairly large and intricate project, so patience is required to start understanding it.&lt;br /&gt;
&lt;br /&gt;
At the top level, OpenSim code is broken up into seven sections.  There's also a bit more detail on the most significant packages within those sections.&lt;br /&gt;
&lt;br /&gt;
* '''OpenSim'''.  This contains the classes which launch the OpenSim region server and handle the console&lt;br /&gt;
** The Main() for &amp;lt;tt&amp;gt;OpenSim.exe&amp;lt;/tt&amp;gt; can be found in the file &amp;lt;tt&amp;gt;OpenSim/Region/Application/Application.cs&amp;lt;/tt&amp;gt;&lt;br /&gt;
* '''OpenSim.ApplicationPlugins'''.  Each package is an individual application plugin - an application plugin is a modular piece of code that has an effect on the entire region server.  See [[RegionModules]] for more details or one of [http://justincc.wordpress.com/2008/05/08/opensim-tech-basics-my-god-its-full-of-modules/ justincc's blogposts] for a higher level overview (which should really be in this wiki).&lt;br /&gt;
* '''OpenSim.Data'''.  This is all the low level database manipulation stuff.  In here, you'll see packages for SQLite, MySQL and MSSQL (which tends to lag), as well as code for [http://www.hibernate.org/ NHibernate] which will hopefully reduce our reliance on manipulation code for specific databases.&lt;br /&gt;
* '''OpenSim.Framework'''.  General framework code used by the rest of OpenSim which is felt to be not specific to a region.  &lt;br /&gt;
** ''OpenSim.Framework.Communications''.  Contains asset and inventory caching code (to cut down on communication with a remote asset or inventory service), and contains CAPS code, a Linden approach to splitting some aspects of the Second Life protocol into independent, secured services.  See a [http://mrtopf.de/blog/secondlife/slga-capabilities-explained-technical/ blog post] from Tao for more background on this.&lt;br /&gt;
** ''OpenSim.Framework.Servers''.  Contains generic server code, such as the base OpenSim server and http servers.&lt;br /&gt;
** ''OpenSim.Framework.Stats''.  Collects statistical information on OpenSim operations.&lt;br /&gt;
* '''OpenSim.Server''': these are things that are part of the R.O.B.U.S.T. services, including grid servers, avatar servers, asset servers, inventory servers, and the like.&lt;br /&gt;
* '''OpenSim.Region'''.  Contains most of the meaty code that it specifically concerned with region manipulation.&lt;br /&gt;
** ''OpenSim.Region.ClientStack.LindenUDP''.  The code necessary for communicating with clients using the Second Life protocol.&lt;br /&gt;
** ''OpenSim.Region.Communications.Local''.  Code used for communicating with non-region services (user, asset, grid, etc.) when OpenSim is running in standalone mode.&lt;br /&gt;
** ''OpenSim.Region.Communications.OGS1''.  Code for communicating with remote UGAI services using the Open Grid Services 1 protocol.&lt;br /&gt;
** ''OpenSim.Region.Environment''.  A large package containing both the vast majority of the region modules (categorized under modules) and the central scene manipulation code (under Scenes, appropriately enough).  Modules here do everything from handling region chat to loading and saving terrain.&lt;br /&gt;
** ''OpenSim.Region.Modules''.  More region module code.  Actually, I'm not too sure why these aren't in the OpenSim.Region.Environment package.&lt;br /&gt;
** ''OpenSim.Region.Physics''.  General physics framework code and plugins for specific engines (BulletX, ODE, etc).  The ODE code is by far the most reliable and stable.&lt;br /&gt;
** ''OpenSim.Region.ScriptEngine''.  Script engine code that powers the scripts run within OpenSim.  Currently there are two engines, the classic [[DotNetEngine]] and the relatively new [[XEngine]].&lt;br /&gt;
* '''OpenSim.Tests'''.  Test code.  Really, we don't actually have much of this (yet).&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Updatelibrary.py</id>
		<title>Updatelibrary.py</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Updatelibrary.py"/>
				<updated>2011-07-22T01:40:04Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A python script for maintaining a server inventory library and associated asset set.  See [[Custom Libraries]] for more information.&lt;br /&gt;
&lt;br /&gt;
You can download the current version from [http://www.sonic.net/~rknop/php/vw/updatelibrary.py http://www.sonic.net/~rknop/php/vw/updatelibrary.py]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python&lt;br /&gt;
&lt;br /&gt;
# updatelibrary.py Version 1.2 by Rob Knop aka Prospero Frobozz (rknop@pobox.com)&lt;br /&gt;
&lt;br /&gt;
# Written with some reference to genassets.pl by Illuminous Beltran/IBM,&lt;br /&gt;
# as found on the OpenSim wiki.&lt;br /&gt;
&lt;br /&gt;
# Copyright 2011 Rob Knop (aka Prospero Frobozz). All rights reserved.&lt;br /&gt;
#&lt;br /&gt;
# Redistribution and use in source and binary forms, with or without&lt;br /&gt;
# modification, are permitted provided that the following conditions are&lt;br /&gt;
# met:&lt;br /&gt;
#&lt;br /&gt;
#    1. Redistributions of source code must retain the above copyright&lt;br /&gt;
#       notice, this list of conditions and the following disclaimer.&lt;br /&gt;
&lt;br /&gt;
#    2. Redistributions in binary form must reproduce the above&lt;br /&gt;
#       copyright notice, this list of conditions and the following&lt;br /&gt;
#       disclaimer in the documentation and/or other materials provided&lt;br /&gt;
#       with the distribution.&lt;br /&gt;
#&lt;br /&gt;
# THIS SOFTWARE IS PROVIDED BY ROB KNOP ``AS IS'' AND ANY&lt;br /&gt;
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE&lt;br /&gt;
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR&lt;br /&gt;
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ROB KNOP OR&lt;br /&gt;
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,&lt;br /&gt;
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,&lt;br /&gt;
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR&lt;br /&gt;
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF&lt;br /&gt;
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING&lt;br /&gt;
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
#&lt;br /&gt;
# The views and conclusions contained in the software and documentation&lt;br /&gt;
# are those of the authors and should not be interpreted as representing&lt;br /&gt;
# official policies, either expressed or implied, of Rob Knop.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
import os, os.path, sys, stat, shutil, re, uuid&lt;br /&gt;
import xml.dom, xml.dom.minidom&lt;br /&gt;
import traceback&lt;br /&gt;
from optparse import OptionParser&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
opensim_library_root_uuid = &amp;quot;00000112-000f-0000-0000-000100bba000&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class AssetExistsException(Exception):&lt;br /&gt;
    def __init__(self, value):&lt;br /&gt;
        self.value = value&lt;br /&gt;
    def __str__(self, value):&lt;br /&gt;
        return repr(value)&lt;br /&gt;
&lt;br /&gt;
class InventoryException(Exception):&lt;br /&gt;
    def __init__(self, value):&lt;br /&gt;
        self.value = value&lt;br /&gt;
    def __str__(self, value):&lt;br /&gt;
        return repr(value)&lt;br /&gt;
&lt;br /&gt;
class NiniException(Exception):&lt;br /&gt;
    def __init__(self, value):&lt;br /&gt;
        self.value = value&lt;br /&gt;
    def __str__(self, value):&lt;br /&gt;
        return repr(value)&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
class NiniSection(object):&lt;br /&gt;
    def __init__(self, sectionname, keyvalues):&lt;br /&gt;
        self.sectionname = sectionname&lt;br /&gt;
        self.keyvalues = keyvalues&lt;br /&gt;
&lt;br /&gt;
    def name(self):&lt;br /&gt;
        return self.sectionname&lt;br /&gt;
&lt;br /&gt;
    def keyvalues(self):&lt;br /&gt;
        return self.keyvalues&lt;br /&gt;
&lt;br /&gt;
    def value(self, key):&lt;br /&gt;
        return self.keyvalues[key]&lt;br /&gt;
&lt;br /&gt;
    def setvalue(self, key, value):&lt;br /&gt;
        self.keyvalues[key] = value&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class NiniThing(object):&lt;br /&gt;
    def __init__(self, keynames, ninitype):&lt;br /&gt;
        self.keynames = keynames&lt;br /&gt;
        self.ninitype = ninitype&lt;br /&gt;
&lt;br /&gt;
    def readXML(self, filename):&lt;br /&gt;
        sections = []&lt;br /&gt;
&lt;br /&gt;
        if not os.path.exists(filename):&lt;br /&gt;
            sys.stderr.write(&amp;quot;WARNING: {0} file {1} doesn't exist. Returning empty list.\n&amp;quot;.&lt;br /&gt;
                             format(self.ninitype, filename))&lt;br /&gt;
            return sections&lt;br /&gt;
&lt;br /&gt;
        xmlblob = xml.dom.minidom.parse(filename)&lt;br /&gt;
        topelem = xmlblob.documentElement&lt;br /&gt;
        if topelem.tagName != &amp;quot;Nini&amp;quot;:&lt;br /&gt;
            raise NiniException(&amp;quot;Error not a Nini file: {0}&amp;quot;.format(filename))&lt;br /&gt;
&lt;br /&gt;
        for sec in topelem.childNodes:&lt;br /&gt;
            if sec.nodeType == xml.dom.Node.ELEMENT_NODE:&lt;br /&gt;
                if sec.tagName != 'Section':&lt;br /&gt;
                    raise NiniException(&amp;quot;Error {0} file: expecting a 'Section', found a {1}&amp;quot;.&lt;br /&gt;
                                        format(self.ninitype), sec.tagName)&lt;br /&gt;
&lt;br /&gt;
                item = NiniSection(sec.getAttribute(&amp;quot;Name&amp;quot;), dict())&lt;br /&gt;
                for keyname in self.keynames:&lt;br /&gt;
                    item.setvalue(keyname, &amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
                for seckey in sec.childNodes:&lt;br /&gt;
                    if seckey.nodeType == xml.dom.Node.ELEMENT_NODE:&lt;br /&gt;
                        if seckey.tagName != &amp;quot;Key&amp;quot;:&lt;br /&gt;
                            raise NiniException(&amp;quot;Error reading {0}: expecting a 'Key', found a {1}&amp;quot;.&lt;br /&gt;
                                                format(self.ninitype, seckey.tagName) )&lt;br /&gt;
                        item.setvalue(seckey.getAttribute(&amp;quot;Name&amp;quot;), seckey.getAttribute(&amp;quot;Value&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
                sections.append(item)&lt;br /&gt;
&lt;br /&gt;
        xmlblob.unlink()&lt;br /&gt;
&lt;br /&gt;
        return sections&lt;br /&gt;
&lt;br /&gt;
    def writeXML(self, filename, sections):&lt;br /&gt;
        ofh = open(filename, &amp;quot;w&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        ofh.write(&amp;quot;&amp;lt;Nini&amp;gt;\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        for item in sections:&lt;br /&gt;
            ofh.write(&amp;quot;  &amp;lt;Section Name=\&amp;quot;{0}\&amp;quot;&amp;gt;\n&amp;quot;.format(item.name()))&lt;br /&gt;
            for keyname in self.keynames:&lt;br /&gt;
                ofh.write(&amp;quot;    &amp;lt;Key Name=\&amp;quot;{0}\&amp;quot; Value=\&amp;quot;{1}\&amp;quot; /&amp;gt;\n&amp;quot;.format(keyname, item.value(keyname)))&lt;br /&gt;
            ofh.write(&amp;quot;  &amp;lt;/Section&amp;gt;\n\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        ofh.write(&amp;quot;&amp;lt;/Nini&amp;gt;\n&amp;quot;)&lt;br /&gt;
        ofh.close()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class AssetSet(NiniThing):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(AssetSet,self).__init__( [ &amp;quot;assetID&amp;quot;,&lt;br /&gt;
                                          &amp;quot;name&amp;quot;,&lt;br /&gt;
                                          &amp;quot;assetType&amp;quot;,&lt;br /&gt;
                                          &amp;quot;inventoryType&amp;quot;,&lt;br /&gt;
                                          &amp;quot;fileName&amp;quot;&lt;br /&gt;
                                          ],&lt;br /&gt;
                                        &amp;quot;Asset Set&amp;quot; )&lt;br /&gt;
        self.assets = []&lt;br /&gt;
&lt;br /&gt;
    def __iter__(self):&lt;br /&gt;
        return self.assets.__iter__()&lt;br /&gt;
&lt;br /&gt;
    def addasset(self, uuid, name, asstype, invtype, filename):&lt;br /&gt;
        ass = NiniSection(filename,&lt;br /&gt;
                          { 'assetID': uuid,&lt;br /&gt;
                            'name': name,&lt;br /&gt;
                            'assetType': asstype,&lt;br /&gt;
                            'inventoryType': invtype,&lt;br /&gt;
                            'fileName': filename }&lt;br /&gt;
                          )&lt;br /&gt;
        self.assets.append(ass)&lt;br /&gt;
        return ass&lt;br /&gt;
&lt;br /&gt;
    def findbyfilename(self, filename):&lt;br /&gt;
        for ass in self.assets:&lt;br /&gt;
            if ass.value('fileName') == filename:&lt;br /&gt;
                return ass&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def findbyuuid(self, uuid):&lt;br /&gt;
        for ass in self.assets:&lt;br /&gt;
            if ass.value('assetID') == uuid:&lt;br /&gt;
                return ass&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def readXML(self, filename):&lt;br /&gt;
        self.assets = super(AssetSet, self).readXML(filename)&lt;br /&gt;
&lt;br /&gt;
    def writeXML(self, filename):&lt;br /&gt;
        super(AssetSet, self).writeXML(filename, self.assets)&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class InvFolders(NiniThing):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(InvFolders, self).__init__( [ &amp;quot;folderID&amp;quot;,&lt;br /&gt;
                                            &amp;quot;parentFolderID&amp;quot;,&lt;br /&gt;
                                            &amp;quot;name&amp;quot;,&lt;br /&gt;
                                            &amp;quot;type&amp;quot;&lt;br /&gt;
                                            ],&lt;br /&gt;
                                          &amp;quot;Inventory Folders&amp;quot; )&lt;br /&gt;
        self.folders = []&lt;br /&gt;
&lt;br /&gt;
    def __iter__(self):&lt;br /&gt;
        return self.folders.__iter__()&lt;br /&gt;
&lt;br /&gt;
    def findbyuuid(self, uuid):&lt;br /&gt;
        for folder in self.folders:&lt;br /&gt;
            if folder.value('folderID') == uuid:&lt;br /&gt;
                return folder&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    # NOTE -- findbyname only finds the first folder of&lt;br /&gt;
    #  the given name inside the given parent folder.&lt;br /&gt;
    #  It is possible, if perverse, to have more than&lt;br /&gt;
    #  one folder with the same name...&lt;br /&gt;
&lt;br /&gt;
    def findbyname(self, name, parentid):&lt;br /&gt;
        for folder in self.folders:&lt;br /&gt;
            if ( ( folder.value('parentFolderID') == parentid ) and&lt;br /&gt;
                 ( folder.value('name') == name ) ):&lt;br /&gt;
                return folder&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def ensureexists(self, path, name, parentid):&lt;br /&gt;
        if ( ( parentid != opensim_library_root_uuid ) and&lt;br /&gt;
             ( not self.findbyuuid(parentid) ) ):&lt;br /&gt;
            raise InventoryException(&amp;quot;No such parent folder exists: &amp;quot; + str(parentid))&lt;br /&gt;
&lt;br /&gt;
        folder = self.findbyname(name, parentid)&lt;br /&gt;
        if folder != None:&lt;br /&gt;
            return folder&lt;br /&gt;
&lt;br /&gt;
        # HACK ALERT -- I want this &amp;quot;type 6&amp;quot; to become whatever the right&lt;br /&gt;
        #  type is for no icon&lt;br /&gt;
        # http://opensimulator.org/wiki/AssetServer/DeveloperDocs doesn't tell me enough&lt;br /&gt;
&lt;br /&gt;
        folder = NiniSection(path,&lt;br /&gt;
                             { 'folderID' : uuid.uuid4(),&lt;br /&gt;
                               'parentFolderID' : parentid,&lt;br /&gt;
                               'name' : name,&lt;br /&gt;
                               'type' : -1&lt;br /&gt;
                               }&lt;br /&gt;
                             )&lt;br /&gt;
        self.folders.append(folder)&lt;br /&gt;
&lt;br /&gt;
        return folder&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    def readXML(self, filename):&lt;br /&gt;
        self.folders = super(InvFolders, self).readXML(filename)&lt;br /&gt;
&lt;br /&gt;
    def writeXML(self, filename):&lt;br /&gt;
        super(InvFolders, self).writeXML(filename, self.folders)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class InvItems(NiniThing):&lt;br /&gt;
    def __init__(self, folders):&lt;br /&gt;
        super(InvItems, self).__init__( [ &amp;quot;inventoryID&amp;quot;,&lt;br /&gt;
                                          &amp;quot;assetID&amp;quot;,&lt;br /&gt;
                                          &amp;quot;folderID&amp;quot;,&lt;br /&gt;
                                          &amp;quot;name&amp;quot;,&lt;br /&gt;
                                          &amp;quot;description&amp;quot;,&lt;br /&gt;
                                          &amp;quot;assetType&amp;quot;,&lt;br /&gt;
                                          &amp;quot;inventoryType&amp;quot;,&lt;br /&gt;
                                          &amp;quot;currentPermissions&amp;quot;,&lt;br /&gt;
                                          &amp;quot;nextPermissions&amp;quot;,&lt;br /&gt;
                                          &amp;quot;everyonePermissions&amp;quot;,&lt;br /&gt;
                                          &amp;quot;basePermissions&amp;quot;&lt;br /&gt;
                                          ],&lt;br /&gt;
                                        &amp;quot;Inventory Items&amp;quot; )&lt;br /&gt;
        self.folders = folders&lt;br /&gt;
        self.items = []&lt;br /&gt;
&lt;br /&gt;
    def findbyinvid(self, uuid):&lt;br /&gt;
        for item in self.items:&lt;br /&gt;
            if item.value('inventoryID') == uuid:&lt;br /&gt;
                return item&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    # Note -- findbyname only finds the first one of that name&lt;br /&gt;
    #  in that folder.  You can have more than one thing of&lt;br /&gt;
    #  the same name in a given folder....&lt;br /&gt;
&lt;br /&gt;
    def findbyname(self, name, folderid):&lt;br /&gt;
        for item in self.items:&lt;br /&gt;
            if ( ( item.value('name') == name ) and&lt;br /&gt;
                 ( item.value('folderID') == folderid) ):&lt;br /&gt;
               return item&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def ensureexists(self, path, name, assetid, assettype, invtype, folderid):&lt;br /&gt;
        if ( ( folderid != opensim_library_root_uuid) and&lt;br /&gt;
             ( not self.folders.findbyuuid(folderid) ) ):&lt;br /&gt;
            raise InventoryException(&amp;quot;No such folder for item: &amp;quot; + str(folderid))&lt;br /&gt;
&lt;br /&gt;
        for item in self.items:&lt;br /&gt;
            if ( ( item.value('assetID') == assetid ) and&lt;br /&gt;
                 ( item.value('folderID') == folderid ) and&lt;br /&gt;
                 ( item.value('name') == name ) ):&lt;br /&gt;
                return item&lt;br /&gt;
&lt;br /&gt;
        item = NiniSection(path,&lt;br /&gt;
                           { 'inventoryID' : uuid.uuid4(),&lt;br /&gt;
                             'assetID' : assetid,&lt;br /&gt;
                             'folderID' : folderid,&lt;br /&gt;
                             'name' : name,&lt;br /&gt;
                             'description' : &amp;quot;&amp;quot;,&lt;br /&gt;
                             'assetType' : assettype,&lt;br /&gt;
                             'inventoryType' : invtype,&lt;br /&gt;
                             'currentPermissions' : &amp;quot;2147483647&amp;quot;,&lt;br /&gt;
                             'nextPermissions' : &amp;quot;2147483647&amp;quot;,&lt;br /&gt;
                             'everyonePermissions' : &amp;quot;2147483647&amp;quot;,&lt;br /&gt;
                             'basePermissions' : &amp;quot;2147483647&amp;quot;&lt;br /&gt;
                             }&lt;br /&gt;
                           )&lt;br /&gt;
        self.items.append(item)&lt;br /&gt;
&lt;br /&gt;
        return item&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    def readXML(self, filename):&lt;br /&gt;
        self.items = super(InvItems, self).readXML(filename)&lt;br /&gt;
&lt;br /&gt;
    def writeXML(self, filename):&lt;br /&gt;
        super(InvItems, self).writeXML(filename, self.items)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class LibraryGenerator(object):&lt;br /&gt;
    def __init__(self, libname, shortname):&lt;br /&gt;
        self.libname = libname&lt;br /&gt;
        self.shortname = shortname&lt;br /&gt;
        self.asset_dir = os.path.abspath(os.path.join(&amp;quot;assets&amp;quot;, &amp;quot;{0}AssetSet&amp;quot;.format(shortname)))&lt;br /&gt;
        self.inv_dir = os.path.abspath(os.path.join(&amp;quot;inventory&amp;quot;, shortname))&lt;br /&gt;
        self.asset_xmlfile = &amp;quot;{0}AssetSet.xml&amp;quot;.format(shortname)&lt;br /&gt;
        self.folders_xmlfile = &amp;quot;{0}InvFolders.xml&amp;quot;.format(shortname)&lt;br /&gt;
        self.items_xmlfile = &amp;quot;{0}InvItems.xml&amp;quot;.format(shortname)&lt;br /&gt;
        self.skips = []&lt;br /&gt;
        self.wipeinv = False&lt;br /&gt;
&lt;br /&gt;
        self.matchj2k = re.compile(&amp;quot;\.j2k$&amp;quot;)&lt;br /&gt;
        self.matchtxt = re.compile(&amp;quot;\.txt$&amp;quot;)&lt;br /&gt;
        self.matchlsl = re.compile(&amp;quot;\.lsl$&amp;quot;)&lt;br /&gt;
        self.endsinslash = re.compile(&amp;quot;/$&amp;quot;)&lt;br /&gt;
        self.commentline = re.compile(&amp;quot;^\s*#&amp;quot;)&lt;br /&gt;
        self.blankline = re.compile(&amp;quot;^\s*$&amp;quot;)&lt;br /&gt;
        self.assetlistline = re.compile(&amp;quot;^\s*([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\s*(\d+)\s*(\d+)\s*(.*\S)\s*$&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def set_skip_patterns(self, skips):&lt;br /&gt;
        self.skips = skips&lt;br /&gt;
&lt;br /&gt;
    def set_asset_dir(self, asset_dir):&lt;br /&gt;
        self.asset_dir = asset_dir&lt;br /&gt;
&lt;br /&gt;
    def set_inv_dir(self, inv_dir):&lt;br /&gt;
        self.inv_dir = inv_dir&lt;br /&gt;
&lt;br /&gt;
    def set_asset_xmlfile(self, asset_xmlfile):&lt;br /&gt;
        self.asset_xmlfile = asset_xmlfile&lt;br /&gt;
&lt;br /&gt;
    def set_folders_xmlfile(self, folders_xmlfile):&lt;br /&gt;
        self.folders_xmlfile = folders_xmlfile&lt;br /&gt;
&lt;br /&gt;
    def set_items_xmlfile(self, items_xmlfile):&lt;br /&gt;
        self.items_xmlfile = items_xmlfile&lt;br /&gt;
&lt;br /&gt;
    def wipe_inventory(self):&lt;br /&gt;
        self.wipeinv = True&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
    def run(self):&lt;br /&gt;
        # Create our storage for things, and read any current&lt;br /&gt;
        #  XML files if they exist&lt;br /&gt;
&lt;br /&gt;
        self.assets = AssetSet()&lt;br /&gt;
        self.assets.readXML(os.path.join(self.asset_dir, self.asset_xmlfile))&lt;br /&gt;
&lt;br /&gt;
        self.folders = InvFolders()&lt;br /&gt;
        if not self.wipeinv:&lt;br /&gt;
            self.folders.readXML(os.path.join(self.inv_dir, self.folders_xmlfile))&lt;br /&gt;
&lt;br /&gt;
        self.items = InvItems(self.folders)&lt;br /&gt;
        if not self.wipeinv:&lt;br /&gt;
            self.items.readXML(os.path.join(self.inv_dir, self.items_xmlfile))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        # Run the recursive directory processor thingie&lt;br /&gt;
&lt;br /&gt;
        origdir = os.getcwd()&lt;br /&gt;
        os.chdir(self.asset_dir)&lt;br /&gt;
        self.process_dir(opensim_library_root_uuid, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
        os.chdir(origdir)&lt;br /&gt;
&lt;br /&gt;
        # Write the XML files, saving copies of the old ones out of paranoia&lt;br /&gt;
&lt;br /&gt;
        if os.path.exists(os.path.join(self.asset_dir, self.asset_xmlfile)):&lt;br /&gt;
            shutil.copy2(os.path.join(self.asset_dir, self.asset_xmlfile),&lt;br /&gt;
                         os.path.join(self.asset_dir, &amp;quot;{0}-old&amp;quot;.format(self.asset_xmlfile)))&lt;br /&gt;
&lt;br /&gt;
        self.assets.writeXML(os.path.join(self.asset_dir, self.asset_xmlfile))&lt;br /&gt;
&lt;br /&gt;
        if os.path.exists(os.path.join(self.inv_dir, self.folders_xmlfile)):&lt;br /&gt;
            shutil.copy2(os.path.join(self.inv_dir, self.folders_xmlfile),&lt;br /&gt;
                         os.path.join(self.inv_dir, &amp;quot;{0}-old&amp;quot;.format(self.folders_xmlfile)))&lt;br /&gt;
&lt;br /&gt;
        self.folders.writeXML(os.path.join(self.inv_dir, self.folders_xmlfile))&lt;br /&gt;
&lt;br /&gt;
        if os.path.exists(os.path.join(self.inv_dir, self.items_xmlfile)):&lt;br /&gt;
            shutil.copy2(os.path.join(self.inv_dir, self.items_xmlfile),&lt;br /&gt;
                         os.path.join(self.inv_dir, &amp;quot;{0}-old&amp;quot;.format(self.items_xmlfile)))&lt;br /&gt;
&lt;br /&gt;
        self.items.writeXML(os.path.join(self.inv_dir, self.items_xmlfile))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    def process_dir(self, parent_uuid, my_name, path):&lt;br /&gt;
        origdir = os.getcwd()&lt;br /&gt;
        sys.stderr.write(&amp;quot;Processing directory: {0} \n&amp;quot;.format(os.path.join(self.asset_dir, path)))&lt;br /&gt;
        if my_name != &amp;quot;&amp;quot;:&lt;br /&gt;
            os.chdir(my_name)&lt;br /&gt;
        else:&lt;br /&gt;
            my_name = self.libname&lt;br /&gt;
            &lt;br /&gt;
        # Create the folder XML blob if necessary&lt;br /&gt;
&lt;br /&gt;
        if (path == &amp;quot;&amp;quot;):&lt;br /&gt;
            curfolder = self.folders.ensureexists(self.libname, my_name, parent_uuid)&lt;br /&gt;
        else:&lt;br /&gt;
            curfolder = self.folders.ensureexists(path, my_name, parent_uuid)&lt;br /&gt;
        my_uuid = curfolder.value(&amp;quot;folderID&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Walk through this directory and process everything in it&lt;br /&gt;
&lt;br /&gt;
        for fname in os.listdir(&amp;quot;.&amp;quot;):&lt;br /&gt;
            statinfo = os.stat(fname)&lt;br /&gt;
&lt;br /&gt;
            doskip = False&lt;br /&gt;
            for skip in self.skips:&lt;br /&gt;
                if re.search(skip, fname):&lt;br /&gt;
                    doskip = True&lt;br /&gt;
            if doskip: continue&lt;br /&gt;
&lt;br /&gt;
            if stat.S_ISDIR(statinfo.st_mode):&lt;br /&gt;
                self.process_dir(my_uuid, fname, os.path.join(path, fname) )&lt;br /&gt;
                continue&lt;br /&gt;
&lt;br /&gt;
            fpath = os.path.join(path, fname)&lt;br /&gt;
            &lt;br /&gt;
            if fpath == self.asset_xmlfile:&lt;br /&gt;
                # Ignore the XML file we're working on!&lt;br /&gt;
                continue&lt;br /&gt;
&lt;br /&gt;
            elif fname == &amp;quot;addassets.lis&amp;quot;:&lt;br /&gt;
                # Ignore the file specifing pre-existing assets to add&lt;br /&gt;
                #   to inventory&lt;br /&gt;
                continue&lt;br /&gt;
&lt;br /&gt;
            elif self.matchj2k.search(fname):&lt;br /&gt;
                asset_type = 0&lt;br /&gt;
            elif self.matchtxt.search(fname):&lt;br /&gt;
                asset_type = 7&lt;br /&gt;
            elif self.matchlsl.search(fname):&lt;br /&gt;
                asset_type = 10&lt;br /&gt;
            else:&lt;br /&gt;
                sys.stderr.write(&amp;quot;WARNING: Skipping unrecognized file &amp;quot; +&lt;br /&gt;
                                 fname + &amp;quot;\n&amp;quot;)&lt;br /&gt;
                continue&lt;br /&gt;
&lt;br /&gt;
            # Strip the extension for aesthetic purposes&lt;br /&gt;
            #  (Right now, that must be .txt, .lsl, or .j2k, so&lt;br /&gt;
            #   we can assume it's 4 characters long.)&lt;br /&gt;
&lt;br /&gt;
            name = fname[0:-4]&lt;br /&gt;
&lt;br /&gt;
            # Create the asset XML blob if necessary&lt;br /&gt;
&lt;br /&gt;
            ass = self.assets.findbyfilename(fpath)&lt;br /&gt;
            if ass == None:&lt;br /&gt;
                ass = self.assets.addasset(uuid.uuid4(), name, asset_type,&lt;br /&gt;
                                           asset_type, os.path.join(path, fname))&lt;br /&gt;
&lt;br /&gt;
            # Create the inventory XML blob if necessary&lt;br /&gt;
&lt;br /&gt;
            self.items.ensureexists(os.path.join(path, name), name, ass.value('assetID'), &lt;br /&gt;
                                    asset_type, asset_type, my_uuid)&lt;br /&gt;
&lt;br /&gt;
        # Add pre-existing assets (to inventory only) from file addassets.lis&lt;br /&gt;
&lt;br /&gt;
        if os.path.exists(&amp;quot;addassets.lis&amp;quot;):&lt;br /&gt;
            asslis = open(&amp;quot;addassets.lis&amp;quot;)&lt;br /&gt;
            for line in asslis:&lt;br /&gt;
                line.rstrip(&amp;quot;\r\n&amp;quot;)&lt;br /&gt;
                if self.blankline.search(line) or self.commentline.search(line):&lt;br /&gt;
                    continue&lt;br /&gt;
                match = self.assetlistline.search(line)&lt;br /&gt;
                if match == None:&lt;br /&gt;
                    sys.stderr.write(&amp;quot;WARNING : error parsing line in {0}\n&amp;quot;.&lt;br /&gt;
                                     format(os.path.join(path, &amp;quot;addassets.lis&amp;quot;)))&lt;br /&gt;
                    sys.stderr.write(&amp;quot;Offending line: \&amp;quot;{0}\&amp;quot;\n&amp;quot;.format(line))&lt;br /&gt;
                    continue&lt;br /&gt;
                self.items.ensureexists(os.path.join(path, match.group(4)), match.group(4), &lt;br /&gt;
                                        match.group(1), match.group(2), match.group(3), my_uuid)&lt;br /&gt;
            asslis.close()&lt;br /&gt;
&lt;br /&gt;
        # We're done; restore the CWD to where we started and return&lt;br /&gt;
&lt;br /&gt;
        os.chdir(origdir)&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
&lt;br /&gt;
    usage = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    updatelibrary.py -n &amp;quot;Library Name&amp;quot; -s ShortLibName [options]&lt;br /&gt;
&lt;br /&gt;
  Goes through your asset set directory.  (See below for how to specify&lt;br /&gt;
  it, and what the default is.)  Finds all .j2k images, .txt files, and&lt;br /&gt;
  .lsl files in that directory and all subdirectories.  Generates an&lt;br /&gt;
  Asset Set XML file for all of those files.  Also generates library&lt;br /&gt;
  Inventory Folder and Inventory Item XML files for all of those assets,&lt;br /&gt;
  organized in a folder hierarchy that matches the directory hierarchy.&lt;br /&gt;
&lt;br /&gt;
  Additional assets that already exist in the grid's asset store may be&lt;br /&gt;
  specified in each directory in a file named &amp;quot;addassets.lis&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
  For more documentation, see http://opensimulator.org/wiki/Custom_Libraries&lt;br /&gt;
&lt;br /&gt;
  When done, you will need to manually add your asset directory to the&lt;br /&gt;
  OpenSim AssetSets.xml file (in &amp;quot;assets&amp;quot; under the OpenSim bin&lt;br /&gt;
  directory), and your inventory XML files to the Libraries.xml file (in&lt;br /&gt;
  &amp;quot;inventory&amp;quot; under the OpenSim bin directory).&lt;br /&gt;
&lt;br /&gt;
  Written 2011 by Rob Knop aka Prospero Frobozz.  I've only used this on&lt;br /&gt;
  Linux; I have no idea how well it will function on Windows.  If you're&lt;br /&gt;
  on Windows, I recommend http://www.ubuntu.com&lt;br /&gt;
&lt;br /&gt;
  Run updatelibrary.py --help for option listings&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    parser = OptionParser(usage = usage)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-n&amp;quot;, &amp;quot;--lib-name&amp;quot;, action=&amp;quot;store&amp;quot;, type=&amp;quot;string&amp;quot;,&lt;br /&gt;
                      dest=&amp;quot;libname&amp;quot;, default=&amp;quot;New Library&amp;quot;,&lt;br /&gt;
                      help=&amp;quot;The name of your library as it appears in the viewer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-s&amp;quot;, &amp;quot;--short-name&amp;quot;, action=&amp;quot;store&amp;quot;, type=&amp;quot;string&amp;quot;,&lt;br /&gt;
                      dest=&amp;quot;shortname&amp;quot;, default=&amp;quot;NewLibrary&amp;quot;,&lt;br /&gt;
                      help=&amp;quot;A name without spaces of your library for filename purposes.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-w&amp;quot;, &amp;quot;--wipe-inventory&amp;quot;, action=&amp;quot;store_true&amp;quot;, default=False,&lt;br /&gt;
                      dest=&amp;quot;wipeinv&amp;quot;,&lt;br /&gt;
                      help=&amp;quot;Wipe &amp;amp; start over the inventory? (Safe! Use this if you've removed things.)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-a&amp;quot;, &amp;quot;--asset-dir&amp;quot;, action=&amp;quot;store&amp;quot;,&lt;br /&gt;
                      type=&amp;quot;string&amp;quot;, dest=&amp;quot;asset_dir&amp;quot;,&lt;br /&gt;
                      default=None,&lt;br /&gt;
                      help=&amp;quot;Directory where your .j2k, .txt, and .lsl files are, and which will &amp;quot;+&lt;br /&gt;
                      &amp;quot;serve as the Assset Set in the OpenSim library.  Defaults to assets/[shortname]AssetSet&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-i&amp;quot;, &amp;quot;--inv-dir&amp;quot;, action=&amp;quot;store&amp;quot;, type=&amp;quot;string&amp;quot;,&lt;br /&gt;
                      dest=&amp;quot;inv_dir&amp;quot;, default=None,&lt;br /&gt;
                      help=&amp;quot;Directory in which to put the inventory XML files.  Defaults to &amp;quot;+&lt;br /&gt;
                      &amp;quot;inventory/[shortname]&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;&amp;quot;, &amp;quot;--asset-xmlfile&amp;quot;, action=&amp;quot;store&amp;quot;,&lt;br /&gt;
                      type=&amp;quot;string&amp;quot;, dest=&amp;quot;asset_xmlfile&amp;quot;, default=None,&lt;br /&gt;
                      help=&amp;quot;Name of Asset XML file.  Defaults to [shortname]AssetSet.xml&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;&amp;quot;, &amp;quot;--folders-xmlfile&amp;quot;, action=&amp;quot;store&amp;quot;,&lt;br /&gt;
                      type=&amp;quot;string&amp;quot;, dest=&amp;quot;folders_xmlfile&amp;quot;, default=None,&lt;br /&gt;
                      help=&amp;quot;Name of Inventory Folders XML file.  Defaults to [shortname]InvFolders.xml&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;&amp;quot;, &amp;quot;--items-xmlfile&amp;quot;, action=&amp;quot;store&amp;quot;,&lt;br /&gt;
                      type=&amp;quot;string&amp;quot;, dest=&amp;quot;items_xmlfile&amp;quot;, default=None,&lt;br /&gt;
                      help=&amp;quot;Name of Inventory Folders XML file.  Defaults to [shortname]InvItems.xml&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;&amp;quot;, &amp;quot;--skip&amp;quot;, action=&amp;quot;append&amp;quot;, type=&amp;quot;string&amp;quot;,&lt;br /&gt;
                      dest=&amp;quot;skip_patterns&amp;quot;,&lt;br /&gt;
                      default=['^\.hg$', '^\.git$', '^\.svn$'],&lt;br /&gt;
                      help=&amp;quot;Regex for filenames to not process&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if len(sys.argv) &amp;lt; 2:&lt;br /&gt;
        parser.print_usage()&lt;br /&gt;
        sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
    options, args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        generator = LibraryGenerator(options.libname, options.shortname)&lt;br /&gt;
&lt;br /&gt;
        if options.skip_patterns:&lt;br /&gt;
            generator.set_skip_patterns(options.skip_patterns)&lt;br /&gt;
&lt;br /&gt;
        if options.asset_dir != None:&lt;br /&gt;
            generator.set_asset_dir(options.asset_dir)&lt;br /&gt;
&lt;br /&gt;
        if options.inv_dir != None:&lt;br /&gt;
            generator.set_inv_dir(options.inv_dir)&lt;br /&gt;
&lt;br /&gt;
        if options.asset_xmlfile != None:&lt;br /&gt;
            generator.set_asset_xmlfile(options.asset_xmlfile)&lt;br /&gt;
&lt;br /&gt;
        if options.folders_xmlfile != None:&lt;br /&gt;
            generator.set_folders_xmlfile(options.folders_xmlfile)&lt;br /&gt;
&lt;br /&gt;
        if options.items_xmlfile != None:&lt;br /&gt;
            generator.set_items_xmlfile(options.items_xmlfile)&lt;br /&gt;
&lt;br /&gt;
        if options.wipeinv:&lt;br /&gt;
            generator.wipe_inventory()&lt;br /&gt;
&lt;br /&gt;
        generator.run()&lt;br /&gt;
&lt;br /&gt;
    except Exception:&lt;br /&gt;
        print &amp;quot;FAIL&amp;quot;&lt;br /&gt;
        traceback.print_exc()&lt;br /&gt;
        sys.exit(20)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Updatelibrary.py</id>
		<title>Updatelibrary.py</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Updatelibrary.py"/>
				<updated>2011-07-21T22:03:42Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A python script for maintaining a server inventory library and associated asset set.  See [[Custom Libraries]] for more information.&lt;br /&gt;
&lt;br /&gt;
You can download the current version from [http://www.sonic.net/~rknop/php/vw/updatelibrary.py http://www.sonic.net/~rknop/php/vw/updatelibrary.py]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python&lt;br /&gt;
&lt;br /&gt;
# updatelibrary.py Version 1.1 by Rob Knop aka Prospero Frobozz (rknop@pobox.com)&lt;br /&gt;
&lt;br /&gt;
# Written with some reference to genassets.pl by Illuminous Beltran/IBM,&lt;br /&gt;
# as found on the OpenSim wiki.&lt;br /&gt;
&lt;br /&gt;
# Copyright 2011 Rob Knop (aka Prospero Frobozz). All rights reserved.&lt;br /&gt;
#&lt;br /&gt;
# Redistribution and use in source and binary forms, with or without&lt;br /&gt;
# modification, are permitted provided that the following conditions are&lt;br /&gt;
# met:&lt;br /&gt;
#&lt;br /&gt;
#    1. Redistributions of source code must retain the above copyright&lt;br /&gt;
#       notice, this list of conditions and the following disclaimer.&lt;br /&gt;
&lt;br /&gt;
#    2. Redistributions in binary form must reproduce the above&lt;br /&gt;
#       copyright notice, this list of conditions and the following&lt;br /&gt;
#       disclaimer in the documentation and/or other materials provided&lt;br /&gt;
#       with the distribution.&lt;br /&gt;
#&lt;br /&gt;
# THIS SOFTWARE IS PROVIDED BY ROB KNOP ``AS IS'' AND ANY&lt;br /&gt;
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE&lt;br /&gt;
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR&lt;br /&gt;
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ROB KNOP OR&lt;br /&gt;
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,&lt;br /&gt;
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,&lt;br /&gt;
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR&lt;br /&gt;
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF&lt;br /&gt;
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING&lt;br /&gt;
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
#&lt;br /&gt;
# The views and conclusions contained in the software and documentation&lt;br /&gt;
# are those of the authors and should not be interpreted as representing&lt;br /&gt;
# official policies, either expressed or implied, of Rob Knop.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
import os, os.path, sys, stat, shutil, re, uuid&lt;br /&gt;
import xml.dom, xml.dom.minidom&lt;br /&gt;
import traceback&lt;br /&gt;
from optparse import OptionParser&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
opensim_library_root_uuid = &amp;quot;00000112-000f-0000-0000-000100bba000&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class AssetExistsException(Exception):&lt;br /&gt;
    def __init__(self, value):&lt;br /&gt;
        self.value = value&lt;br /&gt;
    def __str__(self, value):&lt;br /&gt;
        return repr(value)&lt;br /&gt;
&lt;br /&gt;
class InventoryException(Exception):&lt;br /&gt;
    def __init__(self, value):&lt;br /&gt;
        self.value = value&lt;br /&gt;
    def __str__(self, value):&lt;br /&gt;
        return repr(value)&lt;br /&gt;
&lt;br /&gt;
class NiniException(Exception):&lt;br /&gt;
    def __init__(self, value):&lt;br /&gt;
        self.value = value&lt;br /&gt;
    def __str__(self, value):&lt;br /&gt;
        return repr(value)&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
class NiniSection(object):&lt;br /&gt;
    def __init__(self, sectionname, keyvalues):&lt;br /&gt;
        self.sectionname = sectionname&lt;br /&gt;
        self.keyvalues = keyvalues&lt;br /&gt;
&lt;br /&gt;
    def name(self):&lt;br /&gt;
        return self.sectionname&lt;br /&gt;
&lt;br /&gt;
    def keyvalues(self):&lt;br /&gt;
        return self.keyvalues&lt;br /&gt;
&lt;br /&gt;
    def value(self, key):&lt;br /&gt;
        return self.keyvalues[key]&lt;br /&gt;
&lt;br /&gt;
    def setvalue(self, key, value):&lt;br /&gt;
        self.keyvalues[key] = value&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class NiniThing(object):&lt;br /&gt;
    def __init__(self, keynames, ninitype):&lt;br /&gt;
        self.keynames = keynames&lt;br /&gt;
        self.ninitype = ninitype&lt;br /&gt;
&lt;br /&gt;
    def readXML(self, filename):&lt;br /&gt;
        sections = []&lt;br /&gt;
&lt;br /&gt;
        if not os.path.exists(filename):&lt;br /&gt;
            sys.stderr.write(&amp;quot;WARNING: {0} file {1} doesn't exist. Returning empty list.\n&amp;quot;.&lt;br /&gt;
                             format(self.ninitype, filename))&lt;br /&gt;
            return sections&lt;br /&gt;
&lt;br /&gt;
        xmlblob = xml.dom.minidom.parse(filename)&lt;br /&gt;
        topelem = xmlblob.documentElement&lt;br /&gt;
        if topelem.tagName != &amp;quot;Nini&amp;quot;:&lt;br /&gt;
            raise NiniException(&amp;quot;Error not a Nini file: {0}&amp;quot;.format(filename))&lt;br /&gt;
&lt;br /&gt;
        for sec in topelem.childNodes:&lt;br /&gt;
            if sec.nodeType == xml.dom.Node.ELEMENT_NODE:&lt;br /&gt;
                if sec.tagName != 'Section':&lt;br /&gt;
                    raise NiniException(&amp;quot;Error {0} file: expecting a 'Section', found a {1}&amp;quot;.&lt;br /&gt;
                                        format(self.ninitype), sec.tagName)&lt;br /&gt;
&lt;br /&gt;
                item = NiniSection(sec.getAttribute(&amp;quot;Name&amp;quot;), dict())&lt;br /&gt;
                for keyname in self.keynames:&lt;br /&gt;
                    item.setvalue(keyname, &amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
                for seckey in sec.childNodes:&lt;br /&gt;
                    if seckey.nodeType == xml.dom.Node.ELEMENT_NODE:&lt;br /&gt;
                        if seckey.tagName != &amp;quot;Key&amp;quot;:&lt;br /&gt;
                            raise NiniException(&amp;quot;Error reading {0}: expecting a 'Key', found a {1}&amp;quot;.&lt;br /&gt;
                                                format(self.ninitype, seckey.tagName) )&lt;br /&gt;
                        item.setvalue(seckey.getAttribute(&amp;quot;Name&amp;quot;), seckey.getAttribute(&amp;quot;Value&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
                sections.append(item)&lt;br /&gt;
&lt;br /&gt;
        xmlblob.unlink()&lt;br /&gt;
&lt;br /&gt;
        return sections&lt;br /&gt;
&lt;br /&gt;
    def writeXML(self, filename, sections):&lt;br /&gt;
        ofh = open(filename, &amp;quot;w&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        ofh.write(&amp;quot;&amp;lt;Nini&amp;gt;\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        for item in sections:&lt;br /&gt;
            ofh.write(&amp;quot;  &amp;lt;Section Name=\&amp;quot;{0}\&amp;quot;&amp;gt;\n&amp;quot;.format(item.name()))&lt;br /&gt;
            for keyname in self.keynames:&lt;br /&gt;
                ofh.write(&amp;quot;    &amp;lt;Key Name=\&amp;quot;{0}\&amp;quot; Value=\&amp;quot;{1}\&amp;quot; /&amp;gt;\n&amp;quot;.format(keyname, item.value(keyname)))&lt;br /&gt;
            ofh.write(&amp;quot;  &amp;lt;/Section&amp;gt;\n\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        ofh.write(&amp;quot;&amp;lt;/Nini&amp;gt;\n&amp;quot;)&lt;br /&gt;
        ofh.close()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class AssetSet(NiniThing):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(AssetSet,self).__init__( [ &amp;quot;assetID&amp;quot;,&lt;br /&gt;
                                          &amp;quot;name&amp;quot;,&lt;br /&gt;
                                          &amp;quot;assetType&amp;quot;,&lt;br /&gt;
                                          &amp;quot;inventoryType&amp;quot;,&lt;br /&gt;
                                          &amp;quot;fileName&amp;quot;&lt;br /&gt;
                                          ],&lt;br /&gt;
                                        &amp;quot;Asset Set&amp;quot; )&lt;br /&gt;
        self.assets = []&lt;br /&gt;
&lt;br /&gt;
    def __iter__(self):&lt;br /&gt;
        return self.assets.__iter__()&lt;br /&gt;
&lt;br /&gt;
    def addasset(self, uuid, name, asstype, invtype, filename):&lt;br /&gt;
        ass = NiniSection(filename,&lt;br /&gt;
                          { 'assetID': uuid,&lt;br /&gt;
                            'name': name,&lt;br /&gt;
                            'assetType': asstype,&lt;br /&gt;
                            'inventoryType': invtype,&lt;br /&gt;
                            'fileName': filename }&lt;br /&gt;
                          )&lt;br /&gt;
        self.assets.append(ass)&lt;br /&gt;
        return ass&lt;br /&gt;
&lt;br /&gt;
    def findbyfilename(self, filename):&lt;br /&gt;
        for ass in self.assets:&lt;br /&gt;
            if ass.value('fileName') == filename:&lt;br /&gt;
                return ass&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def findbyuuid(self, uuid):&lt;br /&gt;
        for ass in self.assets:&lt;br /&gt;
            if ass.value('assetID') == uuid:&lt;br /&gt;
                return ass&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def readXML(self, filename):&lt;br /&gt;
        self.assets = super(AssetSet, self).readXML(filename)&lt;br /&gt;
&lt;br /&gt;
    def writeXML(self, filename):&lt;br /&gt;
        super(AssetSet, self).writeXML(filename, self.assets)&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class InvFolders(NiniThing):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(InvFolders, self).__init__( [ &amp;quot;folderID&amp;quot;,&lt;br /&gt;
                                            &amp;quot;parentFolderID&amp;quot;,&lt;br /&gt;
                                            &amp;quot;name&amp;quot;,&lt;br /&gt;
                                            &amp;quot;type&amp;quot;&lt;br /&gt;
                                            ],&lt;br /&gt;
                                          &amp;quot;Inventory Folders&amp;quot; )&lt;br /&gt;
        self.folders = []&lt;br /&gt;
&lt;br /&gt;
    def __iter__(self):&lt;br /&gt;
        return self.folders.__iter__()&lt;br /&gt;
&lt;br /&gt;
    def findbyuuid(self, uuid):&lt;br /&gt;
        for folder in self.folders:&lt;br /&gt;
            if folder.value('folderID') == uuid:&lt;br /&gt;
                return folder&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    # NOTE -- findbyname only finds the first folder of&lt;br /&gt;
    #  the given name inside the given parent folder.&lt;br /&gt;
    #  It is possible, if perverse, to have more than&lt;br /&gt;
    #  one folder with the same name...&lt;br /&gt;
&lt;br /&gt;
    def findbyname(self, name, parentid):&lt;br /&gt;
        for folder in self.folders:&lt;br /&gt;
            if ( ( folder.value('parentFolderID') == parentid ) and&lt;br /&gt;
                 ( folder.value('name') == name ) ):&lt;br /&gt;
                return folder&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def ensureexists(self, path, name, parentid):&lt;br /&gt;
        if ( ( parentid != opensim_library_root_uuid ) and&lt;br /&gt;
             ( not self.findbyuuid(parentid) ) ):&lt;br /&gt;
            raise InventoryException(&amp;quot;No such parent folder exists: &amp;quot; + str(parentid))&lt;br /&gt;
&lt;br /&gt;
        folder = self.findbyname(name, parentid)&lt;br /&gt;
        if folder != None:&lt;br /&gt;
            return folder&lt;br /&gt;
&lt;br /&gt;
        # HACK ALERT -- I want this &amp;quot;type 6&amp;quot; to become whatever the right&lt;br /&gt;
        #  type is for no icon&lt;br /&gt;
        # http://opensimulator.org/wiki/AssetServer/DeveloperDocs doesn't tell me enough&lt;br /&gt;
&lt;br /&gt;
        folder = NiniSection(path,&lt;br /&gt;
                             { 'folderID' : uuid.uuid4(),&lt;br /&gt;
                               'parentFolderID' : parentid,&lt;br /&gt;
                               'name' : name,&lt;br /&gt;
                               'type' : -1&lt;br /&gt;
                               }&lt;br /&gt;
                             )&lt;br /&gt;
        self.folders.append(folder)&lt;br /&gt;
&lt;br /&gt;
        return folder&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    def readXML(self, filename):&lt;br /&gt;
        self.folders = super(InvFolders, self).readXML(filename)&lt;br /&gt;
&lt;br /&gt;
    def writeXML(self, filename):&lt;br /&gt;
        super(InvFolders, self).writeXML(filename, self.folders)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class InvItems(NiniThing):&lt;br /&gt;
    def __init__(self, folders):&lt;br /&gt;
        super(InvItems, self).__init__( [ &amp;quot;inventoryID&amp;quot;,&lt;br /&gt;
                                          &amp;quot;assetID&amp;quot;,&lt;br /&gt;
                                          &amp;quot;folderID&amp;quot;,&lt;br /&gt;
                                          &amp;quot;name&amp;quot;,&lt;br /&gt;
                                          &amp;quot;description&amp;quot;,&lt;br /&gt;
                                          &amp;quot;assetType&amp;quot;,&lt;br /&gt;
                                          &amp;quot;inventoryType&amp;quot;,&lt;br /&gt;
                                          &amp;quot;currentPermissions&amp;quot;,&lt;br /&gt;
                                          &amp;quot;nextPermissions&amp;quot;,&lt;br /&gt;
                                          &amp;quot;everyonePermissions&amp;quot;,&lt;br /&gt;
                                          &amp;quot;basePermissions&amp;quot;&lt;br /&gt;
                                          ],&lt;br /&gt;
                                        &amp;quot;Inventory Items&amp;quot; )&lt;br /&gt;
        self.folders = folders&lt;br /&gt;
        self.items = []&lt;br /&gt;
&lt;br /&gt;
    def findbyinvid(self, uuid):&lt;br /&gt;
        for item in self.items:&lt;br /&gt;
            if item.value('inventoryID') == uuid:&lt;br /&gt;
                return item&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    # Note -- findbyname only finds the first one of that name&lt;br /&gt;
    #  in that folder.  You can have more than one thing of&lt;br /&gt;
    #  the same name in a given folder....&lt;br /&gt;
&lt;br /&gt;
    def findbyname(self, name, folderid):&lt;br /&gt;
        for item in self.items:&lt;br /&gt;
            if ( ( item.value('name') == name ) and&lt;br /&gt;
                 ( item.value('folderID') == folderid) ):&lt;br /&gt;
               return item&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def ensureexists(self, path, name, assetid, assettype, invtype, folderid):&lt;br /&gt;
        if ( ( folderid != opensim_library_root_uuid) and&lt;br /&gt;
             ( not self.folders.findbyuuid(folderid) ) ):&lt;br /&gt;
            raise InventoryException(&amp;quot;No such folder for item: &amp;quot; + str(folderid))&lt;br /&gt;
&lt;br /&gt;
        for item in self.items:&lt;br /&gt;
            if ( ( item.value('assetID') == assetid ) and&lt;br /&gt;
                 ( item.value('folderID') == folderid ) and&lt;br /&gt;
                 ( item.value('name') == name ) ):&lt;br /&gt;
                return item&lt;br /&gt;
&lt;br /&gt;
        item = NiniSection(path,&lt;br /&gt;
                           { 'inventoryID' : uuid.uuid4(),&lt;br /&gt;
                             'assetID' : assetid,&lt;br /&gt;
                             'folderID' : folderid,&lt;br /&gt;
                             'name' : name,&lt;br /&gt;
                             'description' : &amp;quot;&amp;quot;,&lt;br /&gt;
                             'assetType' : assettype,&lt;br /&gt;
                             'inventoryType' : invtype,&lt;br /&gt;
                             'currentPermissions' : &amp;quot;2147483647&amp;quot;,&lt;br /&gt;
                             'nextPermissions' : &amp;quot;2147483647&amp;quot;,&lt;br /&gt;
                             'everyonePermissions' : &amp;quot;2147483647&amp;quot;,&lt;br /&gt;
                             'basePermissions' : &amp;quot;2147483647&amp;quot;&lt;br /&gt;
                             }&lt;br /&gt;
                           )&lt;br /&gt;
        self.items.append(item)&lt;br /&gt;
&lt;br /&gt;
        return item&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    def readXML(self, filename):&lt;br /&gt;
        self.items = super(InvItems, self).readXML(filename)&lt;br /&gt;
&lt;br /&gt;
    def writeXML(self, filename):&lt;br /&gt;
        super(InvItems, self).writeXML(filename, self.items)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class LibraryGenerator(object):&lt;br /&gt;
    def __init__(self, libname, shortname):&lt;br /&gt;
        self.libname = libname&lt;br /&gt;
        self.shortname = shortname&lt;br /&gt;
        self.asset_dir = os.path.abspath(os.path.join(&amp;quot;assets&amp;quot;, &amp;quot;{0}AssetSet&amp;quot;.format(shortname)))&lt;br /&gt;
        self.inv_dir = os.path.abspath(os.path.join(&amp;quot;inventory&amp;quot;, shortname))&lt;br /&gt;
        self.asset_xmlfile = &amp;quot;{0}AssetSet.xml&amp;quot;.format(shortname)&lt;br /&gt;
        self.folders_xmlfile = &amp;quot;{0}InvFolders.xml&amp;quot;.format(shortname)&lt;br /&gt;
        self.items_xmlfile = &amp;quot;{0}InvItems.xml&amp;quot;.format(shortname)&lt;br /&gt;
        self.skips = []&lt;br /&gt;
&lt;br /&gt;
        self.matchj2k = re.compile(&amp;quot;\.j2k$&amp;quot;)&lt;br /&gt;
        self.matchtxt = re.compile(&amp;quot;\.txt$&amp;quot;)&lt;br /&gt;
        self.matchlsl = re.compile(&amp;quot;\.lsl$&amp;quot;)&lt;br /&gt;
        self.endsinslash = re.compile(&amp;quot;/$&amp;quot;)&lt;br /&gt;
        self.commentline = re.compile(&amp;quot;^\s*#&amp;quot;)&lt;br /&gt;
        self.blankline = re.compile(&amp;quot;^\s*$&amp;quot;)&lt;br /&gt;
        self.assetlistline = re.compile(&amp;quot;^\s*([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\s*(\d+)\s*(\d+)\s*(.*\S)\s*$&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def set_skip_patterns(self, skips):&lt;br /&gt;
        self.skips = skips&lt;br /&gt;
&lt;br /&gt;
    def set_asset_dir(self, asset_dir):&lt;br /&gt;
        self.asset_dir = asset_dir&lt;br /&gt;
&lt;br /&gt;
    def set_inv_dir(self, inv_dir):&lt;br /&gt;
        self.inv_dir = inv_dir&lt;br /&gt;
&lt;br /&gt;
    def set_asset_xmlfile(self, asset_xmlfile):&lt;br /&gt;
        self.asset_xmlfile = asset_xmlfile&lt;br /&gt;
&lt;br /&gt;
    def set_folders_xmlfile(self, folders_xmlfile):&lt;br /&gt;
        self.folders_xmlfile = folders_xmlfile&lt;br /&gt;
&lt;br /&gt;
    def set_items_xmlfile(self, items_xmlfile):&lt;br /&gt;
        self.items_xmlfile = items_xmlfile&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    def run(self):&lt;br /&gt;
        # Create our storage for things, and read any current&lt;br /&gt;
        #  XML files if they exist&lt;br /&gt;
&lt;br /&gt;
        self.assets = AssetSet()&lt;br /&gt;
        self.assets.readXML(os.path.join(self.asset_dir, self.asset_xmlfile))&lt;br /&gt;
&lt;br /&gt;
        self.folders = InvFolders()&lt;br /&gt;
        self.folders.readXML(os.path.join(self.inv_dir, self.folders_xmlfile))&lt;br /&gt;
&lt;br /&gt;
        self.items = InvItems(self.folders)&lt;br /&gt;
        self.items.readXML(os.path.join(self.inv_dir, self.items_xmlfile))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        # Run the recursive directory processor thingie&lt;br /&gt;
&lt;br /&gt;
        origdir = os.getcwd()&lt;br /&gt;
        os.chdir(self.asset_dir)&lt;br /&gt;
        self.process_dir(opensim_library_root_uuid, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
        os.chdir(origdir)&lt;br /&gt;
&lt;br /&gt;
        # Write the XML files, saving copies of the old ones out of paranoia&lt;br /&gt;
&lt;br /&gt;
        if os.path.exists(os.path.join(self.asset_dir, self.asset_xmlfile)):&lt;br /&gt;
            shutil.copy2(os.path.join(self.asset_dir, self.asset_xmlfile),&lt;br /&gt;
                         os.path.join(self.asset_dir, &amp;quot;{0}-old&amp;quot;.format(self.asset_xmlfile)))&lt;br /&gt;
&lt;br /&gt;
        self.assets.writeXML(os.path.join(self.asset_dir, self.asset_xmlfile))&lt;br /&gt;
&lt;br /&gt;
        if os.path.exists(os.path.join(self.inv_dir, self.folders_xmlfile)):&lt;br /&gt;
            shutil.copy2(os.path.join(self.inv_dir, self.folders_xmlfile),&lt;br /&gt;
                         os.path.join(self.inv_dir, &amp;quot;{0}-old&amp;quot;.format(self.folders_xmlfile)))&lt;br /&gt;
&lt;br /&gt;
        self.folders.writeXML(os.path.join(self.inv_dir, self.folders_xmlfile))&lt;br /&gt;
&lt;br /&gt;
        if os.path.exists(os.path.join(self.inv_dir, self.items_xmlfile)):&lt;br /&gt;
            shutil.copy2(os.path.join(self.inv_dir, self.items_xmlfile),&lt;br /&gt;
                         os.path.join(self.inv_dir, &amp;quot;{0}-old&amp;quot;.format(self.items_xmlfile)))&lt;br /&gt;
&lt;br /&gt;
        self.items.writeXML(os.path.join(self.inv_dir, self.items_xmlfile))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    def process_dir(self, parent_uuid, my_name, path):&lt;br /&gt;
        origdir = os.getcwd()&lt;br /&gt;
        sys.stderr.write(&amp;quot;Processing directory: {0} \n&amp;quot;.format(os.path.join(self.asset_dir, path)))&lt;br /&gt;
        if my_name != &amp;quot;&amp;quot;:&lt;br /&gt;
            os.chdir(my_name)&lt;br /&gt;
        else:&lt;br /&gt;
            my_name = self.libname&lt;br /&gt;
            &lt;br /&gt;
        # Create the folder XML blob if necessary&lt;br /&gt;
&lt;br /&gt;
        if (path == &amp;quot;&amp;quot;):&lt;br /&gt;
            curfolder = self.folders.ensureexists(self.libname, my_name, parent_uuid)&lt;br /&gt;
        else:&lt;br /&gt;
            curfolder = self.folders.ensureexists(path, my_name, parent_uuid)&lt;br /&gt;
        my_uuid = curfolder.value(&amp;quot;folderID&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Walk through this directory and process everything in it&lt;br /&gt;
&lt;br /&gt;
        for fname in os.listdir(&amp;quot;.&amp;quot;):&lt;br /&gt;
            statinfo = os.stat(fname)&lt;br /&gt;
&lt;br /&gt;
            doskip = False&lt;br /&gt;
            for skip in self.skips:&lt;br /&gt;
                if re.search(skip, fname):&lt;br /&gt;
                    doskip = True&lt;br /&gt;
            if doskip: continue&lt;br /&gt;
&lt;br /&gt;
            if stat.S_ISDIR(statinfo.st_mode):&lt;br /&gt;
                self.process_dir(my_uuid, fname, os.path.join(path, fname) )&lt;br /&gt;
                continue&lt;br /&gt;
&lt;br /&gt;
            fpath = os.path.join(path, fname)&lt;br /&gt;
            &lt;br /&gt;
            if fpath == self.asset_xmlfile:&lt;br /&gt;
                # Ignore the XML file we're working on!&lt;br /&gt;
                continue&lt;br /&gt;
&lt;br /&gt;
            elif fname == &amp;quot;addassets.lis&amp;quot;:&lt;br /&gt;
                # Ignore the file specifing pre-existing assets to add&lt;br /&gt;
                #   to inventory&lt;br /&gt;
                continue&lt;br /&gt;
&lt;br /&gt;
            elif self.matchj2k.search(fname):&lt;br /&gt;
                asset_type = 0&lt;br /&gt;
            elif self.matchtxt.search(fname):&lt;br /&gt;
                asset_type = 7&lt;br /&gt;
            elif self.matchlsl.search(fname):&lt;br /&gt;
                asset_type = 10&lt;br /&gt;
            else:&lt;br /&gt;
                sys.stderr.write(&amp;quot;WARNING: Skipping unrecognized file &amp;quot; +&lt;br /&gt;
                                 fname + &amp;quot;\n&amp;quot;)&lt;br /&gt;
                continue&lt;br /&gt;
&lt;br /&gt;
            # Strip the extension for aesthetic purposes&lt;br /&gt;
            #  (Right now, that must be .txt, .lsl, or .j2k, so&lt;br /&gt;
            #   we can assume it's 4 characters long.)&lt;br /&gt;
&lt;br /&gt;
            name = fname[0:-4]&lt;br /&gt;
&lt;br /&gt;
            # Create the asset XML blob if necessary&lt;br /&gt;
&lt;br /&gt;
            ass = self.assets.findbyfilename(fpath)&lt;br /&gt;
            if ass == None:&lt;br /&gt;
                ass = self.assets.addasset(uuid.uuid4(), name, asset_type,&lt;br /&gt;
                                           asset_type, os.path.join(path, fname))&lt;br /&gt;
&lt;br /&gt;
            # Create the inventory XML blob if necessary&lt;br /&gt;
&lt;br /&gt;
            self.items.ensureexists(os.path.join(path, name), name, ass.value('assetID'), &lt;br /&gt;
                                    asset_type, asset_type, my_uuid)&lt;br /&gt;
&lt;br /&gt;
        # Add pre-existing assets (to inventory only) from file addassets.lis&lt;br /&gt;
&lt;br /&gt;
        if os.path.exists(&amp;quot;addassets.lis&amp;quot;):&lt;br /&gt;
            asslis = open(&amp;quot;addassets.lis&amp;quot;)&lt;br /&gt;
            for line in asslis:&lt;br /&gt;
                line.rstrip(&amp;quot;\r\n&amp;quot;)&lt;br /&gt;
                if self.blankline.search(line) or self.commentline.search(line):&lt;br /&gt;
                    continue&lt;br /&gt;
                match = self.assetlistline.search(line)&lt;br /&gt;
                if match == None:&lt;br /&gt;
                    sys.stderr.write(&amp;quot;WARNING : error parsing line in {0}\n&amp;quot;.&lt;br /&gt;
                                     format(os.path.join(path, &amp;quot;addassets.lis&amp;quot;)))&lt;br /&gt;
                    sys.stderr.write(&amp;quot;Offending line: \&amp;quot;{0}\&amp;quot;\n&amp;quot;.format(line))&lt;br /&gt;
                    continue&lt;br /&gt;
                self.items.ensureexists(os.path.join(path, match.group(4)), match.group(4), &lt;br /&gt;
                                        match.group(1), match.group(2), match.group(3), my_uuid)&lt;br /&gt;
            asslis.close()&lt;br /&gt;
&lt;br /&gt;
        # We're done; restore the CWD to where we started and return&lt;br /&gt;
&lt;br /&gt;
        os.chdir(origdir)&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
&lt;br /&gt;
    usage = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    updatelibrary.py -n &amp;quot;Library Name&amp;quot; -s ShortLibName [options]&lt;br /&gt;
&lt;br /&gt;
  Goes through your asset set directory.  (See below for how to specify&lt;br /&gt;
  it, and what the default is.)  Finds all .j2k images, .txt files, and&lt;br /&gt;
  .lsl files in that directory and all subdirectories.  Generates an&lt;br /&gt;
  Asset Set XML file for all of those files.  Also generates library&lt;br /&gt;
  Inventory Folder and Inventory Item XML files for all of those assets,&lt;br /&gt;
  organized in a folder hierarchy that matches the directory hierarchy.&lt;br /&gt;
&lt;br /&gt;
  Additional assets that already exist in the grid's asset store may be&lt;br /&gt;
  specified in each directory in a file named &amp;quot;addassets.lis&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
  For more documentation, see http://opensimulator.org/wiki/Custom_Libraries&lt;br /&gt;
&lt;br /&gt;
  When done, you will need to manually add your asset directory to the&lt;br /&gt;
  OpenSim AssetSets.xml file (in &amp;quot;assets&amp;quot; under the OpenSim bin&lt;br /&gt;
  directory), and your inventory XML files to the Libraries.xml file (in&lt;br /&gt;
  &amp;quot;inventory&amp;quot; under the OpenSim bin directory).&lt;br /&gt;
&lt;br /&gt;
  Written 2011 by Rob Knop aka Prospero Frobozz.  I've only used this on&lt;br /&gt;
  Linux; I have no idea how well it will function on Windows.  If you're&lt;br /&gt;
  on Windows, I recommend http://www.ubuntu.com&lt;br /&gt;
&lt;br /&gt;
  Run updatelibrary.py --help for option listings&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    parser = OptionParser(usage = usage)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-n&amp;quot;, &amp;quot;--lib-name&amp;quot;, action=&amp;quot;store&amp;quot;, type=&amp;quot;string&amp;quot;,&lt;br /&gt;
                      dest=&amp;quot;libname&amp;quot;, default=&amp;quot;New Library&amp;quot;,&lt;br /&gt;
                      help=&amp;quot;The name of your library as it appears in the viewer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-s&amp;quot;, &amp;quot;--short-name&amp;quot;, action=&amp;quot;store&amp;quot;, type=&amp;quot;string&amp;quot;,&lt;br /&gt;
                      dest=&amp;quot;shortname&amp;quot;, default=&amp;quot;NewLibrary&amp;quot;,&lt;br /&gt;
                      help=&amp;quot;A name without spaces of your library for filename purposes.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-a&amp;quot;, &amp;quot;--asset-dir&amp;quot;, action=&amp;quot;store&amp;quot;,&lt;br /&gt;
                      type=&amp;quot;string&amp;quot;, dest=&amp;quot;asset_dir&amp;quot;,&lt;br /&gt;
                      default=None,&lt;br /&gt;
                      help=&amp;quot;Directory where your .j2k, .txt, and .lsl files are, and which will &amp;quot;+&lt;br /&gt;
                      &amp;quot;serve as the Assset Set in the OpenSim library.  Defaults to assets/[shortname]AssetSet&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-i&amp;quot;, &amp;quot;--inv-dir&amp;quot;, action=&amp;quot;store&amp;quot;, type=&amp;quot;string&amp;quot;,&lt;br /&gt;
                      dest=&amp;quot;inv_dir&amp;quot;, default=None,&lt;br /&gt;
                      help=&amp;quot;Directory in which to put the inventory XML files.  Defaults to &amp;quot;+&lt;br /&gt;
                      &amp;quot;inventory/[shortname]&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;&amp;quot;, &amp;quot;--asset-xmlfile&amp;quot;, action=&amp;quot;store&amp;quot;,&lt;br /&gt;
                      type=&amp;quot;string&amp;quot;, dest=&amp;quot;asset_xmlfile&amp;quot;, default=None,&lt;br /&gt;
                      help=&amp;quot;Name of Asset XML file.  Defaults to [shortname]AssetSet.xml&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;&amp;quot;, &amp;quot;--folders-xmlfile&amp;quot;, action=&amp;quot;store&amp;quot;,&lt;br /&gt;
                      type=&amp;quot;string&amp;quot;, dest=&amp;quot;folders_xmlfile&amp;quot;, default=None,&lt;br /&gt;
                      help=&amp;quot;Name of Inventory Folders XML file.  Defaults to [shortname]InvFolders.xml&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;&amp;quot;, &amp;quot;--items-xmlfile&amp;quot;, action=&amp;quot;store&amp;quot;,&lt;br /&gt;
                      type=&amp;quot;string&amp;quot;, dest=&amp;quot;items_xmlfile&amp;quot;, default=None,&lt;br /&gt;
                      help=&amp;quot;Name of Inventory Folders XML file.  Defaults to [shortname]InvItems.xml&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;&amp;quot;, &amp;quot;--skip&amp;quot;, action=&amp;quot;append&amp;quot;, type=&amp;quot;string&amp;quot;,&lt;br /&gt;
                      dest=&amp;quot;skip_patterns&amp;quot;,&lt;br /&gt;
                      default=['^\.hg$', '^\.git$', '^\.svn$'],&lt;br /&gt;
                      help=&amp;quot;Regex for filenames to not process&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if len(sys.argv) &amp;lt; 2:&lt;br /&gt;
        parser.print_usage()&lt;br /&gt;
        sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
    options, args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        generator = LibraryGenerator(options.libname, options.shortname)&lt;br /&gt;
&lt;br /&gt;
        if options.skip_patterns:&lt;br /&gt;
            generator.set_skip_patterns(options.skip_patterns)&lt;br /&gt;
&lt;br /&gt;
        if options.asset_dir != None:&lt;br /&gt;
            generator.set_asset_dir(options.asset_dir)&lt;br /&gt;
&lt;br /&gt;
        if options.inv_dir != None:&lt;br /&gt;
            generator.set_inv_dir(options.inv_dir)&lt;br /&gt;
&lt;br /&gt;
        if options.asset_xmlfile != None:&lt;br /&gt;
            generator.set_asset_xmlfile(options.asset_xmlfile)&lt;br /&gt;
&lt;br /&gt;
        if options.folders_xmlfile != None:&lt;br /&gt;
            generator.set_folders_xmlfile(options.folders_xmlfile)&lt;br /&gt;
&lt;br /&gt;
        if options.items_xmlfile != None:&lt;br /&gt;
            generator.set_items_xmlfile(options.items_xmlfile)&lt;br /&gt;
&lt;br /&gt;
        generator.run()&lt;br /&gt;
&lt;br /&gt;
    except Exception:&lt;br /&gt;
        print &amp;quot;FAIL&amp;quot;&lt;br /&gt;
        traceback.print_exc()&lt;br /&gt;
        sys.exit(20)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Updatelibrary.py</id>
		<title>Updatelibrary.py</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Updatelibrary.py"/>
				<updated>2011-07-16T02:22:29Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: New page: A python script for maintaining a server inventory library and associated asset set.  See Custom Libraries for more information.  You can download the current version from [http://www....&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A python script for maintaining a server inventory library and associated asset set.  See [[Custom Libraries]] for more information.&lt;br /&gt;
&lt;br /&gt;
You can download the current version from [http://www.sonic.net/~rknop/php/vw/updatelibrary.py http://www.sonic.net/~rknop/php/vw/updatelibrary.py]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python&lt;br /&gt;
&lt;br /&gt;
# updatelibrary.py Version 1.0 by Rob Knop aka Prospero Frobozz (rknop@pobox.com)&lt;br /&gt;
&lt;br /&gt;
# Written with some reference to genassets.pl by Illuminous Beltran/IBM,&lt;br /&gt;
# as found on the OpenSim wiki.&lt;br /&gt;
&lt;br /&gt;
# Copyright 2011 Rob Knop (aka Prospero Frobozz). All rights reserved.&lt;br /&gt;
#&lt;br /&gt;
# Redistribution and use in source and binary forms, with or without&lt;br /&gt;
# modification, are permitted provided that the following conditions are&lt;br /&gt;
# met:&lt;br /&gt;
#&lt;br /&gt;
#    1. Redistributions of source code must retain the above copyright&lt;br /&gt;
#       notice, this list of conditions and the following disclaimer.&lt;br /&gt;
&lt;br /&gt;
#    2. Redistributions in binary form must reproduce the above&lt;br /&gt;
#       copyright notice, this list of conditions and the following&lt;br /&gt;
#       disclaimer in the documentation and/or other materials provided&lt;br /&gt;
#       with the distribution.&lt;br /&gt;
#&lt;br /&gt;
# THIS SOFTWARE IS PROVIDED BY ROB KNOP ``AS IS'' AND ANY&lt;br /&gt;
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE&lt;br /&gt;
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR&lt;br /&gt;
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ROB KNOP OR&lt;br /&gt;
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,&lt;br /&gt;
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,&lt;br /&gt;
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR&lt;br /&gt;
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF&lt;br /&gt;
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING&lt;br /&gt;
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;br /&gt;
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;br /&gt;
#&lt;br /&gt;
# The views and conclusions contained in the software and documentation&lt;br /&gt;
# are those of the authors and should not be interpreted as representing&lt;br /&gt;
# official policies, either expressed or implied, of Rob Knop.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
import os, os.path, sys, stat, shutil, re, uuid&lt;br /&gt;
import xml.dom, xml.dom.minidom&lt;br /&gt;
import traceback&lt;br /&gt;
from optparse import OptionParser&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
opensim_library_root_uuid = &amp;quot;00000112-000f-0000-0000-000100bba000&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class AssetExistsException(Exception):&lt;br /&gt;
    def __init__(self, value):&lt;br /&gt;
        self.value = value&lt;br /&gt;
    def __str__(self, value):&lt;br /&gt;
        return repr(value)&lt;br /&gt;
&lt;br /&gt;
class InventoryException(Exception):&lt;br /&gt;
    def __init__(self, value):&lt;br /&gt;
        self.value = value&lt;br /&gt;
    def __str__(self, value):&lt;br /&gt;
        return repr(value)&lt;br /&gt;
&lt;br /&gt;
class NiniException(Exception):&lt;br /&gt;
    def __init__(self, value):&lt;br /&gt;
        self.value = value&lt;br /&gt;
    def __str__(self, value):&lt;br /&gt;
        return repr(value)&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class NiniThing(object):&lt;br /&gt;
    def __init__(self, keynames, ninitype):&lt;br /&gt;
        self.keynames = keynames&lt;br /&gt;
        self.ninitype = ninitype&lt;br /&gt;
&lt;br /&gt;
    def readXML(self, filename):&lt;br /&gt;
        sections = []&lt;br /&gt;
&lt;br /&gt;
        if not os.path.exists(filename):&lt;br /&gt;
            sys.stderr.write(&amp;quot;WARNING: {0} file {1} doesn't exist. Returning empty list.\n&amp;quot;.&lt;br /&gt;
                             format(self.ninitype, filename))&lt;br /&gt;
            return sections&lt;br /&gt;
&lt;br /&gt;
        xmlblob = xml.dom.minidom.parse(filename)&lt;br /&gt;
        topelem = xmlblob.documentElement&lt;br /&gt;
        if topelem.tagName != &amp;quot;Nini&amp;quot;:&lt;br /&gt;
            raise NiniException(&amp;quot;Error not a Nini file: {0}&amp;quot;.format(filename))&lt;br /&gt;
&lt;br /&gt;
        for sec in topelem.childNodes:&lt;br /&gt;
            if sec.nodeType == xml.dom.Node.ELEMENT_NODE:&lt;br /&gt;
                if sec.tagName != 'Section':&lt;br /&gt;
                    raise NiniException(&amp;quot;Error {0} file: expecting a 'Section', found a {1}&amp;quot;.&lt;br /&gt;
                                        format(self.ninitype), sec.tagName)&lt;br /&gt;
&lt;br /&gt;
                item = dict()&lt;br /&gt;
                for keyname in self.keynames:&lt;br /&gt;
                    item[keyname] = &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
                for seckey in sec.childNodes:&lt;br /&gt;
                    if seckey.nodeType == xml.dom.Node.ELEMENT_NODE:&lt;br /&gt;
                        if seckey.tagName != &amp;quot;Key&amp;quot;:&lt;br /&gt;
                            raise NiniException(&amp;quot;Error reading {0}: expecting a 'Key', found a {1}&amp;quot;.&lt;br /&gt;
                                                format(self.ninitype, seckey.tagName) )&lt;br /&gt;
                        item[seckey.getAttribute(&amp;quot;Name&amp;quot;)] = seckey.getAttribute(&amp;quot;Value&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
                sections.append(item)&lt;br /&gt;
&lt;br /&gt;
        xmlblob.unlink()&lt;br /&gt;
&lt;br /&gt;
        return sections&lt;br /&gt;
&lt;br /&gt;
    def writeXML(self, filename, sections):&lt;br /&gt;
        ofh = open(filename, &amp;quot;w&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        ofh.write(&amp;quot;&amp;lt;Nini&amp;gt;\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        for item in sections:&lt;br /&gt;
            ofh.write(&amp;quot;  &amp;lt;Section Name=\&amp;quot;{0}\&amp;quot;&amp;gt;\n&amp;quot;.format(item[&amp;quot;name&amp;quot;]))&lt;br /&gt;
            for keyname in self.keynames:&lt;br /&gt;
                ofh.write(&amp;quot;    &amp;lt;Key Name=\&amp;quot;{0}\&amp;quot; Value=\&amp;quot;{1}\&amp;quot; /&amp;gt;\n&amp;quot;.format(keyname, item[keyname]))&lt;br /&gt;
            ofh.write(&amp;quot;  &amp;lt;/Section&amp;gt;\n\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        ofh.write(&amp;quot;&amp;lt;/Nini&amp;gt;\n&amp;quot;)&lt;br /&gt;
        ofh.close()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class AssetSet(NiniThing):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(AssetSet,self).__init__( [ &amp;quot;assetID&amp;quot;,&lt;br /&gt;
                                          &amp;quot;name&amp;quot;,&lt;br /&gt;
                                          &amp;quot;assetType&amp;quot;,&lt;br /&gt;
                                          &amp;quot;inventoryType&amp;quot;,&lt;br /&gt;
                                          &amp;quot;fileName&amp;quot;&lt;br /&gt;
                                          ],&lt;br /&gt;
                                        &amp;quot;Asset Set&amp;quot; )&lt;br /&gt;
        self.assets = []&lt;br /&gt;
&lt;br /&gt;
    def __iter__(self):&lt;br /&gt;
        return self.assets.__iter__()&lt;br /&gt;
&lt;br /&gt;
    def addasset(self, uuid, name, asstype, invtype, filename):&lt;br /&gt;
        ass = { 'assetID': uuid,&lt;br /&gt;
                'name': name,&lt;br /&gt;
                'assetType': asstype,&lt;br /&gt;
                'inventoryType': invtype,&lt;br /&gt;
                'fileName': filename }&lt;br /&gt;
        self.assets.append(ass)&lt;br /&gt;
        return ass&lt;br /&gt;
&lt;br /&gt;
    def findbyfilename(self, filename):&lt;br /&gt;
        for ass in self.assets:&lt;br /&gt;
            if ass['fileName'] == filename:&lt;br /&gt;
                return ass&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def findbyuuid(self, uuid):&lt;br /&gt;
        for ass in self.assets:&lt;br /&gt;
            if ass['assetID'] == uuid:&lt;br /&gt;
                return ass&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def readXML(self, filename):&lt;br /&gt;
        self.assets = super(AssetSet, self).readXML(filename)&lt;br /&gt;
&lt;br /&gt;
    def writeXML(self, filename):&lt;br /&gt;
        super(AssetSet, self).writeXML(filename, self.assets)&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class InvFolders(NiniThing):&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(InvFolders, self).__init__( [ &amp;quot;folderID&amp;quot;,&lt;br /&gt;
                                            &amp;quot;parentFolderID&amp;quot;,&lt;br /&gt;
                                            &amp;quot;name&amp;quot;,&lt;br /&gt;
                                            &amp;quot;type&amp;quot;&lt;br /&gt;
                                            ],&lt;br /&gt;
                                          &amp;quot;Inventory Folders&amp;quot; )&lt;br /&gt;
        self.folders = []&lt;br /&gt;
&lt;br /&gt;
    def __iter__(self):&lt;br /&gt;
        return self.folders.__iter__()&lt;br /&gt;
&lt;br /&gt;
    def findbyuuid(self, uuid):&lt;br /&gt;
        for folder in self.folders:&lt;br /&gt;
            if folder['folderID'] == uuid:&lt;br /&gt;
                return folder&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    # NOTE -- findbyname only finds the first folder of&lt;br /&gt;
    #  the given name inside the given parent folder.&lt;br /&gt;
    #  It is possible, if perverse, to have more than&lt;br /&gt;
    #  one folder with the same name...&lt;br /&gt;
&lt;br /&gt;
    def findbyname(self, name, parentid):&lt;br /&gt;
        for folder in self.folders:&lt;br /&gt;
            if ( ( folder['parentFolderID'] == parentid ) and&lt;br /&gt;
                 ( folder['name'] == name ) ):&lt;br /&gt;
                return folder&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def ensureexists(self, name, parentid):&lt;br /&gt;
        if ( ( parentid != opensim_library_root_uuid ) and&lt;br /&gt;
             ( not self.findbyuuid(parentid) ) ):&lt;br /&gt;
            raise InventoryException(&amp;quot;No such parent folder exists: &amp;quot; + str(parentid))&lt;br /&gt;
&lt;br /&gt;
        folder = self.findbyname(name, parentid)&lt;br /&gt;
        if folder != None:&lt;br /&gt;
            return folder&lt;br /&gt;
&lt;br /&gt;
        # HACK ALERT -- I want this &amp;quot;type 6&amp;quot; to become whatever the right&lt;br /&gt;
        #  type is for no icon&lt;br /&gt;
        # http://opensimulator.org/wiki/AssetServer/DeveloperDocs doesn't tell me enough&lt;br /&gt;
&lt;br /&gt;
        folder = { 'folderID' : uuid.uuid4(),&lt;br /&gt;
                   'parentFolderID' : parentid,&lt;br /&gt;
                   'name' : name,&lt;br /&gt;
                   'type' : 6&lt;br /&gt;
                  }&lt;br /&gt;
        self.folders.append(folder)&lt;br /&gt;
&lt;br /&gt;
        return folder&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    def readXML(self, filename):&lt;br /&gt;
        self.folders = super(InvFolders, self).readXML(filename)&lt;br /&gt;
&lt;br /&gt;
    def writeXML(self, filename):&lt;br /&gt;
        super(InvFolders, self).writeXML(filename, self.folders)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class InvItems(NiniThing):&lt;br /&gt;
    def __init__(self, folders):&lt;br /&gt;
        super(InvItems, self).__init__( [ &amp;quot;inventoryID&amp;quot;,&lt;br /&gt;
                                          &amp;quot;assetID&amp;quot;,&lt;br /&gt;
                                          &amp;quot;folderID&amp;quot;,&lt;br /&gt;
                                          &amp;quot;name&amp;quot;,&lt;br /&gt;
                                          &amp;quot;description&amp;quot;,&lt;br /&gt;
                                          &amp;quot;assetType&amp;quot;,&lt;br /&gt;
                                          &amp;quot;inventoryType&amp;quot;,&lt;br /&gt;
                                          &amp;quot;currentPermissions&amp;quot;,&lt;br /&gt;
                                          &amp;quot;nextPermissions&amp;quot;,&lt;br /&gt;
                                          &amp;quot;everyonePermissions&amp;quot;,&lt;br /&gt;
                                          &amp;quot;basePermissions&amp;quot;&lt;br /&gt;
                                          ],&lt;br /&gt;
                                        &amp;quot;Inventory Items&amp;quot; )&lt;br /&gt;
        self.folders = folders&lt;br /&gt;
        self.items = []&lt;br /&gt;
&lt;br /&gt;
    def findbyinvid(self, uuid):&lt;br /&gt;
        for item in self.items:&lt;br /&gt;
            if item['inventoryID'] == uuid:&lt;br /&gt;
                return item&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    # Note -- findbyname only finds the first one of that name&lt;br /&gt;
    #  in that folder.  You can have more than one thing of&lt;br /&gt;
    #  the same name in a given folder....&lt;br /&gt;
&lt;br /&gt;
    def findbyname(self, name, folderid):&lt;br /&gt;
        for item in self.items:&lt;br /&gt;
            if ( ( item['name'] == name ) and&lt;br /&gt;
                 ( item['folderID'] == folderid) ):&lt;br /&gt;
               return item&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def ensureexists(self, name, assetid, assettype, invtype, folderid):&lt;br /&gt;
        if ( ( folderid != opensim_library_root_uuid) and&lt;br /&gt;
             ( not self.folders.findbyuuid(folderid) ) ):&lt;br /&gt;
            raise InventoryException(&amp;quot;No such folder for item: &amp;quot; + str(folderid))&lt;br /&gt;
&lt;br /&gt;
        for item in self.items:&lt;br /&gt;
            if ( ( item['assetID'] == assetid ) and&lt;br /&gt;
                 ( item['folderID'] == folderid ) and&lt;br /&gt;
                 ( item['name'] == name ) ):&lt;br /&gt;
                return item&lt;br /&gt;
&lt;br /&gt;
        item = { 'inventoryID' : uuid.uuid4(),&lt;br /&gt;
                 'assetID' : assetid,&lt;br /&gt;
                 'folderID' : folderid,&lt;br /&gt;
                 'name' : name,&lt;br /&gt;
                 'description' : &amp;quot;&amp;quot;,&lt;br /&gt;
                 'assetType' : assettype,&lt;br /&gt;
                 'inventoryType' : invtype,&lt;br /&gt;
                 'currentPermissions' : &amp;quot;2147483647&amp;quot;,&lt;br /&gt;
                 'nextPermissions' : &amp;quot;2147483647&amp;quot;,&lt;br /&gt;
                 'everyonePermissions' : &amp;quot;2147483647&amp;quot;,&lt;br /&gt;
                 'basePermissions' : &amp;quot;2147483647&amp;quot;&lt;br /&gt;
               }&lt;br /&gt;
        self.items.append(item)&lt;br /&gt;
&lt;br /&gt;
        return item&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    def readXML(self, filename):&lt;br /&gt;
        self.items = super(InvItems, self).readXML(filename)&lt;br /&gt;
&lt;br /&gt;
    def writeXML(self, filename):&lt;br /&gt;
        super(InvItems, self).writeXML(filename, self.items)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
class LibraryGenerator(object):&lt;br /&gt;
    def __init__(self, libname, shortname):&lt;br /&gt;
        self.libname = libname&lt;br /&gt;
        self.shortname = shortname&lt;br /&gt;
        self.asset_dir = os.path.abspath(os.path.join(&amp;quot;assets&amp;quot;, &amp;quot;{0}AssetSet&amp;quot;.format(shortname)))&lt;br /&gt;
        self.inv_dir = os.path.abspath(os.path.join(&amp;quot;inventory&amp;quot;, shortname))&lt;br /&gt;
        self.asset_xmlfile = &amp;quot;{0}AssetSet.xml&amp;quot;.format(shortname)&lt;br /&gt;
        self.folders_xmlfile = &amp;quot;{0}InvFolders.xml&amp;quot;.format(shortname)&lt;br /&gt;
        self.items_xmlfile = &amp;quot;{0}InvItems.xml&amp;quot;.format(shortname)&lt;br /&gt;
        self.skips = []&lt;br /&gt;
&lt;br /&gt;
        self.matchj2k = re.compile(&amp;quot;\.j2k$&amp;quot;)&lt;br /&gt;
        self.matchtxt = re.compile(&amp;quot;\.txt$&amp;quot;)&lt;br /&gt;
        self.matchlsl = re.compile(&amp;quot;\.lsl$&amp;quot;)&lt;br /&gt;
        self.endsinslash = re.compile(&amp;quot;/$&amp;quot;)&lt;br /&gt;
        self.commentline = re.compile(&amp;quot;^\s*#&amp;quot;)&lt;br /&gt;
        self.blankline = re.compile(&amp;quot;^\s*$&amp;quot;)&lt;br /&gt;
        self.assetlistline = re.compile(&amp;quot;^\s*([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\s*(\d+)\s*(\d+)\s*(.*\S)\s*$&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def set_skip_patterns(self, skips):&lt;br /&gt;
        self.skips = skips&lt;br /&gt;
&lt;br /&gt;
    def set_asset_dir(self, asset_dir):&lt;br /&gt;
        self.asset_dir = asset_dir&lt;br /&gt;
&lt;br /&gt;
    def set_inv_dir(self, inv_dir):&lt;br /&gt;
        self.inv_dir = inv_dir&lt;br /&gt;
&lt;br /&gt;
    def set_asset_xmlfile(self, asset_xmlfile):&lt;br /&gt;
        self.asset_xmlfile = asset_xmlfile&lt;br /&gt;
&lt;br /&gt;
    def set_folders_xmlfile(self, folders_xmlfile):&lt;br /&gt;
        self.folders_xmlfile = folders_xmlfile&lt;br /&gt;
&lt;br /&gt;
    def set_items_xmlfile(self, items_xmlfile):&lt;br /&gt;
        self.items_xmlfile = items_xmlfile&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    def run(self):&lt;br /&gt;
        # Create our storage for things, and read any current&lt;br /&gt;
        #  XML files if they exist&lt;br /&gt;
&lt;br /&gt;
        self.assets = AssetSet()&lt;br /&gt;
        self.assets.readXML(os.path.join(self.asset_dir, self.asset_xmlfile))&lt;br /&gt;
&lt;br /&gt;
        self.folders = InvFolders()&lt;br /&gt;
        self.folders.readXML(os.path.join(self.inv_dir, self.folders_xmlfile))&lt;br /&gt;
&lt;br /&gt;
        self.items = InvItems(self.folders)&lt;br /&gt;
        self.items.readXML(os.path.join(self.inv_dir, self.items_xmlfile))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        # Run the recursive directory processor thingie&lt;br /&gt;
&lt;br /&gt;
        origdir = os.getcwd()&lt;br /&gt;
        os.chdir(self.asset_dir)&lt;br /&gt;
        self.process_dir(opensim_library_root_uuid, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
        os.chdir(origdir)&lt;br /&gt;
&lt;br /&gt;
        # Write the XML files, saving copies of the old ones out of paranoia&lt;br /&gt;
&lt;br /&gt;
        if os.path.exists(os.path.join(self.asset_dir, self.asset_xmlfile)):&lt;br /&gt;
            shutil.copy2(os.path.join(self.asset_dir, self.asset_xmlfile),&lt;br /&gt;
                         os.path.join(self.asset_dir, &amp;quot;{0}-old&amp;quot;.format(self.asset_xmlfile)))&lt;br /&gt;
&lt;br /&gt;
        self.assets.writeXML(os.path.join(self.asset_dir, self.asset_xmlfile))&lt;br /&gt;
&lt;br /&gt;
        if os.path.exists(os.path.join(self.inv_dir, self.folders_xmlfile)):&lt;br /&gt;
            shutil.copy2(os.path.join(self.inv_dir, self.folders_xmlfile),&lt;br /&gt;
                         os.path.join(self.inv_dir, &amp;quot;{0}-old&amp;quot;.format(self.folders_xmlfile)))&lt;br /&gt;
&lt;br /&gt;
        self.folders.writeXML(os.path.join(self.inv_dir, self.folders_xmlfile))&lt;br /&gt;
&lt;br /&gt;
        if os.path.exists(os.path.join(self.inv_dir, self.items_xmlfile)):&lt;br /&gt;
            shutil.copy2(os.path.join(self.inv_dir, self.items_xmlfile),&lt;br /&gt;
                         os.path.join(self.inv_dir, &amp;quot;{0}-old&amp;quot;.format(self.items_xmlfile)))&lt;br /&gt;
&lt;br /&gt;
        self.items.writeXML(os.path.join(self.inv_dir, self.items_xmlfile))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    def process_dir(self, parent_uuid, my_name, path):&lt;br /&gt;
        origdir = os.getcwd()&lt;br /&gt;
        sys.stderr.write(&amp;quot;Processing directory: {0} \n&amp;quot;.format(os.path.join(self.asset_dir, path)))&lt;br /&gt;
        if my_name != &amp;quot;&amp;quot;:&lt;br /&gt;
            os.chdir(my_name)&lt;br /&gt;
        else:&lt;br /&gt;
            my_name = self.libname&lt;br /&gt;
            &lt;br /&gt;
        # Create the folder XML blob if necessary&lt;br /&gt;
&lt;br /&gt;
        curfolder = self.folders.ensureexists(my_name, parent_uuid)&lt;br /&gt;
        my_uuid = curfolder[&amp;quot;folderID&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
        # Walk through this directory and process everything in it&lt;br /&gt;
&lt;br /&gt;
        for fname in os.listdir(&amp;quot;.&amp;quot;):&lt;br /&gt;
            statinfo = os.stat(fname)&lt;br /&gt;
&lt;br /&gt;
            doskip = False&lt;br /&gt;
            for skip in self.skips:&lt;br /&gt;
                if re.search(skip, fname):&lt;br /&gt;
                    doskip = True&lt;br /&gt;
            if doskip: continue&lt;br /&gt;
&lt;br /&gt;
            if stat.S_ISDIR(statinfo.st_mode):&lt;br /&gt;
                self.process_dir(my_uuid, fname, os.path.join(path, fname) )&lt;br /&gt;
                continue&lt;br /&gt;
&lt;br /&gt;
            fpath = os.path.join(path, fname)&lt;br /&gt;
            &lt;br /&gt;
            if fpath == self.asset_xmlfile:&lt;br /&gt;
                # Ignore the XML file we're working on!&lt;br /&gt;
                continue&lt;br /&gt;
&lt;br /&gt;
            elif fname == &amp;quot;addassets.lis&amp;quot;:&lt;br /&gt;
                # Ignore the file specifing pre-existing assets to add&lt;br /&gt;
                #   to inventory&lt;br /&gt;
                continue&lt;br /&gt;
&lt;br /&gt;
            elif self.matchj2k.search(fname):&lt;br /&gt;
                asset_type = 0&lt;br /&gt;
            elif self.matchtxt.search(fname):&lt;br /&gt;
                asset_type = 7&lt;br /&gt;
            elif self.matchlsl.search(fname):&lt;br /&gt;
                asset_type = 10&lt;br /&gt;
            else:&lt;br /&gt;
                sys.stderr.write(&amp;quot;WARNING: Skipping unrecognized file &amp;quot; +&lt;br /&gt;
                                 fname + &amp;quot;\n&amp;quot;)&lt;br /&gt;
                continue&lt;br /&gt;
&lt;br /&gt;
            # Strip the extension for aesthetic purposes&lt;br /&gt;
            #  (Right now, that must be .txt, .lsl, or .j2k, so&lt;br /&gt;
            #   we can assume it's 4 characters long.)&lt;br /&gt;
&lt;br /&gt;
            name = fname[0:-4]&lt;br /&gt;
&lt;br /&gt;
            # Create the asset XML blob if necessary&lt;br /&gt;
&lt;br /&gt;
            ass = self.assets.findbyfilename(fpath)&lt;br /&gt;
            if ass == None:&lt;br /&gt;
                ass = self.assets.addasset(uuid.uuid4(), name, asset_type,&lt;br /&gt;
                                           asset_type, os.path.join(path, fname))&lt;br /&gt;
&lt;br /&gt;
            # Create the inventory XML blob if necessary&lt;br /&gt;
&lt;br /&gt;
            self.items.ensureexists(name, ass['assetID'], asset_type, asset_type, my_uuid)&lt;br /&gt;
&lt;br /&gt;
        # Add pre-existing assets (to inventory only) from file addassets.lis&lt;br /&gt;
&lt;br /&gt;
        if os.path.exists(&amp;quot;addassets.lis&amp;quot;):&lt;br /&gt;
            asslis = open(&amp;quot;addassets.lis&amp;quot;)&lt;br /&gt;
            for line in asslis:&lt;br /&gt;
                line.rstrip(&amp;quot;\r\n&amp;quot;)&lt;br /&gt;
                if self.blankline.search(line) or self.commentline.search(line):&lt;br /&gt;
                    continue&lt;br /&gt;
                match = self.assetlistline.search(line)&lt;br /&gt;
                if match == None:&lt;br /&gt;
                    sys.stderr.write(&amp;quot;WARNING : error parsing line in {0}\n&amp;quot;.&lt;br /&gt;
                                     format(os.path.join(path, &amp;quot;addassets.lis&amp;quot;)))&lt;br /&gt;
                    sys.stderr.write(&amp;quot;Offending line: \&amp;quot;{0}\&amp;quot;\n&amp;quot;.format(line))&lt;br /&gt;
                    continue&lt;br /&gt;
                self.items.ensureexists(match.group(4), match.group(1), match.group(2), match.group(3), my_uuid)&lt;br /&gt;
            asslis.close()&lt;br /&gt;
&lt;br /&gt;
        # We're done; restore the CWD to where we started and return&lt;br /&gt;
&lt;br /&gt;
        os.chdir(origdir)&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
&lt;br /&gt;
    usage = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    updatelibrary.py -n &amp;quot;Library Name&amp;quot; -s ShortLibName [options]&lt;br /&gt;
&lt;br /&gt;
  Goes through your asset set directory.  (See below for how to specify&lt;br /&gt;
  it, and what the default is.)  Finds all .j2k images, .txt files, and&lt;br /&gt;
  .lsl files in that directory and all subdirectories.  Generates an&lt;br /&gt;
  Asset Set XML file for all of those files.  Also generates library&lt;br /&gt;
  Inventory Folder and Inventory Item XML files for all of those assets,&lt;br /&gt;
  organized in a folder hierarchy that matches the directory hierarchy.&lt;br /&gt;
&lt;br /&gt;
  Additional assets that already exist in the grid's asset store may be&lt;br /&gt;
  specified in each directory in a file named &amp;quot;addassets.lis&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
  For more documentation, see http://opensimulator.org/wiki/Custom_Libraries&lt;br /&gt;
&lt;br /&gt;
  When done, you will need to manually add your asset directory to the&lt;br /&gt;
  OpenSim AssetSets.xml file (in &amp;quot;assets&amp;quot; under the OpenSim bin&lt;br /&gt;
  directory), and your inventory XML files to the Libraries.xml file (in&lt;br /&gt;
  &amp;quot;inventory&amp;quot; under the OpenSim bin directory).&lt;br /&gt;
&lt;br /&gt;
  Written 2011 by Rob Knop aka Prospero Frobozz.  I've only used this on&lt;br /&gt;
  Linux; I have no idea how well it will function on Windows.  If you're&lt;br /&gt;
  on Windows, I recommend http://www.ubuntu.com&lt;br /&gt;
&lt;br /&gt;
  Run updatelibrary.py --help for option listings&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    parser = OptionParser(usage = usage)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-n&amp;quot;, &amp;quot;--lib-name&amp;quot;, action=&amp;quot;store&amp;quot;, type=&amp;quot;string&amp;quot;,&lt;br /&gt;
                      dest=&amp;quot;libname&amp;quot;, default=&amp;quot;New Library&amp;quot;,&lt;br /&gt;
                      help=&amp;quot;The name of your library as it appears in the viewer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-s&amp;quot;, &amp;quot;--short-name&amp;quot;, action=&amp;quot;store&amp;quot;, type=&amp;quot;string&amp;quot;,&lt;br /&gt;
                      dest=&amp;quot;shortname&amp;quot;, default=&amp;quot;NewLibrary&amp;quot;,&lt;br /&gt;
                      help=&amp;quot;A name without spaces of your library for filename purposes.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-a&amp;quot;, &amp;quot;--asset-dir&amp;quot;, action=&amp;quot;store&amp;quot;,&lt;br /&gt;
                      type=&amp;quot;string&amp;quot;, dest=&amp;quot;asset_dir&amp;quot;,&lt;br /&gt;
                      default=None,&lt;br /&gt;
                      help=&amp;quot;Directory where your .j2k, .txt, and .lsl files are, and which will &amp;quot;+&lt;br /&gt;
                      &amp;quot;serve as the Assset Set in the OpenSim library.  Defaults to assets/[shortname]AssetSet&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;-i&amp;quot;, &amp;quot;--inv-dir&amp;quot;, action=&amp;quot;store&amp;quot;, type=&amp;quot;string&amp;quot;,&lt;br /&gt;
                      dest=&amp;quot;inv_dir&amp;quot;, default=None,&lt;br /&gt;
                      help=&amp;quot;Directory in which to put the inventory XML files.  Defaults to &amp;quot;+&lt;br /&gt;
                      &amp;quot;inventory/[shortname]&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;&amp;quot;, &amp;quot;--asset-xmlfile&amp;quot;, action=&amp;quot;store&amp;quot;,&lt;br /&gt;
                      type=&amp;quot;string&amp;quot;, dest=&amp;quot;asset_xmlfile&amp;quot;, default=None,&lt;br /&gt;
                      help=&amp;quot;Name of Asset XML file.  Defaults to [shortname]AssetSet.xml&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;&amp;quot;, &amp;quot;--folders-xmlfile&amp;quot;, action=&amp;quot;store&amp;quot;,&lt;br /&gt;
                      type=&amp;quot;string&amp;quot;, dest=&amp;quot;folders_xmlfile&amp;quot;, default=None,&lt;br /&gt;
                      help=&amp;quot;Name of Inventory Folders XML file.  Defaults to [shortname]InvFolders.xml&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;&amp;quot;, &amp;quot;--items-xmlfile&amp;quot;, action=&amp;quot;store&amp;quot;,&lt;br /&gt;
                      type=&amp;quot;string&amp;quot;, dest=&amp;quot;items_xmlfile&amp;quot;, default=None,&lt;br /&gt;
                      help=&amp;quot;Name of Inventory Folders XML file.  Defaults to [shortname]InvItems.xml&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    parser.add_option(&amp;quot;&amp;quot;, &amp;quot;--skip&amp;quot;, action=&amp;quot;append&amp;quot;, type=&amp;quot;string&amp;quot;,&lt;br /&gt;
                      dest=&amp;quot;skip_patterns&amp;quot;,&lt;br /&gt;
                      default=['^\.hg$', '^\.git$', '^\.svn$'],&lt;br /&gt;
                      help=&amp;quot;Regex for filenames to not process&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if len(sys.argv) &amp;lt; 2:&lt;br /&gt;
        parser.print_usage()&lt;br /&gt;
        sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
    options, args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        generator = LibraryGenerator(options.libname, options.shortname)&lt;br /&gt;
&lt;br /&gt;
        if options.skip_patterns:&lt;br /&gt;
            generator.set_skip_patterns(options.skip_patterns)&lt;br /&gt;
&lt;br /&gt;
        if options.asset_dir != None:&lt;br /&gt;
            generator.set_asset_dir(options.asset_dir)&lt;br /&gt;
&lt;br /&gt;
        if options.inv_dir != None:&lt;br /&gt;
            generator.set_inv_dir(options.inv_dir)&lt;br /&gt;
&lt;br /&gt;
        if options.asset_xmlfile != None:&lt;br /&gt;
            generator.set_asset_xmlfile(options.asset_xmlfile)&lt;br /&gt;
&lt;br /&gt;
        if options.folders_xmlfile != None:&lt;br /&gt;
            generator.set_folders_xmlfile(options.folders_xmlfile)&lt;br /&gt;
&lt;br /&gt;
        if options.items_xmlfile != None:&lt;br /&gt;
            generator.set_items_xmlfile(options.items_xmlfile)&lt;br /&gt;
&lt;br /&gt;
        generator.run()&lt;br /&gt;
&lt;br /&gt;
    except Exception:&lt;br /&gt;
        print &amp;quot;FAIL&amp;quot;&lt;br /&gt;
        traceback.print_exc()&lt;br /&gt;
        sys.exit(20)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# **********************************************************************&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Custom_Libraries</id>
		<title>Custom Libraries</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Custom_Libraries"/>
				<updated>2011-07-16T02:17:51Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Library Overview=&lt;br /&gt;
&lt;br /&gt;
The library in OpenSim is described in the file &amp;lt;tt&amp;gt;bin/inventory/Libraries.xml&amp;lt;/tt&amp;gt;.  That file defines a number of other libraries, each of which have a file for folders and a file for items.  The files described in &amp;lt;tt&amp;gt;Libraries.xml&amp;lt;/tt&amp;gt; are read each time the server starts.  (Note, however, that the viewer caches library information, so you may need to clear your cache viewer side to see changes you've made.)&lt;br /&gt;
&lt;br /&gt;
If you want to add assets to the Library on your OpenSim server, there are two fundamental steps.  The first is generating the assets, the second is generating these inventory XML files.  The assets have information about the objects themselves; the geometry of prims, the image of textures, the text of notecards, etc.  The inventory items are entries in the folders that allow users to actually access the assets.&lt;br /&gt;
&lt;br /&gt;
If you want ready-to-import libraries, you could check out the [[Free Assets]] section...&lt;br /&gt;
&lt;br /&gt;
=Generating Assets=&lt;br /&gt;
&lt;br /&gt;
The server also is able to bulk import asset sets.  These asset sets are described in the file &amp;lt;tt&amp;gt;bin/assets/AssetSets.xml&amp;lt;/tt&amp;gt;.  Each asset set has its own XML file describing the assets, coupled with another file that has the actual asset data (image or text data).  You can define new asset sets and add the XML file describing them to &amp;lt;tt&amp;gt;AssetSets.xml&amp;lt;/tt&amp;gt;.  When Robust (in grid mode) or OpenSim (in standalone mode) starts up, it looks at the AssetSets.xml file.  It figures out which of the assets in the asset sets don't exist in its asset store, and adds them.&lt;br /&gt;
&lt;br /&gt;
==Generating Assets With the Viewer==&lt;br /&gt;
&lt;br /&gt;
The easiest way to generate assets is just to create them in-world, or upload them with the viewer.  If you do this, there is no need to muck about with asset sets.&lt;br /&gt;
&lt;br /&gt;
==In Bulk==&lt;br /&gt;
&lt;br /&gt;
However, if you want to create assets in bulk, then you need to define your own asset set.  Look at some of the asset sets defined in &amp;lt;tt&amp;gt;AssetSets.xml&amp;lt;/tt&amp;gt;, to get a sense for what the an asset set XML file looks like.&lt;br /&gt;
&lt;br /&gt;
Practically speaking, at the moment, you can only import lsl scripts, notecards, and textures this way.  There are two steps.  First, you must get the assets into the right format.  Second, you must generate the XML files for the assets.&lt;br /&gt;
&lt;br /&gt;
===Getting Assets into the Right Formats===&lt;br /&gt;
&lt;br /&gt;
Notecards and lsl files are plain text files.&lt;br /&gt;
&lt;br /&gt;
Images have a size that is a power of two on each side.  That is, both the width and height must be one of 16, 32, 64, 128, 256, 512, or 1024.  They must also be in be in JPEG2000 .j2k format.  You can use the [http://www.openjpeg.org/ OpenJPEG] utilities to convert from other formats to JPEG2000.  Note that version 1.3 of the OpenJPEG libraries does not support greyscale images or transparency.  It will fail to work on greyscale images, and will remove any alpha channel from transparent images.  As of revision 824 in the OpenJPEG svn archives, it also supports transparency, and may read PNG files directly, and (at least with PNG files) handles greyscale images.  It's worth compiling a more recent version [http://code.google.com/p/openjpeg/source/checkout from the svn archives], at least until a version of OpenJPEG is officially released that supports these features.&lt;br /&gt;
&lt;br /&gt;
Convert a single image file to OpenJPEG with&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;tt&amp;gt;image_to_j2k -i ''inputfile'' -o ''outputbase''.j2k -r 100,30,10&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note on compression: the values after &amp;quot;-r&amp;quot; are the compression ratios to store in the OpenJPEG file.  If you upload an image with the viewer (at least with Imprudence), the list of compression ratios used is 1920,480,120,30,10.  Bigger numbers mean more compression, and hence blurrier images.  The advantage of storing multiple levels of compression is that when the (small amount) of data for a high level of compression is downloaded, at least that much can be rendered.  This is why when you watch a texture load, it starts blurry, and (at least if you're lucky) eventually becomes sharp.  A compression level of 1 is lossless... and also uses a lot of space in the asset store, and a lot of bandwidth when it's sent down.  A smallest compression of 10 should be good for most purposes.  However, for things like sculpt maps (or small, precise textures), you may want to add a compression ratio of 1 to the end of the arguments.&lt;br /&gt;
&lt;br /&gt;
Two scripts exist, a [[jp2_batch_converter|Linux script]] or [[Jp2_batch_converter_for_windows|Windows script]] in perl.  They use ImageMagick and image_to_j2k to resize image files to the appropriate size and convert them to j2k files (although named with an extension of .jp2, since that's what the viewer expects for some perverse reason).  However, if you want to use this, be aware of some caveats:&lt;br /&gt;
&lt;br /&gt;
* The script ''deletes'' your original image file.&lt;br /&gt;
* The script ''does no error checking''.  This means that if for whatever reason (and there can be several!) image_to_j2k file fails, the script will delete your image file ''anyway''.  This could make you sad if, like a certain stupid wiki page editor, you didn't make backup copies first.&lt;br /&gt;
* The script makes j2k files with compression ratios 20,10,1.  While this is great for image files that are bundled with the viewer, it's not good for server-side image files.  That lossless compression means gratuitous use of server asset store space and bandwidth.&lt;br /&gt;
&lt;br /&gt;
Maybe one day there will be an updated script....&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Creating Asset Set XML Files===&lt;br /&gt;
&lt;br /&gt;
Once you have all your assets in the right format, you need to create the AssetSet XML file.  Ultimately, you're going to want to make a new subdirectory underneath &amp;lt;tt&amp;gt;bin/assets&amp;lt;/tt&amp;gt;.  For example, let's suppose you're making a new asset set called &amp;lt;tt&amp;gt;MyAwesomeAssetSet&amp;lt;/tt&amp;gt;.  You'll need to create, in that directory, a file &amp;lt;tt&amp;gt;MyAwesomeAssetSet.xml&amp;lt;/tt&amp;gt;.  You can use the python script [[updatelibrary.py]] to generate this file.  It will also generate the inventory XML files needed.  This script is documented [[#Generating_Inventory_and_Asset_Files|below]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Terrains==&lt;br /&gt;
===Create a terrain heightmap===&lt;br /&gt;
&lt;br /&gt;
* [[Using_L3DT|Creating custom terrains with L3DT]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Generating Inventory Items=&lt;br /&gt;
&lt;br /&gt;
The folders that show up in the library are defined in &amp;lt;tt&amp;gt;bin/inventory/Libraries.xml&amp;lt;/tt&amp;gt;.  That xml file has an entry for each library; each library is defined by two XML files.  One describes the folders in the library, (i.e. subfolders underneath a top folder that shows up underneath OpenSim Library), and the other describes the items in those folders.  What you probably want to do is create a new library.  Make a subdirectory for that library.  Generate the two XML files describing the folders and items in that library.  Add an entry to &amp;lt;tt&amp;gt;Libraries.xml&amp;lt;/tt&amp;gt; giving the name of the two XML files for your library.  You're done!  Except that it's very painful, because it will involve copying and generating a lot of UUIDs.  As such, except for the most trivial of libraries, you don't want to do this by hand.&lt;br /&gt;
&lt;br /&gt;
==Generating Inventory and Asset Files==&lt;br /&gt;
&lt;br /&gt;
The python script &amp;lt;tt&amp;gt;[[updatelibrary.py]]&amp;lt;/tt&amp;gt; is able to generate asset and inventory XML files at the same time.  Basically, you maintain a tree of assets in an asset set directory, and run this script to sync the XML files with your tree.  (Note that at the moment it can only ''add'' assets; it will not delete them if you remove them frmo yoru tree.)  It is able to add both assets in your asset set, ''and'' pre-existing assets already in your grid's asset store (for which you don't have to add something to an asset set.)&lt;br /&gt;
&lt;br /&gt;
In order to use it, you must:&lt;br /&gt;
* Create an asset set directory&lt;br /&gt;
* Arrange all of your asset files (text files for scripts and notecards, properly sized j2k files for textures) in directories underneath that asset set directory that will correspond to the folders and subfolders underneath your top-level library directory.&lt;br /&gt;
* Decide on the name of your library, and on a short version (without spaces) that will be used for filenames.&lt;br /&gt;
&lt;br /&gt;
For example, if you're making a library that will show up as a folder under the OpenSim Library folder as &amp;quot;My Awesome Library&amp;quot;, you could build it inside the MyAwesomeAssetSet directory.  Underneath that directory, make subdirectories named Textures, Clothing, Objects, and so forth.  In the Textures directory, put your properlly formatted j2k files.  Right now, the script only handles textures (.j2k), notecards (.txt), and scripts (.lsl).&lt;br /&gt;
&lt;br /&gt;
In addition, in each directory you can put a file named &amp;quot;addassets.lis&amp;quot;.  You can list assets that are already in your grid's asset store here to be added to the library at the folder corresponding to the directory of each adassets.lis file.  ''Any'' type of asset may be added to the library this way.  This file is a series of lines, each of which follows the format&lt;br /&gt;
&lt;br /&gt;
  asset_uuid  asset_type  inventory_type  name of object in inventory&lt;br /&gt;
&lt;br /&gt;
A viewer such as Imprudence is able to tell you the asset_uuid of anything in your inventory; you can just copy this to the addassets.lis file.  asset_type is a number, depending on the type of asset:&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
!Type of Object&lt;br /&gt;
!asset_type&lt;br /&gt;
!&lt;br /&gt;
!Type of Object&lt;br /&gt;
!asset_type&lt;br /&gt;
|-&lt;br /&gt;
|Texture&lt;br /&gt;
|0&lt;br /&gt;
|&lt;br /&gt;
|Notecard&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|Sound&lt;br /&gt;
|1&lt;br /&gt;
|&lt;br /&gt;
|LSL Text&lt;br /&gt;
|10&lt;br /&gt;
|-&lt;br /&gt;
|Calling Card&lt;br /&gt;
|2&lt;br /&gt;
|&lt;br /&gt;
|LSL Bytecode&lt;br /&gt;
|11&lt;br /&gt;
|-&lt;br /&gt;
|Landmark&lt;br /&gt;
|3&lt;br /&gt;
|&lt;br /&gt;
|Bodypart&lt;br /&gt;
|13&lt;br /&gt;
|-&lt;br /&gt;
|Clothing&lt;br /&gt;
|5&lt;br /&gt;
|&lt;br /&gt;
|Animation&lt;br /&gt;
|20&lt;br /&gt;
|-&lt;br /&gt;
|Primitive&lt;br /&gt;
|6&lt;br /&gt;
|&lt;br /&gt;
|Gesture&lt;br /&gt;
|21&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inventory_type is another number, again depending on the type of inventory.  (Inventory type and asset type are not the same thing, although they're often closely related.  Inventory type is what tells the viewer which sort of icon to show next to the inventory item's name.)&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
!Type of Object&lt;br /&gt;
!inventory_type&lt;br /&gt;
!&lt;br /&gt;
!Type of Object&lt;br /&gt;
!inventory_type&lt;br /&gt;
|-&lt;br /&gt;
|Texture&lt;br /&gt;
|0&lt;br /&gt;
|&lt;br /&gt;
|Root Category&lt;br /&gt;
|9&lt;br /&gt;
|-&lt;br /&gt;
|Sound&lt;br /&gt;
|1&lt;br /&gt;
|&lt;br /&gt;
|LSL Script&lt;br /&gt;
|10&lt;br /&gt;
|-&lt;br /&gt;
|Calling Card&lt;br /&gt;
|2&lt;br /&gt;
|&lt;br /&gt;
|Snapshot&lt;br /&gt;
|15&lt;br /&gt;
|-&lt;br /&gt;
|Landmark&lt;br /&gt;
|3&lt;br /&gt;
|&lt;br /&gt;
|Attachment&lt;br /&gt;
|17&lt;br /&gt;
|-&lt;br /&gt;
|Object&lt;br /&gt;
|6&lt;br /&gt;
|&lt;br /&gt;
|Wearable&lt;br /&gt;
|18&lt;br /&gt;
|-&lt;br /&gt;
|Notecard&lt;br /&gt;
|7&lt;br /&gt;
|&lt;br /&gt;
|Animation&lt;br /&gt;
|19&lt;br /&gt;
|-&lt;br /&gt;
|Category&lt;br /&gt;
|8&lt;br /&gt;
|&lt;br /&gt;
|Gesture&lt;br /&gt;
|20&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(There is also the &amp;quot;None&amp;quot; inventory type, which has number -1.  Body Parts and Clothing are both wearables.)&lt;br /&gt;
&lt;br /&gt;
Run the script.  (Run it with &amp;lt;tt&amp;gt;--help&amp;lt;/tt&amp;gt; to get usage instructions.)  It will go through the entire directory tree where you have put your asset files.  It will read the Asset Set, Inventory Folder, and Inventory Item XML files that already exist.  It will then add entries as necessary to those files for any new .j2k, .txt, or .lsl files in your directory tree, as well as for any new entries in any addassets.lis file.&lt;br /&gt;
&lt;br /&gt;
When the script is complete, you need only to edit &amp;lt;tt&amp;gt;inventory/Libraries.xml&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;assets/AssetSets.xml&amp;lt;/tt&amp;gt; to tell it about your new asset set and your new library.  Next time you start up OpenSim or (in grid mode) Robust, it should import your assets and add your entries to the library.  Again, remember that the viewer caches the library list, so you may need to clear your cache on the viewer in order to get the current version of the library.&lt;br /&gt;
&lt;br /&gt;
==Caution==&lt;br /&gt;
&lt;br /&gt;
(I don't know if this is true, but I seem to remember reading somewhere that in grid mode, library inventory xml files must exist not only on the Robust server, but also on each and every individual region OpenSim server.  I do not know if this is the case.  If it is, it certainly complicates matters.)&lt;br /&gt;
&lt;br /&gt;
Additionally, all of this may be obsolete in the future.  Rather than using this code, it's possible that OpenSim will use IAR files to define the library (or, perhaps, default items for avatars).  For the time being, though, try this.&lt;br /&gt;
&lt;br /&gt;
Contact Rob Knop (rknop on freenode, usually hanging out in opensim-dev; Prospero Frobozz on many grids) with any questions about &amp;lt;tt&amp;gt;[[updatelibrary.py]]&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Custom_Libraries</id>
		<title>Custom Libraries</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Custom_Libraries"/>
				<updated>2011-07-16T02:09:08Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* Generating Inventory and Asset Files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Library Overview=&lt;br /&gt;
&lt;br /&gt;
The library in OpenSim is described in the file &amp;lt;tt&amp;gt;bin/inventory/Libraries.xml&amp;lt;/tt&amp;gt;.  That file defines a number of other libraries, each of which have a file for folders and a file for items.  The files described in &amp;lt;tt&amp;gt;Libraries.xml&amp;lt;/tt&amp;gt; are read each time the server starts.  (Note, however, that the viewer caches library information, so you may need to clear your cache viewer side to see changes you've made.)&lt;br /&gt;
&lt;br /&gt;
If you want to add assets to the Library on your OpenSim server, there are two fundamental steps.  The first is generating the assets, the second is generating these inventory XML files.  The assets have information about the objects themselves; the geometry of prims, the image of textures, the text of notecards, etc.  The inventory items are entries in the folders that allow users to actually access the assets.&lt;br /&gt;
&lt;br /&gt;
If you want ready-to-import libraries, you could check out the [[Free Assets]] section...&lt;br /&gt;
&lt;br /&gt;
=Generating Assets=&lt;br /&gt;
&lt;br /&gt;
The server also is able to bulk import asset sets.  These asset sets are described in the file &amp;lt;tt&amp;gt;bin/assets/AssetSets.xml&amp;lt;/tt&amp;gt;.  Each asset set has its own XML file describing the assets, coupled with another file that has the actual asset data (image or text data).  You can define new asset sets and add the XML file describing them to &amp;lt;tt&amp;gt;AssetSets.xml&amp;lt;/tt&amp;gt;.  When Robust (in grid mode) or OpenSim (in standalone mode) starts up, it looks at the AssetSets.xml file.  It figures out which of the assets in the asset sets don't exist in its asset store, and adds them.&lt;br /&gt;
&lt;br /&gt;
==Generating Assets With the Viewer==&lt;br /&gt;
&lt;br /&gt;
The easiest way to generate assets is just to create them in-world, or upload them with the viewer.  If you do this, there is no need to muck about with asset sets.&lt;br /&gt;
&lt;br /&gt;
==In Bulk==&lt;br /&gt;
&lt;br /&gt;
However, if you want to create assets in bulk, then you need to define your own asset set.  Look at some of the asset sets defined in &amp;lt;tt&amp;gt;AssetSets.xml&amp;lt;/tt&amp;gt;, to get a sense for what the an asset set XML file looks like.&lt;br /&gt;
&lt;br /&gt;
Practically speaking, at the moment, you can only import lsl scripts, notecards, and textures this way.  There are two steps.  First, you must get the assets into the right format.  Second, you must generate the XML files for the assets.&lt;br /&gt;
&lt;br /&gt;
===Getting Assets into the Right Formats===&lt;br /&gt;
&lt;br /&gt;
Notecards and lsl files are plain text files.&lt;br /&gt;
&lt;br /&gt;
Images have a size that is a power of two on each side.  That is, both the width and height must be one of 16, 32, 64, 128, 256, 512, or 1024.  They must also be in be in JPEG2000 .j2k format.  You can use the [http://www.openjpeg.org/ OpenJPEG] utilities to convert from other formats to JPEG2000.  Note that version 1.3 of the OpenJPEG libraries does not support greyscale images or transparency.  It will fail to work on greyscale images, and will remove any alpha channel from transparent images.  As of revision 824 in the OpenJPEG svn archives, it also supports transparency, and may read PNG files directly, and (at least with PNG files) handles greyscale images.  It's worth compiling a more recent version [http://code.google.com/p/openjpeg/source/checkout from the svn archives], at least until a version of OpenJPEG is officially released that supports these features.&lt;br /&gt;
&lt;br /&gt;
Convert a single image file to OpenJPEG with&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;tt&amp;gt;image_to_j2k -i ''inputfile'' -o ''outputbase''.j2k -r 100,30,10&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note on compression: the values after &amp;quot;-r&amp;quot; are the compression ratios to store in the OpenJPEG file.  If you upload an image with the viewer (at least with Imprudence), the list of compression ratios used is 1920,480,120,30,10.  Bigger numbers mean more compression, and hence blurrier images.  The advantage of storing multiple levels of compression is that when the (small amount) of data for a high level of compression is downloaded, at least that much can be rendered.  This is why when you watch a texture load, it starts blurry, and (at least if you're lucky) eventually becomes sharp.  A compression level of 1 is lossless... and also uses a lot of space in the asset store, and a lot of bandwidth when it's sent down.  A smallest compression of 10 should be good for most purposes.  However, for things like sculpt maps (or small, precise textures), you may want to add a compression ratio of 1 to the end of the arguments.&lt;br /&gt;
&lt;br /&gt;
Two scripts exist, a [[jp2_batch_converter|Linux script]] or [[Jp2_batch_converter_for_windows|Windows script]] in perl.  They use ImageMagick and image_to_j2k to resize image files to the appropriate size and convert them to j2k files (although named with an extension of .jp2, since that's what the viewer expects for some perverse reason).  However, if you want to use this, be aware of some caveats:&lt;br /&gt;
&lt;br /&gt;
* The script ''deletes'' your original image file.&lt;br /&gt;
* The script ''does no error checking''.  This means that if for whatever reason (and there can be several!) image_to_j2k file fails, the script will delete your image file ''anyway''.  This could make you sad if, like a certain stupid wiki page editor, you didn't make backup copies first.&lt;br /&gt;
* The script makes j2k files with compression ratios 20,10,1.  While this is great for image files that are bundled with the viewer, it's not good for server-side image files.  That lossless compression means gratuitous use of server asset store space and bandwidth.&lt;br /&gt;
&lt;br /&gt;
Maybe one day there will be an updated script....&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Creating Asset Set XML Files===&lt;br /&gt;
&lt;br /&gt;
Once you have all your assets in the right format, you need to create the AssetSet XML file.  Ultimately, you're going to want to make a new subdirectory underneath &amp;lt;tt&amp;gt;bin/assets&amp;lt;/tt&amp;gt;.  For example, let's suppose you're making a new asset set called &amp;lt;tt&amp;gt;MyAwesomeAssetSet&amp;lt;/tt&amp;gt;.  You'll need to create, in that directory, a file &amp;lt;tt&amp;gt;MyAwesomeAssetSet.xml&amp;lt;/tt&amp;gt;.  You can use the python script updatelibrary.py to generate this file.  It will also generate the inventory XML files needed.  This script is documented [[#Generating_Inventory_and_Asset_Files|below]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Terrains==&lt;br /&gt;
===Create a terrain heightmap===&lt;br /&gt;
&lt;br /&gt;
* [[Using_L3DT|Creating custom terrains with L3DT]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Generating Inventory Items=&lt;br /&gt;
&lt;br /&gt;
The folders that show up in the library are defined in &amp;lt;tt&amp;gt;bin/inventory/Libraries.xml&amp;lt;/tt&amp;gt;.  That xml file has an entry for each library; each library is defined by two XML files.  One describes the folders in the library, (i.e. subfolders underneath a top folder that shows up underneath OpenSim Library), and the other describes the items in those folders.  What you probably want to do is create a new library.  Make a subdirectory for that library.  Generate the two XML files describing the folders and items in that library.  Add an entry to &amp;lt;tt&amp;gt;Libraries.xml&amp;lt;/tt&amp;gt; giving the name of the two XML files for your library.  You're done!  Except that it's very painful, because it will involve copying and generating a lot of UUIDs.  As such, except for the most trivial of libraries, you don't want to do this by hand.&lt;br /&gt;
&lt;br /&gt;
==Generating Inventory and Asset Files==&lt;br /&gt;
&lt;br /&gt;
The python script &amp;lt;tt&amp;gt;updatelibrary.py&amp;lt;/tt&amp;gt; is able to generate asset and inventory XML files at the same time.  Basically, you maintain a tree of assets in an asset set directory, and run this script to sync the XML files with your tree.  (Note that at the moment it can only ''add'' assets; it will not delete them if you remove them frmo yoru tree.)  It is able to add both assets in your asset set, ''and'' pre-existing assets already in your grid's asset store (for which you don't have to add something to an asset set.)&lt;br /&gt;
&lt;br /&gt;
In order to use it, you must:&lt;br /&gt;
* Create an asset set directory&lt;br /&gt;
* Arrange all of your asset files (text files for scripts and notecards, properly sized j2k files for textures) in directories underneath that asset set directory that will correspond to the folders and subfolders underneath your top-level library directory.&lt;br /&gt;
* Decide on the name of your library, and on a short version (without spaces) that will be used for filenames.&lt;br /&gt;
&lt;br /&gt;
For example, if you're making a library that will show up as a folder under the OpenSim Library folder as &amp;quot;My Awesome Library&amp;quot;, you could build it inside the MyAwesomeAssetSet directory.  Underneath that directory, make subdirectories named Textures, Clothing, Objects, and so forth.  In the Textures directory, put your properlly formatted j2k files.  Right now, the script only handles textures (.j2k), notecards (.txt), and scripts (.lsl).&lt;br /&gt;
&lt;br /&gt;
In addition, in each directory you can put a file named &amp;quot;addassets.lis&amp;quot;.  You can list assets that are already in your grid's asset store here to be added to the library at the folder corresponding to the directory of each adassets.lis file.  ''Any'' type of asset may be added to the library this way.  This file is a series of lines, each of which follows the format&lt;br /&gt;
&lt;br /&gt;
  asset_uuid  asset_type  inventory_type  name of object in inventory&lt;br /&gt;
&lt;br /&gt;
A viewer such as Imprudence is able to tell you the asset_uuid of anything in your inventory; you can just copy this to the addassets.lis file.  asset_type is a number, depending on the type of asset:&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
!Type of Object&lt;br /&gt;
!asset_type&lt;br /&gt;
!&lt;br /&gt;
!Type of Object&lt;br /&gt;
!asset_type&lt;br /&gt;
|-&lt;br /&gt;
|Texture&lt;br /&gt;
|0&lt;br /&gt;
|&lt;br /&gt;
|Notecard&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|Sound&lt;br /&gt;
|1&lt;br /&gt;
|&lt;br /&gt;
|LSL Text&lt;br /&gt;
|10&lt;br /&gt;
|-&lt;br /&gt;
|Calling Card&lt;br /&gt;
|2&lt;br /&gt;
|&lt;br /&gt;
|LSL Bytecode&lt;br /&gt;
|11&lt;br /&gt;
|-&lt;br /&gt;
|Landmark&lt;br /&gt;
|3&lt;br /&gt;
|&lt;br /&gt;
|Bodypart&lt;br /&gt;
|13&lt;br /&gt;
|-&lt;br /&gt;
|Clothing&lt;br /&gt;
|5&lt;br /&gt;
|&lt;br /&gt;
|Animation&lt;br /&gt;
|20&lt;br /&gt;
|-&lt;br /&gt;
|Primitive&lt;br /&gt;
|6&lt;br /&gt;
|&lt;br /&gt;
|Gesture&lt;br /&gt;
|21&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inventory_type is another number, again depending on the type of inventory.  (Inventory type and asset type are not the same thing, although they're often closely related.  Inventory type is what tells the viewer which sort of icon to show next to the inventory item's name.)&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
!Type of Object&lt;br /&gt;
!inventory_type&lt;br /&gt;
!&lt;br /&gt;
!Type of Object&lt;br /&gt;
!inventory_type&lt;br /&gt;
|-&lt;br /&gt;
|Texture&lt;br /&gt;
|0&lt;br /&gt;
|&lt;br /&gt;
|Root Category&lt;br /&gt;
|9&lt;br /&gt;
|-&lt;br /&gt;
|Sound&lt;br /&gt;
|1&lt;br /&gt;
|&lt;br /&gt;
|LSL Script&lt;br /&gt;
|10&lt;br /&gt;
|-&lt;br /&gt;
|Calling Card&lt;br /&gt;
|2&lt;br /&gt;
|&lt;br /&gt;
|Snapshot&lt;br /&gt;
|15&lt;br /&gt;
|-&lt;br /&gt;
|Landmark&lt;br /&gt;
|3&lt;br /&gt;
|&lt;br /&gt;
|Attachment&lt;br /&gt;
|17&lt;br /&gt;
|-&lt;br /&gt;
|Object&lt;br /&gt;
|6&lt;br /&gt;
|&lt;br /&gt;
|Wearable&lt;br /&gt;
|18&lt;br /&gt;
|-&lt;br /&gt;
|Notecard&lt;br /&gt;
|7&lt;br /&gt;
|&lt;br /&gt;
|Animation&lt;br /&gt;
|19&lt;br /&gt;
|-&lt;br /&gt;
|Category&lt;br /&gt;
|8&lt;br /&gt;
|&lt;br /&gt;
|Gesture&lt;br /&gt;
|20&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(There is also the &amp;quot;None&amp;quot; inventory type, which has number -1.  Body Parts and Clothing are both wearables.)&lt;br /&gt;
&lt;br /&gt;
Run the script.  (Run it with &amp;lt;tt&amp;gt;--help&amp;lt;/tt&amp;gt; to get usage instructions.)  It will go through the entire directory tree where you have put your asset files.  It will read the Asset Set, Inventory Folder, and Inventory Item XML files that already exist.  It will then add entries as necessary to those files for any new .j2k, .txt, or .lsl files in your directory tree, as well as for any new entries in any addassets.lis file.&lt;br /&gt;
&lt;br /&gt;
When the script is complete, you need only to edit &amp;lt;tt&amp;gt;inventory/Libraries.xml&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;assets/AssetSets.xml&amp;lt;/tt&amp;gt; to tell it about your new asset set and your new library.  Next time you start up OpenSim or (in grid mode) Robust, it should import your assets and add your entries to the library.  Again, remember that the viewer caches the library list, so you may need to clear your cache on the viewer in order to get the current version of the library.&lt;br /&gt;
&lt;br /&gt;
==Caution==&lt;br /&gt;
&lt;br /&gt;
(I don't know if this is true, but I seem to remember reading somewhere that in grid mode, library inventory xml files must exist not only on the Robust server, but also on each and every individual region OpenSim server.  I do not know if this is the case.  If it is, it certainly complicates matters.)&lt;br /&gt;
&lt;br /&gt;
Additionally, all of this may be obsolete in the future.  Rather than using this code, it's possible that OpenSim will use IAR files to define the library (or, perhaps, default items for avatars).  For the time being, though, try this.&lt;br /&gt;
&lt;br /&gt;
Contact Rob Knop (rknop on freenode, usually hanging out in opensim-dev; Prospero Frobozz on many grids) with any questions about &amp;lt;tt&amp;gt;updatelibrary.py&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Custom_Libraries</id>
		<title>Custom Libraries</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Custom_Libraries"/>
				<updated>2011-07-16T02:08:13Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* Generating Inventory and Asset Files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Library Overview=&lt;br /&gt;
&lt;br /&gt;
The library in OpenSim is described in the file &amp;lt;tt&amp;gt;bin/inventory/Libraries.xml&amp;lt;/tt&amp;gt;.  That file defines a number of other libraries, each of which have a file for folders and a file for items.  The files described in &amp;lt;tt&amp;gt;Libraries.xml&amp;lt;/tt&amp;gt; are read each time the server starts.  (Note, however, that the viewer caches library information, so you may need to clear your cache viewer side to see changes you've made.)&lt;br /&gt;
&lt;br /&gt;
If you want to add assets to the Library on your OpenSim server, there are two fundamental steps.  The first is generating the assets, the second is generating these inventory XML files.  The assets have information about the objects themselves; the geometry of prims, the image of textures, the text of notecards, etc.  The inventory items are entries in the folders that allow users to actually access the assets.&lt;br /&gt;
&lt;br /&gt;
If you want ready-to-import libraries, you could check out the [[Free Assets]] section...&lt;br /&gt;
&lt;br /&gt;
=Generating Assets=&lt;br /&gt;
&lt;br /&gt;
The server also is able to bulk import asset sets.  These asset sets are described in the file &amp;lt;tt&amp;gt;bin/assets/AssetSets.xml&amp;lt;/tt&amp;gt;.  Each asset set has its own XML file describing the assets, coupled with another file that has the actual asset data (image or text data).  You can define new asset sets and add the XML file describing them to &amp;lt;tt&amp;gt;AssetSets.xml&amp;lt;/tt&amp;gt;.  When Robust (in grid mode) or OpenSim (in standalone mode) starts up, it looks at the AssetSets.xml file.  It figures out which of the assets in the asset sets don't exist in its asset store, and adds them.&lt;br /&gt;
&lt;br /&gt;
==Generating Assets With the Viewer==&lt;br /&gt;
&lt;br /&gt;
The easiest way to generate assets is just to create them in-world, or upload them with the viewer.  If you do this, there is no need to muck about with asset sets.&lt;br /&gt;
&lt;br /&gt;
==In Bulk==&lt;br /&gt;
&lt;br /&gt;
However, if you want to create assets in bulk, then you need to define your own asset set.  Look at some of the asset sets defined in &amp;lt;tt&amp;gt;AssetSets.xml&amp;lt;/tt&amp;gt;, to get a sense for what the an asset set XML file looks like.&lt;br /&gt;
&lt;br /&gt;
Practically speaking, at the moment, you can only import lsl scripts, notecards, and textures this way.  There are two steps.  First, you must get the assets into the right format.  Second, you must generate the XML files for the assets.&lt;br /&gt;
&lt;br /&gt;
===Getting Assets into the Right Formats===&lt;br /&gt;
&lt;br /&gt;
Notecards and lsl files are plain text files.&lt;br /&gt;
&lt;br /&gt;
Images have a size that is a power of two on each side.  That is, both the width and height must be one of 16, 32, 64, 128, 256, 512, or 1024.  They must also be in be in JPEG2000 .j2k format.  You can use the [http://www.openjpeg.org/ OpenJPEG] utilities to convert from other formats to JPEG2000.  Note that version 1.3 of the OpenJPEG libraries does not support greyscale images or transparency.  It will fail to work on greyscale images, and will remove any alpha channel from transparent images.  As of revision 824 in the OpenJPEG svn archives, it also supports transparency, and may read PNG files directly, and (at least with PNG files) handles greyscale images.  It's worth compiling a more recent version [http://code.google.com/p/openjpeg/source/checkout from the svn archives], at least until a version of OpenJPEG is officially released that supports these features.&lt;br /&gt;
&lt;br /&gt;
Convert a single image file to OpenJPEG with&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;tt&amp;gt;image_to_j2k -i ''inputfile'' -o ''outputbase''.j2k -r 100,30,10&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note on compression: the values after &amp;quot;-r&amp;quot; are the compression ratios to store in the OpenJPEG file.  If you upload an image with the viewer (at least with Imprudence), the list of compression ratios used is 1920,480,120,30,10.  Bigger numbers mean more compression, and hence blurrier images.  The advantage of storing multiple levels of compression is that when the (small amount) of data for a high level of compression is downloaded, at least that much can be rendered.  This is why when you watch a texture load, it starts blurry, and (at least if you're lucky) eventually becomes sharp.  A compression level of 1 is lossless... and also uses a lot of space in the asset store, and a lot of bandwidth when it's sent down.  A smallest compression of 10 should be good for most purposes.  However, for things like sculpt maps (or small, precise textures), you may want to add a compression ratio of 1 to the end of the arguments.&lt;br /&gt;
&lt;br /&gt;
Two scripts exist, a [[jp2_batch_converter|Linux script]] or [[Jp2_batch_converter_for_windows|Windows script]] in perl.  They use ImageMagick and image_to_j2k to resize image files to the appropriate size and convert them to j2k files (although named with an extension of .jp2, since that's what the viewer expects for some perverse reason).  However, if you want to use this, be aware of some caveats:&lt;br /&gt;
&lt;br /&gt;
* The script ''deletes'' your original image file.&lt;br /&gt;
* The script ''does no error checking''.  This means that if for whatever reason (and there can be several!) image_to_j2k file fails, the script will delete your image file ''anyway''.  This could make you sad if, like a certain stupid wiki page editor, you didn't make backup copies first.&lt;br /&gt;
* The script makes j2k files with compression ratios 20,10,1.  While this is great for image files that are bundled with the viewer, it's not good for server-side image files.  That lossless compression means gratuitous use of server asset store space and bandwidth.&lt;br /&gt;
&lt;br /&gt;
Maybe one day there will be an updated script....&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Creating Asset Set XML Files===&lt;br /&gt;
&lt;br /&gt;
Once you have all your assets in the right format, you need to create the AssetSet XML file.  Ultimately, you're going to want to make a new subdirectory underneath &amp;lt;tt&amp;gt;bin/assets&amp;lt;/tt&amp;gt;.  For example, let's suppose you're making a new asset set called &amp;lt;tt&amp;gt;MyAwesomeAssetSet&amp;lt;/tt&amp;gt;.  You'll need to create, in that directory, a file &amp;lt;tt&amp;gt;MyAwesomeAssetSet.xml&amp;lt;/tt&amp;gt;.  You can use the python script updatelibrary.py to generate this file.  It will also generate the inventory XML files needed.  This script is documented [[#Generating_Inventory_and_Asset_Files|below]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Terrains==&lt;br /&gt;
===Create a terrain heightmap===&lt;br /&gt;
&lt;br /&gt;
* [[Using_L3DT|Creating custom terrains with L3DT]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Generating Inventory Items=&lt;br /&gt;
&lt;br /&gt;
The folders that show up in the library are defined in &amp;lt;tt&amp;gt;bin/inventory/Libraries.xml&amp;lt;/tt&amp;gt;.  That xml file has an entry for each library; each library is defined by two XML files.  One describes the folders in the library, (i.e. subfolders underneath a top folder that shows up underneath OpenSim Library), and the other describes the items in those folders.  What you probably want to do is create a new library.  Make a subdirectory for that library.  Generate the two XML files describing the folders and items in that library.  Add an entry to &amp;lt;tt&amp;gt;Libraries.xml&amp;lt;/tt&amp;gt; giving the name of the two XML files for your library.  You're done!  Except that it's very painful, because it will involve copying and generating a lot of UUIDs.  As such, except for the most trivial of libraries, you don't want to do this by hand.&lt;br /&gt;
&lt;br /&gt;
==Generating Inventory and Asset Files==&lt;br /&gt;
&lt;br /&gt;
The python script &amp;lt;tt&amp;gt;updatelibrary.py&amp;lt;/tt&amp;gt; is able to generate asset and inventory XML files at the same time.  Basically, you maintain a tree of assets in an asset set directory, and run this script to sync the XML files with your tree.  (Note that at the moment it can only ''add'' assets; it will not delete them if you remove them frmo yoru tree.)  It is able to add both assets in your asset set, ''and'' pre-existing assets already in your grid's asset store (for which you don't have to add something to an asset set.)&lt;br /&gt;
&lt;br /&gt;
In order to use it, you must:&lt;br /&gt;
* Create an asset set directory&lt;br /&gt;
* Arrange all of your asset files (text files for scripts and notecards, properly sized j2k files for textures) in directories underneath that asset set directory that will correspond to the folders and subfolders underneath your top-level library directory.&lt;br /&gt;
* Decide on the name of your library, and on a short version (without spaces) that will be used for filenames.&lt;br /&gt;
&lt;br /&gt;
For example, if you're making a library that will show up as a folder under the OpenSim Library folder as &amp;quot;My Awesome Library&amp;quot;, you could build it inside the MyAwesomeAssetSet directory.  Underneath that directory, make subdirectories named Textures, Clothing, Objects, and so forth.  In the Textures directory, put your properlly formatted j2k files.  Right now, the script only handles textures (.j2k), notecards (.txt), and scripts (.lsl).&lt;br /&gt;
&lt;br /&gt;
In addition, in each directory you can put a file named &amp;quot;addassets.lis&amp;quot;.  You can list assets that are already in your grid's asset store here to be added to the library at the folder corresponding to the directory of each adassets.lis file.  ''Any'' type of asset may be added to the library this way.  This file is a series of lines, each of which follows the format&lt;br /&gt;
&lt;br /&gt;
  asset_uuid  asset_type  inventory_type  name of object in inventory&lt;br /&gt;
&lt;br /&gt;
A viewer such as Imprudence is able to tell you the asset_uuid of anything in your inventory; you can just copy this to the addassets.lis file.  asset_type is a number, depending on the type of asset:&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
!Type of Object&lt;br /&gt;
!asset_type&lt;br /&gt;
!&lt;br /&gt;
!Type of Object&lt;br /&gt;
!asset_type&lt;br /&gt;
|-&lt;br /&gt;
|Texture&lt;br /&gt;
|0&lt;br /&gt;
|&lt;br /&gt;
|Notecard&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|Sound&lt;br /&gt;
|1&lt;br /&gt;
|&lt;br /&gt;
|LSL Text&lt;br /&gt;
|10&lt;br /&gt;
|-&lt;br /&gt;
|Calling Card&lt;br /&gt;
|2&lt;br /&gt;
|&lt;br /&gt;
|LSL Bytecode&lt;br /&gt;
|11&lt;br /&gt;
|-&lt;br /&gt;
|Landmark&lt;br /&gt;
|3&lt;br /&gt;
|&lt;br /&gt;
|Bodypart&lt;br /&gt;
|13&lt;br /&gt;
|-&lt;br /&gt;
|Clothing&lt;br /&gt;
|5&lt;br /&gt;
|&lt;br /&gt;
|Animation&lt;br /&gt;
|20&lt;br /&gt;
|-&lt;br /&gt;
|Primitive&lt;br /&gt;
|6&lt;br /&gt;
|&lt;br /&gt;
|Gesture&lt;br /&gt;
|21&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inventory_type is another number, again depending on the type of inventory.  (Inventory type and asset type are not the same thing, although they're often closely related.  Inventory type is what tells the viewer which sort of icon to show next to the inventory item's name.)&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
!Type of Object&lt;br /&gt;
!inventory_type&lt;br /&gt;
!&lt;br /&gt;
!Type of Object&lt;br /&gt;
!inventory_type&lt;br /&gt;
|-&lt;br /&gt;
|Texture&lt;br /&gt;
|0&lt;br /&gt;
|&lt;br /&gt;
|Root Category&lt;br /&gt;
|9&lt;br /&gt;
|-&lt;br /&gt;
|Sound&lt;br /&gt;
|1&lt;br /&gt;
|&lt;br /&gt;
|LSL Script&lt;br /&gt;
|10&lt;br /&gt;
|-&lt;br /&gt;
|Calling Card&lt;br /&gt;
|2&lt;br /&gt;
|&lt;br /&gt;
|Snapshot&lt;br /&gt;
|15&lt;br /&gt;
|-&lt;br /&gt;
|Landmark&lt;br /&gt;
|3&lt;br /&gt;
|&lt;br /&gt;
|Attachment&lt;br /&gt;
|17&lt;br /&gt;
|-&lt;br /&gt;
|Object&lt;br /&gt;
|6&lt;br /&gt;
|&lt;br /&gt;
|Wearable&lt;br /&gt;
|18&lt;br /&gt;
|-&lt;br /&gt;
|Notecard&lt;br /&gt;
|7&lt;br /&gt;
|&lt;br /&gt;
|Animation&lt;br /&gt;
|19&lt;br /&gt;
|-&lt;br /&gt;
|Category&lt;br /&gt;
|8&lt;br /&gt;
|&lt;br /&gt;
|Gesture&lt;br /&gt;
|20&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(There is also the &amp;quot;None&amp;quot; inventory type, which has number -1.)&lt;br /&gt;
&lt;br /&gt;
Run the script.  (Run it with &amp;lt;tt&amp;gt;--help&amp;lt;/tt&amp;gt; to get usage instructions.)  It will go through the entire directory tree where you have put your asset files.  It will read the Asset Set, Inventory Folder, and Inventory Item XML files that already exist.  It will then add entries as necessary to those files for any new .j2k, .txt, or .lsl files in your directory tree, as well as for any new entries in any addassets.lis file.&lt;br /&gt;
&lt;br /&gt;
When the script is complete, you need only to edit &amp;lt;tt&amp;gt;inventory/Libraries.xml&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;assets/AssetSets.xml&amp;lt;/tt&amp;gt; to tell it about your new asset set and your new library.  Next time you start up OpenSim or (in grid mode) Robust, it should import your assets and add your entries to the library.  Again, remember that the viewer caches the library list, so you may need to clear your cache on the viewer in order to get the current version of the library.&lt;br /&gt;
&lt;br /&gt;
==Caution==&lt;br /&gt;
&lt;br /&gt;
(I don't know if this is true, but I seem to remember reading somewhere that in grid mode, library inventory xml files must exist not only on the Robust server, but also on each and every individual region OpenSim server.  I do not know if this is the case.  If it is, it certainly complicates matters.)&lt;br /&gt;
&lt;br /&gt;
Additionally, all of this may be obsolete in the future.  Rather than using this code, it's possible that OpenSim will use IAR files to define the library (or, perhaps, default items for avatars).  For the time being, though, try this.&lt;br /&gt;
&lt;br /&gt;
Contact Rob Knop (rknop on freenode, usually hanging out in opensim-dev; Prospero Frobozz on many grids) with any questions about &amp;lt;tt&amp;gt;updatelibrary.py&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Custom_Libraries</id>
		<title>Custom Libraries</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Custom_Libraries"/>
				<updated>2011-07-16T02:06:42Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Library Overview=&lt;br /&gt;
&lt;br /&gt;
The library in OpenSim is described in the file &amp;lt;tt&amp;gt;bin/inventory/Libraries.xml&amp;lt;/tt&amp;gt;.  That file defines a number of other libraries, each of which have a file for folders and a file for items.  The files described in &amp;lt;tt&amp;gt;Libraries.xml&amp;lt;/tt&amp;gt; are read each time the server starts.  (Note, however, that the viewer caches library information, so you may need to clear your cache viewer side to see changes you've made.)&lt;br /&gt;
&lt;br /&gt;
If you want to add assets to the Library on your OpenSim server, there are two fundamental steps.  The first is generating the assets, the second is generating these inventory XML files.  The assets have information about the objects themselves; the geometry of prims, the image of textures, the text of notecards, etc.  The inventory items are entries in the folders that allow users to actually access the assets.&lt;br /&gt;
&lt;br /&gt;
If you want ready-to-import libraries, you could check out the [[Free Assets]] section...&lt;br /&gt;
&lt;br /&gt;
=Generating Assets=&lt;br /&gt;
&lt;br /&gt;
The server also is able to bulk import asset sets.  These asset sets are described in the file &amp;lt;tt&amp;gt;bin/assets/AssetSets.xml&amp;lt;/tt&amp;gt;.  Each asset set has its own XML file describing the assets, coupled with another file that has the actual asset data (image or text data).  You can define new asset sets and add the XML file describing them to &amp;lt;tt&amp;gt;AssetSets.xml&amp;lt;/tt&amp;gt;.  When Robust (in grid mode) or OpenSim (in standalone mode) starts up, it looks at the AssetSets.xml file.  It figures out which of the assets in the asset sets don't exist in its asset store, and adds them.&lt;br /&gt;
&lt;br /&gt;
==Generating Assets With the Viewer==&lt;br /&gt;
&lt;br /&gt;
The easiest way to generate assets is just to create them in-world, or upload them with the viewer.  If you do this, there is no need to muck about with asset sets.&lt;br /&gt;
&lt;br /&gt;
==In Bulk==&lt;br /&gt;
&lt;br /&gt;
However, if you want to create assets in bulk, then you need to define your own asset set.  Look at some of the asset sets defined in &amp;lt;tt&amp;gt;AssetSets.xml&amp;lt;/tt&amp;gt;, to get a sense for what the an asset set XML file looks like.&lt;br /&gt;
&lt;br /&gt;
Practically speaking, at the moment, you can only import lsl scripts, notecards, and textures this way.  There are two steps.  First, you must get the assets into the right format.  Second, you must generate the XML files for the assets.&lt;br /&gt;
&lt;br /&gt;
===Getting Assets into the Right Formats===&lt;br /&gt;
&lt;br /&gt;
Notecards and lsl files are plain text files.&lt;br /&gt;
&lt;br /&gt;
Images have a size that is a power of two on each side.  That is, both the width and height must be one of 16, 32, 64, 128, 256, 512, or 1024.  They must also be in be in JPEG2000 .j2k format.  You can use the [http://www.openjpeg.org/ OpenJPEG] utilities to convert from other formats to JPEG2000.  Note that version 1.3 of the OpenJPEG libraries does not support greyscale images or transparency.  It will fail to work on greyscale images, and will remove any alpha channel from transparent images.  As of revision 824 in the OpenJPEG svn archives, it also supports transparency, and may read PNG files directly, and (at least with PNG files) handles greyscale images.  It's worth compiling a more recent version [http://code.google.com/p/openjpeg/source/checkout from the svn archives], at least until a version of OpenJPEG is officially released that supports these features.&lt;br /&gt;
&lt;br /&gt;
Convert a single image file to OpenJPEG with&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;tt&amp;gt;image_to_j2k -i ''inputfile'' -o ''outputbase''.j2k -r 100,30,10&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note on compression: the values after &amp;quot;-r&amp;quot; are the compression ratios to store in the OpenJPEG file.  If you upload an image with the viewer (at least with Imprudence), the list of compression ratios used is 1920,480,120,30,10.  Bigger numbers mean more compression, and hence blurrier images.  The advantage of storing multiple levels of compression is that when the (small amount) of data for a high level of compression is downloaded, at least that much can be rendered.  This is why when you watch a texture load, it starts blurry, and (at least if you're lucky) eventually becomes sharp.  A compression level of 1 is lossless... and also uses a lot of space in the asset store, and a lot of bandwidth when it's sent down.  A smallest compression of 10 should be good for most purposes.  However, for things like sculpt maps (or small, precise textures), you may want to add a compression ratio of 1 to the end of the arguments.&lt;br /&gt;
&lt;br /&gt;
Two scripts exist, a [[jp2_batch_converter|Linux script]] or [[Jp2_batch_converter_for_windows|Windows script]] in perl.  They use ImageMagick and image_to_j2k to resize image files to the appropriate size and convert them to j2k files (although named with an extension of .jp2, since that's what the viewer expects for some perverse reason).  However, if you want to use this, be aware of some caveats:&lt;br /&gt;
&lt;br /&gt;
* The script ''deletes'' your original image file.&lt;br /&gt;
* The script ''does no error checking''.  This means that if for whatever reason (and there can be several!) image_to_j2k file fails, the script will delete your image file ''anyway''.  This could make you sad if, like a certain stupid wiki page editor, you didn't make backup copies first.&lt;br /&gt;
* The script makes j2k files with compression ratios 20,10,1.  While this is great for image files that are bundled with the viewer, it's not good for server-side image files.  That lossless compression means gratuitous use of server asset store space and bandwidth.&lt;br /&gt;
&lt;br /&gt;
Maybe one day there will be an updated script....&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Creating Asset Set XML Files===&lt;br /&gt;
&lt;br /&gt;
Once you have all your assets in the right format, you need to create the AssetSet XML file.  Ultimately, you're going to want to make a new subdirectory underneath &amp;lt;tt&amp;gt;bin/assets&amp;lt;/tt&amp;gt;.  For example, let's suppose you're making a new asset set called &amp;lt;tt&amp;gt;MyAwesomeAssetSet&amp;lt;/tt&amp;gt;.  You'll need to create, in that directory, a file &amp;lt;tt&amp;gt;MyAwesomeAssetSet.xml&amp;lt;/tt&amp;gt;.  You can use the python script updatelibrary.py to generate this file.  It will also generate the inventory XML files needed.  This script is documented [[#Generating_Inventory_and_Asset_Files|below]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Terrains==&lt;br /&gt;
===Create a terrain heightmap===&lt;br /&gt;
&lt;br /&gt;
* [[Using_L3DT|Creating custom terrains with L3DT]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Generating Inventory Items=&lt;br /&gt;
&lt;br /&gt;
The folders that show up in the library are defined in &amp;lt;tt&amp;gt;bin/inventory/Libraries.xml&amp;lt;/tt&amp;gt;.  That xml file has an entry for each library; each library is defined by two XML files.  One describes the folders in the library, (i.e. subfolders underneath a top folder that shows up underneath OpenSim Library), and the other describes the items in those folders.  What you probably want to do is create a new library.  Make a subdirectory for that library.  Generate the two XML files describing the folders and items in that library.  Add an entry to &amp;lt;tt&amp;gt;Libraries.xml&amp;lt;/tt&amp;gt; giving the name of the two XML files for your library.  You're done!  Except that it's very painful, because it will involve copying and generating a lot of UUIDs.  As such, except for the most trivial of libraries, you don't want to do this by hand.&lt;br /&gt;
&lt;br /&gt;
==Generating Inventory and Asset Files==&lt;br /&gt;
&lt;br /&gt;
The python script &amp;lt;tt&amp;gt;updatelibrary.py&amp;lt;/tt&amp;gt; is able to generate asset and inventory XML files at the same time.  Basically, you maintain a tree of assets in an asset set directory, and run this script to sync the XML files with your tree.  (Note that at the moment it can only ''add'' assets; it will not delete them if you remove them frmo yoru tree.)  It is able to add both assets in your asset set, ''and'' pre-existing assets already in your grid's asset store (for which you don't have to add something to an asset set.)&lt;br /&gt;
&lt;br /&gt;
In order to use it, you must:&lt;br /&gt;
* Create an asset set directory&lt;br /&gt;
* Arrange all of your asset files (text files for scripts and notecards, properly sized j2k files for textures) in directories underneath that asset set directory that will correspond to the folders and subfolders underneath your top-level library directory.&lt;br /&gt;
* Decide on the name of your library, and on a short version (without spaces) that will be used for filenames.&lt;br /&gt;
&lt;br /&gt;
For example, if you're making a library that will show up as a folder under the OpenSim Library folder as &amp;quot;My Awesome Library&amp;quot;, you could build it inside the MyAwesomeAssetSet directory.  Underneath that directory, make subdirectories named Textures, Clothing, Objects, and so forth.  In the Textures directory, put your properlly formatted j2k files.  Right now, the script only handles textures (.j2k), notecards (.txt), and scripts (.lsl).&lt;br /&gt;
&lt;br /&gt;
In addition, in each directory you can put a file named &amp;quot;addassets.lis&amp;quot;.  You can list assets that are already in your grid's asset store here to be added to the library at the folder corresponding to the directory of each adassets.lis file.  ''Any'' type of asset may be added to the library this way.  This file is a series of lines, each of which follows the format&lt;br /&gt;
&lt;br /&gt;
  asset_uuid  asset_type  inventory_type  name of object in inventory&lt;br /&gt;
&lt;br /&gt;
A viewer such as Imprudence is able to tell you the asset_uuid of anything in your inventory; you can just copy this to the addassets.lis file.  asset_type is a number, depending on the type of asset:&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
!Type of Object&lt;br /&gt;
!asset_type&lt;br /&gt;
!&lt;br /&gt;
!Type of Object&lt;br /&gt;
!asset_type&lt;br /&gt;
|-&lt;br /&gt;
|Texture&lt;br /&gt;
|0&lt;br /&gt;
|&lt;br /&gt;
|Notecard&lt;br /&gt;
|7&lt;br /&gt;
|-&lt;br /&gt;
|Sound&lt;br /&gt;
|1&lt;br /&gt;
|&lt;br /&gt;
|LSL Text&lt;br /&gt;
|10&lt;br /&gt;
|-&lt;br /&gt;
|Calling Card&lt;br /&gt;
|2&lt;br /&gt;
|&lt;br /&gt;
|LSL Bytecode&lt;br /&gt;
|11&lt;br /&gt;
|-&lt;br /&gt;
|Landmark&lt;br /&gt;
|3&lt;br /&gt;
|&lt;br /&gt;
|Bodypart&lt;br /&gt;
|13&lt;br /&gt;
|-&lt;br /&gt;
|Clothing&lt;br /&gt;
|5&lt;br /&gt;
|&lt;br /&gt;
|Animation&lt;br /&gt;
|20&lt;br /&gt;
|-&lt;br /&gt;
|Primitive&lt;br /&gt;
|6&lt;br /&gt;
|&lt;br /&gt;
|Gesture&lt;br /&gt;
|21&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inventory_type is another number, again depending on the type of inventory.  (Inventory type and asset type are not the same thing, although they're often closely related.  Inventory type is what tells the viewer which sort of icon to show next to the inventory item's name.)&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;2&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
!Type of Object&lt;br /&gt;
!inventory_type&lt;br /&gt;
!&lt;br /&gt;
!Type of Object&lt;br /&gt;
!inventory_type&lt;br /&gt;
|-&lt;br /&gt;
|Texture&lt;br /&gt;
|0&lt;br /&gt;
|&lt;br /&gt;
|Root Category&lt;br /&gt;
|9&lt;br /&gt;
|-&lt;br /&gt;
|Sound&lt;br /&gt;
|1&lt;br /&gt;
|&lt;br /&gt;
|LSL Script&lt;br /&gt;
|10&lt;br /&gt;
|-&lt;br /&gt;
|Calling Card&lt;br /&gt;
|2&lt;br /&gt;
|&lt;br /&gt;
|Snapshot&lt;br /&gt;
|15&lt;br /&gt;
|-&lt;br /&gt;
|Landmark&lt;br /&gt;
|3&lt;br /&gt;
|&lt;br /&gt;
|Attachment&lt;br /&gt;
|17&lt;br /&gt;
|-&lt;br /&gt;
|Object&lt;br /&gt;
|6&lt;br /&gt;
|&lt;br /&gt;
|Wearable&lt;br /&gt;
|18&lt;br /&gt;
|-&lt;br /&gt;
|Notecard&lt;br /&gt;
|7&lt;br /&gt;
|&lt;br /&gt;
|Animation&lt;br /&gt;
|19&lt;br /&gt;
|-&lt;br /&gt;
|Category&lt;br /&gt;
|8&lt;br /&gt;
|&lt;br /&gt;
|Gesture&lt;br /&gt;
|20&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(There is also the &amp;quot;None&amp;quot; inventory type, which has number -1.)&lt;br /&gt;
&lt;br /&gt;
Run the script.  It will go through the entire directory tree where you have put your asset files.  It will read the Asset Set, Inventory Folder, and Inventory Item XML files that already exist.  It will then add entries as necessary to those files for any new .j2k, .txt, or .lsl files in your directory tree, as well as for any new entries in any addassets.lis file.&lt;br /&gt;
&lt;br /&gt;
When the script is complete, you need only to edit &amp;lt;tt&amp;gt;inventory/Libraries.xml&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;assets/AssetSets.xml&amp;lt;/tt&amp;gt; to tell it about your new asset set and your new library.  Next time you start up OpenSim or (in grid mode) Robust, it should import your assets and add your entries to the library.  Again, remember that the viewer caches the library list, so you may need to clear your cache on the viewer in order to get the current version of the library.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Caution==&lt;br /&gt;
&lt;br /&gt;
(I don't know if this is true, but I seem to remember reading somewhere that in grid mode, library inventory xml files must exist not only on the Robust server, but also on each and every individual region OpenSim server.  I do not know if this is the case.  If it is, it certainly complicates matters.)&lt;br /&gt;
&lt;br /&gt;
Additionally, all of this may be obsolete in the future.  Rather than using this code, it's possible that OpenSim will use IAR files to define the library (or, perhaps, default items for avatars).  For the time being, though, try this.&lt;br /&gt;
&lt;br /&gt;
Contact Rob Knop (rknop on freenode, usually hanging out in opensim-dev; Prospero Frobozz on many grids) with any questions about &amp;lt;tt&amp;gt;updatelibrary.py&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Custom_Libraries</id>
		<title>Custom Libraries</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Custom_Libraries"/>
				<updated>2011-07-15T05:24:19Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* Generating Assets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to add assets to the Library on your OpenSim server, there are two fundamental steps.  The first is generating the assets, the second is generating the inventory items.  The assets have information about the objects themselves; the geometry of prims, the image of textures, the text of notecards, etc.  The inventory items are entries in the folders that allow users to actually access the assets.&lt;br /&gt;
&lt;br /&gt;
If you want ready-to-import libraries, you could check out the [[Free Assets]] section...&lt;br /&gt;
&lt;br /&gt;
=Generating Assets=&lt;br /&gt;
&lt;br /&gt;
==With the Viewer==&lt;br /&gt;
&lt;br /&gt;
The easiest way to generate assets is just to create them in-world, or upload them with the viewer.&lt;br /&gt;
&lt;br /&gt;
==In Bulk==&lt;br /&gt;
&lt;br /&gt;
However, if you want to create assets in bulk, for instance from a directory of image files, you can create images and add them into the default asset sets.  These are found in the &amp;lt;tt&amp;gt;bin/assets&amp;lt;/tt&amp;gt; directory.  The file &amp;lt;tt&amp;gt;AssetSets.xml&amp;lt;/tt&amp;gt; has a list of &amp;quot;asset sets&amp;quot;, directories that contain the actual data for the assets and an XML file that has the metadata.  Look at the XML file for the example; the format is not too complicated.&lt;br /&gt;
&lt;br /&gt;
Practically speaking, at the moment, you can only import lsl scripts, notecards, and textures this way.  There are two steps.  First, you must get the assets into the right format.  Second, you must generate the XML files for the assets.&lt;br /&gt;
&lt;br /&gt;
===Getting Assets into the Right Formats===&lt;br /&gt;
&lt;br /&gt;
Notecards and lsl files are plain text files.&lt;br /&gt;
&lt;br /&gt;
Images have a size that is a power of two on each side.  That is, both the width and height must be one of 16, 32, 64, 128, 256, 512, or 1024.  They must also be in be in JPEG2000 .j2k format.  You can use the [http://www.openjpeg.org/ OpenJPEG] utilities to convert from other formats to JPEG2000.  Note that version 1.3 of the OpenJPEG libraries does not support greyscale images or transparency.  It will fail to work on greyscale images, and will remove any alpha channel from transparent images.  As of revision 824 in the OpenJPEG svn archives, it also supports transparency, and may read PNG files directly, and (at least with PNG files) handles greyscale images.  It's worth compiling a more recent version [http://code.google.com/p/openjpeg/source/checkout from the svn archives], at least until a version of OpenJPEG is officially released that supports these features.&lt;br /&gt;
&lt;br /&gt;
Convert a single image file to OpenJPEG with&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;tt&amp;gt;image_to_j2k -i ''inputfile'' -o ''outputbase''.j2k -r 100,30,10&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note on compression: the values after &amp;quot;-r&amp;quot; are the compression ratios to store in the OpenJPEG file.  If you upload an image with the viewer (at least with Imprudence), the list of compression ratios used is 1920,480,120,30,10.  Bigger numbers mean more compression, and hence blurrier images.  The advantage of storing multiple levels of compression is that when the (small amount) of data for a high level of compression is downloaded, at least that much can be rendered.  This is why when you watch a texture load, it starts blurry, and (at least if you're lucky) eventually becomes sharp.  A compression level of 1 is lossless... and also uses a lot of space in the asset store, and a lot of bandwidth when it's sent down.  A smallest compression of 10 should be good for most purposes.  However, for things like sculpt maps (or small, precise textures), you may want to add a compression ratio of 1 to the end of the arguments.&lt;br /&gt;
&lt;br /&gt;
Two scripts exist, a [[jp2_batch_converter|Linux script]] or [[Jp2_batch_converter_for_windows|Windows script]] in perl.  They use ImageMagick and image_to_j2k to resize image files to the appropriate size and convert them to j2k files (although named with an extension of .jp2, since that's what the viewer expects for some perverse reason).  However, if you want to use this, be aware of some caveats:&lt;br /&gt;
&lt;br /&gt;
* The script ''deletes'' your original image file.&lt;br /&gt;
* The script ''does no error checking''.  This means that if for whatever reason (and there can be several!) image_to_j2k file fails, the script will delete your image file ''anyway''.  This could make you sad if, like a certain stupid wiki page editor, you didn't make backup copies first.&lt;br /&gt;
* The script makes j2k files with compression ratios 20,10,1.  While this is great for image files that are bundled with the viewer, it's not good for server-side image files.  That lossless compression means gratuitous use of server asset store space and bandwidth.&lt;br /&gt;
&lt;br /&gt;
Maybe one day there will be an updated script....&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Creating Asset Set XML Files===&lt;br /&gt;
&lt;br /&gt;
Once you have all your assets in the right format, you need to create the AssetSet XML file.  Ultimately, you're going to want to make a new subdirectory underneath &amp;lt;tt&amp;gt;bin/assets&amp;lt;/tt&amp;gt;.  For example, let's suppose you're making a new asset set called &amp;lt;tt&amp;gt;MyAwesomeAssetSet&amp;lt;/tt&amp;gt;.  You'll need to create, in that directory, a file &amp;lt;tt&amp;gt;MyAwesomeAssetSet.xml&amp;lt;/tt&amp;gt;.  You can use the python script genassets.py to generate this file.  It will also generate the inventory XML files needeed.  This script is documented [[#Generating_Inventory_and_Asset_Files|below]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Terrains==&lt;br /&gt;
===Create a terrain heightmap===&lt;br /&gt;
&lt;br /&gt;
* [[Using_L3DT|Creating custom terrains with L3DT]]&lt;br /&gt;
&lt;br /&gt;
=Generating Inventory Items=&lt;br /&gt;
&lt;br /&gt;
The folders that show up in the library are defined in &amp;lt;tt&amp;gt;bin/inventory/Libraries.xml&amp;lt;/tt&amp;gt;.  That xml file has an entry for each library.  What you probably want to do is create a new library.  Make a subdirectory for that library.  Generate the XML files describing the folders and items in that library.  Add an entry to &amp;lt;tt&amp;gt;Libraries.xml&amp;lt;/tt&amp;gt; giving the name of the two XML files for your library.&lt;br /&gt;
&lt;br /&gt;
==Generating Inventory and Asset Files==&lt;br /&gt;
&lt;br /&gt;
The python script &amp;lt;tt&amp;gt;genassets.py&amp;lt;/tt&amp;gt; is able to generate asset and inventory XML files at the same time.  In order to use it, you must:&lt;br /&gt;
* Arrange all of your asset files (text files for scripts and notecards, properly sized j2k files for textures) in a directory tree that corresponds to the folders you want to see in your new library.&lt;br /&gt;
* Decide on the name of your library, and on a short version (without spaces) that will be used for filenames.&lt;br /&gt;
&lt;br /&gt;
Run the script.  It will go through the entire directory tree where you have put your asset files.  It will copy all of those asset files to an asset directory, and generate the AssetSet XML file there.  (Thus, you tell the script the asset directory is your new directory underneath &amp;lt;tt&amp;gt;bin/assets&amp;lt;/tt&amp;gt;, which is where you want the files to end up eventually.)  It will also generate two inventory XML files, one for folders and one for items, that put all of your new assets into the library.  You can make the inventory directory (to which only those two XML files are written) your new directory underneath &amp;lt;tt&amp;gt;bin/inventory&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
When the script is complete, you need only to edit &amp;lt;tt&amp;gt;inventory/Libraries.xml&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;assets/AssetSets.xml&amp;lt;/tt&amp;gt; to tell it about your new library.  Next time you start up OpenSim or (in grid mode) Robust, it should import your assets.&lt;br /&gt;
&lt;br /&gt;
'''NOTE''': the generator script replaces the XML files it finds.  This means that it's not really useful for adding files to an existing library but for creating the library from whole cloth.  Each time you run it, it generates new UUIDs for all of the assets.  That means if you run it on a set of assets you've already imported, they will get re-imported into the asset store; the old ones ''will not'' be deleted.  (They may also be used in-world already!)  To avoid redundancy and cruft, you don't want to re-import things.  If you want to add things to a library, just generate XML files as if they were all new.  Then, merge the XML files by hand in a text editor.&lt;br /&gt;
&lt;br /&gt;
==Generating Inventory Files for Existing Assets==&lt;br /&gt;
&lt;br /&gt;
If you have assets that you've already uploaded, and you just want to have them appear in the library folders, then... there is more to be written.&lt;br /&gt;
&lt;br /&gt;
==Caution==&lt;br /&gt;
&lt;br /&gt;
(I don't know if this is true, but I seem to remember reading somewhere that in grid mode, library assets have to exist not only on the Robust server, but also on each and every individual region OpenSim server.  I do not know if this is the case.  If it is, it certainly complicates matters.)&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Custom_Libraries</id>
		<title>Custom Libraries</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Custom_Libraries"/>
				<updated>2011-07-15T05:17:26Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: Massive rewriting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to add assets to the Library on your OpenSim server, there are two fundamental steps.  The first is generating the assets, the second is generating the inventory items.  The assets have information about the objects themselves; the geometry of prims, the image of textures, the text of notecards, etc.  The inventory items are entries in the folders that allow users to actually access the assets.&lt;br /&gt;
&lt;br /&gt;
If you want ready-to-import libraries, you could check out the [[Free Assets]] section...&lt;br /&gt;
&lt;br /&gt;
=Generating Assets=&lt;br /&gt;
&lt;br /&gt;
==With the Viewer==&lt;br /&gt;
&lt;br /&gt;
The easiest way to generate assets is just to create them in-world, or upload them with the viewer.&lt;br /&gt;
&lt;br /&gt;
==In Bulk==&lt;br /&gt;
&lt;br /&gt;
However, if you want to create assets in bulk, for instance from a directory of image files, you can create images and add them into the default asset sets.  These are found in the &amp;lt;tt&amp;gt;bin/assets&amp;lt;/tt&amp;gt; directory.  The file &amp;lt;tt&amp;gt;AssetSets.xml&amp;lt;/tt&amp;gt; has a list of &amp;quot;asset sets&amp;quot;, directories that contain the actual data for the assets and an XML file that has the metadata.  Look at the XML file for the example; the format is not too complicated.&lt;br /&gt;
&lt;br /&gt;
Practically speaking, at the moment, you can only import lsl scripts, notecards, and textures this way.  There are two steps.  First, you must get the assets into the right format.  Second, you must generate the XML files for the assets.&lt;br /&gt;
&lt;br /&gt;
===Getting Assets into the Right Formats===&lt;br /&gt;
&lt;br /&gt;
Notecards and lsl files are plain text files.&lt;br /&gt;
&lt;br /&gt;
Images have a size that is a power of two on each side.  That is, both the width and height must be one of 16, 32, 64, 128, 256, 512, or 1024.  They must also be in be in JPEG2000 .j2k format.  You can use the [http://www.openjpeg.org/ OpenJPEG] utilities to convert from other formats to JPEG2000.  Note that version 1.3 of the OpenJPEG libraries does not support greyscale images or transparency.  It will fail to work on greyscale images, and will remove any alpha channel from transparent images.  As of revision 824 in the OpenJPEG svn archives, it also supports transparency, and may read PNG files directly, and (at least with PNG files) handles greyscale images.  It's worth compiling a more recent version [http://code.google.com/p/openjpeg/source/checkout from the svn archives], at least until a version of OpenJPEG is officially released that supports these features.&lt;br /&gt;
&lt;br /&gt;
Convert a single image file to OpenJPEG with&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;tt&amp;gt;image_to_j2k -i ''inputfile'' -o ''outputbase''.j2k -r 100,30,10&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A note on compression: the values after &amp;quot;-r&amp;quot; are the compression ratios to store in the OpenJPEG file.  If you upload an image with the viewer (at least with Imprudence), the list of compression ratios used is 1920,480,120,30,10.  Bigger numbers mean more compression, and hence blurrier images.  The advantage of storing multiple levels of compression is that when the (small amount) of data for a high level of compression is downloaded, at least that much can be rendered.  This is why when you watch a texture load, it starts blurry, and (at least if you're lucky) eventually becomes sharp.  A compression level of 1 is lossless... and also uses a lot of space in the asset store, and a lot of bandwidth when it's sent down.  A smallest compression of 10 should be good for most purposes.  However, for things like sculpt maps (or small, precise textures), you may want to add a compression ratio of 1 to the end of the arguments.&lt;br /&gt;
&lt;br /&gt;
Two scripts exist, a [[jp2_batch_converter|Linux script]] or [[Jp2_batch_converter_for_windows|Windows script]] in perl.  They use ImageMagick and image_to_j2k to resize image files to the appropriate size and convert them to j2k files (although named with an extension of .jp2, since that's what the viewer expects for some perverse reason).  However, if you want to use this, be aware of some caveats:&lt;br /&gt;
&lt;br /&gt;
* The script ''deletes'' your original image file.&lt;br /&gt;
* The script ''does no error checking''.  This means that if for whatever reason (and there can be several!) image_to_j2k file fails, the script will delete your image file ''anyway''.  This could make you sad if, like a certain stupid wiki page editor, you didn't make backup copies first.&lt;br /&gt;
* The script makes j2k files with compression ratios 20,10,1.  While this is great for image files that are bundled with the viewer, it's not good for server-side image files.  That lossless compression means gratuitous use of server asset store space and bandwidth.&lt;br /&gt;
&lt;br /&gt;
Maybe one day there will be an updated script....&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating Asset Set XML Files==&lt;br /&gt;
&lt;br /&gt;
Once you have all your assets in the right format, you need to create the AssetSet XML file.  Ultimately, you're going to want to make a new subdirectory underneath &amp;lt;tt&amp;gt;bin/assets&amp;lt;/tt&amp;gt;.  For example, let's suppose you're making a new asset set called &amp;lt;tt&amp;gt;MyAwesomeAssetSet&amp;lt;/tt&amp;gt;.  You'll need to create, in that directory, a file &amp;lt;tt&amp;gt;MyAwesomeAssetSet.xml&amp;lt;/tt&amp;gt;.  You can use the python script genassets.py to generate this file.  It will also generate the inventory XML files needeed.  This script is documented [[#Generating_Inventory_and_Asset_Files|below]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Terrains==&lt;br /&gt;
===Create a terrain heightmap===&lt;br /&gt;
&lt;br /&gt;
* [[Using_L3DT|Creating custom terrains with L3DT]]&lt;br /&gt;
&lt;br /&gt;
=Generating Inventory Items=&lt;br /&gt;
&lt;br /&gt;
The folders that show up in the library are defined in &amp;lt;tt&amp;gt;bin/inventory/Libraries.xml&amp;lt;/tt&amp;gt;.  That xml file has an entry for each library.  What you probably want to do is create a new library.  Make a subdirectory for that library.  Generate the XML files describing the folders and items in that library.  Add an entry to &amp;lt;tt&amp;gt;Libraries.xml&amp;lt;/tt&amp;gt; giving the name of the two XML files for your library.&lt;br /&gt;
&lt;br /&gt;
==Generating Inventory and Asset Files==&lt;br /&gt;
&lt;br /&gt;
The python script &amp;lt;tt&amp;gt;genassets.py&amp;lt;/tt&amp;gt; is able to generate asset and inventory XML files at the same time.  In order to use it, you must:&lt;br /&gt;
* Arrange all of your asset files (text files for scripts and notecards, properly sized j2k files for textures) in a directory tree that corresponds to the folders you want to see in your new library.&lt;br /&gt;
* Decide on the name of your library, and on a short version (without spaces) that will be used for filenames.&lt;br /&gt;
&lt;br /&gt;
Run the script.  It will go through the entire directory tree where you have put your asset files.  It will copy all of those asset files to an asset directory, and generate the AssetSet XML file there.  (Thus, you tell the script the asset directory is your new directory underneath &amp;lt;tt&amp;gt;bin/assets&amp;lt;/tt&amp;gt;, which is where you want the files to end up eventually.)  It will also generate two inventory XML files, one for folders and one for items, that put all of your new assets into the library.  You can make the inventory directory (to which only those two XML files are written) your new directory underneath &amp;lt;tt&amp;gt;bin/inventory&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
When the script is complete, you need only to edit &amp;lt;tt&amp;gt;inventory/Libraries.xml&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;assets/AssetSets.xml&amp;lt;/tt&amp;gt; to tell it about your new library.  Next time you start up OpenSim or (in grid mode) Robust, it should import your assets.&lt;br /&gt;
&lt;br /&gt;
'''NOTE''': the generator script replaces the XML files it finds.  This means that it's not really useful for adding files to an existing library but for creating the library from whole cloth.  Each time you run it, it generates new UUIDs for all of the assets.  That means if you run it on a set of assets you've already imported, they will get re-imported into the asset store; the old ones ''will not'' be deleted.  (They may also be used in-world already!)  To avoid redundancy and cruft, you don't want to re-import things.  If you want to add things to a library, just generate XML files as if they were all new.  Then, merge the XML files by hand in a text editor.&lt;br /&gt;
&lt;br /&gt;
==Generating Inventory Files for Existing Assets==&lt;br /&gt;
&lt;br /&gt;
If you have assets that you've already uploaded, and you just want to have them appear in the library folders, then... there is more to be written.&lt;br /&gt;
&lt;br /&gt;
==Caution==&lt;br /&gt;
&lt;br /&gt;
(I don't know if this is true, but I seem to remember reading somewhere that in grid mode, library assets have to exist not only on the Robust server, but also on each and every individual region OpenSim server.  I do not know if this is the case.  If it is, it certainly complicates matters.)&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Custom_Libraries</id>
		<title>Custom Libraries</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Custom_Libraries"/>
				<updated>2011-07-14T05:03:30Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* Textures */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Adding new content(scripts,textures,notecards,objects,etc.) to your OpenSim server isn't that hard to do. The two ways to do it are:&lt;br /&gt;
* Using the viewer &lt;br /&gt;
* Preparing your content, and directly importing it to the server (preferred for large amounts of content)&lt;br /&gt;
&lt;br /&gt;
The second method can be divided into two parts:&lt;br /&gt;
* [[#Preparing Library]] - how to create extra items for the default inventory&lt;br /&gt;
* [[#Importing Library]] - how to import extra items into the default inventory&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Preparing Library=&lt;br /&gt;
&lt;br /&gt;
If you want ready-to-import libraries, you could check out the [[Free Assets]] section...&lt;br /&gt;
&lt;br /&gt;
==Textures==&lt;br /&gt;
===Converting Textures===&lt;br /&gt;
The jp2 files used by the Secondlife client, are actually j2k files. These can be encoded by image_to_j2k from openjpeg. There is a [[jp2_batch_converter|Linux script]] or [[Jp2_batch_converter_for_windows|Windows script]] in perl, that does all the work for you. It uses imageMagick and image_to_j2k to make valid input files and converts them to j2k fileformat. It then renames the j2k file to jp2 extension, so these can be used within the viewer. &lt;br /&gt;
* Download the [http://www.tellim.com/texture_cd.tar.gz blender texture cd] (as an example)&lt;br /&gt;
* Prepare your imagefiles (jp2 files with 16,32,64,128,256,512,1024 resolution and aspect ratios 1:1,1:2,1:4,1:8,1:16,1:32,etc. are supported)&lt;br /&gt;
* Copy the jp2 files(including directory-structures) into the /opt/opensim/library directory&lt;br /&gt;
&lt;br /&gt;
'''WARNING''': this script merrily deletes the original image, without checking to make sure everything worked.  If something goes wrong and the jp2 image isn't created, your image may be ''gone''.  Make backup copies of the images before you try to run the script on the conversion!&lt;br /&gt;
&lt;br /&gt;
Version 1.3 of the OpenJPEG libraries does not support greyscale images.  If you have a greyscale image, that will trigger the condition above where your image gets deleted.  Version 1.3 of the OpenJPEG libraries also does not support transparency.&lt;br /&gt;
&lt;br /&gt;
As of revision 824 of the OpenJPEG SVN library, image_to_j2k is able to write out jp2 files directly.  (The script assumes that only j2k files may be written, and does a rename.  It also supports transparency, and may read PNG files directly, and (at least with PNG files) handles greyscale images.  It's worth compiling one of those versions.  &amp;quot;Somebody should&amp;quot; update the conversion script to be safer.  (Yeah, yeah, I know.)&lt;br /&gt;
&lt;br /&gt;
==Terrains==&lt;br /&gt;
===Create a terrain heightmap===&lt;br /&gt;
&lt;br /&gt;
* [[Using_L3DT|Creating custom terrains with L3DT]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Importing Library=&lt;br /&gt;
&lt;br /&gt;
==Creating a custom library==&lt;br /&gt;
* Create the appropriate xml storage files using the [[assets_generator|Asset Generator]] script&lt;br /&gt;
* Edit the opensim inventory library reference file&lt;br /&gt;
 nano /opt/opensim/production/bin/inventory/Libraries.xml&lt;br /&gt;
* Add the inventory reference&lt;br /&gt;
 &amp;lt;Section Name=&amp;quot;OpenSim Custom Library&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;Key Name=&amp;quot;foldersFile&amp;quot; Value=&amp;quot;MyCoolOpenSimLibrary/3DDCInventoryFolders.xml&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;Key Name=&amp;quot;itemsFile&amp;quot; Value=&amp;quot;MyCoolOpenSimLibrary/3DDCInventoryItems.xml&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/Section&amp;gt; &lt;br /&gt;
* Edit the opensim assets library reference file&lt;br /&gt;
 nano /opt/opensim/production/bin/assets/AssetSets.xml&lt;br /&gt;
* Add the asset reference&lt;br /&gt;
 &amp;lt;Section Name=&amp;quot;OpenSim Custom Asset Set&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;Key Name=&amp;quot;file&amp;quot; Value=&amp;quot;MyCoolOpenSimAssetSet/3DDCAssetSet.xml&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/Section&amp;gt;&lt;br /&gt;
* Restart OpenSim&lt;br /&gt;
* Check out if the textures are rendered correctly in the viewer&lt;br /&gt;
&lt;br /&gt;
==Load Terrain==&lt;br /&gt;
Assume your file is called &amp;quot;terrain.r32&amp;quot;.At the region console, type:&amp;lt;br&amp;gt;&lt;br /&gt;
 script terrain load terrain.r32&lt;br /&gt;
You now have your new terrain! You can at this point use the terrain add, terrain scale, or terrain multiply to rescale it to your liking.&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/External_Files</id>
		<title>External Files</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/External_Files"/>
				<updated>2011-07-12T23:51:50Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* External Files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{content}}&lt;br /&gt;
&lt;br /&gt;
== External Files ==&lt;br /&gt;
In the bin directory of the OpenSim distribution are three example html files.&lt;br /&gt;
* http_404.html.example&lt;br /&gt;
* http_500.html.example&lt;br /&gt;
* http_loginform.html.example&lt;br /&gt;
&lt;br /&gt;
For account management from the web on OpenSimulator 0.7 and later, take a look at the [[Wifi]] module created by Diva Canto&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Configuration</id>
		<title>Configuration</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Configuration"/>
				<updated>2011-07-12T22:48:38Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* Note About Mono */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Quicklinks}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==OpenSim simulator configuration file==&lt;br /&gt;
The region simulator configuration is managed using a file called OpenSim.ini. This file is used regardless of whether the sim is running in standalone or grid mode.  This file references some additional configuration information from the config-include/ directory.  Information about the various settings is contained in the OpenSim.ini file itself (or OpenSim.ini.example for reference).&lt;br /&gt;
&lt;br /&gt;
Please note, that the name OpenSim.ini can be changed via [[OpenSim.exe Command Line Options|command line arguments]].&lt;br /&gt;
&lt;br /&gt;
It is also possible to distribute the inifile settings over two files. This is useful if you want to run several OpenSim processes where most of your settings are identical except for a few.  The master file is read first, then the inifile is read. Settings given in the inifile overrule settings given in the master file.  The master file has the same format and the same keywords as the inifile, so the same documentation applies.&lt;br /&gt;
&lt;br /&gt;
== Database  ==&lt;br /&gt;
&lt;br /&gt;
Opensim supports the following database-engines. Information about setting these up can be found in the OpenSim.ini.example file and the other various example files in bin/config-include. See [[Database Settings]] to know the detailed settings for each database.&lt;br /&gt;
&lt;br /&gt;
*'''SQLite''' (default) - a lightweight database that comes bundled with OpenSim and can be used without requiring any extra configuration. It is mostly intended to get you up and running quickly, not for production use. It is significantly slower than MySQL. A few features here (such as attachment persistence) have not yet been fully implemented. &lt;br /&gt;
&lt;br /&gt;
*'''MySQL 5.1''' (fully supported) - This is the recommended database for any use beyond experimentation or small standalone applications. &lt;br /&gt;
::*'''OpenSim 0.7.1:''' It supports MySQL 5.5 out of the box.&lt;br /&gt;
::*'''Windows x64 systems:''' &amp;amp;nbsp;There is currently an unresolved [http://opensimulator.org/mantis/bug_view_advanced_page.php?bug_id=5294 bug_id=5294] found when running OpenSim with MySQL 5.5 on Windows x64 systems.&lt;br /&gt;
::*'''Opensim 0.7.0.2:''' &amp;amp;nbsp;Some users have reported problems with MySQL 5.1.55 and up with Opensim 0.7.0.2, see [http://opensim-users.2152040.n2.nabble.com/OpenSim-1-7-0-2-and-MySQL-Versions-td6155064.html this thread] for more information. The issue can be resolved by using an updated version of MySql.Data.dll OR installing an older version of MySQL such as [http://downloads.mysql.com/archives.php?p=mysql-5.1&amp;amp;v=5.1.52 MySQL 5.1.52] with Opensim version 0.7.0.2. &amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
*'''MSSQL''' (partially supported) - some recent OpenSim features may not yet be implemented.&lt;br /&gt;
&lt;br /&gt;
==Standalone vs. Grid==&lt;br /&gt;
We recommend that you first get OpenSim running in standalone mode before you attempt to connect it to a grid or run your own grid.  OpenSim will start up in standalone mode out-of-the-box on the binary distributions.&lt;br /&gt;
&lt;br /&gt;
An OpenSim configuration consists of regions (run by region simulators) and backend data services (such as user, assets and inventory management).&lt;br /&gt;
&lt;br /&gt;
A system running in '''standalone mode''' runs both the region simulator and all the data services in a single process when you run OpenSim.exe.  In this mode you can run as many regions as you like but only on a single machine.&lt;br /&gt;
&lt;br /&gt;
[[image:Opensim-standalone.png|frame|center|OpenSim running in standalone mode.  Both simulator and services run in the same process (OpenSim.exe).]]&lt;br /&gt;
&lt;br /&gt;
In '''grid mode''', the data services are not part of the region server process.  Instead, they are run in a separate executable called Robust.exe.  A Robust shell can run all the services or they can be split amongst any number of Robust instances.  This allows them to be run on entirely separate machines if necessary.  In this mode, the OpenSim.exe acts solely as the region server, serving one or more regions that communicate with the separate data services.  At this point you can run multiple OpenSim.exe region simulators on different machines.&lt;br /&gt;
&lt;br /&gt;
[[image:Opensim-grid-simple.png|frame|center|OpenSim running in grid mode.  In this case, all the services are being run within a Robust.exe process.  Multiple copies of OpenSim.exe (usually running on different machines) all use the same set of common services.]]&lt;br /&gt;
&lt;br /&gt;
Running in grid mode is more complicated than running in standalone mode.  It requires an understanding of UUID, X,Y location, server handshake passwords, estates and estate owners, and a couple of other settings. These require more care and patience to set up.  We strongly recommend that you don't attempt this unless you are extremely patient and very technically proficient.&lt;br /&gt;
&lt;br /&gt;
= Running OpenSim in Standalone mode =&lt;br /&gt;
Getting a binary distribution of OpenSim running in standalone configuration is relatively straightforward since it's configured this way by default.  On the other hand, if you build OpenSim from the source distribution or from the git repository then you will need to:&lt;br /&gt;
&lt;br /&gt;
# Copy the bin/OpenSim.ini.example file to bin/OpenSim.ini.  This configures the 3D simulator itself.&lt;br /&gt;
# Copy the bin/config-include/StandaloneCommon.ini.example file to bin/config-include/StandaloneCommon.ini.  This configures the in-process data services used by the standalone configuration.&lt;br /&gt;
# In the [Architecture] section of OpenSim.ini at the bottom of the file, uncomment the Standalone.ini line.  To uncomment a line of code, remove the semi-colon (;) comment symbols preceding the line so that it says:&lt;br /&gt;
&lt;br /&gt;
 Include-Architecture = &amp;quot;config-include/Standalone.ini&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Running OpenSim is then a matter of launching OpenSim.exe. However, you need to have installed all dependencies before that. See [[Dependencies]] for details. After that, open a command prompt (for Windows users, Start menu &amp;gt; Run &amp;gt; cmd) and navigate to the Opensim /bin directory.&lt;br /&gt;
&lt;br /&gt;
On a '''Windows 32-bit''' command prompt:&lt;br /&gt;
 OpenSim.exe&lt;br /&gt;
Under '''Windows 64-bit''', ODE cannot yet be compiled for 64 bit mode, so if using the default ODE physics plugin run:&lt;br /&gt;
 OpenSim.32BitLaunch.exe&lt;br /&gt;
On '''Linux''' run:&lt;br /&gt;
 mono OpenSim.exe&lt;br /&gt;
This can be done under both 32 and 64 bit modes with the ODE physics engine.&lt;br /&gt;
&lt;br /&gt;
== Running OpenSim for the first time ==&lt;br /&gt;
&lt;br /&gt;
If you're running OpenSim for the first time, it will ask you several questions at the console that will set up a single region for you.  The configuration options you enter will be written to the bin/Regions/Regions.ini file, which you can then edit at a later date if you need to make changes.&lt;br /&gt;
&lt;br /&gt;
Many of the questions have defaults.  Here are some explanations of the questions asked:&lt;br /&gt;
&lt;br /&gt;
* '''New region name'''&lt;br /&gt;
::The name for your region.  Don't leave this blank!&lt;br /&gt;
* '''Region UUID'''&lt;br /&gt;
::The unique ID of your region.  In pretty much all cases you will want to accept the randomly generated default in the square brackets.  The only time when you wouldn't is if you were trying to set up a configuration to point to pre-existing region data.  But in this case you are probably better off editing the Regions.ini file directly anyway&lt;br /&gt;
* '''Region Location'''&lt;br /&gt;
::This is the location of the region on the grid.  In standalone mode you can safely leave these as the default (1000,1000).  If you were to set up additional regions later on in Regions.ini then they would need different grid co-ordinates (e.g. 1000,1001).  OpenSim regions can be placed anywhere on a 65536 by 65536 grid, but [[Hypergrid]] enabled regions may need special consideration for region location.  See [[Installing_and_Running_Hypergrid#The_4096_Regions_Limit]] for more information.&lt;br /&gt;
* '''Internal IP address'''&lt;br /&gt;
::In virtually all cases this can be left as 0.0.0.0 (this is a wildcard that allows OpenSim to listen for UDP connections on any of the server's network interfaces).  If you want to restrict UDP connections to only one network interface then you can specify an explicit IP address.  This address is only used internally - the '''External host name''' is the one that is actually passed to the viewer (and hence is the important one).&lt;br /&gt;
* '''Internal port'''&lt;br /&gt;
::This is the IP port for all incoming client connections.  The name is a bit misleading since it will be used externally (by a Second Life viewer, for instance) as well as internally. You can make this any port you want, but it is safe to leave at the default 9000. Each region on your server must have a unique port.&lt;br /&gt;
* '''Allow alternate ports'''&lt;br /&gt;
::This is currently experimental.  Please leave it at the default of False.&lt;br /&gt;
* '''External host name'''&lt;br /&gt;
::If you leave this at the default 'SYSTEMIP' then this will become the LAN network address of the machine (e.g. 192.168.1.2).  This is fine if you are connecting only from within your LAN.  If you want to connect to it from a client on the internet, this should be the External IP Address of your router.  Fully Qualified Domain Names (FQDNs) can also be used though they will be converted to a numeric IP address before being sent to the viewer.&lt;br /&gt;
&lt;br /&gt;
The following details are also asked in OpenSim 0.6.9 and earlier.&lt;br /&gt;
&lt;br /&gt;
* '''Master Avatar UUID'''&lt;br /&gt;
::This is a legacy OpenSim feature and can be left at the default of 00000000-0000-0000-0000-000000000000.  Later on, you may want to change this to your own avatar's UUID in Regions.ini if you have problems editing terrain.&lt;br /&gt;
* '''Master Avatar first name'''&lt;br /&gt;
::This is an alternative way of specifying the master avatar by avatar name rather than UUID.  If you press enter here then both this field and the last name field will be left blank.  Accepting the blank default is fine - this can always be changed later in Regions.ini file.&lt;br /&gt;
* '''Master Avatar last name'''&lt;br /&gt;
::The last name of the master avatar.&lt;br /&gt;
* '''Master Avatar sandbox password'''&lt;br /&gt;
::The password of the master avatar.&lt;br /&gt;
&lt;br /&gt;
In OpenSim 0.7 and later, OpenSim will ask you to assign each region to an estate during the setup process.  If an estate needs to be created then it will also ask you to assign an estate manager.  In standalone mode, an estate manager can also be created during the setup process.&lt;br /&gt;
&lt;br /&gt;
Don't forget the account details you use to set up the master avatar (in 0.6.9) or the estate manager (in 0.7 and later).  Only this user will initially be able to configure the in-world settings for your region.  This is also a user account that you can use to perform your initial login test.&lt;br /&gt;
&lt;br /&gt;
See [[Configuring Regions]] for more information about the Regions.ini file that these questions generate.&lt;br /&gt;
&lt;br /&gt;
If you want to create a user other than the estate manager, then in the server console type:&lt;br /&gt;
&lt;br /&gt;
 create user&lt;br /&gt;
&lt;br /&gt;
This will ask you a series of questions for creating a user (such as first name, last name and password).&lt;br /&gt;
&lt;br /&gt;
== Connecting to OpenSim ==&lt;br /&gt;
&lt;br /&gt;
To connect to your new sim with your user, start up a Second Life viewer with the following command line switches:&lt;br /&gt;
&lt;br /&gt;
'''Client on same machine as OpenSim:'''&lt;br /&gt;
 -loginuri http://127.0.0.1:9000&lt;br /&gt;
&lt;br /&gt;
'''Client on same LAN as OpenSim:'''&lt;br /&gt;
 -loginuri http://lan_ip:9000&lt;br /&gt;
&lt;br /&gt;
'''Client on different machine or internet:'''&lt;br /&gt;
 -loginuri http://external_ip:9000&lt;br /&gt;
&lt;br /&gt;
Then enter the user name and password you set up in the previous step and your new user should login.&lt;br /&gt;
&lt;br /&gt;
Be aware of [http://osgrid.org/forums/viewtopic.php?f=5&amp;amp;t=400&amp;amp;start=0&amp;amp;st=0&amp;amp;sk=t&amp;amp;sd=a loopback] problems when Running viewer &amp;amp;amp; server(s) on the same machine (LAN) by using the &amp;quot;external&amp;quot; configuration. (&amp;lt;u&amp;gt;'''You might notice endless waiting for region handshake'''&amp;lt;/u&amp;gt;.) See also [[Troubleshooting|troubleshoot hints]].  If you're having Connectivity problems, [[Network_Settings|be sure to read the Network Configuration Page]]. This is important if you see Region handshake issues&lt;br /&gt;
&lt;br /&gt;
= Running OpenSim in Grid mode =&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;background:LavenderBlush; color:black&amp;quot; |&lt;br /&gt;
[[Image:Exclamation.png|left]]&lt;br /&gt;
NOTE: 0.7 is the first OpenSim release that fully migrates all services to the ROBUST server shell.  OpenSim.Grid.UserServer.exe and MessageServer.exe from OpenSim 0.6.9 are no longer necessary.  Please see the [[0.7_Release|0.7 release notes]] for more details.  For details on how to set up grid services in OpenSim 0.6.9 and earlier please see [[OpenSim 0.6.9 Grid Mode Configuration]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Running OpenSim in grid mode is considerably more complicated than running a standalone instance.  Instead of running everything in the same process, backend data services (asset, inventory, etc.) run in one or more separate processes, often on a different machine.  This allows multiple OpenSim.exe simulator instances to use the same asset and inventory data.&lt;br /&gt;
&lt;br /&gt;
== Step 1: Set up a ROBUST services instance ==&lt;br /&gt;
&lt;br /&gt;
1.  In the bin directory, copy Robust.ini.example to Robust.ini.  The example file is configured to run all the services in a single ROBUST instance.&lt;br /&gt;
&lt;br /&gt;
2.  Configure the [DatabaseService] section of Robust.ini to use your MySQL database.  Only MySQL is supported for running grid services.&lt;br /&gt;
&lt;br /&gt;
3.  Start up Robust.exe.  &lt;br /&gt;
&lt;br /&gt;
 mono Robust.exe (Linux, BSD, Mac OS X)&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Robust.exe (Windows)&lt;br /&gt;
&lt;br /&gt;
If you don't see any errors (in red) on the console then you can move on to the next step.&lt;br /&gt;
&lt;br /&gt;
4.  Every region must belong to an estate, and every estate must have an owner which is a valid user account in OpenSim's user account service.  Create a user on the ROBUST command console with the following command.&lt;br /&gt;
&lt;br /&gt;
 create user&lt;br /&gt;
&lt;br /&gt;
This will ask you for the user's name, password and an optional e-mail.  Remember this name since you will need it when you start up the simulator for the first time.&lt;br /&gt;
&lt;br /&gt;
== Step 2: Configure an OpenSim.exe to use the ROBUST services ==  &lt;br /&gt;
&lt;br /&gt;
In grid mode, as in standalone mode, you need to configure OpenSim.ini which controls the 3D simulator itself.&lt;br /&gt;
&lt;br /&gt;
However, instead of using and configuring the file config-include/StandaloneCommon.ini, a simulator connecting to a grid needs to use and configure the config-include/GridCommon.ini file, in order to connect to the ROBUST hosted remote data services rather than in-process local ones.&lt;br /&gt;
&lt;br /&gt;
The steps for both these operations are as follows.&lt;br /&gt;
&lt;br /&gt;
1.  Copy bin/OpenSim.ini.example to OpenSim.ini&lt;br /&gt;
&lt;br /&gt;
2.  Find the [Architecture] section at the very bottom of OpenSim.ini.  Make sure that one of the following lines is uncommented:&lt;br /&gt;
&lt;br /&gt;
 Include-Architecture = &amp;quot;config-include/Grid.ini&amp;quot; (in OpenSim 0.7.1 and later)&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Include-Grid         = &amp;quot;config-include/Grid.ini&amp;quot; (in OpenSim 0.7.0.2 and earlier)&lt;br /&gt;
&lt;br /&gt;
The others should remain commented.&lt;br /&gt;
&lt;br /&gt;
3.  Go to bin/config-include and copy GridCommon.ini.example to GridCommon.ini.&lt;br /&gt;
&lt;br /&gt;
4.  Open GridCommon.ini in a text editor.  You will see lots of URL entries, each of which have dummy defaults of http://myassetserver.com:8003, http://myinventoryserver.com:8003, etc.  You will need to change each of these to point towards the address of your ROBUST instance.  For instance, if you're running ROBUST on a machine with a local IP address of 192.168.1.2, you will need to change AssetServerURI to the setting&lt;br /&gt;
&lt;br /&gt;
 AssetServerURI = &amp;quot;http://192.168.1.2:8003&amp;quot;&lt;br /&gt;
&lt;br /&gt;
5.  Run OpenSim.exe.  If you're running OpenSim.exe for the first time you will get the same questions about setting up the region that occur on a first-run in standalone mode.  Please see the standalone section for instructions on how to answer these, or read more information about the Regions.ini file on the [[Configuring Regions]] page.&lt;br /&gt;
&lt;br /&gt;
If everything is set up correctly, when starting up OpenSim.exe you shouldn't see any errors.  You should also see the ROBUST console display log lines saying that the region has registered with the grid service.  For example,&lt;br /&gt;
&lt;br /&gt;
 21:43:45 - [GRID SERVICE]: Region t1 (176cc95e-f693-4b02-8e08-af86e2372faa) registered successfully at 256000-256000&lt;br /&gt;
 21:43:47 - [GRID SERVICE]: region t1 has 0 neighbours&lt;br /&gt;
&lt;br /&gt;
6.  Login with a client.  Your client startup line will look something like&lt;br /&gt;
&lt;br /&gt;
 -loginuri http://192.168.1.2:8002&lt;br /&gt;
&lt;br /&gt;
The loginuri needs to be the address to the login service.  In standalone mode, this was the same address as the region simulator and the port was 9000 by default.  However, in grid mode it will be the address to login service hosted on the ROBUST instance.  In this case, the address will be 192.168.1.2.  The port number of 8002 is the traditional one for the grid login service and is the default in Robust.ini.example.&lt;br /&gt;
&lt;br /&gt;
7.  If the login is successful, you will see log lines on the ROBUST console (for the login itself) and then log lines on the region simulator console (as the login process tells the simulator to expect the avatar, tells the viewer the address of the region simulator and then when the viewer starts talking to the simulator directly).&lt;br /&gt;
&lt;br /&gt;
==Attaching your sim to someone else's grid==&lt;br /&gt;
&lt;br /&gt;
To set up the region server (i.e., &amp;lt;tt&amp;gt;OpenSim.exe&amp;lt;/tt&amp;gt;) to connect to an external grid, follow the [[Configuration#Step_2:_Configure_an_OpenSim.exe_to_use_the_ROBUST_services]] instructions above.&lt;br /&gt;
&lt;br /&gt;
The grid will have already provided with the required services.  In step 2 you will need to use the provided URLs for their services.&lt;br /&gt;
&lt;br /&gt;
In your bin/Regions.ini file (or other region config file) you will also need to set the grid co-ordinates to your regions provided from the grid operator.  See [[Configuring Regions]] for more information.&lt;br /&gt;
&lt;br /&gt;
=Running an OpenSim standalone or grid installation with Hypergrid enabled=&lt;br /&gt;
[[Hypergrid]] is an emerging architecture supported by OpenSimulator that allows a user with an account on one standalone or grid to visit other Hypergrid-enabled standalones or grids, and for users from those grids to visit the home grid.  This does not require the two installations to share a central set of data services (assets, inventory, etc.).  Please see [[Installing and Running Hypergrid]] for more details.&lt;br /&gt;
&lt;br /&gt;
=Further notes=&lt;br /&gt;
&lt;br /&gt;
==Troubleshooting==&lt;br /&gt;
&lt;br /&gt;
See [[Troubleshooting]] &lt;br /&gt;
&lt;br /&gt;
==Running OpenSim 0.6.7 and onwards in 64 bit Windows==&lt;br /&gt;
[[Image:Exclamation.png|left]]&lt;br /&gt;
As of OpenSim 0.6.7, the default physics engine for OpenSim was changed to the ODE engine.  This is because ODE is by far the most advanced physics engine plugin currently in OpenSim.  Unfortunately, it has the drawback in that its library is not compilable under 64-bit in Windows.  &lt;br /&gt;
&lt;br /&gt;
Therefore, in order to launch the region simulator, 64-bit Windows users may need to run: &lt;br /&gt;
&lt;br /&gt;
 OpenSim.32BitLaunch.exe&lt;br /&gt;
&lt;br /&gt;
instead of:&lt;br /&gt;
&lt;br /&gt;
 OpenSim.exe&lt;br /&gt;
&lt;br /&gt;
An alternative is to use the basicphysics engine instead or one of the other alternative physics engines bundled with OpenSim, though all these are far less functional than the ODE plugin.&lt;br /&gt;
&lt;br /&gt;
==Note About Mono==&lt;br /&gt;
&lt;br /&gt;
''This only applies for Mono before 2.6.  More recent versions of Mono have better thread handling.  For more information, see [http://www.mono-project.com/ThreadPool_DeadLocks ThreadPool_Deadlocks at the mono-project website].''&lt;br /&gt;
&lt;br /&gt;
If you're using mono, you should increase the value of the mono environment variable MONO_THREADS_PER_CPU from its default of 5 to some number that works for your sim. The exact number depends on many factors including: the number of CPUs in your machine, what else you use that machine for, how many regions you have in your sim, how many of them are adjacent, how many scripts you have, and how many avatars you expect to serve at the same time. As a reference, Wright Plaza in OSGrid, which is running as a single region on a sim and routinely hosts meetings with 20 avatars, uses the value 125. &lt;br /&gt;
&lt;br /&gt;
If this number is too low, the operation of your sim will start to break in all sorts of different ways. A common symptom is the freezing of all activity upon login of a new avatar. Other symptoms are a lot more subtle.&lt;br /&gt;
&lt;br /&gt;
For example: $ export MONO_THREADS_PER_CPU=125&lt;br /&gt;
&lt;br /&gt;
==Increasing the stack reserve level when using OpenDynamicsEngine on *nix==&lt;br /&gt;
&lt;br /&gt;
If you have problems using the OpenDynamicsEngine on *nix, try setting your stack reserve level higher than the default with the following command;&lt;br /&gt;
&amp;lt;tt&amp;gt;ulimit -s 262144&amp;lt;/tt&amp;gt; Or, run the opensim-ode.sh to start up OpenSimulator.&lt;br /&gt;
&lt;br /&gt;
== Firewalls ==&lt;br /&gt;
Some operation systems or distributions run their own firewall by default. If you can't access to OpenSimulator from remote client, you'll need to check their settings. See [[Firewall Settings]] for details.&lt;br /&gt;
&lt;br /&gt;
== Legacy Configuration Information ==&lt;br /&gt;
These are some pages containing some legacy configuration information of unknown accuracy.&lt;br /&gt;
&lt;br /&gt;
[[OpenSim 0.6.6 legacy configuration information]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Additional Optional Configuration Tasks ==&lt;br /&gt;
&lt;br /&gt;
===Futher configuring OpenSim===&lt;br /&gt;
&lt;br /&gt;
If you've looked through OpenSim.ini.example or any other of the config files, you'll see that there's a very large number of configurable parameters.  See [[Configuring Simulator Parameters]] for more details.&lt;br /&gt;
&lt;br /&gt;
===OpenSim.exe command line options===&lt;br /&gt;
OpenSim.exe has command line options which allow you to perform actions such as reading configuration files from a different directory.  See [[OpenSim.exe Command Line Options]] for more details.&lt;br /&gt;
&lt;br /&gt;
===Script engine===&lt;br /&gt;
OpenSim supports multiple script engines. See [[ScriptEngines]] for details.  If you don't know what this means then the default script engine will be fine.  In fact, recent versions of OpenSim only ship with one script engine, the XEngine.&lt;br /&gt;
&lt;br /&gt;
===Permissions Configuration===&lt;br /&gt;
OpenSim has a quite elaborate set of permissions. See [[Permissions (Server)]] for details.  By default, permissions are not active on region simulators.&lt;br /&gt;
&lt;br /&gt;
=== Logging ===&lt;br /&gt;
By default, OpenSim logs information to a file called OpenSim.log in the bin directory.  See [[Logging]] for details on how to further configure this if required.&lt;br /&gt;
&lt;br /&gt;
=== Configuration of region modules ===&lt;br /&gt;
* [[IRCBridgeModule]]&lt;br /&gt;
* [[Freeswitch_Module]]&lt;br /&gt;
* [[Offline Messaging]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration of Metaverse Exchange Protocol (MXP) ===&lt;br /&gt;
* [[Metaverse Exchange Protocol]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration of Web Server and Pages===&lt;br /&gt;
OpenSim contains a web server that can serve up a variety of pages.  Some which come from external files and some are generated internally.&lt;br /&gt;
* [[External Files]]&lt;br /&gt;
* [[Internally Generated]]&lt;br /&gt;
&lt;br /&gt;
=== Configuration of Multiple Standalone Regions on the Same Server ===&lt;br /&gt;
For the second region, change 'http_listener_port' in OpenSim.ini to the value excluding 9000, and 'InternalPort' in Regions.ini to the value excluding 9000.&lt;br /&gt;
&lt;br /&gt;
= Where to go from here =&lt;br /&gt;
&lt;br /&gt;
*[[Upgrading]] to mySQL from SQLite.&lt;br /&gt;
&lt;br /&gt;
*[[Server Commands]] for creating users and controlling the system.&lt;br /&gt;
&lt;br /&gt;
*Fix the bent knees bug: [[FAQ#Why_are_my_knees_bent_when_I_stand_idle.3F]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [http://dist.opensimulator.org/wiki/opensim-standalone.odg OpenOffice draw file for OpenSim standalone diagram]&lt;br /&gt;
* [http://dist.opensimulator.org/wiki/opensim-grid-simple.odg OpenOffice draw file for OpenSim grid diagram]&lt;br /&gt;
&lt;br /&gt;
[[Category:Configuration]]&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Physics_Engine_Interface</id>
		<title>Physics Engine Interface</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Physics_Engine_Interface"/>
				<updated>2009-09-18T20:24:48Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* PhysicsActor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base Classes ==&lt;br /&gt;
&lt;br /&gt;
''Note: I ([[User:Rknop]]) am trying to figure this out by looking at some of the code; my main interest is the NewtonPlugin.  AS such, there are whole swaths of the physics engine, such as joints, that I have no clue about at the moment''&lt;br /&gt;
&lt;br /&gt;
The base classes for a physics module can be found in OpenSim.Region.Physics.Manager.  The physics module itself should be a subclass of Physics, e.g. OpenSim.Region.Physics.OdePlugin.&lt;br /&gt;
&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsActor&amp;lt;/tt&amp;gt;''' is the base class for both prims and avatars.&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsScene&amp;lt;/tt&amp;gt;''' is the main base class that interfaces with the region's Scene.&lt;br /&gt;
* (others)&lt;br /&gt;
&lt;br /&gt;
The Physics Scene doesn't access the Region Scene.  The region scene will tell the physics engine about prims and avatars, and will send updates to the physics engine.  It will then pull positions and velocities of objects and avatars out of the physics engine.&lt;br /&gt;
&lt;br /&gt;
For the most part, the things that will be interfacing with the physics engine are the classes &amp;lt;tt&amp;gt;OpenSim.Region.Framework.Scenes.Scene&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OpenSim.Region.Framework.Scenes.SceneObjectGroup&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;OpenSim.Region.Framework.Scenes.SceneObjectPart&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The Plugin Class ==&lt;br /&gt;
&lt;br /&gt;
If you're writing a Physics engine named Foo, you need to write a class OpenSim.Region.Physics.FooPlugin with the following methods:&lt;br /&gt;
&lt;br /&gt;
* '''FooPlugin()''' &amp;amp;mdash; constructor&lt;br /&gt;
* '''bool Init()''' &amp;amp;mdash; (not sure exactly when this is called.  return true)&lt;br /&gt;
* '''PhysicsScene GetScene(String sceneIdentifier)''' &amp;amp;mdash; return a FooScene, which is derived from PhysicsScene&lt;br /&gt;
* '''string GetName()''' &amp;amp;mdash; return the name that folks can use in OpenSim.ini to select this physics engine&lt;br /&gt;
* '''Dispose()''' &amp;amp;mdash; destructor&lt;br /&gt;
&lt;br /&gt;
== PhysicsScene ==&lt;br /&gt;
&lt;br /&gt;
Your class OpenSim.Region.Physics.FooScene must derive from OpenSim.Region.Physics.PhysicsScene.  Members include:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void Initialize(IMesher meshmerizer, IConfigSource config)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size, bool isFlying)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetWaterLevel(float baseheight)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemovePrim(PhysicsActor prim)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; This gets called when a prim is made into something the physics engine no longer needs to know about.  The physics engine should remove it from any internal lists of prims it is keeping track of.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemoveAvatar(PhysicsActor character)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; Like RemovePrim, but for avatars.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; Tells the physics engine to add a new prim it needs to keep track of.  This prim is ''not'' a physical prim, but as long as it's not phantom, physical objects may collide with it, and thus the physics engine (may) need to know about it.  (Unless the physics engine punts on collisions, as, for instance, NewtonPlugin does.)  Comments in the code indicate that this method is slated to be removed....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation, bool isPhysical)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Like the previous one, but you've got the flag that tells you if it's physical or not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPhysicsActorTaint(PhysicsActor prim)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;(I don't know what taints are, so I can't document them yet....)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void GetResults()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override bol IsThreaded'''&lt;br /&gt;
&amp;lt;dd&amp;gt;A member that needs a get method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetTerrain(float[] heightMap)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void DeleteTerrain()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public overrid Dictionary&amp;lt;unit, float&amp;gt; GetTopColliders()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override float Simulate(float timestep)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This is the core function.  This gets called by the main loop when it wants the Physics engine to do its magic and propagate forward the positions and velocities of all the stuff it knows about.  The physics engine should update the Position and Velocity members of the PhysicsActor class it knows about (those things that have been added to it by the methods above).  '''Important:''' when the physics engine thinks that things have changed enough for any given prims that the surrounding scene should updates it's own idea about the positions and velocities of those prims, it should call the RequestPhysicsterseUpdate() method of the changed PhysicsActors().  (The safest, but slowest, way to do this is for Simulate() to call this for every physical prim it knows about every time it is called.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PhysicsActor ==&lt;br /&gt;
&lt;br /&gt;
PhysicsActor represents both prims and characters.  You may want to make separate classes for the two.  You can get away with this because PhysicsActors are actually created by PhysicsScene.  Your subclass of PhysicsScene has different methods called when an avatar or a prim is added to the scene, returning a PhysicsActor.  You can return the appropriate subclass in each case.&lt;br /&gt;
&lt;br /&gt;
Members:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;'''int PhysicsActorType'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set methods.  Return ActorTypes.Prim or ActorTypes.Agent if it's a prim or an avatar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool IsPhysical'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Position'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  If an object is physical, the physics engine keeps the &amp;quot;real&amp;quot; position for that object.  However, it's the surrounding scene's impression of the position that gets rendered and sent to the client.  It will pull the position out of the physics engine by looking at this member, and tell the physics engine about any external changes in its position through this member.  Note that the scene doesn't automatically pull out the position, but only when it thinks it needs to.  You can call the RequestPhysicsterseUpdate() method of PhysicsActor to ask the Scene to update its position for any given PhysicsActor.  (See PhysicsScene.Simulate() above.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Velocity'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Need get and set.  Similar considerations to Position&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector RotationalVelocity'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Acceleration'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get; there's no set method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetAcceleration(PhysicsVector accel)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Do what you'd think Acceleration.set would do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Size'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float Mass'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get; there is no set method at the moment&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetMass(float mass)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Instead of Mass.set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetMomentum(PhysicsVector momentum)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;I am disturbed that this exists in addition to Velocity.set and SetMass....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''Quarternion Orientation'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool ThrottleUpdates'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  I'm not sure what this means, exactly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool IsColliding'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool CollidingGround'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool CollidingObj'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Stopped'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs get&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector CenterOfMass'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs get&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector GeometricCenter'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs get&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PrimitiveBaseShape Shape'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Force'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  I ''think'' this is a steady force (in N) always acting on the object.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Torque'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  Like Force, I think this is a steady torque operating on the object.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void AddForce(PhysicsVector force, bool pushforce)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This should apply a one-time impulse to the object of magnitude &amp;quot;force&amp;quot; Newton-seconds.  I am not sure what &amp;quot;pushforce&amp;quot; means....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void AddAngularForce(PhsyicsVector force, bool pushforce)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;A one-time angular impulse.  I'm not sure the units, nor what pushforce means.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''int VehicleType'''&lt;br /&gt;
&amp;lt;dd&amp;gt;(I don't know anything about the vehicle code requirements)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void VehicleFloatParam(int param, float value)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void VehicleVectorParam(int param, PhysicsVector value)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void VehicleRotationParam(int param, Quarternion rotation)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetVoulumeDetect(int param)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This is some weird mode that can be set via a LSL function&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float Buoyancy'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool FloatOnWater'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float CollisionScore'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  I don't know what this is.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Flying'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool SetAlwaysRun'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''unit LocalID'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs set.  I don't know what this is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Grabbed'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs set.  I'm not sure what this is, but I'm guessing it's when you control-click on an object?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void link(PhysicsActor obj)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;I haven't delved into how linking works in the physics engine.  I'm ''guessing'' that this says &amp;quot;link yourself to obj with obj as the root&amp;quot;, but I could be wrong.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void delink()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void LockAngularMomentum(PhysicsVector axis)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Selected'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void CrossingFailure()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector PIDTarget'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set.  I don't know what this is, but I'm guessing it's a place to which an object is supposed to move.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool PIDActive'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDTau'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set.  I'm guessing that this is the timescale (in seconds) in which the object should move to PIDTarget when it is set to be PID Active.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDHoverHeight'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDHoverActive'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PIDHoverType PIDHoverType'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDHoverTau'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SubscribeEvents(int ms)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;I do not know what sorts of events the PhysicsActor sends... hopefully I'll update this if/when I figure that out!  It looks like you can ask for OnPositionUpdate, OnVelocityUpdate, OnOrientationUpdate, OnRequestTerseUpdate, OnCollisionUpdate, and OnOutOfBounds... but I have yet to fully understand the OpenSim event system, so I may be speaking out of the side of my mouth here.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool SubscribedEvents()'''&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Physics_Engine_Interface</id>
		<title>Physics Engine Interface</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Physics_Engine_Interface"/>
				<updated>2009-09-18T20:24:03Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* PhysicsScene */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base Classes ==&lt;br /&gt;
&lt;br /&gt;
''Note: I ([[User:Rknop]]) am trying to figure this out by looking at some of the code; my main interest is the NewtonPlugin.  AS such, there are whole swaths of the physics engine, such as joints, that I have no clue about at the moment''&lt;br /&gt;
&lt;br /&gt;
The base classes for a physics module can be found in OpenSim.Region.Physics.Manager.  The physics module itself should be a subclass of Physics, e.g. OpenSim.Region.Physics.OdePlugin.&lt;br /&gt;
&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsActor&amp;lt;/tt&amp;gt;''' is the base class for both prims and avatars.&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsScene&amp;lt;/tt&amp;gt;''' is the main base class that interfaces with the region's Scene.&lt;br /&gt;
* (others)&lt;br /&gt;
&lt;br /&gt;
The Physics Scene doesn't access the Region Scene.  The region scene will tell the physics engine about prims and avatars, and will send updates to the physics engine.  It will then pull positions and velocities of objects and avatars out of the physics engine.&lt;br /&gt;
&lt;br /&gt;
For the most part, the things that will be interfacing with the physics engine are the classes &amp;lt;tt&amp;gt;OpenSim.Region.Framework.Scenes.Scene&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OpenSim.Region.Framework.Scenes.SceneObjectGroup&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;OpenSim.Region.Framework.Scenes.SceneObjectPart&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The Plugin Class ==&lt;br /&gt;
&lt;br /&gt;
If you're writing a Physics engine named Foo, you need to write a class OpenSim.Region.Physics.FooPlugin with the following methods:&lt;br /&gt;
&lt;br /&gt;
* '''FooPlugin()''' &amp;amp;mdash; constructor&lt;br /&gt;
* '''bool Init()''' &amp;amp;mdash; (not sure exactly when this is called.  return true)&lt;br /&gt;
* '''PhysicsScene GetScene(String sceneIdentifier)''' &amp;amp;mdash; return a FooScene, which is derived from PhysicsScene&lt;br /&gt;
* '''string GetName()''' &amp;amp;mdash; return the name that folks can use in OpenSim.ini to select this physics engine&lt;br /&gt;
* '''Dispose()''' &amp;amp;mdash; destructor&lt;br /&gt;
&lt;br /&gt;
== PhysicsScene ==&lt;br /&gt;
&lt;br /&gt;
Your class OpenSim.Region.Physics.FooScene must derive from OpenSim.Region.Physics.PhysicsScene.  Members include:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void Initialize(IMesher meshmerizer, IConfigSource config)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size, bool isFlying)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetWaterLevel(float baseheight)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemovePrim(PhysicsActor prim)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; This gets called when a prim is made into something the physics engine no longer needs to know about.  The physics engine should remove it from any internal lists of prims it is keeping track of.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemoveAvatar(PhysicsActor character)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; Like RemovePrim, but for avatars.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; Tells the physics engine to add a new prim it needs to keep track of.  This prim is ''not'' a physical prim, but as long as it's not phantom, physical objects may collide with it, and thus the physics engine (may) need to know about it.  (Unless the physics engine punts on collisions, as, for instance, NewtonPlugin does.)  Comments in the code indicate that this method is slated to be removed....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation, bool isPhysical)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Like the previous one, but you've got the flag that tells you if it's physical or not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPhysicsActorTaint(PhysicsActor prim)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;(I don't know what taints are, so I can't document them yet....)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void GetResults()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override bol IsThreaded'''&lt;br /&gt;
&amp;lt;dd&amp;gt;A member that needs a get method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetTerrain(float[] heightMap)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void DeleteTerrain()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public overrid Dictionary&amp;lt;unit, float&amp;gt; GetTopColliders()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override float Simulate(float timestep)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This is the core function.  This gets called by the main loop when it wants the Physics engine to do its magic and propagate forward the positions and velocities of all the stuff it knows about.  The physics engine should update the Position and Velocity members of the PhysicsActor class it knows about (those things that have been added to it by the methods above).  '''Important:''' when the physics engine thinks that things have changed enough for any given prims that the surrounding scene should updates it's own idea about the positions and velocities of those prims, it should call the RequestPhysicsterseUpdate() method of the changed PhysicsActors().  (The safest, but slowest, way to do this is for Simulate() to call this for every physical prim it knows about every time it is called.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PhysicsActor ==&lt;br /&gt;
&lt;br /&gt;
PhysicsActor represents both prims and characters.  You may want to make separate classes for the two.&lt;br /&gt;
&lt;br /&gt;
Members:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;'''int PhysicsActorType'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set methods.  Return ActorTypes.Prim or ActorTypes.Agent if it's a prim or an avatar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool IsPhysical'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Position'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  If an object is physical, the physics engine keeps the &amp;quot;real&amp;quot; position for that object.  However, it's the surrounding scene's impression of the position that gets rendered and sent to the client.  It will pull the position out of the physics engine by looking at this member, and tell the physics engine about any external changes in its position through this member.  Note that the scene doesn't automatically pull out the position, but only when it thinks it needs to.  You can call the RequestPhysicsterseUpdate() method of PhysicsActor to ask the Scene to update its position for any given PhysicsActor.  (See PhysicsScene.Simulate() above.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Velocity'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Need get and set.  Similar considerations to Position&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector RotationalVelocity'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Acceleration'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get; there's no set method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetAcceleration(PhysicsVector accel)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Do what you'd think Acceleration.set would do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Size'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float Mass'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get; there is no set method at the moment&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetMass(float mass)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Instead of Mass.set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetMomentum(PhysicsVector momentum)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;I am disturbed that this exists in addition to Velocity.set and SetMass....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''Quarternion Orientation'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool ThrottleUpdates'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  I'm not sure what this means, exactly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool IsColliding'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool CollidingGround'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool CollidingObj'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Stopped'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs get&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector CenterOfMass'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs get&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector GeometricCenter'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs get&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PrimitiveBaseShape Shape'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Force'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  I ''think'' this is a steady force (in N) always acting on the object.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Torque'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  Like Force, I think this is a steady torque operating on the object.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void AddForce(PhysicsVector force, bool pushforce)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This should apply a one-time impulse to the object of magnitude &amp;quot;force&amp;quot; Newton-seconds.  I am not sure what &amp;quot;pushforce&amp;quot; means....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void AddAngularForce(PhsyicsVector force, bool pushforce)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;A one-time angular impulse.  I'm not sure the units, nor what pushforce means.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''int VehicleType'''&lt;br /&gt;
&amp;lt;dd&amp;gt;(I don't know anything about the vehicle code requirements)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void VehicleFloatParam(int param, float value)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void VehicleVectorParam(int param, PhysicsVector value)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void VehicleRotationParam(int param, Quarternion rotation)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetVoulumeDetect(int param)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This is some weird mode that can be set via a LSL function&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float Buoyancy'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool FloatOnWater'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float CollisionScore'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  I don't know what this is.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Flying'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool SetAlwaysRun'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''unit LocalID'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs set.  I don't know what this is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Grabbed'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs set.  I'm not sure what this is, but I'm guessing it's when you control-click on an object?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void link(PhysicsActor obj)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;I haven't delved into how linking works in the physics engine.  I'm ''guessing'' that this says &amp;quot;link yourself to obj with obj as the root&amp;quot;, but I could be wrong.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void delink()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void LockAngularMomentum(PhysicsVector axis)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Selected'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void CrossingFailure()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector PIDTarget'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set.  I don't know what this is, but I'm guessing it's a place to which an object is supposed to move.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool PIDActive'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDTau'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set.  I'm guessing that this is the timescale (in seconds) in which the object should move to PIDTarget when it is set to be PID Active.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDHoverHeight'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDHoverActive'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PIDHoverType PIDHoverType'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDHoverTau'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SubscribeEvents(int ms)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;I do not know what sorts of events the PhysicsActor sends... hopefully I'll update this if/when I figure that out!  It looks like you can ask for OnPositionUpdate, OnVelocityUpdate, OnOrientationUpdate, OnRequestTerseUpdate, OnCollisionUpdate, and OnOutOfBounds... but I have yet to fully understand the OpenSim event system, so I may be speaking out of the side of my mouth here.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool SubscribedEvents()'''&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Physics_Engine_Interface</id>
		<title>Physics Engine Interface</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Physics_Engine_Interface"/>
				<updated>2009-09-18T20:21:47Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base Classes ==&lt;br /&gt;
&lt;br /&gt;
''Note: I ([[User:Rknop]]) am trying to figure this out by looking at some of the code; my main interest is the NewtonPlugin.  AS such, there are whole swaths of the physics engine, such as joints, that I have no clue about at the moment''&lt;br /&gt;
&lt;br /&gt;
The base classes for a physics module can be found in OpenSim.Region.Physics.Manager.  The physics module itself should be a subclass of Physics, e.g. OpenSim.Region.Physics.OdePlugin.&lt;br /&gt;
&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsActor&amp;lt;/tt&amp;gt;''' is the base class for both prims and avatars.&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsScene&amp;lt;/tt&amp;gt;''' is the main base class that interfaces with the region's Scene.&lt;br /&gt;
* (others)&lt;br /&gt;
&lt;br /&gt;
The Physics Scene doesn't access the Region Scene.  The region scene will tell the physics engine about prims and avatars, and will send updates to the physics engine.  It will then pull positions and velocities of objects and avatars out of the physics engine.&lt;br /&gt;
&lt;br /&gt;
For the most part, the things that will be interfacing with the physics engine are the classes &amp;lt;tt&amp;gt;OpenSim.Region.Framework.Scenes.Scene&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OpenSim.Region.Framework.Scenes.SceneObjectGroup&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;OpenSim.Region.Framework.Scenes.SceneObjectPart&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The Plugin Class ==&lt;br /&gt;
&lt;br /&gt;
If you're writing a Physics engine named Foo, you need to write a class OpenSim.Region.Physics.FooPlugin with the following methods:&lt;br /&gt;
&lt;br /&gt;
* '''FooPlugin()''' &amp;amp;mdash; constructor&lt;br /&gt;
* '''bool Init()''' &amp;amp;mdash; (not sure exactly when this is called.  return true)&lt;br /&gt;
* '''PhysicsScene GetScene(String sceneIdentifier)''' &amp;amp;mdash; return a FooScene, which is derived from PhysicsScene&lt;br /&gt;
* '''string GetName()''' &amp;amp;mdash; return the name that folks can use in OpenSim.ini to select this physics engine&lt;br /&gt;
* '''Dispose()''' &amp;amp;mdash; destructor&lt;br /&gt;
&lt;br /&gt;
== PhysicsScene ==&lt;br /&gt;
&lt;br /&gt;
Your class OpenSim.Region.Physics.FooScene must derive from OpenSim.Region.Physics.PhysicsScene.  Members include:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void Initialize(IMesher meshmerizer, IConfigSource config)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size, bool isFlying)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetWaterLevel(float baseheight)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemovePrim(PhysicsActor prim)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; This gets called when a prim is made into something the physics engine no longer needs to know about.  The physics engine should remove it from any internal lists of prims it is keeping track of.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemoveAvatar(PhysicsActor character)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; Like RemovePrim, but for avatars.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; Tells the physics engine to add a new prim it needs to keep track of.  This prim is ''not'' a physical prim, but as long as it's not phantom, physical objects may collide with it, and thus the physics engine (may) need to know about it.  (Unless the physics engine punts on collisions, as, for instance, NewtonPlugin does.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation, bool isPhysical)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Like the previous one, but you've got the flag that tells you if it's physical or not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPhysicsActorTaint(PhysicsActor prim)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;(I don't know what taints are, so I can't document them yet....)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void GetResults()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override bol IsThreaded'''&lt;br /&gt;
&amp;lt;dd&amp;gt;A member that needs a get method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetTerrain(float[] heightMap)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void DeleteTerrain()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public overrid Dictionary&amp;lt;unit, float&amp;gt; GetTopColliders()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override float Simulate(float timestep)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This is the core function.  This gets called by the main loop when it wants the Physics engine to do its magic and propagate forward the positions and velocities of all the stuff it knows about.  The physics engine should update the Position and Velocity members of the PhysicsActor class it knows about (those things that have been added to it by the methods above).  '''Important:''' when the physics engine thinks that things have changed enough for any given prims that the surrounding scene should updates it's own idea about the positions and velocities of those prims, it should call the RequestPhysicsterseUpdate() method of the changed PhysicsActors().  (The safest, but slowest, way to do this is for Simulate() to call this for every physical prim it knows about every time it is called.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PhysicsActor ==&lt;br /&gt;
&lt;br /&gt;
PhysicsActor represents both prims and characters.  You may want to make separate classes for the two.&lt;br /&gt;
&lt;br /&gt;
Members:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;'''int PhysicsActorType'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set methods.  Return ActorTypes.Prim or ActorTypes.Agent if it's a prim or an avatar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool IsPhysical'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Position'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  If an object is physical, the physics engine keeps the &amp;quot;real&amp;quot; position for that object.  However, it's the surrounding scene's impression of the position that gets rendered and sent to the client.  It will pull the position out of the physics engine by looking at this member, and tell the physics engine about any external changes in its position through this member.  Note that the scene doesn't automatically pull out the position, but only when it thinks it needs to.  You can call the RequestPhysicsterseUpdate() method of PhysicsActor to ask the Scene to update its position for any given PhysicsActor.  (See PhysicsScene.Simulate() above.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Velocity'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Need get and set.  Similar considerations to Position&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector RotationalVelocity'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Acceleration'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get; there's no set method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetAcceleration(PhysicsVector accel)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Do what you'd think Acceleration.set would do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Size'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float Mass'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get; there is no set method at the moment&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetMass(float mass)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Instead of Mass.set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetMomentum(PhysicsVector momentum)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;I am disturbed that this exists in addition to Velocity.set and SetMass....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''Quarternion Orientation'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool ThrottleUpdates'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  I'm not sure what this means, exactly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool IsColliding'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool CollidingGround'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool CollidingObj'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Stopped'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs get&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector CenterOfMass'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs get&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector GeometricCenter'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs get&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PrimitiveBaseShape Shape'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Force'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  I ''think'' this is a steady force (in N) always acting on the object.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Torque'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  Like Force, I think this is a steady torque operating on the object.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void AddForce(PhysicsVector force, bool pushforce)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This should apply a one-time impulse to the object of magnitude &amp;quot;force&amp;quot; Newton-seconds.  I am not sure what &amp;quot;pushforce&amp;quot; means....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void AddAngularForce(PhsyicsVector force, bool pushforce)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;A one-time angular impulse.  I'm not sure the units, nor what pushforce means.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''int VehicleType'''&lt;br /&gt;
&amp;lt;dd&amp;gt;(I don't know anything about the vehicle code requirements)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void VehicleFloatParam(int param, float value)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void VehicleVectorParam(int param, PhysicsVector value)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void VehicleRotationParam(int param, Quarternion rotation)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetVoulumeDetect(int param)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This is some weird mode that can be set via a LSL function&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float Buoyancy'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool FloatOnWater'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float CollisionScore'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  I don't know what this is.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Flying'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool SetAlwaysRun'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''unit LocalID'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs set.  I don't know what this is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Grabbed'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs set.  I'm not sure what this is, but I'm guessing it's when you control-click on an object?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void link(PhysicsActor obj)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;I haven't delved into how linking works in the physics engine.  I'm ''guessing'' that this says &amp;quot;link yourself to obj with obj as the root&amp;quot;, but I could be wrong.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void delink()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void LockAngularMomentum(PhysicsVector axis)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Selected'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void CrossingFailure()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector PIDTarget'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set.  I don't know what this is, but I'm guessing it's a place to which an object is supposed to move.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool PIDActive'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDTau'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set.  I'm guessing that this is the timescale (in seconds) in which the object should move to PIDTarget when it is set to be PID Active.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDHoverHeight'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDHoverActive'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PIDHoverType PIDHoverType'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDHoverTau'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SubscribeEvents(int ms)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;I do not know what sorts of events the PhysicsActor sends... hopefully I'll update this if/when I figure that out!  It looks like you can ask for OnPositionUpdate, OnVelocityUpdate, OnOrientationUpdate, OnRequestTerseUpdate, OnCollisionUpdate, and OnOutOfBounds... but I have yet to fully understand the OpenSim event system, so I may be speaking out of the side of my mouth here.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool SubscribedEvents()'''&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Physics_Engine_Interface</id>
		<title>Physics Engine Interface</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Physics_Engine_Interface"/>
				<updated>2009-09-18T20:20:02Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base Classes ==&lt;br /&gt;
&lt;br /&gt;
''Note: I ([[User:Rknop]]) am trying to figure this out by looking at some of the code; my main interest is the NewtonPlugin.  AS such, there are whole swaths of the physics engine, such as joints, that I have no clue about at the moment''&lt;br /&gt;
&lt;br /&gt;
The base classes for a physics module can be found in OpenSim.Region.Physics.Manager.  The physics module itself should be a subclass of Physics, e.g. OpenSim.Region.Physics.OdePlugin.&lt;br /&gt;
&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsActor&amp;lt;/tt&amp;gt;''' is the base class for both prims and avatars.&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsScene&amp;lt;/tt&amp;gt;''' is the main base class that interfaces with the region's Scene.&lt;br /&gt;
* (others)&lt;br /&gt;
&lt;br /&gt;
The Physics Scene doesn't access the Region Scene.  The region scene will tell the physics engine about prims and avatars, and will send updates to the physics engine.  It will then pull positions and velocities of objects and avatars out of the physics engine.&lt;br /&gt;
&lt;br /&gt;
== The Plugin Class ==&lt;br /&gt;
&lt;br /&gt;
If you're writing a Physics engine named Foo, you need to write a class OpenSim.Region.Physics.FooPlugin with the following methods:&lt;br /&gt;
&lt;br /&gt;
* '''FooPlugin()''' &amp;amp;mdash; constructor&lt;br /&gt;
* '''bool Init()''' &amp;amp;mdash; (not sure exactly when this is called.  return true)&lt;br /&gt;
* '''PhysicsScene GetScene(String sceneIdentifier)''' &amp;amp;mdash; return a FooScene, which is derived from PhysicsScene&lt;br /&gt;
* '''string GetName()''' &amp;amp;mdash; return the name that folks can use in OpenSim.ini to select this physics engine&lt;br /&gt;
* '''Dispose()''' &amp;amp;mdash; destructor&lt;br /&gt;
&lt;br /&gt;
== PhysicsScene ==&lt;br /&gt;
&lt;br /&gt;
Your class OpenSim.Region.Physics.FooScene must derive from OpenSim.Region.Physics.PhysicsScene.  Members include:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void Initialize(IMesher meshmerizer, IConfigSource config)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size, bool isFlying)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetWaterLevel(float baseheight)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemovePrim(PhysicsActor prim)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; This gets called when a prim is made into something the physics engine no longer needs to know about.  The physics engine should remove it from any internal lists of prims it is keeping track of.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemoveAvatar(PhysicsActor character)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; Like RemovePrim, but for avatars.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; Tells the physics engine to add a new prim it needs to keep track of.  This prim is ''not'' a physical prim, but as long as it's not phantom, physical objects may collide with it, and thus the physics engine (may) need to know about it.  (Unless the physics engine punts on collisions, as, for instance, NewtonPlugin does.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation, bool isPhysical)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Like the previous one, but you've got the flag that tells you if it's physical or not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPhysicsActorTaint(PhysicsActor prim)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;(I don't know what taints are, so I can't document them yet....)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void GetResults()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override bol IsThreaded'''&lt;br /&gt;
&amp;lt;dd&amp;gt;A member that needs a get method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetTerrain(float[] heightMap)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void DeleteTerrain()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public overrid Dictionary&amp;lt;unit, float&amp;gt; GetTopColliders()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override float Simulate(float timestep)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This is the core function.  This gets called by the main loop when it wants the Physics engine to do its magic and propagate forward the positions and velocities of all the stuff it knows about.  The physics engine should update the Position and Velocity members of the PhysicsActor class it knows about (those things that have been added to it by the methods above).  '''Important:''' when the physics engine thinks that things have changed enough for any given prims that the surrounding scene should updates it's own idea about the positions and velocities of those prims, it should call the RequestPhysicsterseUpdate() method of the changed PhysicsActors().  (The safest, but slowest, way to do this is for Simulate() to call this for every physical prim it knows about every time it is called.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PhysicsActor ==&lt;br /&gt;
&lt;br /&gt;
PhysicsActor represents both prims and characters.  You may want to make separate classes for the two.&lt;br /&gt;
&lt;br /&gt;
Members:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;'''int PhysicsActorType'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set methods.  Return ActorTypes.Prim or ActorTypes.Agent if it's a prim or an avatar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool IsPhysical'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Position'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  If an object is physical, the physics engine keeps the &amp;quot;real&amp;quot; position for that object.  However, it's the surrounding scene's impression of the position that gets rendered and sent to the client.  It will pull the position out of the physics engine by looking at this member, and tell the physics engine about any external changes in its position through this member.  Note that the scene doesn't automatically pull out the position, but only when it thinks it needs to.  You can call the RequestPhysicsterseUpdate() method of PhysicsActor to ask the Scene to update its position for any given PhysicsActor.  (See PhysicsScene.Simulate() above.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Velocity'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Need get and set.  Similar considerations to Position&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector RotationalVelocity'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Acceleration'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get; there's no set method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetAcceleration(PhysicsVector accel)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Do what you'd think Acceleration.set would do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Size'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float Mass'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get; there is no set method at the moment&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetMass(float mass)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Instead of Mass.set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetMomentum(PhysicsVector momentum)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;I am disturbed that this exists in addition to Velocity.set and SetMass....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''Quarternion Orientation'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool ThrottleUpdates'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  I'm not sure what this means, exactly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool IsColliding'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool CollidingGround'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool CollidingObj'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Stopped'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs get&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector CenterOfMass'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs get&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector GeometricCenter'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs get&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PrimitiveBaseShape Shape'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Force'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  I ''think'' this is a steady force (in N) always acting on the object.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector Torque'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  Like Force, I think this is a steady torque operating on the object.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void AddForce(PhysicsVector force, bool pushforce)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This should apply a one-time impulse to the object of magnitude &amp;quot;force&amp;quot; Newton-seconds.  I am not sure what &amp;quot;pushforce&amp;quot; means....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void AddAngularForce(PhsyicsVector force, bool pushforce)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;A one-time angular impulse.  I'm not sure the units, nor what pushforce means.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''int VehicleType'''&lt;br /&gt;
&amp;lt;dd&amp;gt;(I don't know anything about the vehicle code requirements)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void VehicleFloatParam(int param, float value)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void VehicleVectorParam(int param, PhysicsVector value)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void VehicleRotationParam(int param, Quarternion rotation)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SetVoulumeDetect(int param)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This is some weird mode that can be set via a LSL function&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float Buoyancy'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool FloatOnWater'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float CollisionScore'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set.  I don't know what this is.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Flying'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool SetAlwaysRun'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs get and set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''unit LocalID'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs set.  I don't know what this is&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Grabbed'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Needs set.  I'm not sure what this is, but I'm guessing it's when you control-click on an object?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void link(PhysicsActor obj)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;I haven't delved into how linking works in the physics engine.  I'm ''guessing'' that this says &amp;quot;link yourself to obj with obj as the root&amp;quot;, but I could be wrong.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void delink()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void LockAngularMomentum(PhysicsVector axis)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool Selected'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void CrossingFailure()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PhysicsVector PIDTarget'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set.  I don't know what this is, but I'm guessing it's a place to which an object is supposed to move.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool PIDActive'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDTau'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Just needs set.  I'm guessing that this is the timescale (in seconds) in which the object should move to PIDTarget when it is set to be PID Active.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDHoverHeight'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDHoverActive'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''PIDHoverType PIDHoverType'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''float PIDHoverTau'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''void SubscribeEvents(int ms)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;I do not know what sorts of events the PhysicsActor sends... hopefully I'll update this if/when I figure that out!  It looks like you can ask for OnPositionUpdate, OnVelocityUpdate, OnOrientationUpdate, OnRequestTerseUpdate, OnCollisionUpdate, and OnOutOfBounds... but I have yet to fully understand the OpenSim event system, so I may be speaking out of the side of my mouth here.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''bool SubscribedEvents()'''&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/User:Rknop</id>
		<title>User:Rknop</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/User:Rknop"/>
				<updated>2009-09-18T19:48:47Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: New page: Rob Knop, aka Prospero Frobozz in Second Life.  Itinerant astrophysicist and computer engineer.  Home page : http://www.sonic.net/~rknop  Blog : http://www.sonic.net/~rknop/blog  E-mail : ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Rob Knop, aka Prospero Frobozz in Second Life.&lt;br /&gt;
&lt;br /&gt;
Itinerant astrophysicist and computer engineer.&lt;br /&gt;
&lt;br /&gt;
Home page : http://www.sonic.net/~rknop&lt;br /&gt;
&lt;br /&gt;
Blog : http://www.sonic.net/~rknop/blog&lt;br /&gt;
&lt;br /&gt;
E-mail : rknop@pobox.com&lt;br /&gt;
&lt;br /&gt;
rknop on #opensim and #opensim-dev&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Physics_Engine_Interface</id>
		<title>Physics Engine Interface</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Physics_Engine_Interface"/>
				<updated>2009-09-18T19:47:03Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* PhysicsScene */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base Classes ==&lt;br /&gt;
&lt;br /&gt;
''Note: I ([[User:Rknop]]) am trying to figure this out by looking at some of the code; my main interest is the NewtonPlugin.  AS such, there are whole swaths of the physics engine, such as joints, that I have no clue about at the moment''&lt;br /&gt;
&lt;br /&gt;
The base classes for a physics module can be found in OpenSim.Region.Physics.Manager.  The physics module itself should be a subclass of Physics, e.g. OpenSim.Region.Physics.OdePlugin.&lt;br /&gt;
&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsActor&amp;lt;/tt&amp;gt;''' is the base class for both prims and avatars.&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsScene&amp;lt;/tt&amp;gt;''' is the main base class that interfaces with the region's Scene.&lt;br /&gt;
* (others)&lt;br /&gt;
&lt;br /&gt;
The Physics Scene doesn't access the Region Scene.  The region scene will tell the physics engine about prims and avatars, and will send updates to the physics engine.  It will then pull positions and velocities of objects and avatars out of the physics engine.&lt;br /&gt;
&lt;br /&gt;
== The Plugin Class ==&lt;br /&gt;
&lt;br /&gt;
If you're writing a Physics engine named Foo, you need to write a class OpenSim.Region.Physics.FooPlugin with the following methods:&lt;br /&gt;
&lt;br /&gt;
* '''FooPlugin()''' &amp;amp;mdash; constructor&lt;br /&gt;
* '''bool Init()''' &amp;amp;mdash; (not sure exactly when this is called.  return true)&lt;br /&gt;
* '''PhysicsScene GetScene(String sceneIdentifier)''' &amp;amp;mdash; return a FooScene, which is derived from PhysicsScene&lt;br /&gt;
* '''string GetName()''' &amp;amp;mdash; return the name that folks can use in OpenSim.ini to select this physics engine&lt;br /&gt;
* '''Dispose()''' &amp;amp;mdash; destructor&lt;br /&gt;
&lt;br /&gt;
== PhysicsScene ==&lt;br /&gt;
&lt;br /&gt;
Your class OpenSim.Region.Physics.FooScene must derive from OpenSim.Region.Physics.PhysicsScene.  Members include:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void Initialize(IMesher meshmerizer, IConfigSource config)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size, bool isFlying)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetWaterLevel(float baseheight)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemovePrim(PhysicsActor prim)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; This gets called when a prim is made into something the physics engine no longer needs to know about.  The physics engine should remove it from any internal lists of prims it is keeping track of.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemoveAvatar(PhysicsActor character)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; Like RemovePrim, but for avatars.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; Tells the physics engine to add a new prim it needs to keep track of.  This prim is ''not'' a physical prim, but as long as it's not phantom, physical objects may collide with it, and thus the physics engine (may) need to know about it.  (Unless the physics engine punts on collisions, as, for instance, NewtonPlugin does.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation, bool isPhysical)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Like the previous one, but you've got the flag that tells you if it's physical or not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPhysicsActorTaint(PhysicsActor prim)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;(I don't know what taints are, so I can't document them yet....)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void GetResults()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override bol IsThreaded'''&lt;br /&gt;
&amp;lt;dd&amp;gt;A member that needs a get method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetTerrain(float[] heightMap)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void DeleteTerrain()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public overrid Dictionary&amp;lt;unit, float&amp;gt; GetTopColliders()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override float Simulate(float timestep)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This is the core function.  This gets called by the main loop when it wants the Physics engine to do its magic and propagate forward the positions and velocities of all the stuff it knows about.  The physics engine should update the Position and Velocity members of the PhysicsActor class it knows about (those things that have been added to it by the methods above).  '''Important:''' when the physics engine thinks that things have changed enough for any given prims that the surrounding scene should updates it's own idea about the positions and velocities of those prims, it should call the RequestPhysicsterseUpdate() method of the changed PhysicsActors().  (The safest, but slowest, way to do this is for Simulate() to call this for every physical prim it knows about every time it is called.)&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Physics_Engine_Interface</id>
		<title>Physics Engine Interface</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Physics_Engine_Interface"/>
				<updated>2009-09-18T19:44:57Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* PhysicsScene */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base Classes ==&lt;br /&gt;
&lt;br /&gt;
''Note: I ([[User:Rknop]]) am trying to figure this out by looking at some of the code; my main interest is the NewtonPlugin.  AS such, there are whole swaths of the physics engine, such as joints, that I have no clue about at the moment''&lt;br /&gt;
&lt;br /&gt;
The base classes for a physics module can be found in OpenSim.Region.Physics.Manager.  The physics module itself should be a subclass of Physics, e.g. OpenSim.Region.Physics.OdePlugin.&lt;br /&gt;
&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsActor&amp;lt;/tt&amp;gt;''' is the base class for both prims and avatars.&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsScene&amp;lt;/tt&amp;gt;''' is the main base class that interfaces with the region's Scene.&lt;br /&gt;
* (others)&lt;br /&gt;
&lt;br /&gt;
The Physics Scene doesn't access the Region Scene.  The region scene will tell the physics engine about prims and avatars, and will send updates to the physics engine.  It will then pull positions and velocities of objects and avatars out of the physics engine.&lt;br /&gt;
&lt;br /&gt;
== The Plugin Class ==&lt;br /&gt;
&lt;br /&gt;
If you're writing a Physics engine named Foo, you need to write a class OpenSim.Region.Physics.FooPlugin with the following methods:&lt;br /&gt;
&lt;br /&gt;
* '''FooPlugin()''' &amp;amp;mdash; constructor&lt;br /&gt;
* '''bool Init()''' &amp;amp;mdash; (not sure exactly when this is called.  return true)&lt;br /&gt;
* '''PhysicsScene GetScene(String sceneIdentifier)''' &amp;amp;mdash; return a FooScene, which is derived from PhysicsScene&lt;br /&gt;
* '''string GetName()''' &amp;amp;mdash; return the name that folks can use in OpenSim.ini to select this physics engine&lt;br /&gt;
* '''Dispose()''' &amp;amp;mdash; destructor&lt;br /&gt;
&lt;br /&gt;
== PhysicsScene ==&lt;br /&gt;
&lt;br /&gt;
Your class OpenSim.Region.Physics.FooScene must derive from OpenSim.Region.Physics.PhysicsScene.  Methods include:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void Initialize(IMesher meshmerizer, IConfigSource config)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size, bool isFlying)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetWaterLevel(float baseheight)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemovePrim(PhysicsActor prim)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; This gets called when a prim is made into something the physics engine no longer needs to know about.  The physics engine should remove it from any internal lists of prims it is keeping track of.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemoveAvatar(PhysicsActor character)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; Like RemovePrim, but for avatars.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation)'''&lt;br /&gt;
&amp;lt;dd&amp;gt; Tells the physics engine to add a new prim it needs to keep track of.  This prim is ''not'' a physical prim, but as long as it's not phantom, physical objects may collide with it, and thus the physics engine (may) need to know about it.  (Unless the physics engine punts on collisions, as, for instance, NewtonPlugin does.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation, bool isPhysical)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;Like the previous one, but you've got the flag that tells you if it's physical or not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPhysicsActorTaint(PhysicsActor prim)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;(I don't know what taints are, so I can't document them yet....)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void GetResults()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override bol IsThreaded'''&lt;br /&gt;
&amp;lt;dd&amp;gt;A member that needs a get method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetTerrain(float[] heightMap)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void DeleteTerrain()'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public overrid Dictionary&amp;lt;unit, float&amp;gt; GetTopColliders()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override float Simulate(float timestep)'''&lt;br /&gt;
&amp;lt;dd&amp;gt;This is the core function.  This gets called by the main loop when it wants the Physics engine to do its magic and propagate forward the positions and velocities of all the stuff it knows about.  The physics engine should update the Position and Velocity members of the PhysicsActor class it knows about (those things that have been added to it by the methods above).  '''Important:''' when the physics engine thinks that things have changed enough for any given prims that the surrounding scene should updates it's own idea about the positions and velocities of those prims, it should call the RequestPhysicsterseUpdate() method of the changed PhysicsActors().  (The safest, but slowest, way to do this is for Simulate() to call this for every physical prim it knows about every time it is called.)&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Physics_Engine_Interface</id>
		<title>Physics Engine Interface</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Physics_Engine_Interface"/>
				<updated>2009-09-18T19:42:08Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: New page: == Base Classes ==  ''Note: I (User:Rknop) am trying to figure this out by looking at some of the code; my main interest is the NewtonPlugin.  AS such, there are whole swaths of the ph...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Base Classes ==&lt;br /&gt;
&lt;br /&gt;
''Note: I ([[User:Rknop]]) am trying to figure this out by looking at some of the code; my main interest is the NewtonPlugin.  AS such, there are whole swaths of the physics engine, such as joints, that I have no clue about at the moment''&lt;br /&gt;
&lt;br /&gt;
The base classes for a physics module can be found in OpenSim.Region.Physics.Manager.  The physics module itself should be a subclass of Physics, e.g. OpenSim.Region.Physics.OdePlugin.&lt;br /&gt;
&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsActor&amp;lt;/tt&amp;gt;''' is the base class for both prims and avatars.&lt;br /&gt;
* '''&amp;lt;tt&amp;gt;PhysicsScene&amp;lt;/tt&amp;gt;''' is the main base class that interfaces with the region's Scene.&lt;br /&gt;
* (others)&lt;br /&gt;
&lt;br /&gt;
The Physics Scene doesn't access the Region Scene.  The region scene will tell the physics engine about prims and avatars, and will send updates to the physics engine.  It will then pull positions and velocities of objects and avatars out of the physics engine.&lt;br /&gt;
&lt;br /&gt;
== The Plugin Class ==&lt;br /&gt;
&lt;br /&gt;
If you're writing a Physics engine named Foo, you need to write a class OpenSim.Region.Physics.FooPlugin with the following methods:&lt;br /&gt;
&lt;br /&gt;
* '''FooPlugin()''' &amp;amp;mdash; constructor&lt;br /&gt;
* '''bool Init()''' &amp;amp;mdash; (not sure exactly when this is called.  return true)&lt;br /&gt;
* '''PhysicsScene GetScene(String sceneIdentifier)''' &amp;amp;mdash; return a FooScene, which is derived from PhysicsScene&lt;br /&gt;
* '''string GetName()''' &amp;amp;mdash; return the name that folks can use in OpenSim.ini to select this physics engine&lt;br /&gt;
* '''Dispose()''' &amp;amp;mdash; destructor&lt;br /&gt;
&lt;br /&gt;
== PhysicsScene ==&lt;br /&gt;
&lt;br /&gt;
Your class OpenSim.Region.Physics.FooScene must derive from OpenSim.Region.Physics.PhysicsScene.  Methods include:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void Initialize(IMesher meshmerizer, IConfigSource config)'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size, bool isFlying)'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetWaterLevel(float baseheight)'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemovePrim(PhysicsActor prim)'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt; This gets called when a prim is made into something the physics engine no longer needs to know about.  The physics engine should remove it from any internal lists of prims it is keeping track of.&amp;lt;/dd&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void RemoveAvatar(PhysicsActor character)'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt; Like RemovePrim, but for avatars.&amp;lt;/dd&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation)'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt; Tells the physics engine to add a new prim it needs to keep track of.  This prim is ''not'' a physical prim, but as long as it's not phantom, physical objects may collide with it, and thus the physics engine (may) need to know about it.  (Unless the physics engine punts on collisions, as, for instance, NewtonPlugin does.)&amp;lt;/dd&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quarternion rotation, bool isPhysical)'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Like the previous one, but you've got the flag that tells you if it's physical or not.&amp;lt;/dd&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void AddPhysicsActorTaint(PhysicsActor prim)'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;(I don't know what taints are, so I can't document them yet....)&amp;lt;/dd&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void GetResults()'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override bol IsThreaded'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void SetTerrain(float[] heightMap)'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override void DeleteTerrain()'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public overrid Dictionary&amp;lt;unit, float&amp;gt; GetTopColliders()&amp;lt;/dt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dt&amp;gt;'''public override float Simulate(float timestep)'''&amp;lt;/dt&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;This is the core function.  This gets called by the main loop when it wants the Physics engine to do its magic and propagate forward the positions and velocities of all the stuff it knows about.  The physics engine should update the Position and Velocity members of the PhysicsActor class it knows about (those things that have been added to it by the methods above).  '''Important:''' when the physics engine thinks that things have changed enough for any given prims that the surrounding scene should updates it's own idea about the positions and velocities of those prims, it should call the RequestPhysicsterseUpdate() method of the changed PhysicsActors().  (The safest, but slowest, way to do this is for Simulate() to call this for every physical prim it knows about every time it is called.)&amp;lt;/dd&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Developer_Documentation</id>
		<title>Developer Documentation</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Developer_Documentation"/>
				<updated>2009-09-18T19:19:26Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* Physics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Quicklinks}}&lt;br /&gt;
&lt;br /&gt;
[[Technical Reference | Technical Reference]] -&amp;gt; [[Technical Reference/terms | Terms]] -&amp;gt; [[Developer_Documentation | Developer Documentation]]&lt;br /&gt;
&lt;br /&gt;
== Developer Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== General ====&lt;br /&gt;
* [[Development Team]] &amp;amp;mdash; OpenSim is brought to you by...&lt;br /&gt;
* [[OpenSim:Introduction_and_Definitions  | OpenSim: Introduction and Definitions]] &amp;amp;mdash; A work in progress describing the high level components of OpenSim&lt;br /&gt;
* [[Technical Reference | OpenSim: Technical Reference]] &amp;amp;mdash; A technical description of the simulator operation.&lt;br /&gt;
* [[Grid Architecture Diagram]]&lt;br /&gt;
* [[OpenSim: Screenshots]] &amp;amp;mdash; Various OpenSim screenshots.&lt;br /&gt;
* [http://docs.opensimulator.org/index.html The OpenSim API]&lt;br /&gt;
&lt;br /&gt;
==== Development ====&lt;br /&gt;
* [[Release Cycle]]&lt;br /&gt;
* [[On revisions, tags and branches]]&lt;br /&gt;
* [[Hacking OpenSim for fun and profit]] &amp;amp;mdash; A starters guide for programming OpenSim.&lt;br /&gt;
* [[Coding standards]] &amp;amp;mdash; Coding conventions for developers.&lt;br /&gt;
* [[Automated Testing]] &amp;amp;mdash; How to write tests for OpenSim.&lt;br /&gt;
* [[Debugging Unit Tests]] &amp;amp;mdash; How to debug the automated tests.&lt;br /&gt;
* [[Branches]] &amp;amp;mdash; An overview of the repository branches and what they are for.&lt;br /&gt;
* [[Monodevelop]] &amp;amp;mdash; How to use the [[monodevelop]] IDE for editing C# solutions.&lt;br /&gt;
* [[Creating New Solution]] &amp;amp;mdash; How to create new solution according to OpenSim conventions.&lt;br /&gt;
* [[Improving Performance]] &amp;amp;mdash; Efforts to increase OpenSim's performance.&lt;br /&gt;
&lt;br /&gt;
==== Services ====&lt;br /&gt;
&lt;br /&gt;
* [http://opensimulator.org/mantis Mantis Bug Tracking] &amp;amp;mdash; Mantis is the issue tracking tool of OpenSimulator.&lt;br /&gt;
* [http://www.opensimulator.org:8085/browse/OPENSIM-TRUNK Bamboo Continuous Integration] &amp;amp;mdash; Bamboo builds the source base continuously and runs unit tests.&lt;br /&gt;
* [http://forge.opensimulator.org/gf/ OpenSimulator GForge] &amp;amp;mdash; Project hosting for OpenSimulator related projects.&lt;br /&gt;
&lt;br /&gt;
==== Client Stacks ====&lt;br /&gt;
* [[Sim Throttles]] &amp;amp;mdash; Information on how OpenSim handles throttling of packets to the client.&lt;br /&gt;
&lt;br /&gt;
==== Database ====&lt;br /&gt;
* [[Database Documentation]] &amp;amp;mdash; A map of grid and region instances used in OpenSim&lt;br /&gt;
* [[MonoSqlite]] &amp;amp;mdash; How the database model currently works.&lt;br /&gt;
* [[LSL:PrimitiveParams]] &amp;amp;mdash; Notes on converting SL Edit GUI values and LSL PrimitiveParams to OpenSim PrimitiveBaseShape fields&lt;br /&gt;
* [[NHibernate Performance Testing]] &amp;amp;mdash; SQLite and MySQL performance tests with NHibernate.&lt;br /&gt;
&lt;br /&gt;
==== File formats ====&lt;br /&gt;
* [[Technical_Reference/OpenSim_Archive_Region_Format]] - Opensim ARchive (OAR) region archive file format.&lt;br /&gt;
&lt;br /&gt;
==== Grid ====&lt;br /&gt;
* [[Asset Server problems]] - list of known problems with the asset server&lt;br /&gt;
* [[Teleports]] - some diagrams about OGP and Hypergrid teleport sequences&lt;br /&gt;
* [[Agent Domain / Service]] - Details about the GridForge hosted Agent Domain/Service code&lt;br /&gt;
&lt;br /&gt;
==== Web Integration ====&lt;br /&gt;
* [[Webinterface]] &amp;amp;mdash; How to mashup with the web.&lt;br /&gt;
* [[RemoteAdmin]] &amp;amp;mdash; How to use the remote admin plug-in.&lt;br /&gt;
* [[RestConsole]] - Description how to use the REST remote console &lt;br /&gt;
* [[REST]] &amp;amp;mdash; Information about the REST interface to assets, inventory, etc.&lt;br /&gt;
* [[Known Web Interfaces within OpenSim]] &amp;amp;mdash; The set of CAPS, XMLRPC, or REST entry points in the project.&lt;br /&gt;
&lt;br /&gt;
==== Modules ====&lt;br /&gt;
* [[RegionModules]] &amp;amp;mdash; The various modules that are used in the RegionServer and how to write new ones.&lt;br /&gt;
* [[How to create a dynamic plugin]] - A tutorial for using PluginLoader&lt;br /&gt;
* [[Getting Started with Region Modules]] - This brief tutorial is intended to get people started with developing applications with/for opensim using region modules and the opensim API.&lt;br /&gt;
* [[Web Statistics Module]] - The web statistics module documentation and counter wish list.&lt;br /&gt;
&lt;br /&gt;
==== Permissions ====&lt;br /&gt;
* [[OpenSim:Permissions(Server)]]   &amp;amp;mdash; Permissions system as implemented on the region server.&lt;br /&gt;
* [[OpenSim: Permissions]] &amp;amp;mdash; Notes on how object permissions are handled on the client.&lt;br /&gt;
&lt;br /&gt;
==== Physics ====&lt;br /&gt;
* [[PhysicsEngines]]   &amp;amp;mdash; Options for physics engines in OpenSim.&lt;br /&gt;
* [[Physics Engine Interface]] &amp;amp;mdash; what methods and such exist in a Physics module&lt;br /&gt;
&lt;br /&gt;
==== Protocols ====&lt;br /&gt;
* [[Metaverse Exchange Protocol]] &amp;amp;mdash; MXP is alternative protocol for secondlife protocol.&lt;br /&gt;
&lt;br /&gt;
==== Regions ====&lt;br /&gt;
* [[Overview of How Regions Work]] - notes from ter_afk to rknop in #opensim-dev, cleaned up a bit&lt;br /&gt;
* [[OpenSim: Permissions]] &amp;amp;mdash; Notes on object permissions &amp;amp; definition of the ObjectFlags variable.&lt;br /&gt;
* [[OpenSim Load Balancing and Region Splitting]] - Instructions for using load balancing and region splitting features.&lt;br /&gt;
&lt;br /&gt;
==== Threading ====&lt;br /&gt;
* [[OpenSim: Threading strategy]] &amp;amp;mdash; How threading is implemented and handled.&lt;br /&gt;
&lt;br /&gt;
==== Scripting ====&lt;br /&gt;
* [[Scripting_Documentation]] &amp;amp;mdash; How to use scripts and what limitations apply.&lt;br /&gt;
* [[LSL_Status/Functions|LSL Implemented]]   &amp;amp;mdash; A list of LSL-functions that are available in OpenSim.&lt;br /&gt;
* [[OSSL]] &amp;amp;mdash; Some information about the OpenSimulator Scripting Language, and how to implement an OSSL function&lt;br /&gt;
* [[OpenSim.Region.ScriptEngine]] &amp;amp;mdash; How the ScriptEngine looks internally.&lt;br /&gt;
&lt;br /&gt;
==== Search ====&lt;br /&gt;
* [[OpenSim.Region.DataSnapshot]] - Shiny new data gathering/search system&lt;br /&gt;
* [[ImageService]] - Shiny new region module for serving search-related images&lt;br /&gt;
&lt;br /&gt;
==== Testing ====&lt;br /&gt;
* [[Automated_Testing]] &amp;amp;mdash; Writing Automated tests for OpenSim.&lt;br /&gt;
* [[Debugging Unit Tests]] &amp;amp;mdash; Debugging unit tests.&lt;br /&gt;
* [[OpenSim: Debugging - profiler dumps]] &amp;amp;mdash; Dumps of OpenSim profiles to aid in tracking memory leaks.&lt;br /&gt;
* [[Prim_Linking_Testing]] &amp;amp;mdash; Test cases for in world link/unlinking of prims.&lt;br /&gt;
&lt;br /&gt;
==Proposals==&lt;br /&gt;
&lt;br /&gt;
* [[Opensim: 0.5 Release Target Discussion]]&lt;br /&gt;
* [[Opensim: 0.6 Release Target Discussion]]&lt;br /&gt;
* [[Opensim: Future Release Discussion]]&lt;br /&gt;
&lt;br /&gt;
* [[A better SimCrossing]] - A work in progress about implementing a smooth simcrossing&lt;br /&gt;
* [[OpenID]] - Proposal for using OpenID in OpenSim&lt;br /&gt;
* [[AssetServerProposal]] - Proposal for a distributed asset server&lt;br /&gt;
* [[Creating profiles not used for login]] - RFC for alternative ways of creating profiles that will never be used for login&lt;br /&gt;
* [[OpenSim_Services_and_Service_Connectors]] - new infrastructure for connecting region simulators to backend services&lt;br /&gt;
* [[OpenSim Profile Anchors]] - a mechanism for retaining creator information for offline item transfers&lt;br /&gt;
* [[Explicit Object Serialization]] - a proposal to explicitly serialize scene objects rather than using automatic .NET XML serialization&lt;br /&gt;
&lt;br /&gt;
==== Proposed projects ====&lt;br /&gt;
&lt;br /&gt;
* [[OpenWiredux: Taking the next step]]&lt;br /&gt;
* [[Using SNMP in OpenSim]]&lt;br /&gt;
&lt;br /&gt;
==Communication==&lt;br /&gt;
&lt;br /&gt;
A good first point of contact is the OpenSim IRC, on irc.freenode.net channels #opensim / #opensim-dev. The OpenSim developers hold [[office hours]] once a week in-world on Tuesdays at &amp;quot;Wright Plaza&amp;quot; on OSGrid. There is a &amp;quot;Test Hour&amp;quot; on Saturdays, also generally on &amp;quot;Wright Plaza&amp;quot;. Both these weekly events are held at 1900UTC. Check on the #opensim IRC channel on Freenode just before each of these events if there is any confusion.&lt;br /&gt;
&lt;br /&gt;
There is also a mailman email distribution list available at https://lists.berlios.de/mailman/listinfo/opensim-dev&lt;br /&gt;
&lt;br /&gt;
==Interest Groups==&lt;br /&gt;
* [[OpenSim Quality Focus Group]] - A proposed group for developers interested in improving the quality of OpenSim as we head towards beta status.&lt;br /&gt;
&lt;br /&gt;
==Git Access==&lt;br /&gt;
You can browse the source code for OpenSim [http://opensimulator.org/viewgit using a web browser] or via git.&lt;br /&gt;
* Anonymous Checkout - see [[Download]]&lt;br /&gt;
* Developer Checkout&lt;br /&gt;
 git clone ssh://USERNAME@opensimulator.org/var/git/opensim&lt;br /&gt;
&lt;br /&gt;
==Submitting Patches==&lt;br /&gt;
&lt;br /&gt;
Please review [[Submitting_code_to_OpenSim]]&lt;br /&gt;
&lt;br /&gt;
==Recent Git Commits==&lt;br /&gt;
&amp;lt;rss&amp;gt;http://opensimulator.org/viewgit?a=rss-log&amp;amp;p=opensim|max=5|title=none&amp;lt;/rss&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Main]]&lt;br /&gt;
[[Category:Support]]&lt;br /&gt;
[[Category:Tech Reference]] &lt;br /&gt;
[[Category:Help]]&lt;br /&gt;
[[Category:Configuration]]&lt;br /&gt;
[[Category:Getting_Started]]&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
&amp;lt;cleanpage title=hide cats=hide /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Overview_of_How_Regions_Work</id>
		<title>Overview of How Regions Work</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Overview_of_How_Regions_Work"/>
				<updated>2009-09-18T19:16:48Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: New page: The following is based on a brief discussion between ter_afk and rknop on #opensim-dev.  It's archived here so that hopefully others can benefit from it.  == Scene: the Core of the Region ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following is based on a brief discussion between ter_afk and rknop on #opensim-dev.  It's archived here so that hopefully others can benefit from it.&lt;br /&gt;
&lt;br /&gt;
== Scene: the Core of the Region ==&lt;br /&gt;
&lt;br /&gt;
OpenSim.Region.Framework.Scenes.Scene is the &amp;quot;heart&amp;quot; of OpenSimulator's functionality.  The method Scene.Heartbeat() starts the heartbeat going; it does this by calling the Update() method.  That method is the &amp;quot;main loop&amp;quot; of the region:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        public override void Update()&lt;br /&gt;
        {&lt;br /&gt;
            int maintc = 0;&lt;br /&gt;
            while (!shuttingdown)&lt;br /&gt;
            {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That loop is run over and over again.  At the bottom of the loop is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                maintc = Environment.TickCount - maintc;&lt;br /&gt;
                maintc = (int)(m_timespan * 1000) - maintc;&lt;br /&gt;
&lt;br /&gt;
                if ((maintc &amp;lt; (m_timespan * 1000)) &amp;amp;&amp;amp; maintc &amp;gt; 0)&lt;br /&gt;
                    Thread.Sleep(maintc);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In other words, if everything else didn't take as long as one heartbeat is supposed to take, the thread goes to sleep until it's time to service the next heartbeat.  This heartbeat runs about 10 times a second.&lt;br /&gt;
&lt;br /&gt;
Other modules of all sorts can register heartbeat events that get called each pass through the main loop, and there are other events that modules can register for as well.  (Details forthcoming....)&lt;br /&gt;
&lt;br /&gt;
== Which regions run? ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;bin/Regions/Regions.ini&amp;lt;/tt&amp;gt; file determines which regions run.  Here's an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Test]&lt;br /&gt;
RegionUUID = 4b516a07-aa32-47e4-b4d9-52116255b4d2&lt;br /&gt;
Location = 1000,1000&lt;br /&gt;
InternalAddress = 127.0.0.1&lt;br /&gt;
InternalPort = 9000&lt;br /&gt;
AllowAlternatePorts = False&lt;br /&gt;
ExternalHostName = SYSTEMIP&lt;br /&gt;
MasterAvatarFirstName = Master&lt;br /&gt;
MasterAvatarLastName = Avatar&lt;br /&gt;
MasterAvatarSandboxPassword = master_avatar_password&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	<entry>
		<id>http://opensimulator.org/wiki/Developer_Documentation</id>
		<title>Developer Documentation</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/wiki/Developer_Documentation"/>
				<updated>2009-09-18T19:09:57Z</updated>
		
		<summary type="html">&lt;p&gt;Rknop: /* Regions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Quicklinks}}&lt;br /&gt;
&lt;br /&gt;
[[Technical Reference | Technical Reference]] -&amp;gt; [[Technical Reference/terms | Terms]] -&amp;gt; [[Developer_Documentation | Developer Documentation]]&lt;br /&gt;
&lt;br /&gt;
== Developer Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== General ====&lt;br /&gt;
* [[Development Team]] &amp;amp;mdash; OpenSim is brought to you by...&lt;br /&gt;
* [[OpenSim:Introduction_and_Definitions  | OpenSim: Introduction and Definitions]] &amp;amp;mdash; A work in progress describing the high level components of OpenSim&lt;br /&gt;
* [[Technical Reference | OpenSim: Technical Reference]] &amp;amp;mdash; A technical description of the simulator operation.&lt;br /&gt;
* [[Grid Architecture Diagram]]&lt;br /&gt;
* [[OpenSim: Screenshots]] &amp;amp;mdash; Various OpenSim screenshots.&lt;br /&gt;
* [http://docs.opensimulator.org/index.html The OpenSim API]&lt;br /&gt;
&lt;br /&gt;
==== Development ====&lt;br /&gt;
* [[Release Cycle]]&lt;br /&gt;
* [[On revisions, tags and branches]]&lt;br /&gt;
* [[Hacking OpenSim for fun and profit]] &amp;amp;mdash; A starters guide for programming OpenSim.&lt;br /&gt;
* [[Coding standards]] &amp;amp;mdash; Coding conventions for developers.&lt;br /&gt;
* [[Automated Testing]] &amp;amp;mdash; How to write tests for OpenSim.&lt;br /&gt;
* [[Debugging Unit Tests]] &amp;amp;mdash; How to debug the automated tests.&lt;br /&gt;
* [[Branches]] &amp;amp;mdash; An overview of the repository branches and what they are for.&lt;br /&gt;
* [[Monodevelop]] &amp;amp;mdash; How to use the [[monodevelop]] IDE for editing C# solutions.&lt;br /&gt;
* [[Creating New Solution]] &amp;amp;mdash; How to create new solution according to OpenSim conventions.&lt;br /&gt;
* [[Improving Performance]] &amp;amp;mdash; Efforts to increase OpenSim's performance.&lt;br /&gt;
&lt;br /&gt;
==== Services ====&lt;br /&gt;
&lt;br /&gt;
* [http://opensimulator.org/mantis Mantis Bug Tracking] &amp;amp;mdash; Mantis is the issue tracking tool of OpenSimulator.&lt;br /&gt;
* [http://www.opensimulator.org:8085/browse/OPENSIM-TRUNK Bamboo Continuous Integration] &amp;amp;mdash; Bamboo builds the source base continuously and runs unit tests.&lt;br /&gt;
* [http://forge.opensimulator.org/gf/ OpenSimulator GForge] &amp;amp;mdash; Project hosting for OpenSimulator related projects.&lt;br /&gt;
&lt;br /&gt;
==== Client Stacks ====&lt;br /&gt;
* [[Sim Throttles]] &amp;amp;mdash; Information on how OpenSim handles throttling of packets to the client.&lt;br /&gt;
&lt;br /&gt;
==== Database ====&lt;br /&gt;
* [[Database Documentation]] &amp;amp;mdash; A map of grid and region instances used in OpenSim&lt;br /&gt;
* [[MonoSqlite]] &amp;amp;mdash; How the database model currently works.&lt;br /&gt;
* [[LSL:PrimitiveParams]] &amp;amp;mdash; Notes on converting SL Edit GUI values and LSL PrimitiveParams to OpenSim PrimitiveBaseShape fields&lt;br /&gt;
* [[NHibernate Performance Testing]] &amp;amp;mdash; SQLite and MySQL performance tests with NHibernate.&lt;br /&gt;
&lt;br /&gt;
==== File formats ====&lt;br /&gt;
* [[Technical_Reference/OpenSim_Archive_Region_Format]] - Opensim ARchive (OAR) region archive file format.&lt;br /&gt;
&lt;br /&gt;
==== Grid ====&lt;br /&gt;
* [[Asset Server problems]] - list of known problems with the asset server&lt;br /&gt;
* [[Teleports]] - some diagrams about OGP and Hypergrid teleport sequences&lt;br /&gt;
* [[Agent Domain / Service]] - Details about the GridForge hosted Agent Domain/Service code&lt;br /&gt;
&lt;br /&gt;
==== Web Integration ====&lt;br /&gt;
* [[Webinterface]] &amp;amp;mdash; How to mashup with the web.&lt;br /&gt;
* [[RemoteAdmin]] &amp;amp;mdash; How to use the remote admin plug-in.&lt;br /&gt;
* [[RestConsole]] - Description how to use the REST remote console &lt;br /&gt;
* [[REST]] &amp;amp;mdash; Information about the REST interface to assets, inventory, etc.&lt;br /&gt;
* [[Known Web Interfaces within OpenSim]] &amp;amp;mdash; The set of CAPS, XMLRPC, or REST entry points in the project.&lt;br /&gt;
&lt;br /&gt;
==== Modules ====&lt;br /&gt;
* [[RegionModules]] &amp;amp;mdash; The various modules that are used in the RegionServer and how to write new ones.&lt;br /&gt;
* [[How to create a dynamic plugin]] - A tutorial for using PluginLoader&lt;br /&gt;
* [[Getting Started with Region Modules]] - This brief tutorial is intended to get people started with developing applications with/for opensim using region modules and the opensim API.&lt;br /&gt;
* [[Web Statistics Module]] - The web statistics module documentation and counter wish list.&lt;br /&gt;
&lt;br /&gt;
==== Permissions ====&lt;br /&gt;
* [[OpenSim:Permissions(Server)]]   &amp;amp;mdash; Permissions system as implemented on the region server.&lt;br /&gt;
* [[OpenSim: Permissions]] &amp;amp;mdash; Notes on how object permissions are handled on the client.&lt;br /&gt;
&lt;br /&gt;
==== Physics ====&lt;br /&gt;
* [[PhysicsEngines]]   &amp;amp;mdash; Options for physics engines in OpenSim.&lt;br /&gt;
&lt;br /&gt;
==== Protocols ====&lt;br /&gt;
* [[Metaverse Exchange Protocol]] &amp;amp;mdash; MXP is alternative protocol for secondlife protocol.&lt;br /&gt;
&lt;br /&gt;
==== Regions ====&lt;br /&gt;
* [[Overview of How Regions Work]] - notes from ter_afk to rknop in #opensim-dev, cleaned up a bit&lt;br /&gt;
* [[OpenSim: Permissions]] &amp;amp;mdash; Notes on object permissions &amp;amp; definition of the ObjectFlags variable.&lt;br /&gt;
* [[OpenSim Load Balancing and Region Splitting]] - Instructions for using load balancing and region splitting features.&lt;br /&gt;
&lt;br /&gt;
==== Threading ====&lt;br /&gt;
* [[OpenSim: Threading strategy]] &amp;amp;mdash; How threading is implemented and handled.&lt;br /&gt;
&lt;br /&gt;
==== Scripting ====&lt;br /&gt;
* [[Scripting_Documentation]] &amp;amp;mdash; How to use scripts and what limitations apply.&lt;br /&gt;
* [[LSL_Status/Functions|LSL Implemented]]   &amp;amp;mdash; A list of LSL-functions that are available in OpenSim.&lt;br /&gt;
* [[OSSL]] &amp;amp;mdash; Some information about the OpenSimulator Scripting Language, and how to implement an OSSL function&lt;br /&gt;
* [[OpenSim.Region.ScriptEngine]] &amp;amp;mdash; How the ScriptEngine looks internally.&lt;br /&gt;
&lt;br /&gt;
==== Search ====&lt;br /&gt;
* [[OpenSim.Region.DataSnapshot]] - Shiny new data gathering/search system&lt;br /&gt;
* [[ImageService]] - Shiny new region module for serving search-related images&lt;br /&gt;
&lt;br /&gt;
==== Testing ====&lt;br /&gt;
* [[Automated_Testing]] &amp;amp;mdash; Writing Automated tests for OpenSim.&lt;br /&gt;
* [[Debugging Unit Tests]] &amp;amp;mdash; Debugging unit tests.&lt;br /&gt;
* [[OpenSim: Debugging - profiler dumps]] &amp;amp;mdash; Dumps of OpenSim profiles to aid in tracking memory leaks.&lt;br /&gt;
* [[Prim_Linking_Testing]] &amp;amp;mdash; Test cases for in world link/unlinking of prims.&lt;br /&gt;
&lt;br /&gt;
==Proposals==&lt;br /&gt;
&lt;br /&gt;
* [[Opensim: 0.5 Release Target Discussion]]&lt;br /&gt;
* [[Opensim: 0.6 Release Target Discussion]]&lt;br /&gt;
* [[Opensim: Future Release Discussion]]&lt;br /&gt;
&lt;br /&gt;
* [[A better SimCrossing]] - A work in progress about implementing a smooth simcrossing&lt;br /&gt;
* [[OpenID]] - Proposal for using OpenID in OpenSim&lt;br /&gt;
* [[AssetServerProposal]] - Proposal for a distributed asset server&lt;br /&gt;
* [[Creating profiles not used for login]] - RFC for alternative ways of creating profiles that will never be used for login&lt;br /&gt;
* [[OpenSim_Services_and_Service_Connectors]] - new infrastructure for connecting region simulators to backend services&lt;br /&gt;
* [[OpenSim Profile Anchors]] - a mechanism for retaining creator information for offline item transfers&lt;br /&gt;
* [[Explicit Object Serialization]] - a proposal to explicitly serialize scene objects rather than using automatic .NET XML serialization&lt;br /&gt;
&lt;br /&gt;
==== Proposed projects ====&lt;br /&gt;
&lt;br /&gt;
* [[OpenWiredux: Taking the next step]]&lt;br /&gt;
* [[Using SNMP in OpenSim]]&lt;br /&gt;
&lt;br /&gt;
==Communication==&lt;br /&gt;
&lt;br /&gt;
A good first point of contact is the OpenSim IRC, on irc.freenode.net channels #opensim / #opensim-dev. The OpenSim developers hold [[office hours]] once a week in-world on Tuesdays at &amp;quot;Wright Plaza&amp;quot; on OSGrid. There is a &amp;quot;Test Hour&amp;quot; on Saturdays, also generally on &amp;quot;Wright Plaza&amp;quot;. Both these weekly events are held at 1900UTC. Check on the #opensim IRC channel on Freenode just before each of these events if there is any confusion.&lt;br /&gt;
&lt;br /&gt;
There is also a mailman email distribution list available at https://lists.berlios.de/mailman/listinfo/opensim-dev&lt;br /&gt;
&lt;br /&gt;
==Interest Groups==&lt;br /&gt;
* [[OpenSim Quality Focus Group]] - A proposed group for developers interested in improving the quality of OpenSim as we head towards beta status.&lt;br /&gt;
&lt;br /&gt;
==Git Access==&lt;br /&gt;
You can browse the source code for OpenSim [http://opensimulator.org/viewgit using a web browser] or via git.&lt;br /&gt;
* Anonymous Checkout - see [[Download]]&lt;br /&gt;
* Developer Checkout&lt;br /&gt;
 git clone ssh://USERNAME@opensimulator.org/var/git/opensim&lt;br /&gt;
&lt;br /&gt;
==Submitting Patches==&lt;br /&gt;
&lt;br /&gt;
Please review [[Submitting_code_to_OpenSim]]&lt;br /&gt;
&lt;br /&gt;
==Recent Git Commits==&lt;br /&gt;
&amp;lt;rss&amp;gt;http://opensimulator.org/viewgit?a=rss-log&amp;amp;p=opensim|max=5|title=none&amp;lt;/rss&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Main]]&lt;br /&gt;
[[Category:Support]]&lt;br /&gt;
[[Category:Tech Reference]] &lt;br /&gt;
[[Category:Help]]&lt;br /&gt;
[[Category:Configuration]]&lt;br /&gt;
[[Category:Getting_Started]]&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
&amp;lt;cleanpage title=hide cats=hide /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rknop</name></author>	</entry>

	</feed>