Simian:
* First pass at persistence support * Fixed a chat crashing bug * Remove avatars from the scene on logout * Sanity check before adding objects to the scene in ObjectAdd * Sanity check in CompleteAgentMovementHandler if the avatar is already in the scene * Added ContainsKey() to DoubleDictionary git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@2245 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
@@ -18,7 +18,6 @@ namespace Simian.Extensions
|
||||
server.UDP.RegisterPacketCallback(PacketType.UseCircuitCode, new PacketCallback(UseCircuitCodeHandler));
|
||||
server.UDP.RegisterPacketCallback(PacketType.StartPingCheck, new PacketCallback(StartPingCheckHandler));
|
||||
server.UDP.RegisterPacketCallback(PacketType.LogoutRequest, new PacketCallback(LogoutRequestHandler));
|
||||
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
@@ -74,15 +73,6 @@ namespace Simian.Extensions
|
||||
{
|
||||
LogoutRequestPacket request = (LogoutRequestPacket)packet;
|
||||
|
||||
LogoutReplyPacket reply = new LogoutReplyPacket();
|
||||
reply.AgentData.AgentID = agent.AgentID;
|
||||
reply.AgentData.SessionID = agent.SessionID;
|
||||
reply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
|
||||
reply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
|
||||
reply.InventoryData[0].ItemID = UUID.Zero;
|
||||
|
||||
server.UDP.SendPacket(agent.AgentID, reply, PacketCategory.Transaction);
|
||||
|
||||
lock (server.Agents)
|
||||
{
|
||||
if (server.Agents.ContainsKey(agent.AgentID))
|
||||
@@ -96,8 +86,25 @@ namespace Simian.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the avatar from the scene
|
||||
SimulationObject obj;
|
||||
if (server.Scene.TryGetObject(agent.AgentID, out obj))
|
||||
server.Scene.ObjectRemove(this, obj);
|
||||
else
|
||||
Logger.Log("Logout request from an agent that is not in the scene", Helpers.LogLevel.Warning);
|
||||
|
||||
// Remove the UDP client
|
||||
server.UDP.RemoveClient(agent);
|
||||
|
||||
LogoutReplyPacket reply = new LogoutReplyPacket();
|
||||
reply.AgentData.AgentID = agent.AgentID;
|
||||
reply.AgentData.SessionID = agent.SessionID;
|
||||
reply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
|
||||
reply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
|
||||
reply.InventoryData[0].ItemID = UUID.Zero;
|
||||
|
||||
server.UDP.SendPacket(agent.AgentID, reply, PacketCategory.Transaction);
|
||||
|
||||
//HACK: Notify everyone when someone logs off
|
||||
OfflineNotificationPacket offline = new OfflineNotificationPacket();
|
||||
offline.AgentBlock = new OfflineNotificationPacket.AgentBlockBlock[1];
|
||||
|
||||
@@ -30,7 +30,8 @@ namespace Simian.Extensions
|
||||
ChatFromViewerPacket viewerChat = (ChatFromViewerPacket)packet;
|
||||
|
||||
string message = Utils.BytesToString(viewerChat.ChatData.Message);
|
||||
if (viewerChat.ChatData.Channel != 0 || message.Substring(0, 1) == "/") return; //not public chat
|
||||
if (viewerChat.ChatData.Channel != 0 || (message.Length > 0 && message.Substring(0, 1) == "/"))
|
||||
return; //not public chat
|
||||
|
||||
//TODO: add distance constraints to AudibleLevel and Message
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ namespace Simian.Extensions
|
||||
Server.UDP.RegisterPacketCallback(PacketType.ObjectDelink, new PacketCallback(ObjectDelinkHandler));
|
||||
Server.UDP.RegisterPacketCallback(PacketType.ObjectShape, new PacketCallback(ObjectShapeHandler));
|
||||
Server.UDP.RegisterPacketCallback(PacketType.ObjectFlagUpdate, new PacketCallback(ObjectFlagUpdateHandler));
|
||||
Server.UDP.RegisterPacketCallback(PacketType.ObjectExtraParams, new PacketCallback(ObjectExtraParamsHandler));
|
||||
Server.UDP.RegisterPacketCallback(PacketType.ObjectImage, new PacketCallback(ObjectImageHandler));
|
||||
Server.UDP.RegisterPacketCallback(PacketType.DeRezObject, new PacketCallback(DeRezObjectHandler));
|
||||
Server.UDP.RegisterPacketCallback(PacketType.MultipleObjectUpdate, new PacketCallback(MultipleObjectUpdateHandler));
|
||||
Server.UDP.RegisterPacketCallback(PacketType.RequestObjectPropertiesFamily, new PacketCallback(RequestObjectPropertiesFamilyHandler));
|
||||
@@ -481,6 +483,27 @@ namespace Simian.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectExtraParamsHandler(Packet packet, Agent agent)
|
||||
{
|
||||
ObjectExtraParamsPacket extra = (ObjectExtraParamsPacket)packet;
|
||||
|
||||
for (int i = 0; i < extra.ObjectData.Length; i++)
|
||||
{
|
||||
ObjectExtraParamsPacket.ObjectDataBlock block = extra.ObjectData[i];
|
||||
|
||||
SimulationObject obj;
|
||||
if (Server.Scene.TryGetObject(block.ObjectLocalID, out obj))
|
||||
{
|
||||
ExtraParamType type = (ExtraParamType)block.ParamType;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectImageHandler(Packet packet, Agent agent)
|
||||
{
|
||||
}
|
||||
|
||||
void DeRezObjectHandler(Packet packet, Agent agent)
|
||||
{
|
||||
DeRezObjectPacket derez = (DeRezObjectPacket)packet;
|
||||
|
||||
@@ -55,6 +55,14 @@ namespace Simian.Extensions
|
||||
|
||||
public bool ObjectAdd(object sender, Agent creator, SimulationObject obj, PrimFlags creatorFlags)
|
||||
{
|
||||
// Check if the object already exists in the scene
|
||||
if (sceneObjects.ContainsKey(obj.Prim.ID))
|
||||
{
|
||||
Logger.Log(String.Format("Attempting to add duplicate object {0} to the scene",
|
||||
obj.Prim.ID), Helpers.LogLevel.Warning);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assign a unique LocalID to this object
|
||||
obj.Prim.LocalID = (uint)Interlocked.Increment(ref currentLocalID);
|
||||
|
||||
@@ -205,30 +213,36 @@ namespace Simian.Extensions
|
||||
// Give testers a provisionary balance of 1000L
|
||||
agent.Balance = 1000;
|
||||
|
||||
// Send a response back to the client
|
||||
AgentMovementCompletePacket complete = new AgentMovementCompletePacket();
|
||||
complete.AgentData.AgentID = agent.AgentID;
|
||||
complete.AgentData.SessionID = agent.SessionID;
|
||||
complete.Data.LookAt = Vector3.UnitX;
|
||||
complete.Data.Position = avatar.Position;
|
||||
complete.Data.RegionHandle = server.RegionHandle;
|
||||
complete.Data.Timestamp = Utils.DateTimeToUnixTime(DateTime.Now);
|
||||
complete.SimData.ChannelVersion = Utils.StringToBytes("Simian");
|
||||
|
||||
server.UDP.SendPacket(agent.AgentID, complete, PacketCategory.Transaction);
|
||||
|
||||
// Add this avatar as an object in the scene
|
||||
ObjectAdd(this, agent, new SimulationObject(agent.Avatar, server), PrimFlags.None);
|
||||
if (ObjectAdd(this, agent, new SimulationObject(agent.Avatar, server), PrimFlags.None))
|
||||
{
|
||||
// Send a response back to the client
|
||||
AgentMovementCompletePacket complete = new AgentMovementCompletePacket();
|
||||
complete.AgentData.AgentID = agent.AgentID;
|
||||
complete.AgentData.SessionID = agent.SessionID;
|
||||
complete.Data.LookAt = Vector3.UnitX;
|
||||
complete.Data.Position = avatar.Position;
|
||||
complete.Data.RegionHandle = server.RegionHandle;
|
||||
complete.Data.Timestamp = Utils.DateTimeToUnixTime(DateTime.Now);
|
||||
complete.SimData.ChannelVersion = Utils.StringToBytes("Simian");
|
||||
|
||||
// Send updates and appearances for every avatar to this new avatar
|
||||
SynchronizeStateTo(agent);
|
||||
server.UDP.SendPacket(agent.AgentID, complete, PacketCategory.Transaction);
|
||||
|
||||
//HACK: Notify everyone when someone logs on to the simulator
|
||||
OnlineNotificationPacket online = new OnlineNotificationPacket();
|
||||
online.AgentBlock = new OnlineNotificationPacket.AgentBlockBlock[1];
|
||||
online.AgentBlock[0] = new OnlineNotificationPacket.AgentBlockBlock();
|
||||
online.AgentBlock[0].AgentID = agent.AgentID;
|
||||
server.UDP.BroadcastPacket(online, PacketCategory.State);
|
||||
// Send updates and appearances for every avatar to this new avatar
|
||||
SynchronizeStateTo(agent);
|
||||
|
||||
//HACK: Notify everyone when someone logs on to the simulator
|
||||
OnlineNotificationPacket online = new OnlineNotificationPacket();
|
||||
online.AgentBlock = new OnlineNotificationPacket.AgentBlockBlock[1];
|
||||
online.AgentBlock[0] = new OnlineNotificationPacket.AgentBlockBlock();
|
||||
online.AgentBlock[0].AgentID = agent.AgentID;
|
||||
server.UDP.BroadcastPacket(online, PacketCategory.State);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("Received a CompleteAgentMovement from an avatar already in the scene, " +
|
||||
agent.FullName, Helpers.LogLevel.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
// HACK: The reduction provider will deprecate this at some point
|
||||
|
||||
87
Programs/Simian/Extensions/XMLPersistence.cs
Normal file
87
Programs/Simian/Extensions/XMLPersistence.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace Simian.Extensions
|
||||
{
|
||||
public class XMLPersistence : ISimianExtension, IPersistenceProvider
|
||||
{
|
||||
Simian server;
|
||||
|
||||
public XMLPersistence(Simian server)
|
||||
{
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
LLSD llsd;
|
||||
|
||||
try
|
||||
{
|
||||
XmlTextReader reader = new XmlTextReader(File.OpenRead(server.DataDir + "simiandata.xml"));
|
||||
llsd = LLSDParser.DeserializeXml(reader);
|
||||
reader.Close();
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log("Failed to load saved data: " + ex.Message, Helpers.LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (llsd is LLSDMap)
|
||||
{
|
||||
LLSDMap dictionary = (LLSDMap)llsd;
|
||||
|
||||
for (int i = 0; i < server.PersistentExtensions.Count; i++)
|
||||
{
|
||||
IPersistable persistable = server.PersistentExtensions[i];
|
||||
|
||||
LLSD savedData;
|
||||
if (dictionary.TryGetValue(persistable.ToString(), out savedData))
|
||||
{
|
||||
Logger.DebugLog("Loading saved data for " + persistable.ToString());
|
||||
persistable.Deserialize(savedData);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.DebugLog("No saved data found for " + persistable.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
LLSDMap dictionary = new LLSDMap(server.PersistentExtensions.Count);
|
||||
|
||||
for (int i = 0; i < server.PersistentExtensions.Count; i++)
|
||||
{
|
||||
IPersistable persistable = server.PersistentExtensions[i];
|
||||
|
||||
Logger.DebugLog("Storing persistant data for " + persistable.ToString());
|
||||
dictionary.Add(persistable.ToString(), persistable.Serialize());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
XmlTextWriter writer = new XmlTextWriter(server.DataDir + "simiandata.xml", System.Text.Encoding.UTF8);
|
||||
writer.WriteStartElement("llsd");
|
||||
LLSDParser.SerializeXmlElement(writer, dictionary);
|
||||
writer.WriteEndElement();
|
||||
writer.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log("Failed to save persistance data: " + ex.Message, Helpers.LogLevel.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user