summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authormadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-10-14 19:06:21 +0200
committermadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-10-14 19:06:21 +0200
commit5b7de82a79e3f18affcffd686484a681d187942a (patch)
tree3a0b766fd827de634456bee9ea9ce225f40bfb60 /source
parentBiomal CompoGen now generates sea with STATIONARY_WATER instead of regular WATER. (diff)
downloadcuberite-5b7de82a79e3f18affcffd686484a681d187942a.tar
cuberite-5b7de82a79e3f18affcffd686484a681d187942a.tar.gz
cuberite-5b7de82a79e3f18affcffd686484a681d187942a.tar.bz2
cuberite-5b7de82a79e3f18affcffd686484a681d187942a.tar.lz
cuberite-5b7de82a79e3f18affcffd686484a681d187942a.tar.xz
cuberite-5b7de82a79e3f18affcffd686484a681d187942a.tar.zst
cuberite-5b7de82a79e3f18affcffd686484a681d187942a.zip
Diffstat (limited to '')
-rw-r--r--source/Simulator/ClassicFluidSimulator.cpp9
-rw-r--r--source/Simulator/ClassicFluidSimulator.h1
-rw-r--r--source/Simulator/DelayedFluidSimulator.cpp92
-rw-r--r--source/Simulator/DelayedFluidSimulator.h44
-rw-r--r--source/Simulator/FireSimulator.cpp40
-rw-r--r--source/Simulator/FireSimulator.h1
-rw-r--r--source/Simulator/FloodyFluidSimulator.cpp159
-rw-r--r--source/Simulator/FloodyFluidSimulator.h49
-rw-r--r--source/Simulator/FluidSimulator.cpp55
-rw-r--r--source/Simulator/FluidSimulator.h7
-rw-r--r--source/Simulator/Simulator.h1
-rw-r--r--source/World.cpp26
12 files changed, 430 insertions, 54 deletions
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<Vector3i> 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);
}