Umzugsservice von A nach B

Mit der Zeit häufen sich auch im virtuellen Dasein eine Menge Güter an. Die alte Erkenntnis aus der materiellen Welt – je größer die Wohnung, desto mehr Plunder – gilt auch, und erst recht, für die virtuelle Welt, denn das Inventar ist riesig.

Es lohnt sich, Ordnung in diesem Inventar zu halten. Nicht nur, während man sich in der virtuellen Welt aufhält („Wo waren noch einmal diese tollen Schuhe, die ich vor einem halben Jahr mal gekauft habe?“), sondern auch für den Fall, dass man mal umzieht.

Second Life ist diesbezüglich mal wieder etwas „kastriert“, denn nach den neuesten Spielregeln von Linden Lab dürfen nur solche Objekte exportiert werden, die man selbst erstellt hat. Fast könnte man meinen, die Lindens hätten sich das bei einem anderen Weltenschöpfer abgeguckt, denn bekanntermaßen nimmt man auch aus diesem ganz unvirtuellen Leben nichts mit.

Für OpenSim gelten diese Beschränkungen nicht. Einen Weg, Ländereien, Güter und Besitztümer von A nach B zu transportieren, stellt die Möglichkeit einer OAR-Datei dar. Wie das funktioniert, habe ich bereits an anderer Stelle geschildert.

Allerdings haben manche Viewer auch eingebaute Möglichkeiten, virtuelle Gegenstände zu exportieren und in einem anderen Grid wieder zu importieren. Der offizielle Linden-Viewer bietet diese Möglichkeit nicht, aber der Hippo Viewer beherrscht den Export von Objekten, ebenso der Imprudence-Viewer, der von OSGrid als Standardviewer empfohlen wird.

Über die Konsole gibt s zwar auch die (experiementelle) Möglichkeit, ein komplettes Inventar zu exportieren, beim Export über den Viewer jedoch mus das Objekt gerezzt sein. Anschließend muss das Objekt noch markiert, sein, ehe man mit dem Export beginnen kann. Die Position der jeweiligen Prims wird ebenso mitexportiert wie die Information, ob die Prims verlinkt sind. Gespeichert wird das Ganze in einer XML-Datei.

Ebenfalls mitexportiert werden die Texturen, die der Viewer jeweils in Dateien ablegt, die die bisherige UUID als Dateinamen tragen.

Beim Import hat man dann die Wahl, entweder nur das Objekt selbst oder die Texturen gleich mit zu importieren.

Nach meinem subjektiven Empfinden beherrscht der Imprudence Viewer den Im- und Export ein wenig besser als der Hippo Viewer. Zumindest erhielt ich beim Imprudence keine Fehlermeldung, während der Hippo meckerte, dass er die eine oder andere Textur nicht tranportieren konnte.

Nicht mit exportiert werden Skripte und Animationen, die in den Prims enthalten sind. Während Skripte einfach per Copy & Paste neu angelegt werden können (sofern man die notwendigen Rechte auf das Skript hat), muss man die Animation als Kopie auf der Festplatte haben und sie neu hochladen.

Wichtig zu wissen ist noch: Im Zielgrid wird der importierende Avatar auch als Creator eingetragen.

Informationen zu WordPress

Weil ich gerade etwas suchen musste um es letztlich zu finden: WordPress braucht die gd-Library um Thumbs (diese miniaturisierten Grafiken) zu erstellen, und bei Debian ist das das Package „php5-gd“, weil WordPress natürlich php und so … 😉

Und um im guten alten Brenner-Stil weiterzumachen: Aber wenn du jetzt denkst, das geht so ohne weiteres, dann Irrtum, weil:

[code lang=“dos“]dpkg: libgd2-noxpm: dependency problems, but removing anyway as you request[/code]

und da

[code lang=“dos“] webalizer depends on libgd2-noxpm (>= 2.0.36~rc1~dfsg) | libgd2-xpm (>= 2.0.36~rc1~dfsg); however:
Package libgd2-noxpm is to be removed.
Package libgd2-xpm is not installed.
(Reading database … 38287 files and directories currently installed.)
Removing libgd2-noxpm …
Selecting previously deselected package libgd2-xpm.
(Reading database … 38276 files and directories currently installed.)
Unpacking libgd2-xpm (from …/libgd2-xpm_2.0.36~rc1~dfsg-3+lenny1_amd64.deb) …
Selecting previously deselected package libt1-5.
Unpacking libt1-5 (from …/libt1-5_5.1.2-3_amd64.deb) …
Selecting previously deselected package php5-gd.
Unpacking php5-gd (from …/php5-gd_5.2.6.dfsg.1-1+lenny9_amd64.deb) …
Setting up libgd2-xpm (2.0.36~rc1~dfsg-3+lenny1) …
Setting up libt1-5 (5.1.2-3) …
Setting up php5-gd (5.2.6.dfsg.1-1+lenny9) …[/code]

könnten wir jetzt ein Problem mit WebAlyzer haben … ,) … nun, das sehen wir dann morgen nach dem nächsten Lauf. 🙂

Solution – was für ein treffender Name

„Solution“ nennt Microsoft bei ihren IDEs (Integrated Development Environment) – und davon gibt es schon bei den VisualStudio-Express-Varianten vier Stück  (Basic, C++, C# und das andere hab ich grad vergessen) – eine Sammlung von Projekten unter einem Dach. Es gibt also, anders als bei anderen Entwicklungsumgebungen noch etwas über dem „Projekt“, und bei den OpenSim-Entwicklungen wurde das hinreichend genutzt. Das Programm eignet sich sicherlich recht gut für Teamarbeiten. Eine gute Sache, dass M$ diese Express-Version kostenlos zur Verfügung stellt für private Nutzungen, so kann man reinschnuppern und erste Gehversuche damit machen. Tja, wäre es so leicht für iPhone Apps zu entwickeln … aber das ist eine andere Geschichte. 🙂 Solution – was für ein treffender Name weiterlesen

Viel Raum für eine Ausstellung?

Vor ein paar Tagen habe ich die Bilbliothek von unserem Standalone-Grid nach Metropolis geholt. An dem Gebäude liegt mir wirklich viel, weil ich einiges an Arbeit und Kreativität darauf verwendet habe.

Nun steht es also da. Heute habe ich mal eine Allee hin zum Haupteingang gezimmert – mit Straße und Bäumen. Doch das Innere des Gebäudes ist derzeit hässlich leer. Fragt sich also, wie es verwendet werden kann (denn als pure Kulisse fände ich es etwas schade).

Im Hinterkopf ist ja immer noch die Überlegung, eines Tages wirklich eine Bibliothek daraus zu machen. Das wird jedoch erst passieren, wenn wir mal eine vernünftige Art und Weise gefunden haben, Inhalte darzustellen.

Bis dahin bietet sich der Raum vielleicht an, eine Fotoausstellung auszurichten. Denn für solche Zwecke ist die Opensim-Umgebung wirklich sehr gut geeignet.

„Houston, wir haben einen linked Prim!“

Genau, das Problem ist gelöst; letztendlich lag es an einem kleinen Ausrufezeichen. Danke an Bert! „Wir sind der Meinung, das war: Spitze!“ 😀

Virtuelles (Zusammen-)Leben organisieren

Die Motivation, sich in eine 3D-Umgebung zu begeben, dürfte bei den meisten Menschen ähnlich sein, und vermutlich unterscheidet sie sich auch nicht von der Antriebskraft, die vor fünfhundert oder tausend Jahren Menschen bewegte, in neue Welten aufzubrechen: Neugier. Doch wie kann es gelingen, dass Menschen auch in einer virtuellen Welt bleiben, dass sie nicht die Lust daran nach einer gewissen Zeit verlieren oder gar aus Frust, Enttäuschung oder Ärger wieder ab- oder weiterziehen? Mit anderen Worten: Wie kann es gelingen, virtuelles Leben und Zusammenleben so zu organisieren, dass diejenigen, die daran teilhaben, den Spaß nicht verlieren?

Virtuelles (Zusammen-)Leben organisieren weiterlesen

Im Linden-Dschungel Teil 2

Immer noch geht es um die Linked Prims, aber möglicherweise fangen wir gerade erst an, wollen also nicht so lamentieren zu Beginn ;).

Um das Logging zum Einsatz zu bringen waren noch zwei Includes (using bei c#) notwendig und das Anlegen einer statischen Variable. Erstes Modul auf das ich mich stürze ist MySQLRegionData.cs in Region/Framework/Scenes. Kein Erfolg ist feststellbar dass das Loggen irgendein hilfreiches Protokoll bringt. Die else-Zweige bei der Prozedur StoreObject die beschritten werden wenn kein „persistent“ gegeben ist das zum Speichern führen soll werden entkommentiert und mit Leben gefüllt, aber nichts zu bemerken. Es kommen aber schon interessante Erkenntnisse darüber was da wann geschieht, der eine else-Zweig dient nämlich dazu im Modus „selected“ noch nicht zu speichern, klingt vernünftig. Auch Anpassungen im neuen MySQLLegacyRegionData.cs – das in der 0.6.6er noch gar nicht vorhanden war – bringen nichts.

Der nächste Bereich ist, dass ständig – und zwar im 20-Sekunden-Abstand – von diesem Modul versucht wird auf Speicherfähigkeit zu prüfen, ehrlich gesagt halte ich die Last die hier erzeugt wird für ziemlich schlecht. Man merkt das ja gar nicht da im else-Zweig keine Ausgabe erfolgt, mit den debugging-Infos kommt alle paar Sekunden – und das schon für nur 3 Prims „did not update persistance“. Der interessante Punkt ist der, dass nur gespeichert wird wenn „HasGroupChanged“ wahr ist. Ich suche eine Art „HasPositionChanged“ das aber nicht aufzutreiben ist.

In der 0.6.9er wird das in Vorgängerversionen verwendete Setzen von HasGroupChanged an etlichen Stellen auskommentiert. Da mir das verdächtig erscheint nehme ich es mal wieder rein, jedoch ohne dass dies Auswirkungen auf das Speichern von Links hätte.

Nach einigen Tests bekomme ich schließlich eine Erleuchtung: Wir suchen ja einen Trigger der ausgelöst wird noch bevor überhaupt in den Speicherbereich eingestiegen wird, denn selbst VOR dem Speichern müsste ein Wechsel vom Fokus beim Select ja schon das Erhaltenbleiben des Links signalisieren, was definitiv nicht geschieht. Bisher also die komplett falsche Baustelle – die aber einige nette Erkenntnisse gebracht hat die wir sicherlich irgendwann gebrauchen können 😉

Mit vollständig neuer Herangehensweise steige ich in den ClientStack ein, nach einiger Suche werde ich fündig: Es gibt einen LinkHandler neben etlichen anderen – nämlich für all das was im Client ausgelöst werden soll – in LLClientView.cs im Bereich Region/ClientStack/LindenUDP. Und Heureka: Dort ein Logging eingebaut bringt sofort nach dem versuchten Linken eine Protokoll-Meldung auf der Konsole: Ich habe soeben den Hebel an der richtigen Stelle angesetzt.

Ein Kongress-Zentrum

Kongresszentrum

Eine der freien Sims, die ich auf meinem lokalen Simulator mal importiert habe, enthält übrigens ein komplettes Kongress-Zentrum inklusive eines Vortragssaals mit (gefühlten) hundert Stühlen – wenn die mal alle besetzt sind, ist der Simulator wahrscheinlich so lahm, dass keine Kommunikation mehr möglich ist 😉 – und diversen anderen Einrichtungen. Wenn man es gerne großmächtig haben möchte, ist so etwas dann die ideale Startsim…

Die Sim stammt übrigens von OpenVCE.

Aus gegebenem Anlass: Ein Bewegungs-Script ohne Physics für OpenSim

[code lang=“c“]
integer alpha = 0;
vector basepos;
vector newpos;
integer timerset = 0;
float meterProSec = 3;
float offsetX = 0.0;
float offsetY = 0.2;
float offsetZ = 0.0;
integer i = 0;
integer timerSec = 1;
float grenzeYL = 100.0;
float grenzeYH = 110.0;
float grenzeXL = 100.0;
float grenzeXH = 110.0;
default
{
state_entry() {
llSay(0, „ready“);
llSleep(0.1);
basepos = llGetPos();
}

timer() {
vector pos = llGetPos();
float miniOffsetY = offsetY / 10;
float miniOffsetX = offsetX / 10;
for (i = 1; i <= 20; i++) { newpos = pos + ;
llSetPrimitiveParams([PRIM_POSITION, newpos]);
llSleep(0.1);
}
//llOwnerSay(“ am at : “ + (string)newpos);
//llOwnerSay(“ offsets : “ + (string)offsetX + „/“ + (string)offsetY);

// die randsteine
if ((newpos.x <= grenzeXL) && (newpos.y >= grenzeYH)) {
offsetX = meterProSec;
offsetY = 0;
llSetRot(llEuler2Rot(<0.0, 0.0, -PI_BY_TWO>) * llGetRot());
//llOwnerSay(„c1“);
} else if ((newpos.x >= grenzeXH) && (newpos.y >= grenzeYH)) {
offsetX = 0;
offsetY = -meterProSec;
llSetRot(llEuler2Rot(<0.0, 0.0, -PI_BY_TWO>) * llGetRot());
//llOwnerSay(„c2“);
} else if ((newpos.x >= grenzeXH) && (newpos.y <= grenzeYL)) { offsetX = -meterProSec; offsetY = 0; llSetRot(llEuler2Rot(<0.0, 0.0, -PI_BY_TWO>) * llGetRot());
//llOwnerSay(„c3“);
} else if ((newpos.x <= grenzeXL) && (newpos.y <= grenzeYL)) { offsetX = 0; offsetY = meterProSec; llSetRot(llEuler2Rot(<0.0, 0.0, -PI_BY_TWO>) * llGetRot());
//llOwnerSay(„c4“);
}

// die notfallbremsen
else if ((newpos.y > grenzeYH) && (offsetY != 0)) {
offsetY = 0;
offsetX = meterProSec;
llSetRot(llEuler2Rot(<0.0, 0.0, -PI_BY_TWO>) * llGetRot());
//llOwnerSay(„c5“);
} else if ((newpos.x > grenzeXH) && (offsetX != 0)) {
offsetX = 0;
offsetY = meterProSec;
llSetRot(llEuler2Rot(<0.0, 0.0, -PI_BY_TWO>) * llGetRot());
//llOwnerSay(„c6“);
} else if ((newpos.y < grenzeYL) && (offsetY != 0)) { offsetY = 0; offsetX = meterProSec; llSetRot(llEuler2Rot(<0.0, 0.0, -PI_BY_TWO>) * llGetRot());
//llOwnerSay(„c7“);
} else if ((newpos.x < grenzeXL) && (offsetX != 0)) { offsetX = 0; offsetY = meterProSec; llSetRot(llEuler2Rot(<0.0, 0.0, -PI_BY_TWO>) * llGetRot());
//llOwnerSay(„c8“);
}
}
touch_start(integer total_number) {
if (timerset) {
llOwnerSay(„stopping timer“);
timerset = 0;
llSetTimerEvent(0);
} else {
llOwnerSay(„starting timer“);
timerset = 1;
llSetTimerEvent(timerSec);
}
}
}
[/code]

des Programmierers Fundgrube: Wiederholungen

Es geht doch nichts darüber, wenn man gelegentlich Dinge findet die sich einfach kopieren lassen. Sei es von anderen (Programmierer klauen bekanntermassen wie die sprichwörtlichen Raben ^^) oder eben von einem selbst. Und es gab schon bei der mittlerweile schön laufenden 0.6.6 Probleme beim Speichern, die schon erwähnte GroupPosition lief gelegentlich auf einen kapitalen Fehler da sie nicht speicherbare Werte enthielt. Und damals – es ist witzigerweise fast genau ein Jahr her – ergänzte ich die Routine MySQLRegionData.cs um folgenden Schnipsel, der mir gute Dienste leistet immer noch:
[code lang=“csharp“]// bert@wolfsbone.de START 20091018
m_log.DebugFormat(„[DATA]: [BTRACE]: we will now inspect GroupPosition-Value Z“);
double tempGroupPositionZ = prim.GroupPosition.Z;
string tempString = tempGroupPositionZ.ToString(„0.00“);
string tempMessage = „[DATA]: [BTRACE]: it is: <“ + tempString + „>“;
m_log.DebugFormat(tempMessage);
if (tempString == „NaN“) {
m_log.DebugFormat(„[DATA]: [BTRACE]: now setting to 30, should be okay.“);
tempGroupPositionZ = 30;
}
// bert@wolfsbone.de END 20091018

cmd.Parameters.AddWithValue(„GroupPositionX“, (double)prim.GroupPosition.X);
cmd.Parameters.AddWithValue(„GroupPositionY“, (double)prim.GroupPosition.Y);
cmd.Parameters.AddWithValue(„GroupPositionZ“, (double)tempGroupPositionZ);[/code]

Etwas Ähnliches wollen wir dann doch mal wieder einbauen in die 0.6.9er, zunächst nur mit Meldecharakter um zu sehen was wann geschieht.