1
0

Merge branch 'master' into SslWebAdmin

This commit is contained in:
Mattes D 2014-05-10 21:27:57 +02:00
commit 28815252e6
131 changed files with 2774 additions and 1859 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

@ -2,23 +2,33 @@ return
{
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
Desc = [[
This hook is called when a client is about to be disconnected from the server, for whatever reason.
<p><b>Note that this hook will be removed after <1.7 protocol support is removed, as it was originally a hook for
the client sending the server a disconnect packet, which no longer happens.</b></p>
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
for server ping connections.</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 =
{
{ 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" },
},
Returns = [[
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,
the player is disconnected.
the client is disconnected.
]],
}, -- HOOK_DISCONNECT
}

View File

@ -27,10 +27,14 @@ local function LoadAPIFiles(a_Folder, a_DstTable)
-- We only want .lua files from the folder:
if (cFile:IsFile(FileName) and fnam:match(".*%.lua$")) then
local TablesFn, Err = loadfile(FileName);
if (TablesFn == nil) then
if (type(TablesFn) ~= "function") then
LOGWARNING("Cannot load API descriptions from " .. FileName .. ", Lua error '" .. Err .. "'.");
else
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
a_DstTable[k] = cls;
end

@ -1 +1 @@
Subproject commit 013a32a7fb3c8a6cfe0aef892d4c7394d4e1be59
Subproject commit 5c8557d4fdfa580c100510cde07a1a778ea2e244

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

@ -243,7 +243,7 @@ int cIniFile::FindKey(const AString & a_KeyName) const
{
if (CheckCase(names[keyID]) == CaseKeyName)
{
return keyID;
return (int)keyID;
}
}
return noID;
@ -279,7 +279,7 @@ int cIniFile::AddKeyName(const AString & keyname)
{
names.resize(names.size() + 1, keyname);
keys.resize(keys.size() + 1);
return names.size() - 1;
return (int)names.size() - 1;
}
@ -683,7 +683,7 @@ int cIniFile::GetNumKeyComments(const int keyID) const
{
if (keyID < (int)keys.size())
{
return keys[keyID].comments.size();
return (int)keys[keyID].comments.size();
}
return 0;
}

View File

@ -42,7 +42,7 @@ bool cLuaChunkStay::AddChunks(int a_ChunkCoordTableStackPos)
// Add each set of coords:
int NumChunks = luaL_getn(L, a_ChunkCoordTableStackPos);
m_Chunks.reserve(NumChunks);
m_Chunks.reserve((size_t)NumChunks);
for (int idx = 1; idx <= NumChunks; idx++)
{
// 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>
// tolua_begin
unsigned int GetTime()
inline unsigned int GetTime()
{
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 ]);
}

View File

@ -37,7 +37,7 @@
/****************************
* 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
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
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:
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();
lua_createtable(tolua_S, AllGroups.size(), 0);
lua_createtable(tolua_S, (int)AllGroups.size(), 0);
int newTable = lua_gettop(tolua_S);
int index = 1;
cPlayer::GroupList::const_iterator iter = AllGroups.begin();
while(iter != AllGroups.end())
while (iter != AllGroups.end())
{
const cGroup* Group = *iter;
tolua_pushusertype( tolua_S, (void*)Group, "const cGroup" );
const cGroup * Group = *iter;
tolua_pushusertype(tolua_S, (void *)Group, "const cGroup");
lua_rawseti(tolua_S, newTable, index);
++iter;
++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();
lua_createtable(tolua_S, AllPermissions.size(), 0);
lua_createtable(tolua_S, (int)AllPermissions.size(), 0);
int newTable = lua_gettop(tolua_S);
int index = 1;
cPlayer::StringList::iterator iter = AllPermissions.begin();
while(iter != AllPermissions.end())
while (iter != AllPermissions.end())
{
std::string& Permission = *iter;
tolua_pushstring( tolua_S, Permission.c_str() );
std::string & Permission = *iter;
lua_pushlstring(tolua_S, Permission.c_str(), Permission.length());
lua_rawseti(tolua_S, newTable, index);
++iter;
++index;
@ -2076,18 +2076,18 @@ static int tolua_get_HTTPRequest_FormData(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();
lua_createtable(tolua_S, AllPlugins.size(), 0);
lua_createtable(tolua_S, (int)AllPlugins.size(), 0);
int newTable = lua_gettop(tolua_S);
int index = 1;
cWebAdmin::PluginList::const_iterator iter = AllPlugins.begin();
while(iter != AllPlugins.end())
while (iter != AllPlugins.end())
{
const cWebPlugin* Plugin = *iter;
tolua_pushusertype( tolua_S, (void*)Plugin, "const cWebPlugin" );
const cWebPlugin * Plugin = *iter;
tolua_pushusertype(tolua_S, (void *)Plugin, "const cWebPlugin");
lua_rawseti(tolua_S, newTable, index);
++iter;
++index;

View File

@ -56,7 +56,7 @@ public:
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 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 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;

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);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_DISCONNECT];
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)
{
return true;

View File

@ -79,7 +79,7 @@ public:
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 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 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;

View File

@ -143,13 +143,14 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
}
}
if (GetNumPlugins() == 0)
size_t NumLoadedPlugins = GetNumPlugins();
if (NumLoadedPlugins == 0)
{
LOG("-- No Plugins Loaded --");
}
else if (GetNumPlugins() > 1)
else if (NumLoadedPlugins > 1)
{
LOG("-- Loaded %i Plugins --", GetNumPlugins());
LOG("-- Loaded %i Plugins --", (int)NumLoadedPlugins);
}
else
{
@ -442,7 +443,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);
if (Plugins == m_Hooks.end())
@ -451,7 +452,7 @@ bool cPluginManager::CallHookDisconnect(cPlayer * a_Player, const AString & a_Re
}
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;
}
@ -1869,7 +1870,7 @@ void cPluginManager::AddHook(cPlugin * a_Plugin, int a_Hook)
unsigned int cPluginManager::GetNumPlugins() const
size_t cPluginManager::GetNumPlugins() const
{
return m_Plugins.size();
}

View File

@ -159,7 +159,7 @@ public: // tolua_export
/** Adds the plugin to the list of plugins called for the specified hook type. Handles multiple adds as a single add */
void AddHook(cPlugin * a_Plugin, int a_HookType);
unsigned int GetNumPlugins() const; // tolua_export
size_t GetNumPlugins() const; // tolua_export
// Calls for individual hooks. Each returns false if the action is to continue or true if the plugin wants to abort
bool CallHookBlockSpread (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source);
@ -172,7 +172,7 @@ public: // tolua_export
bool CallHookChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ);
bool CallHookCollectingPickup (cPlayer * a_Player, cPickup & a_Pickup);
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 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);

View File

@ -707,11 +707,11 @@ void cBlockArea::Merge(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_R
if (IsDummyMetas)
{
MergeByStrategy<true>(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas);
MergeByStrategy<false>(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas);
}
else
{
MergeByStrategy<false>(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas);
MergeByStrategy<true>(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas);
}
}
@ -738,31 +738,31 @@ void cBlockArea::Fill(int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_Block
a_DataTypes = a_DataTypes & GetDataTypes();
}
int BlockCount = GetBlockCount();
size_t BlockCount = GetBlockCount();
if ((a_DataTypes & baTypes) != 0)
{
for (int i = 0; i < BlockCount; i++)
for (size_t i = 0; i < BlockCount; i++)
{
m_BlockTypes[i] = a_BlockType;
}
}
if ((a_DataTypes & baMetas) != 0)
{
for (int i = 0; i < BlockCount; i++)
for (size_t i = 0; i < BlockCount; i++)
{
m_BlockMetas[i] = a_BlockMeta;
}
}
if ((a_DataTypes & baLight) != 0)
{
for (int i = 0; i < BlockCount; i++)
for (size_t i = 0; i < BlockCount; i++)
{
m_BlockLight[i] = a_BlockLight;
}
}
if ((a_DataTypes & baSkyLight) != 0)
{
for (int i = 0; i < BlockCount; i++)
for (size_t i = 0; i < BlockCount; i++)
{
m_BlockSkyLight[i] = a_BlockSkyLight;
}

View File

@ -110,10 +110,13 @@ void cBlockInfo::Initialize(void)
// Transparent blocks
ms_Info[E_BLOCK_ACTIVATOR_RAIL ].m_Transparent = true;
ms_Info[E_BLOCK_AIR ].m_Transparent = true;
ms_Info[E_BLOCK_ANVIL ].m_Transparent = true;
ms_Info[E_BLOCK_BIG_FLOWER ].m_Transparent = true;
ms_Info[E_BLOCK_BROWN_MUSHROOM ].m_Transparent = true;
ms_Info[E_BLOCK_CAKE ].m_Transparent = true;
ms_Info[E_BLOCK_CARROTS ].m_Transparent = true;
ms_Info[E_BLOCK_CHEST ].m_Transparent = true;
ms_Info[E_BLOCK_COBBLESTONE_WALL ].m_Transparent = true;
ms_Info[E_BLOCK_COBWEB ].m_Transparent = true;
ms_Info[E_BLOCK_CROPS ].m_Transparent = true;
ms_Info[E_BLOCK_DANDELION ].m_Transparent = true;
@ -126,6 +129,7 @@ void cBlockInfo::Initialize(void)
ms_Info[E_BLOCK_FLOWER_POT ].m_Transparent = true;
ms_Info[E_BLOCK_GLASS ].m_Transparent = true;
ms_Info[E_BLOCK_GLASS_PANE ].m_Transparent = true;
ms_Info[E_BLOCK_HEAD ].m_Transparent = true;
ms_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_Transparent = true;
ms_Info[E_BLOCK_ICE ].m_Transparent = true;
ms_Info[E_BLOCK_IRON_DOOR ].m_Transparent = true;
@ -196,12 +200,14 @@ void cBlockInfo::Initialize(void)
ms_Info[E_BLOCK_BED ].m_PistonBreakable = true;
ms_Info[E_BLOCK_BIG_FLOWER ].m_PistonBreakable = true;
ms_Info[E_BLOCK_BROWN_MUSHROOM ].m_PistonBreakable = true;
ms_Info[E_BLOCK_CAKE ].m_PistonBreakable = true;
ms_Info[E_BLOCK_COBWEB ].m_PistonBreakable = true;
ms_Info[E_BLOCK_CROPS ].m_PistonBreakable = true;
ms_Info[E_BLOCK_DANDELION ].m_PistonBreakable = true;
ms_Info[E_BLOCK_DEAD_BUSH ].m_PistonBreakable = true;
ms_Info[E_BLOCK_FIRE ].m_PistonBreakable = true;
ms_Info[E_BLOCK_FLOWER ].m_PistonBreakable = true;
ms_Info[E_BLOCK_HEAD ].m_PistonBreakable = true;
ms_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_PistonBreakable = true;
ms_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_PistonBreakable = true;
ms_Info[E_BLOCK_IRON_DOOR ].m_PistonBreakable = true;
@ -243,6 +249,7 @@ void cBlockInfo::Initialize(void)
ms_Info[E_BLOCK_CACTUS ].m_IsSnowable = false;
ms_Info[E_BLOCK_CHEST ].m_IsSnowable = false;
ms_Info[E_BLOCK_CROPS ].m_IsSnowable = false;
ms_Info[E_BLOCK_COBBLESTONE_WALL ].m_IsSnowable = false;
ms_Info[E_BLOCK_DANDELION ].m_IsSnowable = false;
ms_Info[E_BLOCK_FIRE ].m_IsSnowable = false;
ms_Info[E_BLOCK_FLOWER ].m_IsSnowable = false;
@ -276,6 +283,7 @@ void cBlockInfo::Initialize(void)
ms_Info[E_BLOCK_POWERED_RAIL ].m_IsSnowable = false;
ms_Info[E_BLOCK_DETECTOR_RAIL ].m_IsSnowable = false;
ms_Info[E_BLOCK_COBWEB ].m_IsSnowable = false;
ms_Info[E_BLOCK_HEAD ].m_IsSnowable = false;
// Blocks that don't drop without a special tool:
@ -283,6 +291,7 @@ void cBlockInfo::Initialize(void)
ms_Info[E_BLOCK_CAULDRON ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_COAL_ORE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_COBBLESTONE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_COBBLESTONE_WALL ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_COBBLESTONE_STAIRS ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_COBWEB ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_DIAMOND_BLOCK ].m_RequiresSpecialTool = true;
@ -325,6 +334,7 @@ void cBlockInfo::Initialize(void)
ms_Info[E_BLOCK_AIR ].m_IsSolid = false;
ms_Info[E_BLOCK_BIG_FLOWER ].m_IsSolid = false;
ms_Info[E_BLOCK_BROWN_MUSHROOM ].m_IsSolid = false;
ms_Info[E_BLOCK_CAKE ].m_IsSolid = false;
ms_Info[E_BLOCK_CARROTS ].m_IsSolid = false;
ms_Info[E_BLOCK_COBWEB ].m_IsSolid = false;
ms_Info[E_BLOCK_CROPS ].m_IsSolid = false;

View File

@ -23,6 +23,13 @@ public:
{
a_Pickups.push_back(cItem(E_BLOCK_ANVIL, 1, a_BlockMeta >> 2));
}
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{
cWindow * Window = new cAnvilWindow(a_BlockX, a_BlockY, a_BlockZ);
a_Player->OpenWindow(Window);
}
virtual bool GetPlacementBlockTypeMeta(

View File

@ -39,6 +39,13 @@ public:
}
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
{
return true;
}
// Bed specific helper functions
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{

View File

@ -35,8 +35,10 @@ public:
// Grass becomes dirt if there is something on top of it:
if (a_RelY < cChunkDef::Height - 1)
{
BLOCKTYPE Above = a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ);
if ((!cBlockInfo::IsTransparent(Above) && !cBlockInfo::IsOneHitDig(Above)) || IsBlockWater(Above))
BLOCKTYPE Above;
NIBBLETYPE AboveMeta;
a_Chunk.GetBlockTypeMeta(a_RelX, a_RelY + 1, a_RelZ, Above, AboveMeta);
if (!cBlockInfo::GetHandler(Above)->CanDirtGrowGrass(AboveMeta))
{
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_DIRT, E_META_DIRT_NORMAL);
return;
@ -77,7 +79,7 @@ public:
BLOCKTYPE AboveDest;
NIBBLETYPE AboveMeta;
Chunk->GetBlockTypeMeta(BlockX, BlockY + 1, BlockZ, AboveDest, AboveMeta);
if ((cBlockInfo::IsOneHitDig(AboveDest) || cBlockInfo::IsTransparent(AboveDest)) && !IsBlockWater(AboveDest))
if (cBlockInfo::GetHandler(AboveDest)->CanDirtGrowGrass(AboveMeta))
{
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread((cWorld*) &a_WorldInterface, BlockX * cChunkDef::Width, BlockY, BlockZ * cChunkDef::Width, ssGrassSpread))
{

View File

@ -52,9 +52,9 @@ public:
return;
}
int NumBlocks = Area.GetBlockCount();
size_t NumBlocks = Area.GetBlockCount();
BLOCKTYPE * BlockTypes = Area.GetBlockTypes();
for (int i = 0; i < NumBlocks; i++)
for (size_t i = 0; i < NumBlocks; i++)
{
if (
(BlockTypes[i] == E_BLOCK_WATER) ||

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

@ -49,6 +49,12 @@ public:
}
super::Check(a_ChunkInterface, a_PluginInterface, a_RelX, a_RelY, a_RelZ, a_Chunk);
}
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
{
return false;
}
} ;

View File

@ -400,6 +400,15 @@ bool cBlockHandler::CanBeAt(cChunkInterface & a_ChunkInterface, int a_BlockX, in
bool cBlockHandler::CanDirtGrowGrass(NIBBLETYPE a_Meta)
{
return ((cBlockInfo::IsTransparent(m_BlockType)) || (cBlockInfo::IsOneHitDig(m_BlockType)));
}
bool cBlockHandler::IsUseable()
{
return false;

View File

@ -85,6 +85,9 @@ public:
/// Checks if the block can stay at the specified relative coords in the chunk
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk);
/** Can the dirt under this block grow to grass? */
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta);
/** Checks if the block can be placed at this point.
Default: CanBeAt(...)

View File

@ -138,14 +138,14 @@ bool HasNearLog(cBlockArea & a_Area, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Filter the blocks into a {leaves, log, other (air)} set:
BLOCKTYPE * Types = a_Area.GetBlockTypes();
for (int i = a_Area.GetBlockCount() - 1; i > 0; i--)
for (size_t i = a_Area.GetBlockCount() - 1; i > 0; i--)
{
switch (Types[i])
{
case E_BLOCK_NEW_LEAVES:
case E_BLOCK_NEW_LOG:
case E_BLOCK_LEAVES:
case E_BLOCK_LOG:
case E_BLOCK_NEW_LEAVES:
case E_BLOCK_NEW_LOG:
{
break;
}

View File

@ -2,6 +2,7 @@
#pragma once
#include "BlockHandler.h"
#include "../Mobs/Monster.h"
@ -38,6 +39,19 @@ public:
return; // No pickups
}
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
{
cFastRandom Random;
if (Random.NextInt(2000) != 0)
{
return;
}
int PosX = a_Chunk.GetPosX() * 16 + a_RelX;
int PosZ = a_Chunk.GetPosZ() * 16 + a_RelZ;
a_WorldInterface.SpawnMob(PosX, a_RelY, PosZ, cMonster::mtZombiePigman);
}
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{

View File

@ -97,6 +97,12 @@ public:
return "";
}
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
{
return ((a_Meta & 0x8) != 0);
}
/// Returns true if the specified blocktype is one of the slabs handled by this handler
static bool IsAnySlabType(BLOCKTYPE a_BlockType)

View File

@ -77,6 +77,11 @@ public:
// Reset meta to 0
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
{
return true;
}
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{

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 "";
}
@ -633,6 +633,10 @@ void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString
// Client <-> Server branding exchange
SendPluginMessage("MC|Brand", "MCServer");
}
else if (a_Channel == "MC|ItemName")
{
HandleAnvilItemName(a_Message.c_str(), a_Message.size());
}
else if (a_Channel == "REGISTER")
{
if (HasPluginChannel(a_Channel))
@ -774,6 +778,29 @@ void cClientHandle::HandleCommandBlockMessage(const char * a_Data, size_t a_Leng
void cClientHandle::HandleAnvilItemName(const char * a_Data, size_t a_Length)
{
if (a_Length < 1)
{
return;
}
if ((m_Player->GetWindow() == NULL) || (m_Player->GetWindow()->GetWindowType() != cWindow::wtAnvil))
{
return;
}
AString Name(a_Data, a_Length);
if (Name.length() <= 30)
{
((cAnvilWindow *)m_Player->GetWindow())->SetRepairedItemName(Name, m_Player);
}
}
void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, char a_Status)
{
LOGD("HandleLeftClick: {%i, %i, %i}; Face: %i; Stat: %i",
@ -1510,7 +1537,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());
cRoot::Get()->GetPluginManager()->CallHookDisconnect(m_Player, a_Reason);
cRoot::Get()->GetPluginManager()->CallHookDisconnect(*this, a_Reason);
m_HasSentDC = true;
Destroy();
@ -2690,9 +2717,9 @@ void cClientHandle::SocketClosed(void)
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();

View File

@ -385,6 +385,9 @@ private:
/** Handles the "MC|AdvCdm" plugin message */
void HandleCommandBlockMessage(const char * a_Data, size_t a_Length);
/** Handles the "MC|ItemName" plugin message */
void HandleAnvilItemName(const char * a_Data, size_t a_Length);
// cSocketThreads::cCallback overrides:
virtual bool DataReceived (const char * a_Data, size_t a_Size) override; // Data is received from the client

View File

@ -802,7 +802,7 @@ void cCraftingRecipes::HandleFireworks(const cItem * a_CraftingGrid, cCraftingRe
break;
}
case E_ITEM_PAPER: break;
default: LOG("Unexpected item in firework rocket a_Recipe, was the crafting file fireworks section changed?"); break;
default: LOG("Unexpected item in firework rocket recipe, was the crafting file's fireworks section changed?"); break;
}
}
}
@ -837,7 +837,7 @@ void cCraftingRecipes::HandleFireworks(const cItem * a_CraftingGrid, cCraftingRe
case E_ITEM_GOLD_NUGGET: a_Recipe->m_Result.m_FireworkItem.m_Type = 2; break;
case E_ITEM_FEATHER: a_Recipe->m_Result.m_FireworkItem.m_Type = 4; break;
case E_ITEM_HEAD: a_Recipe->m_Result.m_FireworkItem.m_Type = 3; break;
default: LOG("Unexpected item in firework star a_Recipe, was the crafting file fireworks section changed?"); break; // ermahgerd BARD ardmins
default: LOG("Unexpected item in firework star recipe, was the crafting file's fireworks section changed?"); break; // ermahgerd BARD ardmins
}
}

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

@ -83,6 +83,15 @@ void cEnchantments::AddFromString(const AString & a_StringSpec)
size_t cEnchantments::Count(void)
{
return m_Enchantments.size();
}
AString cEnchantments::ToString(void) const
{
// Serialize all the enchantments into a string

View File

@ -84,6 +84,9 @@ public:
/** Adds enchantments in the stringspec; if a specified enchantment already exists, overwrites it */
void AddFromString(const AString & a_StringSpec);
/** Get the count of enchantments */
size_t Count(void);
/** Serializes all the enchantments into a string */
AString ToString(void) const;

View File

@ -15,6 +15,7 @@ cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a
m_IsCritical(false),
m_Timer(0),
m_HitGroundTimer(0),
m_HasTeleported(false),
m_bIsCollected(false),
m_HitBlockPos(Vector3i(0, 0, 0))
{

View File

<
@ -1,3 +1,4 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Entity.h"
@ -10,7 +11,6 @@
#include "../Simulator/FluidSimulator.h"
#include "../Bindings/PluginManager.h"
#include "../Tracer.h"
#include "Minecart.h"
#include "Player.h"
@ -32,16 +32,10 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
, m_Attachee(NULL)
, m_bDirtyHead(true)
, m_bDirtyOrientation(true)
, m_bDirtyPosition(true)
, m_bDirtySpeed(true)
, m_bOnGround( false )
, m_Gravity( -9.81f )
, m_LastPosX( 0.0 )
, m_LastPosY( 0.0 )
, m_LastPosZ( 0.0 )
, m_TimeLastTeleportPacket(0)
, m_TimeLastMoveReltPacket(0)
, m_TimeLastSpeedPacket(0)
, m_bHasSentNoSpeed(true)
, m_bOnGround(false)
, m_Gravity(-9.81f)
, m_LastPos(a_X, a_Y, a_Z)