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). 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: Install git, cmake and gcc or clang, using your platform's package manager:
``` ```
@ -61,6 +84,14 @@ git submodule init
git submodule update 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 ###
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. 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 mkdir Release
cd 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`. The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer`.
### Debug Mode ### ### Debug Mode ###
@ -81,8 +114,10 @@ Assuming you are in the MCServer folder created in the Getting the sources step,
``` ```
mkdir Debug mkdir Debug
cd 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`. The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer_debug`.
### 32 Bit Mode switch ### ### 32 Bit Mode switch ###

View File

@ -221,7 +221,7 @@ typedef unsigned char Byte;
#if (defined(_MSC_VER) && (_MSC_VER < 1600)) #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 // 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 #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 // C++11 has std::shared_ptr in <memory>, included earlier
#define SharedPtr std::shared_ptr #define SharedPtr std::shared_ptr
#else #else

View File

@ -68,7 +68,6 @@ public:
{ {
return 0; return 0;
} }
for (int newY = Y + 1; newY < cChunkDef::Height; newY++) for (int newY = Y + 1; newY < cChunkDef::Height; newY++)
{ {
@ -84,7 +83,7 @@ public:
// This is because the frame is a solid obsidian pillar // This is because the frame is a solid obsidian pillar
if ((MaxY != 0) && (newY == Y + 1)) 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 else
{ {
@ -99,18 +98,18 @@ public:
} }
/// Evaluates if coords have a valid border on top, based on MaxY /// 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 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) if (a_ChunkInterface.GetBlock(X, checkBorder, Z) != E_BLOCK_OBSIDIAN)
{ {
// Base obsidian, base + 1 obsidian, base + x NOT obsidian -> not complete portal // Base obsidian, base + 1 obsidian, base + x NOT obsidian -> not complete portal
return 0; return false;
} }
} }
// Everything was obsidian, found a border! // 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) /// 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 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) 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); int Value = FindObsidianCeiling(X2, Y, Z, a_ChunkInterface, MaxY);
@ -199,13 +198,13 @@ public:
if ((Value == -1) || (ValueTwo == -1)) if ((Value == -1) || (ValueTwo == -1))
{ {
FoundFrameZP = true; FoundFrameZP = true;
continue; break;
} }
else if ((Value != MaxY) && (ValueTwo != MaxY)) else if ((Value != MaxY) && (ValueTwo != MaxY))
{ {
return false; 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--) 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); int Value = FindObsidianCeiling(X, Y, Z2, a_ChunkInterface, MaxY);
@ -213,13 +212,13 @@ public:
if ((Value == -1) || (ValueTwo == -1)) if ((Value == -1) || (ValueTwo == -1))
{ {
FoundFrameZM = true; FoundFrameZM = true;
continue; break;
} }
else if ((Value != MaxY) && (ValueTwo != MaxY)) else if ((Value != MaxY) && (ValueTwo != MaxY))
{ {
return false; return false;
} }
} XZM = Z2 + 2; } XZM = Z2 + 1;
return (FoundFrameZP && FoundFrameZM); return (FoundFrameZP && FoundFrameZM);
} }
}; };

View File

@ -380,12 +380,12 @@ void cChunk::SetLight(
{ // Compress blocklight { // Compress blocklight
m_BlockLight.clear(); 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 { // Compress skylight
m_BlockSkyLight.clear(); 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; m_IsLightValid = true;
@ -749,7 +749,7 @@ void cChunk::ProcessQueuedSetBlocks(void)
{ {
if (itr->m_Tick <= CurrTick) 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) 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) 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. // 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; 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_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 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_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta) { SetMeta(MakeIndex(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); } 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 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); } 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; cWorld * m_World;
cChunkMap * m_ChunkMap; cChunkMap * m_ChunkMap;
// TODO: Make these pointers and don't allocate what isn't needed
COMPRESSED_BLOCKTYPE m_BlockTypes; COMPRESSED_BLOCKTYPE m_BlockTypes;
COMPRESSED_NIBBLETYPE m_BlockMeta; COMPRESSED_NIBBLETYPE m_BlockMeta;
COMPRESSED_NIBBLETYPE m_BlockLight; 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()) if ((Chunk != NULL) && Chunk->IsValid())
{ {
Chunk->SetMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta); 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) switch (a_ChatPrefix)
{ {
case mtCustom: return AString(); case mtCustom: return "";
case mtFailure: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Rose, cChatColor::White); case mtFailure: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Rose, cChatColor::White);
case mtInformation: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Yellow, cChatColor::White); case mtInformation: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Yellow, cChatColor::White);
case mtSuccess: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Green, 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!"); 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); WorldAges::iterator itr = m_WorldAges.find(a_WorldName);
if (itr == m_WorldAges.end()) if (itr == m_WorldAges.end())
{ {
ASSERT(!"Unknown world in cDeadlockDetect"); SetWorldAge(a_WorldName, a_Age);
return; return;
} }

View File

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

View File

@ -108,14 +108,13 @@ void cAggressiveMonster::Attack(float a_Dt)
bool cAggressiveMonster::IsMovingToTargetPosition() bool cAggressiveMonster::IsMovingToTargetPosition()
{ {
static const float epsilon = 0.000000000001f;
// Difference between destination x and target x is negligible (to 10^-12 precision) // 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; return false;
} }
// Difference between destination z and target z is negligible (to 10^-12 precision) // 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; return false;
} }

View File

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

View File

@ -214,7 +214,7 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
ReplaceString(ActualAddress, "%SERVERID%", a_ServerId); ReplaceString(ActualAddress, "%SERVERID%", a_ServerId);
AString Request; 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 += "Host: " + m_Server + "\r\n";
Request += "User-Agent: MCServer\r\n"; Request += "User-Agent: MCServer\r\n";
Request += "Connection: close\r\n"; Request += "Connection: close\r\n";

View File

@ -238,7 +238,7 @@ protected:
bool m_IsEncrypted; bool m_IsEncrypted;
cAesCfb128Decryptor m_Decryptor; cAesCfb128Decryptor m_Decryptor;
cAesCfb128Decryptor m_Encryptor; cAesCfb128Encryptor m_Encryptor;
/** The logfile where the comm is logged, when g_ShouldLogComm is true */ /** The logfile where the comm is logged, when g_ShouldLogComm is true */
cFile m_CommLogFile; 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)) if (SpreadFurther && (NewMeta < 8))
{ {
// Spread to the neighbors: // 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: // 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);
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); 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. /** 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); bool HardenBlock(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta);
/** Spread water to neighbors. /** 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.
* May be overridden to provide more sophisticated algorithms. 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);
virtual void Spread(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) 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 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 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_DelayTicks; // For how many ticks should the repeater delay
unsigned char a_ElapsedTicks; // How much of the previous has been elapsed? unsigned char a_ElapsedTicks; // How much of the previous has been elapsed?
bool ShouldPowerOn; // What happens when the delay time is fulfilled? bool ShouldPowerOn; // What happens when the delay time is fulfilled?
@ -91,80 +91,80 @@ private:
/* ====== SOURCES ====== */ /* ====== SOURCES ====== */
/** Handles the redstone torch */ /** 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 */ /** 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 */ /** 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 */ /** 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 */ /** 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 */ /** 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 ====== */ /* ====== CARRIERS ====== */
/** Handles redstone wire */ /** 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 */ /** 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 ====== */ /* ====== DEVICES ====== */
/** Handles pistons */ /** 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 */ /** 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) */ /** 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 */ /** 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 */ /** 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 */ /** 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 */ /** 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 */ /** 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 */ /** 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 */ /** 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 ====== */ /* ====== Helper functions ====== */
/** Marks a block as powered */ /** 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 */ /** 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 */ /** 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 */ /** 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 */ /** 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 */ /** 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 */ /** 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 */ /** 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 */ /** 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) */ /** 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 */ /** 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 */ /** 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 */ /** 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 /** 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 */ 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 */ /** 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]; int Cost[4];
Cost[0] = CalculateFlowCost(a_Chunk, a_RelX + 1, a_RelY, a_RelZ, X_PLUS); 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[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[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); Cost[3] = CalculateFlowCost(a_Chunk, a_RelX, a_RelY, a_RelZ - 1, Z_MINUS);
// Find the minimum distance:
int MinCost = InfiniteCost; int MinCost = InfiniteCost;
for (unsigned int i = 0; i < ARRAYCOUNT(Cost); ++i) 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) if (Cost[0] == MinCost)
{ {
SpreadToNeighbor(a_Chunk, a_RelX + 1, a_RelY, a_RelZ, a_NewMeta); 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; 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; return Cost;
} }

View File

@ -30,7 +30,7 @@ public:
protected: protected:
// cFloodyFluidSimulator overrides: // 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. */ /** 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); 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) {} Vector3(const Vector3<_T> * a_Rhs) : x(a_Rhs->x), y(a_Rhs->y), z(a_Rhs->z) {}
// tolua_begin // tolua_begin
inline void Set(T a_x, T a_y, T a_z) inline void Set(T a_x, T a_y, T a_z)
{ {
x = a_x; x = a_x;
@ -105,23 +104,18 @@ public:
inline bool Equals(const Vector3<T> & a_Rhs) const 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); return (Abs(x - a_Rhs.x) < a_Eps) && (Abs(y - a_Rhs.y) < a_Eps) && (Abs(z - a_Rhs.z) < a_Eps);
}
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);
} }
inline void Move(T a_X, T a_Y, T a_Z) inline void Move(T a_X, T a_Y, T a_Z)
@ -140,6 +134,16 @@ public:
// tolua_end // 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) inline void operator += (const Vector3<T> & a_Rhs)
{ {
x += a_Rhs.x; x += a_Rhs.x;
@ -168,8 +172,16 @@ public:
z *= a_v; 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 inline Vector3<T> operator + (const Vector3<T>& a_Rhs) const
{ {
return Vector3<T>( return Vector3<T>(
@ -222,7 +234,7 @@ public:
*/ */
inline double LineCoeffToXYPlane(const Vector3<T> & a_OtherEnd, T a_Z) const 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; return NO_INTERSECTION;
} }
@ -237,7 +249,7 @@ public:
*/ */
inline double LineCoeffToXZPlane(const Vector3<T> & a_OtherEnd, T a_Y) const 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; return NO_INTERSECTION;
} }
@ -252,7 +264,7 @@ public:
*/ */
inline double LineCoeffToYZPlane(const Vector3<T> & a_OtherEnd, T a_X) const 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; return NO_INTERSECTION;
} }
@ -265,7 +277,15 @@ public:
/** Return value of LineCoeffToPlane() if the line is parallel to the plane. */ /** Return value of LineCoeffToPlane() if the line is parallel to the plane. */
static const double NO_INTERSECTION; 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 // tolua_end

View File

@ -351,7 +351,7 @@ public:
/** Is the trapdoor open? Returns false if there is no trapdoor at the specified coords. */ /** 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 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 bool SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open); // tolua_export
/** Regenerate the given chunk: */ /** Regenerate the given chunk: */