mirror of
https://github.com/opensim/opensim.git
synced 2026-07-16 12:42:02 +08:00
*Parcel now sends ParcelProperties when the owner changes information as soon as the information is changed
372 lines
17 KiB
C#
372 lines
17 KiB
C#
/*
|
|
* Copyright (c) Contributors, http://www.openmetaverse.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 OpenSim 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 System.Collections.Generic;
|
|
using System.Text;
|
|
using libsecondlife;
|
|
using libsecondlife.Packets;
|
|
using OpenSim.RegionServer.Client;
|
|
|
|
namespace OpenSim.RegionServer.Simulator
|
|
{
|
|
partial class Avatar
|
|
{
|
|
public override void update()
|
|
{
|
|
if (!this.childAvatar)
|
|
{
|
|
if (this._physActor == null)
|
|
{
|
|
//HACKHACK: Note to work out why this entity does not have a physics actor
|
|
// and prehaps create one.
|
|
return;
|
|
}
|
|
libsecondlife.LLVector3 pos2 = new LLVector3(this._physActor.Position.X, this._physActor.Position.Y, this._physActor.Position.Z);
|
|
if (this.updateflag)
|
|
{
|
|
//need to send movement info
|
|
//so create the improvedterseobjectupdate packet
|
|
//use CreateTerseBlock()
|
|
ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = CreateTerseBlock();
|
|
ImprovedTerseObjectUpdatePacket terse = new ImprovedTerseObjectUpdatePacket();
|
|
terse.RegionData.RegionHandle = m_world.m_regInfo.RegionHandle;
|
|
terse.RegionData.TimeDilation = 64096;
|
|
terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
|
|
terse.ObjectData[0] = terseBlock;
|
|
List<Avatar> avList = this.m_world.RequestAvatarList();
|
|
foreach (Avatar client in avList)
|
|
{
|
|
client.SendPacketToViewer(terse);
|
|
}
|
|
|
|
updateflag = false;
|
|
//this._updateCount = 0;
|
|
}
|
|
else
|
|
{
|
|
|
|
if ((pos2 != this.positionLastFrame) || (this.movementflag == 16))
|
|
{
|
|
_updateCount++;
|
|
if (((!PhysicsEngineFlying) && (_updateCount > 3)) || (PhysicsEngineFlying) && (_updateCount > 0))
|
|
{
|
|
//It has been a while since last update was sent so lets send one.
|
|
ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = CreateTerseBlock();
|
|
ImprovedTerseObjectUpdatePacket terse = new ImprovedTerseObjectUpdatePacket();
|
|
terse.RegionData.RegionHandle = m_world.m_regInfo.RegionHandle;
|
|
terse.RegionData.TimeDilation = 64096;
|
|
terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
|
|
terse.ObjectData[0] = terseBlock;
|
|
List<Avatar> avList = this.m_world.RequestAvatarList();
|
|
foreach (Avatar client in avList)
|
|
{
|
|
client.SendPacketToViewer(terse);
|
|
}
|
|
_updateCount = 0;
|
|
}
|
|
|
|
if (this.movementflag == 16)
|
|
{
|
|
movementflag = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (positionFrameBeforeLast != pos2)
|
|
{
|
|
this.positionFrameBeforeLast = this.positionLastFrame;
|
|
this.positionLastFrame = pos2;
|
|
int tempRoundedX = (int)Math.Round(positionLastFrame.X);
|
|
int tempRoundedY = (int)Math.Round(positionLastFrame.Y);
|
|
if (this.positionRoundedX != tempRoundedX || this.positionRoundedY != tempRoundedY)
|
|
{
|
|
|
|
this.positionRoundedX = tempRoundedX;
|
|
this.positionRoundedY = tempRoundedY;
|
|
int currentParcelLocalID = m_world.parcelManager.getParcel(tempRoundedX, tempRoundedY).parcelData.localID;
|
|
if(currentParcelLocalID != this.positionParcelHoverLocalID)
|
|
{
|
|
|
|
Console.WriteLine("NEW PARCEL: " + m_world.parcelManager.getParcel(tempRoundedX, tempRoundedY).parcelData.parcelName);
|
|
m_world.parcelManager.getParcel(tempRoundedX, tempRoundedY).sendParcelProperties(this.parcelUpdateSequenceIncrement, false, 0,this.ControllingClient);
|
|
this.positionParcelHoverLocalID = currentParcelLocalID;
|
|
this.parcelUpdateSequenceIncrement++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!this.ControllingClient.m_sandboxMode)
|
|
{
|
|
if (pos2.X < 0)
|
|
{
|
|
ControllingClient.CrossSimBorder(new LLVector3(this._physActor.Position.X, this._physActor.Position.Y, this._physActor.Position.Z));
|
|
}
|
|
|
|
if (pos2.Y < 0)
|
|
{
|
|
ControllingClient.CrossSimBorder(new LLVector3(this._physActor.Position.X, this._physActor.Position.Y, this._physActor.Position.Z));
|
|
}
|
|
|
|
if (pos2.X > 255)
|
|
{
|
|
ControllingClient.CrossSimBorder(new LLVector3(this._physActor.Position.X, this._physActor.Position.Y, this._physActor.Position.Z));
|
|
}
|
|
|
|
if (pos2.Y > 255)
|
|
{
|
|
ControllingClient.CrossSimBorder(new LLVector3(this._physActor.Position.X, this._physActor.Position.Y, this._physActor.Position.Z));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public void SendUpdateToOtherClient(Avatar remoteAvatar)
|
|
{
|
|
ObjectUpdatePacket objupdate = CreateUpdatePacket();
|
|
remoteAvatar.SendPacketToViewer(objupdate);
|
|
}
|
|
|
|
public ObjectUpdatePacket CreateUpdatePacket()
|
|
{
|
|
System.Text.Encoding _enc = System.Text.Encoding.ASCII;
|
|
//send a objectupdate packet with information about the clients avatar
|
|
ObjectUpdatePacket objupdate = new ObjectUpdatePacket();
|
|
objupdate.RegionData.RegionHandle = m_world.m_regInfo.RegionHandle;
|
|
objupdate.RegionData.TimeDilation = 64096;
|
|
objupdate.ObjectData = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock[1];
|
|
|
|
objupdate.ObjectData[0] = AvatarTemplate;
|
|
//give this avatar object a local id and assign the user a name
|
|
objupdate.ObjectData[0].ID = this.localid;
|
|
objupdate.ObjectData[0].FullID = ControllingClient.AgentID;
|
|
objupdate.ObjectData[0].NameValue = _enc.GetBytes("FirstName STRING RW SV " + firstname + "\nLastName STRING RW SV " + lastname + " \0");
|
|
|
|
libsecondlife.LLVector3 pos2 = new LLVector3((float)this._physActor.Position.X, (float)this._physActor.Position.Y, (float)this._physActor.Position.Z);
|
|
|
|
byte[] pb = pos2.GetBytes();
|
|
|
|
Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length);
|
|
return objupdate;
|
|
}
|
|
|
|
public void SendInitialPosition()
|
|
{
|
|
System.Text.Encoding _enc = System.Text.Encoding.ASCII;
|
|
//send a objectupdate packet with information about the clients avatar
|
|
|
|
ObjectUpdatePacket objupdate = new ObjectUpdatePacket();
|
|
objupdate.RegionData.RegionHandle = m_world.m_regInfo.RegionHandle;
|
|
objupdate.RegionData.TimeDilation = 64096;
|
|
objupdate.ObjectData = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock[1];
|
|
objupdate.ObjectData[0] = AvatarTemplate;
|
|
//give this avatar object a local id and assign the user a name
|
|
|
|
objupdate.ObjectData[0].ID = this.localid;
|
|
this.uuid = objupdate.ObjectData[0].FullID = ControllingClient.AgentID;
|
|
objupdate.ObjectData[0].NameValue = _enc.GetBytes("FirstName STRING RW SV " + firstname + "\nLastName STRING RW SV " + lastname + " \0");
|
|
libsecondlife.LLVector3 pos2 = new LLVector3((float)this.Pos.X, (float)this.Pos.Y, (float)this.Pos.Z);
|
|
byte[] pb = pos2.GetBytes();
|
|
Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length);
|
|
m_world._localNumber++;
|
|
|
|
List<Avatar> avList = this.m_world.RequestAvatarList();
|
|
foreach (Avatar client in avList)
|
|
{
|
|
client.SendPacketToViewer(objupdate);
|
|
if (client.ControllingClient.AgentID != this.ControllingClient.AgentID)
|
|
{
|
|
SendAppearanceToOtherAgent(client);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SendOurAppearance()
|
|
{
|
|
ControllingClient.SendAppearance(this.Wearables);
|
|
}
|
|
|
|
public void SendOurAppearance(ClientView OurClient)
|
|
{
|
|
//event handler for wearables request
|
|
this.SendOurAppearance();
|
|
}
|
|
|
|
public void SendAppearanceToOtherAgent(Avatar avatarInfo)
|
|
{
|
|
AvatarAppearancePacket avp = new AvatarAppearancePacket();
|
|
avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218];
|
|
avp.ObjectData.TextureEntry = this.avatarAppearanceTexture.ToBytes();
|
|
|
|
AvatarAppearancePacket.VisualParamBlock avblock = null;
|
|
for (int i = 0; i < 218; i++)
|
|
{
|
|
avblock = new AvatarAppearancePacket.VisualParamBlock();
|
|
avblock.ParamValue = visualParams[i];
|
|
avp.VisualParam[i] = avblock;
|
|
}
|
|
|
|
avp.Sender.IsTrial = false;
|
|
avp.Sender.ID = ControllingClient.AgentID;
|
|
avatarInfo.SendPacketToViewer(avp);
|
|
}
|
|
|
|
public void SetAppearance(byte[] texture, AgentSetAppearancePacket.VisualParamBlock[] visualParam)
|
|
{
|
|
LLObject.TextureEntry tex = new LLObject.TextureEntry(texture, 0, texture.Length);
|
|
this.avatarAppearanceTexture = tex;
|
|
|
|
for (int i = 0; i < visualParam.Length; i++)
|
|
{
|
|
this.visualParams[i] = visualParam[i].ParamValue;
|
|
}
|
|
|
|
List<Avatar> avList = this.m_world.RequestAvatarList();
|
|
foreach (Avatar client in avList)
|
|
{
|
|
if (client.ControllingClient.AgentID != this.ControllingClient.AgentID)
|
|
{
|
|
SendAppearanceToOtherAgent(client);
|
|
}
|
|
}
|
|
}
|
|
|
|
public ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateTerseBlock()
|
|
{
|
|
byte[] bytes = new byte[60];
|
|
int i = 0;
|
|
ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
|
|
|
|
dat.TextureEntry = new byte[0];// AvatarTemplate.TextureEntry;
|
|
libsecondlife.LLVector3 pos2 = new LLVector3(0, 0, 0);
|
|
lock (m_world.LockPhysicsEngine)
|
|
{
|
|
pos2 = new LLVector3(this._physActor.Position.X, this._physActor.Position.Y, this._physActor.Position.Z);
|
|
}
|
|
|
|
uint ID = this.localid;
|
|
|
|
bytes[i++] = (byte)(ID % 256);
|
|
bytes[i++] = (byte)((ID >> 8) % 256);
|
|
bytes[i++] = (byte)((ID >> 16) % 256);
|
|
bytes[i++] = (byte)((ID >> 24) % 256);
|
|
bytes[i++] = 0;
|
|
bytes[i++] = 1;
|
|
i += 14;
|
|
bytes[i++] = 128;
|
|
bytes[i++] = 63;
|
|
|
|
byte[] pb = pos2.GetBytes();
|
|
Array.Copy(pb, 0, bytes, i, pb.Length);
|
|
i += 12;
|
|
ushort InternVelocityX;
|
|
ushort InternVelocityY;
|
|
ushort InternVelocityZ;
|
|
Axiom.MathLib.Vector3 internDirec = new Axiom.MathLib.Vector3(0, 0, 0);
|
|
lock (m_world.LockPhysicsEngine)
|
|
{
|
|
internDirec = new Axiom.MathLib.Vector3(this._physActor.Velocity.X, this._physActor.Velocity.Y, this._physActor.Velocity.Z);
|
|
}
|
|
internDirec = internDirec / 128.0f;
|
|
internDirec.x += 1;
|
|
internDirec.y += 1;
|
|
internDirec.z += 1;
|
|
|
|
InternVelocityX = (ushort)(32768 * internDirec.x);
|
|
InternVelocityY = (ushort)(32768 * internDirec.y);
|
|
InternVelocityZ = (ushort)(32768 * internDirec.z);
|
|
|
|
ushort ac = 32767;
|
|
bytes[i++] = (byte)(InternVelocityX % 256);
|
|
bytes[i++] = (byte)((InternVelocityX >> 8) % 256);
|
|
bytes[i++] = (byte)(InternVelocityY % 256);
|
|
bytes[i++] = (byte)((InternVelocityY >> 8) % 256);
|
|
bytes[i++] = (byte)(InternVelocityZ % 256);
|
|
bytes[i++] = (byte)((InternVelocityZ >> 8) % 256);
|
|
|
|
//accel
|
|
bytes[i++] = (byte)(ac % 256);
|
|
bytes[i++] = (byte)((ac >> 8) % 256);
|
|
bytes[i++] = (byte)(ac % 256);
|
|
bytes[i++] = (byte)((ac >> 8) % 256);
|
|
bytes[i++] = (byte)(ac % 256);
|
|
bytes[i++] = (byte)((ac >> 8) % 256);
|
|
|
|
//rot
|
|
bytes[i++] = (byte)(ac % 256);
|
|
bytes[i++] = (byte)((ac >> 8) % 256);
|
|
bytes[i++] = (byte)(ac % 256);
|
|
bytes[i++] = (byte)((ac >> 8) % 256);
|
|
bytes[i++] = (byte)(ac % 256);
|
|
bytes[i++] = (byte)((ac >> 8) % 256);
|
|
bytes[i++] = (byte)(ac % 256);
|
|
bytes[i++] = (byte)((ac >> 8) % 256);
|
|
|
|
//rotation vel
|
|
bytes[i++] = (byte)(ac % 256);
|
|
bytes[i++] = (byte)((ac >> 8) % 256);
|
|
bytes[i++] = (byte)(ac % 256);
|
|
bytes[i++] = (byte)((ac >> 8) % 256);
|
|
bytes[i++] = (byte)(ac % 256);
|
|
bytes[i++] = (byte)((ac >> 8) % 256);
|
|
|
|
dat.Data = bytes;
|
|
return (dat);
|
|
}
|
|
|
|
// Sends animation update
|
|
public void SendAnimPack(LLUUID animID, int seq)
|
|
{
|
|
AvatarAnimationPacket ani = new AvatarAnimationPacket();
|
|
ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[1];
|
|
ani.AnimationSourceList[0] = new AvatarAnimationPacket.AnimationSourceListBlock();
|
|
ani.AnimationSourceList[0].ObjectID = ControllingClient.AgentID;
|
|
ani.Sender = new AvatarAnimationPacket.SenderBlock();
|
|
ani.Sender.ID = ControllingClient.AgentID;
|
|
ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[1];
|
|
ani.AnimationList[0] = new AvatarAnimationPacket.AnimationListBlock();
|
|
ani.AnimationList[0].AnimID = this.current_anim = animID;
|
|
ani.AnimationList[0].AnimSequenceID = this.anim_seq = seq;
|
|
|
|
List<Avatar> avList = this.m_world.RequestAvatarList();
|
|
foreach (Avatar client in avList)
|
|
{
|
|
client.SendPacketToViewer(ani);
|
|
}
|
|
|
|
}
|
|
|
|
public void SendAnimPack()
|
|
{
|
|
this.SendAnimPack(this.current_anim, this.anim_seq);
|
|
}
|
|
|
|
}
|
|
}
|