1
0

Merge branch 'master' into chunksparsing/structs

Conflicts:
	src/Chunk.cpp
This commit is contained in:
Tycho 2014-05-03 06:07:56 -07:00
commit ec407dd27d
36 changed files with 198 additions and 92 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

@ -2,23 +2,33 @@ return
{ {
HOOK_DISCONNECT = HOOK_DISCONNECT =
{ {
CalledWhen = "A player has explicitly disconnected.", CalledWhen = [[
A client has disconnected, either by explicitly sending the disconnect packet (in older protocols) or
their connection was terminated
]],
DefaultFnName = "OnDisconnect", -- also used as pagename DefaultFnName = "OnDisconnect", -- also used as pagename
Desc = [[ Desc = [[
This hook is called when a client is about to be disconnected from the server, for whatever reason. This hook is called when a client has disconnected from the server, for whatever reason. It is also
called when the client sends the Disconnect packet (only in pre-1.7 protocols). This hook is not called
<p><b>Note that this hook will be removed after <1.7 protocol support is removed, as it was originally a hook for for server ping connections.</p>
the client sending the server a disconnect packet, which no longer happens.</b></p> <p>
Note that the hook is called even for connections to players who failed to auth. In such a case there's
no {{cPlayer}} object associated with the client.</p>
<p>
See also the {{OnHandshake|HOOK_HANDSHAKE}} hook which is called when the client connects (and presents
a handshake message, so that they are not just status-pinging). If you need to store a per-player
object, use the {{OnPlayerJoined|HOOK_PLAYER_JOINED}} and {{OnPlayerDestroyed|HOOK_PLAYER_DESTROYED}}
hooks instead, those are guaranteed to have the {{cPlayer}} object associated.
]], ]],
Params = Params =
{ {
{ Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has disconnected" }, { Name = "Client", Type = "{{cClientHandle}}", Notes = "The client who has disconnected" },
{ Name = "Reason", Type = "string", Notes = "The reason that the client has sent in the disconnect packet" }, { Name = "Reason", Type = "string", Notes = "The reason that the client has sent in the disconnect packet" },
}, },
Returns = [[ Returns = [[
If the function returns false or no value, MCServer calls other plugins' callbacks for this event. If the function returns false or no value, MCServer calls other plugins' callbacks for this event.
If the function returns true, no other plugins are called for this event. In either case, If the function returns true, no other plugins are called for this event. In either case,
the player is disconnected. the client is disconnected.
]], ]],
}, -- HOOK_DISCONNECT }, -- HOOK_DISCONNECT
} }

View File

@ -27,10 +27,14 @@ local function LoadAPIFiles(a_Folder, a_DstTable)
-- We only want .lua files from the folder: -- We only want .lua files from the folder:
if (cFile:IsFile(FileName) and fnam:match(".*%.lua$")) then if (cFile:IsFile(FileName) and fnam:match(".*%.lua$")) then
local TablesFn, Err = loadfile(FileName); local TablesFn, Err = loadfile(FileName);
if (TablesFn == nil) then if (type(TablesFn) ~= "function") then
LOGWARNING("Cannot load API descriptions from " .. FileName .. ", Lua error '" .. Err .. "'."); LOGWARNING("Cannot load API descriptions from " .. FileName .. ", Lua error '" .. Err .. "'.");
else else
local Tables = TablesFn(); local Tables = TablesFn();
if (type(Tables) ~= "table") then
LOGWARNING("Cannot load API descriptions from " .. FileName .. ", returned object is not a table (" .. type(Tables) .. ").");
break
end
for k, cls in pairs(Tables) do for k, cls in pairs(Tables) do
a_DstTable[k] = cls; a_DstTable[k] = cls;
end end

View File

@ -42,7 +42,7 @@ bool cLuaChunkStay::AddChunks(int a_ChunkCoordTableStackPos)
// Add each set of coords: // Add each set of coords:
int NumChunks = luaL_getn(L, a_ChunkCoordTableStackPos); int NumChunks = luaL_getn(L, a_ChunkCoordTableStackPos);
m_Chunks.reserve(NumChunks); m_Chunks.reserve((size_t)NumChunks);
for (int idx = 1; idx <= NumChunks; idx++) for (int idx = 1; idx <= NumChunks; idx++)
{ {
// Push the idx-th element of the array onto stack top, check that it's a table: // Push the idx-th element of the array onto stack top, check that it's a table:

View File

@ -4,12 +4,12 @@
#include <time.h> #include <time.h>
// tolua_begin // tolua_begin
unsigned int GetTime() inline unsigned int GetTime()
{ {
return (unsigned int)time(0); return (unsigned int)time(0);
} }
std::string GetChar( std::string & a_Str, unsigned int a_Idx ) inline std::string GetChar( std::string & a_Str, unsigned int a_Idx )
{ {
return std::string(1, a_Str[ a_Idx ]); return std::string(1, a_Str[ a_Idx ]);
} }

View File

@ -37,7 +37,7 @@
/**************************** /****************************
* Better error reporting for Lua * Better error reporting for Lua
**/ **/
int tolua_do_error(lua_State* L, const char * a_pMsg, tolua_Error * a_pToLuaError) static int tolua_do_error(lua_State* L, const char * a_pMsg, tolua_Error * a_pToLuaError)
{ {
// Retrieve current function name // Retrieve current function name
lua_Debug entry; lua_Debug entry;
@ -57,7 +57,7 @@ int tolua_do_error(lua_State* L, const char * a_pMsg, tolua_Error * a_pToLuaErro
int lua_do_error(lua_State* L, const char * a_pFormat, ...) static int lua_do_error(lua_State* L, const char * a_pFormat, ...)
{ {
// Retrieve current function name // Retrieve current function name
lua_Debug entry; lua_Debug entry;
@ -235,7 +235,7 @@ static int tolua_Base64Decode(lua_State * tolua_S)
cPluginLua * GetLuaPlugin(lua_State * L) static cPluginLua * GetLuaPlugin(lua_State * L)
{ {
// Get the plugin identification out of LuaState: // Get the plugin identification out of LuaState:
lua_getglobal(L, LUA_PLUGIN_INSTANCE_VAR_NAME); lua_getglobal(L, LUA_PLUGIN_INSTANCE_VAR_NAME);
@ -1776,20 +1776,20 @@ static int tolua_cWorld_ChunkStay(lua_State * tolua_S)
static int tolua_cPlayer_GetGroups(lua_State* tolua_S) static int tolua_cPlayer_GetGroups(lua_State * tolua_S)
{ {
cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S, 1, NULL); cPlayer * self = (cPlayer *)tolua_tousertype(tolua_S, 1, NULL);
const cPlayer::GroupList & AllGroups = self->GetGroups(); const cPlayer::GroupList & AllGroups = self->GetGroups();
lua_createtable(tolua_S, AllGroups.size(), 0); lua_createtable(tolua_S, (int)AllGroups.size(), 0);
int newTable = lua_gettop(tolua_S); int newTable = lua_gettop(tolua_S);
int index = 1; int index = 1;
cPlayer::GroupList::const_iterator iter = AllGroups.begin(); cPlayer::GroupList::const_iterator iter = AllGroups.begin();
while(iter != AllGroups.end()) while (iter != AllGroups.end())
{ {
const cGroup* Group = *iter; const cGroup * Group = *iter;
tolua_pushusertype( tolua_S, (void*)Group, "const cGroup" ); tolua_pushusertype(tolua_S, (void *)Group, "const cGroup");
lua_rawseti(tolua_S, newTable, index); lua_rawseti(tolua_S, newTable, index);
++iter; ++iter;
++index; ++index;
@ -1801,20 +1801,20 @@ static int tolua_cPlayer_GetGroups(lua_State* tolua_S)
static int tolua_cPlayer_GetResolvedPermissions(lua_State* tolua_S) static int tolua_cPlayer_GetResolvedPermissions(lua_State * tolua_S)
{ {
cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S, 1, NULL); cPlayer * self = (cPlayer*) tolua_tousertype(tolua_S, 1, NULL);
cPlayer::StringList AllPermissions = self->GetResolvedPermissions(); cPlayer::StringList AllPermissions = self->GetResolvedPermissions();
lua_createtable(tolua_S, AllPermissions.size(), 0); lua_createtable(tolua_S, (int)AllPermissions.size(), 0);
int newTable = lua_gettop(tolua_S); int newTable = lua_gettop(tolua_S);
int index = 1; int index = 1;
cPlayer::StringList::iterator iter = AllPermissions.begin(); cPlayer::StringList::iterator iter = AllPermissions.begin();
while(iter != AllPermissions.end()) while (iter != AllPermissions.end())
{ {
std::string& Permission = *iter; std::string & Permission = *iter;
tolua_pushstring( tolua_S, Permission.c_str() ); lua_pushlstring(tolua_S, Permission.c_str(), Permission.length());
lua_rawseti(tolua_S, newTable, index); lua_rawseti(tolua_S, newTable, index);
++iter; ++iter;
++index; ++index;
@ -2076,18 +2076,18 @@ static int tolua_get_HTTPRequest_FormData(lua_State* tolua_S)
static int tolua_cWebAdmin_GetPlugins(lua_State * tolua_S) static int tolua_cWebAdmin_GetPlugins(lua_State * tolua_S)
{ {
cWebAdmin* self = (cWebAdmin*) tolua_tousertype(tolua_S, 1, NULL); cWebAdmin * self = (cWebAdmin *)tolua_tousertype(tolua_S, 1, NULL);
const cWebAdmin::PluginList & AllPlugins = self->GetPlugins(); const cWebAdmin::PluginList & AllPlugins = self->GetPlugins();
lua_createtable(tolua_S, AllPlugins.size(), 0); lua_createtable(tolua_S, (int)AllPlugins.size(), 0);
int newTable = lua_gettop(tolua_S); int newTable = lua_gettop(tolua_S);
int index = 1; int index = 1;
cWebAdmin::PluginList::const_iterator iter = AllPlugins.begin(); cWebAdmin::PluginList::const_iterator iter = AllPlugins.begin();
while(iter != AllPlugins.end()) while (iter != AllPlugins.end())
{ {
const cWebPlugin* Plugin = *iter; const cWebPlugin * Plugin = *iter;
tolua_pushusertype( tolua_S, (void*)Plugin, "const cWebPlugin" ); tolua_pushusertype(tolua_S, (void *)Plugin, "const cWebPlugin");
lua_rawseti(tolua_S, newTable, index); lua_rawseti(tolua_S, newTable, index);
++iter; ++iter;
++index; ++index;

View File

@ -56,7 +56,7 @@ public:
virtual bool OnChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ) = 0; virtual bool OnChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ) = 0;
virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup) = 0; virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup) = 0;
virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) = 0; virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) = 0;
virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason) = 0; virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) = 0;
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) = 0; virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) = 0;
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0; virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;
virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0; virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;

View File

@ -400,14 +400,14 @@ bool cPluginLua::OnCraftingNoRecipe(const cPlayer * a_Player, const cCraftingGri
bool cPluginLua::OnDisconnect(cPlayer * a_Player, const AString & a_Reason) bool cPluginLua::OnDisconnect(cClientHandle & a_Client, const AString & a_Reason)
{ {
cCSLock Lock(m_CriticalSection); cCSLock Lock(m_CriticalSection);
bool res = false; bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_DISCONNECT]; cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_DISCONNECT];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr) for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{ {
m_LuaState.Call((int)(**itr), a_Player, a_Reason, cLuaState::Return, res); m_LuaState.Call((int)(**itr), &a_Client, a_Reason, cLuaState::Return, res);
if (res) if (res)
{ {
return true; return true;

View File

@ -79,7 +79,7 @@ public:
virtual bool OnChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ) override; virtual bool OnChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ) override;
virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup) override; virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup) override;
virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override; virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason) override; virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) override;
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) override; virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) override;
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override; virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;
virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override; virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;

View File

@ -442,7 +442,7 @@ bool cPluginManager::CallHookCraftingNoRecipe(const cPlayer * a_Player, const cC
bool cPluginManager::CallHookDisconnect(cPlayer * a_Player, const AString & a_Reason) bool cPluginManager::CallHookDisconnect(cClientHandle & a_Client, const AString & a_Reason)
{ {
HookMap::iterator Plugins = m_Hooks.find(HOOK_DISCONNECT); HookMap::iterator Plugins = m_Hooks.find(HOOK_DISCONNECT);
if (Plugins == m_Hooks.end()) if (Plugins == m_Hooks.end())
@ -451,7 +451,7 @@ bool cPluginManager::CallHookDisconnect(cPlayer * a_Player, const AString & a_Re
} }
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr) for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{ {
if ((*itr)->OnDisconnect(a_Player, a_Reason)) if ((*itr)->OnDisconnect(a_Client, a_Reason))
{ {
return true; return true;
} }

View File

@ -172,7 +172,7 @@ public: // tolua_export
bool CallHookChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ); bool CallHookChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ);
bool CallHookCollectingPickup (cPlayer * a_Player, cPickup & a_Pickup); bool CallHookCollectingPickup (cPlayer * a_Player, cPickup & a_Pickup);
bool CallHookCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); bool CallHookCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookDisconnect (cPlayer * a_Player, const AString & a_Reason); bool CallHookDisconnect (cClientHandle & a_Client, const AString & a_Reason);
bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split); // If a_Player == NULL, it is a console cmd bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split); // If a_Player == NULL, it is a console cmd
bool CallHookExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData); bool CallHookExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);
bool CallHookExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData); bool CallHookExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);

View File

@ -1977,7 +1977,7 @@ void cBlockArea::ExpandBlockTypes(int a_SubMinX, int a_AddMaxX, int a_SubMinY, i
int NewSizeX = m_Size.x + a_SubMinX + a_AddMaxX; int NewSizeX = m_Size.x + a_SubMinX + a_AddMaxX;
int NewSizeY = m_Size.y + a_SubMinY + a_AddMaxY; int NewSizeY = m_Size.y + a_SubMinY + a_AddMaxY;
int NewSizeZ = m_Size.z + a_SubMinZ + a_AddMaxZ; int NewSizeZ = m_Size.z + a_SubMinZ + a_AddMaxZ;
size_t BlockCount = (size_t)NewSizeX * NewSizeY * NewSizeZ; size_t BlockCount = (size_t)(NewSizeX * NewSizeY * NewSizeZ);
BLOCKTYPE * NewBlockTypes = new BLOCKTYPE[BlockCount]; BLOCKTYPE * NewBlockTypes = new BLOCKTYPE[BlockCount];
memset(NewBlockTypes, 0, BlockCount * sizeof(BLOCKTYPE)); memset(NewBlockTypes, 0, BlockCount * sizeof(BLOCKTYPE));
int OldIndex = 0; int OldIndex = 0;
@ -2007,7 +2007,7 @@ void cBlockArea::ExpandNibbles(NIBBLEARRAY & a_Array, int a_SubMinX, int a_AddMa
int NewSizeX = m_Size.x + a_SubMinX + a_AddMaxX; int NewSizeX = m_Size.x + a_SubMinX + a_AddMaxX;
int NewSizeY = m_Size.y + a_SubMinY + a_AddMaxY; int NewSizeY = m_Size.y + a_SubMinY + a_AddMaxY;
int NewSizeZ = m_Size.z + a_SubMinZ + a_AddMaxZ; int NewSizeZ = m_Size.z + a_SubMinZ + a_AddMaxZ;
size_t BlockCount = (size_t)NewSizeX * NewSizeY * NewSizeZ; size_t BlockCount = (size_t)(NewSizeX * NewSizeY * NewSizeZ);
NIBBLETYPE * NewNibbles = new NIBBLETYPE[BlockCount]; NIBBLETYPE * NewNibbles = new NIBBLETYPE[BlockCount];
memset(NewNibbles, 0, BlockCount * sizeof(NIBBLETYPE)); memset(NewNibbles, 0, BlockCount * sizeof(NIBBLETYPE));
int OldIndex = 0; int OldIndex = 0;

View File

@ -294,7 +294,7 @@ public:
NIBBLETYPE * GetBlockMetas (void) const { return m_BlockMetas; } // NOTE: one byte per block! NIBBLETYPE * GetBlockMetas (void) const { return m_BlockMetas; } // NOTE: one byte per block!
NIBBLETYPE * GetBlockLight (void) const { return m_BlockLight; } // NOTE: one byte per block! NIBBLETYPE * GetBlockLight (void) const { return m_BlockLight; } // NOTE: one byte per block!
NIBBLETYPE * GetBlockSkyLight(void) const { return m_BlockSkyLight; } // NOTE: one byte per block! NIBBLETYPE * GetBlockSkyLight(void) const { return m_BlockSkyLight; } // NOTE: one byte per block!
size_t GetBlockCount(void) const { return m_Size.x * m_Size.y * m_Size.z; } size_t GetBlockCount(void) const { return (size_t)(m_Size.x * m_Size.y * m_Size.z); }
int MakeIndex(int a_RelX, int a_RelY, int a_RelZ) const; int MakeIndex(int a_RelX, int a_RelY, int a_RelZ) const;
protected: protected:

View File

@ -102,7 +102,7 @@ public:
return true; return true;
} }
a_Item.m_ItemDamage = atoi(Split[1].c_str()); a_Item.m_ItemDamage = (short)atoi(Split[1].c_str());
if ((a_Item.m_ItemDamage == 0) && (Split[1] != "0")) if ((a_Item.m_ItemDamage == 0) && (Split[1] != "0"))
{ {
// Parsing the number failed // Parsing the number failed

View File

@ -327,7 +327,7 @@ bool cByteBuffer::ReadBEShort(short & a_Value)
CheckValid(); CheckValid();
NEEDBYTES(2); NEEDBYTES(2);
ReadBuf(&a_Value, 2); ReadBuf(&a_Value, 2);
a_Value = ntohs(a_Value); a_Value = (short)ntohs((u_short)a_Value);
return true; return true;
} }
@ -341,7 +341,7 @@ bool cByteBuffer::ReadBEInt(int & a_Value)
CheckValid(); CheckValid();
NEEDBYTES(4); NEEDBYTES(4);
ReadBuf(&a_Value, 4); ReadBuf(&a_Value, 4);
a_Value = ntohl(a_Value); a_Value = (int)ntohl((u_long)a_Value);
return true; return true;
} }
@ -420,7 +420,7 @@ bool cByteBuffer::ReadBEUTF16String16(AString & a_Value)
ASSERT(!"Negative string length? Are you sure?"); ASSERT(!"Negative string length? Are you sure?");
return true; return true;
} }
return ReadUTF16String(a_Value, Length); return ReadUTF16String(a_Value, (size_t)Length);
} }
@ -438,7 +438,7 @@ bool cByteBuffer::ReadVarInt(UInt32 & a_Value)
{ {
NEEDBYTES(1); NEEDBYTES(1);
ReadBuf(&b, 1); ReadBuf(&b, 1);
Value = Value | (((Int64)(b & 0x7f)) << Shift); Value = Value | (((UInt32)(b & 0x7f)) << Shift);
Shift += 7; Shift += 7;
} while ((b & 0x80) != 0); } while ((b & 0x80) != 0);
a_Value = Value; a_Value = Value;
@ -462,7 +462,7 @@ bool cByteBuffer::ReadVarUTF8String(AString & a_Value)
{ {
LOGWARNING("%s: String too large: %u (%u KiB)", __FUNCTION__, Size, Size / 1024); LOGWARNING("%s: String too large: %u (%u KiB)", __FUNCTION__, Size, Size / 1024);
} }
return ReadString(a_Value, (int)Size); return ReadString(a_Value, (size_t)Size);
} }
@ -517,7 +517,7 @@ bool cByteBuffer::WriteBEShort(short a_Value)
CHECK_THREAD; CHECK_THREAD;
CheckValid(); CheckValid();
PUTBYTES(2); PUTBYTES(2);
short Converted = htons(a_Value); u_short Converted = htons((u_short)a_Value);
return WriteBuf(&Converted, 2); return WriteBuf(&Converted, 2);
} }
@ -530,7 +530,7 @@ bool cByteBuffer::WriteBEInt(int a_Value)
CHECK_THREAD; CHECK_THREAD;
CheckValid(); CheckValid();
PUTBYTES(4); PUTBYTES(4);
int Converted = HostToNetwork4(&a_Value); UInt32 Converted = HostToNetwork4(&a_Value);
return WriteBuf(&Converted, 4); return WriteBuf(&Converted, 4);
} }
@ -543,7 +543,7 @@ bool cByteBuffer::WriteBEInt64(Int64 a_Value)
CHECK_THREAD; CHECK_THREAD;
CheckValid(); CheckValid();
PUTBYTES(8); PUTBYTES(8);
Int64 Converted = HostToNetwork8(&a_Value); UInt64 Converted = HostToNetwork8(&a_Value);
return WriteBuf(&Converted, 8); return WriteBuf(&Converted, 8);
} }
@ -556,7 +556,7 @@ bool cByteBuffer::WriteBEFloat(float a_Value)
CHECK_THREAD; CHECK_THREAD;
CheckValid(); CheckValid();
PUTBYTES(4); PUTBYTES(4);
int Converted = HostToNetwork4(&a_Value); UInt32 Converted = HostToNetwork4(&a_Value);
return WriteBuf(&Converted, 4); return WriteBuf(&Converted, 4);
} }
@ -569,7 +569,7 @@ bool cByteBuffer::WriteBEDouble(double a_Value)
CHECK_THREAD; CHECK_THREAD;
CheckValid(); CheckValid();
PUTBYTES(8); PUTBYTES(8);
Int64 Converted = HostToNetwork8(&a_Value); UInt64 Converted = HostToNetwork8(&a_Value);
return WriteBuf(&Converted, 8); return WriteBuf(&Converted, 8);
} }
@ -613,7 +613,7 @@ bool cByteBuffer::WriteVarInt(UInt32 a_Value)
// A 32-bit integer can be encoded by at most 5 bytes: // A 32-bit integer can be encoded by at most 5 bytes:
unsigned char b[5]; unsigned char b[5];
int idx = 0; size_t idx = 0;
do do
{ {
b[idx] = (a_Value & 0x7f) | ((a_Value > 0x7f) ? 0x80 : 0x00); b[idx] = (a_Value & 0x7f) | ((a_Value > 0x7f) ? 0x80 : 0x00);
@ -632,7 +632,7 @@ bool cByteBuffer::WriteVarUTF8String(const AString & a_Value)
CHECK_THREAD; CHECK_THREAD;
CheckValid(); CheckValid();
PUTBYTES(a_Value.size() + 1); // This is a lower-bound on the bytes that will be actually written. Fail early. PUTBYTES(a_Value.size() + 1); // This is a lower-bound on the bytes that will be actually written. Fail early.
bool res = WriteVarInt(a_Value.size()); bool res = WriteVarInt((UInt32)(a_Value.size()));
if (!res) if (!res)
{ {
return false; return false;
@ -757,7 +757,7 @@ bool cByteBuffer::ReadString(AString & a_String, size_t a_Count)
bool cByteBuffer::ReadUTF16String(AString & a_String, int a_NumChars) bool cByteBuffer::ReadUTF16String(AString & a_String, size_t a_NumChars)
{ {
// Reads 2 * a_NumChars bytes and interprets it as a UTF16 string, converting it into UTF8 string a_String // Reads 2 * a_NumChars bytes and interprets it as a UTF16 string, converting it into UTF8 string a_String
CHECK_THREAD; CHECK_THREAD;

View File

@ -101,7 +101,7 @@ public:
bool ReadString(AString & a_String, size_t a_Count); bool ReadString(AString & a_String, size_t a_Count);
/// Reads 2 * a_NumChars bytes and interprets it as a UTF16-BE string, converting it into UTF8 string a_String /// Reads 2 * a_NumChars bytes and interprets it as a UTF16-BE string, converting it into UTF8 string a_String
bool ReadUTF16String(AString & a_String, int a_NumChars); bool ReadUTF16String(AString & a_String, size_t a_NumChars);
/// Skips reading by a_Count bytes; returns false if not enough bytes in the ringbuffer /// Skips reading by a_Count bytes; returns false if not enough bytes in the ringbuffer
bool SkipRead(size_t a_Count); bool SkipRead(size_t a_Count);

View File

@ -716,7 +716,7 @@ void cClientHandle::UnregisterPluginChannels(const AStringVector & a_ChannelList
void cClientHandle::HandleCommandBlockMessage(const char * a_Data, unsigned int a_Length) void cClientHandle::HandleCommandBlockMessage(const char * a_Data, size_t a_Length)
{ {
if (a_Length < 14) if (a_Length < 14)
{ {
@ -1510,7 +1510,7 @@ void cClientHandle::HandleDisconnect(const AString & a_Reason)
{ {
LOGD("Received d/c packet from %s with reason \"%s\"", m_Username.c_str(), a_Reason.c_str()); LOGD("Received d/c packet from %s with reason \"%s\"", m_Username.c_str(), a_Reason.c_str());
cRoot::Get()->GetPluginManager()->CallHookDisconnect(m_Player, a_Reason); cRoot::Get()->GetPluginManager()->CallHookDisconnect(*this, a_Reason);
m_HasSentDC = true; m_HasSentDC = true;
Destroy(); Destroy();
@ -1658,7 +1658,7 @@ void cClientHandle::SendData(const char * a_Data, size_t a_Size)
{ {
// There is a queued overflow. Append to it, then send as much from its front as possible // There is a queued overflow. Append to it, then send as much from its front as possible
m_OutgoingDataOverflow.append(a_Data, a_Size); m_OutgoingDataOverflow.append(a_Data, a_Size);
int CanFit = m_OutgoingData.GetFreeSpace(); size_t CanFit = m_OutgoingData.GetFreeSpace();
if (CanFit > 128) if (CanFit > 128)
{ {
// No point in moving the data over if it's not large enough - too much effort for too little an effect // No point in moving the data over if it's not large enough - too much effort for too little an effect
@ -2689,9 +2689,9 @@ void cClientHandle::SocketClosed(void)
LOGD("Player %s @ %s disconnected", m_Username.c_str(), m_IPString.c_str()); LOGD("Player %s @ %s disconnected", m_Username.c_str(), m_IPString.c_str());
if (m_Username != "") // Ignore client pings if (!m_Username.empty()) // Ignore client pings
{ {
cRoot::Get()->GetPluginManager()->CallHookDisconnect(m_Player, "Player disconnected"); cRoot::Get()->GetPluginManager()->CallHookDisconnect(*this, "Player disconnected");
} }
Destroy(); Destroy();

View File

@ -384,7 +384,7 @@ private:
void UnregisterPluginChannels(const AStringVector & a_ChannelList); void UnregisterPluginChannels(const AStringVector & a_ChannelList);
/** Handles the "MC|AdvCdm" plugin message */ /** Handles the "MC|AdvCdm" plugin message */
void HandleCommandBlockMessage(const char * a_Data, unsigned int a_Length); void HandleCommandBlockMessage(const char * a_Data, size_t a_Length);
// cSocketThreads::cCallback overrides: // cSocketThreads::cCallback overrides:
virtual void DataReceived (const char * a_Data, size_t a_Size) override; // Data is received from the client virtual void DataReceived (const char * a_Data, size_t a_Size) override; // Data is received from the client

View File

@ -73,6 +73,10 @@ public:
} }
// The constructor is disabled in code, because the compiler generates it anyway,
// but it needs to stay because ToLua needs to generate the binding for it
#if 0
/** Creates an exact copy of the item */ /** Creates an exact copy of the item */
cItem(const cItem & a_CopyFrom) : cItem(const cItem & a_CopyFrom) :
m_ItemType (a_CopyFrom.m_ItemType), m_ItemType (a_CopyFrom.m_ItemType),
@ -85,6 +89,8 @@ public:
{ {
} }
#endif
void Empty(void) void Empty(void)
{ {

View File

@ -33,7 +33,10 @@ public:
a_BlockY--; a_BlockY--;
} }
if (a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, (cMonster::eType)(a_Item.m_ItemDamage)) >= 0) cMonster::eType MonsterType = ItemDamageToMonsterType(a_Item.m_ItemDamage);
if (
(MonsterType != cMonster::mtInvalidType) && // Valid monster type
(a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, MonsterType) >= 0)) // Spawning succeeded
{ {
if (!a_Player->IsGameModeCreative()) if (!a_Player->IsGameModeCreative())
{ {
@ -45,6 +48,41 @@ public:
return false; return false;
} }
/** Converts the Spawn egg item damage to the monster type to spawn.
Returns mtInvalidType for invalid damage values. */
static cMonster::eType ItemDamageToMonsterType(short a_ItemDamage)
{
switch (a_ItemDamage)
{
case E_META_SPAWN_EGG_BAT: return cMonster::mtBat;
case E_META_SPAWN_EGG_BLAZE: return cMonster::mtBlaze;
case E_META_SPAWN_EGG_CAVE_SPIDER: return cMonster::mtCaveSpider;
case E_META_SPAWN_EGG_CHICKEN: return cMonster::mtChicken;
case E_META_SPAWN_EGG_COW: return cMonster::mtCow;
case E_META_SPAWN_EGG_CREEPER: return cMonster::mtCreeper;
case E_META_SPAWN_EGG_ENDERMAN: return cMonster::mtEnderman;
case E_META_SPAWN_EGG_GHAST: return cMonster::mtGhast;
case E_META_SPAWN_EGG_HORSE: return cMonster::mtHorse;
case E_META_SPAWN_EGG_MAGMA_CUBE: return cMonster::mtMagmaCube;
case E_META_SPAWN_EGG_MOOSHROOM: return cMonster::mtMooshroom;
case E_META_SPAWN_EGG_OCELOT: return cMonster::mtOcelot;
case E_META_SPAWN_EGG_PIG: return cMonster::mtPig;
case E_META_SPAWN_EGG_SHEEP: return cMonster::mtSheep;
case E_META_SPAWN_EGG_SILVERFISH: return cMonster::mtSilverfish;
case E_META_SPAWN_EGG_SKELETON: return cMonster::mtSkeleton;
case E_META_SPAWN_EGG_SLIME: return cMonster::mtSlime;
case E_META_SPAWN_EGG_SPIDER: return cMonster::mtSpider;
case E_META_SPAWN_EGG_SQUID: return cMonster::mtSquid;
case E_META_SPAWN_EGG_VILLAGER: return cMonster::mtVillager;
case E_META_SPAWN_EGG_WITCH: return cMonster::mtWitch;
case E_META_SPAWN_EGG_WOLF: return cMonster::mtWolf;
case E_META_SPAWN_EGG_ZOMBIE: return cMonster::mtZombie;
case E_META_SPAWN_EGG_ZOMBIE_PIGMAN: return cMonster::mtZombiePigman;
}
return cMonster::mtInvalidType;
}
} ; } ;

View File

@ -827,6 +827,10 @@ cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType)
switch (a_MobType) switch (a_MobType)
{ {
case mtMagmaCube: case mtMagmaCube:
{
toReturn = new cMagmaCube(Random.NextInt(2) + 1);
break;
}
case mtSlime: case mtSlime:
{ {
toReturn = new cSlime(Random.NextInt(2) + 1); toReturn = new cSlime(Random.NextInt(2) + 1);

View File

@ -280,7 +280,7 @@ NOISE_DATATYPE cNoise::CubicInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B,
NOISE_DATATYPE cNoise::CosineInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct) NOISE_DATATYPE cNoise::CosineInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct)
{ {
const NOISE_DATATYPE ft = a_Pct * (NOISE_DATATYPE)3.1415927; const NOISE_DATATYPE ft = a_Pct * (NOISE_DATATYPE)3.1415927;
const NOISE_DATATYPE f = (1 - cos(ft)) * (NOISE_DATATYPE)0.5; const NOISE_DATATYPE f = (NOISE_DATATYPE)((NOISE_DATATYPE)(1 - cos(ft)) * (NOISE_DATATYPE)0.5);
return a_A * (1 - f) + a_B * f; return a_A * (1 - f) + a_B * f;
} }

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

@ -23,6 +23,9 @@ public:
class cDataCallbacks class cDataCallbacks
{ {
public: public:
// Force a virtual destructor in descendants:
virtual ~cDataCallbacks() {}
/** Called when PolarSSL wants to read encrypted data from the SSL peer. /** Called when PolarSSL wants to read encrypted data from the SSL peer.
The returned value is the number of bytes received, or a PolarSSL error on failure. The returned value is the number of bytes received, or a PolarSSL error on failure.
The implementation can return POLARSSL_ERR_NET_WANT_READ or POLARSSL_ERR_NET_WANT_WRITE to indicate The implementation can return POLARSSL_ERR_NET_WANT_READ or POLARSSL_ERR_NET_WANT_WRITE to indicate

View File

@ -123,7 +123,7 @@ public:
virtual void SendWholeInventory (const cWindow & a_Window) = 0; virtual void SendWholeInventory (const cWindow & a_Window) = 0;
virtual void SendWindowClose (const cWindow & a_Window) = 0; virtual void SendWindowClose (const cWindow & a_Window) = 0;
virtual void SendWindowOpen (const cWindow & a_Window) = 0; virtual void SendWindowOpen (const cWindow & a_Window) = 0;
virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) = 0; virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) = 0;
/// Returns the ServerID used for authentication through session.minecraft.net /// Returns the ServerID used for authentication through session.minecraft.net
virtual AString GetAuthServerID(void) = 0; virtual AString GetAuthServerID(void) = 0;

View File

@ -1175,7 +1175,7 @@ void cProtocol125::SendWindowOpen(const cWindow & a_Window)
void cProtocol125::SendWindowProperty(const cWindow & a_Window, short a_Property, short a_Value) void cProtocol125::SendWindowProperty(const cWindow & a_Window, int a_Property, int a_Value)
{ {
cCSLock Lock(m_CSPacket); cCSLock Lock(m_CSPacket);
WriteByte (PACKET_WINDOW_PROPERTY); WriteByte (PACKET_WINDOW_PROPERTY);

View File

@ -96,7 +96,7 @@ public:
virtual void SendWholeInventory (const cWindow & a_Window) override; virtual void SendWholeInventory (const cWindow & a_Window) override;
virtual void SendWindowClose (const cWindow & a_Window) override; virtual void SendWindowClose (const cWindow & a_Window) override;
virtual void SendWindowOpen (const cWindow & a_Window) override; virtual void SendWindowOpen (const cWindow & a_Window) override;
virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) override; virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override;
virtual AString GetAuthServerID(void) override; virtual AString GetAuthServerID(void) override;

View File

@ -1383,7 +1383,7 @@ void cProtocol172::SendWindowOpen(const cWindow & a_Window)
void cProtocol172::SendWindowProperty(const cWindow & a_Window, short a_Property, short a_Value) void cProtocol172::SendWindowProperty(const cWindow & a_Window, int a_Property, int a_Value)
{ {
ASSERT(m_State == 3); // In game mode? ASSERT(m_State == 3); // In game mode?

View File

@ -128,7 +128,7 @@ public:
virtual void SendWholeInventory (const cWindow & a_Window) override; virtual void SendWholeInventory (const cWindow & a_Window) override;
virtual void SendWindowClose (const cWindow & a_Window) override; virtual void SendWindowClose (const cWindow & a_Window) override;
virtual void SendWindowOpen (const cWindow & a_Window) override; virtual void SendWindowOpen (const cWindow & a_Window) override;
virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) override; virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override;
virtual AString GetAuthServerID(void) override { return m_AuthServerID; } virtual AString GetAuthServerID(void) override { return m_AuthServerID; }

View File

@ -357,7 +357,7 @@ void cProtocolRecognizer::SendHealth(void)
void cProtocolRecognizer::SendWindowProperty(const cWindow & a_Window, short a_Property, short a_Value) void cProtocolRecognizer::SendWindowProperty(const cWindow & a_Window, int a_Property, int a_Value)
{ {
ASSERT(m_Protocol != NULL); ASSERT(m_Protocol != NULL);
m_Protocol->SendWindowProperty(a_Window, a_Property, a_Value); m_Protocol->SendWindowProperty(a_Window, a_Property, a_Value);

View File

@ -131,7 +131,7 @@ public:
virtual void SendWholeInventory (const cWindow & a_Window) override; virtual void SendWholeInventory (const cWindow & a_Window) override;
virtual void SendWindowClose (const cWindow & a_Window) override; virtual void SendWindowClose (const cWindow & a_Window) override;
virtual void SendWindowOpen (const cWindow & a_Window) override; virtual void SendWindowOpen (const cWindow & a_Window) override;
virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) override; virtual void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value) override;
virtual AString GetAuthServerID(void) override; virtual AString GetAuthServerID(void) override;

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);
} ; } ;

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;
} }
@ -96,7 +102,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 can be passed by the liquid ...
(IsBlockLiquid(BlockType) && (BlockMeta != 0)) // ... or it is a liquid and not a source block
)
{ {
// Path found, exit // Path found, exit
return a_Iteration; return a_Iteration;

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

@ -237,7 +237,7 @@ public:
{ {
ASSERT(m_Tags[(size_t)a_Tag].m_Type == TAG_String); ASSERT(m_Tags[(size_t)a_Tag].m_Type == TAG_String);
AString res; AString res;
res.assign(m_Data + m_Tags[(size_t)a_Tag].m_DataStart, m_Tags[(size_t)a_Tag].m_DataLength); res.assign(m_Data + m_Tags[(size_t)a_Tag].m_DataStart, (size_t)m_Tags[(size_t)a_Tag].m_DataLength);
return res; return res;
} }
@ -245,7 +245,7 @@ public:
inline AString GetName(int a_Tag) const inline AString GetName(int a_Tag) const
{ {
AString res; AString res;
res.assign(m_Data + m_Tags[(size_t)a_Tag].m_NameStart, m_Tags[(size_t)a_Tag].m_NameLength); res.assign(m_Data + m_Tags[(size_t)a_Tag].m_NameStart, (size_t)m_Tags[(size_t)a_Tag].m_NameLength);
return res; return res;
} }