From 5b7de82a79e3f18affcffd686484a681d187942a Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sun, 14 Oct 2012 17:06:21 +0000 Subject: [PATCH] Initial Floody fluid simulator. Can spread, cannot dry. git-svn-id: http://mc-server.googlecode.com/svn/trunk@963 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- VC2008/MCServer.vcproj | 16 +++ source/Simulator/ClassicFluidSimulator.cpp | 9 -- source/Simulator/ClassicFluidSimulator.h | 1 - source/Simulator/DelayedFluidSimulator.cpp | 92 ++++++++++++ source/Simulator/DelayedFluidSimulator.h | 44 ++++++ source/Simulator/FireSimulator.cpp | 40 +++--- source/Simulator/FireSimulator.h | 1 - source/Simulator/FloodyFluidSimulator.cpp | 159 +++++++++++++++++++++ source/Simulator/FloodyFluidSimulator.h | 49 +++++++ source/Simulator/FluidSimulator.cpp | 55 ++++++- source/Simulator/FluidSimulator.h | 7 + source/Simulator/Simulator.h | 1 + source/World.cpp | 26 ++-- 13 files changed, 446 insertions(+), 54 deletions(-) create mode 100644 source/Simulator/DelayedFluidSimulator.cpp create mode 100644 source/Simulator/DelayedFluidSimulator.h create mode 100644 source/Simulator/FloodyFluidSimulator.cpp create mode 100644 source/Simulator/FloodyFluidSimulator.h diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj index 0dc4b62f3..4f40a83ca 100644 --- a/VC2008/MCServer.vcproj +++ b/VC2008/MCServer.vcproj @@ -1018,6 +1018,14 @@ RelativePath="..\source\Simulator\ClassicFluidSimulator.h" > + + + + @@ -1026,6 +1034,14 @@ RelativePath="..\source\Simulator\FireSimulator.h" > + + + + diff --git a/source/Simulator/ClassicFluidSimulator.cpp b/source/Simulator/ClassicFluidSimulator.cpp index 70dbd0f6f..232e8205d 100644 --- a/source/Simulator/ClassicFluidSimulator.cpp +++ b/source/Simulator/ClassicFluidSimulator.cpp @@ -300,15 +300,6 @@ void cClassicFluidSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ) -bool cClassicFluidSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType) -{ - return ((a_BlockType == m_FluidBlock) || (a_BlockType == m_StationaryFluidBlock)); -} - - - - - NIBBLETYPE cClassicFluidSimulator::GetHighestLevelAround(int a_BlockX, int a_BlockY, int a_BlockZ) { NIBBLETYPE Max = m_MaxHeight + m_Falloff; diff --git a/source/Simulator/ClassicFluidSimulator.h b/source/Simulator/ClassicFluidSimulator.h index 4b6301b9a..4198f16de 100644 --- a/source/Simulator/ClassicFluidSimulator.h +++ b/source/Simulator/ClassicFluidSimulator.h @@ -25,7 +25,6 @@ public: // cSimulator overrides: virtual void Simulate(float a_Dt) override; virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override; protected: NIBBLETYPE GetHighestLevelAround(int a_BlockX, int a_BlockY, int a_BlockZ); diff --git a/source/Simulator/DelayedFluidSimulator.cpp b/source/Simulator/DelayedFluidSimulator.cpp new file mode 100644 index 000000000..3ace286ed --- /dev/null +++ b/source/Simulator/DelayedFluidSimulator.cpp @@ -0,0 +1,92 @@ + +// DelayedFluidSimulator.cpp + +// Interfaces to the cDelayedFluidSimulator class representing a fluid simulator that has a configurable delay +// before simulating a block. Each tick it takes a consecutive delay "slot" and simulates only blocks in that slot. + +#include "Globals.h" + +#include "DelayedFluidSimulator.h" +#include "../World.h" + + + + + +cDelayedFluidSimulator::cDelayedFluidSimulator(cWorld * a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, int a_TickDelay) : + super(a_World, a_Fluid, a_StationaryFluid), + m_TickDelay(a_TickDelay), + m_Slots(NULL), + m_CurrentSlotNum(a_TickDelay - 1) +{ + m_Slots = new CoordsArray[a_TickDelay]; +} + + + + + +cDelayedFluidSimulator::~cDelayedFluidSimulator() +{ + delete[] m_Slots; + m_Slots = NULL; +} + + + + + +void cDelayedFluidSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ) +{ + if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height)) + { + // Not inside the world (may happen when rclk with a full bucket - the client sends Y = -1) + return; + } + + BLOCKTYPE BlockType = m_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); + if (BlockType != m_FluidBlock) + { + return; + } + + CoordsArray & Blocks = m_Slots[m_CurrentSlotNum]; + + // Check for duplicates: + for (CoordsArray::iterator itr = Blocks.begin(), end = Blocks.end(); itr != end; ++itr) + { + if ((itr->x == a_BlockX) && (itr->y == a_BlockY) && (itr->z == a_BlockZ)) + { + return; + } + } + + Blocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ)); +} + + + + + +void cDelayedFluidSimulator::Simulate(float a_Dt) +{ + CoordsArray & Blocks = m_Slots[m_CurrentSlotNum]; + + // First move to the next slot, so that simulated blocks can write another batch of scheduled blocks: + m_CurrentSlotNum += 1; + if (m_CurrentSlotNum >= m_TickDelay) + { + m_CurrentSlotNum = 0; + } + + // Simulate the blocks in the scheduled slot: + for (CoordsArray::iterator itr = Blocks.begin(), end = Blocks.end(); itr != end; ++itr) + { + SimulateBlock(itr->x, itr->y, itr->z); + } + Blocks.clear(); +} + + + + diff --git a/source/Simulator/DelayedFluidSimulator.h b/source/Simulator/DelayedFluidSimulator.h new file mode 100644 index 000000000..b9c180580 --- /dev/null +++ b/source/Simulator/DelayedFluidSimulator.h @@ -0,0 +1,44 @@ + +// DelayedFluidSimulator.h + +// Interfaces to the cDelayedFluidSimulator class representing a fluid simulator that has a configurable delay +// before simulating a block. Each tick it takes a consecutive delay "slot" and simulates only blocks in that slot. + + + + +#pragma once + +#include "FluidSimulator.h" + + + + + +class cDelayedFluidSimulator : + public cFluidSimulator +{ + typedef cFluidSimulator super; + +public: + cDelayedFluidSimulator(cWorld * a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, int a_TickDelay); + virtual ~cDelayedFluidSimulator(); + + // cSimulator overrides: + virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void Simulate(float a_Dt) override; + +protected: + typedef std::vector CoordsArray; + + int m_TickDelay; // Count of the m_Slots array + CoordsArray * m_Slots; // Slots, one for each delay tick + int m_CurrentSlotNum; // Index into m_Slots[] where to insert new blocks + + /// Called from Simulate() to simulate each block in one slot of blocks. Descendants override this method to provide custom simulation. + virtual void SimulateBlock(int a_BlockX, int a_BlockY, int a_BlockZ) = 0; +} ; + + + + diff --git a/source/Simulator/FireSimulator.cpp b/source/Simulator/FireSimulator.cpp index c2f22668b..1f20b0497 100644 --- a/source/Simulator/FireSimulator.cpp +++ b/source/Simulator/FireSimulator.cpp @@ -47,8 +47,10 @@ void cFireSimulator::Simulate( float a_Dt ) if(!IsAllowedBlock(BlockID)) //Check wheather the block is still burning continue; - if(BurnBlockAround(Pos.x, Pos.y, Pos.z)) //Burn single block and if there was one -> next time again - _AddBlock(Pos.x, Pos.y, Pos.z); + if (BurnBlockAround(Pos.x, Pos.y, Pos.z)) //Burn single block and if there was one -> next time again + { + m_Blocks->push_back(Pos); + } else if(!IsForeverBurnable(m_World->GetBlock(Pos.x, Pos.y - 1, Pos.z)) && !FiresForever(BlockID)) m_World->SetBlock(Pos.x, Pos.y, Pos.z, E_BLOCK_AIR, 0); @@ -61,42 +63,34 @@ void cFireSimulator::Simulate( float a_Dt ) -bool cFireSimulator::IsAllowedBlock( BLOCKTYPE a_BlockType ) +bool cFireSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType) { - return a_BlockType == E_BLOCK_FIRE - || IsBlockLava(a_BlockType); + return (a_BlockType == E_BLOCK_FIRE) || IsBlockLava(a_BlockType); } -void cFireSimulator::AddBlock(int a_X, int a_Y, int a_Z) +void cFireSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ) { - char BlockID = m_World->GetBlock(a_X, a_Y, a_Z); - if(!IsAllowedBlock(BlockID)) //This should save very much time because it doesnīt have to iterate through all blocks + BLOCKTYPE BlockType = m_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); + if (!IsAllowedBlock(BlockType)) + { return; + } - //check for duplicates - for( BlockList::iterator itr = m_Blocks->begin(); itr != m_Blocks->end(); ++itr ) + // Check for duplicates: + for (BlockList::iterator itr = m_Blocks->begin(); itr != m_Blocks->end(); ++itr ) { Vector3i Pos = *itr; - if( Pos.x == a_X && Pos.y == a_Y && Pos.z == a_Z ) + if ((Pos.x == a_BlockX) && (Pos.y == a_BlockY) && (Pos.z == a_BlockZ)) + { return; + } } - _AddBlock(a_X, a_Y, a_Z); - -} - - - - - -void cFireSimulator::_AddBlock(int a_X, int a_Y, int a_Z) -{ - m_Blocks->push_back( Vector3i(a_X, a_Y, a_Z) ); - + m_Blocks->push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ)); } diff --git a/source/Simulator/FireSimulator.h b/source/Simulator/FireSimulator.h index 753259c2c..826d24340 100644 --- a/source/Simulator/FireSimulator.h +++ b/source/Simulator/FireSimulator.h @@ -24,7 +24,6 @@ public: protected: virtual void AddBlock(int a_X, int a_Y, int a_Z) override; - virtual void _AddBlock(int a_X, int a_Y, int a_Z); // _X 2012_10_13: WTF? what kind of naming is this? Use proper names! virtual bool BurnBlockAround(int a_X, int a_Y, int a_Z); virtual bool BurnBlock(int a_X, int a_Y, int a_Z); diff --git a/source/Simulator/FloodyFluidSimulator.cpp b/source/Simulator/FloodyFluidSimulator.cpp new file mode 100644 index 000000000..7dcd4edca --- /dev/null +++ b/source/Simulator/FloodyFluidSimulator.cpp @@ -0,0 +1,159 @@ + +// FloodyFluidSimulator.cpp + +// Interfaces to the cFloodyFluidSimulator that represents a fluid simulator that tries to flood everything :) +// http://forum.mc-server.org/showthread.php?tid=565 + +#include "Globals.h" + +#include "FloodyFluidSimulator.h" +#include "../World.h" +#include "../BlockArea.h" +#include "../Blocks/BlockHandler.h" + + + + + +cFloodyFluidSimulator::cFloodyFluidSimulator(cWorld * a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, NIBBLETYPE a_Falloff, int a_TickDelay) : + super(a_World, a_Fluid, a_StationaryFluid, a_TickDelay), + m_Falloff(a_Falloff) +{ +} + + + + + +void cFloodyFluidSimulator::SimulateBlock(int a_BlockX, int a_BlockY, int a_BlockZ) +{ + cBlockArea Area; + int MinBlockY = std::max(0, a_BlockY - 1); + int MaxBlockY = std::min(cChunkDef::Height, a_BlockY + 1); + if (!Area.Read(m_World, a_BlockX - 1, a_BlockX + 1, MinBlockY, MaxBlockY, a_BlockZ - 1, a_BlockZ + 1)) + { + // Cannot read the immediate neighborhood, probably too close to an unloaded chunk. Bail out. + // TODO: Shouldn't we re-schedule? + return; + } + int y = (a_BlockY > 0) ? 1 : 0; // Relative y-coord of this block in Area + + NIBBLETYPE MyMeta = Area.GetRelBlockMeta(1, y, 1); + + if (MyMeta != 0) + { + if (CheckTributaries(a_BlockX, a_BlockY, a_BlockZ, Area, MyMeta)) + { + return; + } + } + + // New meta for the spreading to neighbors: + // If this is a source block or was falling, the new meta is just the falloff + // Otherwise it is the current meta plus falloff (may be larger than max height, will be checked later) + NIBBLETYPE NewMeta = ((MyMeta == 0) || ((MyMeta & 0x08) != 0)) ? m_Falloff : (MyMeta + m_Falloff); + + BLOCKTYPE Below = Area.GetRelBlockType(1, 0, 1); + if ((a_BlockY > 0) && IsPassableForFluid(Below)) + { + // Spread only down, possibly washing away what's there: + SpreadToNeighbor(a_BlockX, a_BlockY - 1, a_BlockZ, Area, 8); + } + else if (NewMeta < 8) // Can reach there + { + // Spread to the neighbors: + SpreadToNeighbor(a_BlockX - 1, a_BlockY, a_BlockZ, Area, NewMeta); + SpreadToNeighbor(a_BlockX + 1, a_BlockY, a_BlockZ, Area, NewMeta); + SpreadToNeighbor(a_BlockX, a_BlockY, a_BlockZ - 1, Area, NewMeta); + SpreadToNeighbor(a_BlockX, a_BlockY, a_BlockZ + 1, Area, NewMeta); + } + + // Mark as processed: + m_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_StationaryFluidBlock, MyMeta); +} + + + + + +bool cFloodyFluidSimulator::CheckTributaries(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockArea & a_Area, NIBBLETYPE a_MyMeta) +{ + bool IsFed = false; + int y = (a_BlockY > 0) ? 1 : 0; // Relative y-coord of this block in Area + + // If we have a section above, check if there's fluid above this block that would feed it: + if (a_BlockY < cChunkDef::Height - 1) + { + IsFed = IsAnyFluidBlock(a_Area.GetRelBlockType(1, 2, 1)); + } + + // If not fed from above, check if there's a feed from the side: + if (!IsFed) + { + IsFed = ( + (IsAnyFluidBlock(a_Area.GetRelBlockType(0, y, 1)) && IsHigherMeta(a_Area.GetRelBlockMeta(0, y, 1), a_MyMeta)) || + (IsAnyFluidBlock(a_Area.GetRelBlockType(2, y, 1)) && IsHigherMeta(a_Area.GetRelBlockMeta(2, y, 1), a_MyMeta)) || + (IsAnyFluidBlock(a_Area.GetRelBlockType(1, y, 0)) && IsHigherMeta(a_Area.GetRelBlockMeta(1, y, 0), a_MyMeta)) || + (IsAnyFluidBlock(a_Area.GetRelBlockType(1, y, 2)) && IsHigherMeta(a_Area.GetRelBlockMeta(1, y, 2), a_MyMeta)) + ); + } + + // If not fed, decrease by m_Falloff levels: + if (!IsFed) + { + a_MyMeta += m_Falloff; + if (a_MyMeta < 8) + { + m_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_StationaryFluidBlock, a_MyMeta); + } + else + { + m_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); + } + return true; + } + return false; +} + + + + + +void cFloodyFluidSimulator::SpreadToNeighbor(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockArea & a_Area, NIBBLETYPE a_NewMeta) +{ + BLOCKTYPE Block = a_Area.GetBlockType(a_BlockX, a_BlockY, a_BlockZ); + + if (IsAnyFluidBlock(Block)) + { + NIBBLETYPE Meta = a_Area.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); + if (!IsHigherMeta(a_NewMeta, Meta)) + { + // Don't spread there, there's already a higher level there + return; + } + } + if (!IsPassableForFluid(Block)) + { + // Can't spread there + return; + } + + // Wash away the block there, if possible: + if (CanWashAway(Block)) + { + cBlockHandler * Handler = BlockHandler(Block); + if (Handler->DoesDropOnUnsuitable()) + { + Handler->DropBlock(m_World, a_BlockX, a_BlockY, a_BlockZ); + } + } + + // Spread: + LOGD("Fluid: spreading to block {%d, %d, %d}, meta %d", a_BlockX, a_BlockY, a_BlockZ, a_NewMeta); + + m_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_FluidBlock, a_NewMeta); +} + + + + diff --git a/source/Simulator/FloodyFluidSimulator.h b/source/Simulator/FloodyFluidSimulator.h new file mode 100644 index 000000000..d3fa85fce --- /dev/null +++ b/source/Simulator/FloodyFluidSimulator.h @@ -0,0 +1,49 @@ + +// FloodyFluidSimulator.h + +// Interfaces to the cFloodyFluidSimulator that represents a fluid simulator that tries to flood everything :) +// http://forum.mc-server.org/showthread.php?tid=565 + + + + + +#pragma once + +#include "DelayedFluidSimulator.h" + + + + + +// fwd: +class cBlockArea; + + + + + +class cFloodyFluidSimulator : + public cDelayedFluidSimulator +{ + typedef cDelayedFluidSimulator super; + +public: + cFloodyFluidSimulator(cWorld * a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, NIBBLETYPE a_Falloff, int a_TickDelay); + +protected: + NIBBLETYPE m_Falloff; + + // cDelayedFluidSimulator overrides: + virtual void SimulateBlock(int a_BlockX, int a_BlockY, int a_BlockZ) override; + + /// Checks tributaries, if not fed, decreases the block's level and returns true + bool CheckTributaries(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockArea & a_Area, NIBBLETYPE a_MyMeta); + + /// Spreads into the specified block, if the block there allows. a_Area is for checking. + void SpreadToNeighbor(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockArea & a_Area, NIBBLETYPE a_NewMeta); +} ; + + + + diff --git a/source/Simulator/FluidSimulator.cpp b/source/Simulator/FluidSimulator.cpp index 4c867aa79..f1930c91f 100644 --- a/source/Simulator/FluidSimulator.cpp +++ b/source/Simulator/FluidSimulator.cpp @@ -19,14 +19,9 @@ cFluidSimulator::cFluidSimulator(cWorld * a_World, BLOCKTYPE a_Fluid, BLOCKTYPE -bool cFluidSimulator::IsPassableForFluid(BLOCKTYPE a_BlockType) +bool cFluidSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType) { - return ( - (a_BlockType == E_BLOCK_AIR) || - (a_BlockType == E_BLOCK_FIRE) || - IsAllowedBlock(a_BlockType) || - CanWashAway(a_BlockType) - ); + return ((a_BlockType == m_FluidBlock) || (a_BlockType == m_StationaryFluidBlock)); } @@ -65,6 +60,52 @@ bool cFluidSimulator::IsSolidBlock(BLOCKTYPE a_BlockType) +bool cFluidSimulator::IsPassableForFluid(BLOCKTYPE a_BlockType) +{ + return ( + (a_BlockType == E_BLOCK_AIR) || + (a_BlockType == E_BLOCK_FIRE) || + IsAllowedBlock(a_BlockType) || + CanWashAway(a_BlockType) + ); +} + + + + + +bool cFluidSimulator::IsHigherMeta(NIBBLETYPE a_Meta1, NIBBLETYPE a_Meta2) +{ + if (a_Meta1 == 0) + { + // Source block is higher than anything, even itself. + return true; + } + if ((a_Meta1 & 0x08) != 0) + { + // Falling fluid is higher than anything, including self + return true; + } + + if (a_Meta2 == 0) + { + // Second block is a source and first block isn't + return false; + } + if ((a_Meta2 & 0x08) != 0) + { + // Second block is falling and the first one is neither a source nor falling + return false; + } + + // All special cases have been handled, now it's just a raw comparison: + return (a_Meta1 < a_Meta2); +} + + + + + // TODO Not working very well yet :s Direction cFluidSimulator::GetFlowingDirection(int a_X, int a_Y, int a_Z, bool a_Over) { diff --git a/source/Simulator/FluidSimulator.h b/source/Simulator/FluidSimulator.h index f90de5e71..ec225728e 100644 --- a/source/Simulator/FluidSimulator.h +++ b/source/Simulator/FluidSimulator.h @@ -30,17 +30,24 @@ class cFluidSimulator : public: cFluidSimulator(cWorld * a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid); + // cSimulator overrides: + virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override; + /// Gets the flowing direction. If a_Over is true also the block over the current block affects the direction (standard) virtual Direction GetFlowingDirection(int a_X, int a_Y, int a_Z, bool a_Over = true); bool IsFluidBlock (BLOCKTYPE a_BlockType) const { return (a_BlockType == m_FluidBlock); } bool IsStationaryFluidBlock(BLOCKTYPE a_BlockType) const { return (a_BlockType == m_StationaryFluidBlock); } + bool IsAnyFluidBlock (BLOCKTYPE a_BlockType) const { return ((a_BlockType == m_FluidBlock) || (a_BlockType == m_StationaryFluidBlock)); } static bool CanWashAway(BLOCKTYPE a_BlockType); bool IsSolidBlock (BLOCKTYPE a_BlockType); bool IsPassableForFluid(BLOCKTYPE a_BlockType); + /// Returns true if a_Meta1 is a higher fluid than a_Meta2. Takes source blocks into account. + bool IsHigherMeta(NIBBLETYPE a_Meta1, NIBBLETYPE a_Meta2); + protected: BLOCKTYPE m_FluidBlock; // The fluid block type that needs simulating BLOCKTYPE m_StationaryFluidBlock; // The fluid block type that indicates no simulation is needed diff --git a/source/Simulator/Simulator.h b/source/Simulator/Simulator.h index 84a1630c2..1fecb0c96 100644 --- a/source/Simulator/Simulator.h +++ b/source/Simulator/Simulator.h @@ -28,6 +28,7 @@ public: virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) = 0; protected: + /// Called to simulate a new block virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ) = 0; cWorld * m_World; diff --git a/source/World.cpp b/source/World.cpp index f932c7c04..68f674ab6 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -16,6 +16,7 @@ // Simulators: #include "Simulator/SimulatorManager.h" #include "Simulator/ClassicFluidSimulator.h" +#include "Simulator/FloodyFluidSimulator.h" #include "Simulator/FluidSimulator.h" #include "Simulator/FireSimulator.h" #include "Simulator/SandSimulator.h" @@ -252,15 +253,10 @@ cWorld::cWorld( const AString & a_WorldName ) m_IsPumpkinBonemealable = IniFile.GetValueSetB("Plants", "IsPumpkinBonemealable", false); m_IsSugarcaneBonemealable = IniFile.GetValueSetB("Plants", "IsSugarcaneBonemealable", false); m_IsCactusBonemealable = IniFile.GetValueSetB("Plants", "IsCactusBonemealable", false); - m_bEnabledPVP = IniFile.GetValueSetB("PVP", "Enabled", true); + m_bEnabledPVP = IniFile.GetValueSetB("PVP", "Enabled", true); m_GameMode = (eGameMode)IniFile.GetValueSetI("GameMode", "GameMode", m_GameMode ); - if (!IniFile.WriteFile()) - { - LOG("WARNING: Could not write to %s", m_IniFileName.c_str()); - } - m_Lighting.Start(this); m_Storage.Start(this, StorageSchema); m_Generator.Start(this, IniFile); @@ -286,7 +282,7 @@ cWorld::cWorld( const AString & a_WorldName ) m_LastSave = 0; m_LastUnload = 0; - //preallocate some memory for ticking blocks so we donīt need to allocate that often + // preallocate some memory for ticking blocks so we donīt need to allocate that often m_BlockTickQueue.reserve(1000); m_BlockTickQueueCopy.reserve(1000); @@ -303,6 +299,12 @@ cWorld::cWorld( const AString & a_WorldName ) m_SimulatorManager->RegisterSimulator(m_SandSimulator, 1); m_SimulatorManager->RegisterSimulator(m_FireSimulator, 10); m_SimulatorManager->RegisterSimulator(m_RedstoneSimulator, 1); + + // Save any changes that the defaults may have done to the ini file: + if (!IniFile.WriteFile()) + { + LOG("WARNING: Could not write to %s", m_IniFileName.c_str()); + } } @@ -2161,7 +2163,7 @@ cFluidSimulator * cWorld::InitializeFluidSimulator(cIniFile & a_IniFile, const c Printf(SimulatorNameKey, "%sSimulator", a_FluidName); AString SimulatorSectionName; Printf(SimulatorSectionName, "%sSimulator", a_FluidName); - AString SimulatorName = a_IniFile.GetValue("Physics", SimulatorNameKey, ""); + AString SimulatorName = a_IniFile.GetValueSet("Physics", SimulatorNameKey, ""); if (SimulatorName.empty()) { LOGWARNING("%s [Physics]:%s not present or empty, using the default of \"Classic\".", GetIniFileName().c_str(), SimulatorNameKey.c_str()); @@ -2169,15 +2171,13 @@ cFluidSimulator * cWorld::InitializeFluidSimulator(cIniFile & a_IniFile, const c } cFluidSimulator * res = NULL; - /* // TODO: other fluid simulators if (NoCaseCompare(SimulatorName, "floody") == 0) { // TODO: Floody simulator params - res = new cFloodyFluidSimulator(this, a_SimulateBlock, a_StationaryBlock); + res = new cFloodyFluidSimulator(this, a_SimulateBlock, a_StationaryBlock, 1, 5); } else - */ { if (NoCaseCompare(SimulatorName, "classic") != 0) { @@ -2186,8 +2186,8 @@ cFluidSimulator * cWorld::InitializeFluidSimulator(cIniFile & a_IniFile, const c } int DefaultFalloff = (strcmp(a_FluidName, "Water") == 0) ? 1 : 2; int DefaultMaxHeight = (strcmp(a_FluidName, "Water") == 0) ? 7 : 6; - int Falloff = a_IniFile.GetValueI(SimulatorSectionName, "Falloff", DefaultFalloff); - int MaxHeight = a_IniFile.GetValueI(SimulatorSectionName, "MaxHeight", DefaultMaxHeight); + int Falloff = a_IniFile.GetValueSetI(SimulatorSectionName, "Falloff", DefaultFalloff); + int MaxHeight = a_IniFile.GetValueSetI(SimulatorSectionName, "MaxHeight", DefaultMaxHeight); res = new cClassicFluidSimulator(this, a_SimulateBlock, a_StationaryBlock, MaxHeight, Falloff); }