summaryrefslogtreecommitdiffstats
path: root/source/Simulator
diff options
context:
space:
mode:
authorAlexander Harkness <bearbin@gmail.com>2013-11-24 15:19:41 +0100
committerAlexander Harkness <bearbin@gmail.com>2013-11-24 15:19:41 +0100
commit675b4aa878f16291ce33fced48a2bc7425f635ae (patch)
tree409914df27a98f65adf866da669429c4de141b6f /source/Simulator
parentLineBlockTracer: Using the coord-based block faces. (diff)
downloadcuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar
cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.gz
cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.bz2
cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.lz
cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.xz
cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.zst
cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.zip
Diffstat (limited to 'source/Simulator')
-rw-r--r--source/Simulator/DelayedFluidSimulator.cpp158
-rw-r--r--source/Simulator/DelayedFluidSimulator.h82
-rw-r--r--source/Simulator/FireSimulator.cpp374
-rw-r--r--source/Simulator/FireSimulator.h75
-rw-r--r--source/Simulator/FloodyFluidSimulator.cpp330
-rw-r--r--source/Simulator/FloodyFluidSimulator.h53
-rw-r--r--source/Simulator/FluidSimulator.cpp212
-rw-r--r--source/Simulator/FluidSimulator.h75
-rw-r--r--source/Simulator/NoopFluidSimulator.h36
-rw-r--r--source/Simulator/RedstoneSimulator.cpp1178
-rw-r--r--source/Simulator/RedstoneSimulator.h86
-rw-r--r--source/Simulator/SandSimulator.cpp309
-rw-r--r--source/Simulator/SandSimulator.h63
-rw-r--r--source/Simulator/Simulator.cpp51
-rw-r--r--source/Simulator/Simulator.h46
-rw-r--r--source/Simulator/SimulatorManager.cpp80
-rw-r--r--source/Simulator/SimulatorManager.h52
-rw-r--r--source/Simulator/VaporizeFluidSimulator.cpp53
-rw-r--r--source/Simulator/VaporizeFluidSimulator.h34
19 files changed, 0 insertions, 3347 deletions
diff --git a/source/Simulator/DelayedFluidSimulator.cpp b/source/Simulator/DelayedFluidSimulator.cpp
deleted file mode 100644
index a4645ca09..000000000
--- a/source/Simulator/DelayedFluidSimulator.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-
-// 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"
-#include "../Chunk.h"
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cDelayedFluidSimulatorChunkData::cSlot
-
-bool cDelayedFluidSimulatorChunkData::cSlot::Add(int a_RelX, int a_RelY, int a_RelZ)
-{
- ASSERT(a_RelZ >= 0);
- ASSERT(a_RelZ < ARRAYCOUNT(m_Blocks));
-
- cCoordWithIntVector & Blocks = m_Blocks[a_RelZ];
- int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
- for (cCoordWithIntVector::const_iterator itr = Blocks.begin(), end = Blocks.end(); itr != end; ++itr)
- {
- if (itr->Data == Index)
- {
- // Already present
- return false;
- }
- } // for itr - Blocks[]
- Blocks.push_back(cCoordWithInt(a_RelX, a_RelY, a_RelZ, Index));
- return true;
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cDelayedFluidSimulatorChunkData:
-
-cDelayedFluidSimulatorChunkData::cDelayedFluidSimulatorChunkData(int a_TickDelay) :
- m_Slots(new cSlot[a_TickDelay])
-{
-}
-
-
-
-
-
-cDelayedFluidSimulatorChunkData::~cDelayedFluidSimulatorChunkData()
-{
- delete[] m_Slots;
- m_Slots = NULL;
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cDelayedFluidSimulator:
-
-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_AddSlotNum(a_TickDelay - 1),
- m_SimSlotNum(0),
- m_TotalBlocks(0)
-{
-}
-
-
-
-
-
-void cDelayedFluidSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
-{
- 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;
- }
-
- if ((a_Chunk == NULL) || !a_Chunk->IsValid())
- {
- return;
- }
-
- int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
- int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
- BLOCKTYPE BlockType = a_Chunk->GetBlock(RelX, a_BlockY, RelZ);
- if (BlockType != m_FluidBlock)
- {
- return;
- }
-
- void * ChunkDataRaw = (m_FluidBlock == E_BLOCK_WATER) ? a_Chunk->GetWaterSimulatorData() : a_Chunk->GetLavaSimulatorData();
- cDelayedFluidSimulatorChunkData * ChunkData = (cDelayedFluidSimulatorChunkData *)ChunkDataRaw;
- cDelayedFluidSimulatorChunkData::cSlot & Slot = ChunkData->m_Slots[m_AddSlotNum];
-
- // Add, if not already present:
- if (!Slot.Add(RelX, a_BlockY, RelZ))
- {
- return;
- }
-
- ++m_TotalBlocks;
-}
-
-
-
-
-
-void cDelayedFluidSimulator::Simulate(float a_Dt)
-{
- m_AddSlotNum = m_SimSlotNum;
- m_SimSlotNum += 1;
- if (m_SimSlotNum >= m_TickDelay)
- {
- m_SimSlotNum = 0;
- }
-}
-
-
-
-
-
-void cDelayedFluidSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
-{
- void * ChunkDataRaw = (m_FluidBlock == E_BLOCK_WATER) ? a_Chunk->GetWaterSimulatorData() : a_Chunk->GetLavaSimulatorData();
- cDelayedFluidSimulatorChunkData * ChunkData = (cDelayedFluidSimulatorChunkData *)ChunkDataRaw;
- cDelayedFluidSimulatorChunkData::cSlot & Slot = ChunkData->m_Slots[m_SimSlotNum];
-
- // Simulate all the blocks in the scheduled slot:
- for (int i = 0; i < ARRAYCOUNT(Slot.m_Blocks); i++)
- {
- cCoordWithIntVector & Blocks = Slot.m_Blocks[i];
- if (Blocks.empty())
- {
- continue;
- }
- for (cCoordWithIntVector::iterator itr = Blocks.begin(), end = Blocks.end(); itr != end; ++itr)
- {
- SimulateBlock(a_Chunk, itr->x, itr->y, itr->z);
- }
- m_TotalBlocks -= Blocks.size();
- Blocks.clear();
- }
-}
-
-
-
-
diff --git a/source/Simulator/DelayedFluidSimulator.h b/source/Simulator/DelayedFluidSimulator.h
deleted file mode 100644
index c81500741..000000000
--- a/source/Simulator/DelayedFluidSimulator.h
+++ /dev/null
@@ -1,82 +0,0 @@
-
-// 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 cDelayedFluidSimulatorChunkData :
- public cFluidSimulatorData
-{
-public:
- class cSlot
- {
- public:
- /// Returns true if the specified block is stored
- bool HasBlock(int a_RelX, int a_RelY, int a_RelZ);
-
- /// Adds the specified block unless already present; returns true if added, false if the block was already present
- bool Add(int a_RelX, int a_RelY, int a_RelZ);
-
- /** Array of block containers, each item stores blocks for one Z coord
- Int param is the block index (for faster duplicate comparison in Add())
- */
- cCoordWithIntVector m_Blocks[16];
- } ;
-
- cDelayedFluidSimulatorChunkData(int a_TickDelay);
- virtual ~cDelayedFluidSimulatorChunkData();
-
- /// Slots, one for each delay tick, each containing the blocks to simulate
- cSlot * m_Slots;
-} ;
-
-
-
-
-
-class cDelayedFluidSimulator :
- public cFluidSimulator
-{
- typedef cFluidSimulator super;
-
-public:
- cDelayedFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, int a_TickDelay);
-
- // cSimulator overrides:
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
- virtual void Simulate(float a_Dt) override;
- virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override;
- virtual cFluidSimulatorData * CreateChunkData(void) override { return new cDelayedFluidSimulatorChunkData(m_TickDelay); }
-
-protected:
-
- int m_TickDelay; // Count of the m_Slots array in each ChunkData
- int m_AddSlotNum; // Index into m_Slots[] where to add new blocks in each ChunkData
- int m_SimSlotNum; // Index into m_Slots[] where to simulate blocks in each ChunkData
-
- int m_TotalBlocks; // Statistics only: the total number of blocks currently queued
-
- /*
- Slots:
- | 0 | 1 | ... | m_AddSlotNum | m_SimSlotNum | ... | m_TickDelay - 1 |
- adding blocks here ^ | ^ simulating here
- */
-
- /// Called from SimulateChunk() to simulate each block in one slot of blocks. Descendants override this method to provide custom simulation.
- virtual void SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ) = 0;
-} ;
-
-
-
-
diff --git a/source/Simulator/FireSimulator.cpp b/source/Simulator/FireSimulator.cpp
deleted file mode 100644
index ac3fb9695..000000000
--- a/source/Simulator/FireSimulator.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "FireSimulator.h"
-#include "../World.h"
-#include "../BlockID.h"
-#include "../Defines.h"
-#include "../Chunk.h"
-
-
-
-
-
-// Easy switch for turning on debugging logging:
-#if 0
- #define FLOG LOGD
-#else
- #define FLOG(...)
-#endif
-
-
-
-
-
-#define MAX_CHANCE_REPLACE_FUEL 100000
-#define MAX_CHANCE_FLAMMABILITY 100000
-
-
-
-
-
-static const struct
-{
- int x, y, z;
-} gCrossCoords[] =
-{
- { 1, 0, 0},
- {-1, 0, 0},
- { 0, 0, 1},
- { 0, 0, -1},
-} ;
-
-
-
-
-
-static const struct
-{
- int x, y, z;
-} gNeighborCoords[] =
-{
- { 1, 0, 0},
- {-1, 0, 0},
- { 0, 1, 0},
- { 0, -1, 0},
- { 0, 0, 1},
- { 0, 0, -1},
-} ;
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cFireSimulator:
-
-cFireSimulator::cFireSimulator(cWorld & a_World, cIniFile & a_IniFile) :
- cSimulator(a_World)
-{
- // Read params from the ini file:
- m_BurnStepTimeFuel = a_IniFile.GetValueSetI("FireSimulator", "BurnStepTimeFuel", 500);
- m_BurnStepTimeNonfuel = a_IniFile.GetValueSetI("FireSimulator", "BurnStepTimeNonfuel", 100);
- m_Flammability = a_IniFile.GetValueSetI("FireSimulator", "Flammability", 50);
- m_ReplaceFuelChance = a_IniFile.GetValueSetI("FireSimulator", "ReplaceFuelChance", 50000);
-}
-
-
-
-
-
-cFireSimulator::~cFireSimulator()
-{
-}
-
-
-
-
-
-void cFireSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
-{
- cCoordWithIntList & Data = a_Chunk->GetFireSimulatorData();
-
- int NumMSecs = (int)a_Dt;
- for (cCoordWithIntList::iterator itr = Data.begin(); itr != Data.end();)
- {
- int idx = cChunkDef::MakeIndexNoCheck(itr->x, itr->y, itr->z);
- BLOCKTYPE BlockType = a_Chunk->GetBlock(idx);
-
- if (!IsAllowedBlock(BlockType))
- {
- // The block is no longer eligible (not a fire block anymore; a player probably placed a block over the fire)
- FLOG("FS: Removing block {%d, %d, %d}",
- itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
- );
- itr = Data.erase(itr);
- continue;
- }
-
- // Try to spread the fire:
- TrySpreadFire(a_Chunk, itr->x, itr->y, itr->z);
-
- itr->Data -= NumMSecs;
- if (itr->Data >= 0)
- {
- // Not yet, wait for it longer
- ++itr;
- continue;
- }
-
- // Burn out the fire one step by increasing the meta:
- /*
- FLOG("FS: Fire at {%d, %d, %d} is stepping",
- itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
- );
- */
- NIBBLETYPE BlockMeta = a_Chunk->GetMeta(idx);
- if (BlockMeta == 0x0f)
- {
- // The fire burnt out completely
- FLOG("FS: Fire at {%d, %d, %d} burnt out, removing the fire block",
- itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
- );
- a_Chunk->SetBlock(itr->x, itr->y, itr->z, E_BLOCK_AIR, 0);
- RemoveFuelNeighbors(a_Chunk, itr->x, itr->y, itr->z);
- itr = Data.erase(itr);
- continue;
- }
- a_Chunk->SetMeta(idx, BlockMeta + 1);
- itr->Data = GetBurnStepTime(a_Chunk, itr->x, itr->y, itr->z); // TODO: Add some randomness into this
- } // for itr - Data[]
-}
-
-
-
-
-
-bool cFireSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType)
-{
- return (a_BlockType == E_BLOCK_FIRE);
-}
-
-
-
-
-
-bool cFireSimulator::IsFuel(BLOCKTYPE a_BlockType)
-{
- switch (a_BlockType)
- {
- case E_BLOCK_PLANKS:
- case E_BLOCK_LEAVES:
- case E_BLOCK_LOG:
- case E_BLOCK_WOOL:
- case E_BLOCK_BOOKCASE:
- case E_BLOCK_FENCE:
- case E_BLOCK_TNT:
- case E_BLOCK_VINES:
- {
- return true;
- }
- }
- return false;
-}
-
-
-
-
-
-bool cFireSimulator::IsForever(BLOCKTYPE a_BlockType)
-{
- return (a_BlockType == E_BLOCK_NETHERRACK);
-}
-
-
-
-
-
-void cFireSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
-{
- if ((a_Chunk == NULL) || !a_Chunk->IsValid())
- {
- return;
- }
-
- int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
- int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
- BLOCKTYPE BlockType = a_Chunk->GetBlock(RelX, a_BlockY, RelZ);
- if (!IsAllowedBlock(BlockType))
- {
- return;
- }
-
- // Check for duplicates:
- cFireSimulatorChunkData & ChunkData = a_Chunk->GetFireSimulatorData();
- for (cCoordWithIntList::iterator itr = ChunkData.begin(), end = ChunkData.end(); itr != end; ++itr)
- {
- if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ))
- {
- // Already present, skip adding
- return;
- }
- } // for itr - ChunkData[]
-
- FLOG("FS: Adding block {%d, %d, %d}", a_BlockX, a_BlockY, a_BlockZ);
- ChunkData.push_back(cCoordWithInt(RelX, a_BlockY, RelZ, 100));
-}
-
-
-
-
-
-int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
-{
- bool IsBlockBelowSolid = false;
- if (a_RelY > 0)
- {
- BLOCKTYPE BlockBelow = a_Chunk->GetBlock(a_RelX, a_RelY - 1, a_RelZ);
- if (IsForever(BlockBelow))
- {
- // Is burning atop of netherrack, burn forever (re-check in 10 sec)
- return 10000;
- }
- if (IsFuel(BlockBelow))
- {
- return m_BurnStepTimeFuel;
- }
- IsBlockBelowSolid = g_BlockIsSolid[BlockBelow];
- }
-
- for (int i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
- {
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- if (a_Chunk->UnboundedRelGetBlock(a_RelX + gCrossCoords[i].x, a_RelY, a_RelZ + gCrossCoords[i].z, BlockType, BlockMeta))
- {
- if (IsFuel(BlockType))
- {
- return m_BurnStepTimeFuel;
- }
- }
- } // for i - gCrossCoords[]
-
- if (!IsBlockBelowSolid && (a_RelY >= 0))
- {
- // Checked through everything, nothing was flammable
- // If block below isn't solid, we can't have fire, it would be a non-fueled fire
- // SetBlock just to make sure fire doesn't spawn
- a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0);
- return 0;
- }
- return m_BurnStepTimeNonfuel;
-}
-
-
-
-
-
-void cFireSimulator::TrySpreadFire(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
-{
- /*
- if (m_World.GetTickRandomNumber(10000) > 100)
- {
- // Make the chance to spread 100x smaller
- return;
- }
- */
-
- for (int x = a_RelX - 1; x <= a_RelX + 1; x++)
- {
- for (int z = a_RelZ - 1; z <= a_RelZ + 1; z++)
- {
- for (int y = a_RelY - 1; y <= a_RelY + 2; y++) // flames spread up one more block than around
- {
- // No need to check the coords for equality with the parent block,
- // it cannot catch fire anyway (because it's not an air block)
-
- if (m_World.GetTickRandomNumber(MAX_CHANCE_FLAMMABILITY) > m_Flammability)
- {
- continue;
- }
-
- // Start the fire in the neighbor {x, y, z}
- /*
- FLOG("FS: Trying to start fire at {%d, %d, %d}.",
- x + a_Chunk->GetPosX() * cChunkDef::Width, y, z + a_Chunk->GetPosZ() * cChunkDef::Width
- );
- */
- if (CanStartFireInBlock(a_Chunk, x, y, z))
- {
- FLOG("FS: Starting new fire at {%d, %d, %d}.",
- x + a_Chunk->GetPosX() * cChunkDef::Width, y, z + a_Chunk->GetPosZ() * cChunkDef::Width
- );
- a_Chunk->UnboundedRelSetBlock(x, y, z, E_BLOCK_FIRE, 0);
- }
- } // for y
- } // for z
- } // for x
-}
-
-
-
-
-
-void cFireSimulator::RemoveFuelNeighbors(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
-{
- for (int i = 0; i < ARRAYCOUNT(gNeighborCoords); i++)
- {
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- if (!a_Chunk->UnboundedRelGetBlock(a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z, BlockType, BlockMeta))
- {
- // Neighbor not accessible, ignore it
- continue;
- }
- if (!IsFuel(BlockType))
- {
- continue;
- }
- bool ShouldReplaceFuel = (m_World.GetTickRandomNumber(MAX_CHANCE_REPLACE_FUEL) < m_ReplaceFuelChance);
- a_Chunk->UnboundedRelSetBlock(
- a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z,
- ShouldReplaceFuel ? E_BLOCK_FIRE : E_BLOCK_AIR, 0
- );
- } // for i - Coords[]
-}
-
-
-
-
-
-bool cFireSimulator::CanStartFireInBlock(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ)
-{
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- if (!a_NearChunk->UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta))
- {
- // The chunk is not accessible
- return false;
- }
-
- if (BlockType != E_BLOCK_AIR)
- {
- // Only an air block can be replaced by a fire block
- return false;
- }
-
- for (int i = 0; i < ARRAYCOUNT(gNeighborCoords); i++)
- {
- if (!a_NearChunk->UnboundedRelGetBlock(a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z, BlockType, BlockMeta))
- {
- // Neighbor inaccessible, skip it while evaluating
- continue;
- }
- if (IsFuel(BlockType))
- {
- return true;
- }
- } // for i - Coords[]
- return false;
-}
-
-
-
-
diff --git a/source/Simulator/FireSimulator.h b/source/Simulator/FireSimulator.h
deleted file mode 100644
index 0d8a548ef..000000000
--- a/source/Simulator/FireSimulator.h
+++ /dev/null
@@ -1,75 +0,0 @@
-
-#pragma once
-
-#include "Simulator.h"
-#include "../BlockEntities/BlockEntity.h"
-
-
-
-
-
-/** The fire simulator takes care of the fire blocks.
-It periodically increases their meta ("steps") until they "burn out"; it also supports the forever burning netherrack.
-Each individual fire block gets stored in per-chunk data; that list is then used for fast retrieval.
-The data value associated with each coord is used as the number of msec that the fire takes until
-it progresses to the next step (blockmeta++). This value is updated if a neighbor is changed.
-The simulator reads its parameters from the ini file given to the constructor.
-*/
-class cFireSimulator :
- public cSimulator
-{
-public:
- cFireSimulator(cWorld & a_World, cIniFile & a_IniFile);
- ~cFireSimulator();
-
- virtual void Simulate(float a_Dt) override {} // not used
- virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override;
-
- virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override;
-
- bool IsFuel (BLOCKTYPE a_BlockType);
- bool IsForever(BLOCKTYPE a_BlockType);
-
-protected:
- /// Time (in msec) that a fire block takes to burn with a fuel block into the next step
- unsigned m_BurnStepTimeFuel;
-
- /// Time (in msec) that a fire block takes to burn without a fuel block into the next step
- unsigned m_BurnStepTimeNonfuel;
-
- /// Chance [0..100000] of an adjacent fuel to catch fire on each tick
- int m_Flammability;
-
- /// Chance [0..100000] of a fuel burning out being replaced by a new fire block instead of an air block
- int m_ReplaceFuelChance;
-
-
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
-
- /// Returns the time [msec] after which the specified fire block is stepped again; based on surrounding fuels
- int GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
-
- /// Tries to spread fire to a neighborhood of the specified block
- void TrySpreadFire(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
-
- /// Removes all burnable blocks neighboring the specified block
- void RemoveFuelNeighbors(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
-
- /** Returns true if a fire can be started in the specified block,
- that is, it is an air block and has fuel next to it.
- Note that a_NearChunk may be a chunk neighbor to the block specified!
- The coords are relative to a_NearChunk but not necessarily in it.
- */
- bool CanStartFireInBlock(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ);
-} ;
-
-
-
-
-
-/// Stores individual fire blocks in the chunk; the int data is used as the time [msec] the fire takes to step to another stage (blockmeta++)
-typedef cCoordWithIntList cFireSimulatorChunkData;
-
-
-
-
diff --git a/source/Simulator/FloodyFluidSimulator.cpp b/source/Simulator/FloodyFluidSimulator.cpp
deleted file mode 100644
index d204a1f8b..000000000
--- a/source/Simulator/FloodyFluidSimulator.cpp
+++ /dev/null
@@ -1,330 +0,0 @@
-
-// 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 "../Chunk.h"
-#include "../BlockArea.h"
-#include "../Blocks/BlockHandler.h"
-
-
-
-
-
-// Enable or disable detailed logging
-#if 0
- #define FLOG LOGD
-#else
- #define FLOG(...)
-#endif
-
-
-
-
-
-cFloodyFluidSimulator::cFloodyFluidSimulator(
- 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_TickDelay),
- m_Falloff(a_Falloff),
- m_NumNeighborsForSource(a_NumNeighborsForSource)
-{
-}
-
-
-
-
-
-void cFloodyFluidSimulator::SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
-{
- FLOG("Simulating block {%d, %d, %d}: block %d, meta %d",
- a_Chunk->GetPosX() * cChunkDef::Width + a_RelX, a_RelY, a_Chunk->GetPosZ() * cChunkDef::Width + a_RelZ,
- a_Chunk->GetBlock(a_RelX, a_RelY, a_RelZ),
- a_Chunk->GetMeta(a_RelX, a_RelY, a_RelZ)
- );
-
- NIBBLETYPE MyMeta = a_Chunk->GetMeta(a_RelX, a_RelY, a_RelZ);
- if (!IsAnyFluidBlock(a_Chunk->GetBlock(a_RelX, a_RelY, a_RelZ)))
- {
- // Can happen - if a block is scheduled for simulating and gets replaced in the meantime.
- FLOG(" BadBlockType exit");
- return;
- }
-
- if (MyMeta != 0)
- {
- // Source blocks aren't checked for tributaries, others are.
- if (CheckTributaries(a_Chunk, a_RelX, a_RelY, a_RelZ, MyMeta))
- {
- // Has no tributary, has been decreased (in CheckTributaries()),
- // no more processing needed (neighbors have been scheduled by the decrease)
- FLOG(" CheckTributaries exit");
- 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);
- bool SpreadFurther = true;
- if (a_RelY > 0)
- {
- BLOCKTYPE Below = a_Chunk->GetBlock(a_RelX, a_RelY - 1, a_RelZ);
- if (IsPassableForFluid(Below) || IsBlockLava(Below) || IsBlockWater(Below))
- {
- // 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;
- }
- // If source creation is on, check for it here:
- else if (
- (m_NumNeighborsForSource > 0) && // Source creation is on
- (MyMeta == m_Falloff) && // Only exactly one block away from a source (fast bail-out)
- !IsPassableForFluid(Below) && // Only exactly 1 block deep
- CheckNeighborsForSource(a_Chunk, a_RelX, a_RelY, a_RelZ) // Did we create a source?
- )
- {
- // We created a source, no more spreading is to be done now
- // Also has been re-scheduled for ticking in the next wave, so no marking is needed
- return;
- }
- }
-
- 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);
- }
-
- // Mark as processed:
- a_Chunk->FastSetBlock(a_RelX, a_RelY, a_RelZ, m_StationaryFluidBlock, MyMeta);
-}
-
-
-
-
-
-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:
- if (a_RelY < cChunkDef::Height - 1)
- {
- if (IsAnyFluidBlock(a_Chunk->GetBlock(a_RelX, a_RelY + 1, a_RelZ)))
- {
- // This block is fed from above, no more processing needed
- FLOG(" Fed from above");
- return false;
- }
- }
-
- // Not fed from above, check if there's a feed from the side (but not if it's a downward-flowing block):
- if (a_MyMeta != 8)
- {
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- static const Vector3i Coords[] =
- {
- Vector3i( 1, 0, 0),
- Vector3i(-1, 0, 0),
- Vector3i( 0, 0, 1),
- Vector3i( 0, 0, -1),
- } ;
- for (int i = 0; i < ARRAYCOUNT(Coords); i++)
- {
- if (!a_Chunk->UnboundedRelGetBlock(a_RelX + Coords[i].x, a_RelY, a_RelZ + Coords[i].z, BlockType, BlockMeta))
- {
- continue;
- }
- if (IsAllowedBlock(BlockType) && IsHigherMeta(BlockMeta, a_MyMeta))
- {
- // This block is fed, no more processing needed
- FLOG(" Fed from {%d, %d, %d}, type %d, meta %d",
- a_Chunk->GetPosX() * cChunkDef::Width + a_RelX + Coords[i].x,
- a_RelY,
- a_Chunk->GetPosZ() * cChunkDef::Width + a_RelZ + Coords[i].z,
- BlockType, BlockMeta
- );
- return false;
- }
- } // for i - Coords[]
- } // if not fed from above
-
- // Block is not fed, decrease by m_Falloff levels:
- if (a_MyMeta >= 8)
- {
- FLOG(" Not fed and downwards, turning into non-downwards meta %d", m_Falloff);
- a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, m_StationaryFluidBlock, m_Falloff);
- }
- else
- {
- a_MyMeta += m_Falloff;
- if (a_MyMeta < 8)
- {
- FLOG(" Not fed, decreasing from %d to %d", a_MyMeta - m_Falloff, a_MyMeta);
- a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, m_StationaryFluidBlock, a_MyMeta);
- }
- else
- {
- FLOG(" Not fed, meta %d, erasing altogether", a_MyMeta);
- a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0);
- }
- }
- return true;
-}
-
-
-
-
-
-void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta)
-{
- ASSERT(a_NewMeta <= 8); // Invalid meta values
- ASSERT(a_NewMeta > 0); // Source blocks aren't spread
-
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- if (!a_NearChunk->UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta))
- {
- // Chunk not available
- return;
- }
-
- if (IsAllowedBlock(BlockType))
- {
- if ((BlockMeta == a_NewMeta) || IsHigherMeta(BlockMeta, a_NewMeta))
- {
- // Don't spread there, there's already a higher or same level there
- return;
- }
- }
-
- // Check water - lava interaction:
- if (m_FluidBlock == E_BLOCK_LAVA)
- {
- if (IsBlockWater(BlockType))
- {
- // Lava flowing into water, change to stone / cobblestone based on direction:
- BLOCKTYPE NewBlock = (a_NewMeta == 8) ? E_BLOCK_STONE : E_BLOCK_COBBLESTONE;
- FLOG(" Lava flowing into water, turning water at rel {%d, %d, %d} into stone",
- a_RelX, a_RelY, a_RelZ,
- ItemTypeToString(NewBlock).c_str()
- );
- a_NearChunk->UnboundedRelSetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0);
- m_World.BroadcastSoundEffect("random.fizz", a_RelX * 8, a_RelY * 8, a_RelZ * 8, 0.5f, 1.5f);
- return;
- }
- }
- else if (m_FluidBlock == E_BLOCK_WATER)
- {
- if (IsBlockLava(BlockType))
- {
- // Water flowing into lava, change to cobblestone / obsidian based on dest block:
- BLOCKTYPE NewBlock = (BlockMeta == 0) ? E_BLOCK_OBSIDIAN : E_BLOCK_COBBLESTONE;
- FLOG(" Water flowing into lava, turning lava at rel {%d, %d, %d} into %s",
- a_RelX, a_RelY, a_RelZ, ItemTypeToString(NewBlock).c_str()
- );
- a_NearChunk->UnboundedRelSetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0);
- m_World.BroadcastSoundEffect("random.fizz", a_RelX * 8, a_RelY * 8, a_RelZ * 8, 0.5f, 1.5f);
- return;
- }
- }
- else
- {
- ASSERT(!"Unknown fluid!");
- }
-
- if (!IsPassableForFluid(BlockType))
- {
- // Can't spread there
- return;
- }
-
- // Wash away the block there, if possible:
- if (CanWashAway(BlockType))
- {
- cBlockHandler * Handler = BlockHandler(BlockType);
- if (Handler->DoesDropOnUnsuitable())
- {
- Handler->DropBlock(
- &m_World, NULL,
- a_NearChunk->GetPosX() * cChunkDef::Width + a_RelX,
- a_RelY,
- a_NearChunk->GetPosZ() * cChunkDef::Width + a_RelZ
- );
- }
- } // if (CanWashAway)
-
- // Spread:
- FLOG(" Spreading to {%d, %d, %d} with meta %d",
- a_NearChunk->GetPosX() * cChunkDef::Width + a_RelX,
- a_RelY,
- a_NearChunk->GetPosZ() * cChunkDef::Width + a_RelZ,
- a_NewMeta
- );
- a_NearChunk->UnboundedRelSetBlock(a_RelX, a_RelY, a_RelZ, m_FluidBlock, a_NewMeta);
-}
-
-
-
-
-
-bool cFloodyFluidSimulator::CheckNeighborsForSource(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
-{
- FLOG(" Checking neighbors for source creation");
-
- static const Vector3i NeighborCoords[] =
- {
- Vector3i(-1, 0, 0),
- Vector3i( 1, 0, 0),
- Vector3i( 0, 0, -1),
- Vector3i( 0, 0, 1),
- } ;
-
- int NumNeeded = m_NumNeighborsForSource;
- for (int i = 0; i < ARRAYCOUNT(NeighborCoords); i++)
- {
- int x = a_RelX + NeighborCoords[i].x;
- int y = a_RelY + NeighborCoords[i].y;
- int z = a_RelZ + NeighborCoords[i].z;
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- if (!a_Chunk->UnboundedRelGetBlock(x, y, z, BlockType, BlockMeta))
- {
- // Neighbor not available, skip it
- continue;
- }
- // FLOG(" Neighbor at {%d, %d, %d}: %s", x, y, z, ItemToFullString(cItem(BlockType, 1, BlockMeta)).c_str());
- if ((BlockMeta == 0) && IsAnyFluidBlock(BlockType))
- {
- NumNeeded--;
- // FLOG(" Found a neighbor source at {%d, %d, %d}, NumNeeded := %d", x, y, z, NumNeeded);
- if (NumNeeded == 0)
- {
- // Found enough, turn into a source and bail out
- // FLOG(" Found enough neighbor sources, turning into a source");
- a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, m_FluidBlock, 0);
- return true;
- }
- }
- }
- // FLOG(" Not enough neighbors for turning into a source, NumNeeded = %d", NumNeeded);
- return false;
-}
-
-
-
-
diff --git a/source/Simulator/FloodyFluidSimulator.h b/source/Simulator/FloodyFluidSimulator.h
deleted file mode 100644
index c4af2e246..000000000
--- a/source/Simulator/FloodyFluidSimulator.h
+++ /dev/null
@@ -1,53 +0,0 @@
-
-// 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, int a_NumNeighborsForSource);
-
-protected:
- NIBBLETYPE m_Falloff;
- int m_NumNeighborsForSource;
-
- // 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
- 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.
- 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
- bool CheckNeighborsForSource(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
-} ;
-
-
-
-
diff --git a/source/Simulator/FluidSimulator.cpp b/source/Simulator/FluidSimulator.cpp
deleted file mode 100644
index dac666484..000000000
--- a/source/Simulator/FluidSimulator.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-
-#include "Globals.h"
-
-#include "FluidSimulator.h"
-#include "../World.h"
-
-
-
-
-
-cFluidSimulator::cFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid) :
- super(a_World),
- m_FluidBlock(a_Fluid),
- m_StationaryFluidBlock(a_StationaryFluid)
-{
-}
-
-
-
-
-
-bool cFluidSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType)
-{
- return ((a_BlockType == m_FluidBlock) || (a_BlockType == m_StationaryFluidBlock));
-}
-
-
-
-
-
-bool cFluidSimulator::CanWashAway(BLOCKTYPE a_BlockType)
-{
- switch (a_BlockType)
- {
- case E_BLOCK_BROWN_MUSHROOM:
- case E_BLOCK_CACTUS:
- case E_BLOCK_COBWEB:
- case E_BLOCK_CROPS:
- case E_BLOCK_DEAD_BUSH:
- case E_BLOCK_RAIL:
- case E_BLOCK_REDSTONE_TORCH_OFF:
- case E_BLOCK_REDSTONE_TORCH_ON:
- case E_BLOCK_REDSTONE_WIRE:
- case E_BLOCK_RED_MUSHROOM:
- case E_BLOCK_RED_ROSE:
- case E_BLOCK_SNOW:
- case E_BLOCK_SUGARCANE:
- case E_BLOCK_TALL_GRASS:
- case E_BLOCK_TORCH:
- case E_BLOCK_YELLOW_FLOWER:
- {
- return true;
- }
- default:
- {
- return false;
- }
- }
-}
-
-
-
-
-
-bool cFluidSimulator::IsSolidBlock(BLOCKTYPE a_BlockType)
-{
- return !IsPassableForFluid(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)
-{
- if ((a_Y < 0) || (a_Y >= cChunkDef::Height))
- {
- return NONE;
- }
- BLOCKTYPE BlockID = m_World.GetBlock(a_X, a_Y, a_Z);
- if (!IsAllowedBlock(BlockID)) // No Fluid -> No Flowing direction :D
- {
- return NONE;
- }
-
- /*
- Disabled because of causing problems and being useless atm
- char BlockBelow = m_World.GetBlock(a_X, a_Y - 1, a_Z); //If there is nothing or fluid below it -> dominating flow is down :D
- if (BlockBelow == E_BLOCK_AIR || IsAllowedBlock(BlockBelow))
- return Y_MINUS;
- */
-
- NIBBLETYPE LowestPoint = m_World.GetBlockMeta(a_X, a_Y, a_Z); //Current Block Meta so only lower points will be counted
- int X = 0, Y = 0, Z = 0; //Lowest Pos will be stored here
-
- if (IsAllowedBlock(m_World.GetBlock(a_X, a_Y + 1, a_Z)) && a_Over) //check for upper block to flow because this also affects the flowing direction
- {
- return GetFlowingDirection(a_X, a_Y + 1, a_Z, false);
- }
-
- std::vector< Vector3i * > Points;
-
- Points.reserve(4); //Already allocate 4 places :D
-
- //add blocks around the checking pos
- Points.push_back(new Vector3i(a_X - 1, a_Y, a_Z));
- Points.push_back(new Vector3i(a_X + 1, a_Y, a_Z));
- Points.push_back(new Vector3i(a_X, a_Y, a_Z + 1));
- Points.push_back(new Vector3i(a_X, a_Y, a_Z - 1));
-
- for (std::vector<Vector3i *>::iterator it = Points.begin(); it < Points.end(); it++)
- {
- Vector3i *Pos = (*it);
- char BlockID = m_World.GetBlock(Pos->x, Pos->y, Pos->z);
- if(IsAllowedBlock(BlockID))
- {
- char Meta = m_World.GetBlockMeta(Pos->x, Pos->y, Pos->z);
-
- if(Meta > LowestPoint)
- {
- LowestPoint = Meta;
- X = Pos->x;
- Y = Pos->y;
- Z = Pos->z;
- }
- }else if(BlockID == E_BLOCK_AIR)
- {
- LowestPoint = 9; //This always dominates
- X = Pos->x;
- Y = Pos->y;
- Z = Pos->z;
-
- }
- delete Pos;
- }
-
- if (LowestPoint == m_World.GetBlockMeta(a_X, a_Y, a_Z))
- return NONE;
-
- if (a_X - X > 0)
- {
- return X_MINUS;
- }
-
- if (a_X - X < 0)
- {
- return X_PLUS;
- }
-
- if (a_Z - Z > 0)
- {
- return Z_MINUS;
- }
-
- if (a_Z - Z < 0)
- {
- return Z_PLUS;
- }
-
- return NONE;
-}
-
-
-
-
diff --git a/source/Simulator/FluidSimulator.h b/source/Simulator/FluidSimulator.h
deleted file mode 100644
index 672b740a2..000000000
--- a/source/Simulator/FluidSimulator.h
+++ /dev/null
@@ -1,75 +0,0 @@
-
-#pragma once
-
-#include "Simulator.h"
-
-
-
-
-
-enum Direction
-{
- X_PLUS,
- X_MINUS,
- Y_PLUS,
- Y_MINUS,
- Z_PLUS,
- Z_MINUS,
- NONE
-};
-
-
-
-
-
-/** This is a base class for all fluid simulator data classes.
-Needed so that cChunk can properly delete instances of fluid simulator data, no matter what simulator it's using
-*/
-class cFluidSimulatorData
-{
-public:
- virtual ~cFluidSimulatorData() {}
-} ;
-
-
-
-
-
-class cFluidSimulator :
- public cSimulator
-{
- typedef cSimulator super;
-
-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);
-
- /// Creates a ChunkData object for the simulator to use. The simulator returns the correct object type.
- virtual cFluidSimulatorData * CreateChunkData(void) { return NULL; }
-
- 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/NoopFluidSimulator.h b/source/Simulator/NoopFluidSimulator.h
deleted file mode 100644
index 8f894433f..000000000
--- a/source/Simulator/NoopFluidSimulator.h
+++ /dev/null
@@ -1,36 +0,0 @@
-
-// NoopFluidSimulator.h
-
-// Declares the cNoopFluidSimulator class representing a fluid simulator that performs nothing, it ignores all blocks
-
-
-
-
-
-#pragma once
-
-#include "FluidSimulator.h"
-
-
-
-
-
-class cNoopFluidSimulator :
- public cFluidSimulator
-{
- typedef cFluidSimulator super;
-
-public:
- cNoopFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid) :
- super(a_World, a_Fluid, a_StationaryFluid)
- {
- }
-
- // cSimulator overrides:
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override {}
- virtual void Simulate(float a_Dt) override {}
-} ;
-
-
-
-
diff --git a/source/Simulator/RedstoneSimulator.cpp b/source/Simulator/RedstoneSimulator.cpp
deleted file mode 100644
index 8526a888e..000000000
--- a/source/Simulator/RedstoneSimulator.cpp
+++ /dev/null
@@ -1,1178 +0,0 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "RedstoneSimulator.h"
-#include "../BlockEntities/DropSpenserEntity.h"
-#include "../Blocks/BlockTorch.h"
-#include "../Piston.h"
-#include "../World.h"
-#include "../BlockID.h"
-#include "../Chunk.h"
-#include "../Entities/TNTEntity.h"
-
-
-
-
-
-cRedstoneSimulator::cRedstoneSimulator(cWorld & a_World)
- : super(a_World)
-{
-}
-
-
-
-
-
-cRedstoneSimulator::~cRedstoneSimulator()
-{
-}
-
-
-
-
-
-void cRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
-{
- if (a_Chunk == NULL)
- {
- return;
- }
- int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
- int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
-
- // Check if any close neighbor is redstone-related:
- int MinY = (a_BlockY > 0) ? -1 : 0;
- int MaxY = (a_BlockY < cChunkDef::Height - 1) ? 1 : 0;
- for (int y = MinY; y <= MaxY; y++) for (int x = -1; x < 2; x++) for (int z = -1; z < 2; z++)
- {
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- if (!a_Chunk->UnboundedRelGetBlock(RelX + x, a_BlockY + y, RelZ + z, BlockType, BlockMeta))
- {
- continue;
- }
- switch (BlockType)
- {
- case E_BLOCK_PISTON:
- case E_BLOCK_STICKY_PISTON:
- case E_BLOCK_DISPENSER:
- case E_BLOCK_DROPPER:
- case E_BLOCK_REDSTONE_LAMP_OFF:
- case E_BLOCK_REDSTONE_LAMP_ON:
- case E_BLOCK_REDSTONE_REPEATER_OFF:
- case E_BLOCK_REDSTONE_REPEATER_ON:
- case E_BLOCK_REDSTONE_TORCH_OFF:
- case E_BLOCK_REDSTONE_TORCH_ON:
- case E_BLOCK_REDSTONE_WIRE:
- case E_BLOCK_LEVER:
- case E_BLOCK_STONE_BUTTON:
- case E_BLOCK_WOODEN_BUTTON:
- case E_BLOCK_TRIPWIRE_HOOK:
- {
- m_Blocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
- return;
- }
- } // switch (BlockType)
- } // for y, x, z - neighbors
-}
-
-
-
-
-
-void cRedstoneSimulator::Simulate(float a_Dt)
-{
- // Toggle torches on/off
- while (!m_RefreshTorchesAround.empty())
- {
- Vector3i pos = m_RefreshTorchesAround.front();
- m_RefreshTorchesAround.pop_front();
-
- RefreshTorchesAround(pos);
- }
-
- // Set repeaters to correct values, and decrement ticks
- for (RepeaterList::iterator itr = m_SetRepeaters.begin(); itr != m_SetRepeaters.end();)
- {
- if (--itr->Ticks > 0)
- {
- // Not yet, move to next item in the list
- ++itr;
- continue;
- }
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- m_World.GetBlockTypeMeta(itr->Position.x, itr->Position.y, itr->Position.z, BlockType, BlockMeta);
- if (itr->bPowerOn && (BlockType == E_BLOCK_REDSTONE_REPEATER_OFF))
- {
- m_World.FastSetBlock(itr->Position.x, itr->Position.y, itr->Position.z, E_BLOCK_REDSTONE_REPEATER_ON, BlockMeta);
- m_Blocks.push_back(itr->Position);
- }
- else if (!itr->bPowerOn && (BlockType == E_BLOCK_REDSTONE_REPEATER_ON))
- {
- m_World.FastSetBlock(itr->Position.x, itr->Position.y, itr->Position.z, E_BLOCK_REDSTONE_REPEATER_OFF, BlockMeta);
- m_Blocks.push_back(itr->Position);
- }
-
- if (itr->bPowerOffNextTime)
- {
- itr->bPowerOn = false;
- itr->bPowerOffNextTime = false;
- itr->Ticks = 10; // TODO: Look up actual ticks from block metadata
- ++itr;
- }
- else
- {
- itr = m_SetRepeaters.erase(itr);
- }
- }
-
- // Handle changed blocks
- {
- cCSLock Lock(m_CS);
- std::swap(m_Blocks, m_BlocksBuffer);
- }
- for (BlockList::iterator itr = m_BlocksBuffer.begin(); itr != m_BlocksBuffer.end(); ++itr)
- {
- HandleChange(*itr);
- }
- m_BlocksBuffer.clear();
-}
-
-
-
-
-
-void cRedstoneSimulator::RefreshTorchesAround(const Vector3i & a_BlockPos)
-{
- static Vector3i Surroundings [] = {
- Vector3i(-1, 0, 0),
- Vector3i(1, 0, 0),
- Vector3i(0, 0,-1),
- Vector3i(0, 0, 1),
- Vector3i(0, 1, 0), // Also toggle torch on top
- };
- BLOCKTYPE TargetBlockType = E_BLOCK_REDSTONE_TORCH_ON;
- BLOCKTYPE TargetRepeaterType = E_BLOCK_REDSTONE_REPEATER_OFF;
- if (IsPowered(a_BlockPos, true))
- {
- TargetBlockType = E_BLOCK_REDSTONE_TORCH_OFF;
- TargetRepeaterType = E_BLOCK_REDSTONE_REPEATER_ON;
- //Make TNT Explode when it gets powered.
- if (m_World.GetBlock(a_BlockPos) == E_BLOCK_TNT)
- {
- m_World.BroadcastSoundEffect("random.fuse", a_BlockPos.x * 8, a_BlockPos.y * 8, a_BlockPos.z * 8, 0.5f, 0.6f);
- m_World.SpawnPrimedTNT(a_BlockPos.x + 0.5, a_BlockPos.y + 0.5, a_BlockPos.z + 0.5, 4); // 4 seconds to boom
- m_World.SetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_AIR, 0);
- }
- //Turn a redstone lamp on when it gets powered.
- if (m_World.GetBlock(a_BlockPos) == E_BLOCK_REDSTONE_LAMP_OFF)
- {
- m_World.SetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_REDSTONE_LAMP_ON, 0);
- }
- //if (m_World.GetBlock(a_BlockPos) == E_BLOCK_DIRT)
- //{
- // m_World.FastSetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_STONE, 0);
- //}
- }
- else
- {
- //Turn a redstone lamp off when it gets powered.
- if (m_World.GetBlock(a_BlockPos) == E_BLOCK_REDSTONE_LAMP_ON)
- {
- m_World.SetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_REDSTONE_LAMP_OFF, 0);
- }
- //if (m_World.GetBlock(a_BlockPos) == E_BLOCK_STONE)
- //{
- // m_World.FastSetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_DIRT, 0);
- //}
- }
-
- for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i)
- {
- Vector3i TorchPos = a_BlockPos + Surroundings[i];
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- m_World.GetBlockTypeMeta(TorchPos.x, TorchPos.y, TorchPos.z, BlockType, BlockMeta);
- switch (BlockType)
- {
- case E_BLOCK_REDSTONE_TORCH_ON:
- case E_BLOCK_REDSTONE_TORCH_OFF:
- {
- if (BlockType != TargetBlockType)
- {
- if (cBlockTorchHandler::IsAttachedTo(TorchPos, BlockMeta, a_BlockPos))
- {
- m_World.FastSetBlock(TorchPos.x, TorchPos.y, TorchPos.z, TargetBlockType, BlockMeta);
- m_Blocks.push_back(TorchPos);
- }
- }
- break;
- }
- case E_BLOCK_REDSTONE_REPEATER_ON:
- case E_BLOCK_REDSTONE_REPEATER_OFF:
- {
- if ((BlockType != TargetRepeaterType) && IsRepeaterPointingAway(TorchPos, BlockMeta, a_BlockPos))
- {
- SetRepeater(TorchPos, 10, (TargetRepeaterType == E_BLOCK_REDSTONE_REPEATER_ON));
- }
- break;
- }
- } // switch (BlockType)
- } // for i - Surroundings[]
-}
-
-
-
-
-
-void cRedstoneSimulator::HandleChange(const Vector3i & a_BlockPos)
-{
- std::deque< Vector3i > SpreadStack;
-
- static const Vector3i Surroundings[] = {
- Vector3i(1, 0, 0),
- Vector3i(1, 1, 0),
- Vector3i(1,-1, 0),
- Vector3i(-1, 0, 0),
- Vector3i(-1, 1, 0),
- Vector3i(-1,-1, 0),
- Vector3i(0, 0, 1),
- Vector3i(0, 1, 1),
- Vector3i(0,-1, 1),
- Vector3i(0, 0,-1),
- Vector3i(0, 1,-1),
- Vector3i(0,-1,-1),
- Vector3i(0,-1, 0),
- };
-
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta);
-
- // First check whether torch should be on or off
- switch (BlockType)
- {
- case E_BLOCK_REDSTONE_TORCH_ON:
- case E_BLOCK_REDSTONE_TORCH_OFF:
- {
- static const Vector3i Surroundings [] = {
- Vector3i(-1, 0, 0),
- Vector3i(1, 0, 0),
- Vector3i(0, 0,-1),
- Vector3i(0, 0, 1),
- Vector3i(0,-1, 0),
- };
- for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i)
- {
- Vector3i pos = a_BlockPos + Surroundings[i];
- BLOCKTYPE OtherBlock = m_World.GetBlock(pos);
- if (
- (OtherBlock != E_BLOCK_AIR) &&
- (OtherBlock != E_BLOCK_REDSTONE_TORCH_ON) &&
- (OtherBlock != E_BLOCK_REDSTONE_TORCH_OFF)
- )
- {
- RefreshTorchesAround(pos);
- }
- }
- m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta);
- break;
- } // case "torches"
-
- case E_BLOCK_REDSTONE_REPEATER_ON:
- case E_BLOCK_REDSTONE_REPEATER_OFF:
- {
- // Check if repeater is powered by a 'powered block' (not wires/torch)
- Vector3i Direction = GetRepeaterDirection(BlockMeta);
- Vector3i pos = a_BlockPos - Direction; // NOTE: It's minus Direction
- BLOCKTYPE OtherBlock = m_World.GetBlock(pos);
- if (
- (OtherBlock != E_BLOCK_AIR) &&
- (OtherBlock != E_BLOCK_REDSTONE_TORCH_ON) &&
- (OtherBlock != E_BLOCK_REDSTONE_TORCH_OFF) &&
- (OtherBlock != E_BLOCK_REDSTONE_WIRE)
- )
- {
- RefreshTorchesAround(pos);
- }
- else
- {
- SetRepeater(a_BlockPos, 10, IsPowered(a_BlockPos, false));
- }
- m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta);
- break;
- }
- } // switch (BlockType)
-
- BlockList Sources;
- switch (BlockType)
- {
- case E_BLOCK_REDSTONE_TORCH_ON:
- {
- // If torch is still on, use it as a source
- Sources.push_back(a_BlockPos);
- break;
- }
-
- case E_BLOCK_REDSTONE_REPEATER_ON:
- {
- // Repeater only spreads charge right in front, and up to one block up:
- static const Vector3i Surroundings [] = {
- Vector3i(0, 0, 0),
- Vector3i(0, 1, 0),
- };
- Vector3i Direction = GetRepeaterDirection(BlockMeta);
- for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i)
- {
- Vector3i pos = a_BlockPos + Direction + Surroundings[i];
- if (PowerBlock(pos, a_BlockPos, 0xf))
- {
- SpreadStack.push_back(pos);
- }
- }
- break;
- } // case E_BLOCK_REDSTONE_REPEATER_ON
-
- case E_BLOCK_LEVER:
- {
- // Adding lever to the source queue
- if (cRedstoneSimulator::IsLeverOn(BlockMeta))
- {
- Sources.push_back(a_BlockPos);
- }
- break;
- } // case E_BLOCK_LEVER
- } // switch (BlockType)
-
- // Power all blocks legally connected to the sources
- if (BlockType != E_BLOCK_REDSTONE_REPEATER_ON)
- {
- BlockList NewSources = RemoveCurrent(a_BlockPos);
- Sources.insert(Sources.end(), NewSources.begin(), NewSources.end());
- while (!Sources.empty())
- {
- Vector3i SourcePos = Sources.back();
- Sources.pop_back();
-
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- m_World.GetBlockTypeMeta(SourcePos.x, SourcePos.y, SourcePos.z, BlockType, BlockMeta);
- switch (BlockType)
- {
- case E_BLOCK_LEVER: // Treating lever as a torch
- case E_BLOCK_REDSTONE_TORCH_OFF:
- case E_BLOCK_REDSTONE_TORCH_ON:
- {
- static Vector3i Surroundings [] = {
- Vector3i(-1, 0, 0),
- Vector3i(1, 0, 0),
- Vector3i(0, 0,-1),
- Vector3i(0, 0, 1),
- };
- for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i)
- {
- Vector3i OtherPos = SourcePos + Surroundings[i];
- if (PowerBlock(OtherPos, a_BlockPos, 0xf))
- {
- SpreadStack.push_back(OtherPos); // Changed, so add to stack
- }
- }
- break;
- }
-
- case E_BLOCK_REDSTONE_REPEATER_OFF:
- case E_BLOCK_REDSTONE_REPEATER_ON:
- {
- static Vector3i Surroundings [] = {
- Vector3i(0, 0, 0),
- Vector3i(0, 1, 0),
- };
- Vector3i Direction = GetRepeaterDirection(BlockMeta);
- for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i)
- {
- Vector3i pos = SourcePos + Direction + Surroundings[i];
- if (PowerBlock(pos, a_BlockPos, 0xf))
- {
- SpreadStack.push_back(pos);
- }
- }
- break;
- }
- } // switch (BlockType)
- } // while (Sources[])
- } // if (!repeater_on)
-
- // Do a floodfill
- while (!SpreadStack.empty())
- {
- Vector3i pos = SpreadStack.back();
- SpreadStack.pop_back();
- NIBBLETYPE Meta = m_World.GetBlockMeta(pos);
-
- for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i)
- {
- Vector3i OtherPos = pos + Surroundings[i];
- if (PowerBlock(OtherPos, pos, Meta - 1))
- {
- SpreadStack.push_back(OtherPos); // Changed, so add to stack
- }
- }
- }
-
- // Only after a redstone area has been completely simulated the redstone entities can react
- while (!m_RefreshPistons.empty())
- {
- Vector3i pos = m_RefreshPistons.back();
- m_RefreshPistons.pop_back();
-
- BLOCKTYPE BlockType = m_World.GetBlock(pos);
- switch (BlockType)
- {
- case E_BLOCK_PISTON:
- case E_BLOCK_STICKY_PISTON:
- {
- if (IsPowered(pos))
- {
- cPiston Piston(&m_World);
- Piston.ExtendPiston(pos.x, pos.y, pos.z);
- }
- else
- {
- cPiston Piston(&m_World);
- Piston.RetractPiston(pos.x, pos.y, pos.z);
- }
- break;
- }
- } // switch (BlockType)
- } // while (m_RefreshPistons[])
-
- while (!m_RefreshDropSpensers.empty())
- {
- Vector3i pos = m_RefreshDropSpensers.back();
- m_RefreshDropSpensers.pop_back();
-
- BLOCKTYPE BlockType = m_World.GetBlock(pos);
- if ((BlockType == E_BLOCK_DISPENSER) || (BlockType == E_BLOCK_DROPPER))
- {
- class cSetPowerToDropSpenser :
- public cDropSpenserCallback
- {
- bool m_IsPowered;
- public:
- cSetPowerToDropSpenser(bool a_IsPowered) : m_IsPowered(a_IsPowered) {}
-
- virtual bool Item(cDropSpenserEntity * a_DropSpenser) override
- {
- a_DropSpenser->SetRedstonePower(m_IsPowered);
- return false;
- }
- } DrSpSP(IsPowered(pos));
- m_World.DoWithDropSpenserAt(pos.x, pos.y, pos.z, DrSpSP);
- }
- }
-}
-
-
-
-
-
-bool cRedstoneSimulator::PowerBlock(const Vector3i & a_BlockPos, const Vector3i & a_FromBlock, char a_Power)
-{
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta);
- switch (BlockType)
- {
- case E_BLOCK_REDSTONE_WIRE:
- {
- if (BlockMeta < a_Power)
- {
- m_World.SetBlockMeta(a_BlockPos, a_Power);
- return true;
- }
- break;
- }
-
- case E_BLOCK_PISTON:
- case E_BLOCK_STICKY_PISTON:
- {
- m_RefreshPistons.push_back(a_BlockPos);
- break;
- }
-
- case E_BLOCK_DISPENSER:
- case E_BLOCK_DROPPER:
- {
- m_RefreshDropSpensers.push_back(a_BlockPos);
- break;
- }
-
- case E_BLOCK_REDSTONE_REPEATER_OFF:
- case E_BLOCK_REDSTONE_REPEATER_ON:
- {
- if (IsRepeaterPointingAway(a_BlockPos, BlockMeta, a_FromBlock))
- {
- SetRepeater(a_BlockPos, 10, true);
- }
- break;
- }
-
- case E_BLOCK_REDSTONE_LAMP_OFF:
- {
- m_World.FastSetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_REDSTONE_LAMP_ON, 0);
- break;
- }
-
- case E_BLOCK_TNT:
- {
- m_World.BroadcastSoundEffect("random.fuse", a_BlockPos.x * 8, a_BlockPos.y * 8, a_BlockPos.z * 8, 0.5f, 0.6f);
- m_World.SpawnPrimedTNT(a_BlockPos.x + 0.5, a_BlockPos.y + 0.5, a_BlockPos.z + 0.5, 4); // 4 seconds to boom
- m_World.SetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_AIR, 0);
- break;
- }
-
- default:
- {
- if (
- (BlockType != E_BLOCK_AIR) &&
- (BlockType != E_BLOCK_REDSTONE_TORCH_ON) &&
- (BlockType != E_BLOCK_REDSTONE_TORCH_OFF) &&
- (BlockType != E_BLOCK_LEVER) // Treating lever as a torch, for refreshing
- )
- {
- if (IsPowered(a_BlockPos, true))
- {
- m_RefreshTorchesAround.push_back(a_BlockPos);
- }
- }
- break;
- }
- } // switch (BlockType)
-
- return false;
-}
-
-
-
-
-
-int cRedstoneSimulator::UnPowerBlock(const Vector3i & a_BlockPos, const Vector3i & a_FromBlock)
-{
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- if ((a_BlockPos.y < 0) || (a_BlockPos.y >= cChunkDef::Height))
- {
- return 0;
- }
- m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta);
- switch (BlockType)
- {
- case E_BLOCK_REDSTONE_WIRE:
- {
- if (BlockMeta > 0)
- {
- m_World.SetBlockMeta(a_BlockPos, 0);
- return 1;
- }
- break;
- }
-
- case E_BLOCK_PISTON:
- case E_BLOCK_STICKY_PISTON:
- {
- m_RefreshPistons.push_back(a_BlockPos);
- break;
- }
-
- case E_BLOCK_DISPENSER:
- case E_BLOCK_DROPPER:
- {
- m_RefreshDropSpensers.push_back(a_BlockPos);
- break;
- }
-
- case E_BLOCK_REDSTONE_TORCH_ON:
- {
- return 2;
- break;
- }
-
- case E_BLOCK_LEVER:
- {
- // Check if lever is ON. If it is, report it back as a source
- if (cRedstoneSimulator::IsLeverOn(BlockMeta))
- {
- return 2;
- }
- break;
- }
-
- case E_BLOCK_REDSTONE_REPEATER_ON:
- {
- if (
- IsRepeaterPointingTo(a_BlockPos, BlockMeta, a_FromBlock) || // Repeater is next to wire
- IsRepeaterPointingTo(a_BlockPos, BlockMeta, a_FromBlock - Vector3i(0, 1, 0)) // Repeater is below wire
- )
- {
- return 2;
- }
- else if (IsRepeaterPointingAway(a_BlockPos, BlockMeta, a_FromBlock))
- {
- SetRepeater(a_BlockPos, 10, false);
- }
- // fall-through:
- }
-
- case E_BLOCK_REDSTONE_REPEATER_OFF:
- {
- if (IsRepeaterPointingAway(a_BlockPos, BlockMeta, a_FromBlock))
- {
- SetRepeater(a_BlockPos, 10, false);
- }
- break;
- }
-
- case E_BLOCK_REDSTONE_LAMP_ON:
- {
- m_World.FastSetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_REDSTONE_LAMP_OFF, 0);
- break;
- }
-
- default:
- {
- if (
- (BlockType != E_BLOCK_AIR) &&
- (BlockType != E_BLOCK_REDSTONE_TORCH_ON) &&
- (BlockType != E_BLOCK_REDSTONE_TORCH_OFF) &&
- (BlockType != E_BLOCK_LEVER)
- )
- {
- if (!IsPowered(a_BlockPos, true))
- {
- m_RefreshTorchesAround.push_back(a_BlockPos);
- }
- }
- break;
- }
- } // switch (BlockType)
-
- return 0;
-}
-
-
-
-
-
-// Removes current from all powered redstone wires until it reaches an energy source.
-// Also returns all energy sources it encountered
-cRedstoneSimulator::BlockList cRedstoneSimulator::RemoveCurrent(const Vector3i & a_BlockPos)
-{
-
-
- std::deque< Vector3i > SpreadStack;
- std::deque< Vector3i > FoundSources;
-
- Vector3i Surroundings[] = {
- Vector3i(1, 0, 0),
- Vector3i(1, 1, 0),
- Vector3i(1,-1, 0),
- Vector3i(-1, 0, 0),
- Vector3i(-1, 1, 0),
- Vector3i(-1,-1, 0),
- Vector3i(0, 0, 1),
- Vector3i(0, 1, 1),
- Vector3i(0,-1, 1),
- Vector3i(0, 0,-1),
- Vector3i(0, 1,-1),
- Vector3i(0,-1,-1),
- Vector3i(0,-1, 0),
- };
-
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta);
- switch (BlockType)
- {
- case E_BLOCK_REDSTONE_REPEATER_ON:
- case E_BLOCK_REDSTONE_REPEATER_OFF:
- {
- // Repeaters only spread to their front front and 0 or 1 block up
- static Vector3i Surroundings [] = {
- Vector3i(0, 0, 0),
- Vector3i(0, 1, 0),
- };
- Vector3i Direction = GetRepeaterDirection(BlockMeta);
- for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i)
- {
- Vector3i pos = a_BlockPos + Direction + Surroundings[i];
- int RetVal = UnPowerBlock(pos, a_BlockPos);
- if (RetVal == 1)
- {
- // Changed, so add to stack
- SpreadStack.push_back(pos);
- }
- else if (RetVal == 2)
- {
- FoundSources.push_back(pos);
- }
- }
- break;
- }
-
- case E_BLOCK_REDSTONE_TORCH_OFF:
- case E_BLOCK_REDSTONE_TORCH_ON:
- case E_BLOCK_LEVER:
- {
- static Vector3i Surroundings [] = { // Torches only spread on the same level
- Vector3i(-1, 0, 0),
- Vector3i(1, 0, 0),
- Vector3i(0, 0,-1),
- Vector3i(0, 0, 1),
- };
-
- for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i)
- {
- Vector3i pos = Vector3i(a_BlockPos) + Surroundings[i];
- int RetVal = UnPowerBlock(pos, a_BlockPos);
- if (RetVal == 1)
- {
- SpreadStack.push_back(pos); // Changed, so add to stack
- }
- else if (RetVal == 2)
- {
- FoundSources.push_back(pos);
- }
- }
- break;
- }
-
- default:
- {
- SpreadStack.push_back(a_BlockPos);
- break;
- }
- } // switch (BlockType)
-
-
- while (!SpreadStack.empty())
- {
- Vector3i pos = SpreadStack.back();
- SpreadStack.pop_back();
-
- for (unsigned int i = 0; i < ARRAYCOUNT(Surroundings); ++i)
- {
- Vector3i OtherPos = pos + Surroundings[i];
- int RetVal = UnPowerBlock(OtherPos, pos);
- if (RetVal == 1)
- {
- SpreadStack.push_back(OtherPos); // Changed, so add to stack
- }
- else if (RetVal == 2)
- {
- FoundSources.push_back(OtherPos);
- }
- }
- }
-
- return FoundSources;
-}
-
-
-
-
-
-bool cRedstoneSimulator::IsPowering(const Vector3i & a_PowerPos, const Vector3i & a_BlockPos, eRedstoneDirection a_WireDirection, bool a_bOnlyByWire)
-{
- BLOCKTYPE PowerBlock;
- NIBBLETYPE PowerMeta;
- m_World.GetBlockTypeMeta(a_PowerPos.x, a_PowerPos.y, a_PowerPos.z, PowerBlock, PowerMeta);
-
- // Filter out powering blocks for a_bOnlyByWire
- if (
- !a_bOnlyByWire && (
- (PowerBlock == E_BLOCK_REDSTONE_TORCH_ON) ||
- (PowerBlock == E_BLOCK_LEVER)
- )
- )
- {
- return true;
- }
-
- switch (PowerBlock)
- {
- case E_BLOCK_REDSTONE_REPEATER_ON:
- {
- // A repeater pointing towards block is regarded as wire
- if (IsRepeaterPointingTo(a_PowerPos, PowerMeta, a_BlockPos))
- {
- return true;
- }
- break;
- }
-
- case E_BLOCK_REDSTONE_WIRE:
- {
- if (PowerMeta > 0)
- {
- if (GetWireDirection(a_PowerPos) == a_WireDirection)
- {
- return true;
- }
- }
- break;
- }
- } // switch (PowerBlock)
-
- return false;
-}
-
-
-
-
-
-bool cRedstoneSimulator::IsPowered(const Vector3i & a_BlockPos, bool a_bOnlyByWire /* = false */)
-{
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, BlockType, BlockMeta);
- if ((BlockType == E_BLOCK_REDSTONE_REPEATER_OFF) || (BlockType == E_BLOCK_REDSTONE_REPEATER_ON))
- {
- Vector3i Behind = a_BlockPos - GetRepeaterDirection(BlockMeta);
- BLOCKTYPE BehindBlock;
- NIBBLETYPE BehindMeta;
- m_World.GetBlockTypeMeta(Behind.x, Behind.y, Behind.z, BehindBlock, BehindMeta);
- switch (BehindBlock)
- {
- case E_BLOCK_REDSTONE_TORCH_ON:
- case E_BLOCK_LEVER:
- {
- // _X: TODO: Shouldn't a lever be checked if it is switched on?
- return true;
- }
- case E_BLOCK_REDSTONE_WIRE:
- {
- return (BehindMeta > 0);
- }
- case E_BLOCK_REDSTONE_REPEATER_ON:
- {
- return IsRepeaterPointingTo(Behind, BehindMeta, a_BlockPos);
- }
- } // switch (BehindBlock)
- return false;
- }
-
- if (IsPowering(Vector3i(a_BlockPos.x - 1, a_BlockPos.y, a_BlockPos.z), a_BlockPos, REDSTONE_X_POS, a_bOnlyByWire))
- {
- return true;
- }
- if (IsPowering(Vector3i(a_BlockPos.x + 1, a_BlockPos.y, a_BlockPos.z), a_BlockPos, REDSTONE_X_NEG, a_bOnlyByWire))
- {
- return true;
- }
- if (IsPowering(Vector3i(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z - 1), a_BlockPos, REDSTONE_Z_POS, a_bOnlyByWire))
- {
- return true;
- }
- if (IsPowering(Vector3i(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z + 1), a_BlockPos, REDSTONE_Z_NEG, a_bOnlyByWire))
- {
- return true;
- }
-
- // Only wires can power the bottom block
- BLOCKTYPE PosYType;
- NIBBLETYPE PosYMeta;
- m_World.GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y + 1, a_BlockPos.z, PosYType, PosYMeta);
- if (PosYType == E_BLOCK_REDSTONE_WIRE)
- {
- return (PosYMeta > 0);
- }
-
- return false;
-}
-
-
-
-
-// Believe me, it works!! TODO: Add repeaters and low/high wires
-cRedstoneSimulator::eRedstoneDirection cRedstoneSimulator::GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ)
-{
- int Dir = REDSTONE_NONE;
-
- BLOCKTYPE NegX = m_World.GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ);
- if (
- (NegX == E_BLOCK_REDSTONE_WIRE) ||
- (NegX == E_BLOCK_REDSTONE_TORCH_ON) ||
- (NegX == E_BLOCK_LEVER)
- )
- {
- Dir |= (REDSTONE_X_POS);
- }
-
- BLOCKTYPE PosX = m_World.GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ);
- if (
- (PosX == E_BLOCK_REDSTONE_WIRE) ||
- (PosX == E_BLOCK_REDSTONE_TORCH_ON) ||
- (PosX == E_BLOCK_LEVER)
- )
- {
- Dir |= (REDSTONE_X_NEG);
- }
-
- BLOCKTYPE NegZ = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1);
- if (
- (NegZ == E_BLOCK_REDSTONE_WIRE) ||
- (NegZ == E_BLOCK_REDSTONE_TORCH_ON) ||
- (NegZ == E_BLOCK_LEVER)
- )
- {
- if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner
- {
- Dir ^= REDSTONE_X_POS;
- Dir |= REDSTONE_X_NEG;
- }
- if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner
- {
- Dir ^= REDSTONE_X_NEG;
- Dir |= REDSTONE_X_POS;
- }
- Dir |= REDSTONE_Z_POS;
- }
-
- BLOCKTYPE PosZ = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1);
- if (
- (PosZ == E_BLOCK_REDSTONE_WIRE) ||
- (PosZ == E_BLOCK_REDSTONE_TORCH_ON) ||
- (PosZ == E_BLOCK_LEVER)
- )
- {
- if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner
- {
- Dir ^= REDSTONE_X_POS;
- Dir |= REDSTONE_X_NEG;
- }
- if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner
- {
- Dir ^= REDSTONE_X_NEG;
- Dir |= REDSTONE_X_POS;
- }
- Dir |= REDSTONE_Z_NEG;
- }
-
- return (eRedstoneDirection)Dir;
-}
-
-
-
-
-
-bool cRedstoneSimulator::IsRepeaterPointingTo(const Vector3i & a_RepeaterPos, char a_MetaData, const Vector3i & a_BlockPos)
-{
- switch (a_MetaData & 0x3)
- {
- case 0x0:
- {
- if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(0, 0, 1)))
- {
- return true;
- }
- break;
- }
-
- case 0x1:
- {
- if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(-1, 0, 0)))
- {
- return true;
- }
- break;
- }
-
- case 0x2:
- {
- if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(0, 0,-1)))
- {
- return true;
- }
- break;
- }
-
- case 0x3:
- {
- if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(1, 0, 0)))
- {
- return true;
- }
- break;
- }
- }
- return false;
-}
-
-
-
-
-
-bool cRedstoneSimulator::IsRepeaterPointingAway(const Vector3i & a_RepeaterPos, char a_MetaData, const Vector3i & a_BlockPos)
-{
- switch (a_MetaData & 0x3)
- {
- case 0x0:
- {
- if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(0, 0,-1)))
- {
- return true;
- }
- break;
- }
-
- case 0x1:
- {
- if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(1, 0, 0)))
- {
- return true;
- }
- break;
- }
-
- case 0x2:
- {
- if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(0, 0, 1)))
- {
- return true;
- }
- break;
- }
-
- case 0x3:
- {
- if ((a_RepeaterPos - a_BlockPos).Equals(Vector3i(-1, 0, 0)))
- {
- return true;
- }
- break;
- }
- }
- return false;
-}
-
-
-
-
-
-NIBBLETYPE cRedstoneSimulator::RepeaterRotationToMetaData(double a_Rotation)
-{
- a_Rotation += 90 + 45; // So its not aligned with axis
- if (a_Rotation > 360)
- {
- a_Rotation -= 360;
- }
-
- if ((a_Rotation >= 0) && (a_Rotation < 90))
- {
- return 0x1;
- }
- else if ((a_Rotation >= 180) && (a_Rotation < 270))
- {
- return 0x3;
- }
- else if ((a_Rotation >= 90) && (a_Rotation < 180))
- {
- return 0x2;
- }
- else
- {
- return 0x0;
- }
-}
-
-
-
-
-
-Vector3i cRedstoneSimulator::GetRepeaterDirection(NIBBLETYPE a_MetaData)
-{
- switch (a_MetaData & 0x3)
- {
- case 0x0: return Vector3i(0, 0,-1);
- case 0x1: return Vector3i(1, 0, 0);
- case 0x2: return Vector3i(0, 0, 1);
- case 0x3: return Vector3i(-1, 0, 0);
- }
- return Vector3i();
-}
-
-
-
-
-
-NIBBLETYPE cRedstoneSimulator::LeverDirectionToMetaData(char a_Dir)
-{
- // Determine lever direction:
- switch (a_Dir)
- {
- case BLOCK_FACE_TOP: return 0x6;
- case BLOCK_FACE_EAST: return 0x1;
- case BLOCK_FACE_WEST: return 0x2;
- case BLOCK_FACE_SOUTH: return 0x3;
- case BLOCK_FACE_NORTH: return 0x4;
- case BLOCK_FACE_BOTTOM: return 0x0;
- default: return 0x6;
- }
-}
-
-
-
-
-
-bool cRedstoneSimulator::IsLeverOn(cWorld * a_World, const Vector3i & a_BlockPos)
-{
- // Extract the metadata and ask the lower level:
- return IsLeverOn(a_World->GetBlockMeta(a_BlockPos));
-}
-
-
-
-
-
-bool cRedstoneSimulator::IsLeverOn(NIBBLETYPE a_BlockMeta)
-{
- // Extract the ON bit from metadata and return if true if it is set:
- return ((a_BlockMeta & 0x8) == 0x8);
-}
-
-
-
-
-
-void cRedstoneSimulator::SetRepeater(const Vector3i & a_Position, int a_Ticks, bool a_bPowerOn)
-{
- for (RepeaterList::iterator itr = m_SetRepeaters.begin(); itr != m_SetRepeaters.end(); ++itr)
- {
- sRepeaterChange & Change = *itr;
- if (Change.Position.Equals(a_Position))
- {
- if (Change.bPowerOn && !a_bPowerOn)
- {
- Change.bPowerOffNextTime = true;
- }
- if (a_bPowerOn)
- {
- Change.bPowerOffNextTime = false;
- }
- Change.bPowerOn |= a_bPowerOn;
- return;
- }
- }
-
- sRepeaterChange RC;
- RC.Position = a_Position;
- RC.Ticks = a_Ticks;
- RC.bPowerOn = a_bPowerOn;
- RC.bPowerOffNextTime = false;
- m_SetRepeaters.push_back(RC);
-}
-
-
-
-
diff --git a/source/Simulator/RedstoneSimulator.h b/source/Simulator/RedstoneSimulator.h
deleted file mode 100644
index c0d5795c7..000000000
--- a/source/Simulator/RedstoneSimulator.h
+++ /dev/null
@@ -1,86 +0,0 @@
-
-#pragma once
-
-#include "Simulator.h"
-
-
-
-
-
-class cRedstoneSimulator :
- public cSimulator
-{
- typedef cSimulator super;
-public:
- cRedstoneSimulator(cWorld & a_World);
- ~cRedstoneSimulator();
-
- virtual void Simulate( float a_Dt ) override;
- virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType ) override { return true; }
-
- virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
-
- enum eRedstoneDirection
- {
- REDSTONE_NONE = 0,
- REDSTONE_X_POS = 0x1,
- REDSTONE_X_NEG = 0x2,
- REDSTONE_Z_POS = 0x4,
- REDSTONE_Z_NEG = 0x8,
- };
- eRedstoneDirection GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ);
- eRedstoneDirection GetWireDirection(const Vector3i & a_Pos) { return GetWireDirection(a_Pos.x, a_Pos.y, a_Pos.z); }
-
- static bool IsRepeaterPointingTo (const Vector3i & a_RepeaterPos, char a_MetaData, const Vector3i & a_BlockPos);
- static bool IsRepeaterPointingAway(const Vector3i & a_RepeaterPos, char a_MetaData, const Vector3i & a_BlockPos);
- static NIBBLETYPE RepeaterRotationToMetaData(double a_Rotation);
- static Vector3i GetRepeaterDirection(NIBBLETYPE a_MetaData);
- static NIBBLETYPE LeverDirectionToMetaData(char a_Dir);
- static bool IsLeverOn(cWorld * a_World, const Vector3i & a_BlockPos);
- static bool IsLeverOn(NIBBLETYPE a_BlockMeta);
-
-
-private:
- struct sRepeaterChange
- {
- Vector3i Position;
- int Ticks;
- bool bPowerOn;
- bool bPowerOffNextTime;
- };
-
- typedef std::deque <Vector3i> BlockList;
-
- typedef std::deque< sRepeaterChange > RepeaterList;
- RepeaterList m_SetRepeaters;
-
- void SetRepeater(const Vector3i & a_Position, int a_Ticks, bool a_bPowerOn);
-
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override {}
-
- void HandleChange( const Vector3i & a_BlockPos );
- BlockList RemoveCurrent( const Vector3i & a_BlockPos );
-
- bool PowerBlock( const Vector3i & a_BlockPos, const Vector3i & a_FromBlock, char a_Power );
- int UnPowerBlock( const Vector3i & a_BlockPos, const Vector3i & a_FromBlock );
-
- bool IsPowered( const Vector3i & a_BlockPos, bool a_bOnlyByWire = false );
- bool IsPowering( const Vector3i & a_PowerPos, const Vector3i & a_BlockPos, eRedstoneDirection a_WireDirection, bool a_bOnlyByWire );
-
- BlockList m_Blocks;
- BlockList m_BlocksBuffer;
-
- BlockList m_RefreshPistons;
- BlockList m_RefreshDropSpensers;
-
- BlockList m_RefreshTorchesAround;
-
- void RefreshTorchesAround( const Vector3i & a_BlockPos );
-
- // TODO: The entire simulator is synchronized, no need to lock data structures; remove this
- cCriticalSection m_CS;
-};
-
-
-
-
diff --git a/source/Simulator/SandSimulator.cpp b/source/Simulator/SandSimulator.cpp
deleted file mode 100644
index 87fb83357..000000000
--- a/source/Simulator/SandSimulator.cpp
+++ /dev/null
@@ -1,309 +0,0 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "SandSimulator.h"
-#include "../World.h"
-#include "../BlockID.h"
-#include "../Defines.h"
-#include "../Entities/FallingBlock.h"
-#include "../Chunk.h"
-
-
-
-
-
-cSandSimulator::cSandSimulator(cWorld & a_World, cIniFile & a_IniFile) :
- cSimulator(a_World),
- m_TotalBlocks(0)
-{
- m_IsInstantFall = a_IniFile.GetValueSetB("Physics", "SandInstantFall", false);
-}
-
-
-
-
-
-void cSandSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
-{
- cSandSimulatorChunkData & ChunkData = a_Chunk->GetSandSimulatorData();
- if (ChunkData.empty())
- {
- return;
- }
-
- int BaseX = a_Chunk->GetPosX() * cChunkDef::Width;
- int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width;
- for (cSandSimulatorChunkData::const_iterator itr = ChunkData.begin(), end = ChunkData.end(); itr != end; ++itr)
- {
- BLOCKTYPE BlockType = a_Chunk->GetBlock(itr->x, itr->y, itr->z);
- if (!IsAllowedBlock(BlockType) || (itr->y <= 0))
- {
- continue;
- }
-
- BLOCKTYPE BlockBelow = (itr->y > 0) ? a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z) : E_BLOCK_AIR;
- if (CanStartFallingThrough(BlockBelow))
- {
- if (m_IsInstantFall)
- {
- DoInstantFall(a_Chunk, itr->x, itr->y, itr->z);
- continue;
- }
- Vector3i Pos;
- Pos.x = itr->x + BaseX;
- Pos.y = itr->y;
- Pos.z = itr->z + BaseZ;
- /*
- LOGD(
- "Creating a falling block at {%d, %d, %d} of type %s, block below: %s",
- Pos.x, Pos.y, Pos.z, ItemTypeToString(BlockType).c_str(), ItemTypeToString(BlockBelow).c_str()
- );
- */
- cFallingBlock * FallingBlock = new cFallingBlock(Pos, BlockType, a_Chunk->GetMeta(itr->x, itr->y, itr->z));
- FallingBlock->Initialize(&m_World);
- a_Chunk->SetBlock(itr->x, itr->y, itr->z, E_BLOCK_AIR, 0);
- }
- }
- m_TotalBlocks -= ChunkData.size();
- ChunkData.clear();
-}
-
-
-
-
-
-bool cSandSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType)
-{
- switch (a_BlockType)
- {
- case E_BLOCK_SAND:
- case E_BLOCK_GRAVEL:
- case E_BLOCK_ANVIL:
- case E_BLOCK_DRAGON_EGG:
- {
- return true;
- }
- }
- return false;
-}
-
-
-
-
-
-void cSandSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
-{
- if ((a_Chunk == NULL) || !a_Chunk->IsValid())
- {
- return;
- }
- int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
- int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
- if (!IsAllowedBlock(a_Chunk->GetBlock(RelX, a_BlockY, RelZ)))
- {
- return;
- }
-
- // Check for duplicates:
- cSandSimulatorChunkData & ChunkData = a_Chunk->GetSandSimulatorData();
- for (cSandSimulatorChunkData::iterator itr = ChunkData.begin(); itr != ChunkData.end(); ++itr)
- {
- if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ))
- {
- return;
- }
- }
-
- m_TotalBlocks += 1;
- ChunkData.push_back(cCoordWithInt(RelX, a_BlockY, RelZ));
-}
-
-
-
-
-
-bool cSandSimulator::CanStartFallingThrough(BLOCKTYPE a_BlockType)
-{
- // Please keep the list alpha-sorted
- switch (a_BlockType)
- {
- case E_BLOCK_AIR:
- case E_BLOCK_FIRE:
- case E_BLOCK_LAVA:
- case E_BLOCK_SNOW:
- case E_BLOCK_STATIONARY_LAVA:
- case E_BLOCK_STATIONARY_WATER:
- case E_BLOCK_WATER:
- {
- return true;
- }
- }
- return false;
-}
-
-
-
-
-
-bool cSandSimulator::CanContinueFallThrough(BLOCKTYPE a_BlockType)
-{
- // Please keep the list alpha-sorted
- switch (a_BlockType)
- {
- case E_BLOCK_AIR:
- case E_BLOCK_BROWN_MUSHROOM:
- case E_BLOCK_COBWEB:
- case E_BLOCK_CROPS:
- case E_BLOCK_DEAD_BUSH:
- case E_BLOCK_DETECTOR_RAIL:
- case E_BLOCK_FIRE:
- case E_BLOCK_FLOWER_POT:
- case E_BLOCK_LAVA:
- case E_BLOCK_LEVER:
- case E_BLOCK_MINECART_TRACKS:
- case E_BLOCK_MELON_STEM:
- case E_BLOCK_POWERED_RAIL:
- case E_BLOCK_PUMPKIN_STEM:
- case E_BLOCK_REDSTONE_REPEATER_OFF:
- case E_BLOCK_REDSTONE_REPEATER_ON:
- case E_BLOCK_REDSTONE_TORCH_OFF:
- case E_BLOCK_REDSTONE_TORCH_ON:
- case E_BLOCK_REDSTONE_WIRE:
- case E_BLOCK_RED_MUSHROOM:
- case E_BLOCK_RED_ROSE:
- case E_BLOCK_SIGN_POST:
- case E_BLOCK_SNOW:
- case E_BLOCK_STATIONARY_LAVA:
- case E_BLOCK_STATIONARY_WATER:
- case E_BLOCK_STONE_BUTTON:
- case E_BLOCK_STONE_PRESSURE_PLATE:
- case E_BLOCK_TALL_GRASS:
- case E_BLOCK_TORCH:
- case E_BLOCK_TRAPDOOR:
- case E_BLOCK_TRIPWIRE:
- case E_BLOCK_TRIPWIRE_HOOK:
- case E_BLOCK_WALLSIGN:
- case E_BLOCK_WATER:
- case E_BLOCK_WOODEN_BUTTON:
- case E_BLOCK_WOODEN_PRESSURE_PLATE:
- case E_BLOCK_YELLOW_FLOWER:
- {
- return true;
- }
- }
- return false;
-}
-
-
-
-
-
-bool cSandSimulator::IsReplacedOnRematerialization(BLOCKTYPE a_BlockType)
-{
- // Please keep the list alpha-sorted
- switch (a_BlockType)
- {
- case E_BLOCK_AIR:
- case E_BLOCK_DEAD_BUSH:
- case E_BLOCK_FIRE:
- case E_BLOCK_LAVA:
- case E_BLOCK_SNOW:
- case E_BLOCK_STATIONARY_LAVA:
- case E_BLOCK_STATIONARY_WATER:
- case E_BLOCK_TALL_GRASS:
- case E_BLOCK_WATER:
- {
- return true;
- }
- }
- return false;
-}
-
-
-
-
-
-bool cSandSimulator::DoesBreakFallingThrough(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
-{
- switch (a_BlockType)
- {
- case E_BLOCK_STONE_SLAB:
- case E_BLOCK_WOODEN_SLAB:
- {
- return ((a_BlockMeta & 0x08) == 0); // Only a bottom-slab breaks the block
- }
- }
- return false;
-}
-
-
-
-
-
-void cSandSimulator::FinishFalling(
- cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ,
- BLOCKTYPE a_FallingBlockType, NIBBLETYPE a_FallingBlockMeta
-)
-{
- ASSERT(a_BlockY < cChunkDef::Height);
-
- BLOCKTYPE CurrentBlockType = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- if ((a_FallingBlockType == E_BLOCK_ANVIL) || IsReplacedOnRematerialization(CurrentBlockType))
- {
- // Rematerialize the material here:
- a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_FallingBlockType, a_FallingBlockMeta);
- return;
- }
-
- // Create a pickup instead:
- cItems Pickups;
- Pickups.Add((ENUM_ITEM_ID)a_FallingBlockType, 1, a_FallingBlockMeta);
- a_World->SpawnItemPickups(Pickups, (double)a_BlockX + 0.5, (double)a_BlockY + 0.5, (double)a_BlockZ + 0.5);
-}
-
-
-
-
-
-void cSandSimulator::DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
-{
- // Remove the original block:
- BLOCKTYPE FallingBlockType;
- NIBBLETYPE FallingBlockMeta;
- a_Chunk->GetBlockTypeMeta(a_RelX, a_RelY, a_RelZ, FallingBlockType, FallingBlockMeta);
- a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0);
-
- // Search for a place to put it:
- for (int y = a_RelY - 1; y >= 0; y--)
- {
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- a_Chunk->GetBlockTypeMeta(a_RelX, y, a_RelZ, BlockType, BlockMeta);
- int BlockY;
- if (DoesBreakFallingThrough(BlockType, BlockMeta))
- {
- BlockY = y;
- }
- else if (!CanContinueFallThrough(BlockType))
- {
- BlockY = y + 1;
- }
- else
- {
- // Can fall further down
- continue;
- }
-
- // Finish the fall at the found bottom:
- int BlockX = a_RelX + a_Chunk->GetPosX() * cChunkDef::Width;
- int BlockZ = a_RelZ + a_Chunk->GetPosZ() * cChunkDef::Width;
- FinishFalling(&m_World, BlockX, BlockY, BlockZ, FallingBlockType, FallingBlockMeta);
- return;
- }
-
- // The block just "fell off the world" without leaving a trace
-}
-
-
-
-
diff --git a/source/Simulator/SandSimulator.h b/source/Simulator/SandSimulator.h
deleted file mode 100644
index 6e9ea15ac..000000000
--- a/source/Simulator/SandSimulator.h
+++ /dev/null
@@ -1,63 +0,0 @@
-
-#pragma once
-
-#include "Simulator.h"
-
-
-
-
-
-/// Despite the class name, this simulator takes care of all blocks that fall when suspended in the air.
-class cSandSimulator :
- public cSimulator
-{
-public:
- cSandSimulator(cWorld & a_World, cIniFile & a_IniFile);
-
- // cSimulator overrides:
- virtual void Simulate(float a_Dt) override {} // Unused in this simulator
- virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override;
- virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override;
-
- /// Returns true if a falling-able block can start falling through the specified block type
- static bool CanStartFallingThrough(BLOCKTYPE a_BlockType);
-
- /// Returns true if an already-falling block can pass through the specified block type (e. g. torch)
- static bool CanContinueFallThrough(BLOCKTYPE a_BlockType);
-
- /// Returns true if the falling block rematerializing will replace the specified block type (e. g. tall grass)
- static bool IsReplacedOnRematerialization(BLOCKTYPE a_BlockType);
-
- /// Returns true if the specified block breaks falling blocks while they fall through it (e. g. halfslabs)
- static bool DoesBreakFallingThrough(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
-
- /** Called when a block finishes falling at the specified coords, either by insta-fall,
- or through cFallingBlock entity.
- It either rematerializes the block (a_FallingBlockType) at the specified coords, or creates a pickup,
- based on the block currently present in the world at the dest specified coords
- */
- static void FinishFalling(
- cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ,
- BLOCKTYPE a_FallingBlockType, NIBBLETYPE a_FallingBlockMeta
- );
-
-protected:
- bool m_IsInstantFall; // If set to true, blocks don't fall using cFallingBlock entity, but instantly instead
-
- int m_TotalBlocks; // Total number of blocks currently in the queue for simulating
-
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
-
- /// Performs the instant fall of the block - removes it from top, Finishes it at the bottom
- void DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
-};
-
-
-
-
-/// Per-chunk data for the simulator, specified individual chunks to simulate; Data is not used
-typedef cCoordWithIntList cSandSimulatorChunkData;
-
-
-
-
diff --git a/source/Simulator/Simulator.cpp b/source/Simulator/Simulator.cpp
deleted file mode 100644
index 06fd0f858..000000000
--- a/source/Simulator/Simulator.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "Simulator.h"
-#include "../World.h"
-#include "../Vector3i.h"
-#include "../BlockID.h"
-#include "../Defines.h"
-#include "../Chunk.h"
-
-
-
-
-
-cSimulator::cSimulator(cWorld & a_World)
- : m_World(a_World)
-{
-}
-
-
-
-
-
-cSimulator::~cSimulator()
-{
-}
-
-
-
-
-
-void cSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
-{
- AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
- AddBlock(a_BlockX - 1, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 1, a_BlockZ));
- AddBlock(a_BlockX + 1, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 1, a_BlockZ));
- AddBlock(a_BlockX, a_BlockY, a_BlockZ - 1, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 1));
- AddBlock(a_BlockX, a_BlockY, a_BlockZ + 1, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ + 1));
- if (a_BlockY > 0)
- {
- AddBlock(a_BlockX, a_BlockY - 1, a_BlockZ, a_Chunk);
- }
- if (a_BlockY < cChunkDef::Height - 1)
- {
- AddBlock(a_BlockX, a_BlockY + 1, a_BlockZ, a_Chunk);
- }
-}
-
-
-
-
diff --git a/source/Simulator/Simulator.h b/source/Simulator/Simulator.h
deleted file mode 100644
index e1d88f1c5..000000000
--- a/source/Simulator/Simulator.h
+++ /dev/null
@@ -1,46 +0,0 @@
-
-#pragma once
-
-#include "../Vector3i.h"
-#include "../../iniFile/iniFile.h"
-
-
-
-
-
-class cWorld;
-class cChunk;
-
-
-
-
-
-class cSimulator
-{
-public:
- cSimulator(cWorld & a_World);
- virtual ~cSimulator();
-
- /// Called in each tick, a_Dt is the time passed since the last tick, in msec
- virtual void Simulate(float a_Dt) = 0;
-
- /// Called in each tick for each chunk, a_Dt is the time passed since the last tick, in msec; direct access to chunk data available
- virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) {};
-
- /// Called when a block changes
- virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk);
-
- virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) = 0;
-
-protected:
- friend class cChunk; // Calls AddBlock() in its WakeUpSimulators() function, to speed things up
-
- /// Called to simulate a new block
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) = 0;
-
- cWorld & m_World;
-} ;
-
-
-
-
diff --git a/source/Simulator/SimulatorManager.cpp b/source/Simulator/SimulatorManager.cpp
deleted file mode 100644
index 2bc483cbd..000000000
--- a/source/Simulator/SimulatorManager.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "SimulatorManager.h"
-#include "../World.h"
-
-
-
-
-
-cSimulatorManager::cSimulatorManager(cWorld & a_World) :
- m_World(a_World),
- m_Ticks(0)
-{
-}
-
-
-
-
-
-cSimulatorManager::~cSimulatorManager()
-{
-}
-
-
-
-
-
-void cSimulatorManager::Simulate(float a_Dt)
-{
- m_Ticks++;
- for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr )
- {
- if ((m_Ticks % itr->second) == 0)
- {
- itr->first->Simulate(a_Dt);
- }
- }
-}
-
-
-
-
-
-void cSimulatorManager::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
-{
- // m_Ticks has already been increased in Simulate()
- for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr )
- {
- if ((m_Ticks % itr->second) == 0)
- {
- itr->first->SimulateChunk(a_Dt, a_ChunkX, a_ChunkZ, a_Chunk);
- }
- }
-}
-
-
-
-
-
-void cSimulatorManager::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
-{
- for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr )
- {
- itr->first->WakeUp(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
- }
-}
-
-
-
-
-
-void cSimulatorManager::RegisterSimulator(cSimulator * a_Simulator, int a_Rate)
-{
- m_Simulators.push_back(std::make_pair(a_Simulator, a_Rate));
-}
-
-
-
-
diff --git a/source/Simulator/SimulatorManager.h b/source/Simulator/SimulatorManager.h
deleted file mode 100644
index 31a709316..000000000
--- a/source/Simulator/SimulatorManager.h
+++ /dev/null
@@ -1,52 +0,0 @@
-
-// cSimulatorManager.h
-
-
-
-
-#pragma once
-
-
-
-
-#include "Simulator.h"
-
-
-
-
-
-// fwd: Chunk.h
-class cChunk;
-
-// fwd: World.h
-class cWorld;
-
-
-
-
-
-class cSimulatorManager
-{
-public:
- cSimulatorManager(cWorld & a_World);
- ~cSimulatorManager();
-
- void Simulate(float a_Dt);
-
- void SimulateChunk(float a_DT, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk);
-
- void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk);
-
- void RegisterSimulator(cSimulator * a_Simulator, int a_Rate); // Takes ownership of the simulator object!
-
-protected:
- typedef std::vector <std::pair<cSimulator *, int> > cSimulators;
-
- cWorld & m_World;
- cSimulators m_Simulators;
- long long m_Ticks;
-};
-
-
-
-
diff --git a/source/Simulator/VaporizeFluidSimulator.cpp b/source/Simulator/VaporizeFluidSimulator.cpp
deleted file mode 100644
index 4206c64d1..000000000
--- a/source/Simulator/VaporizeFluidSimulator.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-
-// VaporizeFluidSimulator.cpp
-
-// Implements the cVaporizeFluidSimulator class representing a fluid simulator that replaces all fluid blocks with air
-
-#include "Globals.h"
-#include "VaporizeFluidSimulator.h"
-#include "../Chunk.h"
-
-
-
-
-
-cVaporizeFluidSimulator::cVaporizeFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid) :
- super(a_World, a_Fluid, a_StationaryFluid)
-{
-}
-
-
-
-
-
-void cVaporizeFluidSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
-{
- if (a_Chunk == NULL)
- {
- return;
- }
- int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
- int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
- BLOCKTYPE BlockType = a_Chunk->GetBlock(RelX, a_BlockY, RelZ);
- if (
- (BlockType == m_FluidBlock) ||
- (BlockType == m_StationaryFluidBlock)
- )
- {
- a_Chunk->SetBlock(RelX, a_BlockY, RelZ, E_BLOCK_AIR, 0);
- a_Chunk->BroadcastSoundEffect("random.fizz", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 0.6f);
- }
-}
-
-
-
-
-
-void cVaporizeFluidSimulator::Simulate(float a_Dt)
-{
- // Nothing needed
-}
-
-
-
-
diff --git a/source/Simulator/VaporizeFluidSimulator.h b/source/Simulator/VaporizeFluidSimulator.h
deleted file mode 100644
index c8eb7802b..000000000
--- a/source/Simulator/VaporizeFluidSimulator.h
+++ /dev/null
@@ -1,34 +0,0 @@
-
-// VaporizeFluidSimulator.h
-
-// Declares the cVaporizeFluidSimulator class representing a fluid simulator that replaces all fluid blocks with air
-// Useful for water simulation in the Nether
-
-
-
-
-
-#pragma once
-
-#include "FluidSimulator.h"
-
-
-
-
-
-class cVaporizeFluidSimulator :
- public cFluidSimulator
-{
- typedef cFluidSimulator super;
-
-public:
- cVaporizeFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid);
-
- // cSimulator overrides:
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
- virtual void Simulate(float a_Dt) override;
-} ;
-
-
-
-