예제 #1
0
        /// <summary>
        /// Setup the ObjectData parameters for a basic wooden cube prim
        /// </summary>
        /// <returns>ObjectData struct representing a basic wooden cube prim</returns>
        public static LLObject.ObjectData BuildCube()
        {
            LLObject.ObjectData prim = new LLObject.ObjectData();

            prim.PCode = PCode.Prim;
            prim.Material = LLObject.MaterialType.Wood;
            prim.ProfileCurve = LLObject.ProfileCurve.Square;
            prim.PathCurve = LLObject.PathCurve.Line;
            prim.ProfileEnd = 1f;
            prim.PathEnd = 1f;
            prim.PathScaleX = 1f;
            prim.PathScaleY = 1f;
            prim.PathRevolutions = 1f;
            
            return prim;
        }
예제 #2
0
        static void Main(string[] args)
        {
            if (args.Length != 8 && args.Length != 9)
            {
                Console.WriteLine("Usage: importprimscript.exe [firstname] [lastname] [password] " +
                    "[loginuri] [Simulator] [x] [y] [z] [input.primscript]" +
                    Environment.NewLine + "Example: importprimscript.exe My Bot password " + 
                    "Hooper 128 128 40 maya-export" + Path.DirectorySeparatorChar + "ant.primscript" +
                    Environment.NewLine + "(the loginuri is optional and only used for logging in to another grid)");
                Environment.Exit(-1);
            }

            // Strip quotes from any arguments
            for (int i = 0; i < args.Length; i++)
                args[i] = args[i].Trim(new char[] { '"' });

            // Parse the primscript file
            string scriptfilename = args[args.Length - 1];
            string error;
            List<Sculpt> sculpties = ParsePrimscript(scriptfilename, out error);
            scriptfilename = Path.GetFileNameWithoutExtension(scriptfilename);

            // Check for parsing errors
            if (error != String.Empty)
            {
                Console.WriteLine("An error was encountered reading the input file: " + error);
                Environment.Exit(-2);
            }
            else if (sculpties.Count == 0)
            {
                Console.WriteLine("No primitives were read from the input file");
                Environment.Exit(-3);
            }

            // Add callback handlers for asset uploads finishing. new prims spotted, and logging
            Client.Objects.OnNewPrim += new ObjectManager.NewPrimCallback(Objects_OnNewPrim);
            Logger.OnLogMessage += new Logger.LogCallback(Client_OnLogMessage);

            // Optimize the connection for our purposes
            Client.Self.Movement.Camera.Far = 64f;
            Client.Settings.MULTIPLE_SIMS = false;
            Client.Settings.SEND_AGENT_UPDATES = true;
            Client.Settings.DISABLE_AGENT_UPDATE_DUPLICATE_CHECK = true;
            Settings.LOG_LEVEL = Helpers.LogLevel.None;
            Client.Settings.ALWAYS_REQUEST_OBJECTS = true;
            Client.Settings.ALWAYS_DECODE_OBJECTS = true;
            Client.Throttle.Land = 0;
            Client.Throttle.Wind = 0;
            Client.Throttle.Cloud = 0;
            // Not sure if Asset or Texture will help with uploads, but it won't hurt
            Client.Throttle.Asset = 220000.0f;
            Client.Throttle.Texture = 446000.0f;
            Client.Throttle.Task = 446000.0f;

            // Create a handler for the event queue connecting, so we know when
            // it is safe to start uploading
            AutoResetEvent eventQueueEvent = new AutoResetEvent(false);
            NetworkManager.EventQueueRunningCallback eventQueueCallback =
                delegate(Simulator simulator)
                {
                    if (simulator == Client.Network.CurrentSim)
                        eventQueueEvent.Set();
                };
            Client.Network.OnEventQueueRunning += eventQueueCallback;

            int x = Int32.Parse(args[args.Length - 4]);
            int y = Int32.Parse(args[args.Length - 3]);
            int z = Int32.Parse(args[args.Length - 2]);
            string start = NetworkManager.StartLocation(args[args.Length - 5], x, y, z);

            LoginParams loginParams = Client.Network.DefaultLoginParams(args[0], args[1], args[2],
                "importprimscript", "1.4.0");
            loginParams.Start = start;
            if (args.Length == 9) loginParams.URI = args[3];

            // Attempt to login
            if (!Client.Network.Login(loginParams))
            {
                Console.WriteLine("Login failed: " + Client.Network.LoginMessage);
                Environment.Exit(-4);
            }

            // Need to be connected to the event queue before we can upload
            Console.WriteLine("Login succeeded, waiting for the event handler to connect...");
            if (!eventQueueEvent.WaitOne(1000 * 90, false))
            {
                Console.WriteLine("Event queue connection timed out, disconnecting...");
                Client.Network.Logout();
                Environment.Exit(-5);
            }

            // Don't need this anymore
            Client.Network.OnEventQueueRunning -= eventQueueCallback;

            // Set the root position for the import
            RootPosition = Client.Self.SimPosition;
            RootPosition.Z += 3.0f;

            // TODO: Check if our account balance is high enough to upload everything
            //

            // Create a folder to hold all of our texture uploads
            UploadFolderID = Client.Inventory.CreateFolder(Client.Inventory.InventorySkeleton.RootUUID, scriptfilename);

            // Loop through each sculpty and do what we need to do
            for (int i = 0; i < sculpties.Count; i++)
            {
                // Upload the sculpt map and texture
                sculpties[i].SculptID = UploadImage(sculpties[i].SculptFile, true);
                sculpties[i].TextureID = UploadImage(sculpties[i].TextureFile, false);

                // Check for failed uploads
                if (sculpties[i].SculptID == UUID.Zero)
                {
                    Console.WriteLine("Sculpt map " + sculpties[i].SculptFile + " failed to upload, skipping " + sculpties[i].Name);
                    continue;
                }
                else if (sculpties[i].TextureID == UUID.Zero)
                {
                    Console.WriteLine("Texture " + sculpties[i].TextureFile + " failed to upload, skipping " + sculpties[i].Name);
                    continue;
                }

                // Create basic spherical volume parameters. It will be set to
                // a scultpy in the callback for new objects being created
                LLObject.ObjectData volume = new LLObject.ObjectData();
                volume.PCode = PCode.Prim;
                volume.Material = LLObject.MaterialType.Wood;
                volume.PathScaleY = 0.5f;
                volume.PathCurve = LLObject.PathCurve.Circle;
                volume.ProfileCurve = LLObject.ProfileCurve.Circle;

                // Rez this prim
                CurrentSculpt = sculpties[i];
                Client.Objects.AddPrim(Client.Network.CurrentSim, volume, UUID.Zero, 
                    RootPosition + CurrentSculpt.Offset, CurrentSculpt.Scale, Quaternion.Identity);

                // Wait for the prim to rez and the properties be set for it
                if (!RezzedEvent.WaitOne(1000 * 10, false))
                {
                    Console.WriteLine("Timed out waiting for prim " + CurrentSculpt.Name + " to rez, skipping");
                    continue;
                }
            }

            CurrentSculpt = null;

            lock (RezzedPrims)
            {
                // Set full permissions for all of the objects
                Client.Objects.SetPermissions(Client.Network.CurrentSim, RezzedPrims, PermissionWho.All,
                    PermissionMask.All, true);

                // Link the entire object together
                Client.Objects.LinkPrims(Client.Network.CurrentSim, RezzedPrims);
            }

            Console.WriteLine("Rezzed, textured, and linked " + RezzedPrims.Count + " sculpted prims, logging out...");

            Client.Network.Logout();
        }
예제 #3
0
        /// <summary>
        /// Used for new prims, or significant changes to existing prims
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="simulator"></param>
        protected void UpdateHandler(Packet packet, Simulator simulator)
        {
            ObjectUpdatePacket update = (ObjectUpdatePacket)packet;
			UpdateDilation(simulator, update.RegionData.TimeDilation);

            for (int b = 0; b < update.ObjectData.Length; b++)
            {
                ObjectUpdatePacket.ObjectDataBlock block = update.ObjectData[b];

                Vector4 collisionPlane = Vector4.Zero;
                Vector3 position;
                Vector3 velocity;
                Vector3 acceleration;
                Quaternion rotation;
                Vector3 angularVelocity;
                NameValue[] nameValues;
                bool attachment = false;
                PCode pcode = (PCode)block.PCode;

                #region Relevance check

                // Check if we are interested in this object
                if (!Client.Settings.ALWAYS_DECODE_OBJECTS)
                {
                    switch (pcode)
                    {
                        case PCode.Grass:
                        case PCode.Tree:
                        case PCode.NewTree:
                            if (OnNewFoliage == null) continue;
                            break;
                        case PCode.Prim:
                            if (OnNewPrim == null) continue;
                            break;
                        case PCode.Avatar:
                            // Make an exception for updates about our own agent
                            if (block.FullID != Client.Self.AgentID && OnNewAvatar == null) continue;
                            break;
                        case PCode.ParticleSystem:
                            continue; // TODO: Do something with these
                    }
                }

                #endregion Relevance check

                #region NameValue parsing

                string nameValue = Helpers.FieldToUTF8String(block.NameValue);
                if (nameValue.Length > 0)
                {
                    string[] lines = nameValue.Split('\n');
                    nameValues = new NameValue[lines.Length];

                    for (int i = 0; i < lines.Length; i++)
                    {
                        if (!String.IsNullOrEmpty(lines[i]))
                        {
                            NameValue nv = new NameValue(lines[i]);
                            if (nv.Name == "AttachItemID") attachment = true;
                            nameValues[i] = nv;
                        }
                    }
                }
                else
                {
                    nameValues = new NameValue[0];
                }

                #endregion NameValue parsing

                #region Decode Object (primitive) parameters
                LLObject.ObjectData data = new LLObject.ObjectData();
                data.State = block.State;
                data.Material = (LLObject.MaterialType)block.Material;
                data.PathCurve = (LLObject.PathCurve)block.PathCurve;
                data.profileCurve = block.ProfileCurve;
                data.PathBegin = LLObject.UnpackBeginCut(block.PathBegin);
                data.PathEnd = LLObject.UnpackEndCut(block.PathEnd);
                data.PathScaleX = LLObject.UnpackPathScale(block.PathScaleX);
                data.PathScaleY = LLObject.UnpackPathScale(block.PathScaleY);
                data.PathShearX = LLObject.UnpackPathShear((sbyte)block.PathShearX);
                data.PathShearY = LLObject.UnpackPathShear((sbyte)block.PathShearY);
                data.PathTwist = LLObject.UnpackPathTwist(block.PathTwist);
                data.PathTwistBegin = LLObject.UnpackPathTwist(block.PathTwistBegin);
                data.PathRadiusOffset = LLObject.UnpackPathTwist(block.PathRadiusOffset);
                data.PathTaperX = LLObject.UnpackPathTaper(block.PathTaperX);
                data.PathTaperY = LLObject.UnpackPathTaper(block.PathTaperY);
                data.PathRevolutions = LLObject.UnpackPathRevolutions(block.PathRevolutions);
                data.PathSkew = LLObject.UnpackPathTwist(block.PathSkew);
                data.ProfileBegin = LLObject.UnpackBeginCut(block.ProfileBegin);
                data.ProfileEnd = LLObject.UnpackEndCut(block.ProfileEnd);
                data.ProfileHollow = LLObject.UnpackProfileHollow(block.ProfileHollow);
                data.PCode = pcode;
                #endregion

                #region Decode Additional packed parameters in ObjectData
                int pos = 0;
                switch (block.ObjectData.Length)
                {
                    case 76:
                        // Collision normal for avatar
                        collisionPlane = new Vector4(block.ObjectData, pos);
                        pos += 16;

                        goto case 60;
                    case 60:
                        // Position
                        position = new Vector3(block.ObjectData, pos);
                        pos += 12;
                        // Velocity
                        velocity = new Vector3(block.ObjectData, pos);
                        pos += 12;
                        // Acceleration
                        acceleration = new Vector3(block.ObjectData, pos);
                        pos += 12;
                        // Rotation (theta)
                        rotation = new Quaternion(block.ObjectData, pos, true);
                        pos += 12;
                        // Angular velocity (omega)
                        angularVelocity = new Vector3(block.ObjectData, pos);
                        pos += 12;

                        break;
                    case 48:
                        // Collision normal for avatar
                        collisionPlane = new Vector4(block.ObjectData, pos);
                        pos += 16;

                        goto case 32;
                    case 32:
                        // The data is an array of unsigned shorts

                        // Position
                        position = new Vector3(
                            Helpers.UInt16ToFloat(block.ObjectData, pos, -0.5f * 256.0f, 1.5f * 256.0f),
                            Helpers.UInt16ToFloat(block.ObjectData, pos + 2, -0.5f * 256.0f, 1.5f * 256.0f),
                            Helpers.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 3.0f * 256.0f));
                        pos += 6;
                        // Velocity
                        velocity = new Vector3(
                            Helpers.UInt16ToFloat(block.ObjectData, pos, -256.0f, 256.0f),
                            Helpers.UInt16ToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f),
                            Helpers.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 256.0f));
                        pos += 6;
                        // Acceleration
                        acceleration = new Vector3(
                            Helpers.UInt16ToFloat(block.ObjectData, pos, -256.0f, 256.0f),
                            Helpers.UInt16ToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f),
                            Helpers.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 256.0f));
                        pos += 6;
                        // Rotation (theta)
                        rotation = new Quaternion(
                            Helpers.UInt16ToFloat(block.ObjectData, pos, -1.0f, 1.0f),
                            Helpers.UInt16ToFloat(block.ObjectData, pos + 2, -1.0f, 1.0f),
                            Helpers.UInt16ToFloat(block.ObjectData, pos + 4, -1.0f, 1.0f),
                            Helpers.UInt16ToFloat(block.ObjectData, pos + 6, -1.0f, 1.0f));
                        pos += 8;
                        // Angular velocity (omega)
                        angularVelocity = new Vector3(
                            Helpers.UInt16ToFloat(block.ObjectData, pos, -256.0f, 256.0f),
                            Helpers.UInt16ToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f),
                            Helpers.UInt16ToFloat(block.ObjectData, pos + 4, -256.0f, 256.0f));
                        pos += 6;

                        break;
                    case 16:
                        // The data is an array of single bytes (8-bit numbers)

                        // Position
                        position = new Vector3(
                            Helpers.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f),
                            Helpers.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f),
                            Helpers.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f));
                        pos += 3;
                        // Velocity
                        velocity = new Vector3(
                            Helpers.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f),
                            Helpers.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f),
                            Helpers.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f));
                        pos += 3;
                        // Accleration
                        acceleration = new Vector3(
                            Helpers.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f),
                            Helpers.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f),
                            Helpers.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f));
                        pos += 3;
                        // Rotation
                        rotation = new Quaternion(
                            Helpers.ByteToFloat(block.ObjectData, pos, -1.0f, 1.0f),
                            Helpers.ByteToFloat(block.ObjectData, pos + 1, -1.0f, 1.0f),
                            Helpers.ByteToFloat(block.ObjectData, pos + 2, -1.0f, 1.0f),
                            Helpers.ByteToFloat(block.ObjectData, pos + 3, -1.0f, 1.0f));
                        pos += 4;
                        // Angular Velocity
                        angularVelocity = new Vector3(
                            Helpers.ByteToFloat(block.ObjectData, pos, -256.0f, 256.0f),
                            Helpers.ByteToFloat(block.ObjectData, pos + 1, -256.0f, 256.0f),
                            Helpers.ByteToFloat(block.ObjectData, pos + 2, -256.0f, 256.0f));
                        pos += 3;

                        break;
                    default:
                        Logger.Log("Got an ObjectUpdate block with ObjectUpdate field length of " +
                            block.ObjectData.Length, Helpers.LogLevel.Warning, Client);

                        continue;
                }
                #endregion

                // Determine the object type and create the appropriate class
                switch (pcode)
                {
                    #region Prim and Foliage
                    case PCode.Grass:
                    case PCode.Tree:
                    case PCode.NewTree:
                    case PCode.Prim:
                        Primitive prim = GetPrimitive(simulator, block.ID, block.FullID);

                        #region Update Prim Info with decoded data                            
                        prim.Flags = (LLObject.ObjectFlags)block.UpdateFlags;

                        if ((prim.Flags & LLObject.ObjectFlags.ZlibCompressed) != 0)
                        {
                            Logger.Log("Got a ZlibCompressed ObjectUpdate, implement me!", 
                                Helpers.LogLevel.Warning, Client);
                            continue;
                        }

                        // Automatically request ObjectProperties for prim if it was rezzed selected.
                        if ((prim.Flags & LLObject.ObjectFlags.CreateSelected) == LLObject.ObjectFlags.CreateSelected)
                            SelectObject(simulator, prim.LocalID);

                        prim.NameValues = nameValues;
                        prim.LocalID = block.ID;
                        prim.ID = block.FullID;
                        prim.ParentID = block.ParentID;
					    prim.RegionHandle = update.RegionData.RegionHandle;
                        prim.Scale = block.Scale;
                        prim.ClickAction = (ClickAction)block.ClickAction;
                        prim.OwnerID = block.OwnerID;
                        prim.MediaURL = Helpers.FieldToUTF8String(block.MediaURL);
                        prim.Text = Helpers.FieldToUTF8String(block.Text);
                        prim.TextColor = new Color4(block.TextColor, 0, false, true);

                        // Sound information
                        prim.Sound = block.Sound;
                        prim.SoundFlags = block.Flags;
                        prim.SoundGain = block.Gain;
                        prim.SoundRadius = block.Radius;

                        // Joint information
                        prim.Joint = (Primitive.JointType)block.JointType;
                        prim.JointPivot = block.JointPivot;
                        prim.JointAxisOrAnchor = block.JointAxisOrAnchor;
                        
                        // Object parameters
                        prim.Data = data;

                        // Textures, texture animations, particle system, and extra params
                        prim.Textures = new LLObject.TextureEntry(block.TextureEntry, 0,
                            block.TextureEntry.Length);

                        prim.TextureAnim = new Primitive.TextureAnimation(block.TextureAnim, 0);
                        prim.ParticleSys = new Primitive.ParticleSystem(block.PSBlock, 0);
                        prim.SetExtraParamsFromBytes(block.ExtraParams, 0);

                        // PCode-specific data
                        prim.GenericData = block.Data;

                        // Packed parameters
                        prim.CollisionPlane = collisionPlane;
                        prim.Position = position;
                        prim.Velocity = velocity;
                        prim.Acceleration = acceleration;
                        prim.Rotation = rotation;
                        prim.AngularVelocity = angularVelocity;
                        #endregion

                        if (attachment)
                            FireOnNewAttachment(simulator, prim, update.RegionData.RegionHandle, 
                                update.RegionData.TimeDilation);
                        else if (pcode == PCode.Prim)
                            FireOnNewPrim(simulator, prim, update.RegionData.RegionHandle, 
                                update.RegionData.TimeDilation);
                        else
                            FireOnNewFoliage(simulator, prim, update.RegionData.RegionHandle, 
                                update.RegionData.TimeDilation);

                        break;
                    #endregion Prim and Foliage
                    #region Avatar
                    case PCode.Avatar:
                        // Update some internals if this is our avatar
                        if (block.FullID == Client.Self.AgentID)
                        {
                            #region Update Client.Self
                            
                            // We need the local ID to recognize terse updates for our agent
                            Client.Self.localID = block.ID;
                            
                            // Packed parameters
                            Client.Self.collisionPlane = collisionPlane;
                            Client.Self.relativePosition = position;
                            Client.Self.velocity = velocity;
                            Client.Self.acceleration = acceleration;
                            Client.Self.relativeRotation = rotation;
                            Client.Self.angularVelocity = angularVelocity;

                            #endregion
                        }

                        #region Create an Avatar from the decoded data

                        Avatar avatar = GetAvatar(simulator, block.ID, block.FullID);
                        uint oldSeatID = avatar.sittingOn;

                        avatar.ID = block.FullID;
                        avatar.LocalID = block.ID;
                        avatar.CollisionPlane = collisionPlane;
                        avatar.Position = position;
                        avatar.Velocity = velocity;
                        avatar.Acceleration = acceleration;
                        avatar.Rotation = rotation;
                        avatar.AngularVelocity = angularVelocity;
                        avatar.NameValues = nameValues;
                        avatar.Data = data;
                        avatar.GenericData = block.Data;
                        avatar.sittingOn = block.ParentID;

                        SetAvatarSittingOn(simulator, avatar, block.ParentID, oldSeatID);

                        // Set the current simulator for this avatar
                        avatar.CurrentSim = simulator;

                        // Textures
                        avatar.Textures = new Primitive.TextureEntry(block.TextureEntry, 0, 
                            block.TextureEntry.Length);

                        #endregion Create an Avatar from the decoded data

                        FireOnNewAvatar(simulator, avatar, update.RegionData.RegionHandle, 
                            update.RegionData.TimeDilation);

                        break;
                    #endregion Avatar
                    case PCode.ParticleSystem:
                        DecodeParticleUpdate(block);
                        // TODO: Create a callback for particle updates
                        break;
                    default:
                        Logger.DebugLog("Got an ObjectUpdate block with an unrecognized PCode " + pcode.ToString(), Client);
                        break;
                }
            }
        }