/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* 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 OpenSimulator Project 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 DEVELOPERS ``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 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.
*/
using System;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.ScriptEngine.Shared;
//using log4net;
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
namespace OpenSim.Region.ScriptEngine.Yengine
{
///
/// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it.
///
public partial class Yengine
{
public static readonly object[] zeroObjectArray = new object[0];
public static readonly object[] oneObjectArrayOne = new object[1] { 1 };
private void InitEvents()
{
m_log.Info("[YEngine] Hooking up to server events");
EventManager eManager = this.World.EventManager;
eManager.OnAttach += attach;
eManager.OnObjectGrab += touch_start;
eManager.OnObjectGrabbing += touch;
eManager.OnObjectDeGrab += touch_end;
eManager.OnScriptChangedEvent += changed;
eManager.OnScriptAtTargetEvent += at_target;
eManager.OnScriptNotAtTargetEvent += not_at_target;
eManager.OnScriptAtRotTargetEvent += at_rot_target;
eManager.OnScriptNotAtRotTargetEvent += not_at_rot_target;
eManager.OnScriptMovingStartEvent += moving_start;
eManager.OnScriptMovingEndEvent += moving_end;
eManager.OnScriptControlEvent += control;
eManager.OnScriptColliderStart += collision_start;
eManager.OnScriptColliding += collision;
eManager.OnScriptCollidingEnd += collision_end;
eManager.OnScriptLandColliderStart += land_collision_start;
eManager.OnScriptLandColliding += land_collision;
eManager.OnScriptLandColliderEnd += land_collision_end;
eManager.OnScriptListenEvent += script_listen;
IMoneyModule money = this.World.RequestModuleInterface();
if(money != null)
{
money.OnObjectPaid += HandleObjectPaid;
}
}
///
/// When an object gets paid by an avatar and generates the paid event,
/// this will pipe it to the script engine
///
/// Object ID that got paid
/// Agent Id that did the paying
/// Amount paid
private void HandleObjectPaid(UUID objectID, UUID agentID,
int amount)
{
// Add to queue for all scripts in ObjectID object
DetectParams[] det = new DetectParams[1];
det[0] = new DetectParams();
det[0].Key = agentID;
det[0].Populate(this.World);
// Since this is an event from a shared module, all scenes will
// get it. But only one has the object in question. The others
// just ignore it.
//
SceneObjectPart part = World.GetSceneObjectPart(objectID);
if(part == null)
return;
if((part.ScriptEvents & scriptEvents.money) == 0)
part = part.ParentGroup.RootPart;
Verbose("Paid: " + objectID + " from " + agentID + ", amount " + amount);
if(part != null)
{
money(part.LocalId, agentID, amount, det);
}
}
///
/// Handles piping the proper stuff to The script engine for touching
/// Including DetectedParams
///
///
///
///
///
///
public void touch_start(uint localID, uint originalID, Vector3 offsetPos,
IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
{
touches(localID, originalID, offsetPos, remoteClient, surfaceArgs, "touch_start");
}
public void touch(uint localID, uint originalID, Vector3 offsetPos,
IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
{
touches(localID, originalID, offsetPos, remoteClient, surfaceArgs, "touch");
}
private static Vector3 zeroVec3 = new Vector3(0, 0, 0);
public void touch_end(uint localID, uint originalID, IClientAPI remoteClient,
SurfaceTouchEventArgs surfaceArgs)
{
touches(localID, originalID, zeroVec3, remoteClient, surfaceArgs, "touch_end");
}
private void touches(uint localID, uint originalID, Vector3 offsetPos,
IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs, string eventname)
{
if (m_Exiting)
return;
SceneObjectPart part = World.GetSceneObjectPart(localID);
if(part == null || part.IsDeleted)
return;
int linknum;
if(originalID != 0 && originalID != localID)
{
SceneObjectPart srcpart = World.GetSceneObjectPart(originalID);
if(srcpart == null || part.IsDeleted)
return;
linknum = srcpart.LinkNum;
}
else
linknum = part.LinkNum;
DetectParams det = new DetectParams();
det.Key = remoteClient.AgentId;
det.Populate(World);
det.OffsetPos = new LSL_Vector(offsetPos.X,
offsetPos.Y,
offsetPos.Z);
det.LinkNum = linknum;
if(surfaceArgs != null)
{
det.SurfaceTouchArgs = surfaceArgs;
}
// Add to queue for all scripts in ObjectID object
PostPrimEvent(part, new EventParams(
eventname, oneObjectArrayOne,
new DetectParams[] { det }));
}
public void changed(uint localID, uint change, object parameter)
{
int ch = (int)change;
// Add to queue for all scripts in localID, Object pass change.
if(parameter == null)
{
PostObjectEvent(localID, new EventParams(
"changed", new object[] { ch },
zeroDetectParams));
return;
}
if ( parameter is UUID)
{
DetectParams det = new DetectParams();
det.Key = (UUID)parameter;
PostObjectEvent(localID, new EventParams(
"changed", new object[] { ch },
new DetectParams[] { det }));
return;
}
}
public void script_listen(UUID scriptID, int channel, string name, UUID id, string message)
{
object[] resobj = new object[]
{
new LSL_Types.LSLInteger(channel),
new LSL_Types.LSLString(name),
new LSL_Types.LSLString(id.ToString()),
new LSL_Types.LSLString(message)
};
PostScriptEvent(scriptID, new EventParams("listen", resobj, new DetectParams[0]));
}
// state_entry: not processed here
// state_exit: not processed here
public void money(uint localID, UUID agentID, int amount, DetectParams[] det)
{
PostObjectEvent(localID, new EventParams(
"money", new object[] {
agentID.ToString(),
amount },
det));
}
public void collision_start(uint localID, ColliderArgs col)
{
collisions(localID, col, "collision_start");
}
public void collision(uint localID, ColliderArgs col)
{
collisions(localID, col, "collision");
}
public void collision_end(uint localID, ColliderArgs col)
{
collisions(localID, col, "collision_end");
}
private void collisions(uint localID, ColliderArgs col, string eventname)
{
int dc = col.Colliders.Count;
if(dc > 0)
{
DetectParams[] det = new DetectParams[dc];
int i = 0;
foreach(DetectedObject detobj in col.Colliders)
{
DetectParams d = new DetectParams();
det[i++] = d;
d.Key = detobj.keyUUID;
d.Populate(World, detobj);
}
this.PostObjectEvent(localID, new EventParams(
eventname,
new Object[] { dc },
det));
}
}
public void land_collision_start(uint localID, ColliderArgs col)
{
land_collisions(localID, col, "land_collision_start");
}
public void land_collision(uint localID, ColliderArgs col)
{
land_collisions(localID, col, "land_collision");
}
public void land_collision_end(uint localID, ColliderArgs col)
{
land_collisions(localID, col, "land_collision_end");
}
private void land_collisions(uint localID, ColliderArgs col, string eventname)
{
foreach(DetectedObject detobj in col.Colliders)
{
LSL_Vector vec = new LSL_Vector(detobj.posVector.X,
detobj.posVector.Y,
detobj.posVector.Z);
EventParams eps = new EventParams(eventname,
new Object[] { vec },
zeroDetectParams);
this.PostObjectEvent(localID, eps);
}
}
// timer: not handled here
// listen: not handled here
public void control(UUID itemID, UUID agentID, uint held, uint change)
{
this.PostScriptEvent(itemID, new EventParams(
"control", new object[] {
agentID.ToString(),
(int)held,
(int)change},
zeroDetectParams));
}
public void email(uint localID, UUID itemID, string timeSent,
string address, string subject, string message, int numLeft)
{
this.PostObjectEvent(localID, new EventParams(
"email", new object[] {
timeSent,
address,
subject,
message,
numLeft},
zeroDetectParams));
}
public void at_target(UUID scriptID, uint handle, Vector3 targetpos, Vector3 atpos)
{
PostScriptEvent(scriptID, new EventParams(
"at_target", new object[] {
(int)handle,
new LSL_Vector(targetpos.X,targetpos.Y,targetpos.Z),
new LSL_Vector(atpos.X,atpos.Y,atpos.Z) },
zeroDetectParams));
}
public void not_at_target(UUID scriptID)
{
PostScriptEvent(scriptID, new EventParams(
"not_at_target", zeroObjectArray,
zeroDetectParams));
}
public void at_rot_target(UUID scriptID, uint handle, OpenMetaverse.Quaternion targetrot, OpenMetaverse.Quaternion atrot)
{
PostScriptEvent(scriptID, new EventParams(
"at_rot_target",
new object[] {
new LSL_Integer(handle),
new LSL_Rotation(targetrot.X, targetrot.Y, targetrot.Z, targetrot.W),
new LSL_Rotation(atrot.X, atrot.Y, atrot.Z, atrot.W)
},
zeroDetectParams));
}
public void not_at_rot_target(UUID scriptID)
{
PostScriptEvent(scriptID, new EventParams(
"not_at_rot_target", zeroObjectArray,
zeroDetectParams));
}
// run_time_permissions: not handled here
public void attach(uint localID, UUID itemID, UUID avatar)
{
this.PostObjectEvent(localID, new EventParams(
"attach", new object[] {
avatar.ToString() },
zeroDetectParams));
}
// dataserver: not handled here
// link_message: not handled here
public void moving_start(uint localID)
{
this.PostObjectEvent(localID, new EventParams(
"moving_start", zeroObjectArray,
zeroDetectParams));
}
public void moving_end(uint localID)
{
this.PostObjectEvent(localID, new EventParams(
"moving_end", zeroObjectArray,
zeroDetectParams));
}
// object_rez: not handled here
// remote_data: not handled here
// http_response: not handled here
}
}