diff --git a/Minecraft.Client/Common/App_Defines.h b/Minecraft.Client/Common/App_Defines.h index 7e96896c9..db276e149 100644 --- a/Minecraft.Client/Common/App_Defines.h +++ b/Minecraft.Client/Common/App_Defines.h @@ -105,6 +105,9 @@ enum EGameHostOptionWorldSize #define GAMESETTING_PS3EULAREAD 0x00010000 #define GAMESETTING_PSVITANETWORKMODEADHOC 0x00020000 +// Dynamic Lighting (bits 24-25) +#define GAMESETTING_DYNAMICLIGHTING 0x01000000 +#define GAMESETTING_DYNLIGHTMODE 0x02000000 // defines for languages diff --git a/Minecraft.Client/Common/App_enums.h b/Minecraft.Client/Common/App_enums.h index 15a179787..07f48b786 100644 --- a/Minecraft.Client/Common/App_enums.h +++ b/Minecraft.Client/Common/App_enums.h @@ -178,7 +178,9 @@ enum eGameSetting // PSVita eGameSetting_PSVita_NetworkModeAdhoc, - + // Dynamic Lighting + eGameSetting_DynamicLighting, + eGameSetting_DynLightMode, }; diff --git a/Minecraft.Client/Common/Consoles_App.cpp b/Minecraft.Client/Common/Consoles_App.cpp index 0a2fd159a..4a4cbf6fa 100644 --- a/Minecraft.Client/Common/Consoles_App.cpp +++ b/Minecraft.Client/Common/Consoles_App.cpp @@ -900,6 +900,10 @@ int CMinecraftApp::SetDefaultOptions(C_4JProfile::PROFILESETTINGS *pSettings,con // TU 7 SetGameSettings(iPad,eGameSetting_CustomSkinAnim,1); + // Dynamic Lighting + SetGameSettings(iPad,eGameSetting_DynamicLighting,1); + SetGameSettings(iPad,eGameSetting_DynLightMode,1); // 0=Fast, 1=Fancy + // TU 9 SetGameSettings(iPad,eGameSetting_DeathMessages,1); SetGameSettings(iPad,eGameSetting_UISize,1); @@ -2328,6 +2332,17 @@ void CMinecraftApp::SetGameSettings(int iPad,eGameSetting eVal,unsigned char ucV } break; + case eGameSetting_DynamicLighting: + if(ucVal) GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_DYNAMICLIGHTING; + else GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_DYNAMICLIGHTING; + GameSettingsA[iPad]->bSettingsChanged = true; + break; + case eGameSetting_DynLightMode: + if(ucVal) GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_DYNLIGHTMODE; + else GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_DYNLIGHTMODE; + GameSettingsA[iPad]->bSettingsChanged = true; + break; + } } @@ -2463,6 +2478,11 @@ unsigned char CMinecraftApp::GetGameSettings(int iPad,eGameSetting eVal) case eGameSetting_PSVita_NetworkModeAdhoc: return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)>>17; + case eGameSetting_DynamicLighting: + return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_DYNAMICLIGHTING) ? 1 : 0; + case eGameSetting_DynLightMode: + return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_DYNLIGHTMODE) ? 1 : 0; + } return 0; } diff --git a/Minecraft.Client/Common/Media/SettingsGraphicsMenu1080.swf b/Minecraft.Client/Common/Media/SettingsGraphicsMenu1080.swf index 2495b4342..bf02941da 100644 Binary files a/Minecraft.Client/Common/Media/SettingsGraphicsMenu1080.swf and b/Minecraft.Client/Common/Media/SettingsGraphicsMenu1080.swf differ diff --git a/Minecraft.Client/Common/Media/SettingsGraphicsMenu480.swf b/Minecraft.Client/Common/Media/SettingsGraphicsMenu480.swf index aae01e78c..897c0d540 100644 Binary files a/Minecraft.Client/Common/Media/SettingsGraphicsMenu480.swf and b/Minecraft.Client/Common/Media/SettingsGraphicsMenu480.swf differ diff --git a/Minecraft.Client/Common/Media/SettingsGraphicsMenu720.swf b/Minecraft.Client/Common/Media/SettingsGraphicsMenu720.swf index 4e860fb1f..51d8c308e 100644 Binary files a/Minecraft.Client/Common/Media/SettingsGraphicsMenu720.swf and b/Minecraft.Client/Common/Media/SettingsGraphicsMenu720.swf differ diff --git a/Minecraft.Client/Common/Media/SettingsGraphicsMenuSplit1080.swf b/Minecraft.Client/Common/Media/SettingsGraphicsMenuSplit1080.swf index 6037882dd..9785cf0ed 100644 Binary files a/Minecraft.Client/Common/Media/SettingsGraphicsMenuSplit1080.swf and b/Minecraft.Client/Common/Media/SettingsGraphicsMenuSplit1080.swf differ diff --git a/Minecraft.Client/Common/Media/SettingsGraphicsMenuSplit720.swf b/Minecraft.Client/Common/Media/SettingsGraphicsMenuSplit720.swf index 133dae454..d4a19381d 100644 Binary files a/Minecraft.Client/Common/Media/SettingsGraphicsMenuSplit720.swf and b/Minecraft.Client/Common/Media/SettingsGraphicsMenuSplit720.swf differ diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp index b258d8c31..363aae2f5 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp @@ -2,6 +2,7 @@ #include "UI.h" #include "UIScene_SettingsGraphicsMenu.h" #include "..\..\Minecraft.h" +#include "..\..\MultiPlayerLevel.h" #include "..\..\Options.h" #include "..\..\GameRenderer.h" @@ -63,7 +64,9 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD m_checkboxBedrockFog.init(app.GetString(IDS_CHECKBOX_RENDER_BEDROCKFOG),eControl_BedrockFog,(app.GetGameSettings(m_iPad,eGameSetting_BedrockFog)!=0)); m_checkboxCustomSkinAnim.init(app.GetString(IDS_CHECKBOX_CUSTOM_SKIN_ANIM),eControl_CustomSkinAnim,(app.GetGameSettings(m_iPad,eGameSetting_CustomSkinAnim)!=0)); - + m_checkboxDynLight.init(L"Dynamic Lighting", eControl_DynamicLighting, + (app.GetGameSettings(m_iPad, eGameSetting_DynamicLighting) != 0)); + WCHAR TempString[256]; swprintf(TempString, 256, L"Render Distance: %d",app.GetGameSettings(m_iPad,eGameSetting_RenderDistance)); @@ -80,6 +83,12 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD swprintf( TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_INTERFACEOPACITY ),app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity)); m_sliderInterfaceOpacity.init(TempString,eControl_InterfaceOpacity,0,100,app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity)); + { + int dynMode = app.GetGameSettings(m_iPad, eGameSetting_DynLightMode); + m_sliderDynLightMode.init(dynMode ? L"Dynamic Light Mode: Fancy" : L"Dynamic Light Mode: Fast", + eControl_DynLightMode, 0, 1, dynMode); + } + doHorizontalResizeCheck(); const bool bInGame=(Minecraft::GetInstance()->level!=nullptr); @@ -166,6 +175,17 @@ void UIScene_SettingsGraphicsMenu::handleInput(int iPad, int key, bool repeat, b app.SetGameSettings(m_iPad,eGameSetting_BedrockFog,m_checkboxBedrockFog.IsChecked()?1:0); app.SetGameSettings(m_iPad,eGameSetting_CustomSkinAnim,m_checkboxCustomSkinAnim.IsChecked()?1:0); + { + bool dynEnabled = m_checkboxDynLight.IsChecked(); + app.SetGameSettings(m_iPad, eGameSetting_DynamicLighting, dynEnabled ? 1 : 0); + Minecraft *mc = Minecraft::GetInstance(); + if (mc && mc->level) + { + mc->level->m_dynLightsEnabled = dynEnabled; + mc->level->m_dynLightFancy = (app.GetGameSettings(m_iPad, eGameSetting_DynLightMode) != 0); + } + } + navigateBack(); handled = true; } @@ -236,5 +256,17 @@ void UIScene_SettingsGraphicsMenu::handleSliderMove(F64 sliderId, F64 currentVal m_sliderInterfaceOpacity.setLabel(TempString); break; + + case eControl_DynLightMode: + { + m_sliderDynLightMode.handleSliderMove(value); + bool fancy = (value != 0); + m_sliderDynLightMode.setLabel(fancy ? L"Dynamic Light Mode: Fancy" : L"Dynamic Light Mode: Fast"); + app.SetGameSettings(m_iPad, eGameSetting_DynLightMode, fancy ? 1 : 0); + Minecraft *mc = Minecraft::GetInstance(); + if (mc && mc->level) + mc->level->m_dynLightFancy = fancy; + } + break; } } diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h index 99022c83f..e4af55b35 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h @@ -15,11 +15,15 @@ private: eControl_RenderDistance, eControl_Gamma, eControl_FOV, - eControl_InterfaceOpacity + eControl_InterfaceOpacity, + eControl_DynamicLighting, + eControl_DynLightMode }; UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim; // Checkboxes + UIControl_CheckBox m_checkboxDynLight; UIControl_Slider m_sliderRenderDistance, m_sliderGamma, m_sliderFOV, m_sliderInterfaceOpacity; // Sliders + UIControl_Slider m_sliderDynLightMode; UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) UI_MAP_ELEMENT( m_checkboxClouds, "Clouds") UI_MAP_ELEMENT( m_checkboxBedrockFog, "BedrockFog") @@ -28,6 +32,8 @@ private: UI_MAP_ELEMENT( m_sliderGamma, "Gamma") UI_MAP_ELEMENT(m_sliderFOV, "FOV") UI_MAP_ELEMENT( m_sliderInterfaceOpacity, "InterfaceOpacity") + UI_MAP_ELEMENT( m_checkboxDynLight, "DynamicLighting") + UI_MAP_ELEMENT( m_sliderDynLightMode, "DynLightMode") UI_END_MAP_ELEMENTS_AND_NAMES() bool m_bNotInGame; diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index 11fd81a0d..017853a47 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -2323,7 +2323,16 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) // soundEngine.playMusicTick(); - if (!pause && level != nullptr) gameMode->tick(); + if (!pause && level != nullptr) + { + gameMode->tick(); + if (player != nullptr) + { + level->m_dynLightsEnabled = (app.GetGameSettings(0, eGameSetting_DynamicLighting) != 0); + level->m_dynLightFancy = (app.GetGameSettings(0, eGameSetting_DynLightMode) != 0); + level->updateDynamicLights(); + } + } MemSect(31); glBindTexture(GL_TEXTURE_2D, textures->loadTexture(TN_TERRAIN)); //L"/terrain.png")); MemSect(0); diff --git a/Minecraft.World/Item.cpp b/Minecraft.World/Item.cpp index ffb310704..4b1dc6e0f 100644 --- a/Minecraft.World/Item.cpp +++ b/Minecraft.World/Item.cpp @@ -503,6 +503,18 @@ void Item::staticInit() Stats::buildItemStats(); } +int Item::getItemLightLevel(shared_ptr item) +{ + if (!item || item->id == 0) return 0; + + if (item->id < 256 && Tile::lightEmission[item->id] > 0) + return Tile::lightEmission[item->id]; + + if (item->id == bucket_lava_Id) return 15; + + return 0; +} + _Tier::Tier(int level, int uses, float speed, float damage, int enchantmentValue) : level( level ), diff --git a/Minecraft.World/Item.h b/Minecraft.World/Item.h index 22d0a9d15..20e65794c 100644 --- a/Minecraft.World/Item.h +++ b/Minecraft.World/Item.h @@ -35,6 +35,7 @@ public: static void staticCtor(); static void staticInit(); + static int getItemLightLevel(shared_ptr item); // 4J-PB - added for new crafting menu enum diff --git a/Minecraft.World/Level.cpp b/Minecraft.World/Level.cpp index 161f4e560..57b0d9a27 100644 --- a/Minecraft.World/Level.cpp +++ b/Minecraft.World/Level.cpp @@ -27,6 +27,8 @@ #include "ThreadName.h" #include "WeighedRandom.h" +#include "net.minecraft.world.item.h" +#include "net.minecraft.world.entity.item.h" #include "ConsoleSaveFile.h" #include #include "..\Minecraft.Client\Minecraft.h" @@ -595,6 +597,10 @@ void Level::_init() m_bDisableAddNewTileEntities = false; m_iHighestY=-1000; m_unsavedChunkCount = 0; + m_dynLightsEnabled = true; + m_dynLightsReady = false; + m_dynLightFancy = true; + InitializeCriticalSection(&m_dynLightCS); } // 4J - brought forward from 1.8.2 @@ -1458,6 +1464,8 @@ int Level::getLightColor(int x, int y, int z, int emitt, int tileId/*=-1*/) { int s = getBrightnessPropagate(LightLayer::Sky, x, y, z, tileId); int b = getBrightnessPropagate(LightLayer::Block, x, y, z, tileId); + int dyn = getDynamicLight(x, y, z); + if (dyn > b) b = dyn; if (b < emitt) b = emitt; return s << 20 | b << 4; } @@ -3128,6 +3136,137 @@ void Level::tick() PIXEndNamedEvent(); } +static int getEntityLightLevel(shared_ptr e) +{ + if (!e || e->removed) return 0; + + eINSTANCEOF type = e->GetType(); + + if (type & eTYPE_PLAYER) + return Item::getItemLightLevel(((Player *)e.get())->getCarriedItem()); + + if (type == eTYPE_ITEMENTITY) + return Item::getItemLightLevel(((ItemEntity *)e.get())->getItem()); + + if (type == eTYPE_BLAZE) return 7; + + if ((type & eTYPE_MOB) || type == eTYPE_ARROW) + if (e->isOnFire()) return 15; + + return 0; +} + +int Level::getDynamicLight(int x, int y, int z) +{ + if (!m_dynLightsReady) return 0; + + if (y >= 0 && y < maxBuildHeight) + { + int t = getTile(x, y, z); + if (t > 0 && Tile::lightBlock[t] >= 15) return 0; + } + + int best = 0; + EnterCriticalSection(&m_dynLightCS); + for (size_t i = 0; i < m_dynLightSources.size(); i++) + { + DynLightSource &src = m_dynLightSources[i]; + float dx = (float)x - src.x, dy = (float)y - src.y, dz = (float)z - src.z; + int dist; + if (m_dynLightFancy) + dist = (int)(sqrtf(dx * dx + dy * dy + dz * dz) + 0.5f); + else + dist = (int)(fabsf(dx) + fabsf(dy) + fabsf(dz)); + int val = src.level - dist; + if (val > best) best = val; + } + LeaveCriticalSection(&m_dynLightCS); + return best; +} + +void Level::updateDynamicLights() +{ + if (players.empty() || !chunkSource) return; + + if (!m_dynLightsEnabled) + { + if (m_dynLightsReady) + { + EnterCriticalSection(&m_dynLightCS); + m_dynLightSources.clear(); + LeaveCriticalSection(&m_dynLightCS); + for (size_t i = 0; i < m_prevDynLightAreas.size(); i++) + { + DynLightPrev &prev = m_prevDynLightAreas[i]; + setTilesDirty(prev.x - prev.radius, prev.y - prev.radius, prev.z - prev.radius, + prev.x + prev.radius, prev.y + prev.radius, prev.z + prev.radius); + } + m_prevDynLightAreas.clear(); + m_dynLightsReady = false; + } + return; + } + + m_dynLightsReady = true; + + for (size_t i = 0; i < m_prevDynLightAreas.size(); i++) + { + DynLightPrev &prev = m_prevDynLightAreas[i]; + setTilesDirty(prev.x - prev.radius, prev.y - prev.radius, prev.z - prev.radius, + prev.x + prev.radius, prev.y + prev.radius, prev.z + prev.radius); + } + m_prevDynLightAreas.clear(); + + vector newSources; + int maxRadius = m_dynLightFancy ? 10 : 6; + + for (size_t i = 0; i < players.size(); i++) + { + if (!players[i]) continue; + int ll = getEntityLightLevel(players[i]); + if (ll <= 0) continue; + if (ll > MAX_BRIGHTNESS) ll = MAX_BRIGHTNESS; + newSources.push_back({(float)players[i]->x, (float)players[i]->y, (float)players[i]->z, ll}); + } + + if (m_dynLightFancy && TryEnterCriticalSection(&m_entitiesCS)) + { + for (size_t i = 0; i < entities.size(); i++) + { + shared_ptr e = entities[i]; + if (!e || e->removed) continue; + + int ll = 0; + eINSTANCEOF type = e->GetType(); + + if (type == eTYPE_ITEMENTITY) + ll = Item::getItemLightLevel(((ItemEntity *)e.get())->getItem()); + else if (type == eTYPE_BLAZE) + ll = 7; + else if ((type & eTYPE_MOB) || type == eTYPE_ARROW) + if (e->isOnFire()) ll = 15; + + if (ll <= 0) continue; + if (ll > MAX_BRIGHTNESS) ll = MAX_BRIGHTNESS; + newSources.push_back({(float)e->x, (float)e->y, (float)e->z, ll}); + } + LeaveCriticalSection(&m_entitiesCS); + } + + EnterCriticalSection(&m_dynLightCS); + m_dynLightSources.swap(newSources); + LeaveCriticalSection(&m_dynLightCS); + + for (size_t i = 0; i < m_dynLightSources.size(); i++) + { + DynLightSource &src = m_dynLightSources[i]; + int r = min(src.level, maxRadius); + int sx = Mth::floor(src.x), sy = Mth::floor(src.y), sz = Mth::floor(src.z); + setTilesDirty(sx - r, sy - r, sz - r, sx + r, sy + r, sz + r); + m_prevDynLightAreas.push_back({sx, sy, sz, r}); + } +} + void Level::prepareWeather() { if (levelData->isRaining()) diff --git a/Minecraft.World/Level.h b/Minecraft.World/Level.h index 2be874722..124ed21a8 100644 --- a/Minecraft.World/Level.h +++ b/Minecraft.World/Level.h @@ -161,6 +161,19 @@ public: shared_ptr villages; VillageSiege *villageSiege; + // Dynamic lighting + bool m_dynLightsEnabled; + bool m_dynLightsReady; + bool m_dynLightFancy; + struct DynLightSource { float x, y, z; int level; }; + vector m_dynLightSources; + struct DynLightPrev { int x, y, z, radius; }; + vector m_prevDynLightAreas; + CRITICAL_SECTION m_dynLightCS; +public: + void updateDynamicLights(); + int getDynamicLight(int x, int y, int z); + private: // 4J - Calendar is now static // Calendar *calendar; diff --git a/Minecraft.World/Region.cpp b/Minecraft.World/Region.cpp index 1e8acaf36..140a8a6bb 100644 --- a/Minecraft.World/Region.cpp +++ b/Minecraft.World/Region.cpp @@ -160,6 +160,10 @@ int Region::getLightColor(int x, int y, int z, int emitt, int tileId/*=-1*/) { int s = getBrightnessPropagate(LightLayer::Sky, x, y, z, tileId); int b = getBrightnessPropagate(LightLayer::Block, x, y, z, tileId); + if (level) { + int dyn = level->getDynamicLight(x, y, z); + if (dyn > b) b = dyn; + } if (b < emitt) b = emitt; return s << 20 | b << 4; }