public DateTime llParcelMediaCommandList(LSL_List commandList) { if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) { return(DateTime.Now); } // according to the docs, this command only works if script owner and land owner are the same // lets add estate owners and gods, too, and use the generic permission check. IParcelManagementModule parcelManagement = World.RequestModuleInterface <IParcelManagementModule>(); if (parcelManagement != null) { ILandObject landObject = parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); if (landObject == null) { return(DateTime.Now); } if (!World.Permissions.CanEditParcel(m_host.OwnerID, landObject)) { return(DateTime.Now); } bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? byte loop = 0; LandData landData = landObject.LandData; string url = landData.MediaURL; string texture = landData.MediaID.ToString(); bool autoAlign = landData.MediaAutoScale != 0; string mediaType = landData.MediaType; string description = landData.MediaDescription; int width = landData.MediaWidth; int height = landData.MediaHeight; float mediaLoopSet = landData.MediaLoopSet; ParcelMediaCommandEnum?commandToSend = null; float time = 0.0f; // default is from start IScenePresence presence = null; for (int i = 0; i < commandList.Data.Length; i++) { int tmp = ((LSL_Integer)commandList.Data[i]).value; ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)tmp; switch (command) { case ParcelMediaCommandEnum.Agent: // we send only to one agent if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) { UUID agentID; if (UUID.TryParse((LSL_String)commandList.Data[i + 1], out agentID)) { presence = World.GetScenePresence(agentID); } } else { Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key"); } ++i; } break; case ParcelMediaCommandEnum.Loop: loop = 1; commandToSend = command; update = true; //need to send the media update packet to set looping break; case ParcelMediaCommandEnum.LoopSet: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_Float) { mediaLoopSet = (float)((LSL_Float)commandList.Data[i + 1]).value; } else { Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_LOOP_SET must be a float"); } ++i; } commandToSend = command; break; case ParcelMediaCommandEnum.Play: loop = 0; commandToSend = command; update = true; //need to send the media update packet to make sure it doesn't loop break; case ParcelMediaCommandEnum.Pause: case ParcelMediaCommandEnum.Stop: case ParcelMediaCommandEnum.Unload: commandToSend = command; break; case ParcelMediaCommandEnum.Url: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) { url = (LSL_String)commandList.Data[i + 1]; update = true; } else { Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_URL must be a string."); } ++i; } break; case ParcelMediaCommandEnum.Texture: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) { texture = (LSL_String)commandList.Data[i + 1]; update = true; } else { Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or key."); } ++i; } break; case ParcelMediaCommandEnum.Time: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_Float) { time = (float)(LSL_Float)commandList.Data[i + 1]; } else { Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TIME must be a float."); } ++i; } commandToSend = command; break; case ParcelMediaCommandEnum.AutoAlign: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_Integer) { autoAlign = (LSL_Integer)commandList.Data[i + 1]; update = true; } else { Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer."); } ++i; } break; case ParcelMediaCommandEnum.Type: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) { mediaType = (LSL_String)commandList.Data[i + 1]; update = true; } else { Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string."); } ++i; } break; case ParcelMediaCommandEnum.Desc: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) { description = (LSL_String)commandList.Data[i + 1]; update = true; } else { Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_DESC must be a string."); } ++i; } break; case ParcelMediaCommandEnum.Size: if ((i + 2) < commandList.Length) { if (commandList.Data[i + 1] is LSL_Integer) { if (commandList.Data[i + 2] is LSL_Integer) { width = (LSL_Integer)commandList.Data[i + 1]; height = (LSL_Integer)commandList.Data[i + 2]; update = true; } else { Error("llParcelMediaCommandList", "The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer."); } } else { Error("llParcelMediaCommandList", "The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer."); } i += 2; } break; default: NotImplemented("llParcelMediaCommandList", "Parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString())); break; } //end switch } //end for // if we didn't get a presence, we send to all and change the url // if we did get a presence, we only send to the agent specified, and *don't change the land settings*! // did something important change or do we only start/stop/pause? if (update) { if (presence == null) { // we send to all landData.MediaID = new UUID(texture); landData.MediaAutoScale = autoAlign ? (byte)1 : (byte)0; landData.MediaWidth = width; landData.MediaHeight = height; landData.MediaType = mediaType; landData.MediaDescription = description; landData.MediaLoop = loop == 1; landData.MediaLoopSet = mediaLoopSet; // do that one last, it will cause a ParcelPropertiesUpdate landObject.SetMediaUrl(url); // now send to all (non-child) agents World.ForEachScenePresence(delegate(IScenePresence sp) { if (!sp.IsChildAgent && (sp.CurrentParcelUUID == landData.GlobalID)) { sp.ControllingClient.SendParcelMediaUpdate( landData.MediaURL, landData.MediaID, landData.MediaAutoScale, mediaType, description, width, height, loop); } }); } else if (!presence.IsChildAgent) { // we only send to one (root) agent presence.ControllingClient.SendParcelMediaUpdate(url, new UUID(texture), autoAlign ? (byte)1 : (byte)0, mediaType, description, width, height, loop); } } if (commandToSend != null) { float ParamToSend = time; if (commandToSend == ParcelMediaCommandEnum.LoopSet) { ParamToSend = mediaLoopSet; } // the commandList contained a start/stop/... command, too if (presence == null) { // send to all (non-child) agents World.ForEachScenePresence(delegate(IScenePresence sp) { if (!sp.IsChildAgent) { sp.ControllingClient.SendParcelMediaCommand( landData.Flags, (ParcelMediaCommandEnum)commandToSend, ParamToSend); } }); } else if (!presence.IsChildAgent) { presence.ControllingClient.SendParcelMediaCommand(landData.Flags, (ParcelMediaCommandEnum)commandToSend, ParamToSend); } } } return(PScriptSleep(m_sleepMsOnParcelMediaCommandList)); }