1
0

Merge branch 'master' into fixes

Conflicts:
	src/Vector3.h
This commit is contained in:
Tiger Wang 2014-05-06 20:15:19 +01:00
commit 696a7bc52e
21 changed files with 759 additions and 526 deletions

View File

@ -45,7 +45,30 @@ It is possible to use an external profiler to learn more about how the code perf
There's a script file, `MCServer/profile_run.cmd` that encapsulates most of the profiling work, have a look at the comments at the top of that script for details on how to get it to work. You'll need to change to a profiled configuration (both debug and release can be profiled).
## Linux, MacOS, FreeBSD etc. ##
## OSX ##
Install git from its [website](http://git-scm.com) or homebrew: `brew install git`.
Install Xcode (commandline tools are recommended) from the App Store or https://developer.apple.com/downloads.
Install CMake from its [website](http://cmake.org) or homebrew: `brew install cmake`.
### Getting the sources ###
```
mkdir MCServer
cd MCServer
git clone https://github.com/mc-server/MCServer.git .
git submodule init
git submodule update
```
### Building ###
Follow the instructions at [CMake on Unix-based platforms](#cmake-on-unix-based-platforms), using Xcode as cmake's generator. If no generator is specified, CMake will use the Makefile generator, in which case you must build with the `make` command.
After doing so, run the command `xcodebuild lib/polarssl/POLARSSL.xcodeproj` in the build directory, in order to build polarssl, a library that is required by MCServer. Lastly, run the command `xcodebuild` to build MCServer. Optionally, you may open the project files for polarssl and then MCServer in Xcode and build there.
## Linux, FreeBSD etc. ##
Install git, cmake and gcc or clang, using your platform's package manager:
```
@ -61,6 +84,14 @@ git submodule init
git submodule update
```
### Building ###
Follow the instructions at [CMake on Unix-based platforms](#cmake-on-unix-based-platforms).
After doing so, run the command `make` in the build directory, and MCServer will build.
## CMake on Unix-based platforms ###
### Release Mode ###
Release mode is preferred for almost all cases, it has much better speed and less console spam. However, if you are developing MCServer actively, debug mode might be better.
@ -69,8 +100,10 @@ Assuming you are in the MCServer folder created in the initial setup step, you n
```
mkdir Release
cd Release
cmake -DCMAKE_BUILD_TYPE=RELEASE .. && make
cmake -DCMAKE_BUILD_TYPE=RELEASE ..
```
NOTE: CMake can generate project files for many different programs, such as Xcode, eclipse, and ninja. To use a different generator, first type `cmake --help`, and at the end, cmake will output the different generators that are available. To specify one, add `-G` followed by the name of the generator, in the `cmake` command. Note that the name is case-sensitive.
The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer`.
### Debug Mode ###
@ -81,8 +114,10 @@ Assuming you are in the MCServer folder created in the Getting the sources step,
```
mkdir Debug
cd Debug
cmake -DCMAKE_BUILD_TYPE=DEBUG .. && make
cmake -DCMAKE_BUILD_TYPE=DEBUG ..
```
NOTE: CMake can generate project files for many different programs, such as Xcode, eclipse, and ninja. To use a different generator, first type `cmake --help`, and at the end, cmake will output the different generators that are available. To specify one, add `-G` followed by the name of the generator, in the `cmake` command. Note that the name is case-sensitive.
The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer_debug`.
### 32 Bit Mode switch ###

View File

@ -221,7 +221,7 @@ typedef unsigned char Byte;
#if (defined(_MSC_VER) && (_MSC_VER < 1600))
// MSVC before 2010 doesn't have std::shared_ptr, but has std::tr1::shared_ptr, defined in <memory> included earlier
#define SharedPtr std::tr1::shared_ptr
#elif (__cplusplus >= 201103L)
#elif (defined(_MSC_VER) || (__cplusplus >= 201103L))
// C++11 has std::shared_ptr in <memory>, included earlier
#define SharedPtr std::shared_ptr
#else

View File

@ -68,7 +68,6 @@ public:
{
return 0;
}
for (int newY = Y + 1; newY < cChunkDef::Height; newY++)
{
@ -84,7 +83,7 @@ public:
// This is because the frame is a solid obsidian pillar
if ((MaxY != 0) && (newY == Y + 1))
{
return EvaluatePortalBorder(X, newY, Z, MaxY, a_ChunkInterface);
return EvaluatePortalBorder(X, newY, Z, MaxY, a_ChunkInterface) ? -1 /* -1 = found a frame */ : 0;
}
else
{
@ -99,18 +98,18 @@ public:
}
/// Evaluates if coords have a valid border on top, based on MaxY
int EvaluatePortalBorder(int X, int FoundObsidianY, int Z, int MaxY, cChunkInterface & a_ChunkInterface)
bool EvaluatePortalBorder(int X, int FoundObsidianY, int Z, int MaxY, cChunkInterface & a_ChunkInterface)
{
for (int checkBorder = FoundObsidianY + 1; checkBorder <= MaxY - 1; checkBorder++) // FoundObsidianY + 1: FoundObsidianY has already been checked in FindObsidianCeiling; MaxY - 1: portal doesn't need corners
{
if (a_ChunkInterface.GetBlock(X, checkBorder, Z) != E_BLOCK_OBSIDIAN)
{
// Base obsidian, base + 1 obsidian, base + x NOT obsidian -> not complete portal
return 0;
return false;
}
}
// Everything was obsidian, found a border!
return -1; // Return -1 for a frame border
return true;
}
/// Finds entire frame in any direction with the coordinates of a base block and fills hole with nether portal (START HERE)
@ -169,7 +168,7 @@ public:
{
return false; // Not valid slice, no portal can be formed
}
} XZP = X1 - 1; // Set boundary of frame interior, note that for some reason, the loop of X and the loop of Z go to different numbers, hence -1 here and -2 there
} XZP = X1 - 1; // Set boundary of frame interior
for (; ((a_ChunkInterface.GetBlock(X2, Y, Z) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock(X2, Y + 1, Z) == E_BLOCK_OBSIDIAN)); X2--) // Go the other direction (XM)
{
int Value = FindObsidianCeiling(X2, Y, Z, a_ChunkInterface, MaxY);
@ -199,13 +198,13 @@ public:
if ((Value == -1) || (ValueTwo == -1))
{
FoundFrameZP = true;
continue;
break;
}
else if ((Value != MaxY) && (ValueTwo != MaxY))
{
return false;
}
} XZP = Z1 - 2;
} XZP = Z1 - 1;
for (; ((a_ChunkInterface.GetBlock(X, Y, Z2) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock(X, Y + 1, Z2) == E_BLOCK_OBSIDIAN)); Z2--)
{
int Value = FindObsidianCeiling(X, Y, Z2, a_ChunkInterface, MaxY);
@ -213,13 +212,13 @@ public:
if ((Value == -1) || (ValueTwo == -1))
{
FoundFrameZM = true;
continue;
break;
}
else if ((Value != MaxY) && (ValueTwo != MaxY))
{
return false;
}
} XZM = Z2 + 2;
} XZM = Z2 + 1;
return (FoundFrameZP && FoundFrameZM);
}
};

View File

@ -380,12 +380,12 @@ void cChunk::SetLight(
{ // Compress blocklight
m_BlockLight.clear();
m_BlockLight.insert(m_BlockLight.end(), &a_BlockLight[0], &a_BlockLight[m_BlockTypes.size()]);
m_BlockLight.insert(m_BlockLight.end(), &a_BlockLight[0], &a_BlockLight[m_BlockTypes.size() / 2]);
}
{ // Compress skylight
m_BlockSkyLight.clear();
m_BlockSkyLight.insert(m_BlockSkyLight.end(), &a_SkyLight[0], &a_SkyLight[m_BlockTypes.size()]);
m_BlockSkyLight.insert(m_BlockSkyLight.end(), &a_SkyLight[0], &a_SkyLight[m_BlockTypes.size() / 2]);
}
m_IsLightValid = true;
@ -749,7 +749,7 @@ void cChunk::ProcessQueuedSetBlocks(void)
{
if (itr->m_Tick <= CurrTick)
{
if (itr->m_PreviousType != E_BLOCK_AIR) // PreviousType defaults to -1 if not specified
if (itr->m_PreviousType != E_BLOCK_AIR) // PreviousType defaults to 0 if not specified
{
if (GetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ) == itr->m_PreviousType)
{
@ -1638,6 +1638,24 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
void cChunk::SetMeta(int a_BlockIdx, NIBBLETYPE a_Meta)
{
if (GetNibble(m_BlockMeta, a_BlockIdx) == a_Meta)
{
return;
}
MarkDirty();
SetNibble(m_BlockMeta, a_BlockIdx, a_Meta);
Vector3i Coords(IndexToCoordinate(a_BlockIdx));
m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, Coords.x, Coords.y, Coords.z, GetBlock(a_BlockIdx), a_Meta));
}
void cChunk::SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client)
{
// The coords must be valid, because the upper level already does chunk lookup. No need to check them again.

View File

@ -320,10 +320,10 @@ public:
m_BlockTickZ = a_RelZ;
}
inline NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ); }
inline NIBBLETYPE GetMeta(int a_BlockIdx) const {return cChunkDef::GetNibble(m_BlockMeta, a_BlockIdx); }
inline void SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta) { cChunkDef::SetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ, a_Meta); }
inline void SetMeta(int a_BlockIdx, NIBBLETYPE a_Meta) { cChunkDef::SetNibble(m_BlockMeta, a_BlockIdx, a_Meta); }
inline NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const { return cChunkDef::GetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ); }
inline NIBBLETYPE GetMeta(int a_BlockIdx) const { return cChunkDef::GetNibble(m_BlockMeta, a_BlockIdx); }
inline void SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta) { SetMeta(MakeIndex(a_RelX, a_RelY, a_RelZ), a_Meta); }
void SetMeta(int a_BlockIdx, NIBBLETYPE a_Meta);
inline NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockLight, a_RelX, a_RelY, a_RelZ); }
inline NIBBLETYPE GetSkyLight (int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_RelX, a_RelY, a_RelZ, true); }
@ -420,7 +420,6 @@ private:
cWorld * m_World;
cChunkMap * m_ChunkMap;
// TODO: Make these pointers and don't allocate what isn't needed
COMPRESSED_BLOCKTYPE m_BlockTypes;
COMPRESSED_NIBBLETYPE m_BlockMeta;
COMPRESSED_NIBBLETYPE m_BlockLight;

View File

@ -1248,8 +1248,6 @@ void cChunkMap::SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYP
if ((Chunk != NULL) && Chunk->IsValid())
{
Chunk->SetMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta);
Chunk->MarkDirty();
Chunk->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, NULL);
}
}

View File

@ -202,7 +202,7 @@ AString cClientHandle::FormatMessageType(bool ShouldAppendChatPrefixes, eMessage
{
switch (a_ChatPrefix)
{
case mtCustom: return AString();
case mtCustom: return "";
case mtFailure: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Rose, cChatColor::White);
case mtInformation: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Yellow, cChatColor::White);
case mtSuccess: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Green, cChatColor::White);
@ -224,7 +224,7 @@ AString cClientHandle::FormatMessageType(bool ShouldAppendChatPrefixes, eMessage
}
}
ASSERT(!"Unhandled chat prefix type!");
return AString();
return "";
}

View File

@ -109,7 +109,7 @@ void cDeadlockDetect::CheckWorldAge(const AString & a_WorldName, Int64 a_Age)
WorldAges::iterator itr = m_WorldAges.find(a_WorldName);
if (itr == m_WorldAges.end())
{
ASSERT(!"Unknown world in cDeadlockDetect");
SetWorldAge(a_WorldName, a_Age);
return;
}

View File

@ -87,9 +87,8 @@ void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
AddSpeedY(MilliDt * -9.8f);
AddPosition(GetSpeed() * MilliDt);
// If not static (One billionth precision) broadcast movement.
static const float epsilon = 0.000000001f;
if ((fabs(GetSpeedX()) > epsilon) || (fabs(GetSpeedZ()) > epsilon))
// If not static (one billionth precision) broadcast movement
if ((fabs(GetSpeedX()) > std::numeric_limits<double>::epsilon()) || (fabs(GetSpeedZ()) > std::numeric_limits<double>::epsilon()))
{
BroadcastMovementUpdate();
}

View File

@ -108,14 +108,13 @@ void cAggressiveMonster::Attack(float a_Dt)
bool cAggressiveMonster::IsMovingToTargetPosition()
{
static const float epsilon = 0.000000000001f;
// Difference between destination x and target x is negligible (to 10^-12 precision)
if (fabsf((float)m_FinalDestination.x - (float)m_Target->GetPosX()) < epsilon)
if (fabsf((float)m_FinalDestination.x - (float)m_Target->GetPosX()) < std::numeric_limits<float>::epsilon())
{
return false;
}
// Difference between destination z and target z is negligible (to 10^-12 precision)
else if (fabsf((float)m_FinalDestination.z - (float)m_Target->GetPosZ()) > epsilon)
else if (fabsf((float)m_FinalDestination.z - (float)m_Target->GetPosZ()) > std::numeric_limits<float>::epsilon())
{
return false;
}

View File

@ -75,7 +75,7 @@ bool cFile::Open(const AString & iFileName, eMode iMode)
}
#ifdef _WIN32
fopen_s(&m_File, (FILE_IO_PREFIX + iFileName).c_str(), Mode);
m_File = _fsopen((FILE_IO_PREFIX + iFileName).c_str(), Mode, _SH_DENYWR);
#else
m_File = fopen((FILE_IO_PREFIX + iFileName).c_str(), Mode);
#endif // _WIN32
@ -88,7 +88,7 @@ bool cFile::Open(const AString & iFileName, eMode iMode)
// Simply re-open for read-writing, erasing existing contents:
#ifdef _WIN32
fopen_s(&m_File, (FILE_IO_PREFIX + iFileName).c_str(), "wb+");
m_File = _fsopen((FILE_IO_PREFIX + iFileName).c_str(), "wb+", _SH_DENYWR);
#else
m_File = fopen((FILE_IO_PREFIX + iFileName).c_str(), "wb+");
#endif // _WIN32

View File

@ -214,7 +214,7 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
ReplaceString(ActualAddress, "%SERVERID%", a_ServerId);
AString Request;
Request += "GET " + ActualAddress + " HTTP/1.1\r\n";
Request += "GET " + ActualAddress + " HTTP/1.0\r\n";
Request += "Host: " + m_Server + "\r\n";
Request += "User-Agent: MCServer\r\n";
Request += "Connection: close\r\n";

View File

@ -238,7 +238,7 @@ protected:
bool m_IsEncrypted;
cAesCfb128Decryptor m_Decryptor;
cAesCfb128Decryptor m_Encryptor;
cAesCfb128Encryptor m_Encryptor;
/** The logfile where the comm is logged, when g_ShouldLogComm is true */
cFile m_CommLogFile;

View File

@ -119,7 +119,7 @@ void cFloodyFluidSimulator::SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_Re
if (SpreadFurther && (NewMeta < 8))
{
// Spread to the neighbors:
Spread(a_Chunk, a_RelX, a_RelY, a_RelZ, NewMeta);
SpreadXZ(a_Chunk, a_RelX, a_RelY, a_RelZ, NewMeta);
}
// Mark as processed:
@ -130,7 +130,7 @@ 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)
void cFloodyFluidSimulator::SpreadXZ(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);

View File

@ -48,16 +48,13 @@ protected:
bool CheckNeighborsForSource(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
/** Checks if the specified block should harden (Water/Lava interaction) and if so, converts it to a suitable block.
*
* Returns whether the block was changed or not.
*/
Returns whether the block was changed or not. */
bool HardenBlock(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta);
/** 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);
/** Spread fluid to XZ neighbors.
The coords are of the block currently being processed; a_NewMeta is the new meta for the new fluid block.
Descendants may overridde to provide more sophisticated algorithms. */
virtual void SpreadXZ(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta);
} ;

File diff suppressed because it is too large Load Diff

View File

@ -55,13 +55,13 @@ private:
struct sSimulatedPlayerToggleableList // Define structure of the list containing simulate-on-update blocks (such as trapdoors that respond once to a block update, and can be toggled by a player)
{
Vector3i a_BlockPos;
Vector3i a_RelBlockPos;
bool WasLastStatePowered; // Was the last state powered or not? Determines whether a source update has happened and if I should resimulate
};
struct sRepeatersDelayList // Define structure of list containing repeaters' delay states
{
Vector3i a_BlockPos;
Vector3i a_RelBlockPos;
unsigned char a_DelayTicks; // For how many ticks should the repeater delay
unsigned char a_ElapsedTicks; // How much of the previous has been elapsed?
bool ShouldPowerOn; // What happens when the delay time is fulfilled?
@ -91,80 +91,80 @@ private:
/* ====== SOURCES ====== */
/** Handles the redstone torch */
void HandleRedstoneTorch(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState);
void HandleRedstoneTorch(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
/** Handles the redstone block */
void HandleRedstoneBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
void HandleRedstoneBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles levers */
void HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_BlockZ);
void HandleRedstoneLever(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles buttons */
void HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType);
void HandleRedstoneButton(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles daylight sensors */
void HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ);
void HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles pressure plates */
void HandlePressurePlate(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType);
void HandlePressurePlate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType);
/* ==================== */
/* ====== CARRIERS ====== */
/** Handles redstone wire */
void HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_BlockZ);
void HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles repeaters */
void HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState);
void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
/* ====================== */
/* ====== DEVICES ====== */
/** Handles pistons */
void HandlePiston(int a_BlockX, int a_BlockY, int a_BlockZ);
void HandlePiston(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles dispensers and droppers */
void HandleDropSpenser(int a_BlockX, int a_BlockY, int a_BlockZ);
void HandleDropSpenser(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles TNT (exploding) */
void HandleTNT(int a_BlockX, int a_BlockY, int a_BlockZ);
void HandleTNT(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles redstone lamps */
void HandleRedstoneLamp(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState);
void HandleRedstoneLamp(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
/** Handles doords */
void HandleDoor(int a_BlockX, int a_BlockY, int a_BlockZ);
void HandleDoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles command blocks */
void HandleCommandBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
void HandleCommandBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles activator, detector, and powered rails */
void HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType);
void HandleRail(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType);
/** Handles trapdoors */
void HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ);
void HandleTrapdoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles fence gates */
void HandleFenceGate(int a_BlockX, int a_BlockY, int a_BlockZ);
void HandleFenceGate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles noteblocks */
void HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
void HandleNoteBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/* ===================== */
/* ====== Helper functions ====== */
/** Marks a block as powered */
void SetBlockPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
void SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
/** Marks a block as being powered through another block */
void SetBlockLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_MiddleX, int a_MiddleY, int a_MiddleZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock, BLOCKTYPE a_MiddeBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
void SetBlockLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelMiddleX, int a_RelMiddleY, int a_RelMiddleZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, BLOCKTYPE a_MiddeBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
/** Marks a block as simulated, who should not be simulated further unless their power state changes, to accomodate a player manually toggling the block without triggering the simulator toggling it back */
void SetPlayerToggleableBlockAsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool WasLastStatePowered);
void SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool WasLastStatePowered);
/** Marks the second block in a direction as linked powered */
void SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, BLOCKTYPE a_SourceBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
void SetDirectionLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, char a_Direction, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
/** Marks all blocks immediately surrounding a coordinate as powered */
void SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
void SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
/** Queues a repeater to be powered or unpowered */
void QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
void QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
/** Returns if a coordinate is powered or linked powered */
bool AreCoordsPowered(int a_BlockX, int a_BlockY, int a_BlockZ) { return AreCoordsDirectlyPowered(a_BlockX, a_BlockY, a_BlockZ) || AreCoordsLinkedPowered(a_BlockX, a_BlockY, a_BlockZ); }
bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }
/** Returns if a coordinate is in the directly powered blocks list */
bool AreCoordsDirectlyPowered(int a_BlockX, int a_BlockY, int a_BlockZ);
bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Returns if a coordinate is in the indirectly powered blocks list */
bool AreCoordsLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ);
bool AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */
bool AreCoordsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool IsCurrentStatePowered);
bool AreCoordsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool IsCurrentStatePowered);
/** Returns if a repeater is powered */
bool IsRepeaterPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta);
bool IsRepeaterPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
/** Returns if a repeater is locked */
bool IsRepeaterLocked(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta);
bool IsRepeaterLocked(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
/** Returns if a piston is powered */
bool IsPistonPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta);
bool IsPistonPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
/** Returns if a wire is powered
The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire */
bool IsWirePowered(int a_BlockX, int a_BlockY, int a_BlockZ, unsigned char & a_PowerLevel);
bool IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel);
/** Returns if lever metadata marks it as emitting power */

View File

@ -35,14 +35,16 @@ cVanillaFluidSimulator::cVanillaFluidSimulator(
void cVanillaFluidSimulator::Spread(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta)
void cVanillaFluidSimulator::SpreadXZ(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta)
{
// Calculate the distance to the nearest "hole" in each direction:
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);
// Find the minimum distance:
int MinCost = InfiniteCost;
for (unsigned int i = 0; i < ARRAYCOUNT(Cost); ++i)
{
@ -52,6 +54,7 @@ void cVanillaFluidSimulator::Spread(cChunk * a_Chunk, int a_RelX, int a_RelY, in
}
}
// Spread in all directions where the distance matches the minimum:
if (Cost[0] == MinCost)
{
SpreadToNeighbor(a_Chunk, a_RelX + 1, a_RelY, a_RelZ, a_NewMeta);
@ -86,7 +89,10 @@ int cVanillaFluidSimulator::CalculateFlowCost(cChunk * a_Chunk, int a_RelX, int
{
return Cost;
}
if (!IsPassableForFluid(BlockType) && !IsBlockLiquid(BlockType))
if (
!IsPassableForFluid(BlockType) || // The block cannot be passed by the liquid ...
(IsAllowedBlock(BlockType) && (BlockMeta == 0)) // ... or if it is liquid, it is a source block
)
{
return Cost;
}

View File

@ -30,7 +30,7 @@ public:
protected:
// cFloodyFluidSimulator overrides:
virtual void Spread(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta) override;
virtual void SpreadXZ(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);

View File

@ -40,7 +40,6 @@ public:
Vector3(const Vector3<_T> * a_Rhs) : x(a_Rhs->x), y(a_Rhs->y), z(a_Rhs->z) {}
// tolua_begin
inline void Set(T a_x, T a_y, T a_z)
{
x = a_x;
@ -105,23 +104,18 @@ public:
inline bool Equals(const Vector3<T> & a_Rhs) const
{
return x == a_Rhs.x && y == a_Rhs.y && z == a_Rhs.z;
// Perform a bitwise comparison of the contents - we want to know whether this object is exactly equal
// To perform EPS-based comparison, use the EqualsEps() function
return (
(memcmp(&x, &a_Rhs.x, sizeof(x)) == 0) &&
(memcmp(&y, &a_Rhs.y, sizeof(y)) == 0) &&
(memcmp(&z, &a_Rhs.z, sizeof(z)) == 0)
);
}
inline bool operator == (const Vector3<T> & a_Rhs) const
inline bool EqualsEps(const Vector3<T> & a_Rhs, T a_Eps) const
{
return Equals(a_Rhs);
}
inline bool operator != (const Vector3<T> & a_Rhs) const
{
return !Equals(a_Rhs);
}
inline bool operator < (const Vector3<T> & a_Rhs)
{
// return (x < a_Rhs.x) && (y < a_Rhs.y) && (z < a_Rhs.z); ?
return (x < a_Rhs.x) || (x == a_Rhs.x && y < a_Rhs.y) || (x == a_Rhs.x && y == a_Rhs.y && z < a_Rhs.z);
return (Abs(x - a_Rhs.x) < a_Eps) && (Abs(y - a_Rhs.y) < a_Eps) && (Abs(z - a_Rhs.z) < a_Eps);
}
inline void Move(T a_X, T a_Y, T a_Z)
@ -140,6 +134,16 @@ public:
// tolua_end
inline bool operator != (const Vector3<T> & a_Rhs) const
{
return !Equals(a_Rhs);
}
inline bool operator == (const Vector3<T> & a_Rhs) const
{
return Equals(a_Rhs);
}
inline void operator += (const Vector3<T> & a_Rhs)
{
x += a_Rhs.x;
@ -168,8 +172,16 @@ public:
z *= a_v;
}
// tolua_begin
inline Vector3<T> & operator = (const Vector3<T> & a_Rhs)
{
x = a_Rhs.x;
y = a_Rhs.y;
z = a_Rhs.z;
return *this;
}
// tolua_begin
inline Vector3<T> operator + (const Vector3<T>& a_Rhs) const
{
return Vector3<T>(
@ -222,7 +234,7 @@ public:
*/
inline double LineCoeffToXYPlane(const Vector3<T> & a_OtherEnd, T a_Z) const
{
if (abs(z - a_OtherEnd.z) < EPS)
if (Abs(z - a_OtherEnd.z) < EPS)
{
return NO_INTERSECTION;
}
@ -237,7 +249,7 @@ public:
*/
inline double LineCoeffToXZPlane(const Vector3<T> & a_OtherEnd, T a_Y) const
{
if (abs(y - a_OtherEnd.y) < EPS)
if (Abs(y - a_OtherEnd.y) < EPS)
{
return NO_INTERSECTION;
}
@ -252,7 +264,7 @@ public:
*/
inline double LineCoeffToYZPlane(const Vector3<T> & a_OtherEnd, T a_X) const
{
if (abs(x - a_OtherEnd.x) < EPS)
if (Abs(x - a_OtherEnd.x) < EPS)
{
return NO_INTERSECTION;
}
@ -265,7 +277,15 @@ public:
/** Return value of LineCoeffToPlane() if the line is parallel to the plane. */
static const double NO_INTERSECTION;
protected:
/** Returns the absolute value of the given argument.
Templatized because the standard library differentiates between abs() and fabs(). */
static T Abs(T a_Value)
{
return (a_Value < 0) ? -a_Value : a_Value;
}
};
// tolua_end

View File

@ -351,7 +351,7 @@ public:
/** Is the trapdoor open? Returns false if there is no trapdoor at the specified coords. */
bool IsTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export
/** Set the state of a trapdoor. Returns true if the trapdoor was update, false if there was no trapdoor at those coords. */
/** Set the state of a trapdoor. Returns true if the trapdoor was updated, false if there was no trapdoor at those coords. */
bool SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open); // tolua_export
/** Regenerate the given chunk: */