diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h
index 87466e6570727beeaeccc9f39a1fb5082c15fbad..9e030528926825dba459f060e44add5a2a8b422c 100644
--- a/indra/llinventory/llsettingsbase.h
+++ b/indra/llinventory/llsettingsbase.h
@@ -317,6 +317,8 @@ class LLSettingsBase :
             mSettings.erase(SETTING_ASSETID);
     }
 
+    // Calculate any custom settings that may need to be cached.
+    virtual void updateSettings() { mDirty = false; mReplaced = false; }
 protected:
 
     LLSettingsBase();
@@ -347,9 +349,6 @@ class LLSettingsBase :
     // rather than lerped.
     virtual stringset_t getSlerpKeys() const { return stringset_t(); }
 
-    // Calculate any custom settings that may need to be cached.
-    virtual void updateSettings() { mDirty = false; mReplaced = false; }
-
     virtual validation_list_t getValidationList() const = 0;
 
     // Apply any settings that need special handling. 
diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index e8dcba516ef4a57774cf5c9321c81aa0f8c06edb..86c83934993af6d0e80447f5f522149f18821e1d 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -139,7 +139,7 @@ const std::string LLSettingsSky::SETTING_SKY_ICE_LEVEL("ice_level");
 
 const LLUUID LLSettingsSky::DEFAULT_ASSET_ID("eb3a7080-831f-9f37-10f0-7b1f9ea4043c");
 
-static const LLUUID DEFAULT_SUN_ID("8ae0acc4-9e87-7f25-e16e-2a6caa5b8fc3"); // dataserver
+static const LLUUID DEFAULT_SUN_ID("32bfbcea-24b1-fb9d-1ef9-48a28a63730f"); // dataserver
 static const LLUUID DEFAULT_MOON_ID("db13b827-7e6a-7ace-bed4-4419ee00984d"); // dataserver
 static const LLUUID DEFAULT_CLOUD_ID("1dc1368f-e8fe-f02d-a08d-9d9f11c1af6b");
 
diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h
index 4d0d4268b2f7d718ad6c12fd7e9d7949da0fb1d4..a09dcd20087366a11bfd2fa68ffab503ee8f514d 100644
--- a/indra/llinventory/llsettingssky.h
+++ b/indra/llinventory/llsettingssky.h
@@ -311,6 +311,7 @@ class LLSettingsSky: public LLSettingsBase
                     F32 constant_term,
                     F32 aniso_factor = 0.0f);
 
+    virtual void        updateSettings() SETTINGS_OVERRIDE;
 protected:
     static const std::string SETTING_LEGACY_EAST_ANGLE;
     static const std::string SETTING_LEGACY_ENABLE_CLOUD_SCROLL;
@@ -320,7 +321,6 @@ class LLSettingsSky: public LLSettingsBase
 
     virtual stringset_t getSlerpKeys() const SETTINGS_OVERRIDE;
     virtual stringset_t getSkipInterpolateKeys() const SETTINGS_OVERRIDE;
-    virtual void    updateSettings() SETTINGS_OVERRIDE;
 
 private:
     static LLSD rayleighConfigDefault();
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 5acd508d5d32b31b1d3138b18c064ba27d034923..415cdfac6afda8efaa0c8ec75508744750e40854 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -97,6 +97,9 @@ namespace
     const std::string KEY_PARCELNAME("ParcelName");     // But changing these would also alter the Experience Log requirements.
     const std::string KEY_COUNT("Count");
 
+    const std::string LISTENER_NAME("LLEnvironmentSingleton");
+    const std::string PUMP_EXPERIENCE("experience_permission");
+
     //---------------------------------------------------------------------
     LLTrace::BlockTimerStatHandle   FTM_ENVIRONMENT_UPDATE("Update Environment Tick");
     LLTrace::BlockTimerStatHandle   FTM_SHADER_PARAM_UPDATE("Update Shader Parameters");
@@ -274,7 +277,6 @@ namespace
         }
     };
 
-
     class LLEnvironmentPushDispatchHandler : public LLDispatchHandler
     {
     public:
@@ -314,6 +316,187 @@ namespace
 
     LLEnvironmentPushDispatchHandler environment_push_dispatch_handler;
 
+    template<class SETTINGT>
+    class LLSettingsInjected : public SETTINGT
+    {
+    public:
+        typedef std::shared_ptr<LLSettingsInjected<SETTINGT> >  ptr_t;
+
+        LLSettingsInjected(typename SETTINGT::ptr_t source) :
+            SETTINGT(),
+            mSource(source)
+        {}
+
+        virtual ~LLSettingsInjected() {};
+
+        typename SETTINGT::ptr_t buildClone() const override;
+
+        typename SETTINGT::ptr_t getSource() const                               { return mSource; }
+        void setSource(const typename SETTINGT::ptr_t &source)        { mSource = source; setDirtyFlag(true); }
+
+        void injectSetting(const std::string keyname, LLSD value, LLUUID experience_id, F32Seconds transition)
+        {
+            Injection::ptr_t injection = std::make_shared<Injection>(transition, keyname, value, true, experience_id);
+
+            mInjections.push_back(injection);
+            std::stable_sort(mInjections.begin(), mInjections.end(), [](const Injection::ptr_t &a, const Injection::ptr_t &b) { return a->mTimeRemaining < b->mTimeRemaining; });
+        }
+
+        void removeInjection(const std::string keyname, LLUUID experience)
+        {
+            auto it = mInjections.begin();
+            while (it != mInjections.end())
+            {
+                if (((*it)->mKeyName == keyname) &&
+                    (experience.isNull() || (experience == (*it)->mExperience)))
+                {
+                    mInjections.erase(it++);
+                }
+                else
+                {
+                    ++it;
+                }
+            }
+
+            for (auto itexp = mOverrideExps.begin(); itexp != mOverrideExps.end();)
+            {
+                if (experience.isNull() || ((*itexp).second == experience))
+                {
+                    mOverrideValues.erase((*itexp).first);
+                    mOverrideExps.erase(itexp++);
+                }
+                else
+                    ++itexp;
+            }
+        }
+
+        void injectExperienceValues(LLSD values, LLUUID experience_id, F32Seconds transition)
+        {
+            for (auto it = values.beginMap(); it != values.endMap(); ++it)
+            {
+                injectSetting((*it).first, (*it).second, experience_id, transition);
+            }
+            setDirtyFlag(true);
+        }
+
+    protected:
+        struct Injection
+        {
+            struct Injection(F32Seconds transition, const std::string &keyname, LLSD value, bool blendin, LLUUID experince, S32 index = -1) :
+                mTransition(transition),
+                mTimeRemaining(transition),
+                mKeyName(keyname),
+                mValue(value),
+                mExperience(experince),
+                mIndex(index),
+                mBlendIn(blendin)
+            {}
+
+            F32Seconds      mTransition;
+            F32Seconds      mTimeRemaining;
+            std::string     mKeyName;
+            LLSD            mValue;
+            LLUUID          mExperience;
+            S32             mIndex;
+            bool            mBlendIn;
+
+            typedef std::shared_ptr<Injection>  ptr_t;
+        };
+
+
+        virtual void            updateSettings() override
+        {
+            static LLFrameTimer timer;
+
+            /**TODO: Add texture code
+             */
+
+            F32Seconds delta(timer.getElapsedTimeAndResetF32());
+
+            if (mSource && mSource->isDirty())
+            {
+                mSource->updateSettings();
+            }
+
+            mSettings = mSource->getSettings();
+
+            for (auto ito = mOverrideValues.beginMap(); ito != mOverrideValues.endMap(); ++ito)
+            {
+                mSettings[(*ito).first] = mOverrideValues[(*ito).first];
+            }
+
+            const stringset_t &slerps = getSlerpKeys();
+            const stringset_t &skips = getSkipInterpolateKeys();
+
+            injections_t::iterator it;
+            for (it = mInjections.begin(); it != mInjections.end(); ++it)
+            {
+                std::string key_name = (*it)->mKeyName;
+                if (skips.find(key_name) != skips.end())
+                    continue;
+                LLSD value = mSettings[key_name];
+                LLSD target = (*it)->mValue;
+
+                (*it)->mTimeRemaining -= delta;
+
+                BlendFactor mix = 1.0f - (((*it)->mTransition.value() - (*it)->mTimeRemaining.value()) / (*it)->mTransition.value());
+
+                if (mix >= 1.0)
+                {
+                    if ((*it)->mBlendIn)
+                    {
+                        mOverrideValues[key_name] = target;
+                        mOverrideExps[key_name] = (*it)->mExperience;
+                    }
+                    mSettings[key_name] = target;
+                }
+                else
+                {
+                    mSettings[key_name] = interpolateSDValue(key_name, value, target, getParameterMap(), mix, slerps);
+                }
+            }
+
+            it = mInjections.begin();
+            it = std::find_if(mInjections.begin(), mInjections.end(), [](const Injection::ptr_t &a) { return a->mTimeRemaining > 0.0f; });
+
+            if (it != mInjections.begin())
+            {
+
+                mInjections.erase(mInjections.begin(), mInjections.end());
+            }
+
+            SETTINGT::updateSettings();
+
+            if (!mInjections.empty())
+                setDirtyFlag(true);
+        }
+
+
+    private:
+        typedef std::map<std::string, LLUUID>   key_to_expid_t;
+        typedef std::deque<typename Injection::ptr_t>    injections_t;
+
+        typename SETTINGT::ptr_t    mSource;
+        injections_t                mInjections;
+        LLSD                        mOverrideValues;
+        key_to_expid_t              mOverrideExps;
+    };
+
+    template<>
+    LLSettingsSky::ptr_t LLSettingsInjected<LLSettingsSky>::buildClone() const
+    {
+        return LLSettingsVOSky::buildSky(getSettings());
+    }
+
+    template<>
+    LLSettingsWater::ptr_t LLSettingsInjected<LLSettingsWater>::buildClone() const
+    {
+        return LLSettingsVOWater::buildWater(getSettings());
+    }
+
+
+    typedef LLSettingsInjected<LLSettingsSky>   LLSettingsInjectedSky;
+    typedef LLSettingsInjected<LLSettingsWater> LLSettingsInjectedWater;
 }
 
 //=========================================================================
@@ -374,6 +557,12 @@ void LLEnvironment::initSingleton()
         gGenericDispatcher.addHandler(MESSAGE_PUSHENVIRONMENT, &environment_push_dispatch_handler);
     }
 
+    LLEventPumps::instance().obtain(PUMP_EXPERIENCE).listen(LISTENER_NAME, [this](LLSD message) { listenExperiencePump(message); return false; });
+}
+
+void LLEnvironment::cleanupSingleton()
+{
+    LLEventPumps::instance().obtain(PUMP_EXPERIENCE).stopListening(LISTENER_NAME);
 }
 
 LLEnvironment::~LLEnvironment()
@@ -808,12 +997,12 @@ LLSettingsDay::Seconds LLEnvironment::getEnvironmentDayOffset(EnvSelection_t env
 }
 
 
-LLEnvironment::fixedEnvironment_t LLEnvironment::getEnvironmentFixed(LLEnvironment::EnvSelection_t env)
+LLEnvironment::fixedEnvironment_t LLEnvironment::getEnvironmentFixed(LLEnvironment::EnvSelection_t env, bool resolve)
 {
-    if (env == ENV_CURRENT)
+    if ((env == ENV_CURRENT) || resolve)
     {
         fixedEnvironment_t fixed;
-        for (S32 idx = mSelectedEnvironment; idx < ENV_END; ++idx)
+        for (S32 idx = ((resolve) ? env : mSelectedEnvironment); idx < ENV_END; ++idx)
         {
             if (fixed.first && fixed.second)
                 break;
@@ -1800,7 +1989,6 @@ void LLEnvironment::handleEnvironmentPush(LLSD &message)
     }
 }
 
-
 void LLEnvironment::handleEnvironmentPushClear(LLUUID experience_id, LLSD &message, F32 transition)
 {
     clearExperienceEnvironment(experience_id, transition);
@@ -1837,15 +2025,15 @@ void LLEnvironment::clearExperienceEnvironment(LLUUID experience_id, F32 transit
     setInstanceBackup(false);
 
     /*TODO blend these back out*/
-    mSkyExperienceBlends.clear();
-    mWaterExperienceBlends.clear();
-    mCurrentEnvironment->getSky();
-
-    injectSettings(experience_id, mSkyExperienceBlends, mSkyOverrides, LLSettingsBase::Seconds(transition_time), false);
-    injectSettings(experience_id, mWaterExperienceBlends, mWaterOverrides, LLSettingsBase::Seconds(transition_time), false);
-
-    mSkyOverrides = LLSD::emptyMap();
-    mWaterOverrides = LLSD::emptyMap();
+//     mSkyExperienceBlends.clear();
+//     mWaterExperienceBlends.clear();
+//     mCurrentEnvironment->getSky();
+// 
+//     injectSettings(experience_id, mSkyExperienceBlends, mSkyOverrides, LLSettingsBase::Seconds(transition_time), false);
+//     injectSettings(experience_id, mWaterExperienceBlends, mWaterOverrides, LLSettingsBase::Seconds(transition_time), false);
+// 
+//     mSkyOverrides = LLSD::emptyMap();
+//     mWaterOverrides = LLSD::emptyMap();
 }
 
 void LLEnvironment::setSharedEnvironment()
@@ -1860,8 +2048,10 @@ void LLEnvironment::setExperienceEnvironment(LLUUID experience_id, LLUUID asset_
     LLSettingsVOBase::getSettingsAsset(asset_id,
         [this, experience_id, transition_time](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat)
     {
-        mPushEnvironmentExpId = experience_id;
-        onSetEnvAssetLoaded(ENV_PUSH, asset_id, settings, 
+//         mPushEnvironmentExpId = experience_id;
+//         removeExperinceInjections(experience_id); 
+        // individual settings will be overridden by the settings.  No need to keep injections.
+        onSetEnvAssetLoaded(ENV_PUSH, asset_id, settings,
             LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, 
             LLSettingsBase::Seconds(transition_time), status, NO_VERSION);
     });
@@ -1880,15 +2070,63 @@ void LLEnvironment::setExperienceEnvironment(LLUUID experience_id, LLSD data, F3
         return;
     }
 
-    setInstanceBackup(true);
+    LLSettingsInjectedSky::ptr_t pinjectedsky;
+    LLSettingsInjectedWater::ptr_t pinjectedwater;
+
+    fixedEnvironment_t pushenv = getEnvironmentFixed(ENV_PUSH, true);
 
     if (!sky.isUndefined())
-        injectSettings(experience_id, mSkyExperienceBlends, sky, LLSettingsBase::Seconds(transition_time), true);
+    {
+        bool newsky(false);
+
+        if (pushenv.first)
+        {
+            pinjectedsky = std::dynamic_pointer_cast<LLSettingsInjectedSky>(pushenv.first);
+        }
+        if (!pinjectedsky)
+        {
+            pinjectedsky = std::make_shared<LLSettingsInjectedSky>(pushenv.first);
+            newsky = true;
+        }
+
+        pinjectedsky->injectExperienceValues(sky, experience_id, F32Seconds(transition_time));
+        if (!newsky)
+            pinjectedsky.reset();
+    }
+
     if (!water.isUndefined())
-        injectSettings(experience_id, mWaterExperienceBlends, water, LLSettingsBase::Seconds(transition_time), true);
+    {
+        bool newwater(false);
+        if (pushenv.second)
+        {
+            pinjectedwater = std::dynamic_pointer_cast<LLSettingsInjectedWater>(pushenv.second);
+        }
+        if (!pinjectedwater)
+        {
+            pinjectedwater = std::make_shared<LLSettingsInjectedWater>(pushenv.second);
+            newwater = true;
+        }
+
+        pinjectedwater->injectExperienceValues(water, experience_id, F32Seconds(transition_time));
+        if (!newwater)
+            pinjectedwater.reset();
+    }
+
+    if (pinjectedsky || pinjectedwater)
+    {
+        setEnvironment(ENV_PUSH, pinjectedsky, pinjectedwater);
+        updateEnvironment(TRANSITION_INSTANT);
+    }
 
-}
 
+//     setInstanceBackup(true);
+// 
+//     if (!sky.isUndefined())
+//         injectSettings(experience_id, mSkyExperienceBlends, sky, LLSettingsBase::Seconds(transition_time), true);
+//     if (!water.isUndefined())
+//         injectSettings(experience_id, mWaterExperienceBlends, water, LLSettingsBase::Seconds(transition_time), true);
+
+}
 
 void LLEnvironment::setInstanceBackup(bool dobackup)
 {
@@ -1905,6 +2143,8 @@ void LLEnvironment::injectSettings(LLUUID experience_id, exerienceBlendValues_t
     for (LLSD::map_iterator it = injections.beginMap(); it != injections.endMap(); ++it)
     {
         blends.push_back(ExpBlendValue(transition, (*it).first, (*it).second, blendin, -1));
+        if (blendin)
+            mExperienceOverrides[(*it).first] = experience_id;
     }
 
     std::stable_sort(blends.begin(), blends.end(), [](const ExpBlendValue &a, const ExpBlendValue &b) { return a.mTimeRemaining < b.mTimeRemaining; });
@@ -1926,7 +2166,6 @@ void LLEnvironment::applyInjectedSettings(DayInstance::ptr_t environment, F32Sec
     }
 }
 
-
 void LLEnvironment::applyInjectedValues(LLSettingsBase::ptr_t psetting, LLSD injection)
 {
     for (LLSD::map_iterator it = injection.beginMap(); it != injection.endMap(); ++it)
@@ -1973,6 +2212,53 @@ void LLEnvironment::blendInjectedValues(LLSettingsBase::ptr_t psetting, exerienc
     }
 }
 
+void LLEnvironment::removeExperinceInjections(const LLUUID &experience_id)
+{
+    auto it = mExperienceOverrides.begin();
+    while (it != mExperienceOverrides.end())
+    {
+        if ((*it).second == experience_id)
+        {
+            std::string override_key((*it).first);
+            mExperienceOverrides.erase(it++);
+
+            if (mSkyOverrides.has(override_key))
+                mSkyOverrides.erase(override_key);
+            if (mWaterOverrides.has(override_key))
+                mWaterOverrides.erase(override_key);
+            auto itBlend = std::find_if(mSkyExperienceBlends.begin(), mSkyExperienceBlends.end(), [override_key](const ExpBlendValue &a) { return a.mKeyName == override_key; });
+            if (itBlend != mSkyExperienceBlends.end())
+                mSkyExperienceBlends.erase(itBlend);
+            itBlend = std::find_if(mWaterExperienceBlends.begin(), mWaterExperienceBlends.end(), [override_key](const ExpBlendValue &a) { return a.mKeyName == override_key; });
+            if (itBlend != mWaterExperienceBlends.end())
+                mWaterExperienceBlends.erase(itBlend);
+        }
+        else
+            ++it;
+    }
+}
+
+void LLEnvironment::removeExperinceSetting(const LLUUID &experience_id)
+{
+    clearExperienceEnvironment(experience_id, TRANSITION_INSTANT);
+}
+
+void LLEnvironment::listenExperiencePump(const LLSD &message)
+{
+    LL_WARNS("LAPRAS") << "Have experience event: " << message << LL_ENDL;
+
+    LLUUID experience_id = message["experience"];
+    LLSD data = message[experience_id.asString()];
+    std::string permission(data["permission"].asString());
+
+    if ((permission == "Forget") || (permission == "Block"))
+    {
+        removeExperinceSetting(experience_id);
+    }
+
+
+}
+
 //=========================================================================
 LLEnvironment::DayInstance::DayInstance(EnvSelection_t env) :
     mDayCycle(),
diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h
index c925ea6e7c06fdba5cfc2503eba90398b2eece56..9d951202a9d589f5d54c90fb70d250c22a0ea02d 100644
--- a/indra/newview/llenvironment.h
+++ b/indra/newview/llenvironment.h
@@ -48,7 +48,7 @@ class LLParcel;
 //-------------------------------------------------------------------------
 class LLEnvironment : public LLSingleton<LLEnvironment>
 {
-    LLSINGLETON(LLEnvironment);
+    LLSINGLETON_C11(LLEnvironment);
     LOG_CLASS(LLEnvironment);
 
 public:
@@ -153,9 +153,9 @@ class LLEnvironment : public LLSingleton<LLEnvironment>
     LLSettingsDay::ptr_t        getEnvironmentDay(EnvSelection_t env);
     LLSettingsDay::Seconds      getEnvironmentDayLength(EnvSelection_t env);
     LLSettingsDay::Seconds      getEnvironmentDayOffset(EnvSelection_t env);
-    fixedEnvironment_t          getEnvironmentFixed(EnvSelection_t env);
-    LLSettingsSky::ptr_t        getEnvironmentFixedSky(EnvSelection_t env)      { return getEnvironmentFixed(env).first; };
-    LLSettingsWater::ptr_t      getEnvironmentFixedWater(EnvSelection_t env)    { return getEnvironmentFixed(env).second; };
+    fixedEnvironment_t          getEnvironmentFixed(EnvSelection_t env, bool resolve = false);
+    LLSettingsSky::ptr_t        getEnvironmentFixedSky(EnvSelection_t env, bool resolve = false)      { return getEnvironmentFixed(env, resolve).first; };
+    LLSettingsWater::ptr_t      getEnvironmentFixedWater(EnvSelection_t env, bool resolve = false)    { return getEnvironmentFixed(env, resolve).second; };
 
     void                        updateEnvironment(LLSettingsBase::Seconds transition = TRANSITION_DEFAULT, bool forced = false);
 
@@ -299,7 +299,9 @@ class LLEnvironment : public LLSingleton<LLEnvironment>
     DayInstance::ptr_t          getSharedEnvironmentInstance();
 
 protected:
-    virtual void                initSingleton();
+    virtual void                initSingleton() override;
+    virtual void                cleanupSingleton() override;
+
 
 private:
     LLVector4 toCFR(const LLVector3 vec) const;
@@ -360,8 +362,8 @@ class LLEnvironment : public LLSingleton<LLEnvironment>
 
     LLSD                        mSkyOverrides;
     LLSD                        mWaterOverrides;
-    LLSD                        mSkyOverrideBlends;
-    LLSD                        mWaterOverrideBlends;
+    typedef std::map<std::string, LLUUID> experience_overrides_t;
+    experience_overrides_t      mExperienceOverrides;
 
     DayInstance::ptr_t          getEnvironmentInstance(EnvSelection_t env, bool create = false);
 
@@ -453,6 +455,9 @@ class LLEnvironment : public LLSingleton<LLEnvironment>
     void                        applyInjectedSettings(DayInstance::ptr_t environment, F32Seconds delta);
     void                        applyInjectedValues(LLSettingsBase::ptr_t psetting, LLSD injection);
     void                        blendInjectedValues(LLSettingsBase::ptr_t psetting, exerienceBlendValues_t &blends, LLSD &overrides, F32Seconds delta);
+    void                        removeExperinceInjections(const LLUUID &experience_id);
+    void                        removeExperinceSetting(const LLUUID &experience_id);
+    void                        listenExperiencePump(const LLSD &message);
 
     exerienceBlendValues_t      mSkyExperienceBlends;
     exerienceBlendValues_t      mWaterExperienceBlends;