mirror of
https://github.com/RaindropViewer/RaindropViewer.git
synced 2026-07-27 22:11:39 +00:00
WIP of porting radegast viewer source code
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DebugTextVM : MonoBehaviour
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f003e7629ecbbdb4c9867c281c3c59c9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
//attached to panel UI. simply toggles UI panels.
|
||||
public class DebugToggleManager : MonoBehaviour
|
||||
{
|
||||
public Stack<GameObject> panelStack;
|
||||
|
||||
public GameObject loginPanel;
|
||||
|
||||
public GameObject gamePanel;
|
||||
|
||||
public GameObject defaultOnPanel;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
panelStack = new Stack<GameObject>();
|
||||
|
||||
defaultOnPanel = loginPanel;
|
||||
addPaneltoView(defaultOnPanel);
|
||||
removeTopPanelFromView();
|
||||
|
||||
gamePanel.SetActive(false);
|
||||
}
|
||||
|
||||
public void togglePanel(GameObject panel)
|
||||
{
|
||||
if (panel.activeInHierarchy == false)
|
||||
{
|
||||
addPaneltoView(panel);
|
||||
} else
|
||||
{
|
||||
removeTopPanelFromView();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void removeTopPanelFromView()
|
||||
{
|
||||
GameObject toppanel;
|
||||
if (panelStack.Count != 0)
|
||||
{
|
||||
toppanel = panelStack.Peek();
|
||||
panelStack.Pop();
|
||||
toppanel.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void addPaneltoView(GameObject defaultOnPanel)
|
||||
{
|
||||
panelStack.Push(defaultOnPanel);
|
||||
|
||||
|
||||
|
||||
defaultOnPanel.SetActive(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9047a9f086d8beb429cb9bad0fe6fbd7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5517ceddb63c378498db7ef3905c90f3
|
||||
guid: 538b2f91dbf71f54eb8346fd20194b00
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,242 @@
|
||||
// ConcurrentQueue.cs
|
||||
//
|
||||
// Copyright (c) 2008 Jérémie "Garuma" Laval
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
//
|
||||
|
||||
// Note this is slightly modified from the original from Mono for compatibility with .Net 3.5
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace System.Threading.Collections
|
||||
{
|
||||
public class ConcurrentQueue<T> : IEnumerable<T>, ICollection, ISerializable, IDeserializationCallback
|
||||
{
|
||||
class Node
|
||||
{
|
||||
public T Value;
|
||||
public Node Next;
|
||||
}
|
||||
|
||||
Node _head = new Node();
|
||||
Node _tail;
|
||||
int _count;
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
public ConcurrentQueue()
|
||||
{
|
||||
_tail = _head;
|
||||
}
|
||||
|
||||
public ConcurrentQueue(IEnumerable<T> enumerable)
|
||||
: this()
|
||||
{
|
||||
foreach (T item in enumerable)
|
||||
Enqueue(item);
|
||||
}
|
||||
|
||||
public void Enqueue(T item)
|
||||
{
|
||||
var node = new Node { Value = item };
|
||||
|
||||
Node oldTail = null;
|
||||
|
||||
bool update = false;
|
||||
while (!update)
|
||||
{
|
||||
oldTail = _tail;
|
||||
var oldNext = oldTail.Next;
|
||||
|
||||
// Did tail was already updated ?
|
||||
if (_tail == oldTail)
|
||||
{
|
||||
if (oldNext == null)
|
||||
{
|
||||
// The place is for us
|
||||
update = Interlocked.CompareExchange(ref _tail.Next, node, null) == null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// another Thread already used the place so give him a hand by putting tail where it should be
|
||||
Interlocked.CompareExchange(ref _tail, oldNext, oldTail);
|
||||
}
|
||||
}
|
||||
}
|
||||
// At this point we added correctly our node, now we have to update tail. If it fails then it will be done by another thread
|
||||
Interlocked.CompareExchange(ref _tail, node, oldTail);
|
||||
|
||||
Interlocked.Increment(ref _count);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool TryDequeue(out T value)
|
||||
{
|
||||
value = default(T);
|
||||
bool advanced = false;
|
||||
while (!advanced)
|
||||
{
|
||||
Node oldHead = _head;
|
||||
Node oldTail = _tail;
|
||||
Node oldNext = oldHead.Next;
|
||||
|
||||
if (oldHead == _head)
|
||||
{
|
||||
// Empty case ?
|
||||
if (oldHead == oldTail)
|
||||
{
|
||||
// This should be false then
|
||||
if (oldNext != null)
|
||||
{
|
||||
// If not then the linked list is mal formed, update tail
|
||||
Interlocked.CompareExchange(ref _tail, oldNext, oldTail);
|
||||
}
|
||||
value = default(T);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = oldNext.Value;
|
||||
advanced = Interlocked.CompareExchange(ref _head, oldNext, oldHead) == oldHead;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Interlocked.Decrement(ref _count);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool TryPeek(out T value)
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
value = default(T);
|
||||
return false;
|
||||
}
|
||||
|
||||
Node first = _head.Next;
|
||||
value = first.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_count = 0;
|
||||
_tail = _head = new Node();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return InternalGetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator()
|
||||
{
|
||||
return InternalGetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return InternalGetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator<T> InternalGetEnumerator()
|
||||
{
|
||||
Node myHead = _head;
|
||||
while ((myHead = myHead.Next) != null)
|
||||
{
|
||||
yield return myHead.Value;
|
||||
}
|
||||
}
|
||||
|
||||
void ICollection.CopyTo(Array array, int index)
|
||||
{
|
||||
T[] dest = array as T[];
|
||||
if (dest == null)
|
||||
return;
|
||||
CopyTo(dest, index);
|
||||
}
|
||||
|
||||
public void CopyTo(T[] dest, int index)
|
||||
{
|
||||
IEnumerator<T> e = InternalGetEnumerator();
|
||||
int i = index;
|
||||
while (e.MoveNext())
|
||||
{
|
||||
dest[i++] = e.Current;
|
||||
}
|
||||
}
|
||||
|
||||
public T[] ToArray()
|
||||
{
|
||||
T[] dest = new T[_count];
|
||||
CopyTo(dest, 0);
|
||||
return dest;
|
||||
}
|
||||
|
||||
public void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
bool ICollection.IsSynchronized
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public void OnDeserialization(object sender)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
readonly object _syncRoot = new object();
|
||||
object ICollection.SyncRoot
|
||||
{
|
||||
get { return _syncRoot; }
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
return _count == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18a25d882e7671d47becffdc6de1f734
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "DisruptorASMDEF",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1364d97af688c264f94c622d729b2059
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,275 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace DisruptorUnity3d
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of the Disruptor pattern
|
||||
/// </summary>
|
||||
/// <typeparam name="T">the type of item to be stored</typeparam>
|
||||
public class RingBuffer<T>
|
||||
{
|
||||
private readonly T[] _entries;
|
||||
private readonly int _modMask;
|
||||
private Volatile.PaddedLong _consumerCursor = new Volatile.PaddedLong();
|
||||
private Volatile.PaddedLong _producerCursor = new Volatile.PaddedLong();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new RingBuffer with the given capacity
|
||||
/// </summary>
|
||||
/// <param name="capacity">The capacity of the buffer</param>
|
||||
/// <remarks>Only a single thread may attempt to consume at any one time</remarks>
|
||||
public RingBuffer(int capacity)
|
||||
{
|
||||
capacity = NextPowerOfTwo(capacity);
|
||||
_modMask = capacity - 1;
|
||||
_entries = new T[capacity];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of items that can be stored
|
||||
/// </summary>
|
||||
public int Capacity
|
||||
{
|
||||
get { return _entries.Length; }
|
||||
}
|
||||
|
||||
public T this[long index]
|
||||
{
|
||||
get { unchecked { return _entries[index & _modMask]; } }
|
||||
set { unchecked { _entries[index & _modMask] = value; } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an item from the buffer.
|
||||
/// </summary>
|
||||
/// <returns>The next available item</returns>
|
||||
public T Dequeue()
|
||||
{
|
||||
var next = _consumerCursor.ReadAcquireFence() + 1;
|
||||
while (_producerCursor.ReadAcquireFence() < next) // makes sure we read the data from _entries after we have read the producer cursor
|
||||
{
|
||||
Thread.SpinWait(1);
|
||||
}
|
||||
var result = this[next];
|
||||
_consumerCursor.WriteReleaseFence(next); // makes sure we read the data from _entries before we update the consumer cursor
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to remove an items from the queue
|
||||
/// </summary>
|
||||
/// <param name="obj">the items</param>
|
||||
/// <returns>True if successful</returns>
|
||||
public bool TryDequeue(out T obj)
|
||||
{
|
||||
var next = _consumerCursor.ReadAcquireFence() + 1;
|
||||
|
||||
if (_producerCursor.ReadAcquireFence() < next)
|
||||
{
|
||||
obj = default(T);
|
||||
return false;
|
||||
}
|
||||
obj = Dequeue();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an item to the buffer
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public void Enqueue(T item)
|
||||
{
|
||||
var next = _producerCursor.ReadAcquireFence() + 1;
|
||||
|
||||
long wrapPoint = next - _entries.Length;
|
||||
long min = _consumerCursor.ReadAcquireFence();
|
||||
|
||||
while (wrapPoint > min)
|
||||
{
|
||||
min = _consumerCursor.ReadAcquireFence();
|
||||
Thread.SpinWait(1);
|
||||
}
|
||||
|
||||
this[next] = item;
|
||||
_producerCursor.WriteReleaseFence(next); // makes sure we write the data in _entries before we update the producer cursor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of items in the buffer
|
||||
/// </summary>
|
||||
/// <remarks>for indicative purposes only, may contain stale data</remarks>
|
||||
public int Count { get { return (int)(_producerCursor.ReadFullFence() - _consumerCursor.ReadFullFence()); } }
|
||||
|
||||
private static int NextPowerOfTwo(int x)
|
||||
{
|
||||
var result = 2;
|
||||
while (result < x)
|
||||
{
|
||||
result <<= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public static class Volatile
|
||||
{
|
||||
private const int CacheLineSize = 64;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = CacheLineSize * 2)]
|
||||
public struct PaddedLong
|
||||
{
|
||||
[FieldOffset(CacheLineSize)]
|
||||
private long _value;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="PaddedLong"/> with the given initial value.
|
||||
/// </summary>
|
||||
/// <param name="value">Initial value</param>
|
||||
public PaddedLong(long value)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read the value without applying any fence
|
||||
/// </summary>
|
||||
/// <returns>The current value</returns>
|
||||
public long ReadUnfenced()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read the value applying acquire fence semantic
|
||||
/// </summary>
|
||||
/// <returns>The current value</returns>
|
||||
public long ReadAcquireFence()
|
||||
{
|
||||
var value = _value;
|
||||
Thread.MemoryBarrier();
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read the value applying full fence semantic
|
||||
/// </summary>
|
||||
/// <returns>The current value</returns>
|
||||
public long ReadFullFence()
|
||||
{
|
||||
Thread.MemoryBarrier();
|
||||
return _value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read the value applying a compiler only fence, no CPU fence is applied
|
||||
/// </summary>
|
||||
/// <returns>The current value</returns>
|
||||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
||||
public long ReadCompilerOnlyFence()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the value applying release fence semantic
|
||||
/// </summary>
|
||||
/// <param name="newValue">The new value</param>
|
||||
public void WriteReleaseFence(long newValue)
|
||||
{
|
||||
Thread.MemoryBarrier();
|
||||
_value = newValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the value applying full fence semantic
|
||||
/// </summary>
|
||||
/// <param name="newValue">The new value</param>
|
||||
public void WriteFullFence(long newValue)
|
||||
{
|
||||
Thread.MemoryBarrier();
|
||||
_value = newValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the value applying a compiler fence only, no CPU fence is applied
|
||||
/// </summary>
|
||||
/// <param name="newValue">The new value</param>
|
||||
[MethodImpl(MethodImplOptions.NoOptimization)]
|
||||
public void WriteCompilerOnlyFence(long newValue)
|
||||
{
|
||||
_value = newValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write without applying any fence
|
||||
/// </summary>
|
||||
/// <param name="newValue">The new value</param>
|
||||
public void WriteUnfenced(long newValue)
|
||||
{
|
||||
_value = newValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Atomically set the value to the given updated value if the current value equals the comparand
|
||||
/// </summary>
|
||||
/// <param name="newValue">The new value</param>
|
||||
/// <param name="comparand">The comparand (expected value)</param>
|
||||
/// <returns></returns>
|
||||
public bool AtomicCompareExchange(long newValue, long comparand)
|
||||
{
|
||||
return Interlocked.CompareExchange(ref _value, newValue, comparand) == comparand;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Atomically set the value to the given updated value
|
||||
/// </summary>
|
||||
/// <param name="newValue">The new value</param>
|
||||
/// <returns>The original value</returns>
|
||||
public long AtomicExchange(long newValue)
|
||||
{
|
||||
return Interlocked.Exchange(ref _value, newValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Atomically add the given value to the current value and return the sum
|
||||
/// </summary>
|
||||
/// <param name="delta">The value to be added</param>
|
||||
/// <returns>The sum of the current value and the given value</returns>
|
||||
public long AtomicAddAndGet(long delta)
|
||||
{
|
||||
return Interlocked.Add(ref _value, delta);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Atomically increment the current value and return the new value
|
||||
/// </summary>
|
||||
/// <returns>The incremented value.</returns>
|
||||
public long AtomicIncrementAndGet()
|
||||
{
|
||||
return Interlocked.Increment(ref _value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Atomically increment the current value and return the new value
|
||||
/// </summary>
|
||||
/// <returns>The decremented value.</returns>
|
||||
public long AtomicDecrementAndGet()
|
||||
{
|
||||
return Interlocked.Decrement(ref _value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the string representation of the current value.
|
||||
/// </summary>
|
||||
/// <returns>the string representation of the current value.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
var value = ReadFullFence();
|
||||
return value.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ed5999a9ac5a0244b4e15b4e2a5c7ee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using UnityEngine;
|
||||
using Debug = UnityEngine.Debug;
|
||||
using Random = System.Random;
|
||||
|
||||
namespace DisruptorUnity3d
|
||||
{
|
||||
public class Test : MonoBehaviour
|
||||
{
|
||||
static readonly Random Rng = new Random();
|
||||
static readonly RingBuffer<int> Queue = new RingBuffer<int>(1000);
|
||||
//static readonly ConcurrentQueue<int> Queue = new ConcurrentQueue<int>();
|
||||
|
||||
static readonly Stopwatch sw = new Stopwatch();
|
||||
private const long Count = 5000000;//100000000;
|
||||
private long _queued = 0;
|
||||
private const long BatchSize = 20000;
|
||||
private Thread _consumerThread;
|
||||
private bool _printed = false;
|
||||
|
||||
private int numberToEnqueue;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Debug.Log("Started Test");
|
||||
_consumerThread = new Thread(() =>
|
||||
{
|
||||
Debug.Log("Started consumer");
|
||||
int expectedNumber = 0;
|
||||
int previousNumber = 0;
|
||||
for (long i = 0; i < Count; )
|
||||
{
|
||||
int val;
|
||||
var dequeued = Queue.TryDequeue(out val);
|
||||
if (dequeued)
|
||||
{
|
||||
if (expectedNumber != val)
|
||||
Debug.Log("wrong value " + val + " ,correct: " + i + " ,previous: " + previousNumber);
|
||||
previousNumber = val;
|
||||
expectedNumber++;
|
||||
++i;
|
||||
}
|
||||
|
||||
}
|
||||
Debug.Log(string.Format("Consumer done {0}", sw.Elapsed));
|
||||
});
|
||||
_consumerThread.Start();
|
||||
sw.Start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Update is called once per frame
|
||||
public void Update()
|
||||
{
|
||||
if (_queued >= Count && !_printed)
|
||||
{
|
||||
sw.Stop();
|
||||
Debug.Log(string.Format("Producer done {0} {1}", sw.Elapsed, _queued));
|
||||
_printed = true;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for (long i = 0; i < BatchSize && _queued < Count; ++i)
|
||||
{
|
||||
Queue.Enqueue(numberToEnqueue++);
|
||||
++_queued;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35efa1e25d8cb8243afec9feafa02080
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -113,14 +113,14 @@ namespace OpenMetaverse.Http
|
||||
if (postData == null)
|
||||
{
|
||||
// GET
|
||||
//Logger.Log.Debug("[CapsClient] GET " + _Address);
|
||||
Logger.DebugLog("[CapsClient] GET " + _Address);
|
||||
_Request = CapsBase.DownloadStringAsync(_Address, _ClientCert, millisecondsTimeout, DownloadProgressHandler,
|
||||
RequestCompletedHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
// POST
|
||||
//Logger.Log.Debug("[CapsClient] POST (" + postData.Length + " bytes) " + _Address);
|
||||
Logger.DebugLog("[CapsClient] POST (" + postData.Length + " bytes) " + _Address);
|
||||
_Request = CapsBase.UploadDataAsync(_Address, _ClientCert, contentType, postData, millisecondsTimeout, null,
|
||||
DownloadProgressHandler, RequestCompletedHandler);
|
||||
}
|
||||
@@ -171,8 +171,11 @@ namespace OpenMetaverse.Http
|
||||
|
||||
if (responseData != null)
|
||||
{
|
||||
Logger.DebugLog("RequestCompletedHandler" + ":" +" responseData is not null.");
|
||||
try { result = OSDParser.Deserialize(responseData); }
|
||||
catch (Exception ex) { error = ex; }
|
||||
catch (Exception ex) {
|
||||
Logger.Log("RequestCompletedHandler" + ":" + " responseData is not null but ran an exception!.",Helpers.LogLevel.Error);
|
||||
error = ex; }
|
||||
}
|
||||
|
||||
FireCompleteCallback(result, error);
|
||||
@@ -185,11 +188,11 @@ namespace OpenMetaverse.Http
|
||||
{
|
||||
try
|
||||
{
|
||||
callback(this, result, error);
|
||||
callback(this, result, error); //exception is "notimplementedexception"
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.DebugLog($"CapsBase.GetResponse() {_CapName} : {ex.Message}");
|
||||
Logger.DebugLog($"CapsBase.GetResponse() {_CapName} : {ex.Message} : {ex.ToString()}"); //here the log is coming from!
|
||||
Logger.Log(ex.Message, Helpers.LogLevel.Error, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,7 +330,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
Logger.Log("No Message handler exists for event " + eventName + ". Unable to decode. Will try Generic Handler next",
|
||||
Helpers.LogLevel.Warning);
|
||||
Logger.Log("Please report this information at https://radegast.life/bugs/issue-entry/: \n" + body,
|
||||
Logger.Log("Please report this information at https://eerbsitehere.com: \n" + body,
|
||||
Helpers.LogLevel.Debug);
|
||||
|
||||
// try generic decoder next which takes a caps event and tries to match it to an existing packet
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"name": "LibreMetaverseAssembly",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
""
|
||||
],
|
||||
"references": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
|
||||
@@ -1619,6 +1619,8 @@ namespace OpenMetaverse
|
||||
LoginErrorKey = "no connection";
|
||||
UpdateLoginStatus(LoginStatus.Failed, error.Message);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,688 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace Raindrop
|
||||
{
|
||||
public class CurrentOutfitFolder : IDisposable
|
||||
{
|
||||
#region Fields
|
||||
GridClient Client;
|
||||
RaindropInstance Instance;
|
||||
bool InitiCOF = false;
|
||||
bool AppearanceSent = false;
|
||||
bool COFReady = false;
|
||||
bool InitialUpdateDone = false;
|
||||
public Dictionary<UUID, InventoryItem> Content = new Dictionary<UUID, InventoryItem>();
|
||||
public InventoryFolder COF;
|
||||
|
||||
#endregion Fields
|
||||
|
||||
#region Construction and disposal
|
||||
public CurrentOutfitFolder(RaindropInstance instance)
|
||||
{
|
||||
this.Instance = instance;
|
||||
this.Client = instance.Client;
|
||||
Instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
|
||||
RegisterClientEvents(Client);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
UnregisterClientEvents(Client);
|
||||
Instance.ClientChanged -= new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
|
||||
}
|
||||
#endregion Construction and disposal
|
||||
|
||||
#region Event handling
|
||||
void instance_ClientChanged(object sender, ClientChangedEventArgs e)
|
||||
{
|
||||
UnregisterClientEvents(Client);
|
||||
Client = e.Client;
|
||||
RegisterClientEvents(Client);
|
||||
}
|
||||
|
||||
void RegisterClientEvents(GridClient client)
|
||||
{
|
||||
client.Network.EventQueueRunning += new EventHandler<EventQueueRunningEventArgs>(Network_EventQueueRunning);
|
||||
client.Inventory.FolderUpdated += new EventHandler<FolderUpdatedEventArgs>(Inventory_FolderUpdated);
|
||||
client.Inventory.ItemReceived += new EventHandler<ItemReceivedEventArgs>(Inventory_ItemReceived);
|
||||
client.Appearance.AppearanceSet += new EventHandler<AppearanceSetEventArgs>(Appearance_AppearanceSet);
|
||||
client.Objects.KillObject += new EventHandler<KillObjectEventArgs>(Objects_KillObject);
|
||||
}
|
||||
|
||||
void UnregisterClientEvents(GridClient client)
|
||||
{
|
||||
client.Network.EventQueueRunning -= new EventHandler<EventQueueRunningEventArgs>(Network_EventQueueRunning);
|
||||
client.Inventory.FolderUpdated -= new EventHandler<FolderUpdatedEventArgs>(Inventory_FolderUpdated);
|
||||
client.Inventory.ItemReceived -= new EventHandler<ItemReceivedEventArgs>(Inventory_ItemReceived);
|
||||
client.Appearance.AppearanceSet -= new EventHandler<AppearanceSetEventArgs>(Appearance_AppearanceSet);
|
||||
client.Objects.KillObject -= new EventHandler<KillObjectEventArgs>(Objects_KillObject);
|
||||
lock (Content) Content.Clear();
|
||||
InitiCOF = false;
|
||||
AppearanceSent = false;
|
||||
COFReady = false;
|
||||
InitialUpdateDone = false;
|
||||
}
|
||||
|
||||
void Appearance_AppearanceSet(object sender, AppearanceSetEventArgs e)
|
||||
{
|
||||
AppearanceSent = true;
|
||||
if (COFReady)
|
||||
{
|
||||
InitialUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory_ItemReceived(object sender, ItemReceivedEventArgs e)
|
||||
{
|
||||
bool partOfCOF = false;
|
||||
var links = ContentLinks();
|
||||
foreach (var cofItem in links)
|
||||
{
|
||||
if (cofItem.AssetUUID == e.Item.UUID)
|
||||
{
|
||||
partOfCOF = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (partOfCOF)
|
||||
{
|
||||
lock (Content)
|
||||
{
|
||||
Content[e.Item.UUID] = e.Item;
|
||||
}
|
||||
}
|
||||
|
||||
if (Content.Count == links.Count)
|
||||
{
|
||||
COFReady = true;
|
||||
if (AppearanceSent)
|
||||
{
|
||||
InitialUpdate();
|
||||
}
|
||||
lock (Content)
|
||||
{
|
||||
foreach (InventoryItem link in Content.Values)
|
||||
{
|
||||
if (link.InventoryType == InventoryType.Wearable)
|
||||
{
|
||||
InventoryWearable w = (InventoryWearable)link;
|
||||
InventoryItem lk = links.Find(l => l.AssetUUID == w.UUID);
|
||||
// Logger.DebugLog(string.Format("\nName: {0}\nDescription: {1}\nType: {2} - {3}", w.Name, lk == null ? "" : lk.Description, w.Flags.ToString(), w.WearableType.ToString())); ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object FolderSync = new object();
|
||||
|
||||
void Inventory_FolderUpdated(object sender, FolderUpdatedEventArgs e)
|
||||
{
|
||||
if (COF == null) return;
|
||||
|
||||
if (e.FolderID == COF.UUID && e.Success)
|
||||
{
|
||||
COF = (InventoryFolder)Client.Inventory.Store[COF.UUID];
|
||||
lock (FolderSync)
|
||||
{
|
||||
lock (Content) Content.Clear();
|
||||
|
||||
|
||||
List<UUID> items = new List<UUID>();
|
||||
List<UUID> owners = new List<UUID>();
|
||||
|
||||
foreach (var link in ContentLinks())
|
||||
{
|
||||
//if (Client.Inventory.Store.Contains(link.AssetUUID))
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
items.Add(link.AssetUUID);
|
||||
owners.Add(Client.Self.AgentID);
|
||||
}
|
||||
|
||||
if (items.Count > 0)
|
||||
{
|
||||
Client.Inventory.RequestFetchInventory(items, owners);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Objects_KillObject(object sender, KillObjectEventArgs e)
|
||||
{
|
||||
if (Client.Network.CurrentSim != e.Simulator) return;
|
||||
|
||||
Primitive prim = null;
|
||||
if (Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(e.ObjectLocalID, out prim))
|
||||
{
|
||||
UUID invItem = GetAttachmentItem(prim);
|
||||
if (invItem != UUID.Zero)
|
||||
{
|
||||
RemoveLink(invItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Network_EventQueueRunning(object sender, EventQueueRunningEventArgs e)
|
||||
{
|
||||
if (e.Simulator == Client.Network.CurrentSim && !InitiCOF)
|
||||
{
|
||||
InitiCOF = true;
|
||||
InitCOF();
|
||||
}
|
||||
}
|
||||
#endregion Event handling
|
||||
|
||||
#region Private methods
|
||||
void RequestDescendants(UUID folderID)
|
||||
{
|
||||
Client.Inventory.RequestFolderContents(folderID, Client.Self.AgentID, true, true, InventorySortOrder.ByDate);
|
||||
}
|
||||
|
||||
void InitCOF()
|
||||
{
|
||||
List<InventoryBase> rootContent = Client.Inventory.Store.GetContents(Client.Inventory.Store.RootFolder.UUID);
|
||||
foreach (InventoryBase baseItem in rootContent)
|
||||
{
|
||||
if (baseItem is InventoryFolder && ((InventoryFolder)baseItem).PreferredType == FolderType.CurrentOutfit)
|
||||
{
|
||||
COF = (InventoryFolder)baseItem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (COF == null)
|
||||
{
|
||||
CreateCOF();
|
||||
}
|
||||
else
|
||||
{
|
||||
RequestDescendants(COF.UUID);
|
||||
}
|
||||
}
|
||||
|
||||
void CreateCOF()
|
||||
{
|
||||
UUID cofID = Client.Inventory.CreateFolder(Client.Inventory.Store.RootFolder.UUID, "Current Outfit", FolderType.CurrentOutfit);
|
||||
if (Client.Inventory.Store.Items.ContainsKey(cofID) && Client.Inventory.Store.Items[cofID].Data is InventoryFolder)
|
||||
{
|
||||
COF = (InventoryFolder)Client.Inventory.Store.Items[cofID].Data;
|
||||
COFReady = true;
|
||||
if (AppearanceSent)
|
||||
{
|
||||
InitialUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitialUpdate()
|
||||
{
|
||||
if (InitialUpdateDone) return;
|
||||
InitialUpdateDone = true;
|
||||
lock (Content)
|
||||
{
|
||||
List<Primitive> myAtt = Client.Network.CurrentSim.ObjectsPrimitives.FindAll((Primitive p) => p.ParentID == Client.Self.LocalID);
|
||||
|
||||
foreach (InventoryItem item in Content.Values)
|
||||
{
|
||||
if (item is InventoryObject || item is InventoryAttachment)
|
||||
{
|
||||
if (!IsAttached(myAtt, item))
|
||||
{
|
||||
Client.Appearance.Attach(item, AttachmentPoint.Default, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion Private methods
|
||||
|
||||
#region Public methods
|
||||
/// <summary>
|
||||
/// Get COF contents
|
||||
/// </summary>
|
||||
/// <returns>List if InventoryItems that can be part of appearance (attachments, wearables)</returns>
|
||||
public List<InventoryItem> ContentLinks()
|
||||
{
|
||||
List<InventoryItem> ret = new List<InventoryItem>();
|
||||
if (COF == null) return ret;
|
||||
|
||||
Client.Inventory.Store.GetContents(COF)
|
||||
.FindAll(b => CanBeWorn(b) && ((InventoryItem)b).AssetType == AssetType.Link)
|
||||
.ForEach(item => ret.Add((InventoryItem)item));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get inventory ID of a prim
|
||||
/// </summary>
|
||||
/// <param name="prim">Prim to check</param>
|
||||
/// <returns>Inventory ID of the object. UUID.Zero if not found</returns>
|
||||
public static UUID GetAttachmentItem(Primitive prim)
|
||||
{
|
||||
if (prim.NameValues == null) return UUID.Zero;
|
||||
|
||||
for (int i = 0; i < prim.NameValues.Length; i++)
|
||||
{
|
||||
if (prim.NameValues[i].Name == "AttachItemID")
|
||||
{
|
||||
return (UUID)prim.NameValues[i].Value.ToString();
|
||||
}
|
||||
}
|
||||
return UUID.Zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is an inventory item currently attached
|
||||
/// </summary>
|
||||
/// <param name="attachments">List of root prims that are attached to our avatar</param>
|
||||
/// <param name="item">Inventory item to check</param>
|
||||
/// <returns>True if the inventory item is attached to avatar</returns>
|
||||
public static bool IsAttached(List<Primitive> attachments, InventoryItem item)
|
||||
{
|
||||
foreach (Primitive prim in attachments)
|
||||
{
|
||||
if (GetAttachmentItem(prim) == item.UUID)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if inventory item of Wearable type is worn
|
||||
/// </summary>
|
||||
/// <param name="currentlyWorn">Current outfit</param>
|
||||
/// <param name="item">Item to check</param>
|
||||
/// <returns>True if the item is worn</returns>
|
||||
public static bool IsWorn(Dictionary<WearableType, AppearanceManager.WearableData> currentlyWorn, InventoryItem item)
|
||||
{
|
||||
foreach (var n in currentlyWorn.Values)
|
||||
{
|
||||
if (n.ItemID == item.UUID)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can this inventory type be worn
|
||||
/// </summary>
|
||||
/// <param name="item">Item to check</param>
|
||||
/// <returns>True if the inventory item can be worn</returns>
|
||||
public static bool CanBeWorn(InventoryBase item)
|
||||
{
|
||||
return item is InventoryWearable || item is InventoryAttachment || item is InventoryObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attach an inventory item
|
||||
/// </summary>
|
||||
/// <param name="item">Item to be attached</param>
|
||||
/// <param name="point">Attachment point</param>
|
||||
/// <param name="replace">Replace existing attachment at that point first?</param>
|
||||
public void Attach(InventoryItem item, AttachmentPoint point, bool replace)
|
||||
{
|
||||
Client.Appearance.Attach(item, point, replace);
|
||||
AddLink(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new COF link
|
||||
/// </summary>
|
||||
/// <param name="item">Original item to be linked from COF</param>
|
||||
public void AddLink(InventoryItem item)
|
||||
{
|
||||
if (item.InventoryType == InventoryType.Wearable && !IsBodyPart(item))
|
||||
{
|
||||
InventoryWearable w = (InventoryWearable)item;
|
||||
int layer = 0;
|
||||
string desc = string.Format("@{0}{1:00}", (int)w.WearableType, layer);
|
||||
AddLink(item, desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddLink(item, string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new COF link
|
||||
/// </summary>
|
||||
/// <param name="item">Original item to be linked from COF</param>
|
||||
/// <param name="newDescription">Description for the link</param>
|
||||
public void AddLink(InventoryItem item, string newDescription)
|
||||
{
|
||||
if (COF == null) return;
|
||||
|
||||
bool linkExists = false;
|
||||
|
||||
linkExists = null != ContentLinks().Find(itemLink => itemLink.AssetUUID == item.UUID);
|
||||
|
||||
if (!linkExists)
|
||||
{
|
||||
Client.Inventory.CreateLink(COF.UUID, item.UUID, item.Name, newDescription, AssetType.Link, item.InventoryType, UUID.Random(), (success, newItem) =>
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
Client.Inventory.RequestFetchInventory(newItem.UUID, newItem.OwnerID);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a link to specified inventory item
|
||||
/// </summary>
|
||||
/// <param name="itemID">ID of the target inventory item for which we want link to be removed</param>
|
||||
public void RemoveLink(UUID itemID)
|
||||
{
|
||||
RemoveLink(new List<UUID>(1) { itemID });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a link to specified inventory item
|
||||
/// </summary>
|
||||
/// <param name="itemIDs">List of IDs of the target inventory item for which we want link to be removed</param>
|
||||
public void RemoveLink(List<UUID> itemIDs)
|
||||
{
|
||||
if (COF == null) return;
|
||||
|
||||
List<UUID> toRemove = new List<UUID>();
|
||||
|
||||
foreach (UUID itemID in itemIDs)
|
||||
{
|
||||
var links = ContentLinks().FindAll(itemLink => itemLink.AssetUUID == itemID);
|
||||
links.ForEach(item => toRemove.Add(item.UUID));
|
||||
}
|
||||
|
||||
Client.Inventory.Remove(toRemove, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove attachment
|
||||
/// </summary>
|
||||
/// <param name="item">>Inventory item to be detached</param>
|
||||
public void Detach(InventoryItem item)
|
||||
{
|
||||
var realItem = RealInventoryItem(item);
|
||||
//if (Instance.RLV.AllowDetach(realItem))
|
||||
//{
|
||||
Client.Appearance.Detach(item);
|
||||
RemoveLink(item.UUID);
|
||||
//}
|
||||
}
|
||||
|
||||
public List<InventoryItem> GetWornAt(WearableType type)
|
||||
{
|
||||
var ret = new List<InventoryItem>();
|
||||
ContentLinks().ForEach(link =>
|
||||
{
|
||||
var item = RealInventoryItem(link);
|
||||
if (item is InventoryWearable)
|
||||
{
|
||||
var w = (InventoryWearable)item;
|
||||
if (w.WearableType == type)
|
||||
{
|
||||
ret.Add(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves inventory links and returns a real inventory item that
|
||||
/// the link is pointing to
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public InventoryItem RealInventoryItem(InventoryItem item)
|
||||
{
|
||||
if (item.IsLink() && Client.Inventory.Store.Contains(item.AssetUUID) && Client.Inventory.Store[item.AssetUUID] is InventoryItem)
|
||||
{
|
||||
return (InventoryItem)Client.Inventory.Store[item.AssetUUID];
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the current outfit and updates COF links accordingly
|
||||
/// </summary>
|
||||
/// <param name="outfit">List of new wearables and attachments that comprise the new outfit</param>
|
||||
public void ReplaceOutfit(List<InventoryItem> newOutfit)
|
||||
{
|
||||
// Resolve inventory links
|
||||
List<InventoryItem> outfit = new List<InventoryItem>();
|
||||
foreach (var item in newOutfit)
|
||||
{
|
||||
outfit.Add(RealInventoryItem(item));
|
||||
}
|
||||
|
||||
// Remove links to all exiting items
|
||||
List<UUID> toRemove = new List<UUID>();
|
||||
ContentLinks().ForEach(item =>
|
||||
{
|
||||
if (IsBodyPart(item))
|
||||
{
|
||||
WearableType linkType = ((InventoryWearable)RealInventoryItem(item)).WearableType;
|
||||
bool hasBodyPart = false;
|
||||
|
||||
foreach (var newItemTmp in newOutfit)
|
||||
{
|
||||
var newItem = RealInventoryItem(newItemTmp);
|
||||
if (IsBodyPart(newItem))
|
||||
{
|
||||
if (((InventoryWearable)newItem).WearableType == linkType)
|
||||
{
|
||||
hasBodyPart = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasBodyPart)
|
||||
{
|
||||
toRemove.Add(item.UUID);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
toRemove.Add(item.UUID);
|
||||
}
|
||||
});
|
||||
|
||||
Client.Inventory.Remove(toRemove, null);
|
||||
|
||||
// Add links to new items
|
||||
List<InventoryItem> newItems = outfit.FindAll(item => CanBeWorn(item));
|
||||
foreach (var item in newItems)
|
||||
{
|
||||
AddLink(item);
|
||||
}
|
||||
|
||||
Client.Appearance.ReplaceOutfit(outfit, false);
|
||||
ThreadPool.QueueUserWorkItem(sync =>
|
||||
{
|
||||
Thread.Sleep(2000);
|
||||
Client.Appearance.RequestSetAppearance(true);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add items to current outfit
|
||||
/// </summary>
|
||||
/// <param name="item">Item to add</param>
|
||||
/// <param name="replace">Should existing wearable of the same type be removed</param>
|
||||
public void AddToOutfit(InventoryItem item, bool replace)
|
||||
{
|
||||
AddToOutfit(new List<InventoryItem>(1) { item }, replace);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add items to current outfit
|
||||
/// </summary>
|
||||
/// <param name="items">List of items to add</param>
|
||||
/// <param name="replace">Should existing wearable of the same type be removed</param>
|
||||
public void AddToOutfit(List<InventoryItem> items, bool replace)
|
||||
{
|
||||
List<InventoryItem> current = ContentLinks();
|
||||
List<UUID> toRemove = new List<UUID>();
|
||||
|
||||
// Resolve inventory links and remove wearables of the same type from COF
|
||||
List<InventoryItem> outfit = new List<InventoryItem>();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
InventoryItem realItem = RealInventoryItem(item);
|
||||
if (realItem is InventoryWearable)
|
||||
{
|
||||
foreach (var link in current)
|
||||
{
|
||||
var currentItem = RealInventoryItem(link);
|
||||
if (link.AssetUUID == item.UUID)
|
||||
{
|
||||
toRemove.Add(link.UUID);
|
||||
}
|
||||
else if (currentItem is InventoryWearable)
|
||||
{
|
||||
var w = (InventoryWearable)currentItem;
|
||||
if (w.WearableType == ((InventoryWearable)realItem).WearableType)
|
||||
{
|
||||
toRemove.Add(link.UUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outfit.Add(realItem);
|
||||
}
|
||||
Client.Inventory.Remove(toRemove, null);
|
||||
|
||||
// Add links to new items
|
||||
List<InventoryItem> newItems = outfit.FindAll(item => CanBeWorn(item));
|
||||
foreach (var item in newItems)
|
||||
{
|
||||
AddLink(item);
|
||||
}
|
||||
|
||||
Client.Appearance.AddToOutfit(outfit, replace);
|
||||
ThreadPool.QueueUserWorkItem(sync =>
|
||||
{
|
||||
Thread.Sleep(2000);
|
||||
Client.Appearance.RequestSetAppearance(true);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove an item from the current outfit
|
||||
/// </summary>
|
||||
/// <param name="items">Item to remove</param>
|
||||
public void RemoveFromOutfit(InventoryItem item)
|
||||
{
|
||||
RemoveFromOutfit(new List<InventoryItem>(1) { item });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove specified items from the current outfit
|
||||
/// </summary>
|
||||
/// <param name="items">List of items to remove</param>
|
||||
public void RemoveFromOutfit(List<InventoryItem> items)
|
||||
{
|
||||
// Resolve inventory links
|
||||
List<InventoryItem> outfit = new List<InventoryItem>();
|
||||
foreach (var item in items)
|
||||
{
|
||||
var realItem = RealInventoryItem(item);
|
||||
//if (Instance.RLV.AllowDetach(realItem))
|
||||
//{
|
||||
outfit.Add(realItem);
|
||||
//}
|
||||
}
|
||||
|
||||
// Remove links to all items that were removed
|
||||
List<UUID> toRemove = new List<UUID>();
|
||||
foreach (InventoryItem item in outfit.FindAll(item => CanBeWorn(item) && !IsBodyPart(item)))
|
||||
{
|
||||
toRemove.Add(item.UUID);
|
||||
}
|
||||
RemoveLink(toRemove);
|
||||
|
||||
Client.Appearance.RemoveFromOutfit(outfit);
|
||||
}
|
||||
|
||||
public bool IsBodyPart(InventoryItem item)
|
||||
{
|
||||
var realItem = RealInventoryItem(item);
|
||||
if (realItem is InventoryWearable)
|
||||
{
|
||||
var w = (InventoryWearable)realItem;
|
||||
var t = w.WearableType;
|
||||
if (t == WearableType.Shape ||
|
||||
t == WearableType.Skin ||
|
||||
t == WearableType.Eyes ||
|
||||
t == WearableType.Hair)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Force rebaking textures
|
||||
/// </summary>
|
||||
public void RebakeTextures()
|
||||
{
|
||||
Client.Appearance.RequestSetAppearance(true);
|
||||
}
|
||||
|
||||
#endregion Public methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
//using System.Reflection;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace Raindrop
|
||||
{
|
||||
public class Grid
|
||||
{
|
||||
public string ID = string.Empty;
|
||||
public string Name = string.Empty;
|
||||
public string Platform = string.Empty;
|
||||
public string LoginURI = string.Empty;
|
||||
public string LoginPage = string.Empty;
|
||||
public string HelperURI = string.Empty;
|
||||
public string Website = string.Empty;
|
||||
public string Support = string.Empty;
|
||||
public string Register = string.Empty;
|
||||
public string PasswordURL = string.Empty;
|
||||
public string Version = "1";
|
||||
|
||||
public Grid() { }
|
||||
|
||||
public Grid(string ID, string name, string loginURI)
|
||||
{
|
||||
this.ID = ID;
|
||||
this.Name = name;
|
||||
this.LoginURI = loginURI;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
public static Grid FromOSD(OSD data)
|
||||
{
|
||||
if (data == null || data.Type != OSDType.Map) return null;
|
||||
Grid grid = new Grid();
|
||||
OSDMap map = (OSDMap)data;
|
||||
|
||||
grid.ID = map["gridnick"].AsString();
|
||||
grid.Name = map["gridname"].AsString();
|
||||
grid.Platform = map["platform"].AsString();
|
||||
grid.LoginURI = map["loginuri"].AsString();
|
||||
grid.LoginPage = map["loginpage"].AsString();
|
||||
grid.HelperURI = map["helperuri"].AsString();
|
||||
grid.Website = map["website"].AsString();
|
||||
grid.Support = map["support"].AsString();
|
||||
grid.Register = map["register"].AsString();
|
||||
grid.PasswordURL = map["password"].AsString();
|
||||
grid.Version = map["version"].AsString();
|
||||
|
||||
return grid;
|
||||
}
|
||||
}
|
||||
|
||||
public class GridManager : IDisposable
|
||||
{
|
||||
public List<Grid> Grids;
|
||||
|
||||
public GridManager()
|
||||
{
|
||||
Grids = new List<Grid>();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public void LoadGrids(string datadir)
|
||||
{
|
||||
Grids.Clear();
|
||||
Grids.Add(new Grid("agni", "Second Life (agni)", "https://login.agni.lindenlab.com/cgi-bin/login.cgi"));
|
||||
Grids.Add(new Grid("aditi", "Second Life Beta (aditi)", "https://login.aditi.lindenlab.com/cgi-bin/login.cgi"));
|
||||
|
||||
try
|
||||
{
|
||||
string sysGridsFile = Path.Combine(Path.GetDirectoryName(datadir), "grids.xml");
|
||||
OSDArray sysGrids = (OSDArray)OSDParser.DeserializeLLSDXml(File.ReadAllText(sysGridsFile));
|
||||
for (int i = 0; i < sysGrids.Count; i++)
|
||||
{
|
||||
RegisterGrid(Grid.FromOSD(sysGrids[i]));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log(string.Format("Error loading grid information: {0}", ex.Message), Helpers.LogLevel.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterGrid(Grid grid)
|
||||
{
|
||||
int ix = Grids.FindIndex((Grid g) => { return g.ID == grid.ID; });
|
||||
if (ix < 0)
|
||||
{
|
||||
Grids.Add(grid);
|
||||
}
|
||||
else
|
||||
{
|
||||
Grids[ix] = grid;
|
||||
}
|
||||
}
|
||||
|
||||
public Grid this[int ix]
|
||||
{
|
||||
get { return Grids[ix]; }
|
||||
}
|
||||
|
||||
public Grid this[string gridID]
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (Grid grid in Grids)
|
||||
{
|
||||
if (grid.ID == gridID) return grid;
|
||||
}
|
||||
throw new KeyNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
public bool KeyExists(string gridID)
|
||||
{
|
||||
foreach (Grid grid in Grids)
|
||||
{
|
||||
if (grid.ID == gridID) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return Grids.Count; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96f21062a49b52b43914d622cebbfb1e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,723 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
#if (COGBOT_LIBOMV || USE_STHREADS)
|
||||
using ThreadPoolUtil;
|
||||
using Thread = ThreadPoolUtil.Thread;
|
||||
using ThreadPool = ThreadPoolUtil.ThreadPool;
|
||||
using Monitor = ThreadPoolUtil.Monitor;
|
||||
#endif
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Raindrop
|
||||
{
|
||||
#region enums
|
||||
/// <summary>
|
||||
/// Enum representing different modes of handling display names
|
||||
/// </summary>
|
||||
public enum NameMode : int
|
||||
{
|
||||
/// <summary> No display names </summary>
|
||||
Standard,
|
||||
/// <summary> Display name followed by (username) if display name is not default </summary>
|
||||
Smart,
|
||||
/// <summary> Display name followed by (username) </summary>
|
||||
OnlyDisplayName,
|
||||
/// <summary> Only display </summary>
|
||||
DisplayNameAndUserName,
|
||||
}
|
||||
#endregion enums
|
||||
|
||||
/// <summary>
|
||||
/// Manager for looking up avatar names and their caching
|
||||
/// </summary>
|
||||
public class NameManager : IDisposable
|
||||
{
|
||||
#region public fields and properties
|
||||
public event EventHandler<UUIDNameReplyEventArgs> NameUpdated;
|
||||
|
||||
public NameMode Mode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!client.Avatars.DisplayNamesAvailable())
|
||||
return NameMode.Standard;
|
||||
|
||||
return (NameMode)instance.GlobalSettings["display_name_mode"].AsInteger();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
instance.GlobalSettings["display_name_mode"] = (int)value;
|
||||
}
|
||||
}
|
||||
#endregion public fields and properties
|
||||
|
||||
#region private fields and properties
|
||||
RaindropInstance instance;
|
||||
GridClient client { get { return instance.Client; } }
|
||||
Timer requestTimer;
|
||||
Timer cacheTimer;
|
||||
string cacheFileName;
|
||||
|
||||
Queue<UUID> requests = new Queue<UUID>();
|
||||
|
||||
int MaxNameRequests = 80;
|
||||
|
||||
// Queue up name request for this many ms, and send a batch requst
|
||||
const int REQUEST_DELAY = 100;
|
||||
// Save name cache after change to names after this many ms
|
||||
const int CACHE_DELAY = 30000;
|
||||
// Consider request failed after this many ms
|
||||
const int MAX_REQ_AGE = 15000;
|
||||
|
||||
Dictionary<UUID, AgentDisplayName> names = new Dictionary<UUID, AgentDisplayName>();
|
||||
Dictionary<UUID, int> activeRequests = new Dictionary<UUID, int>();
|
||||
|
||||
ConcurrentQueue<List<UUID>> PendingLookups;
|
||||
//BlockingQueue<List<UUID>> PendingLookups;
|
||||
Thread requestThread = null;
|
||||
Semaphore lookupGate;
|
||||
bool useRequestThread;
|
||||
|
||||
#endregion private fields and properties
|
||||
|
||||
#region construction and disposal
|
||||
public NameManager(RaindropInstance instance)
|
||||
{
|
||||
this.instance = instance;
|
||||
|
||||
requestTimer = new Timer(MakeRequest, null, Timeout.Infinite, Timeout.Infinite);
|
||||
cacheTimer = new Timer(SaveCache, null, Timeout.Infinite, Timeout.Infinite);
|
||||
cacheFileName = Path.Combine(instance.UserDir, "name.cache");
|
||||
LoadCachedNames();
|
||||
instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
|
||||
RegisterEvents(client);
|
||||
|
||||
// Mono HTTPWebRequest sucks balls
|
||||
useRequestThread = instance.MonoRuntime;
|
||||
|
||||
if (useRequestThread)
|
||||
{
|
||||
PendingLookups = new ConcurrentQueue<List<UUID>>();
|
||||
lookupGate = new Semaphore(4, 4);
|
||||
requestThread = new Thread(new ThreadStart(RequestThread));
|
||||
requestThread.IsBackground = true;
|
||||
requestThread.Name = "Display Name Request Thread";
|
||||
requestThread.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
SaveCache(new object());
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
DeregisterEvents(client);
|
||||
}
|
||||
|
||||
if (requestTimer != null)
|
||||
{
|
||||
requestTimer.Dispose();
|
||||
requestTimer = null;
|
||||
}
|
||||
|
||||
if (cacheTimer != null)
|
||||
{
|
||||
cacheTimer.Dispose();
|
||||
cacheTimer = null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (useRequestThread)
|
||||
{
|
||||
//PendingLookups.Close();
|
||||
if (requestThread != null)
|
||||
{
|
||||
if (!requestThread.Join(5 * 1000))
|
||||
{
|
||||
requestThread.Abort();
|
||||
}
|
||||
requestThread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
#endregion construction and disposal
|
||||
|
||||
#region private methods
|
||||
public void RequestThread()
|
||||
{
|
||||
//PendingLookups.Open();
|
||||
|
||||
while (true)
|
||||
{
|
||||
List<UUID> req = null;
|
||||
if (!PendingLookups.TryDequeue(/*Timeout.Infinite,*/ out req)) break;
|
||||
lookupGate.WaitOne(90 * 1000);
|
||||
client.Avatars.GetDisplayNames(req, (bool success, AgentDisplayName[] names, UUID[] badIDs) =>
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
ProcessDisplayNames(names);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("Failed fetching display names", Helpers.LogLevel.Warning, client);
|
||||
}
|
||||
lookupGate.Release(1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterEvents(GridClient c)
|
||||
{
|
||||
c.Avatars.UUIDNameReply += new EventHandler<UUIDNameReplyEventArgs>(Avatars_UUIDNameReply);
|
||||
c.Avatars.DisplayNameUpdate += new EventHandler<DisplayNameUpdateEventArgs>(Avatars_DisplayNameUpdate);
|
||||
}
|
||||
|
||||
void DeregisterEvents(GridClient c)
|
||||
{
|
||||
c.Avatars.UUIDNameReply -= new EventHandler<UUIDNameReplyEventArgs>(Avatars_UUIDNameReply);
|
||||
c.Avatars.DisplayNameUpdate -= new EventHandler<DisplayNameUpdateEventArgs>(Avatars_DisplayNameUpdate);
|
||||
}
|
||||
|
||||
DateTime UUIDNameOnly = new DateTime(1970, 9, 4, 10, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
void instance_ClientChanged(object sender, ClientChangedEventArgs e)
|
||||
{
|
||||
DeregisterEvents(e.OldClient);
|
||||
RegisterEvents(e.Client);
|
||||
}
|
||||
|
||||
void Avatars_DisplayNameUpdate(object sender, DisplayNameUpdateEventArgs e)
|
||||
{
|
||||
lock (names)
|
||||
{
|
||||
e.DisplayName.Updated = DateTime.Now;
|
||||
names[e.DisplayName.ID] = e.DisplayName;
|
||||
}
|
||||
Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
|
||||
ret.Add(e.DisplayName.ID, FormatName(e.DisplayName));
|
||||
TriggerEvent(ret);
|
||||
}
|
||||
|
||||
void Avatars_UUIDNameReply(object sender, UUIDNameReplyEventArgs e)
|
||||
{
|
||||
Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
|
||||
|
||||
foreach (KeyValuePair<UUID, string> kvp in e.Names)
|
||||
{
|
||||
// Remove from the list of active requests if in UUID only (standard mode)
|
||||
if (Mode == NameMode.Standard)
|
||||
{
|
||||
lock (activeRequests)
|
||||
{
|
||||
activeRequests.Remove(kvp.Key);
|
||||
}
|
||||
}
|
||||
|
||||
lock (names)
|
||||
{
|
||||
if (!names.ContainsKey(kvp.Key))
|
||||
{
|
||||
names[kvp.Key] = new AgentDisplayName();
|
||||
names[kvp.Key].ID = kvp.Key;
|
||||
names[kvp.Key].NextUpdate = UUIDNameOnly;
|
||||
names[kvp.Key].IsDefaultDisplayName = true;
|
||||
}
|
||||
|
||||
names[kvp.Key].Updated = DateTime.Now;
|
||||
|
||||
string[] parts = kvp.Value.Trim().Split(' ');
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
if (InvalidName(names[kvp.Key].DisplayName))
|
||||
{
|
||||
names[kvp.Key].DisplayName = string.Format("{0} {1}", parts[0], parts[1]);
|
||||
}
|
||||
|
||||
names[kvp.Key].LegacyFirstName = parts[0];
|
||||
names[kvp.Key].LegacyLastName = parts[1];
|
||||
if (names[kvp.Key].LegacyLastName == "Resident")
|
||||
{
|
||||
names[kvp.Key].UserName = names[kvp.Key].LegacyFirstName.ToLower();
|
||||
}
|
||||
else
|
||||
{
|
||||
names[kvp.Key].UserName = string.Format("{0}.{1}", parts[0], parts[1]).ToLower();
|
||||
}
|
||||
|
||||
ret.Add(kvp.Key, FormatName(names[kvp.Key]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TriggerEvent(ret);
|
||||
TriggerCacheSave();
|
||||
}
|
||||
|
||||
string FormatName(AgentDisplayName n)
|
||||
{
|
||||
switch (Mode)
|
||||
{
|
||||
case NameMode.OnlyDisplayName:
|
||||
return n.DisplayName;
|
||||
|
||||
case NameMode.Smart:
|
||||
if (n.IsDefaultDisplayName)
|
||||
return n.DisplayName;
|
||||
else
|
||||
return string.Format("{0} ({1})", n.DisplayName, n.UserName);
|
||||
|
||||
case NameMode.DisplayNameAndUserName:
|
||||
return string.Format("{0} ({1})", n.DisplayName, n.UserName);
|
||||
|
||||
default:
|
||||
return n.LegacyFullName;
|
||||
}
|
||||
}
|
||||
|
||||
bool InvalidName(string displayName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(displayName) ||
|
||||
displayName == "???" ||
|
||||
displayName == RaindropInstance.INCOMPLETE_NAME)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ProcessDisplayNames(AgentDisplayName[] names)
|
||||
{
|
||||
Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
|
||||
|
||||
foreach (var name in names)
|
||||
{
|
||||
// Remove from the list of active requests
|
||||
lock (activeRequests)
|
||||
{
|
||||
activeRequests.Remove(name.ID);
|
||||
}
|
||||
|
||||
if (InvalidName(name.DisplayName)) continue;
|
||||
|
||||
ret.Add(name.ID, FormatName(name));
|
||||
|
||||
name.Updated = DateTime.Now;
|
||||
lock (this.names)
|
||||
{
|
||||
this.names[name.ID] = name;
|
||||
}
|
||||
}
|
||||
|
||||
TriggerEvent(ret);
|
||||
TriggerCacheSave();
|
||||
}
|
||||
|
||||
void MakeRequest(object sync)
|
||||
{
|
||||
List<UUID> req = new List<UUID>();
|
||||
lock (requests)
|
||||
{
|
||||
while (requests.Count > 0)
|
||||
req.Add(requests.Dequeue());
|
||||
}
|
||||
|
||||
|
||||
if (req.Count > 0)
|
||||
{
|
||||
if (Mode == NameMode.Standard || (!client.Avatars.DisplayNamesAvailable()))
|
||||
{
|
||||
client.Avatars.RequestAvatarNames(req);
|
||||
}
|
||||
else // Use display names
|
||||
{
|
||||
if (useRequestThread)
|
||||
{
|
||||
PendingLookups.Enqueue(new List<UUID>(req));
|
||||
}
|
||||
else
|
||||
{
|
||||
client.Avatars.GetDisplayNames(req, (bool success, AgentDisplayName[] names, UUID[] badIDs) =>
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
ProcessDisplayNames(names);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("Failed fetching display names", Helpers.LogLevel.Warning, client);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SaveCache(object sync)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(syncx =>
|
||||
{
|
||||
OSDArray namesOSD = new OSDArray(names.Count);
|
||||
lock (names)
|
||||
{
|
||||
foreach (var name in names)
|
||||
{
|
||||
namesOSD.Add(name.Value.GetOSD());
|
||||
}
|
||||
}
|
||||
|
||||
OSDMap cache = new OSDMap(1);
|
||||
cache["names"] = namesOSD;
|
||||
byte[] data = OSDParser.SerializeLLSDBinary(cache, false);
|
||||
Logger.DebugLog(string.Format("Caching {0} avatar names to {1}", namesOSD.Count, cacheFileName));
|
||||
|
||||
try
|
||||
{
|
||||
File.WriteAllBytes(cacheFileName, data);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log("Failed to save avatar name cache: ", Helpers.LogLevel.Error, client, ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LoadCachedNames()
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(syncx =>
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] data = File.ReadAllBytes(cacheFileName);
|
||||
OSDMap cache = (OSDMap)OSDParser.DeserializeLLSDBinary(data);
|
||||
OSDArray namesOSD = (OSDArray)cache["names"];
|
||||
DateTime now = DateTime.Now;
|
||||
TimeSpan maxAge = new TimeSpan(48, 0, 0);
|
||||
NameMode mode = (NameMode)(int)instance.GlobalSettings["display_name_mode"];
|
||||
|
||||
lock (names)
|
||||
{
|
||||
for (int i = 0; i < namesOSD.Count; i++)
|
||||
{
|
||||
AgentDisplayName name = AgentDisplayName.FromOSD(namesOSD[i]);
|
||||
if (mode == NameMode.Standard || ((now - name.Updated) < maxAge))
|
||||
{
|
||||
names[name.ID] = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger.DebugLog(string.Format("Restored {0} names from the avatar name cache", names.Count));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log("Failed loading cached avatar names: ", Helpers.LogLevel.Warning, client, ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void TriggerEvent(Dictionary<UUID, string> ret)
|
||||
{
|
||||
if (NameUpdated == null || ret.Count == 0) return;
|
||||
|
||||
try
|
||||
{
|
||||
NameUpdated(this, new UUIDNameReplyEventArgs(ret));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log("Failure in event handler: " + ex.Message, Helpers.LogLevel.Warning, client, ex);
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerNameRequest()
|
||||
{
|
||||
if (requestTimer != null)
|
||||
{
|
||||
requestTimer.Change(REQUEST_DELAY, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerCacheSave()
|
||||
{
|
||||
if (cacheTimer != null)
|
||||
{
|
||||
cacheTimer.Change(CACHE_DELAY, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
|
||||
void QueueNameRequest(UUID agentID)
|
||||
{
|
||||
// Check if we're already waiting for an answer on this one
|
||||
lock (activeRequests)
|
||||
{
|
||||
if (activeRequests.ContainsKey(agentID))
|
||||
{
|
||||
// Logger.Log("Exiting is active " + agentID.ToString(), Helpers.LogLevel.Error);
|
||||
if (Environment.TickCount - activeRequests[agentID] < MAX_REQ_AGE) // Not timeout yet
|
||||
{
|
||||
// Logger.Log("Exiting is active " + agentID.ToString(), Helpers.LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Logger.Log("Continuing, present but expired " + agentID.ToString(), Helpers.LogLevel.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Logger.Log("Not present " + agentID.ToString(), Helpers.LogLevel.Error);
|
||||
}
|
||||
|
||||
// Record time of when we're making this request
|
||||
activeRequests[agentID] = Environment.TickCount;
|
||||
}
|
||||
|
||||
|
||||
lock (requests)
|
||||
{
|
||||
if (!requests.Contains(agentID))
|
||||
{
|
||||
// Logger.Log("Enqueueing " + agentID.ToString(), Helpers.LogLevel.Error);
|
||||
requests.Enqueue(agentID);
|
||||
|
||||
if (requests.Count >= MaxNameRequests && Mode != NameMode.Standard)
|
||||
{
|
||||
requestTimer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
MakeRequest(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
TriggerNameRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion private methods
|
||||
|
||||
#region public methods
|
||||
/// <summary>
|
||||
/// Cleans avatar name cache
|
||||
/// </summary>
|
||||
public void CleanCache()
|
||||
{
|
||||
lock (names)
|
||||
{
|
||||
try
|
||||
{
|
||||
names.Clear();
|
||||
File.Delete(cacheFileName);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets legacy First Last name
|
||||
/// </summary>
|
||||
/// <param name="agentID">UUID of the agent</param>
|
||||
/// <returns></returns>
|
||||
public string GetLegacyName(UUID agentID)
|
||||
{
|
||||
if (agentID == UUID.Zero) return "(???) (???)";
|
||||
|
||||
lock (names)
|
||||
{
|
||||
if (names.ContainsKey(agentID))
|
||||
{
|
||||
return names[agentID].LegacyFullName;
|
||||
}
|
||||
}
|
||||
|
||||
QueueNameRequest(agentID);
|
||||
return RaindropInstance.INCOMPLETE_NAME;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets UserName
|
||||
/// </summary>
|
||||
/// <param name="agentID">UUID of the agent</param>
|
||||
/// <returns></returns>
|
||||
public string GetUserName(UUID agentID)
|
||||
{
|
||||
if (agentID == UUID.Zero) return "(???) (???)";
|
||||
|
||||
lock (names)
|
||||
{
|
||||
if (names.ContainsKey(agentID))
|
||||
{
|
||||
return names[agentID].UserName;
|
||||
}
|
||||
}
|
||||
|
||||
QueueNameRequest(agentID);
|
||||
return RaindropInstance.INCOMPLETE_NAME;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets DisplayName
|
||||
/// </summary>
|
||||
/// <param name="agentID">UUID of the agent</param>
|
||||
/// <returns></returns>
|
||||
public string GetDisplayName(UUID agentID)
|
||||
{
|
||||
if (agentID == UUID.Zero) return "(???) (???)";
|
||||
|
||||
lock (names)
|
||||
{
|
||||
if (names.ContainsKey(agentID))
|
||||
{
|
||||
return names[agentID].DisplayName;
|
||||
}
|
||||
}
|
||||
|
||||
QueueNameRequest(agentID);
|
||||
return RaindropInstance.INCOMPLETE_NAME;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get avatar display name, or queue fetching of the name
|
||||
/// </summary>
|
||||
/// <param name="agentID">UUID of avatar to lookup</param>
|
||||
/// <returns>Avatar display name or "Loading..." if not in cache</returns>
|
||||
public string Get(UUID agentID)
|
||||
{
|
||||
if (agentID == UUID.Zero) return "(???) (???)";
|
||||
|
||||
lock (names)
|
||||
{
|
||||
if (names.ContainsKey(agentID))
|
||||
{
|
||||
if (Mode != NameMode.Standard && names[agentID].NextUpdate == UUIDNameOnly)
|
||||
{
|
||||
QueueNameRequest(agentID);
|
||||
}
|
||||
return FormatName(names[agentID]);
|
||||
}
|
||||
}
|
||||
|
||||
QueueNameRequest(agentID);
|
||||
return RaindropInstance.INCOMPLETE_NAME;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get avatar display name, or queue fetching of the name
|
||||
/// </summary>
|
||||
/// <param name="agentID">UUID of avatar to lookup</param>
|
||||
/// <param name="blocking">If true, wait until name is recieved, otherwise return immediately</param>
|
||||
/// <returns>Avatar display name or "Loading..." if not in cache</returns>
|
||||
public string Get(UUID agentID, bool blocking)
|
||||
{
|
||||
if (!blocking)
|
||||
Get(agentID);
|
||||
|
||||
string name = null;
|
||||
|
||||
using (ManualResetEvent gotName = new ManualResetEvent(false))
|
||||
{
|
||||
|
||||
EventHandler<UUIDNameReplyEventArgs> handler = (object sender, UUIDNameReplyEventArgs e) =>
|
||||
{
|
||||
if (e.Names.ContainsKey(agentID))
|
||||
{
|
||||
name = e.Names[agentID];
|
||||
gotName.Set();
|
||||
}
|
||||
};
|
||||
|
||||
NameUpdated += handler;
|
||||
name = Get(agentID);
|
||||
|
||||
if (name == RaindropInstance.INCOMPLETE_NAME)
|
||||
{
|
||||
gotName.WaitOne(20 * 1000, false);
|
||||
}
|
||||
|
||||
NameUpdated -= handler;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get avatar display name, or queue fetching of the name
|
||||
/// </summary>
|
||||
/// <param name="agentID">UUID of avatar to lookup</param>
|
||||
/// <param name="defaultValue">If name failed to retrieve, use this</param>
|
||||
/// <returns>Avatar display name or the default value if not in cache</returns>
|
||||
public string Get(UUID agentID, string defaultValue)
|
||||
{
|
||||
if (Mode == NameMode.Standard)
|
||||
return defaultValue;
|
||||
|
||||
string name = Get(agentID);
|
||||
if (name == RaindropInstance.INCOMPLETE_NAME)
|
||||
return defaultValue;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get avatar display name, or queue fetching of the name
|
||||
/// </summary>
|
||||
/// <param name="agentID">UUID of avatar to lookup</param>
|
||||
/// <param name="blocking">If true, wait until name is recieved, otherwise return immediately</param>
|
||||
/// <param name="defaultValue">If name failed to retrieve, use this</param>
|
||||
/// <returns></returns>
|
||||
public string Get(UUID agentID, bool blocking, string defaultValue)
|
||||
{
|
||||
if (Mode == NameMode.Standard)
|
||||
return defaultValue;
|
||||
|
||||
string name = Get(agentID, blocking);
|
||||
if (name == RaindropInstance.INCOMPLETE_NAME)
|
||||
return defaultValue;
|
||||
|
||||
return name;
|
||||
|
||||
}
|
||||
|
||||
#endregion public methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace Raindrop.Netcom
|
||||
{
|
||||
public class ChatSentEventArgs : EventArgs
|
||||
{
|
||||
private string message;
|
||||
private ChatType type;
|
||||
private int channel;
|
||||
|
||||
public ChatSentEventArgs(string message, ChatType type, int channel)
|
||||
{
|
||||
this.message = message;
|
||||
this.type = type;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public string Message
|
||||
{
|
||||
get { return message; }
|
||||
}
|
||||
|
||||
public ChatType Type
|
||||
{
|
||||
get { return type; }
|
||||
}
|
||||
|
||||
public int Channel
|
||||
{
|
||||
get { return channel; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
namespace Raindrop.Netcom
|
||||
{
|
||||
public enum StartLocationType
|
||||
{
|
||||
Home,
|
||||
Last,
|
||||
Custom
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace Raindrop.Netcom
|
||||
{
|
||||
public class InstantMessageSentEventArgs : EventArgs
|
||||
{
|
||||
private string message;
|
||||
private UUID targetID;
|
||||
private UUID sessionID;
|
||||
private DateTime timestamp;
|
||||
|
||||
public InstantMessageSentEventArgs(string message, UUID targetID, UUID sessionID, DateTime timestamp)
|
||||
{
|
||||
this.message = message;
|
||||
this.targetID = targetID;
|
||||
this.sessionID = sessionID;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public string Message
|
||||
{
|
||||
get { return message; }
|
||||
}
|
||||
|
||||
public UUID TargetID
|
||||
{
|
||||
get { return targetID; }
|
||||
}
|
||||
|
||||
public UUID SessionID
|
||||
{
|
||||
get { return sessionID; }
|
||||
}
|
||||
|
||||
public DateTime Timestamp
|
||||
{
|
||||
get { return timestamp; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace Raindrop.Netcom
|
||||
{
|
||||
public class LoginOptions
|
||||
{
|
||||
private string firstName;
|
||||
private string lastName;
|
||||
private string password;
|
||||
private string version = string.Empty;
|
||||
private string channel = string.Empty;
|
||||
|
||||
private StartLocationType startLocation = StartLocationType.Home;
|
||||
private string startLocationCustom = string.Empty;
|
||||
|
||||
private Grid grid;
|
||||
private string gridCustomLoginUri = string.Empty;
|
||||
private LastExecStatus lastExecEvent = LastExecStatus.Normal;
|
||||
|
||||
|
||||
public LoginOptions()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static bool IsPasswordMD5(string pass)
|
||||
{
|
||||
return pass.Length == 35 && pass.StartsWith("$1$");
|
||||
}
|
||||
|
||||
public string FirstName
|
||||
{
|
||||
get { return firstName; }
|
||||
set { firstName = value; }
|
||||
}
|
||||
|
||||
public string LastName
|
||||
{
|
||||
get { return lastName; }
|
||||
set { lastName = value; }
|
||||
}
|
||||
|
||||
public string FullName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName))
|
||||
return string.Empty;
|
||||
else
|
||||
return firstName + " " + lastName;
|
||||
}
|
||||
}
|
||||
|
||||
public string Password
|
||||
{
|
||||
get { return password; }
|
||||
set { password = value; }
|
||||
}
|
||||
|
||||
public StartLocationType StartLocation
|
||||
{
|
||||
get { return startLocation; }
|
||||
set { startLocation = value; }
|
||||
}
|
||||
|
||||
public string StartLocationCustom
|
||||
{
|
||||
get { return startLocationCustom; }
|
||||
set { startLocationCustom = value; }
|
||||
}
|
||||
|
||||
public string Channel
|
||||
{
|
||||
get { return channel; }
|
||||
set { channel = value; }
|
||||
}
|
||||
|
||||
public string Version
|
||||
{
|
||||
get { return version; }
|
||||
set { version = value; }
|
||||
}
|
||||
|
||||
public Grid Grid
|
||||
{
|
||||
get { return grid; }
|
||||
set { grid = value; }
|
||||
}
|
||||
|
||||
public string GridCustomLoginUri
|
||||
{
|
||||
get { return gridCustomLoginUri; }
|
||||
set { gridCustomLoginUri = value; }
|
||||
}
|
||||
|
||||
public LastExecStatus LastExecEvent
|
||||
{
|
||||
get { return lastExecEvent; }
|
||||
set { lastExecEvent = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,420 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using OpenMetaverse;
|
||||
using Raindrop;
|
||||
using OpenMetaverse.Packets;
|
||||
|
||||
namespace Raindrop.Netcom
|
||||
{
|
||||
/// <summary>
|
||||
/// RadegastNetcom is a class built on top of libsecondlife that provides a way to
|
||||
/// raise events on the proper thread (for GUI apps especially).
|
||||
/// </summary>
|
||||
public partial class RaindropNetcom : IDisposable
|
||||
{
|
||||
private RaindropInstance instance;
|
||||
private GridClient client { get { return instance.Client; } }
|
||||
public LoginOptions loginOptions;
|
||||
|
||||
private bool loggingIn = false;
|
||||
private bool loggedIn = false;
|
||||
private bool teleporting = false;
|
||||
private bool agreeToTos = false;
|
||||
public bool AgreeToTos { get { return agreeToTos; } set { agreeToTos = value; } }
|
||||
private Grid grid;
|
||||
public Grid Grid { get { return grid; } }
|
||||
|
||||
// NetcomSync is used for raising certain events on the
|
||||
// GUI/main thread. Useful if you're modifying GUI controls
|
||||
// in the client app when responding to those events.
|
||||
//private Control netcomSync;
|
||||
//we don't use netcomsync or a netcom actually. we just pass all as events to the unitymainthreaddispatcher for now.
|
||||
|
||||
#region ClientConnected event
|
||||
/// <summary>The event subscribers, null of no subscribers</summary>
|
||||
private EventHandler<EventArgs> m_ClientConnected;
|
||||
|
||||
///<summary>Raises the ClientConnected Event</summary>
|
||||
/// <param name="e">A ClientConnectedEventArgs object containing
|
||||
/// the old and the new client</param>
|
||||
protected virtual void OnClientConnected(EventArgs e)
|
||||
{
|
||||
EventHandler<EventArgs> handler = m_ClientConnected;
|
||||
if (handler != null)
|
||||
handler(this, e);
|
||||
}
|
||||
|
||||
/// <summary>Thread sync lock object</summary>
|
||||
private readonly object m_ClientConnectedLock = new object();
|
||||
|
||||
/// <summary>Raise event delegate</summary>
|
||||
private delegate void ClientConnectedRaise(EventArgs e);
|
||||
|
||||
/// <summary>Raised when the GridClient object in the main Radegast instance is changed</summary>
|
||||
public event EventHandler<EventArgs> ClientConnected
|
||||
{
|
||||
add { lock (m_ClientConnectedLock) { m_ClientConnected += value; } }
|
||||
remove { lock (m_ClientConnectedLock) { m_ClientConnected -= value; } }
|
||||
}
|
||||
#endregion ClientConnected event
|
||||
|
||||
public RaindropNetcom(RaindropInstance instance)
|
||||
{
|
||||
this.instance = instance;
|
||||
loginOptions = new LoginOptions();
|
||||
|
||||
instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
|
||||
RegisterClientEvents(client);
|
||||
}
|
||||
|
||||
private void RegisterClientEvents(GridClient client)
|
||||
{
|
||||
client.Self.ChatFromSimulator += new EventHandler<ChatEventArgs>(Self_ChatFromSimulator);
|
||||
client.Self.IM += new EventHandler<InstantMessageEventArgs>(Self_IM);
|
||||
client.Self.MoneyBalance += new EventHandler<BalanceEventArgs>(Self_MoneyBalance);
|
||||
client.Self.TeleportProgress += new EventHandler<TeleportEventArgs>(Self_TeleportProgress);
|
||||
client.Self.AlertMessage += new EventHandler<AlertMessageEventArgs>(Self_AlertMessage);
|
||||
client.Network.Disconnected += new EventHandler<DisconnectedEventArgs>(Network_Disconnected);
|
||||
client.Network.LoginProgress += new EventHandler<LoginProgressEventArgs>(Network_LoginProgress);
|
||||
client.Network.LoggedOut += new EventHandler<LoggedOutEventArgs>(Network_LoggedOut);
|
||||
}
|
||||
|
||||
private void UnregisterClientEvents(GridClient client)
|
||||
{
|
||||
client.Self.ChatFromSimulator -= new EventHandler<ChatEventArgs>(Self_ChatFromSimulator);
|
||||
client.Self.IM -= new EventHandler<InstantMessageEventArgs>(Self_IM);
|
||||
client.Self.MoneyBalance -= new EventHandler<BalanceEventArgs>(Self_MoneyBalance);
|
||||
client.Self.TeleportProgress -= new EventHandler<TeleportEventArgs>(Self_TeleportProgress);
|
||||
client.Self.AlertMessage -= new EventHandler<AlertMessageEventArgs>(Self_AlertMessage);
|
||||
client.Network.Disconnected -= new EventHandler<DisconnectedEventArgs>(Network_Disconnected);
|
||||
client.Network.LoginProgress -= new EventHandler<LoginProgressEventArgs>(Network_LoginProgress);
|
||||
client.Network.LoggedOut -= new EventHandler<LoggedOutEventArgs>(Network_LoggedOut);
|
||||
}
|
||||
|
||||
void instance_ClientChanged(object sender, ClientChangedEventArgs e)
|
||||
{
|
||||
UnregisterClientEvents(e.OldClient);
|
||||
RegisterClientEvents(client);
|
||||
}
|
||||
|
||||
//private bool CanSyncInvoke
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return netcomSync != null && !netcomSync.IsDisposed && netcomSync.IsHandleCreated && netcomSync.InvokeRequired;
|
||||
// }
|
||||
//}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (client != null)
|
||||
{
|
||||
UnregisterClientEvents(client);
|
||||
}
|
||||
}
|
||||
|
||||
void Self_IM(object sender, InstantMessageEventArgs e)
|
||||
{
|
||||
UnityMainThreadDispatcher.Instance().Enqueue(() => {
|
||||
Logger.DebugLog("netcom callback: Self_IM");
|
||||
OnInstantMessageReceived(e);
|
||||
});
|
||||
|
||||
|
||||
//if (CanSyncInvoke)
|
||||
// netcomSync.BeginInvoke(new OnInstantMessageRaise(OnInstantMessageReceived), new object[] { e });
|
||||
//else
|
||||
// OnInstantMessageReceived(e);
|
||||
}
|
||||
|
||||
void Network_LoginProgress(object sender, LoginProgressEventArgs e)
|
||||
{
|
||||
if (e.Status == LoginStatus.Success)
|
||||
{
|
||||
loggedIn = true;
|
||||
client.Self.RequestBalance();
|
||||
if (CanSyncInvoke)
|
||||
{
|
||||
netcomSync.BeginInvoke(new ClientConnectedRaise(OnClientConnected), new object[] { EventArgs.Empty });
|
||||
}
|
||||
else
|
||||
{
|
||||
OnClientConnected(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
if (e.Status == LoginStatus.Failed)
|
||||
{
|
||||
instance.MarkEndExecution();
|
||||
}
|
||||
|
||||
LoginProgressEventArgs ea = new LoginProgressEventArgs(e.Status, e.Message, string.Empty);
|
||||
|
||||
if (CanSyncInvoke)
|
||||
netcomSync.BeginInvoke(new OnClientLoginRaise(OnClientLoginStatus), new object[] { e });
|
||||
else
|
||||
OnClientLoginStatus(e);
|
||||
}
|
||||
|
||||
void Network_LoggedOut(object sender, LoggedOutEventArgs e)
|
||||
{
|
||||
loggedIn = false;
|
||||
|
||||
if (CanSyncInvoke)
|
||||
netcomSync.BeginInvoke(new OnClientLogoutRaise(OnClientLoggedOut), new object[] { EventArgs.Empty });
|
||||
else
|
||||
OnClientLoggedOut(EventArgs.Empty);
|
||||
}
|
||||
|
||||
void Self_TeleportProgress(object sender, TeleportEventArgs e)
|
||||
{
|
||||
if (e.Status == TeleportStatus.Finished || e.Status == TeleportStatus.Failed)
|
||||
teleporting = false;
|
||||
|
||||
if (CanSyncInvoke)
|
||||
netcomSync.BeginInvoke(new OnTeleportStatusRaise(OnTeleportStatusChanged), new object[] { e });
|
||||
else
|
||||
OnTeleportStatusChanged(e);
|
||||
}
|
||||
|
||||
private void Self_ChatFromSimulator(object sender, ChatEventArgs e)
|
||||
{
|
||||
if (CanSyncInvoke)
|
||||
netcomSync.BeginInvoke(new OnChatRaise(OnChatReceived), new object[] { e });
|
||||
else
|
||||
OnChatReceived(e);
|
||||
}
|
||||
|
||||
void Network_Disconnected(object sender, DisconnectedEventArgs e)
|
||||
{
|
||||
loggedIn = false;
|
||||
instance.MarkEndExecution();
|
||||
|
||||
if (CanSyncInvoke)
|
||||
netcomSync.BeginInvoke(new OnClientDisconnectRaise(OnClientDisconnected), new object[] { e });
|
||||
else
|
||||
OnClientDisconnected(e);
|
||||
}
|
||||
|
||||
void Self_MoneyBalance(object sender, BalanceEventArgs e)
|
||||
{
|
||||
if (CanSyncInvoke)
|
||||
netcomSync.BeginInvoke(new OnMoneyBalanceRaise(OnMoneyBalanceUpdated), new object[] { e });
|
||||
else
|
||||
OnMoneyBalanceUpdated(e);
|
||||
}
|
||||
|
||||
void Self_AlertMessage(object sender, AlertMessageEventArgs e)
|
||||
{
|
||||
if (CanSyncInvoke)
|
||||
netcomSync.BeginInvoke(new OnAlertMessageRaise(OnAlertMessageReceived), new object[] { e });
|
||||
else
|
||||
OnAlertMessageReceived(e);
|
||||
}
|
||||
|
||||
public void Login()
|
||||
{
|
||||
loggingIn = true;
|
||||
|
||||
// Report crashes only once and not on relogs/reconnects
|
||||
LastExecStatus execStatus = instance.GetLastExecStatus();
|
||||
if (!instance.AnotherInstanceRunning() && execStatus != LastExecStatus.Normal && (!instance.ReportedCrash))
|
||||
{
|
||||
instance.ReportedCrash = true;
|
||||
loginOptions.LastExecEvent = execStatus;
|
||||
Logger.Log("Reporting crash of the last application run to the grid login service", Helpers.LogLevel.Warning);
|
||||
}
|
||||
else
|
||||
{
|
||||
loginOptions.LastExecEvent = LastExecStatus.Normal;
|
||||
Logger.Log("Reporting normal shutdown of the last application run to the grid login service", Helpers.LogLevel.Info);
|
||||
}
|
||||
instance.MarkStartExecution();
|
||||
|
||||
OverrideEventArgs ea = new OverrideEventArgs();
|
||||
OnClientLoggingIn(ea);
|
||||
|
||||
if (ea.Cancel)
|
||||
{
|
||||
loggingIn = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(loginOptions.FirstName) ||
|
||||
string.IsNullOrEmpty(loginOptions.LastName) ||
|
||||
string.IsNullOrEmpty(loginOptions.Password))
|
||||
{
|
||||
OnClientLoginStatus(
|
||||
new LoginProgressEventArgs(LoginStatus.Failed, "One or more fields are blank.", string.Empty));
|
||||
}
|
||||
|
||||
string startLocation = string.Empty;
|
||||
|
||||
switch (loginOptions.StartLocation)
|
||||
{
|
||||
case StartLocationType.Home: startLocation = "home"; break;
|
||||
case StartLocationType.Last: startLocation = "last"; break;
|
||||
|
||||
case StartLocationType.Custom:
|
||||
startLocation = loginOptions.StartLocationCustom.Trim();
|
||||
|
||||
StartLocationParser parser = new StartLocationParser(startLocation);
|
||||
startLocation = NetworkManager.StartLocation(parser.Sim, parser.X, parser.Y, parser.Z);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
string password;
|
||||
|
||||
if (LoginOptions.IsPasswordMD5(loginOptions.Password))
|
||||
{
|
||||
password = loginOptions.Password;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (loginOptions.Password.Length > 16)
|
||||
{
|
||||
password = Utils.MD5(loginOptions.Password.Substring(0, 16));
|
||||
}
|
||||
else
|
||||
{
|
||||
password = Utils.MD5(loginOptions.Password);
|
||||
}
|
||||
}
|
||||
|
||||
LoginParams loginParams = client.Network.DefaultLoginParams(
|
||||
loginOptions.FirstName, loginOptions.LastName, password,
|
||||
loginOptions.Channel, loginOptions.Version);
|
||||
|
||||
grid = loginOptions.Grid;
|
||||
loginParams.Start = startLocation;
|
||||
loginParams.AgreeToTos = AgreeToTos;
|
||||
loginParams.URI = grid.LoginURI;
|
||||
loginParams.LastExecEvent = loginOptions.LastExecEvent;
|
||||
client.Network.BeginLogin(loginParams);
|
||||
}
|
||||
|
||||
public void Logout()
|
||||
{
|
||||
if (!loggedIn)
|
||||
{
|
||||
OnClientLoggedOut(EventArgs.Empty);
|
||||
return;
|
||||
}
|
||||
|
||||
OverrideEventArgs ea = new OverrideEventArgs();
|
||||
OnClientLoggingOut(ea);
|
||||
if (ea.Cancel) return;
|
||||
|
||||
client.Network.Logout();
|
||||
}
|
||||
|
||||
public void ChatOut(string chat, ChatType type, int channel)
|
||||
{
|
||||
if (!loggedIn) return;
|
||||
|
||||
client.Self.Chat(chat, channel, type);
|
||||
OnChatSent(new ChatSentEventArgs(chat, type, channel));
|
||||
}
|
||||
|
||||
public void SendInstantMessage(string message, UUID target, UUID session)
|
||||
{
|
||||
if (!loggedIn) return;
|
||||
|
||||
client.Self.InstantMessage(
|
||||
loginOptions.FullName, target, message, session, InstantMessageDialog.MessageFromAgent,
|
||||
InstantMessageOnline.Online, client.Self.SimPosition, client.Network.CurrentSim.ID, null);
|
||||
|
||||
OnInstantMessageSent(new InstantMessageSentEventArgs(message, target, session, DateTime.Now));
|
||||
}
|
||||
|
||||
public void SendIMStartTyping(UUID target, UUID session)
|
||||
{
|
||||
if (!loggedIn) return;
|
||||
|
||||
client.Self.InstantMessage(
|
||||
loginOptions.FullName, target, "typing", session, InstantMessageDialog.StartTyping,
|
||||
InstantMessageOnline.Online, client.Self.SimPosition, client.Network.CurrentSim.ID, null);
|
||||
}
|
||||
|
||||
public void SendIMStopTyping(UUID target, UUID session)
|
||||
{
|
||||
if (!loggedIn) return;
|
||||
|
||||
client.Self.InstantMessage(
|
||||
loginOptions.FullName, target, "typing", session, InstantMessageDialog.StopTyping,
|
||||
InstantMessageOnline.Online, client.Self.SimPosition, client.Network.CurrentSim.ID, null);
|
||||
}
|
||||
|
||||
public void Teleport(string sim, Vector3 coordinates)
|
||||
{
|
||||
if (!loggedIn) return;
|
||||
if (teleporting) return;
|
||||
|
||||
TeleportingEventArgs ea = new TeleportingEventArgs(sim, coordinates);
|
||||
OnTeleporting(ea);
|
||||
if (ea.Cancel) return;
|
||||
|
||||
teleporting = true;
|
||||
client.Self.Teleport(sim, coordinates);
|
||||
}
|
||||
|
||||
public bool IsLoggingIn
|
||||
{
|
||||
get { return loggingIn; }
|
||||
}
|
||||
|
||||
public bool IsLoggedIn
|
||||
{
|
||||
get { return loggedIn; }
|
||||
}
|
||||
|
||||
public bool IsTeleporting
|
||||
{
|
||||
get { return teleporting; }
|
||||
}
|
||||
|
||||
public LoginOptions LoginOptions
|
||||
{
|
||||
get { return loginOptions; }
|
||||
set { loginOptions = value; }
|
||||
}
|
||||
|
||||
//public Control NetcomSync
|
||||
//{
|
||||
// get { return netcomSync; }
|
||||
// set { netcomSync = value; }
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace Raindrop.Netcom
|
||||
{
|
||||
public partial class RaindropNetcom
|
||||
{
|
||||
// For the NetcomSync stuff
|
||||
private delegate void OnClientLoginRaise(LoginProgressEventArgs e);
|
||||
private delegate void OnClientLogoutRaise(EventArgs e);
|
||||
private delegate void OnClientDisconnectRaise(DisconnectedEventArgs e);
|
||||
private delegate void OnChatRaise(ChatEventArgs e);
|
||||
private delegate void OnInstantMessageRaise(InstantMessageEventArgs e);
|
||||
private delegate void OnAlertMessageRaise(AlertMessageEventArgs e);
|
||||
private delegate void OnMoneyBalanceRaise(BalanceEventArgs e);
|
||||
private delegate void OnTeleportStatusRaise(TeleportEventArgs e);
|
||||
|
||||
public event EventHandler<OverrideEventArgs> ClientLoggingIn;
|
||||
public event EventHandler<LoginProgressEventArgs> ClientLoginStatus;
|
||||
public event EventHandler<OverrideEventArgs> ClientLoggingOut;
|
||||
public event EventHandler ClientLoggedOut;
|
||||
public event EventHandler<DisconnectedEventArgs> ClientDisconnected;
|
||||
public event EventHandler<ChatEventArgs> ChatReceived;
|
||||
public event EventHandler<ChatSentEventArgs> ChatSent;
|
||||
public event EventHandler<InstantMessageEventArgs> InstantMessageReceived;
|
||||
public event EventHandler<InstantMessageSentEventArgs> InstantMessageSent;
|
||||
public event EventHandler<TeleportingEventArgs> Teleporting;
|
||||
public event EventHandler<TeleportEventArgs> TeleportStatusChanged;
|
||||
public event EventHandler<AlertMessageEventArgs> AlertMessageReceived;
|
||||
public event EventHandler<BalanceEventArgs> MoneyBalanceUpdated;
|
||||
|
||||
protected virtual void OnClientLoggingIn(OverrideEventArgs e)
|
||||
{
|
||||
if (ClientLoggingIn != null) ClientLoggingIn(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnClientLoginStatus(LoginProgressEventArgs e)
|
||||
{
|
||||
if (ClientLoginStatus != null) ClientLoginStatus(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnClientLoggingOut(OverrideEventArgs e)
|
||||
{
|
||||
if (ClientLoggingOut != null) ClientLoggingOut(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnClientLoggedOut(EventArgs e)
|
||||
{
|
||||
if (ClientLoggedOut != null) ClientLoggedOut(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnClientDisconnected(DisconnectedEventArgs e)
|
||||
{
|
||||
if (ClientDisconnected != null) ClientDisconnected(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnChatReceived(ChatEventArgs e)
|
||||
{
|
||||
if (ChatReceived != null) ChatReceived(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnChatSent(ChatSentEventArgs e)
|
||||
{
|
||||
if (ChatSent != null) ChatSent(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnInstantMessageReceived(InstantMessageEventArgs e)
|
||||
{
|
||||
if (InstantMessageReceived != null) InstantMessageReceived(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnInstantMessageSent(InstantMessageSentEventArgs e)
|
||||
{
|
||||
if (InstantMessageSent != null) InstantMessageSent(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnTeleporting(TeleportingEventArgs e)
|
||||
{
|
||||
if (Teleporting != null) Teleporting(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnTeleportStatusChanged(TeleportEventArgs e)
|
||||
{
|
||||
if (TeleportStatusChanged != null) TeleportStatusChanged(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnAlertMessageReceived(AlertMessageEventArgs e)
|
||||
{
|
||||
if (AlertMessageReceived != null) AlertMessageReceived(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnMoneyBalanceUpdated(BalanceEventArgs e)
|
||||
{
|
||||
if (MoneyBalanceUpdated != null) MoneyBalanceUpdated(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
using System;
|
||||
|
||||
namespace Raindrop.Netcom
|
||||
{
|
||||
public class OverrideEventArgs : EventArgs
|
||||
{
|
||||
private bool _cancel = false;
|
||||
|
||||
public OverrideEventArgs()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public OverrideEventArgs(bool cancel)
|
||||
{
|
||||
_cancel = cancel;
|
||||
}
|
||||
|
||||
public bool Cancel
|
||||
{
|
||||
get { return _cancel; }
|
||||
set { _cancel = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
using System;
|
||||
|
||||
namespace Raindrop.Netcom
|
||||
{
|
||||
public class StartLocationParser
|
||||
{
|
||||
private string location;
|
||||
|
||||
public StartLocationParser(string location)
|
||||
{
|
||||
if (location == null) throw new Exception("Location cannot be null.");
|
||||
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
private string GetSim(string location)
|
||||
{
|
||||
if (!location.Contains("/")) return location;
|
||||
|
||||
string[] locSplit = location.Split('/');
|
||||
return locSplit[0];
|
||||
}
|
||||
|
||||
private int GetX(string location)
|
||||
{
|
||||
if (!location.Contains("/")) return 128;
|
||||
|
||||
string[] locSplit = location.Split('/');
|
||||
|
||||
int returnResult;
|
||||
bool stringToInt = int.TryParse(locSplit[1], out returnResult);
|
||||
|
||||
if (stringToInt)
|
||||
return returnResult;
|
||||
else
|
||||
return 128;
|
||||
}
|
||||
|
||||
private int GetY(string location)
|
||||
{
|
||||
if (!location.Contains("/")) return 128;
|
||||
|
||||
string[] locSplit = location.Split('/');
|
||||
|
||||
if (locSplit.Length > 2)
|
||||
{
|
||||
int returnResult;
|
||||
bool stringToInt = int.TryParse(locSplit[2], out returnResult);
|
||||
|
||||
if (stringToInt)
|
||||
return returnResult;
|
||||
}
|
||||
|
||||
return 128;
|
||||
}
|
||||
|
||||
private int GetZ(string location)
|
||||
{
|
||||
if (!location.Contains("/")) return 0;
|
||||
|
||||
string[] locSplit = location.Split('/');
|
||||
|
||||
if (locSplit.Length > 3)
|
||||
{
|
||||
int returnResult;
|
||||
bool stringToInt = int.TryParse(locSplit[3], out returnResult);
|
||||
|
||||
if (stringToInt)
|
||||
return returnResult;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public string Sim
|
||||
{
|
||||
get { return GetSim(location); }
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get { return GetX(location); }
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get { return GetY(location); }
|
||||
}
|
||||
|
||||
public int Z
|
||||
{
|
||||
get { return GetZ(location); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace Raindrop.Netcom
|
||||
{
|
||||
public class TeleportingEventArgs : OverrideEventArgs
|
||||
{
|
||||
private string _sim;
|
||||
private Vector3 _coordinates;
|
||||
|
||||
public TeleportingEventArgs(string sim, Vector3 coordinates) : base()
|
||||
{
|
||||
_sim = sim;
|
||||
_coordinates = coordinates;
|
||||
}
|
||||
|
||||
public string SimName
|
||||
{
|
||||
get { return _sim; }
|
||||
}
|
||||
|
||||
public Vector3 Coordinates
|
||||
{
|
||||
get { return _coordinates; }
|
||||
}
|
||||
}
|
||||
}
|
||||
+224
-170
@@ -1,213 +1,267 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using LibreMetaverse;
|
||||
using OpenMetaverse;
|
||||
//using System.Collections;
|
||||
//using System.Collections.Generic;
|
||||
//using UnityEngine;
|
||||
//using LibreMetaverse;
|
||||
//using OpenMetaverse;
|
||||
//using DisruptorUnity3d;
|
||||
|
||||
//namespace Raindrop
|
||||
//{
|
||||
// //implements (actually, composites) the gridclient
|
||||
// public class RaindropClient //todo: decouple unity, maybe.
|
||||
// {
|
||||
|
||||
// //static readonly RingBuffer<int> Queue = new RingBuffer<int>(1000);
|
||||
|
||||
|
||||
namespace Raindrop
|
||||
{
|
||||
//implements (actually, composites) the gridclient
|
||||
public class RaindropClient
|
||||
{
|
||||
//todo: internal eventbus for raindrop subsystems comms; include ui?
|
||||
public event Notify LoginCompleted;
|
||||
public event Notify LoginFailed;
|
||||
// //todo: internal eventbus for raindrop subsystems comms; include ui?
|
||||
// public event Notify LoginCompleted;
|
||||
// public event Notify LoginFailed;
|
||||
|
||||
public GridClient Client;
|
||||
// public GridClient Client;
|
||||
|
||||
public enum RaindropState
|
||||
{
|
||||
intialise,
|
||||
connected,
|
||||
disconnected
|
||||
// public enum RaindropState
|
||||
// {
|
||||
// intialise,
|
||||
// connected,
|
||||
// disconnected
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
private RaindropState clientstate;
|
||||
// private RaindropState clientstate;
|
||||
|
||||
private string Username { get; set; }
|
||||
private string Password { get; set; }
|
||||
public string configdatapath { get; private set; }
|
||||
// private readonly object eventLock = new object();
|
||||
// private List<UUID> avatars_in_sim = new List<UUID>();
|
||||
// private Global globalRef;
|
||||
|
||||
public RaindropClient()
|
||||
{
|
||||
clientstate = RaindropState.intialise;
|
||||
// private string Username { get; set; }
|
||||
// private string Password { get; set; }
|
||||
// public string configdatapath { get; private set; }
|
||||
|
||||
Client = new GridClient(); // instantiates the GridClient class
|
||||
// to the global Client object
|
||||
// public RaindropClient(string appdatapath, Global global)
|
||||
// {
|
||||
// globalRef = global;
|
||||
|
||||
// //ensure you set the app path first, so that the Setting static prop gets updated before construction of the client instance.
|
||||
// setConfigPath(appdatapath);
|
||||
|
||||
Client.Settings.USE_LLSD_LOGIN = true;
|
||||
const string AGNI_LOGIN_SERVER = "https://login.agni.lindenlab.com/cgi-bin/login.cgi";
|
||||
Client.Settings.LOGIN_SERVER = AGNI_LOGIN_SERVER;
|
||||
// clientstate = RaindropState.intialise;
|
||||
|
||||
// Client = new GridClient(); // instantiates the GridClient class
|
||||
// // to the global Client object
|
||||
|
||||
|
||||
// Client.Settings.USE_LLSD_LOGIN = true;
|
||||
// const string AGNI_LOGIN_SERVER = "https://login.agni.lindenlab.com/cgi-bin/login.cgi";
|
||||
// Client.Settings.LOGIN_SERVER = AGNI_LOGIN_SERVER;
|
||||
|
||||
|
||||
|
||||
// RegisterClientEvents();
|
||||
// }
|
||||
|
||||
RegisterClientEvents();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void RegisterClientEvents()
|
||||
{
|
||||
////register events
|
||||
//Client.Appearance.AgentWearablesReply += Appearance_AgentWearablesReply;
|
||||
//Client.Appearance.AppearanceSet += Appearance_AppearanceSet;
|
||||
//Client.Appearance.CachedBakesReply += Appearance_CachedBakesReply;
|
||||
//Client.Appearance.RebakeAvatarRequested += Appearance_RebakeAvatarRequested;
|
||||
// private void RegisterClientEvents()
|
||||
// {
|
||||
// ////register events
|
||||
// //Client.Appearance.AgentWearablesReply += Appearance_AgentWearablesReply;
|
||||
// //Client.Appearance.AppearanceSet += Appearance_AppearanceSet;
|
||||
// //Client.Appearance.CachedBakesReply += Appearance_CachedBakesReply;
|
||||
// //Client.Appearance.RebakeAvatarRequested += Appearance_RebakeAvatarRequested;
|
||||
|
||||
////local chat
|
||||
Client.Self.ChatFromSimulator += Self_ChatFromSimulator;
|
||||
// ////local chat
|
||||
// Client.Self.ChatFromSimulator += Self_ChatFromSimulator;
|
||||
|
||||
////user connected/disconnected
|
||||
Client.Network.Disconnected += Network_Disconnected;
|
||||
Client.Network.LoginProgress += Network_LoginProgress;
|
||||
// ////user connected/disconnected
|
||||
// Client.Network.Disconnected += Network_Disconnected;
|
||||
// Client.Network.LoginProgress += Network_LoginProgress;
|
||||
|
||||
////grid location update
|
||||
Client.Grid.CoarseLocationUpdate += Grid_CoarseLocationUpdate;
|
||||
Client.Network.SimChanged += Network_SimChanged;
|
||||
// ////grid location update
|
||||
// Client.Grid.CoarseLocationUpdate += Grid_CoarseLocationUpdate;
|
||||
// Client.Network.SimChanged += Network_SimChanged;
|
||||
|
||||
//log
|
||||
OpenMetaverse.Logger.OnLogMessage += Logger_OnLogMessage;
|
||||
}
|
||||
// //log
|
||||
// OpenMetaverse.Logger.OnLogMessage += Logger_OnLogMessage;
|
||||
// }
|
||||
|
||||
private void Logger_OnLogMessage(object message, Helpers.LogLevel level)
|
||||
{
|
||||
if (level == Helpers.LogLevel.Debug)
|
||||
{
|
||||
Debug.Log(message);
|
||||
}
|
||||
else if (level == Helpers.LogLevel.Error)
|
||||
{
|
||||
Debug.LogError(message);
|
||||
}
|
||||
else if (level == Helpers.LogLevel.Info)
|
||||
{
|
||||
Debug.Log(message);
|
||||
}
|
||||
else if (level == Helpers.LogLevel.Warning)
|
||||
{
|
||||
Debug.LogWarning(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError(message);
|
||||
}
|
||||
}
|
||||
//private void Logger_OnLogMessage(object message, Helpers.LogLevel level)
|
||||
//{
|
||||
// if (level == Helpers.LogLevel.Debug)
|
||||
// {
|
||||
// Debug.Log(message);
|
||||
// }
|
||||
// else if (level == Helpers.LogLevel.Error)
|
||||
// {
|
||||
// Debug.LogError(message);
|
||||
// }
|
||||
// else if (level == Helpers.LogLevel.Info)
|
||||
// {
|
||||
// Debug.Log(message);
|
||||
// }
|
||||
// else if (level == Helpers.LogLevel.Warning)
|
||||
// {
|
||||
// Debug.LogWarning(message);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Debug.LogError(message);
|
||||
// }
|
||||
//}
|
||||
|
||||
internal void setConfigPath(string app_data_Path)
|
||||
{
|
||||
this.configdatapath = app_data_Path;
|
||||
// internal void setConfigPath(string app_data_Path)
|
||||
// {
|
||||
// this.configdatapath = app_data_Path;
|
||||
// Settings.RESOURCE_DIR = app_data_Path;
|
||||
// //Client.Settings.ASSET_CACHE_DIR = app_data_Path + "/cache";
|
||||
// }
|
||||
|
||||
}
|
||||
// private void Network_SimChanged(object sender, SimChangedEventArgs e)
|
||||
// {
|
||||
// Debug.Log("Sim was changed.");
|
||||
// }
|
||||
|
||||
private void Network_SimChanged(object sender, SimChangedEventArgs e)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
private void Grid_CoarseLocationUpdate(object sender, CoarseLocationUpdateEventArgs e)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
private void Network_LoginProgress(object sender, LoginProgressEventArgs e)
|
||||
{
|
||||
if (e.Status == LoginStatus.Failed)
|
||||
{
|
||||
LoginFailed?.Invoke(); //raise event.
|
||||
Debug.LogWarning("logging in failed. \n Message: " + e.Message + "fail reason: " + e.FailReason);
|
||||
}
|
||||
else if (e.Status == LoginStatus.Success)
|
||||
{
|
||||
this.clientstate = RaindropState.connected;
|
||||
|
||||
LoginCompleted?.Invoke(); //raise event.
|
||||
|
||||
Disk.SaveLoad.saveCred(Username,Password, configdatapath);
|
||||
// private void Grid_CoarseLocationUpdate(object sender, CoarseLocationUpdateEventArgs e)
|
||||
// {
|
||||
|
||||
|
||||
Debug.Log("logging in success. \n Message: " + e.Message);
|
||||
// lock (eventLock)
|
||||
// {
|
||||
|
||||
// if (e.Simulator == Client.Network.CurrentSim)
|
||||
// {
|
||||
|
||||
|
||||
// foreach (var each in e.NewEntries)
|
||||
// {
|
||||
// avatars_in_sim.Add(each);
|
||||
// }
|
||||
|
||||
// foreach (var each in e.RemovedEntries)
|
||||
// {
|
||||
// if (avatars_in_sim.Contains(each))
|
||||
// {
|
||||
// avatars_in_sim.Remove(each);
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (e.NewEntries.Count != 0 || e.RemovedEntries.Count != 0)
|
||||
// {
|
||||
// Debug.Log("Avatars: " + avatars_in_sim.ToString());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// private void Network_LoginProgress(object sender, LoginProgressEventArgs e)
|
||||
// {
|
||||
// if (e.Status == LoginStatus.Failed)
|
||||
// {
|
||||
// LoginFailed?.Invoke(); //raise event.
|
||||
// Debug.LogWarning("logging in failed. \n Message: " + e.Message + "fail reason: " + e.FailReason);
|
||||
// globalRef.RaindropVM.canvasManager.pushModal(); //error mah boi
|
||||
// }
|
||||
// else if (e.Status == LoginStatus.Success)
|
||||
// {
|
||||
// this.clientstate = RaindropState.connected;
|
||||
|
||||
// //LoginCompleted?.Invoke(); //raise event.
|
||||
|
||||
// UnityMainThreadDispatcher.Instance().Enqueue(() =>
|
||||
// {
|
||||
// Debug.Log("This is executed from the main thread");
|
||||
// Debug.Log("Login success ui update");
|
||||
// globalRef.RaindropVM.canvasManager.popCanvas(); //remove login panel from sight.
|
||||
// globalRef.RaindropVM.canvasManager.pushCanvas(CanvasType.Game);
|
||||
// });
|
||||
|
||||
// Disk.SaveLoad.saveCred(Username,Password, configdatapath);
|
||||
|
||||
|
||||
// Debug.Log("logging in success. \n Message: " + e.Message);
|
||||
|
||||
}
|
||||
else if (e.Status == LoginStatus.ConnectingToLogin)
|
||||
{
|
||||
Debug.Log("ConnectingToLogin. \n Message: " + e.Message);
|
||||
// }
|
||||
// else if (e.Status == LoginStatus.ConnectingToLogin)
|
||||
// {
|
||||
// //Debug.Log("ConnectingToLogin. \n Message: " + e.Message);
|
||||
|
||||
}
|
||||
else if (e.Status == LoginStatus.ConnectingToSim)
|
||||
{
|
||||
Debug.Log("ConnectingToSim. \n Message: " + e.Message);
|
||||
// }
|
||||
// else if (e.Status == LoginStatus.ConnectingToSim)
|
||||
// {
|
||||
// Debug.Log("ConnectingToSim. \n Message: " + e.Message);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("logging in not-supported. \n status type: " + e.Status.ToString() + "\n Message: " + e.Message);
|
||||
}
|
||||
}
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Debug.LogError("logging in not-supported. \n status type: " + e.Status.ToString() + "\n Message: " + e.Message);
|
||||
// }
|
||||
// }
|
||||
|
||||
private void Network_Disconnected(object sender, DisconnectedEventArgs e)
|
||||
{
|
||||
Debug.Log("Disconnected!");
|
||||
}
|
||||
// private void Network_Disconnected(object sender, DisconnectedEventArgs e)
|
||||
// {
|
||||
// Debug.Log("Disconnected!");
|
||||
// }
|
||||
|
||||
private void Self_ChatFromSimulator(object sender, ChatEventArgs e)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
// private void Self_ChatFromSimulator(object sender, ChatEventArgs e)
|
||||
// {
|
||||
// Debug.Log("Chat: " + e.FromName+ " : " + e.Message);
|
||||
|
||||
//private void Appearance_RebakeAvatarRequested(object sender, RebakeAvatarTexturesEventArgs e)
|
||||
//{
|
||||
// throw new System.NotImplementedException();
|
||||
//}
|
||||
// }
|
||||
|
||||
//private void Appearance_CachedBakesReply(object sender, AgentCachedBakesReplyEventArgs e)
|
||||
//{
|
||||
// throw new System.NotImplementedException();
|
||||
//}
|
||||
// //private void Appearance_RebakeAvatarRequested(object sender, RebakeAvatarTexturesEventArgs e)
|
||||
// //{
|
||||
// // throw new System.NotImplementedException();
|
||||
// //}
|
||||
|
||||
//private void Appearance_AppearanceSet(object sender, AppearanceSetEventArgs e)
|
||||
//{
|
||||
// throw new System.NotImplementedException();
|
||||
//}
|
||||
// //private void Appearance_CachedBakesReply(object sender, AgentCachedBakesReplyEventArgs e)
|
||||
// //{
|
||||
// // throw new System.NotImplementedException();
|
||||
// //}
|
||||
|
||||
//private void Appearance_AgentWearablesReply(object sender, AgentWearablesReplyEventArgs e)
|
||||
//{
|
||||
// throw new System.NotImplementedException();
|
||||
//}
|
||||
// //private void Appearance_AppearanceSet(object sender, AppearanceSetEventArgs e)
|
||||
// //{
|
||||
// // throw new System.NotImplementedException();
|
||||
// //}
|
||||
|
||||
//connects to SL. username is either format; ie: "firstname lastname" or "Jaken69" are both compaitble.
|
||||
public void connectTo(string username, string password)
|
||||
{
|
||||
// //private void Appearance_AgentWearablesReply(object sender, AgentWearablesReplyEventArgs e)
|
||||
// //{
|
||||
// // throw new System.NotImplementedException();
|
||||
// //}
|
||||
|
||||
Username = username;
|
||||
Password = password;
|
||||
// //connects to SL. username is either format; ie: "firstname lastname" or "Jaken69" are both compaitble.
|
||||
// public void connectTo(string username, string password)
|
||||
// {
|
||||
|
||||
// Login to Simulator
|
||||
string[] _splitname = username.Split();
|
||||
if (_splitname.Length == 1)
|
||||
{
|
||||
var temp = _splitname[0];
|
||||
_splitname = new string[2];
|
||||
_splitname[0] = temp;
|
||||
_splitname[1] = "";
|
||||
}
|
||||
else if (_splitname.Length != 2)
|
||||
{
|
||||
Debug.LogError("username is not 2 words (tip examples of valid usernames: \'Jake69 Resident\' or \'Jake Aabye\')");
|
||||
return;
|
||||
}
|
||||
// Username = username;
|
||||
// Password = password;
|
||||
|
||||
var lp = new LoginParams(Global.MainRaindropInstance.Client, _splitname[0], _splitname[1], password, "raindropviewer@gmail.com", "RaindropViewer_0.1");
|
||||
Debug.Log("attempt login with name1 " + _splitname[0] + " name 2 " + _splitname[1] + " password " + password);
|
||||
Global.MainRaindropInstance.Client.Network.BeginLogin(lp);
|
||||
// // Login to Simulator
|
||||
// string[] _splitname = username.Split();
|
||||
// if (_splitname.Length == 1)
|
||||
// {
|
||||
// var temp = _splitname[0];
|
||||
// _splitname = new string[2];
|
||||
// _splitname[0] = temp;
|
||||
// _splitname[1] = "";
|
||||
// }
|
||||
// else if (_splitname.Length != 2)
|
||||
// {
|
||||
// Debug.LogError("username is not 2 words (tip examples of valid usernames: \'Jake69 Resident\' or \'Jake Aabye\')");
|
||||
// return;
|
||||
// }
|
||||
|
||||
//UnityClient.Client.Network.Login(lp);
|
||||
// Logout of simulator
|
||||
//Client.Network.Logout();
|
||||
// var lp = new LoginParams(Client, _splitname[0], _splitname[1], password, "raindropviewer@gmail.com", "RaindropViewer_0.1");
|
||||
// Debug.Log("attempt login with name1 " + _splitname[0] + " name 2 " + _splitname[1] + " password " + password);
|
||||
// Client.Network.BeginLogin(lp);
|
||||
|
||||
}
|
||||
// //UnityClient.Client.Network.Login(lp);
|
||||
// // Logout of simulator
|
||||
// //Client.Network.Logout();
|
||||
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
// }
|
||||
//}
|
||||
@@ -1,16 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using System.Threading.Tasks;
|
||||
|
||||
namespace Raindrop
|
||||
{
|
||||
public delegate void Notify();
|
||||
//namespace Raindrop
|
||||
//{
|
||||
// public delegate void Notify();
|
||||
|
||||
|
||||
|
||||
class RaindropEvents
|
||||
{
|
||||
}
|
||||
}
|
||||
// class RaindropEvents
|
||||
// {
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -0,0 +1,851 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
//using Radegast.Commands;
|
||||
using Raindrop.Netcom;
|
||||
//using Radegast.Media;
|
||||
using OpenMetaverse;
|
||||
using UnityEngine;
|
||||
using Logger = OpenMetaverse.Logger;
|
||||
|
||||
namespace Raindrop
|
||||
{
|
||||
public class RaindropInstance
|
||||
{
|
||||
#region OnRadegastFormCreated
|
||||
//Actually this event is never subscribed to!
|
||||
//public event Action<RadegastForm> RadegastFormCreated;
|
||||
///// <summary>
|
||||
///// Triggers the RadegastFormCreated event.
|
||||
///// this method is called directly by the 'form' when the UI is loaded. the payload is the actual form - eg: formProfile
|
||||
///// </summary>
|
||||
//public virtual void OnRadegastFormCreated(RadegastForm radForm)
|
||||
//{
|
||||
// if (RadegastFormCreated != null) RadegastFormCreated(radForm);
|
||||
//}
|
||||
#endregion
|
||||
|
||||
private GridClient client;
|
||||
private RaindropNetcom netcom;
|
||||
|
||||
private StateManager state;
|
||||
private string app_data_dir;
|
||||
|
||||
//private frmMain mainForm; //frmMain is a class that inherits RadegastForm. It seems to be the code-behind of the overall UI, that includes the view and buttons.
|
||||
private mainUI mainCanvas;
|
||||
|
||||
// Singleton, there can be only one instance
|
||||
private static RaindropInstance globalInstance = null;
|
||||
public static RaindropInstance GlobalInstance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (globalInstance == null)
|
||||
{
|
||||
globalInstance = new RaindropInstance(new GridClient());
|
||||
}
|
||||
return globalInstance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages retrieving avatar names
|
||||
/// </summary>
|
||||
public NameManager Names { get { return names; } }
|
||||
private NameManager names;
|
||||
|
||||
/// <summary>
|
||||
/// When was Radegast started (UTC)
|
||||
/// </summary>
|
||||
public readonly DateTime StartupTimeUTC;
|
||||
|
||||
/// <summary>
|
||||
/// Time zone of the current world (currently hard coded to US Pacific time)
|
||||
/// </summary>
|
||||
public TimeZoneInfo WordTimeZone;
|
||||
|
||||
private string userDir;
|
||||
/// <summary>
|
||||
/// System (not grid!) user's dir
|
||||
/// </summary>
|
||||
public string UserDir { get { return userDir; } }
|
||||
|
||||
/// <summary>
|
||||
/// Grid client's user dir for settings and logs
|
||||
/// </summary>
|
||||
public string ClientDir
|
||||
{
|
||||
get
|
||||
{
|
||||
if (client != null && client.Self != null && !string.IsNullOrEmpty(client.Self.Name))
|
||||
{
|
||||
return Path.Combine(userDir, client.Self.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Environment.CurrentDirectory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string InventoryCacheFileName { get { return Path.Combine(ClientDir, "inventory.cache"); } }
|
||||
|
||||
private string globalLogFile;
|
||||
public string GlobalLogFile { get { return globalLogFile; } }
|
||||
|
||||
private bool monoRuntime;
|
||||
public bool MonoRuntime { get { return monoRuntime; } }
|
||||
|
||||
private Dictionary<UUID, Group> groups = new Dictionary<UUID, Group>();
|
||||
public Dictionary<UUID, Group> Groups { get { return groups; } }
|
||||
|
||||
private Settings globalSettings;
|
||||
/// <summary>
|
||||
/// Global settings for the entire application
|
||||
/// </summary>
|
||||
public Settings GlobalSettings { get { return globalSettings; } }
|
||||
|
||||
private Settings clientSettings;
|
||||
/// <summary>
|
||||
/// Per client settings
|
||||
/// </summary>
|
||||
public Settings ClientSettings { get { return clientSettings; } }
|
||||
|
||||
public const string INCOMPLETE_NAME = "Loading...";
|
||||
|
||||
public readonly bool advancedDebugging = false;
|
||||
|
||||
//private PluginManager pluginManager;
|
||||
///// <summary> Handles loading plugins and scripts</summary>
|
||||
//public PluginManager PluginManager { get { return pluginManager; } }
|
||||
|
||||
//private MediaManager mediaManager;
|
||||
///// <summary>
|
||||
///// Radegast media manager for playing streams and in world sounds
|
||||
///// </summary>
|
||||
//public MediaManager MediaManager { get { return mediaManager; } }
|
||||
|
||||
|
||||
//private CommandsManager commandsManager;
|
||||
///// <summary>
|
||||
///// Radegast command manager for executing textual console commands
|
||||
///// </summary>
|
||||
//public CommandsManager CommandsManager { get { return commandsManager; } }
|
||||
|
||||
/// <summary>
|
||||
/// Radegast ContextAction manager for context sensitive actions
|
||||
/// </summary>
|
||||
//public ContextActionsManager ContextActionManager { get; private set; }
|
||||
|
||||
private RaindropMovement movement;
|
||||
/// <summary>
|
||||
/// Allows key emulation for moving avatar around
|
||||
/// </summary>
|
||||
public RaindropMovement Movement { get { return movement; } }
|
||||
|
||||
//private InventoryClipboard inventoryClipboard;
|
||||
///// <summary>
|
||||
///// The last item that was cut or copied in the inventory, used for pasting
|
||||
///// in a different place on the inventory, or other places like profile
|
||||
///// that allow sending copied inventory items
|
||||
///// </summary>
|
||||
//public InventoryClipboard InventoryClipboard
|
||||
//{
|
||||
// get { return inventoryClipboard; }
|
||||
// set
|
||||
// {
|
||||
// inventoryClipboard = value;
|
||||
// OnInventoryClipboardUpdated(EventArgs.Empty);
|
||||
// }
|
||||
//}
|
||||
|
||||
//private RLVManager rlv;
|
||||
|
||||
///// <summary>
|
||||
///// Manager for RLV functionality
|
||||
///// </summary>
|
||||
//public RLVManager RLV { get { return rlv; } }
|
||||
|
||||
private GridManager gridManager;
|
||||
/// <summary>Manages default params for different grids</summary>
|
||||
public GridManager GridManger { get { return gridManager; } }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Current Outfit Folder (appearnce) manager
|
||||
/// </summary>
|
||||
public CurrentOutfitFolder COF;
|
||||
|
||||
/// <summary>
|
||||
/// Did we report crash to the grid login service
|
||||
/// </summary>
|
||||
public bool ReportedCrash = false;
|
||||
|
||||
private string CrashMarkerFileName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(UserDir, "crash_marker");
|
||||
}
|
||||
}
|
||||
|
||||
#region Events
|
||||
|
||||
#region ClientChanged event
|
||||
/// <summary>The event subscribers, null of no subscribers</summary>
|
||||
private EventHandler<ClientChangedEventArgs> m_ClientChanged;
|
||||
|
||||
///<summary>Raises the ClientChanged Event</summary>
|
||||
/// <param name="e">A ClientChangedEventArgs object containing
|
||||
/// the old and the new client</param>
|
||||
protected virtual void OnClientChanged(ClientChangedEventArgs e)
|
||||
{
|
||||
EventHandler<ClientChangedEventArgs> handler = m_ClientChanged;
|
||||
if (handler != null)
|
||||
handler(this, e);
|
||||
}
|
||||
|
||||
/// <summary>Thread sync lock object</summary>
|
||||
private readonly object m_ClientChangedLock = new object();
|
||||
|
||||
/// <summary>Raised when the GridClient object in the main Radegast instance is changed</summary>
|
||||
public event EventHandler<ClientChangedEventArgs> ClientChanged
|
||||
{
|
||||
add { lock (m_ClientChangedLock) { m_ClientChanged += value; } }
|
||||
remove { lock (m_ClientChangedLock) { m_ClientChanged -= value; } }
|
||||
}
|
||||
#endregion ClientChanged event
|
||||
|
||||
#region InventoryClipboardUpdated event
|
||||
/// <summary>The event subscribers, null of no subscribers</summary>
|
||||
private EventHandler<EventArgs> m_InventoryClipboardUpdated;
|
||||
|
||||
///<summary>Raises the InventoryClipboardUpdated Event</summary>
|
||||
/// <param name="e">A EventArgs object containing
|
||||
/// the old and the new client</param>
|
||||
protected virtual void OnInventoryClipboardUpdated(EventArgs e)
|
||||
{
|
||||
EventHandler<EventArgs> handler = m_InventoryClipboardUpdated;
|
||||
if (handler != null)
|
||||
handler(this, e);
|
||||
}
|
||||
|
||||
/// <summary>Thread sync lock object</summary>
|
||||
private readonly object m_InventoryClipboardUpdatedLock = new object();
|
||||
|
||||
/// <summary>Raised when the GridClient object in the main Radegast instance is changed</summary>
|
||||
public event EventHandler<EventArgs> InventoryClipboardUpdated
|
||||
{
|
||||
add { lock (m_InventoryClipboardUpdatedLock) { m_InventoryClipboardUpdated += value; } }
|
||||
remove { lock (m_InventoryClipboardUpdatedLock) { m_InventoryClipboardUpdated -= value; } }
|
||||
}
|
||||
#endregion InventoryClipboardUpdated event
|
||||
|
||||
|
||||
#endregion Events
|
||||
|
||||
public RaindropInstance(GridClient client0)
|
||||
{
|
||||
// incase something else calls GlobalInstance while we are loading
|
||||
globalInstance = this;
|
||||
|
||||
app_data_dir = Application.persistentDataPath;
|
||||
|
||||
//if (!System.Diagnostics.Debugger.IsAttached)
|
||||
//{
|
||||
// Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
|
||||
// Application.ThreadException += HandleThreadException;
|
||||
//}
|
||||
|
||||
client = client0;
|
||||
|
||||
// Initialize current time zone, and mark when we started
|
||||
GetWorldTimeZone();
|
||||
StartupTimeUTC = DateTime.UtcNow;
|
||||
|
||||
// Are we running mono?
|
||||
monoRuntime = Type.GetType("Mono.Runtime") != null;
|
||||
|
||||
//Keyboard = new Keyboard();
|
||||
//Application.AddMessageFilter(Keyboard);
|
||||
|
||||
netcom = new RaindropNetcom(this);
|
||||
state = new StateManager(this);
|
||||
//mediaManager = new MediaManager(this);
|
||||
//commandsManager = new CommandsManager(this);
|
||||
//ContextActionManager = new ContextActionsManager(this);
|
||||
//RegisterContextActions();
|
||||
movement = new RaindropMovement(this);
|
||||
|
||||
InitializeLoggingAndConfig();
|
||||
InitializeClient(client);
|
||||
|
||||
//rlv = new RLVManager(this);
|
||||
gridManager = new GridManager();
|
||||
gridManager.LoadGrids(app_data_dir);
|
||||
|
||||
names = new NameManager(this);
|
||||
COF = new CurrentOutfitFolder(this);
|
||||
|
||||
mainCanvas = new mainUI(this);
|
||||
//mainCanvas.InitializeControls();
|
||||
|
||||
//mainCanvas.Load += new EventHandler(mainForm_Load);
|
||||
//pluginManager = new PluginManager(this);
|
||||
//pluginManager.ScanAndLoadPlugins();
|
||||
}
|
||||
|
||||
private void InitializeClient(GridClient client)
|
||||
{
|
||||
client.Settings.MULTIPLE_SIMS = false;
|
||||
|
||||
client.Settings.USE_INTERPOLATION_TIMER = false;
|
||||
client.Settings.ALWAYS_REQUEST_OBJECTS = true;
|
||||
client.Settings.ALWAYS_DECODE_OBJECTS = true;
|
||||
client.Settings.OBJECT_TRACKING = true;
|
||||
client.Settings.ENABLE_SIMSTATS = true;
|
||||
client.Settings.FETCH_MISSING_INVENTORY = true;
|
||||
client.Settings.SEND_AGENT_THROTTLE = true;
|
||||
client.Settings.SEND_AGENT_UPDATES = true;
|
||||
client.Settings.STORE_LAND_PATCHES = true;
|
||||
|
||||
client.Settings.USE_ASSET_CACHE = true;
|
||||
client.Settings.ASSET_CACHE_DIR = Path.Combine(userDir, "cache");
|
||||
client.Assets.Cache.AutoPruneEnabled = false;
|
||||
client.Assets.Cache.ComputeAssetCacheFilename = ComputeCacheName;
|
||||
|
||||
client.Throttle.Total = 5000000f;
|
||||
client.Settings.THROTTLE_OUTGOING_PACKETS = false;
|
||||
client.Settings.LOGIN_TIMEOUT = 120 * 1000;
|
||||
client.Settings.SIMULATOR_TIMEOUT = 180 * 1000;
|
||||
client.Settings.MAX_CONCURRENT_TEXTURE_DOWNLOADS = 20;
|
||||
|
||||
client.Self.Movement.AutoResetControls = false;
|
||||
client.Self.Movement.UpdateInterval = 250;
|
||||
|
||||
RegisterClientEvents(client);
|
||||
SetClientTag();
|
||||
}
|
||||
|
||||
public string ComputeCacheName(string cacheDir, UUID assetID)
|
||||
{
|
||||
string fileName = assetID.ToString();
|
||||
string dir = cacheDir
|
||||
+ Path.DirectorySeparatorChar + fileName.Substring(0, 1)
|
||||
+ Path.DirectorySeparatorChar + fileName.Substring(1, 1);
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Path.Combine(cacheDir, fileName);
|
||||
}
|
||||
return Path.Combine(dir, fileName);
|
||||
}
|
||||
|
||||
private void RegisterClientEvents(GridClient client)
|
||||
{
|
||||
//log
|
||||
OpenMetaverse.Logger.OnLogMessage += Logger_OnLogMessage;
|
||||
|
||||
client.Groups.CurrentGroups += new EventHandler<CurrentGroupsEventArgs>(Groups_CurrentGroups);
|
||||
client.Groups.GroupLeaveReply += new EventHandler<GroupOperationEventArgs>(Groups_GroupsChanged);
|
||||
client.Groups.GroupDropped += new EventHandler<GroupDroppedEventArgs>(Groups_GroupsChanged);
|
||||
client.Groups.GroupJoinedReply += new EventHandler<GroupOperationEventArgs>(Groups_GroupsChanged);
|
||||
if (netcom != null)
|
||||
netcom.ClientConnected += new EventHandler<EventArgs>(netcom_ClientConnected);
|
||||
client.Network.LoginProgress += new EventHandler<LoginProgressEventArgs>(Network_LoginProgress);
|
||||
}
|
||||
|
||||
private void UnregisterClientEvents(GridClient client)
|
||||
{
|
||||
client.Groups.CurrentGroups -= new EventHandler<CurrentGroupsEventArgs>(Groups_CurrentGroups);
|
||||
client.Groups.GroupLeaveReply -= new EventHandler<GroupOperationEventArgs>(Groups_GroupsChanged);
|
||||
client.Groups.GroupDropped -= new EventHandler<GroupDroppedEventArgs>(Groups_GroupsChanged);
|
||||
client.Groups.GroupJoinedReply -= new EventHandler<GroupOperationEventArgs>(Groups_GroupsChanged);
|
||||
if (netcom != null)
|
||||
netcom.ClientConnected -= new EventHandler<EventArgs>(netcom_ClientConnected);
|
||||
client.Network.LoginProgress -= new EventHandler<LoginProgressEventArgs>(Network_LoginProgress);
|
||||
}
|
||||
|
||||
public void SetClientTag()
|
||||
{
|
||||
if (GlobalSettings["send_rad_client_tag"])
|
||||
{
|
||||
client.Settings.CLIENT_IDENTIFICATION_TAG = new UUID("b748af88-58e2-995b-cf26-9486dea8e830");
|
||||
}
|
||||
else
|
||||
{
|
||||
client.Settings.CLIENT_IDENTIFICATION_TAG = UUID.Zero;
|
||||
}
|
||||
}
|
||||
private void GetWorldTimeZone()
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (TimeZoneInfo tz in TimeZoneInfo.GetSystemTimeZones())
|
||||
{
|
||||
if (tz.Id == "Pacific Standard Time" || tz.Id == "America/Los_Angeles")
|
||||
{
|
||||
WordTimeZone = tz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
public DateTime GetWorldTime()
|
||||
{
|
||||
DateTime now;
|
||||
|
||||
try
|
||||
{
|
||||
if (WordTimeZone != null)
|
||||
now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, WordTimeZone);
|
||||
else
|
||||
now = DateTime.UtcNow.AddHours(-7);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
now = DateTime.UtcNow.AddHours(-7);
|
||||
}
|
||||
|
||||
return now;
|
||||
}
|
||||
|
||||
|
||||
public void Reconnect()
|
||||
{
|
||||
//TabConsole.DisplayNotificationInChat("Attempting to reconnect...", ChatBufferTextStyle.StatusDarkBlue);
|
||||
Logger.Log("Attempting to reconnect", Helpers.LogLevel.Info, client);
|
||||
GridClient oldClient = client;
|
||||
client = new GridClient();
|
||||
UnregisterClientEvents(oldClient);
|
||||
InitializeClient(client);
|
||||
OnClientChanged(new ClientChangedEventArgs(oldClient, client));
|
||||
netcom.Login();
|
||||
}
|
||||
|
||||
public void CleanUp()
|
||||
{
|
||||
MarkEndExecution();
|
||||
|
||||
if (COF != null)
|
||||
{
|
||||
COF.Dispose();
|
||||
COF = null;
|
||||
}
|
||||
|
||||
if (names != null)
|
||||
{
|
||||
names.Dispose();
|
||||
names = null;
|
||||
}
|
||||
|
||||
if (gridManager != null)
|
||||
{
|
||||
gridManager.Dispose();
|
||||
gridManager = null;
|
||||
}
|
||||
|
||||
//if (rlv != null)
|
||||
//{
|
||||
// rlv.Dispose();
|
||||
// rlv = null;
|
||||
//}
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
UnregisterClientEvents(client);
|
||||
}
|
||||
|
||||
//if (pluginManager != null)
|
||||
//{
|
||||
// pluginManager.Dispose();
|
||||
// pluginManager = null;
|
||||
//}
|
||||
|
||||
if (movement != null)
|
||||
{
|
||||
movement.Dispose();
|
||||
movement = null;
|
||||
}
|
||||
//if (commandsManager != null)
|
||||
//{
|
||||
// commandsManager.Dispose();
|
||||
// commandsManager = null;
|
||||
//}
|
||||
//if (ContextActionManager != null)
|
||||
//{
|
||||
// ContextActionManager.Dispose();
|
||||
// ContextActionManager = null;
|
||||
//}
|
||||
//if (mediaManager != null)
|
||||
//{
|
||||
// mediaManager.Dispose();
|
||||
// mediaManager = null;
|
||||
//}
|
||||
if (state != null)
|
||||
{
|
||||
state.Dispose();
|
||||
state = null;
|
||||
}
|
||||
if (netcom != null)
|
||||
{
|
||||
netcom.Dispose();
|
||||
netcom = null;
|
||||
}
|
||||
//if (mainCanvas != null)
|
||||
//{
|
||||
// mainCanvas.Load -= new EventHandler(mainForm_Load);
|
||||
//}
|
||||
Logger.Log("RaindropInstance finished cleaning up.", Helpers.LogLevel.Debug);
|
||||
}
|
||||
|
||||
void mainForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
//pluginManager.StartPlugins();
|
||||
}
|
||||
|
||||
void netcom_ClientConnected(object sender, EventArgs e)
|
||||
{
|
||||
client.Self.RequestMuteList();
|
||||
}
|
||||
|
||||
void Network_LoginProgress(object sender, LoginProgressEventArgs e)
|
||||
{
|
||||
if (e.Status == LoginStatus.ConnectingToSim)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(ClientDir))
|
||||
{
|
||||
Directory.CreateDirectory(ClientDir);
|
||||
}
|
||||
clientSettings = new Settings(Path.Combine(ClientDir, "client_settings.xml"));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log("Failed to create client directory", Helpers.LogLevel.Warning, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Fetches avatar name
|
||||
/// </summary>
|
||||
/// <param name="key">Avatar UUID</param>
|
||||
/// <param name="blocking">Should we wait until the name is retrieved</param>
|
||||
/// <returns>Avatar name</returns>
|
||||
[Obsolete("Use Instance.Names.Get() instead")]
|
||||
public string getAvatarName(UUID key, bool blocking)
|
||||
{
|
||||
return Names.Get(key, blocking);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches avatar name from cache, if not in cache will request name from the server
|
||||
/// </summary>
|
||||
/// <param name="key">Avatar UUID</param>
|
||||
/// <returns>Avatar name</returns>
|
||||
[Obsolete("Use Instance.Names.Get() instead")]
|
||||
public string getAvatarName(UUID key)
|
||||
{
|
||||
return Names.Get(key);
|
||||
}
|
||||
|
||||
void Groups_GroupsChanged(object sender, EventArgs e)
|
||||
{
|
||||
client.Groups.RequestCurrentGroups();
|
||||
}
|
||||
|
||||
public static string SafeFileName(string fileName)
|
||||
{
|
||||
foreach (char lDisallowed in Path.GetInvalidFileNameChars())
|
||||
{
|
||||
fileName = fileName.Replace(lDisallowed.ToString(), "_");
|
||||
}
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public string ChatFileName(string session)
|
||||
{
|
||||
string fileName = session;
|
||||
|
||||
foreach (char lDisallowed in System.IO.Path.GetInvalidFileNameChars())
|
||||
{
|
||||
fileName = fileName.Replace(lDisallowed.ToString(), "_");
|
||||
}
|
||||
|
||||
return Path.Combine(ClientDir, fileName);
|
||||
}
|
||||
|
||||
public void LogClientMessage(string sessioName, string message)
|
||||
{
|
||||
if (globalSettings["disable_chat_im_log"]) return;
|
||||
|
||||
lock (this)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.AppendAllText(ChatFileName(sessioName),
|
||||
DateTime.Now.ToString("yyyy-MM-dd [HH:mm:ss] ") + message + Environment.NewLine);
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
}
|
||||
|
||||
void Groups_CurrentGroups(object sender, CurrentGroupsEventArgs e)
|
||||
{
|
||||
this.groups = e.Groups;
|
||||
}
|
||||
|
||||
private void InitializeLoggingAndConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
userDir = Path.Combine(app_data_dir , PROGRAMNAME);
|
||||
if (!Directory.Exists(userDir))
|
||||
{
|
||||
Directory.CreateDirectory(userDir);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
userDir = System.Environment.CurrentDirectory;
|
||||
};
|
||||
|
||||
globalLogFile = Path.Combine(userDir, PROGRAMNAME + ".log");
|
||||
globalSettings = new Settings(Path.Combine(userDir, "settings.xml"));
|
||||
//frmSettings.InitSettigs(globalSettings, monoRuntime);
|
||||
}
|
||||
|
||||
public GridClient Client
|
||||
{
|
||||
get { return client; }
|
||||
}
|
||||
|
||||
public RaindropNetcom Netcom
|
||||
{
|
||||
get { return netcom; }
|
||||
}
|
||||
|
||||
public StateManager State
|
||||
{
|
||||
get { return state; }
|
||||
}
|
||||
|
||||
public mainUI MainCanvas
|
||||
{
|
||||
get { return mainCanvas; }
|
||||
}
|
||||
|
||||
//public TabsConsole TabConsole
|
||||
//{
|
||||
// get { return mainForm.TabConsole; }
|
||||
//}
|
||||
|
||||
public void HandleThreadException(object sender, ThreadExceptionEventArgs e)
|
||||
{
|
||||
Logger.Log("Unhandled thread exception: "
|
||||
+ e.Exception.Message + Environment.NewLine
|
||||
+ e.Exception.StackTrace + Environment.NewLine,
|
||||
Helpers.LogLevel.Error,
|
||||
client);
|
||||
}
|
||||
|
||||
#region Crash reporting
|
||||
FileStream MarkerLock = null;
|
||||
private string PROGRAMNAME = "RaindropTest_02";
|
||||
|
||||
public bool AnotherInstanceRunning()
|
||||
{
|
||||
// We have successfuly obtained lock
|
||||
if (MarkerLock != null && MarkerLock.CanWrite)
|
||||
{
|
||||
Logger.Log("No other instances detected, marker file already locked", Helpers.LogLevel.Debug);
|
||||
return false || MonoRuntime;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
MarkerLock = new FileStream(CrashMarkerFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
|
||||
Logger.Log(string.Format("Successfully created and locked marker file {0}", CrashMarkerFileName), Helpers.LogLevel.Debug);
|
||||
return false || MonoRuntime;
|
||||
}
|
||||
catch
|
||||
{
|
||||
MarkerLock = null;
|
||||
Logger.Log(string.Format("Another instance detected, marker fils {0} locked", CrashMarkerFileName), Helpers.LogLevel.Debug);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public LastExecStatus GetLastExecStatus()
|
||||
{
|
||||
// Crash marker file found and is not locked by us
|
||||
if (File.Exists(CrashMarkerFileName) && MarkerLock == null)
|
||||
{
|
||||
Logger.Log(string.Format("Found crash marker file {0}", CrashMarkerFileName), Helpers.LogLevel.Debug);
|
||||
return LastExecStatus.OtherCrash;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log(string.Format("No crash marker file {0} found", CrashMarkerFileName), Helpers.LogLevel.Debug);
|
||||
return LastExecStatus.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
public void MarkStartExecution()
|
||||
{
|
||||
Logger.Log(string.Format("Marking start of execution run, creating file: {0}", CrashMarkerFileName), Helpers.LogLevel.Debug);
|
||||
try
|
||||
{
|
||||
File.Create(CrashMarkerFileName).Dispose();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public void MarkEndExecution()
|
||||
{
|
||||
Logger.Log(string.Format("Marking end of execution run, deleting file: {0}", CrashMarkerFileName), Helpers.LogLevel.Debug);
|
||||
try
|
||||
{
|
||||
if (MarkerLock != null)
|
||||
{
|
||||
MarkerLock.Close();
|
||||
MarkerLock.Dispose();
|
||||
MarkerLock = null;
|
||||
}
|
||||
|
||||
File.Delete(CrashMarkerFileName);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
internal void setAppDataDir(string app_data_Path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion Crash reporting
|
||||
|
||||
#region Context Actions
|
||||
//void RegisterContextActions()
|
||||
//{
|
||||
// ContextActionManager.RegisterContextAction(typeof(Primitive), "Save as DAE...", ExportDAEHander);
|
||||
// ContextActionManager.RegisterContextAction(typeof(Primitive), "Copy UUID to clipboard", CopyObjectUUIDHandler);
|
||||
//}
|
||||
|
||||
//void DeregisterContextActions()
|
||||
//{
|
||||
// ContextActionManager.DeregisterContextAction(typeof(Primitive), "Save as DAE...");
|
||||
// ContextActionManager.DeregisterContextAction(typeof(Primitive), "Copy UUID to clipboard");
|
||||
//}
|
||||
|
||||
//void ExportDAEHander(object sender, EventArgs e)
|
||||
//{
|
||||
// MainForm.DisplayColladaConsole((Primitive)sender);
|
||||
//}
|
||||
|
||||
//void CopyObjectUUIDHandler(object sender, EventArgs e)
|
||||
//{
|
||||
// if (mainForm.InvokeRequired)
|
||||
// {
|
||||
// if (mainForm.IsHandleCreated || !MonoRuntime)
|
||||
// {
|
||||
// mainForm.Invoke(new MethodInvoker(() => CopyObjectUUIDHandler(sender, e)));
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Clipboard.SetText(((Primitive)sender).ID.ToString());
|
||||
//}
|
||||
|
||||
#endregion Context Actions
|
||||
|
||||
|
||||
private void Logger_OnLogMessage(object message, Helpers.LogLevel level)
|
||||
{
|
||||
if (level == Helpers.LogLevel.Debug)
|
||||
{
|
||||
Debug.Log(message);
|
||||
}
|
||||
else if (level == Helpers.LogLevel.Error)
|
||||
{
|
||||
Debug.LogError(message);
|
||||
}
|
||||
else if (level == Helpers.LogLevel.Info)
|
||||
{
|
||||
Debug.Log(message);
|
||||
}
|
||||
else if (level == Helpers.LogLevel.Warning)
|
||||
{
|
||||
Debug.LogWarning(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#region Event classes
|
||||
public class ClientChangedEventArgs : EventArgs
|
||||
{
|
||||
private GridClient m_OldClient;
|
||||
private GridClient m_Client;
|
||||
|
||||
public GridClient OldClient { get { return m_OldClient; } }
|
||||
public GridClient Client { get { return m_Client; } }
|
||||
|
||||
public ClientChangedEventArgs(GridClient OldClient, GridClient Client)
|
||||
{
|
||||
m_OldClient = OldClient;
|
||||
m_Client = Client;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Event classes
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a513c3b8d6c8e1b48adc33fd6d665cef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,171 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
using System;
|
||||
using System.Timers;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace Raindrop
|
||||
{
|
||||
public class RaindropMovement : IDisposable
|
||||
{
|
||||
private RaindropInstance instance;
|
||||
private GridClient client { get { return instance.Client; } }
|
||||
private Timer timer;
|
||||
private Vector3 forward = new Vector3(1, 0, 0);
|
||||
private bool turningLeft = false;
|
||||
private bool turningRight = false;
|
||||
private bool movingForward = false;
|
||||
private bool movingBackward = false;
|
||||
|
||||
public bool TurningLeft
|
||||
{
|
||||
get
|
||||
{
|
||||
return turningLeft;
|
||||
}
|
||||
set
|
||||
{
|
||||
turningLeft = value;
|
||||
if (value)
|
||||
{
|
||||
timer_Elapsed(null, null);
|
||||
timer.Enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer.Enabled = false;
|
||||
client.Self.Movement.TurnLeft = false;
|
||||
client.Self.Movement.SendUpdate(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool TurningRight
|
||||
{
|
||||
get
|
||||
{
|
||||
return turningRight;
|
||||
}
|
||||
set
|
||||
{
|
||||
turningRight = value;
|
||||
if (value)
|
||||
{
|
||||
timer_Elapsed(null, null);
|
||||
timer.Enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer.Enabled = false;
|
||||
client.Self.Movement.TurnRight = false;
|
||||
client.Self.Movement.SendUpdate(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool MovingForward
|
||||
{
|
||||
get
|
||||
{
|
||||
return movingForward;
|
||||
}
|
||||
set
|
||||
{
|
||||
movingForward = value;
|
||||
if (value)
|
||||
{
|
||||
client.Self.Movement.AtPos = true;
|
||||
client.Self.Movement.SendUpdate(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
client.Self.Movement.AtPos = false;
|
||||
client.Self.Movement.SendUpdate(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool MovingBackward
|
||||
{
|
||||
get
|
||||
{
|
||||
return movingBackward;
|
||||
}
|
||||
set
|
||||
{
|
||||
movingBackward = value;
|
||||
if (value)
|
||||
{
|
||||
client.Self.Movement.AtNeg = true;
|
||||
client.Self.Movement.SendUpdate(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
client.Self.Movement.AtNeg = false;
|
||||
client.Self.Movement.SendUpdate(true);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RaindropMovement(RaindropInstance instance)
|
||||
{
|
||||
this.instance = instance;
|
||||
timer = new System.Timers.Timer(100);
|
||||
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
|
||||
timer.Enabled = false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
timer.Enabled = false;
|
||||
timer.Dispose();
|
||||
timer = null;
|
||||
}
|
||||
|
||||
void timer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
float delta = (float)timer.Interval / 1000f;
|
||||
if (turningLeft)
|
||||
{
|
||||
client.Self.Movement.TurnLeft = true;
|
||||
client.Self.Movement.BodyRotation = client.Self.Movement.BodyRotation * Quaternion.CreateFromAxisAngle(Vector3.UnitZ, delta);
|
||||
client.Self.Movement.SendUpdate(true);
|
||||
}
|
||||
else if (turningRight)
|
||||
{
|
||||
client.Self.Movement.TurnRight = true;
|
||||
client.Self.Movement.BodyRotation = client.Self.Movement.BodyRotation * Quaternion.CreateFromAxisAngle(Vector3.UnitZ, -delta);
|
||||
client.Self.Movement.SendUpdate(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "RaindropUnity",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:b6ef318018e211441b43da945a1caf13",
|
||||
"GUID:1364d97af688c264f94c622d729b2059"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e5c96f0601ad834f84ded85be85a608
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,417 @@
|
||||
//
|
||||
// Radegast Metaverse Client
|
||||
// Copyright (c) 2009-2014, Radegast Development Team
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the application "Radegast", nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using System.Drawing;
|
||||
//using System.Web.Script.Serialization;
|
||||
using System.ComponentModel;
|
||||
using SixLabors.ImageSharp;
|
||||
|
||||
namespace Raindrop
|
||||
{
|
||||
public class Settings : IDictionary<string, OSD>
|
||||
{
|
||||
private string SettingsFile;
|
||||
private OSDMap SettingsData;
|
||||
|
||||
public delegate void SettingChangedCallback(object sender, SettingsEventArgs e);
|
||||
public event SettingChangedCallback OnSettingChanged;
|
||||
|
||||
public static readonly Dictionary<string, FontSetting> DefaultFontSettings = new Dictionary<string, FontSetting>()
|
||||
{
|
||||
{"Normal", new FontSetting {
|
||||
Name = "Normal",
|
||||
ForeColor = SystemColors.ControlText,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"StatusBlue", new FontSetting {
|
||||
Name = "StatusBlue",
|
||||
ForeColor = Color.Blue,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"StatusDarkBlue", new FontSetting {
|
||||
Name = "StatusDarkBlue",
|
||||
ForeColor = Color.DarkBlue,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"LindenChat", new FontSetting {
|
||||
Name = "LindenChat",
|
||||
ForeColor = Color.DarkGreen,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"ObjectChat", new FontSetting {
|
||||
Name = "ObjectChat",
|
||||
ForeColor = Color.DarkCyan,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"StartupTitle", new FontSetting {
|
||||
Name = "StartupTitle",
|
||||
ForeColor = SystemColors.ControlText,
|
||||
BackColor = Color.Transparent,
|
||||
Font = new Font(FontSetting.DefaultFont, FontStyle.Bold),
|
||||
}},
|
||||
{"Alert", new FontSetting {
|
||||
Name = "Alert",
|
||||
ForeColor = Color.DarkRed,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"Error", new FontSetting {
|
||||
Name = "Error",
|
||||
ForeColor = Color.Red,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"OwnerSay", new FontSetting {
|
||||
Name = "OwnerSay",
|
||||
ForeColor = Color.DarkGoldenrod,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"Timestamp", new FontSetting {
|
||||
Name = "Timestamp",
|
||||
ForeColor = SystemColors.GrayText,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"Name", new FontSetting {
|
||||
Name = "Name",
|
||||
ForeColor = SystemColors.ControlText,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"Notification", new FontSetting {
|
||||
Name = "Notification",
|
||||
ForeColor = SystemColors.ControlText,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"IncomingIM", new FontSetting {
|
||||
Name = "IncomingIM",
|
||||
ForeColor = SystemColors.ControlText,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"OutgoingIM", new FontSetting {
|
||||
Name = "OutgoingIM",
|
||||
ForeColor = SystemColors.ControlText,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"Emote", new FontSetting {
|
||||
Name = "Emote",
|
||||
ForeColor = SystemColors.ControlText,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
{"Self", new FontSetting {
|
||||
Name = "Self",
|
||||
ForeColor = SystemColors.ControlText,
|
||||
BackColor = Color.Transparent,
|
||||
Font = FontSetting.DefaultFont,
|
||||
}},
|
||||
};
|
||||
|
||||
public class FontSetting
|
||||
{
|
||||
[ScriptIgnoreAttribute]
|
||||
public static readonly Font DefaultFont = new Font(FontFamily.GenericSansSerif, 8.0f);
|
||||
|
||||
[ScriptIgnoreAttribute]
|
||||
public Font Font;
|
||||
|
||||
[ScriptIgnoreAttribute]
|
||||
public Color ForeColor;
|
||||
|
||||
[ScriptIgnoreAttribute]
|
||||
public Color BackColor;
|
||||
|
||||
|
||||
public String Name;
|
||||
|
||||
public string ForeColorString
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ForeColor != null)
|
||||
{
|
||||
return ColorTranslator.ToHtml(ForeColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ColorTranslator.ToHtml(SystemColors.ControlText);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
ForeColor = ColorTranslator.FromHtml(value);
|
||||
}
|
||||
}
|
||||
|
||||
public string BackColorString
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BackColor != null)
|
||||
{
|
||||
return ColorTranslator.ToHtml(BackColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ColorTranslator.ToHtml(SystemColors.ControlText);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
BackColor = ColorTranslator.FromHtml(value);
|
||||
}
|
||||
}
|
||||
|
||||
public string FontString
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.Font != null)
|
||||
{
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(typeof(Font));
|
||||
return converter.ConvertToString(this.Font);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
try
|
||||
{
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(typeof(Font));
|
||||
this.Font = converter.ConvertFromString(value) as Font;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
this.Font = DefaultFont;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
||||
public Settings(string fileName)
|
||||
{
|
||||
SettingsFile = fileName;
|
||||
|
||||
try
|
||||
{
|
||||
string xml = File.ReadAllText(SettingsFile);
|
||||
SettingsData = (OSDMap)OSDParser.DeserializeLLSDXml(xml);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logger.DebugLog("Failed opening settings file: " + fileName);
|
||||
SettingsData = new OSDMap();
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
try
|
||||
{
|
||||
File.WriteAllText(SettingsFile, SerializeLLSDXmlStringFormated(SettingsData));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log("Failed saving settings", Helpers.LogLevel.Warning, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static string SerializeLLSDXmlStringFormated(OSD data)
|
||||
{
|
||||
using (StringWriter sw = new StringWriter())
|
||||
{
|
||||
using (XmlTextWriter writer = new XmlTextWriter(sw))
|
||||
{
|
||||
writer.Formatting = Formatting.Indented;
|
||||
writer.Indentation = 4;
|
||||
writer.IndentChar = ' ';
|
||||
|
||||
writer.WriteStartElement(String.Empty, "llsd", String.Empty);
|
||||
OSDParser.SerializeLLSDXmlElement(writer, data);
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.Close();
|
||||
|
||||
return sw.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FireEvent(string key, OSD val)
|
||||
{
|
||||
if (OnSettingChanged != null)
|
||||
{
|
||||
try { OnSettingChanged(this, new SettingsEventArgs(key, val)); }
|
||||
catch (Exception) { }
|
||||
}
|
||||
}
|
||||
|
||||
#region IDictionary Implementation
|
||||
|
||||
public int Count { get { return SettingsData.Count; } }
|
||||
public bool IsReadOnly { get { return false; } }
|
||||
public ICollection<string> Keys { get { return SettingsData.Keys; } }
|
||||
public ICollection<OSD> Values { get { return SettingsData.Values; } }
|
||||
public OSD this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return SettingsData[key];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(key))
|
||||
{
|
||||
Logger.DebugLog("Warning: trying to set an emprty setting: " + Environment.StackTrace.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
SettingsData[key] = value;
|
||||
FireEvent(key, value);
|
||||
Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
return SettingsData.ContainsKey(key);
|
||||
}
|
||||
|
||||
public void Add(string key, OSD llsd)
|
||||
{
|
||||
SettingsData.Add(key, llsd);
|
||||
FireEvent(key, llsd);
|
||||
Save();
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, OSD> kvp)
|
||||
{
|
||||
SettingsData.Add(kvp.Key, kvp.Value);
|
||||
FireEvent(kvp.Key, kvp.Value);
|
||||
Save();
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
bool ret = SettingsData.Remove(key);
|
||||
FireEvent(key, null);
|
||||
Save();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out OSD llsd)
|
||||
{
|
||||
return SettingsData.TryGetValue(key, out llsd);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
SettingsData.Clear();
|
||||
Save();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, OSD> kvp)
|
||||
{
|
||||
// This is a bizarre function... we don't really implement it
|
||||
// properly, hopefully no one wants to use it
|
||||
return SettingsData.ContainsKey(kvp.Key);
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<string, OSD>[] array, int index)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, OSD> kvp)
|
||||
{
|
||||
bool ret = SettingsData.Remove(kvp.Key);
|
||||
FireEvent(kvp.Key, null);
|
||||
Save();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public System.Collections.IDictionaryEnumerator GetEnumerator()
|
||||
{
|
||||
return SettingsData.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<string, OSD>> IEnumerable<KeyValuePair<string, OSD>>.GetEnumerator()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return SettingsData.GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion IDictionary Implementation
|
||||
|
||||
}
|
||||
|
||||
public class SettingsEventArgs : EventArgs
|
||||
{
|
||||
public string Key = string.Empty;
|
||||
public OSD Value = new OSD();
|
||||
|
||||
public SettingsEventArgs(string key, OSD val)
|
||||
{
|
||||
Key = key;
|
||||
Value = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d006287ccb09804583f81650c8c71b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using Raindrop;
|
||||
|
||||
public class Global : MonoBehaviour
|
||||
{
|
||||
//public GameObject CanvasManagerObject;
|
||||
public CanvasManager CanvasManagerRef;
|
||||
|
||||
//this static-new is like a globally accessible instance without a singleton! :)
|
||||
public RaindropInstance MainRaindropInstance;
|
||||
//this one manages the viewmodels and the stacking of UI modals.
|
||||
public RaindropViewManager RaindropVM;
|
||||
|
||||
|
||||
public string app_data_Path { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
CanvasManagerRef= FindObjectOfType<CanvasManager>();
|
||||
|
||||
//initialise your 'statics'
|
||||
|
||||
//Get the path of the Game data folder
|
||||
//app_data_Path = Application.persistentDataPath;
|
||||
|
||||
//Output the Game data path to the console
|
||||
//Debug.Log("dataPath : " + app_data_Path);
|
||||
|
||||
//raindropinstance seems tightly coupled with the applicaiton lifecycle; it seems essentially a subset of the app lifecycle in fact.
|
||||
//make sure you supply the app directory.
|
||||
MainRaindropInstance = RaindropInstance.GlobalInstance;
|
||||
//RaindropInstance.GlobalInstance.setAppDataDir(app_data_Path);
|
||||
|
||||
RaindropVM = new RaindropViewManager(MainRaindropInstance);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Raindrop
|
||||
{
|
||||
|
||||
|
||||
public enum CanvasType
|
||||
{
|
||||
Login,
|
||||
Game
|
||||
}
|
||||
|
||||
public class RaindropViewManager
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public CanvasManager canvasManager;
|
||||
|
||||
//manages all child Viewmodels
|
||||
public RaindropViewManager(RaindropInstance instance)
|
||||
{
|
||||
//Debug.Log("VM manager setup ok");
|
||||
|
||||
//subscribe all events from raindropclient
|
||||
//Client.LoginCompleted += MainRaindropInstance_LoginCompleted;
|
||||
//Client.LoginFailed += MainRaindropInstance_LoginFailed;
|
||||
|
||||
}
|
||||
|
||||
//register the canvas manager which is in a GO, who has the responsibility of flipping pages.
|
||||
//public void registerWithRaindropClient(CanvasManager canvasManager)
|
||||
//{
|
||||
// this.canvasManager = canvasManager;
|
||||
// //start up the initial login panel
|
||||
// pushLoginView();
|
||||
//}
|
||||
private void pushLoginView()
|
||||
{
|
||||
canvasManager.pushCanvas(CanvasType.Login);
|
||||
}
|
||||
|
||||
//private void MainRaindropInstance_LoginFailed()
|
||||
//{
|
||||
// Debug.Log("failed login TODO: why?");
|
||||
//}
|
||||
|
||||
private void showFailedLoginModal()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
//private void MainRaindropInstance_LoginCompleted()
|
||||
//{
|
||||
// cm.popCanvas();//this lince causes error, as the function was called from the login thread!
|
||||
// cm.pushCanvas(CanvasType.Game);
|
||||
// //showSuccessLoginModal();
|
||||
//}
|
||||
|
||||
private void removeLoginView()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void showSuccessLoginModal()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ public class CanvasManager : Singleton<CanvasManager>
|
||||
//CanvasIdentifier lastActiveCanvas;
|
||||
public Stack<CanvasIdentifier> activeCanvasStack = new Stack<CanvasIdentifier>();
|
||||
|
||||
public Global Globalref;
|
||||
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
@@ -20,7 +22,7 @@ public class CanvasManager : Singleton<CanvasManager>
|
||||
pushCanvas(CanvasType.Login);
|
||||
|
||||
//canvas manager (attached to the UI GO) should register with the globals. so that the globals can acess them
|
||||
Global.RaindropVM.registerWithRaindropClient(this);
|
||||
//Globalref.RaindropVM.registerWithRaindropClient(this);
|
||||
|
||||
}
|
||||
public void pushCanvas(CanvasType _type)
|
||||
@@ -52,10 +54,15 @@ public class CanvasManager : Singleton<CanvasManager>
|
||||
var lastActiveCanvas = activeCanvasStack.Peek();
|
||||
if (lastActiveCanvas != null)
|
||||
{
|
||||
lastActiveCanvas.gameObject.SetActive(false);
|
||||
lastActiveCanvas.gameObject.SetActive(false); //this lince causes error, as the function was called from the login thread!
|
||||
activeCanvasStack.Pop();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
internal void pushModal()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using OpenMetaverse;
|
||||
using Raindrop;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
@@ -8,6 +9,10 @@ using UnityWeld.Binding;
|
||||
[Binding]
|
||||
public class LoginVM : MonoBehaviour, INotifyPropertyChanged
|
||||
{
|
||||
public Global globalRef;
|
||||
|
||||
private RaindropInstance instance;
|
||||
private RaindropNetcom netcom { get { return instance.Netcom; } }
|
||||
|
||||
#region state
|
||||
|
||||
@@ -116,9 +121,25 @@ public class LoginVM : MonoBehaviour, INotifyPropertyChanged
|
||||
void Start()
|
||||
{
|
||||
initialise();
|
||||
Global.MainRaindropInstance.LoginCompleted += cb_LoginCompleted;
|
||||
Global.MainRaindropInstance.LoginFailed += cb_LoginFailed;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void AddNetcomEvents()
|
||||
{
|
||||
netcom.ClientLoggingIn += new EventHandler<OverrideEventArgs>(netcom_ClientLoggingIn);
|
||||
netcom.ClientLoginStatus += new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
|
||||
netcom.ClientLoggingOut += new EventHandler<OverrideEventArgs>(netcom_ClientLoggingOut);
|
||||
netcom.ClientLoggedOut += new EventHandler(netcom_ClientLoggedOut);
|
||||
}
|
||||
|
||||
private void RemoveNetcomEvents()
|
||||
{
|
||||
netcom.ClientLoggingIn -= new EventHandler<OverrideEventArgs>(netcom_ClientLoggingIn);
|
||||
netcom.ClientLoginStatus -= new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
|
||||
netcom.ClientLoggingOut -= new EventHandler<OverrideEventArgs>(netcom_ClientLoggingOut);
|
||||
netcom.ClientLoggedOut -= new EventHandler(netcom_ClientLoggedOut);
|
||||
}
|
||||
|
||||
private void cb_LoginFailed()
|
||||
@@ -174,7 +195,7 @@ public class LoginVM : MonoBehaviour, INotifyPropertyChanged
|
||||
Debug.LogError("loggin button but username and password are not defined!");
|
||||
return;
|
||||
}
|
||||
Global.MainRaindropInstance.connectTo(Username,Password);
|
||||
globalRef.MainRaindropInstance.connectTo(Username,Password);
|
||||
|
||||
}
|
||||
|
||||
@@ -184,7 +205,7 @@ public class LoginVM : MonoBehaviour, INotifyPropertyChanged
|
||||
Debug.Log("logout btn");
|
||||
|
||||
// Logout of simulator
|
||||
Global.MainRaindropInstance.Client.Network.Logout();
|
||||
globalRef.MainRaindropInstance.Client.Network.Logout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
using Raindrop.Netcom;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenMetaverse.Assets;
|
||||
|
||||
|
||||
namespace Raindrop
|
||||
{
|
||||
public class mainUI
|
||||
{
|
||||
private RaindropInstance raindropInstance;
|
||||
|
||||
public mainUI(RaindropInstance raindropInstance)
|
||||
{
|
||||
this.raindropInstance = raindropInstance;
|
||||
|
||||
|
||||
// Callbacks
|
||||
netcom.ClientLoginStatus += new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
|
||||
netcom.ClientLoggedOut += new EventHandler(netcom_ClientLoggedOut);
|
||||
netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);
|
||||
instance.Names.NameUpdated += new EventHandler<UUIDNameReplyEventArgs>(Names_NameUpdated);
|
||||
}
|
||||
|
||||
public object instance { get; private set; }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c58dd02bac207f4185512ab84eea324
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -123,6 +123,82 @@ NavMeshSettings:
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &26288764
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 26288765}
|
||||
- component: {fileID: 26288767}
|
||||
- component: {fileID: 26288766}
|
||||
m_Layer: 5
|
||||
m_Name: Overlaydebug
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
--- !u!224 &26288765
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 26288764}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 267083071}
|
||||
m_Father: {fileID: 904771131}
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 461.74963, y: -300.6742}
|
||||
m_SizeDelta: {x: -923.4992, y: -601.3484}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &26288766
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 26288764}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 0.392}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!222 &26288767
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 26288764}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1 &38931173
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -142,7 +218,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!224 &38931174
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -427,6 +503,122 @@ MonoBehaviour:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_IsOn: 1
|
||||
--- !u!1 &267083070
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 267083071}
|
||||
- component: {fileID: 267083075}
|
||||
- component: {fileID: 267083074}
|
||||
- component: {fileID: 267083073}
|
||||
- component: {fileID: 267083072}
|
||||
m_Layer: 5
|
||||
m_Name: Panel
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &267083071
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 267083070}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 1597224912}
|
||||
m_Father: {fileID: 26288765}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 1, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 0}
|
||||
m_AnchoredPosition: {x: -457.23755, y: 191.93365}
|
||||
m_SizeDelta: {x: 914.4751, y: 383.8673}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &267083072
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 267083070}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f003e7629ecbbdb4c9867c281c3c59c9, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!114 &267083073
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 267083070}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Padding:
|
||||
m_Left: 0
|
||||
m_Right: 0
|
||||
m_Top: 0
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 0
|
||||
m_Spacing: 0
|
||||
m_ChildForceExpandWidth: 1
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildControlWidth: 0
|
||||
m_ChildControlHeight: 0
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!114 &267083074
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 267083070}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 0.392}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!222 &267083075
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 267083070}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1 &289478450
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -2227,6 +2419,7 @@ RectTransform:
|
||||
m_Children:
|
||||
- {fileID: 1910810518}
|
||||
- {fileID: 1090573972}
|
||||
- {fileID: 26288765}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 4
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
@@ -2247,6 +2440,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 5759aa2a69d06bf42bc000d03390227e, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
Globalref: {fileID: 0}
|
||||
--- !u!1 &936677284
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -2555,6 +2749,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: c2eeaa71c61350f46902f312854272c9, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
globalRef: {fileID: 0}
|
||||
--- !u!114 &1090573975
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -3690,6 +3885,140 @@ CanvasRenderer:
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1421356640}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1 &1597224911
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1597224912}
|
||||
- component: {fileID: 1597224914}
|
||||
- component: {fileID: 1597224913}
|
||||
m_Layer: 5
|
||||
m_Name: LocationText
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1597224912
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1597224911}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 267083071}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 240.7321, y: -42.3337}
|
||||
m_SizeDelta: {x: 481.4642, y: 84.6674}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &1597224913
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1597224911}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: New Text
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 36
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 1
|
||||
m_VerticalAlignment: 256
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_enableWordWrapping: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 1
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!222 &1597224914
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1597224911}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1 &1603377539
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -4403,6 +4732,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 55c6aede8bf73ca48b10f0d9e2e771f0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
CanvasManagerRef: {fileID: 904771132}
|
||||
--- !u!1 &1889936407
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -4573,6 +4903,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: c2eeaa71c61350f46902f312854272c9, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
globalRef: {fileID: 0}
|
||||
--- !u!114 &1910810522
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace Raindrop.Tests
|
||||
{
|
||||
[TestFixture()]
|
||||
class RaindropTests
|
||||
{
|
||||
[Test()]
|
||||
public void LoginTest()
|
||||
{
|
||||
RaindropClient MainRaindropInstance;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 646de89141f469245ace3f66a81cce73
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -4,7 +4,8 @@
|
||||
"references": [
|
||||
"UnityEngine.TestRunner",
|
||||
"UnityEditor.TestRunner",
|
||||
"LibreMetaverseAssembly"
|
||||
"LibreMetaverseAssembly",
|
||||
"RaindropUnity"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using Raindrop;
|
||||
|
||||
public class Global : MonoBehaviour
|
||||
{
|
||||
//this static-new is like a globally accessible instance without a singleton! :)
|
||||
public static RaindropClient MainRaindropInstance = new RaindropClient();
|
||||
//this one manages the viewmodels and the stacking of UI modals.
|
||||
public static RaindropViewManager RaindropVM = new RaindropViewManager();
|
||||
|
||||
|
||||
public string app_data_Path { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
//initialise your 'statics'
|
||||
|
||||
//Get the path of the Game data folder
|
||||
app_data_Path = Application.persistentDataPath;
|
||||
|
||||
//Output the Game data path to the console
|
||||
Debug.Log("dataPath : " + app_data_Path);
|
||||
|
||||
MainRaindropInstance.setConfigPath(app_data_Path);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Raindrop
|
||||
{
|
||||
public enum CanvasType
|
||||
{
|
||||
Login,
|
||||
Game
|
||||
}
|
||||
|
||||
public class RaindropViewManager
|
||||
{
|
||||
public CanvasManager cm;
|
||||
|
||||
//manages all child Viewmodels
|
||||
public RaindropViewManager()
|
||||
{
|
||||
//Debug.Log("VM manager setup ok");
|
||||
|
||||
//subscribe all events from raindropclient
|
||||
Global.MainRaindropInstance.LoginCompleted += MainRaindropInstance_LoginCompleted;
|
||||
Global.MainRaindropInstance.LoginFailed += MainRaindropInstance_LoginFailed;
|
||||
|
||||
}
|
||||
|
||||
//register the canvas manager which is in a GO, who has the responsibility of flipping pages.
|
||||
public void registerWithRaindropClient(CanvasManager canvasManager)
|
||||
{
|
||||
cm = canvasManager;
|
||||
//start up the initial login panel
|
||||
pushLoginView();
|
||||
}
|
||||
private void pushLoginView()
|
||||
{
|
||||
cm.pushCanvas(CanvasType.Login);
|
||||
}
|
||||
|
||||
private void MainRaindropInstance_LoginFailed()
|
||||
{
|
||||
Debug.Log("failed login TODO: why?");
|
||||
}
|
||||
|
||||
private void showFailedLoginModal()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void MainRaindropInstance_LoginCompleted()
|
||||
{
|
||||
cm.popCanvas();
|
||||
cm.pushCanvas(CanvasType.Game);
|
||||
//showSuccessLoginModal();
|
||||
}
|
||||
|
||||
private void removeLoginView()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void showSuccessLoginModal()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright 2015 Pim de Witte All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
/// Author: Pim de Witte (pimdewitte.com) and contributors, https://github.com/PimDeWitte/UnityMainThreadDispatcher
|
||||
/// <summary>
|
||||
/// A thread-safe class which holds a queue with actions to execute on the next Update() method. It can be used to make calls to the main thread for
|
||||
/// things such as UI Manipulation in Unity. It was developed for use in combination with the Firebase Unity plugin, which uses separate threads for event handling
|
||||
/// </summary>
|
||||
public class UnityMainThreadDispatcher : MonoBehaviour
|
||||
{
|
||||
|
||||
private static readonly Queue<Action> _executionQueue = new Queue<Action>();
|
||||
|
||||
public void Update()
|
||||
{
|
||||
lock (_executionQueue)
|
||||
{
|
||||
while (_executionQueue.Count > 0)
|
||||
{
|
||||
_executionQueue.Dequeue().Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locks the queue and adds the IEnumerator to the queue
|
||||
/// </summary>
|
||||
/// <param name="action">IEnumerator function that will be executed from the main thread.</param>
|
||||
public void Enqueue(IEnumerator action)
|
||||
{
|
||||
lock (_executionQueue)
|
||||
{
|
||||
_executionQueue.Enqueue(() => {
|
||||
StartCoroutine(action);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locks the queue and adds the Action to the queue
|
||||
/// </summary>
|
||||
/// <param name="action">function that will be executed from the main thread.</param>
|
||||
public void Enqueue(Action action)
|
||||
{
|
||||
Enqueue(ActionWrapper(action));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locks the queue and adds the Action to the queue, returning a Task which is completed when the action completes
|
||||
/// </summary>
|
||||
/// <param name="action">function that will be executed from the main thread.</param>
|
||||
/// <returns>A Task that can be awaited until the action completes</returns>
|
||||
public Task EnqueueAsync(Action action)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
void WrappedAction()
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
tcs.TrySetResult(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
tcs.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
Enqueue(ActionWrapper(WrappedAction));
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
|
||||
IEnumerator ActionWrapper(Action a)
|
||||
{
|
||||
a();
|
||||
yield return null;
|
||||
}
|
||||
|
||||
|
||||
private static UnityMainThreadDispatcher _instance = null;
|
||||
|
||||
public static bool Exists()
|
||||
{
|
||||
return _instance != null;
|
||||
}
|
||||
|
||||
public static UnityMainThreadDispatcher Instance()
|
||||
{
|
||||
if (!Exists())
|
||||
{
|
||||
throw new Exception("UnityMainThreadDispatcher could not find the UnityMainThreadDispatcher object. Please ensure you have added the MainThreadExecutor Prefab to your scene.");
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = this;
|
||||
DontDestroyOnLoad(this.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
_instance = null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 518a7b51b6ca76b4aa067bd054208dd9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,471 @@
|
||||
<llsd>
|
||||
<array>
|
||||
|
||||
<!-- Second Life -->
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>agni</string>
|
||||
<key>gridname</key>
|
||||
<string>Second Life (agni)</string>
|
||||
<key>platform</key>
|
||||
<string>SecondLife</string>
|
||||
<key>loginuri</key>
|
||||
<string>https://login.agni.lindenlab.com/cgi-bin/login.cgi</string>
|
||||
<key>loginpage</key>
|
||||
<string>http://secondlife.com/app/login/?channel=Second+Life+Release</string>
|
||||
<key>helperuri</key>
|
||||
<string>https://secondlife.com/helpers/</string>
|
||||
<key>website</key>
|
||||
<string>http://secondlife.com/</string>
|
||||
<key>support</key>
|
||||
<string>http://secondlife.com/support/</string>
|
||||
<key>register</key>
|
||||
<string>http://secondlife.com/registration/</string>
|
||||
<key>password</key>
|
||||
<string>http://secondlife.com/account/request.php</string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
</map>
|
||||
|
||||
<!-- Second Life Beta -->
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>aditi</string>
|
||||
<key>gridname</key>
|
||||
<string>Second Life Beta (aditi)</string>
|
||||
<key>platform</key>
|
||||
<string>SecondLife</string>
|
||||
<key>loginuri</key>
|
||||
<string>https://login.aditi.lindenlab.com/cgi-bin/login.cgi</string>
|
||||
<key>loginpage</key>
|
||||
<string>http://secondlife.com/app/login/?channel=Second+Life+Beta</string>
|
||||
<key>helperuri</key>
|
||||
<string>http://aditi-secondlife.webdev.lindenlab.com/helpers/</string>
|
||||
<key>website</key>
|
||||
<string>http://secondlife.com/</string>
|
||||
<key>support</key>
|
||||
<string>http://secondlife.com/support/</string>
|
||||
<key>register</key>
|
||||
<string>http://secondlife.com/registration/</string>
|
||||
<key>password</key>
|
||||
<string>http://secondlife.com/account/request.php</string>
|
||||
<key>version</key>
|
||||
<string>1</string>
|
||||
</map>
|
||||
|
||||
<!-- Metropolis -->
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>metropolis</string>
|
||||
<key>gridname</key>
|
||||
<string>Metropolis Metaversum</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://hypergrid.org:8002/</string>
|
||||
<key>loginpage</key>
|
||||
<string>http://metropolis.hypergrid.org</string>
|
||||
<key>helperuri</key>
|
||||
<string>http://metropolis.hypergrid.org/currency/helper/</string>
|
||||
<key>website</key>
|
||||
<string>http://metropolis.hypergrid.org</string>
|
||||
<key>support</key>
|
||||
<string>http://metropolis.hypergrid.org</string>
|
||||
<key>register</key>
|
||||
<string>http://metropolis.hypergrid.org/oswi.php</string>
|
||||
<key>password</key>
|
||||
<string>http://metropolis.hypergrid.org/oswi.php</string>
|
||||
<key>version</key>
|
||||
<string>1</string>
|
||||
</map>
|
||||
|
||||
<!-- OSGrid -->
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>osgrid</string>
|
||||
<key>gridname</key>
|
||||
<string>OSGrid</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://login.osgrid.org/</string>
|
||||
<key>loginpage</key>
|
||||
<string>http://osgrid.org/loginscreen.php</string>
|
||||
<key>helperuri</key>
|
||||
<string>http://osgrid.org/</string>
|
||||
<key>website</key>
|
||||
<string>http://osgrid.org/</string>
|
||||
<key>support</key>
|
||||
<string>http://osgrid.org/</string>
|
||||
<key>register</key>
|
||||
<string>http://osgrid.org/elgg/account/register.php</string>
|
||||
<key>password</key>
|
||||
<string>http://osgrid.org/elgg/account/forgotten_password.php</string>
|
||||
<key>version</key>
|
||||
<string>1</string>
|
||||
</map>
|
||||
|
||||
<!-- ReactionGrid -->
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>reactiongrid</string>
|
||||
<key>gridname</key>
|
||||
<string>ReactionGrid</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
|
||||
<key>loginuri</key>
|
||||
<string>http://reactiongrid.com:8008/</string>
|
||||
<key>loginpage</key>
|
||||
<string>http://gsquared.info/portal</string>
|
||||
<key>website</key>
|
||||
<string>http://reactiongrid.com/Default.aspx</string>
|
||||
<key>support</key>
|
||||
<string>http://reactiongrid.com/Support.aspx</string>
|
||||
<key>register</key>
|
||||
<string>http://reactiongrid.com/Register.aspx</string>
|
||||
|
||||
<key>password</key>
|
||||
<string>http://reactiongrid.com/Support/ResetPassword.aspx</string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
</map>
|
||||
|
||||
<!-- 3rd Rock Grid -->
|
||||
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>3rdrock</string>
|
||||
<key>gridname</key>
|
||||
<string>3rd Rock Grid</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://grid.3rdrockgrid.com:8002/</string>
|
||||
|
||||
<key>loginpage</key>
|
||||
<string>http://3rdrockgrid.com/startpage.php</string>
|
||||
<key>helperuri</key>
|
||||
<string>http://3rdrockgrid.com/main/rg_files/wr/</string>
|
||||
<key>website</key>
|
||||
<string>http://3rdrockgrid.com/</string>
|
||||
<key>register</key>
|
||||
<string>http://www.3rdrockgrid.com/main/index.php?option=com_comprofiler&task=registers</string>
|
||||
|
||||
<key>password</key>
|
||||
<string>http://www.3rdrockgrid.com/main/index.php?option=com_comprofiler&task=lostPassword</string>
|
||||
<key>support</key>
|
||||
<string>http://3rdrockgrid.com/</string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
</map>
|
||||
|
||||
<!-- SirinHGpole -->
|
||||
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>sirinhgpole</string>
|
||||
<key>gridname</key>
|
||||
<string>SirinHGpole</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://hg.sirinhgpole.com:8002/</string>
|
||||
|
||||
<key>loginpage</key>
|
||||
<string></string>
|
||||
<key>helperuri</key>
|
||||
<string></string>
|
||||
<key>website</key>
|
||||
<string></string>
|
||||
<key>register</key>
|
||||
<string></string>
|
||||
|
||||
<key>password</key>
|
||||
<string></string>
|
||||
<key>support</key>
|
||||
<string></string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
</map>
|
||||
|
||||
<!-- InWorldz -->
|
||||
|
||||
<map>
|
||||
<key>gridname</key>
|
||||
<string>Inworldz</string>
|
||||
<key>gridnick</key>
|
||||
<string>inworldz</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
|
||||
<key>loginuri</key>
|
||||
<string>http://inworldz.com:8002/</string>
|
||||
<key>loginpage</key>
|
||||
<string>http://inworldz.com/welcome</string>
|
||||
<key>helperuri</key>
|
||||
<string>http://inworldz.com/</string>
|
||||
<key>password</key>
|
||||
<string>http://inworldz.com/wpassword</string>
|
||||
|
||||
<key>register</key>
|
||||
<string>http://inworldz.com/register</string>
|
||||
<key>support</key>
|
||||
<string>http://inworldz.com/help</string>
|
||||
<key>website</key>
|
||||
<string>http://inworldz.com/about/</string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
|
||||
</map>
|
||||
|
||||
<!-- Metavers Francophone FrancoGrid -->
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>francogrid</string>
|
||||
<key>gridname</key>
|
||||
<string>Francogrid</string>
|
||||
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://login.francogrid.org/</string>
|
||||
<key>loginpage</key>
|
||||
<string>http://viewer.francogrid.org/</string>
|
||||
<key>helperuri</key>
|
||||
<string>http://helper.main.francogrid.org/</string>
|
||||
<key>website</key>
|
||||
<string>http:/francogrid.org/</string>
|
||||
|
||||
<key>support</key>
|
||||
<string>http:/francogrid.org/aide</string>
|
||||
<key>register</key>
|
||||
<string>http:/francogrid.org/user/register</string>
|
||||
<key>password</key>
|
||||
<string>http:/francogrid.org/user/password</string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
</map>
|
||||
|
||||
<!-- Legend City Online -->
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>legendcityonline</string>
|
||||
<key>gridname</key>
|
||||
<string>Legend City Online</string>
|
||||
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://login.legendcityonline.com</string>
|
||||
<key>loginpage</key>
|
||||
<string>http://www.legendcityonline.com/welcome.php</string>
|
||||
<key>helperuri</key>
|
||||
<string>https://secure.legendcityonline.com/</string>
|
||||
<key>website</key>
|
||||
<string>http://www.legendcityonline.com/</string>
|
||||
|
||||
<key>support</key>
|
||||
<string>http://www.legendcityonline.com/</string>
|
||||
<key>register</key>
|
||||
<string>http://www.legendcityonline.com/</string>
|
||||
<key>password</key>
|
||||
<string>http://www.legendcityonline.com/</string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
</map>
|
||||
|
||||
<!-- WorldSimTerra -->
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>worldsimterra</string>
|
||||
<key>gridname</key>
|
||||
<string>WorldSimTerra</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
|
||||
<key>loginuri</key>
|
||||
<string>http://wsterra.com:8002</string>
|
||||
<key>loginpage</key>
|
||||
<string>http://wsterra.com/log.php</string>
|
||||
<key>helperuri</key>
|
||||
<string>http://wsterra.com/</string>
|
||||
<key>website</key>
|
||||
<string>http://www.worldsimterra.com/</string>
|
||||
<key>support</key>
|
||||
<string>http://www.worldsimterra.com/</string>
|
||||
|
||||
<key>register</key>
|
||||
<string>http://www.worldsimterra.com/</string>
|
||||
<key>password</key>
|
||||
<string>http://www.worldsimterra.com/</string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
</map>
|
||||
|
||||
<!-- Your Alternative Life -->
|
||||
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>youralternativelife</string>
|
||||
<key>gridname</key>
|
||||
<string>Your Alternative Life</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://grid01.from-ne.com:8002/</string>
|
||||
|
||||
<key>loginpage</key>
|
||||
<string>http://grid01.from-ne.com/tios/loginscreen3.php</string>
|
||||
<key>helperuri</key>
|
||||
<string>http://grid01.from-ne.com/tios/services/</string>
|
||||
<key>website</key>
|
||||
<string>http://www.youralternativelife.com</string>
|
||||
<key>support</key>
|
||||
<string>http://www.youralternativelife.com</string>
|
||||
<key>register</key>
|
||||
<string>http://www.youralternativelife.com</string>
|
||||
|
||||
<key>password</key>
|
||||
<string>http://www.youralternativelife.com</string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
|
||||
</map>
|
||||
|
||||
<!-- The New World Grid -->
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>thenewworldgrid</string>
|
||||
|
||||
<key>gridname</key>
|
||||
<string>The New World Grid</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://grid.newworldgrid.com:8002/</string>
|
||||
<key>loginpage</key>
|
||||
<string>http://account.newworldgrid.com/loginscreen.php</string>
|
||||
<key>helperuri</key>
|
||||
<string>http://account.newworldgrid.com/</string>
|
||||
|
||||
<key>website</key>
|
||||
<string>http://www.newworldgrid.com/</string>
|
||||
<key>support</key>
|
||||
<string>http://www.newworldgrid.com/</string>
|
||||
<key>register</key>
|
||||
<string>http://www.newworldgrid.com/register</string>
|
||||
<key>password</key>
|
||||
<string>http://account.newworldgrid.com/</string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
|
||||
</map>
|
||||
|
||||
<!-- Cyberlandia -->
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>cyberlandia</string>
|
||||
|
||||
<key>gridname</key>
|
||||
<string>Cyberlandia</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://grid.cyberlandia.net:8002</string>
|
||||
<key>loginpage</key>
|
||||
<string></string>
|
||||
<key>helperuri</key>
|
||||
<string></string>
|
||||
|
||||
<key>website</key>
|
||||
<string>http://www.cyberlandia.net</string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
</map>
|
||||
|
||||
<!-- The Gor Grid -->
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>thegorgrid</string>
|
||||
|
||||
<key>gridname</key>
|
||||
<string>The Gor Grid</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://thegorgrid.com:8002</string>
|
||||
<key>loginpage</key>
|
||||
<string>http://thegorgrid.com/loginscreen.php</string>
|
||||
<key>website</key>
|
||||
<string>http://thegorgrid.com/</string>
|
||||
|
||||
<key>register</key>
|
||||
<string>http://thegorgrid.com/index.php?page=create</string>
|
||||
<key>password</key>
|
||||
<string>http://thegorgrid.com/index.php?page=change</string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
</map>
|
||||
|
||||
<!-- GiantGrid -->
|
||||
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>giantgrid</string>
|
||||
<key>gridname</key>
|
||||
<string>GiantGrid</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://Gianttest.no-ip.biz:8002/</string>
|
||||
|
||||
<key>loginpage</key>
|
||||
<string>http://gianttest.no-ip.biz:80/gridsplash?method=login</string>
|
||||
<key>helperuri</key>
|
||||
<string>http://gianttest.no-ip.biz/giantmap/</string>
|
||||
<key>version</key>
|
||||
<string>0</string>
|
||||
</map>
|
||||
|
||||
<!-- Local Host -->
|
||||
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>localhost</string>
|
||||
<key>gridname</key>
|
||||
<string>Local Host</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://127.0.0.1:9000/</string>
|
||||
|
||||
<key>loginpage</key>
|
||||
<string />
|
||||
<key>helperuri</key>
|
||||
<string>http://127.0.0.1:9000/</string>
|
||||
<key>version</key>
|
||||
<string>1</string>
|
||||
</map>
|
||||
|
||||
<!-- Local Host -->
|
||||
|
||||
<map>
|
||||
<key>gridnick</key>
|
||||
<string>gridproxy</string>
|
||||
<key>gridname</key>
|
||||
<string>Grid Proxy</string>
|
||||
<key>platform</key>
|
||||
<string>OpenSim</string>
|
||||
<key>loginuri</key>
|
||||
<string>http://127.0.0.1:8080/</string>
|
||||
<key>loginpage</key>
|
||||
<string />
|
||||
<key>helperuri</key>
|
||||
<string>http://127.0.0.1:8080/</string>
|
||||
<key>version</key>
|
||||
<string>1</string>
|
||||
</map>
|
||||
|
||||
</array>
|
||||
</llsd>
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bfaa316973c5d774593d35cb9ee33169
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user