summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormadmaxoft <github@xoft.cz>2014-03-06 13:24:28 +0100
committermadmaxoft <github@xoft.cz>2014-03-06 13:24:28 +0100
commit3e80e636653274d138c1c5c6551e81a267b4d467 (patch)
tree821b710200bdccbd68386a34b83a425f15ee9b7d
parentMerge pull request #747 from mc-server/InfoDump_Github (diff)
parentImplemented vanilla-like fluid simulator (diff)
downloadcuberite-3e80e636653274d138c1c5c6551e81a267b4d467.tar
cuberite-3e80e636653274d138c1c5c6551e81a267b4d467.tar.gz
cuberite-3e80e636653274d138c1c5c6551e81a267b4d467.tar.bz2
cuberite-3e80e636653274d138c1c5c6551e81a267b4d467.tar.lz
cuberite-3e80e636653274d138c1c5c6551e81a267b4d467.tar.xz
cuberite-3e80e636653274d138c1c5c6551e81a267b4d467.tar.zst
cuberite-3e80e636653274d138c1c5c6551e81a267b4d467.zip
-rw-r--r--src/Scoreboard.cpp2
-rw-r--r--src/Simulator/FloodyFluidSimulator.cpp23
-rw-r--r--src/Simulator/FloodyFluidSimulator.h12
-rw-r--r--src/Simulator/VanillaFluidSimulator.cpp150
-rw-r--r--src/Simulator/VanillaFluidSimulator.h42
-rw-r--r--src/World.cpp26
6 files changed, 238 insertions, 17 deletions
diff --git a/src/Scoreboard.cpp b/src/Scoreboard.cpp
index c1da27086..8088e624b 100644
--- a/src/Scoreboard.cpp
+++ b/src/Scoreboard.cpp
@@ -506,7 +506,7 @@ bool cScoreboard::ForEachObjective(cObjectiveCallback& a_Callback)
bool cScoreboard::ForEachTeam(cTeamCallback& a_Callback)
{
- cCSLock Lock(m_CSObjectives);
+ cCSLock Lock(m_CSTeams);
for (cTeamMap::iterator it = m_Teams.begin(); it != m_Teams.end(); ++it)
{
diff --git a/src/Simulator/FloodyFluidSimulator.cpp b/src/Simulator/FloodyFluidSimulator.cpp
index 95182345c..b1ac734d7 100644
--- a/src/Simulator/FloodyFluidSimulator.cpp
+++ b/src/Simulator/FloodyFluidSimulator.cpp
@@ -86,7 +86,12 @@ void cFloodyFluidSimulator::SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_Re
{
// Spread only down, possibly washing away what's there or turning lava to stone / cobble / obsidian:
SpreadToNeighbor(a_Chunk, a_RelX, a_RelY - 1, a_RelZ, 8);
- SpreadFurther = false;
+
+ // Source blocks spread both downwards and sideways
+ if (MyMeta != 0)
+ {
+ SpreadFurther = false;
+ }
}
// If source creation is on, check for it here:
else if (
@@ -105,10 +110,7 @@ void cFloodyFluidSimulator::SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_Re
if (SpreadFurther && (NewMeta < 8))
{
// Spread to the neighbors:
- SpreadToNeighbor(a_Chunk, a_RelX - 1, a_RelY, a_RelZ, NewMeta);
- SpreadToNeighbor(a_Chunk, a_RelX + 1, a_RelY, a_RelZ, NewMeta);
- SpreadToNeighbor(a_Chunk, a_RelX, a_RelY, a_RelZ - 1, NewMeta);
- SpreadToNeighbor(a_Chunk, a_RelX, a_RelY, a_RelZ + 1, NewMeta);
+ Spread(a_Chunk, a_RelX, a_RelY, a_RelZ, NewMeta);
}
// Mark as processed:
@@ -119,6 +121,17 @@ void cFloodyFluidSimulator::SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_Re
+void cFloodyFluidSimulator::Spread(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta)
+{
+ SpreadToNeighbor(a_Chunk, a_RelX - 1, a_RelY, a_RelZ, a_NewMeta);
+ SpreadToNeighbor(a_Chunk, a_RelX + 1, a_RelY, a_RelZ, a_NewMeta);
+ SpreadToNeighbor(a_Chunk, a_RelX, a_RelY, a_RelZ - 1, a_NewMeta);
+ SpreadToNeighbor(a_Chunk, a_RelX, a_RelY, a_RelZ + 1, a_NewMeta);
+}
+
+
+
+
bool cFloodyFluidSimulator::CheckTributaries(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_MyMeta)
{
// If we have a section above, check if there's fluid above this block that would feed it:
diff --git a/src/Simulator/FloodyFluidSimulator.h b/src/Simulator/FloodyFluidSimulator.h
index c4af2e246..5fd91b2b1 100644
--- a/src/Simulator/FloodyFluidSimulator.h
+++ b/src/Simulator/FloodyFluidSimulator.h
@@ -38,14 +38,20 @@ protected:
// cDelayedFluidSimulator overrides:
virtual void SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override;
- /// Checks tributaries, if not fed, decreases the block's level and returns true
+ /** Checks tributaries, if not fed, decreases the block's level and returns true. */
bool CheckTributaries(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_MyMeta);
- /// Spreads into the specified block, if the blocktype there allows. a_Area is for checking.
+ /** Spreads into the specified block, if the blocktype there allows. a_Area is for checking. */
void SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta);
- /// Checks if there are enough neighbors to create a source at the coords specified; turns into source and returns true if so
+ /** Checks if there are enough neighbors to create a source at the coords specified; turns into source and returns true if so. */
bool CheckNeighborsForSource(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
+
+ /** Spread water to neighbors.
+ *
+ * May be overridden to provide more sophisticated algorithms.
+ */
+ virtual void Spread(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta);
} ;
diff --git a/src/Simulator/VanillaFluidSimulator.cpp b/src/Simulator/VanillaFluidSimulator.cpp
new file mode 100644
index 000000000..5308d162b
--- /dev/null
+++ b/src/Simulator/VanillaFluidSimulator.cpp
@@ -0,0 +1,150 @@
+
+// VanillaFluidSimulator.cpp
+
+#include "Globals.h"
+
+#include "VanillaFluidSimulator.h"
+#include "../World.h"
+#include "../Chunk.h"
+#include "../BlockArea.h"
+#include "../Blocks/BlockHandler.h"
+#include "../BlockInServerPluginInterface.h"
+
+
+
+
+
+static const int InfiniteCost = 100;
+
+
+
+
+
+cVanillaFluidSimulator::cVanillaFluidSimulator(
+ cWorld & a_World,
+ BLOCKTYPE a_Fluid,
+ BLOCKTYPE a_StationaryFluid,
+ NIBBLETYPE a_Falloff,
+ int a_TickDelay,
+ int a_NumNeighborsForSource
+) : super(a_World, a_Fluid, a_StationaryFluid, a_Falloff, a_TickDelay, a_NumNeighborsForSource)
+{
+}
+
+
+
+
+
+void cVanillaFluidSimulator::Spread(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta)
+{
+ int Cost[4];
+ Cost[0] = CalculateFlowCost(a_Chunk, a_RelX + 1, a_RelY, a_RelZ, X_PLUS);
+ Cost[1] = CalculateFlowCost(a_Chunk, a_RelX - 1, a_RelY, a_RelZ, X_MINUS);
+ Cost[2] = CalculateFlowCost(a_Chunk, a_RelX, a_RelY, a_RelZ + 1, Z_PLUS);
+ Cost[3] = CalculateFlowCost(a_Chunk, a_RelX, a_RelY, a_RelZ - 1, Z_MINUS);
+
+ int MinCost = InfiniteCost;
+ for (unsigned int i = 0; i < ARRAYCOUNT(Cost); ++i)
+ {
+ if (Cost[i] < MinCost)
+ {
+ MinCost = Cost[i];
+ }
+ }
+
+ if (Cost[0] == MinCost)
+ {
+ SpreadToNeighbor(a_Chunk, a_RelX + 1, a_RelY, a_RelZ, a_NewMeta);
+ }
+ if (Cost[1] == MinCost)
+ {
+ SpreadToNeighbor(a_Chunk, a_RelX - 1, a_RelY, a_RelZ, a_NewMeta);
+ }
+ if (Cost[2] == MinCost)
+ {
+ SpreadToNeighbor(a_Chunk, a_RelX, a_RelY, a_RelZ + 1, a_NewMeta);
+ }
+ if (Cost[3] == MinCost)
+ {
+ SpreadToNeighbor(a_Chunk, a_RelX, a_RelY, a_RelZ - 1, a_NewMeta);
+ }
+}
+
+
+
+
+
+int cVanillaFluidSimulator::CalculateFlowCost(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, Direction a_Dir, unsigned a_Iteration)
+{
+ int Cost = InfiniteCost;
+
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+
+ // Check if block is passable
+ if (!a_Chunk->UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta))
+ {
+ return Cost;
+ }
+ if (!IsPassableForFluid(BlockType))
+ {
+ return Cost;
+ }
+
+ // Check if block below is passable
+ if (!a_Chunk->UnboundedRelGetBlock(a_RelX, a_RelY - 1, a_RelZ, BlockType, BlockMeta))
+ {
+ return Cost;
+ }
+ if (IsPassableForFluid(BlockType))
+ {
+ // Path found, exit
+ return a_Iteration;
+ }
+
+ // 5 blocks away, bail out
+ if (a_Iteration > 3)
+ {
+ return Cost;
+ }
+
+ // Recurse
+ if (a_Dir != X_MINUS)
+ {
+ int NextCost = CalculateFlowCost(a_Chunk, a_RelX + 1, a_RelY, a_RelZ, X_PLUS, a_Iteration + 1);
+ if (NextCost < Cost)
+ {
+ Cost = NextCost;
+ }
+ }
+ if (a_Dir != X_PLUS)
+ {
+ int NextCost = CalculateFlowCost(a_Chunk, a_RelX - 1, a_RelY, a_RelZ, X_MINUS, a_Iteration + 1);
+ if (NextCost < Cost)
+ {
+ Cost = NextCost;
+ }
+ }
+ if (a_Dir != Z_MINUS)
+ {
+ int NextCost = CalculateFlowCost(a_Chunk, a_RelX, a_RelY, a_RelZ + 1, Z_PLUS, a_Iteration + 1);
+ if (NextCost < Cost)
+ {
+ Cost = NextCost;
+ }
+ }
+ if (a_Dir != Z_PLUS)
+ {
+ int NextCost = CalculateFlowCost(a_Chunk, a_RelX, a_RelY, a_RelZ - 1, Z_MINUS, a_Iteration + 1);
+ if (NextCost < Cost)
+ {
+ Cost = NextCost;
+ }
+ }
+
+ return Cost;
+}
+
+
+
+
diff --git a/src/Simulator/VanillaFluidSimulator.h b/src/Simulator/VanillaFluidSimulator.h
new file mode 100644
index 000000000..a9ea98b5a
--- /dev/null
+++ b/src/Simulator/VanillaFluidSimulator.h
@@ -0,0 +1,42 @@
+
+// VanillaFluidSimulator.h
+
+
+
+
+
+#pragma once
+
+#include "FloodyFluidSimulator.h"
+
+
+
+
+
+// fwd:
+class cBlockArea;
+
+
+
+
+
+class cVanillaFluidSimulator :
+ public cFloodyFluidSimulator
+{
+ typedef cFloodyFluidSimulator super;
+
+public:
+ cVanillaFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, NIBBLETYPE a_Falloff, int a_TickDelay, int a_NumNeighborsForSource);
+
+protected:
+ // cFloodyFluidSimulator overrides:
+ virtual void Spread(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta) override;
+
+ /** Recursively calculates the minimum number of blocks needed to descend a level. */
+ int CalculateFlowCost(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, Direction a_Dir, unsigned a_Iteration = 0);
+
+} ;
+
+
+
+
diff --git a/src/World.cpp b/src/World.cpp
index 37c07b398..73157b5bf 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -34,6 +34,7 @@
#include "Simulator/NoopRedstoneSimulator.h"
#include "Simulator/SandSimulator.h"
#include "Simulator/IncrementalRedstoneSimulator.h"
+#include "Simulator/VanillaFluidSimulator.h"
#include "Simulator/VaporizeFluidSimulator.h"
// Mobs:
@@ -3053,8 +3054,8 @@ cFluidSimulator * cWorld::InitializeFluidSimulator(cIniFile & a_IniFile, const c
AString SimulatorName = a_IniFile.GetValueSet("Physics", SimulatorNameKey, "");
if (SimulatorName.empty())
{
- LOGWARNING("[Physics] %s not present or empty in %s, using the default of \"Floody\".", SimulatorNameKey.c_str(), GetIniFileName().c_str());
- SimulatorName = "Floody";
+ LOGWARNING("[Physics] %s not present or empty in %s, using the default of \"Vanilla\".", SimulatorNameKey.c_str(), GetIniFileName().c_str());
+ SimulatorName = "Vanilla";
}
cFluidSimulator * res = NULL;
@@ -3078,15 +3079,24 @@ cFluidSimulator * cWorld::InitializeFluidSimulator(cIniFile & a_IniFile, const c
}
else
{
- if (NoCaseCompare(SimulatorName, "floody") != 0)
- {
- // The simulator name doesn't match anything we have, issue a warning:
- LOGWARNING("%s [Physics]:%s specifies an unknown simulator, using the default \"Floody\".", GetIniFileName().c_str(), SimulatorNameKey.c_str());
- }
int Falloff = a_IniFile.GetValueSetI(SimulatorSectionName, "Falloff", IsWater ? 1 : 2);
int TickDelay = a_IniFile.GetValueSetI(SimulatorSectionName, "TickDelay", IsWater ? 5 : 30);
int NumNeighborsForSource = a_IniFile.GetValueSetI(SimulatorSectionName, "NumNeighborsForSource", IsWater ? 2 : -1);
- res = new cFloodyFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, Falloff, TickDelay, NumNeighborsForSource);
+
+ if (NoCaseCompare(SimulatorName, "floody") == 0)
+ {
+ res = new cFloodyFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, Falloff, TickDelay, NumNeighborsForSource);
+ }
+ else if (NoCaseCompare(SimulatorName, "vanilla") == 0)
+ {
+ res = new cVanillaFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, Falloff, TickDelay, NumNeighborsForSource);
+ }
+ else
+ {
+ // The simulator name doesn't match anything we have, issue a warning:
+ LOGWARNING("%s [Physics]:%s specifies an unknown simulator, using the default \"Vanilla\".", GetIniFileName().c_str(), SimulatorNameKey.c_str());
+ res = new cVanillaFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, Falloff, TickDelay, NumNeighborsForSource);
+ }
}
m_SimulatorManager->RegisterSimulator(res, Rate);