Merge remote-tracking branch 'origin/master' into CraftingFixes

This commit is contained in:
Mattes D
2014-08-28 16:53:36 +03:00
125 changed files with 5255 additions and 2180 deletions
-1
View File
@@ -67,7 +67,6 @@ $cfile "../Root.h"
$cfile "../Cuboid.h"
$cfile "../BoundingBox.h"
$cfile "../Tracer.h"
$cfile "../Group.h"
$cfile "../BlockArea.h"
$cfile "../Generating/ChunkDesc.h"
$cfile "../CraftingRecipes.h"
+1 -1
View File
@@ -11,6 +11,7 @@ SET (SRCS
LuaState.cpp
LuaWindow.cpp
ManualBindings.cpp
ManualBindings_RankManager.cpp
Plugin.cpp
PluginLua.cpp
PluginManager.cpp
@@ -96,7 +97,6 @@ set(BINDING_DEPENDENCIES
../Entities/HangingEntity.h
../Entities/ItemFrame.h
../Generating/ChunkDesc.h
../Group.h
../Inventory.h
../Item.h
../ItemGrid.h
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#include "../MCLogger.h"
#include "Logger.h"
#include <time.h>
// tolua_begin
+41 -5
View File
@@ -460,7 +460,43 @@ void cLuaState::Push(const Vector3d & a_Vector)
{
ASSERT(IsValid());
tolua_pushusertype(m_LuaState, (void *)&a_Vector, "Vector3d");
tolua_pushusertype(m_LuaState, (void *)&a_Vector, "Vector3<double>");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::Push(const Vector3d * a_Vector)
{
ASSERT(IsValid());
tolua_pushusertype(m_LuaState, (void *)a_Vector, "Vector3<double>");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::Push(const Vector3i & a_Vector)
{
ASSERT(IsValid());
tolua_pushusertype(m_LuaState, (void *)&a_Vector, "Vector3<int>");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::Push(const Vector3i * a_Vector)
{
ASSERT(IsValid());
tolua_pushusertype(m_LuaState, (void *)a_Vector, "Vector3<int>");
m_NumCurrentFunctionArgs += 1;
}
@@ -708,11 +744,11 @@ void cLuaState::Push(TakeDamageInfo * a_TDI)
void cLuaState::Push(Vector3i * a_Vector)
void cLuaState::Push(Vector3d * a_Vector)
{
ASSERT(IsValid());
tolua_pushusertype(m_LuaState, a_Vector, "Vector3i");
tolua_pushusertype(m_LuaState, a_Vector, "Vector3<double>");
m_NumCurrentFunctionArgs += 1;
}
@@ -720,11 +756,11 @@ void cLuaState::Push(Vector3i * a_Vector)
void cLuaState::Push(Vector3d * a_Vector)
void cLuaState::Push(Vector3i * a_Vector)
{
ASSERT(IsValid());
tolua_pushusertype(m_LuaState, a_Vector, "Vector3d");
tolua_pushusertype(m_LuaState, a_Vector, "Vector3<int>");
m_NumCurrentFunctionArgs += 1;
}
+3
View File
@@ -186,6 +186,9 @@ public:
void Push(const HTTPRequest * a_Request);
void Push(const HTTPTemplateRequest * a_Request);
void Push(const Vector3d & a_Vector);
void Push(const Vector3d * a_Vector);
void Push(const Vector3i & a_Vector);
void Push(const Vector3i * a_Vector);
// Push a value onto the stack (keep alpha-sorted):
void Push(bool a_Value);
+122 -47
View File
@@ -168,7 +168,7 @@ static AString GetLogMessage(lua_State * tolua_S)
static int tolua_LOG(lua_State * tolua_S)
{
// If the param is a cCompositeChat, read the log level from it:
cMCLogger::eLogLevel LogLevel = cMCLogger::llRegular;
cLogger::eLogLevel LogLevel = cLogger::llRegular;
tolua_Error err;
if (tolua_isusertype(tolua_S, 1, "cCompositeChat", false, &err))
{
@@ -176,7 +176,7 @@ static int tolua_LOG(lua_State * tolua_S)
}
// Log the message:
cMCLogger::GetInstance()->LogSimple(GetLogMessage(tolua_S).c_str(), LogLevel);
cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S).c_str(), LogLevel);
return 0;
}
@@ -186,7 +186,7 @@ static int tolua_LOG(lua_State * tolua_S)
static int tolua_LOGINFO(lua_State * tolua_S)
{
cMCLogger::GetInstance()->LogSimple(GetLogMessage(tolua_S).c_str(), cMCLogger::llInfo);
cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S).c_str(), cLogger::llInfo);
return 0;
}
@@ -196,7 +196,7 @@ static int tolua_LOGINFO(lua_State * tolua_S)
static int tolua_LOGWARN(lua_State * tolua_S)
{
cMCLogger::GetInstance()->LogSimple(GetLogMessage(tolua_S).c_str(), cMCLogger::llWarning);
cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S).c_str(), cLogger::llWarning);
return 0;
}
@@ -206,7 +206,7 @@ static int tolua_LOGWARN(lua_State * tolua_S)
static int tolua_LOGERROR(lua_State * tolua_S)
{
cMCLogger::GetInstance()->LogSimple(GetLogMessage(tolua_S).c_str(), cMCLogger::llError);
cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S).c_str(), cLogger::llError);
return 0;
}
@@ -1803,49 +1803,30 @@ static int tolua_cWorld_ChunkStay(lua_State * tolua_S)
static int tolua_cPlayer_GetGroups(lua_State * tolua_S)
static int tolua_cPlayer_GetPermissions(lua_State * tolua_S)
{
// Function signature: cPlayer:GetPermissions() -> {permissions-array}
// Check the params:
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cPlayer") ||
!L.CheckParamEnd (2)
)
{
return 0;
}
// Get the params:
cPlayer * self = (cPlayer *)tolua_tousertype(tolua_S, 1, NULL);
const cPlayer::GroupList & AllGroups = self->GetGroups();
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())
if (self == NULL)
{
const cGroup * Group = *iter;
tolua_pushusertype(tolua_S, (void *)Group, "const cGroup");
lua_rawseti(tolua_S, newTable, index);
++iter;
++index;
}
return 1;
}
static int tolua_cPlayer_GetResolvedPermissions(lua_State * tolua_S)
{
cPlayer * self = (cPlayer*) tolua_tousertype(tolua_S, 1, NULL);
cPlayer::StringList AllPermissions = self->GetResolvedPermissions();
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())
{
std::string & Permission = *iter;
lua_pushlstring(tolua_S, Permission.c_str(), Permission.length());
lua_rawseti(tolua_S, newTable, index);
++iter;
++index;
LOGWARNING("%s: invalid self (%p)", __FUNCTION__, self);
return 0;
}
// Push the permissions:
L.Push(self->GetPermissions());
return 1;
}
@@ -1902,6 +1883,40 @@ static int tolua_cPlayer_OpenWindow(lua_State * tolua_S)
static int tolua_cPlayer_PermissionMatches(lua_State * tolua_S)
{
// Function signature: cPlayer:PermissionMatches(PermissionStr, TemplateStr) -> bool
// Check the params:
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cPlayer") ||
!L.CheckParamString (2, 3) ||
!L.CheckParamEnd (4)
)
{
return 0;
}
// Get the params:
cPlayer * self = (cPlayer *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
LOGWARNING("%s: invalid self (%p)", __FUNCTION__, self);
return 0;
}
AString Permission, Template;
L.GetStackValues(2, Permission, Template);
// Push the result of the match:
L.Push(self->PermissionMatches(StringSplit(Permission, "."), StringSplit(Template, ".")));
return 1;
}
template <
class OBJTYPE,
void (OBJTYPE::*SetCallback)(cPluginLua * a_Plugin, int a_FnRef)
@@ -2399,6 +2414,62 @@ static int tolua_cMojangAPI_GetUUIDsFromPlayerNames(lua_State * L)
static int tolua_cMojangAPI_MakeUUIDDashed(lua_State * L)
{
// Function signature: cMojangAPI:MakeUUIDDashed(UUID) -> string
// Check params:
cLuaState S(L);
if (
!S.CheckParamUserTable(1, "cMojangAPI") ||
!S.CheckParamString(2) ||
!S.CheckParamEnd(3)
)
{
return 0;
}
// Get the params:
AString UUID;
S.GetStackValue(2, UUID);
// Push the result:
S.Push(cRoot::Get()->GetMojangAPI().MakeUUIDDashed(UUID));
return 1;
}
static int tolua_cMojangAPI_MakeUUIDShort(lua_State * L)
{
// Function signature: cMojangAPI:MakeUUIDShort(UUID) -> string
// Check params:
cLuaState S(L);
if (
!S.CheckParamUserTable(1, "cMojangAPI") ||
!S.CheckParamString(2) ||
!S.CheckParamEnd(3)
)
{
return 0;
}
// Get the params:
AString UUID;
S.GetStackValue(2, UUID);
// Push the result:
S.Push(cRoot::Get()->GetMojangAPI().MakeUUIDShort(UUID));
return 1;
}
static int Lua_ItemGrid_GetSlotCoords(lua_State * L)
{
tolua_Error tolua_err;
@@ -3295,9 +3366,9 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPlayer");
tolua_function(tolua_S, "GetGroups", tolua_cPlayer_GetGroups);
tolua_function(tolua_S, "GetResolvedPermissions", tolua_cPlayer_GetResolvedPermissions);
tolua_function(tolua_S, "OpenWindow", tolua_cPlayer_OpenWindow);
tolua_function(tolua_S, "GetPermissions", tolua_cPlayer_GetPermissions);
tolua_function(tolua_S, "OpenWindow", tolua_cPlayer_OpenWindow);
tolua_function(tolua_S, "PermissionMatches", tolua_cPlayer_PermissionMatches);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cLuaWindow");
@@ -3340,6 +3411,8 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "GetPlayerNameFromUUID", tolua_cMojangAPI_GetPlayerNameFromUUID);
tolua_function(tolua_S, "GetUUIDFromPlayerName", tolua_cMojangAPI_GetUUIDFromPlayerName);
tolua_function(tolua_S, "GetUUIDsFromPlayerNames", tolua_cMojangAPI_GetUUIDsFromPlayerNames);
tolua_function(tolua_S, "MakeUUIDDashed", tolua_cMojangAPI_MakeUUIDDashed);
tolua_function(tolua_S, "MakeUUIDShort", tolua_cMojangAPI_MakeUUIDShort);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cItemGrid");
@@ -3347,6 +3420,8 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_endmodule(tolua_S);
tolua_function(tolua_S, "md5", tolua_md5);
BindRankManager(tolua_S);
tolua_endmodule(tolua_S);
}
+17 -1
View File
@@ -1,8 +1,24 @@
#pragma once
struct lua_State;
/** Provides namespace for the bindings. */
class ManualBindings
{
public:
static void Bind( lua_State* tolua_S);
/** Binds all the manually implemented functions to tolua_S. */
static void Bind(lua_State * tolua_S);
protected:
/** Binds the manually implemented cRankManager glue code to tolua_S.
Implemented in ManualBindings_RankManager.cpp. */
static void BindRankManager(lua_State * tolua_S);
};
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -73,7 +73,7 @@ public:
virtual bool OnPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel) = 0;
virtual bool OnPlayerJoined (cPlayer & a_Player) = 0;
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) = 0;
virtual bool OnPlayerMoved (cPlayer & a_Player) = 0;
virtual bool OnPlayerMoving (cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) = 0;
virtual bool OnPlayerPlacedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual bool OnPlayerPlacingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual bool OnPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) = 0;
@@ -91,6 +91,7 @@ public:
virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) = 0;
virtual bool OnProjectileHitBlock (cProjectileEntity & a_Projectile, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Face, const Vector3d & a_BlockHitPos) = 0;
virtual bool OnProjectileHitEntity (cProjectileEntity & a_Projectile, cEntity & a_HitEntity) = 0;
virtual bool OnServerPing (cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon) = 0;
virtual bool OnSpawnedEntity (cWorld & a_World, cEntity & a_Entity) = 0;
virtual bool OnSpawnedMonster (cWorld & a_World, cMonster & a_Monster) = 0;
virtual bool OnSpawningEntity (cWorld & a_World, cEntity & a_Entity) = 0;
+23 -2
View File
@@ -835,14 +835,14 @@ bool cPluginLua::OnPlayerLeftClick(cPlayer & a_Player, int a_BlockX, int a_Block
bool cPluginLua::OnPlayerMoved(cPlayer & a_Player)
bool cPluginLua::OnPlayerMoving(cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_MOVING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
m_LuaState.Call((int)(**itr), &a_Player, cLuaState::Return, res);
m_LuaState.Call((int)(**itr), &a_Player, a_OldPosition, a_NewPosition, cLuaState::Return, res);
if (res)
{
return true;
@@ -1193,6 +1193,26 @@ bool cPluginLua::OnProjectileHitEntity(cProjectileEntity & a_Projectile, cEntity
bool cPluginLua::OnServerPing(cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_SERVER_PING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
m_LuaState.Call((int)(**itr), &a_ClientHandle, a_ServerDescription, a_OnlinePlayersCount, a_MaxPlayersCount, a_Favicon, cLuaState::Return, res, a_ServerDescription, a_OnlinePlayersCount, a_MaxPlayersCount, a_Favicon);
if (res)
{
return true;
}
}
return false;
}
bool cPluginLua::OnSpawnedEntity(cWorld & a_World, cEntity & a_Entity)
{
cCSLock Lock(m_CriticalSection);
@@ -1570,6 +1590,7 @@ const char * cPluginLua::GetHookFnName(int a_HookType)
case cPluginManager::HOOK_PLUGINS_LOADED: return "OnPluginsLoaded";
case cPluginManager::HOOK_POST_CRAFTING: return "OnPostCrafting";
case cPluginManager::HOOK_PRE_CRAFTING: return "OnPreCrafting";
case cPluginManager::HOOK_SERVER_PING: return "OnServerPing";
case cPluginManager::HOOK_SPAWNED_ENTITY: return "OnSpawnedEntity";
case cPluginManager::HOOK_SPAWNED_MONSTER: return "OnSpawnedMonster";
case cPluginManager::HOOK_SPAWNING_ENTITY: return "OnSpawningEntity";
+2 -1
View File
@@ -98,8 +98,8 @@ public:
virtual bool OnPlayerFishing (cPlayer & a_Player, cItems & a_Reward) override;
virtual bool OnPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel) override;
virtual bool OnPlayerJoined (cPlayer & a_Player) override;
virtual bool OnPlayerMoved (cPlayer & a_Player) override;
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) override;
virtual bool OnPlayerMoving (cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) override;
virtual bool OnPlayerPlacedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerPlacingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
@@ -117,6 +117,7 @@ public:
virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnProjectileHitBlock (cProjectileEntity & a_Projectile, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Face, const Vector3d & a_BlockHitPos) override;
virtual bool OnProjectileHitEntity (cProjectileEntity & a_Projectile, cEntity & a_HitEntity) override;
virtual bool OnServerPing (cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon) override;
virtual bool OnSpawnedEntity (cWorld & a_World, cEntity & a_Entity) override;
virtual bool OnSpawnedMonster (cWorld & a_World, cMonster & a_Monster) override;
virtual bool OnSpawningEntity (cWorld & a_World, cEntity & a_Entity) override;
+21 -2
View File
@@ -849,14 +849,14 @@ bool cPluginManager::CallHookPlayerLeftClick(cPlayer & a_Player, int a_BlockX, i
bool cPluginManager::CallHookPlayerMoving(cPlayer & a_Player)
bool cPluginManager::CallHookPlayerMoving(cPlayer & a_Player, const Vector3d a_OldPosition, const Vector3d a_NewPosition)
{
FIND_HOOK(HOOK_PLAYER_MOVING);
VERIFY_HOOK;
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerMoved(a_Player))
if ((*itr)->OnPlayerMoving(a_Player, a_OldPosition, a_NewPosition))
{
return true;
}
@@ -1189,6 +1189,25 @@ bool cPluginManager::CallHookProjectileHitEntity(cProjectileEntity & a_Projectil
bool cPluginManager::CallHookServerPing(cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon)
{
FIND_HOOK(HOOK_SERVER_PING);
VERIFY_HOOK;
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnServerPing(a_ClientHandle, a_ServerDescription, a_OnlinePlayersCount, a_MaxPlayersCount, a_Favicon))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookSpawnedEntity(cWorld & a_World, cEntity & a_Entity)
{
FIND_HOOK(HOOK_SPAWNED_ENTITY);
+3 -1
View File
@@ -120,6 +120,7 @@ public:
HOOK_PRE_CRAFTING,
HOOK_PROJECTILE_HIT_BLOCK,
HOOK_PROJECTILE_HIT_ENTITY,
HOOK_SERVER_PING,
HOOK_SPAWNED_ENTITY,
HOOK_SPAWNED_MONSTER,
HOOK_SPAWNING_ENTITY,
@@ -206,7 +207,7 @@ public:
bool CallHookPlayerFishing (cPlayer & a_Player, cItems a_Reward);
bool CallHookPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel);
bool CallHookPlayerJoined (cPlayer & a_Player);
bool CallHookPlayerMoving (cPlayer & a_Player);
bool CallHookPlayerMoving (cPlayer & a_Player, const Vector3d a_OldPosition, const Vector3d a_NewPosition);
bool CallHookPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status);
bool CallHookPlayerPlacedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerPlacingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
@@ -225,6 +226,7 @@ public:
bool CallHookPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookProjectileHitBlock (cProjectileEntity & a_Projectile, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Face, const Vector3d & a_BlockHitPos);
bool CallHookProjectileHitEntity (cProjectileEntity & a_Projectile, cEntity & a_HitEntity);
bool CallHookServerPing (cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon);
bool CallHookSpawnedEntity (cWorld & a_World, cEntity & a_Entity);
bool CallHookSpawnedMonster (cWorld & a_World, cMonster & a_Monster);
bool CallHookSpawningEntity (cWorld & a_World, cEntity & a_Entity);
+28
View File
@@ -54,6 +54,7 @@ local Combinations =
{9, 2},
-- Special combinations:
{5, 5},
{7, 3},
{8, 3},
{9, 5},
@@ -182,6 +183,33 @@ for _, combination in ipairs(Combinations) do
WriteOverload(f, combination[1], combination[2])
end
-- Generate the cLuaState::GetStackValues() multi-param templates:
for i = 2, 6 do
f:write("/** Reads ", i, " consecutive values off the stack */\ntemplate <\n")
-- Write the template function header:
local txt = {}
for idx = 1, i do
table.insert(txt, "\ttypename ArgT" .. idx)
end
f:write(table.concat(txt, ",\n"))
-- Write the argument declarations:
txt = {}
f:write("\n>\nvoid GetStackValues(\n\tint a_BeginPos,\n")
for idx = 1, i do
table.insert(txt, "\tArgT" .. idx .. " & Arg" .. idx)
end
f:write(table.concat(txt, ",\n"))
-- Write the function body:
f:write("\n)\n{\n")
for idx = 1, i do
f:write("\tGetStackValue(a_BeginPos + ", idx - 1, ", Arg", idx, ");\n")
end
f:write("}\n\n\n\n\n\n")
end
-- Close the generated file
f:close()
+3 -1
View File
@@ -1764,7 +1764,9 @@ NIBBLETYPE cBlockArea::GetNibble(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBL
cBlockArea::cChunkReader::cChunkReader(cBlockArea & a_Area) :
m_Area(a_Area),
m_Origin(a_Area.m_Origin.x, a_Area.m_Origin.y, a_Area.m_Origin.z)
m_Origin(a_Area.m_Origin.x, a_Area.m_Origin.y, a_Area.m_Origin.z),
m_CurrentChunkX(0),
m_CurrentChunkZ(0)
{
}
+3 -3
View File
@@ -37,7 +37,7 @@ public:
{
NIBBLETYPE Meta = a_BlockMeta & 0x7;
if ((Meta == 2) || (Meta == 3))
if ((Meta == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS) || (Meta == E_META_BIG_FLOWER_LARGE_FERN))
{
return;
}
@@ -63,11 +63,11 @@ public:
if (r1.randInt(10) == 5)
{
cItems Pickups;
if (FlowerMeta == 2)
if (FlowerMeta == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS)
{
Pickups.Add(E_BLOCK_TALL_GRASS, 2, 1);
}
else if (FlowerMeta == 3)
else if (FlowerMeta == E_META_BIG_FLOWER_LARGE_FERN)
{
Pickups.Add(E_BLOCK_TALL_GRASS, 2, 2);
}
+1 -1
View File
@@ -19,7 +19,7 @@ public:
{
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
if (!a_Player->Feed(2, 0.1))
if (!a_Player->Feed(2, 0.4))
{
return;
}
+1 -1
View File
@@ -81,7 +81,7 @@ public:
Chunk->GetBlockTypeMeta(BlockX, BlockY + 1, BlockZ, AboveDest, AboveMeta);
if (cBlockInfo::GetHandler(AboveDest)->CanDirtGrowGrass(AboveMeta))
{
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread((cWorld*) &a_WorldInterface, BlockX * cChunkDef::Width, BlockY, BlockZ * cChunkDef::Width, ssGrassSpread))
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(Chunk->GetWorld(), Chunk->GetPosX() * cChunkDef::Width + BlockX, BlockY, Chunk->GetPosZ() * cChunkDef::Width + BlockZ, ssGrassSpread))
{
Chunk->FastSetBlock(BlockX, BlockY, BlockZ, E_BLOCK_GRASS, 0);
}
+1 -4
View File
@@ -54,10 +54,7 @@ public:
BLOCKTYPE * BlockTypes = Area.GetBlockTypes();
for (size_t i = 0; i < NumBlocks; i++)
{
if (
(BlockTypes[i] == E_BLOCK_WATER) ||
(BlockTypes[i] == E_BLOCK_STATIONARY_WATER)
)
if (IsBlockWater(BlockTypes[i]))
{
Found = true;
break;
+1
View File
@@ -35,6 +35,7 @@ public:
NIBBLETYPE OldMetaData = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
NIBBLETYPE NewMetaData = PlayerYawToMetaData(a_Player->GetYaw());
OldMetaData ^= 4; // Toggle the gate
if ((OldMetaData & 1) == (NewMetaData & 1))
{
// Standing in front of the gate - apply new direction
+15 -15
View File
@@ -40,11 +40,6 @@ public:
FindAndSetPortalFrame(a_BlockX, a_BlockY - 1, a_BlockZ, a_ChunkInterface, a_WorldInterface);
}
virtual void OnDigging(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override
{
a_ChunkInterface.DigBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ);
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// No pickups from this block
@@ -60,8 +55,8 @@ public:
return "step.wood";
}
/// Traces along YP until it finds an obsidian block, returns Y difference or 0 if no portal, and -1 for border
/// Takes the X, Y, and Z of the base block; with an optional MaxY for portal border finding
/** Traces along YP until it finds an obsidian block, returns Y difference or 0 if no portal, and -1 for border
Takes the X, Y, and Z of the base block; with an optional MaxY for portal border finding */
int FindObsidianCeiling(int X, int Y, int Z, cChunkInterface & a_ChunkInterface, int MaxY = 0)
{
if (a_ChunkInterface.GetBlock(X, Y, Z) != E_BLOCK_OBSIDIAN)
@@ -91,13 +86,12 @@ public:
return newY;
}
}
else { return 0; }
}
return 0;
}
/// Evaluates if coords have a valid border on top, based on MaxY
/** Evaluates if coords have a valid border on top, based on MaxY */
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
@@ -149,8 +143,8 @@ public:
return;
}
/// Evaluates if coordinates are a portal going XP/XM; returns true if so, and writes boundaries to variable
/// Takes coordinates of base block and Y coord of target obsidian ceiling
/** Evaluates if coordinates are a portal going XP/XM; returns true if so, and writes boundaries to variable
Takes coordinates of base block and Y coord of target obsidian ceiling */
bool FindPortalSliceX(int X1, int X2, int Y, int Z, int MaxY, cChunkInterface & a_ChunkInterface)
{
Dir = 1; // Set assumed direction (will change if portal turns out to be facing the other direction)
@@ -168,7 +162,8 @@ public:
{
return false; // Not valid slice, no portal can be formed
}
} XZP = X1 - 1; // Set boundary of frame interior
}
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);
@@ -182,7 +177,9 @@ public:
{
return false;
}
} XZM = X2 + 1; // Set boundary, see previous
}
XZM = X2 + 1; // Set boundary, see previous
return (FoundFrameXP && FoundFrameXM);
}
@@ -204,7 +201,8 @@ public:
{
return false;
}
} XZP = Z1 - 1;
}
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);
@@ -218,7 +216,9 @@ public:
{
return false;
}
} XZM = Z2 + 1;
}
XZM = Z2 + 1;
return (FoundFrameZP && FoundFrameZM);
}
};
+1 -1
View File
@@ -19,7 +19,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
// Reset meta to zero
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
+3 -3
View File
@@ -15,13 +15,13 @@ public:
: cBlockHandler(a_BlockType)
{
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
MTRand r1;
a_Pickups.push_back(cItem(E_ITEM_GLOWSTONE_DUST, (char)(2 + r1.randInt(2)), 0));
cFastRandom Random;
a_Pickups.push_back(cItem(E_ITEM_GLOWSTONE_DUST, (char)(2 + Random.NextInt(3)), 0));
}
} ;
+2 -4
View File
@@ -45,13 +45,11 @@
#include "BlockLadder.h"
#include "BlockLeaves.h"
#include "BlockLilypad.h"
#include "BlockNewLeaves.h"
#include "BlockLever.h"
#include "BlockMelon.h"
#include "BlockMushroom.h"
#include "BlockMycelium.h"
#include "BlockNetherWart.h"
#include "BlockNote.h"
#include "BlockOre.h"
#include "BlockPiston.h"
#include "BlockPlanks.h"
@@ -251,9 +249,9 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_NETHER_PORTAL: return new cBlockPortalHandler (a_BlockType);
case E_BLOCK_NETHER_WART: return new cBlockNetherWartHandler (a_BlockType);
case E_BLOCK_NETHER_QUARTZ_ORE: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_NEW_LEAVES: return new cBlockNewLeavesHandler (a_BlockType);
case E_BLOCK_NEW_LEAVES: return new cBlockLeavesHandler (a_BlockType);
case E_BLOCK_NEW_LOG: return new cBlockSidewaysHandler (a_BlockType);
case E_BLOCK_NOTE_BLOCK: return new cBlockNoteHandler (a_BlockType);
case E_BLOCK_NOTE_BLOCK: return new cBlockEntityHandler (a_BlockType);
case E_BLOCK_PISTON: return new cBlockPistonHandler (a_BlockType);
case E_BLOCK_PISTON_EXTENSION: return new cBlockPistonHeadHandler;
case E_BLOCK_PLANKS: return new cBlockPlanksHandler (a_BlockType);
+2 -2
View File
@@ -19,8 +19,8 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
MTRand r1;
a_Pickups.push_back(cItem(E_ITEM_MELON_SLICE, (char)(3 + r1.randInt(4)), 0));
cFastRandom Random;
a_Pickups.push_back(cItem(E_ITEM_MELON_SLICE, (char)(3 + Random.NextInt(5)), 0));
}
-42
View File
@@ -1,42 +0,0 @@
#pragma once
#include "BlockHandler.h"
#include "BlockLeaves.h"
#include "../World.h"
class cBlockNewLeavesHandler :
public cBlockLeavesHandler
{
public:
cBlockNewLeavesHandler(BLOCKTYPE a_BlockType)
: cBlockLeavesHandler(a_BlockType)
{
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
MTRand rand;
// Only the first 2 bits contain the display information, the others are for growing
if (rand.randInt(5) == 0)
{
a_Pickups.push_back(cItem(E_BLOCK_SAPLING, 1, (a_BlockMeta & 3) + 4));
}
}
void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override
{
cBlockHandler::OnDestroyed(a_ChunkInterface, a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ);
}
} ;
-13
View File
@@ -1,13 +0,0 @@
#pragma once
#include "BlockHandler.h"
#include "BlockEntity.h"
class cBlockNoteHandler : public cBlockEntityHandler
{
public:
cBlockNoteHandler(BLOCKTYPE a_BlockType)
: cBlockEntityHandler(a_BlockType)
{
}
};
+11 -29
View File
@@ -2,7 +2,6 @@
#pragma once
#include "BlockHandler.h"
#include "../MersenneTwister.h"
#include "../World.h"
@@ -20,58 +19,41 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
short ItemType = m_BlockType;
char Count = 1;
short Meta = 0;
MTRand r1;
cFastRandom Random;
switch (m_BlockType)
{
case E_BLOCK_LAPIS_ORE:
{
ItemType = E_ITEM_DYE;
Count = 4 + (char)r1.randInt(4);
Meta = 4;
a_Pickups.push_back(cItem(E_ITEM_DYE, (char)(4 + Random.NextInt(5)), 4));
break;
}
case E_BLOCK_REDSTONE_ORE:
case E_BLOCK_REDSTONE_ORE_GLOWING:
{
Count = 4 + (char)r1.randInt(1);
a_Pickups.push_back(cItem(E_ITEM_REDSTONE_DUST, (char)(4 + Random.NextInt(2)), 0));
break;
}
default:
{
Count = 1;
break;
}
}
switch (m_BlockType)
{
case E_BLOCK_DIAMOND_ORE:
{
ItemType = E_ITEM_DIAMOND;
break;
}
case E_BLOCK_REDSTONE_ORE:
case E_BLOCK_REDSTONE_ORE_GLOWING:
{
ItemType = E_ITEM_REDSTONE_DUST;
a_Pickups.push_back(cItem(E_ITEM_DIAMOND));
break;
}
case E_BLOCK_EMERALD_ORE:
{
ItemType = E_ITEM_EMERALD;
a_Pickups.push_back(cItem(E_ITEM_EMERALD));
break;
}
case E_BLOCK_COAL_ORE:
{
ItemType = E_ITEM_COAL;
a_Pickups.push_back(cItem(E_ITEM_COAL));
break;
}
default:
{
ASSERT(!"Unhandled ore!");
}
}
a_Pickups.push_back(cItem(ItemType, Count, Meta));
}
} ;
+1 -2
View File
@@ -24,8 +24,7 @@ public:
) override
{
a_BlockType = m_BlockType;
NIBBLETYPE Meta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage);
a_BlockMeta = Meta;
a_BlockMeta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage);
return true;
}
+4 -4
View File
@@ -36,7 +36,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
return; // No pickups
// 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
@@ -47,15 +47,15 @@ public:
return;
}
int PosX = a_Chunk.GetPosX() * 16 + a_RelX;
int PosZ = a_Chunk.GetPosZ() * 16 + a_RelZ;
int PosX = a_Chunk.GetPosX() * cChunkDef::Width + a_RelX;
int PosZ = a_Chunk.GetPosZ() * cChunkDef::Width + 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
{
if ((a_RelY - 1 < 0) || (a_RelY + 1 > cChunkDef::Height))
if ((a_RelY <= 0) || (a_RelY >= cChunkDef::Height))
{
return false; // In case someone places a portal with meta 1 or 2 at boundaries, and server tries to get invalid coords at Y - 1 or Y + 1
}
+2 -2
View File
@@ -17,7 +17,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
// Reset meta to zero
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
@@ -29,7 +29,7 @@ public:
}
BLOCKTYPE BlockBelow = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ);
return ((BlockBelow == E_BLOCK_FENCE_GATE) || (BlockBelow == E_BLOCK_FENCE) || cBlockInfo::IsSolid(BlockBelow));
return (cBlockInfo::IsSolid(BlockBelow));
}
} ;
+1
View File
@@ -25,6 +25,7 @@ public:
{
a_BlockType = m_BlockType;
NIBBLETYPE Meta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage);
if (Meta != E_META_QUARTZ_PILLAR) // Check if the block is a pillar block.
{
a_BlockMeta = Meta;
+2 -2
View File
@@ -26,8 +26,8 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
a_Pickups.push_back(cItem(E_ITEM_REDSTONE_DUST, 1));
// Reset meta to zero
a_Pickups.push_back(cItem(E_ITEM_REDSTONE_DUST, 1, 0));
}
} ;
+3 -3
View File
@@ -23,7 +23,7 @@ public:
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
) override
{
a_BlockType = m_BlockType;
a_BlockMeta = RepeaterRotationToMetaData(a_Player->GetYaw());
@@ -46,7 +46,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
// Reset meta to zero
a_Pickups.push_back(cItem(E_ITEM_REDSTONE_REPEATER, 1, 0));
}
@@ -59,7 +59,7 @@ public:
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) != E_BLOCK_AIR));
return ((a_RelY > 0) && cBlockInfo::IsSolid(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)));
}
+10 -10
View File
@@ -16,8 +16,8 @@ public:
{
}
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
@@ -53,8 +53,8 @@ public:
}
return true;
}
virtual const char * GetStepSound(void) override
{
if (
@@ -64,7 +64,7 @@ public:
(m_BlockType == E_BLOCK_ACACIA_WOOD_STAIRS) ||
(m_BlockType == E_BLOCK_BIRCH_WOOD_STAIRS) ||
(m_BlockType == E_BLOCK_DARK_OAK_WOOD_STAIRS)
)
)
{
return "step.wood";
}
@@ -72,17 +72,20 @@ public:
return "step.stone";
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
// Reset meta to zero
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
{
return true;
}
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{
a_Rotation += 90 + 45; // So its not aligned with axis
@@ -108,14 +111,11 @@ public:
}
}
virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) override
{
// Toggle bit 3:
return (a_Meta & 0x0b) | ((~a_Meta) & 0x04);
}
} ;
+1
View File
@@ -29,6 +29,7 @@ public:
{
return false;
}
switch (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ))
{
case E_BLOCK_DIRT:
+2 -2
View File
@@ -126,7 +126,7 @@ public:
(BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
(BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)) &&
(Face == BLOCK_FACE_TOP)
)
)
{
return Face;
}
@@ -162,7 +162,7 @@ public:
(BlockInQuestion == E_BLOCK_END_PORTAL_FRAME) || // Actual vanilla behaviour
(BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
(BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)
)
)
{
// Torches can be placed on tops of glass and fences, despite them being 'untorcheable'
// No need to check for upright orientation, it was done when the torch was placed
+5 -4
View File
@@ -23,7 +23,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
// Reset meta to zero
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
@@ -53,7 +53,7 @@ public:
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
) override
{
a_BlockType = m_BlockType;
a_BlockMeta = BlockFaceToMetaData(a_BlockFace);
@@ -103,9 +103,10 @@ public:
a_Chunk.UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ, Meta);
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
BLOCKTYPE BlockIsOn;
a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
return (a_RelY > 0) && cBlockInfo::IsSolid(BlockIsOn);
return ((a_RelY > 0) && cBlockInfo::IsSolid(BlockIsOn));
}
};
+5 -5
View File
@@ -21,10 +21,9 @@ public:
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
) override
{
a_BlockType = m_BlockType;
a_BlockMeta = DirectionToMetadata(a_BlockFace);
return true;
@@ -56,7 +55,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
// Reset meta to zero
a_Pickups.push_back(cItem(E_BLOCK_TRIPWIRE_HOOK, 1, 0));
}
@@ -66,9 +65,10 @@ public:
a_Chunk.UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ, Meta);
AddFaceDirection(a_RelX, a_RelY, a_RelZ, MetadataToDirection(Meta), true);
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
BLOCKTYPE BlockIsOn;
a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
return (a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(BlockIsOn);
return ((a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(BlockIsOn));
}
virtual const char * GetStepSound(void) override
+3 -3
View File
@@ -46,7 +46,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
// Reset meta to zero
a_Pickups.push_back(cItem(E_BLOCK_VINES, 1, 0));
}
@@ -80,7 +80,7 @@ public:
/// Returns true if the specified block type is good for vines to attach to
static bool IsBlockAttachable(BLOCKTYPE a_BlockType)
{
return (a_BlockType == E_BLOCK_LEAVES) || (a_BlockType == E_BLOCK_NEW_LEAVES) || cBlockInfo::IsSolid(a_BlockType);
return ((a_BlockType == E_BLOCK_LEAVES) || (a_BlockType == E_BLOCK_NEW_LEAVES) || cBlockInfo::IsSolid(a_BlockType));
}
@@ -182,7 +182,7 @@ public:
a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY - 1, a_RelZ, Block);
if (Block == E_BLOCK_AIR)
{
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread((cWorld*) &a_WorldInterface, a_RelX * cChunkDef::Width, a_RelY - 1, a_RelZ * cChunkDef::Width, ssVineSpread))
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread((cWorld*) &a_WorldInterface, a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY - 1, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, ssVineSpread))
{
a_Chunk.UnboundedRelSetBlock(a_RelX, a_RelY - 1, a_RelZ, E_BLOCK_VINES, a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
}
-2
View File
@@ -57,8 +57,6 @@ SET (HDRS
BlockMushroom.h
BlockMycelium.h
BlockNetherWart.h
BlockNewLeaves.h
BlockNote.h
BlockOre.h
BlockPiston.h
BlockPlanks.h
+1 -1
View File
@@ -27,7 +27,7 @@
)
#define IS_LITTLE_ENDIAN
#elif ( \
defined (__ARMEB__) || defined(__sparc) \
defined (__ARMEB__) || defined(__sparc) || defined(__powerpc__) || defined(__POWERPC__) \
)
#define IS_BIG_ENDIAN
#else
+8 -9
View File
@@ -1,6 +1,7 @@
cmake_minimum_required (VERSION 2.8.2)
project (MCServer)
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/")
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/jsoncpp/include")
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/polarssl/include")
@@ -33,16 +34,14 @@ SET (SRCS
FastRandom.cpp
FurnaceRecipe.cpp
Globals.cpp
Group.cpp
GroupManager.cpp
Inventory.cpp
Item.cpp
ItemGrid.cpp
LightingThread.cpp
LineBlockTracer.cpp
LinearInterpolation.cpp
Log.cpp
MCLogger.cpp
LoggerListeners.cpp
Logger.cpp
Map.cpp
MapManager.cpp
MobCensus.cpp
@@ -52,6 +51,7 @@ SET (SRCS
MonsterConfig.cpp
Noise.cpp
ProbabDistrib.cpp
RankManager.cpp
RCONServer.cpp
Root.cpp
Scoreboard.cpp
@@ -97,8 +97,6 @@ SET (HDRS
ForEachChunkProvider.h
FurnaceRecipe.h
Globals.h
Group.h
GroupManager.h
Inventory.h
Item.h
ItemGrid.h
@@ -107,8 +105,8 @@ SET (HDRS
LineBlockTracer.h
LinearInterpolation.h
LinearUpscale.h
Log.h
MCLogger.h
Logger.h
LoggerListeners.h
Map.h
MapManager.h
Matrix4.h
@@ -121,6 +119,7 @@ SET (HDRS
MonsterConfig.h
Noise.h
ProbabDistrib.h
RankManager.h
RCONServer.h
Root.h
Scoreboard.h
@@ -234,7 +233,7 @@ endif()
# Generate a list of all source files:
set(ALLFILES "")
set(ALLFILES "${SRCS}" "${HDRS}")
foreach(folder ${FOLDERS})
get_directory_property(FOLDER_SRCS DIRECTORY ${folder} DEFINITION SRCS)
foreach (src ${FOLDER_SRCS})
+17 -10
View File
@@ -1,3 +1,4 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#ifndef _WIN32
@@ -579,7 +580,7 @@ void cChunk::Tick(float a_Dt)
}
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
{
{
if (!((*itr)->IsMob())) // Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players)
{
// Tick all entities in this chunk (except mobs):
@@ -594,17 +595,19 @@ void cChunk::Tick(float a_Dt)
itr = m_Entities.erase(itr);
delete ToDelete;
}
else if ((*itr)->IsWorldTravellingFrom(m_World)) // Remove all entities that are travelling to another world:
else if ((*itr)->IsWorldTravellingFrom(m_World))
{
// Remove all entities that are travelling to another world
MarkDirty();
(*itr)->SetWorldTravellingFrom(NULL);
itr = m_Entities.erase(itr);
}
else if ( // If any entity moved out of the chunk, move it to the neighbor:
else if (
((*itr)->GetChunkX() != m_PosX) ||
((*itr)->GetChunkZ() != m_PosZ)
)
{
// The entity moved out of the chunk, move it to the neighbor
MarkDirty();
MoveEntityToNewChunk(*itr);
itr = m_Entities.erase(itr);
@@ -885,14 +888,14 @@ void cChunk::ApplyWeatherToTop()
SetBlock(X, Height, Z, E_BLOCK_ICE, 0);
}
else if (
(m_World->IsDeepSnowEnabled()) &&
(
(TopBlock == E_BLOCK_RED_ROSE) ||
(TopBlock == E_BLOCK_YELLOW_FLOWER) ||
(TopBlock == E_BLOCK_RED_MUSHROOM) ||
(TopBlock == E_BLOCK_BROWN_MUSHROOM)
)
(m_World->IsDeepSnowEnabled()) &&
(
(TopBlock == E_BLOCK_RED_ROSE) ||
(TopBlock == E_BLOCK_YELLOW_FLOWER) ||
(TopBlock == E_BLOCK_RED_MUSHROOM) ||
(TopBlock == E_BLOCK_BROWN_MUSHROOM)
)
)
{
SetBlock(X, Height, Z, E_BLOCK_SNOW, 0);
}
@@ -2142,10 +2145,14 @@ bool cChunk::DoWithRedstonePoweredEntityAt(int a_BlockX, int a_BlockY, int a_Blo
case E_BLOCK_DROPPER:
case E_BLOCK_DISPENSER:
case E_BLOCK_NOTE_BLOCK:
{
break;
}
default:
{
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
return false;
}
}
if (a_Callback.Item((cRedstonePoweredEntity *)*itr))
+1 -1
View File
@@ -241,7 +241,7 @@ public:
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
/** Calls the callback for the redstone powered entity at the specified coords; returns false if there's no redstone powered entity at those coords, true if found */
bool DoWithRedstonePoweredEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cRedstonePoweredCallback & a_Callback);
bool DoWithRedstonePoweredEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cRedstonePoweredCallback & a_Callback);
/** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Lua-acessible
+1 -1
View File
@@ -419,7 +419,7 @@ public:
X Data;
cCoordWithData(int a_X, int a_Y, int a_Z) :
x(a_X), y(a_Y), z(a_Z)
x(a_X), y(a_Y), z(a_Z), Data()
{
}
+37 -34
View File
@@ -75,11 +75,21 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) :
m_TimeSinceLastPacket(0),
m_Ping(1000),
m_PingID(1),
m_PingStartTime(0),
m_LastPingTime(1000),
m_BlockDigAnimStage(-1),
m_BlockDigAnimSpeed(0),
m_BlockDigAnimX(0),
m_BlockDigAnimY(256), // Invalid Y, so that the coords don't get picked up
m_BlockDigAnimZ(0),
m_HasStartedDigging(false),
m_LastDigBlockX(0),
m_LastDigBlockY(256), // Invalid Y, so that the coords don't get picked up
m_LastDigBlockZ(0),
m_State(csConnected),
m_ShouldCheckDownloaded(false),
m_NumExplosionsThisTick(0),
m_NumBlockChangeInteractionsThisTick(0),
m_UniqueID(0),
m_HasSentPlayerChunk(false),
m_Locale("en_GB")
@@ -912,19 +922,36 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eB
return;
}
if (
((a_Status == DIG_STATUS_STARTED) || (a_Status == DIG_STATUS_FINISHED)) && // Only do a radius check for block destruction - things like pickup tossing send coordinates that are to be ignored
((Diff(m_Player->GetPosX(), (double)a_BlockX) > 6) ||
(Diff(m_Player->GetPosY(), (double)a_BlockY) > 6) ||
(Diff(m_Player->GetPosZ(), (double)a_BlockZ) > 6))
)
if ((a_Status == DIG_STATUS_STARTED) || (a_Status == DIG_STATUS_FINISHED))
{
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
if (cBlockInfo::GetHandler(m_Player->GetWorld()->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ))->IsClickedThrough())
if (a_BlockFace == BLOCK_FACE_NONE)
{
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player);
return;
}
/* Check for clickthrough-blocks:
When the user breaks a fire block, the client send the wrong block location.
We must find the right block with the face direction. */
int BlockX = a_BlockX;
int BlockY = a_BlockY;
int BlockZ = a_BlockZ;
AddFaceDirection(BlockX, BlockY, BlockZ, a_BlockFace);
if (cBlockInfo::GetHandler(m_Player->GetWorld()->GetBlock(BlockX, BlockY, BlockZ))->IsClickedThrough())
{
a_BlockX = BlockX;
a_BlockY = BlockY;
a_BlockZ = BlockZ;
}
if (
((Diff(m_Player->GetPosX(), (double)a_BlockX) > 6) ||
(Diff(m_Player->GetPosY(), (double)a_BlockY) > 6) ||
(Diff(m_Player->GetPosZ(), (double)a_BlockZ) > 6))
)
{
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
return;
}
return;
}
cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager();
@@ -932,10 +959,6 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eB
{
// A plugin doesn't agree with the action, replace the block on the client and quit:
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
if (cBlockInfo::GetHandler(m_Player->GetWorld()->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ))->IsClickedThrough())
{
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player);
}
return;
}
@@ -1059,26 +1082,6 @@ void cClientHandle::HandleBlockDigStarted(int a_BlockX, int a_BlockY, int a_Bloc
m_LastDigBlockY = a_BlockY;
m_LastDigBlockZ = a_BlockZ;
// Check for clickthrough-blocks:
/* When the user breaks a fire block, the client send the wrong block location.
We must find the right block with the face direction. */
if (a_BlockFace != BLOCK_FACE_NONE)
{
int pX = a_BlockX;
int pY = a_BlockY;
int pZ = a_BlockZ;
AddFaceDirection(pX, pY, pZ, a_BlockFace); // Get the block in front of the clicked coordinates (m_bInverse defaulted to false)
cBlockHandler * Handler = cBlockInfo::GetHandler(m_Player->GetWorld()->GetBlock(pX, pY, pZ));
if (Handler->IsClickedThrough())
{
cChunkInterface ChunkInterface(m_Player->GetWorld()->GetChunkMap());
Handler->OnDigging(ChunkInterface, *m_Player->GetWorld(), m_Player, pX, pY, pZ);
return;
}
}
if (
(m_Player->IsGameModeCreative()) || // In creative mode, digging is done immediately
cBlockInfo::IsOneHitDig(a_OldBlock) // One-hit blocks get destroyed immediately, too
+12 -12
View File
@@ -353,23 +353,23 @@ AString cCompositeChat::ExtractText(void) const
cMCLogger::eLogLevel cCompositeChat::MessageTypeToLogLevel(eMessageType a_MessageType)
cLogger::eLogLevel cCompositeChat::MessageTypeToLogLevel(eMessageType a_MessageType)
{
switch (a_MessageType)
{
case mtCustom: return cMCLogger::llRegular;
case mtFailure: return cMCLogger::llWarning;
case mtInformation: return cMCLogger::llInfo;
case mtSuccess: return cMCLogger::llRegular;
case mtWarning: return cMCLogger::llWarning;
case mtFatal: return cMCLogger::llError;
case mtDeath: return cMCLogger::llRegular;
case mtPrivateMessage: return cMCLogger::llRegular;
case mtJoin: return cMCLogger::llRegular;
case mtLeave: return cMCLogger::llRegular;
case mtCustom: return cLogger::llRegular;
case mtFailure: return cLogger::llWarning;
case mtInformation: return cLogger::llInfo;
case mtSuccess: return cLogger::llRegular;
case mtWarning: return cLogger::llWarning;
case mtFatal: return cLogger::llError;
case mtDeath: return cLogger::llRegular;
case mtPrivateMessage: return cLogger::llRegular;
case mtJoin: return cLogger::llRegular;
case mtLeave: return cLogger::llRegular;
}
ASSERT(!"Unhandled MessageType");
return cMCLogger::llError;
return cLogger::llError;
}
+1 -1
View File
@@ -196,7 +196,7 @@ public:
/** Converts the MessageType to a LogLevel value.
Used by the logging bindings when logging a cCompositeChat object. */
static cMCLogger::eLogLevel MessageTypeToLogLevel(eMessageType a_MessageType);
static cLogger::eLogLevel MessageTypeToLogLevel(eMessageType a_MessageType);
protected:
/** All the parts that */
+3 -1
View File
@@ -21,7 +21,8 @@ const int CYCLE_MILLISECONDS = 100;
cDeadlockDetect::cDeadlockDetect(void) :
super("DeadlockDetect")
super("DeadlockDetect"),
m_IntervalSec(1000)
{
}
@@ -136,6 +137,7 @@ void cDeadlockDetect::CheckWorldAge(const AString & a_WorldName, Int64 a_Age)
void cDeadlockDetect::DeadlockDetected(void)
{
LOGERROR("Deadlock detected, aborting the server");
ASSERT(!"Deadlock detected");
abort();
}
+74 -209
View File
@@ -10,8 +10,6 @@
#include "../Bindings/PluginManager.h"
#include "../BlockEntities/BlockEntity.h"
#include "../BlockEntities/EnderChestEntity.h"
#include "../GroupManager.h"
#include "../Group.h"
#include "../Root.h"
#include "../OSSupport/Timer.h"
#include "../Chunk.h"
@@ -59,7 +57,6 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) :
m_EnderChestContents(9, 3),
m_CurrentWindow(NULL),
m_InventoryWindow(NULL),
m_Color('-'),
m_GameMode(eGameMode_NotSet),
m_IP(""),
m_ClientHandle(a_Client),
@@ -225,16 +222,24 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
SendExperience();
}
bool CanMove = true;
if (!GetPosition().EqualsEps(m_LastPos, 0.01)) // Non negligible change in position from last tick?
{
// Apply food exhaustion from movement:
ApplyFoodExhaustionFromMovement();
cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this);
if (cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this, m_LastPos, GetPosition()))
{
CanMove = false;
TeleportToCoords(m_LastPos.x, m_LastPos.y, m_LastPos.z);
}
m_ClientHandle->StreamChunks();
}
BroadcastMovementUpdate(m_ClientHandle);
if (CanMove)
{
BroadcastMovementUpdate(m_ClientHandle);
}
if (m_Health > 0) // make sure player is alive
{
@@ -884,7 +889,7 @@ void cPlayer::KilledBy(TakeDamageInfo & a_TDI)
Pickups.Add(cItem(E_ITEM_RED_APPLE));
}
m_Stats.AddValue(statItemsDropped, Pickups.Size());
m_Stats.AddValue(statItemsDropped, (StatValue)Pickups.Size());
m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 10);
SaveToDisk(); // Save it, yeah the world is a tough place !
@@ -1359,48 +1364,6 @@ void cPlayer::SetVisible(bool a_bVisible)
void cPlayer::AddToGroup( const AString & a_GroupName)
{
cGroup* Group = cRoot::Get()->GetGroupManager()->GetGroup( a_GroupName);
m_Groups.push_back( Group);
LOGD("Added %s to group %s", GetName().c_str(), a_GroupName.c_str());
ResolveGroups();
ResolvePermissions();
}
void cPlayer::RemoveFromGroup( const AString & a_GroupName)
{
bool bRemoved = false;
for (GroupList::iterator itr = m_Groups.begin(); itr != m_Groups.end(); ++itr)
{
if ((*itr)->GetName().compare(a_GroupName) == 0)
{
m_Groups.erase( itr);
bRemoved = true;
break;
}
}
if (bRemoved)
{
LOGD("Removed %s from group %s", GetName().c_str(), a_GroupName.c_str());
ResolveGroups();
ResolvePermissions();
}
else
{
LOGWARN("Tried to remove %s from group %s but was not in that group", GetName().c_str(), a_GroupName.c_str());
}
}
bool cPlayer::HasPermission(const AString & a_Permission)
{
if (a_Permission.empty())
@@ -1409,47 +1372,18 @@ bool cPlayer::HasPermission(const AString & a_Permission)
return true;
}
AStringVector Split = StringSplit( a_Permission, ".");
PermissionMap Possibilities = m_ResolvedPermissions;
// Now search the namespaces
while (Possibilities.begin() != Possibilities.end())
AStringVector Split = StringSplit(a_Permission, ".");
// Iterate over all granted permissions; if any matches, then return success:
for (AStringVectorVector::const_iterator itr = m_SplitPermissions.begin(), end = m_SplitPermissions.end(); itr != end; ++itr)
{
PermissionMap::iterator itr = Possibilities.begin();
if (itr->second)
if (PermissionMatches(Split, *itr))
{
AStringVector OtherSplit = StringSplit( itr->first, ".");
if (OtherSplit.size() <= Split.size())
{
unsigned int i;
for (i = 0; i < OtherSplit.size(); ++i)
{
if (OtherSplit[i].compare( Split[i]) != 0)
{
if (OtherSplit[i].compare("*") == 0) return true; // WildCard man!! WildCard!
break;
}
}
if (i == Split.size()) return true;
}
}
Possibilities.erase( itr);
}
// Nothing that matched :(
return false;
}
bool cPlayer::IsInGroup( const AString & a_Group)
{
for (GroupList::iterator itr = m_ResolvedGroups.begin(); itr != m_ResolvedGroups.end(); ++itr)
{
if (a_Group.compare( (*itr)->GetName().c_str()) == 0)
return true;
}
}
} // for itr - m_SplitPermissions[]
// No granted permission matches
return false;
}
@@ -1457,68 +1391,35 @@ bool cPlayer::IsInGroup( const AString & a_Group)
void cPlayer::ResolvePermissions()
bool cPlayer::PermissionMatches(const AStringVector & a_Permission, const AStringVector & a_Template)
{
m_ResolvedPermissions.clear(); // Start with an empty map
// Copy all player specific permissions into the resolved permissions map
for (PermissionMap::iterator itr = m_Permissions.begin(); itr != m_Permissions.end(); ++itr)
// Check the sub-items if they are the same or there's a wildcard:
size_t lenP = a_Permission.size();
size_t lenT = a_Template.size();
size_t minLen = std::min(lenP, lenT);
for (size_t i = 0; i < minLen; i++)
{
m_ResolvedPermissions[ itr->first ] = itr->second;
}
for (GroupList::iterator GroupItr = m_ResolvedGroups.begin(); GroupItr != m_ResolvedGroups.end(); ++GroupItr)
{
const cGroup::PermissionMap & Permissions = (*GroupItr)->GetPermissions();
for (cGroup::PermissionMap::const_iterator itr = Permissions.begin(); itr != Permissions.end(); ++itr)
if (a_Template[i] == "*")
{
m_ResolvedPermissions[ itr->first ] = itr->second;
// Has matched so far and now there's a wildcard in the template, so the permission matches:
return true;
}
if (a_Permission[i] != a_Template[i])
{
// Found a mismatch
return false;
}
}
}
void cPlayer::ResolveGroups()
{
// Clear resolved groups first
m_ResolvedGroups.clear();
// Get a complete resolved list of all groups the player is in
std::map< cGroup*, bool > AllGroups; // Use a map, because it's faster than iterating through a list to find duplicates
GroupList ToIterate;
for (GroupList::iterator GroupItr = m_Groups.begin(); GroupItr != m_Groups.end(); ++GroupItr)
// So far all the sub-items have matched
// If the sub-item count is the same, then the permission matches:
if (lenP == lenT)
{
ToIterate.push_back( *GroupItr);
}
while (ToIterate.begin() != ToIterate.end())
{
cGroup* CurrentGroup = *ToIterate.begin();
if (AllGroups.find( CurrentGroup) != AllGroups.end())
{
LOGWARNING("ERROR: Player \"%s\" is in the group multiple times (\"%s\"). Please fix your settings in users.ini!",
GetName().c_str(), CurrentGroup->GetName().c_str()
);
}
else
{
AllGroups[ CurrentGroup ] = true;
m_ResolvedGroups.push_back( CurrentGroup); // Add group to resolved list
const cGroup::GroupList & Inherits = CurrentGroup->GetInherits();
for (cGroup::GroupList::const_iterator itr = Inherits.begin(); itr != Inherits.end(); ++itr)
{
if (AllGroups.find( *itr) != AllGroups.end())
{
LOGERROR("ERROR: Player %s is in the same group multiple times due to inheritance (%s). FIX IT!", GetName().c_str(), (*itr)->GetName().c_str());
continue;
}
ToIterate.push_back( *itr);
}
}
ToIterate.erase( ToIterate.begin());
return true;
}
// There are more sub-items in either the permission or the template, not a match:
return false;
}
@@ -1527,17 +1428,14 @@ void cPlayer::ResolveGroups()
AString cPlayer::GetColor(void) const
{
if (m_Color != '-')
if (m_MsgNameColorCode.empty() || (m_MsgNameColorCode == "-"))
{
return cChatColor::Delimiter + m_Color;
// Color has not been assigned, return an empty string:
return AString();
}
if (m_Groups.size() < 1)
{
return cChatColor::White;
}
return (*m_Groups.begin())->GetColor();
// Return the color, including the delimiter:
return cChatColor::Delimiter + m_MsgNameColorCode;
}
@@ -1610,7 +1508,7 @@ void cPlayer::TossPickup(const cItem & a_Item)
void cPlayer::TossItems(const cItems & a_Items)
{
m_Stats.AddValue(statItemsDropped, a_Items.Size());
m_Stats.AddValue(statItemsDropped, (StatValue)a_Items.Size());
double vX = 0, vY = 0, vZ = 0;
EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY);
@@ -1653,48 +1551,9 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
void cPlayer::LoadPermissionsFromDisk()
{
m_Groups.clear();
m_Permissions.clear();
cIniFile IniFile;
if (IniFile.ReadFile("users.ini"))
{
AString Groups = IniFile.GetValueSet(GetName(), "Groups", "Default");
AStringVector Split = StringSplitAndTrim(Groups, ",");
for (AStringVector::const_iterator itr = Split.begin(), end = Split.end(); itr != end; ++itr)
{
if (!cRoot::Get()->GetGroupManager()->ExistsGroup(*itr))
{
LOGWARNING("The group %s for player %s was not found!", itr->c_str(), GetName().c_str());
}
AddToGroup(*itr);
}
AString Color = IniFile.GetValue(GetName(), "Color", "-");
if (!Color.empty())
{
m_Color = Color[0];
}
}
else
{
cGroupManager::GenerateDefaultUsersIni(IniFile);
IniFile.AddValue("Groups", GetName(), "Default");
AddToGroup("Default");
}
IniFile.WriteFile("users.ini");
ResolvePermissions();
}
bool cPlayer::LoadFromDisk(cWorldPtr & a_World)
{
LoadPermissionsFromDisk();
LoadRank();
// Load from the UUID file:
if (LoadFromFile(GetUUIDFileName(m_UUID), a_World))
@@ -1834,6 +1693,7 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
bool cPlayer::SaveToDisk()
{
cFile::CreateFolder(FILE_IO_PREFIX + AString("players/")); // Create the "players" folder, if it doesn't exist yet (#1268)
cFile::CreateFolder(FILE_IO_PREFIX + AString("players/") + m_UUID.substr(0, 2));
// create the JSON data
@@ -1928,26 +1788,6 @@ bool cPlayer::SaveToDisk()
cPlayer::StringList cPlayer::GetResolvedPermissions()
{
StringList Permissions;
const PermissionMap& ResolvedPermissions = m_ResolvedPermissions;
for (PermissionMap::const_iterator itr = ResolvedPermissions.begin(); itr != ResolvedPermissions.end(); ++itr)
{
if (itr->second)
{
Permissions.push_back( itr->first);
}
}
return Permissions;
}
void cPlayer::UseEquippedItem(int a_Amount)
{
if (IsGameModeCreative()) // No damage in creative
@@ -2206,6 +2046,31 @@ void cPlayer::ApplyFoodExhaustionFromMovement()
void cPlayer::LoadRank(void)
{
// Load the values from cRankManager:
cRankManager & RankMgr = cRoot::Get()->GetRankManager();
m_Rank = RankMgr.GetPlayerRankName(m_UUID);
if (m_Rank.empty())
{
m_Rank = RankMgr.GetDefaultRank();
}
m_Permissions = RankMgr.GetPlayerPermissions(m_UUID);
RankMgr.GetRankVisuals(m_Rank, m_MsgPrefix, m_MsgSuffix, m_MsgNameColorCode);
// Break up the individual permissions on each dot, into m_SplitPermissions:
m_SplitPermissions.clear();
m_SplitPermissions.reserve(m_Permissions.size());
for (AStringVector::const_iterator itr = m_Permissions.begin(), end = m_Permissions.end(); itr != end; ++itr)
{
m_SplitPermissions.push_back(StringSplit(*itr, "."));
} // for itr - m_Permissions[]
}
void cPlayer::Detach()
{
super::Detach();
+30 -24
View File
@@ -13,7 +13,6 @@
class cGroup;
class cWindow;
class cClientHandle;
class cTeam;
@@ -236,24 +235,20 @@ public:
// tolua_end
typedef std::list< cGroup* > GroupList;
typedef std::list< std::string > StringList;
bool HasPermission(const AString & a_Permission); // tolua_export
/** Adds a player to existing group or creates a new group when it doesn't exist */
void AddToGroup( const AString & a_GroupName); // tolua_export
/** Removes a player from the group, resolves permissions and group inheritance (case sensitive) */
void RemoveFromGroup( const AString & a_GroupName); // tolua_export
bool HasPermission( const AString & a_Permission); // tolua_export
const GroupList & GetGroups() { return m_Groups; } // >> EXPORTED IN MANUALBINDINGS <<
StringList GetResolvedPermissions(); // >> EXPORTED IN MANUALBINDINGS <<
bool IsInGroup( const AString & a_Group); // tolua_export
/** Returns true iff a_Permission matches the a_Template.
A match is defined by either being exactly the same, or each sub-item matches until there's a wildcard in a_Template.
Ie. {"a", "b", "c"} matches {"a", "b", "*"} but doesn't match {"a", "b"} */
static bool PermissionMatches(const AStringVector & a_Permission, const AStringVector & a_Template); // Exported in ManualBindings with AString params
/** Returns all the permissions that the player has assigned to them. */
const AStringVector & GetPermissions(void) { return m_Permissions; } // Exported in ManualBindings.cpp
// tolua_begin
/** Returns the full color code to use for this player, based on their primary group or set in m_Color.
The returned value includes the cChatColor::Delimiter. */
/** Returns the full color code to use for this player, based on their rank.
The returned value either is empty, or includes the cChatColor::Delimiter. */
AString GetColor(void) const;
/** tosses the item in the selected hotbar slot */
@@ -347,8 +342,6 @@ public:
*/
bool LoadFromFile(const AString & a_FileName, cWorldPtr & a_World);
void LoadPermissionsFromDisk(void); // tolua_export
const AString & GetLoadedWorldName() { return m_LoadedWorldName; }
void UseEquippedItem(int a_Amount = 1);
@@ -422,6 +415,11 @@ public:
/** Returns the UUID (short format) that has been read from the client, or empty string if not available. */
const AString & GetUUID(void) const { return m_UUID; }
/** (Re)loads the rank and permissions from the cRankManager.
Expects the m_UUID member to be valid.
Loads the m_Rank, m_Permissions, m_MsgPrefix, m_MsgSuffix and m_MsgNameColorCode members. */
void LoadRank(void);
// tolua_end
// cEntity overrides:
@@ -432,12 +430,22 @@ public:
virtual void Detach(void);
protected:
typedef std::map< std::string, bool > PermissionMap;
PermissionMap m_ResolvedPermissions;
PermissionMap m_Permissions;
GroupList m_ResolvedGroups;
GroupList m_Groups;
typedef std::vector<std::vector<AString> > AStringVectorVector;
/** The name of the rank assigned to this player. */
AString m_Rank;
/** All the permissions that this player has, based on their rank. */
AStringVector m_Permissions;
/** All the permissions that this player has, based on their rank, split into individual dot-delimited parts.
This is used mainly by the HasPermission() function to optimize the lookup. */
AStringVectorVector m_SplitPermissions;
// Message visuals:
AString m_MsgPrefix, m_MsgSuffix;
AString m_MsgNameColorCode;
AString m_PlayerName;
AString m_LoadedWorldName;
@@ -482,8 +490,6 @@ protected:
/** The player's last saved bed position */
Vector3i m_LastBedPos;
char m_Color;
eGameMode m_GameMode;
AString m_IP;
+1 -1
View File
@@ -45,7 +45,7 @@ public:
float NextFloat(float a_Range, int a_Salt);
/** Returns a random float between 0 and 1. */
float NextFloat(void) { return NextFloat(1); };
float NextFloat(void) { return NextFloat(1); }
/** Returns a random int in the range [a_Begin .. a_End] */
int GenerateRandomInteger(int a_Begin, int a_End);
+2
View File
@@ -12,6 +12,7 @@ SET (SRCS
CompoGen.cpp
ComposableGenerator.cpp
DistortedHeightmap.cpp
DungeonRoomsFinisher.cpp
EndGen.cpp
FinishGen.cpp
GridStructGen.cpp
@@ -40,6 +41,7 @@ SET (HDRS
CompoGen.h
ComposableGenerator.h
DistortedHeightmap.h
DungeonRoomsFinisher.h
EndGen.h
FinishGen.h
GridStructGen.h
+3
View File
@@ -166,6 +166,9 @@ cCaveTunnel::cCaveTunnel(
if ((a_BlockStartY <= 0) && (a_BlockEndY <= 0))
{
// Don't bother detailing this cave, it's under the world anyway
m_MinBlockX = m_MaxBlockX = 0;
m_MinBlockY = m_MaxBlockY = -1;
m_MinBlockZ = m_MaxBlockZ = 0;
return;
}
+1
View File
@@ -27,6 +27,7 @@ const unsigned int QUEUE_SKIP_LIMIT = 500;
cChunkGenerator::cChunkGenerator(void) :
super("cChunkGenerator"),
m_Seed(0), // Will be overwritten by the actual generator
m_Generator(NULL),
m_PluginInterface(NULL),
m_ChunkSink(NULL)
+9
View File
@@ -19,6 +19,7 @@
#include "Caves.h"
#include "DistortedHeightmap.h"
#include "DungeonRoomsFinisher.h"
#include "EndGen.h"
#include "MineShafts.h"
#include "NetherFortGen.h"
@@ -343,6 +344,14 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
float Threshold = (float)a_IniFile.GetValueSetF("Generator", "DualRidgeCavesThreshold", 0.3);
m_FinishGens.push_back(new cStructGenDualRidgeCaves(Seed, Threshold));
}
else if (NoCaseCompare(*itr, "DungeonRooms") == 0)
{
int GridSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsGridSize", 48);
int MaxSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsMaxSize", 7);
int MinSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsMinSize", 5);
AString HeightDistrib = a_IniFile.GetValueSet ("Generator", "DungeonRoomsHeightDistrib", "0, 0; 10, 10; 11, 500; 40, 500; 60, 40; 90, 1");
m_FinishGens.push_back(new cDungeonRoomsFinisher(*m_HeightGen, Seed, GridSize, MaxSize, MinSize, HeightDistrib));
}
else if (NoCaseCompare(*itr, "Ice") == 0)
{
m_FinishGens.push_back(new cFinishGenIce);
+279
View File
@@ -0,0 +1,279 @@
// DungeonRoomsFinisher.cpp
// Declares the cDungeonRoomsFinisher class representing the finisher that generates dungeon rooms
#include "Globals.h"
#include "DungeonRoomsFinisher.h"
#include "../FastRandom.h"
/** Height, in blocks, of the internal dungeon room open space. This many air blocks Y-wise. */
static const int ROOM_HEIGHT = 4;
////////////////////////////////////////////////////////////////////////////////
// cDungeonRoom:
class cDungeonRoom :
public cGridStructGen::cStructure
{
typedef cGridStructGen::cStructure super;
public:
cDungeonRoom(
int a_GridX, int a_GridZ,
int a_OriginX, int a_OriginZ,
int a_HalfSizeX, int a_HalfSizeZ,
int a_FloorHeight,
cNoise & a_Noise
) :
super(a_GridX, a_GridZ, a_OriginX, a_OriginZ),
m_StartX(a_OriginX - a_HalfSizeX),
m_EndX(a_OriginX + a_HalfSizeX),
m_StartZ(a_OriginZ - a_HalfSizeZ),
m_EndZ(a_OriginZ + a_HalfSizeZ),
m_FloorHeight(a_FloorHeight)
{
/*
Pick coords next to the wall for the chests.
This is done by indexing the possible coords, picking any one for the first chest
and then picking another position for the second chest that is not adjacent to the first pos
*/
int rnd = a_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 7;
int SizeX = m_EndX - m_StartX - 1;
int SizeZ = m_EndZ - m_StartZ - 1;
int NumPositions = 2 * SizeX + 2 * SizeZ;
int FirstChestPos = rnd % NumPositions; // The corner positions are a bit more likely, but we don't mind
rnd = rnd / 512;
int SecondChestPos = (FirstChestPos + 2 + (rnd % (NumPositions - 3))) % NumPositions;
m_Chest1 = DecodeChestCoords(FirstChestPos, SizeX, SizeZ);
m_Chest2 = DecodeChestCoords(SecondChestPos, SizeX, SizeZ);
}
protected:
// The X range of the room, start inclusive, end exclusive:
int m_StartX, m_EndX;
// The Z range of the room, start inclusive, end exclusive:
int m_StartZ, m_EndZ;
/** The Y coord of the floor of the room */
int m_FloorHeight;
/** The (absolute) coords of the first chest. The Y coord represents the chest's Meta value (facing). */
Vector3i m_Chest1;
/** The (absolute) coords of the second chest. The Y coord represents the chest's Meta value (facing). */
Vector3i m_Chest2;
/** Decodes the position index along the room walls into a proper 2D position for a chest. */
Vector3i DecodeChestCoords(int a_PosIdx, int a_SizeX, int a_SizeZ)
{
if (a_PosIdx < a_SizeX)
{
// Return a coord on the ZM side of the room:
return Vector3i(m_StartX + a_PosIdx + 1, E_META_CHEST_FACING_ZP, m_StartZ + 1);
}
a_PosIdx -= a_SizeX;
if (a_PosIdx < a_SizeZ)
{
// Return a coord on the XP side of the room:
return Vector3i(m_EndX - 1, E_META_CHEST_FACING_XM, m_StartZ + a_PosIdx + 1);
}
a_PosIdx -= a_SizeZ;
if (a_PosIdx < a_SizeX)
{
// Return a coord on the ZP side of the room:
return Vector3i(m_StartX + a_PosIdx + 1, E_META_CHEST_FACING_ZM, m_StartZ + 1);
}
a_PosIdx -= a_SizeX;
// Return a coord on the XM side of the room:
return Vector3i(m_StartX + 1, E_META_CHEST_FACING_XP, m_StartZ + a_PosIdx + 1);
}
/** Fills the specified area of blocks in the chunk with the specified blocktype if they are one of the overwritten block types.
The coords are absolute, start coords are inclusive, end coords are exclusive. */
void ReplaceCuboid(cChunkDesc & a_ChunkDesc, int a_StartX, int a_StartY, int a_StartZ, int a_EndX, int a_EndY, int a_EndZ, BLOCKTYPE a_DstBlockType)
{
int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
int RelStartX = Clamp(a_StartX - BlockX, 0, cChunkDef::Width - 1);
int RelStartZ = Clamp(a_StartZ - BlockZ, 0, cChunkDef::Width - 1);
int RelEndX = Clamp(a_EndX - BlockX, 0, cChunkDef::Width);
int RelEndZ = Clamp(a_EndZ - BlockZ, 0, cChunkDef::Width);
for (int y = a_StartY; y < a_EndY; y++)
{
for (int z = RelStartZ; z < RelEndZ; z++)
{
for (int x = RelStartX; x < RelEndX; x++)
{
if (cBlockInfo::CanBeTerraformed(a_ChunkDesc.GetBlockType(x, y, z)))
{
a_ChunkDesc.SetBlockType(x, y, z, a_DstBlockType);
}
} // for x
} // for z
} // for z
}
/** Fills the specified area of blocks in the chunk with a random pattern of the specified blocktypes, if they are one of the overwritten block types.
The coords are absolute, start coords are inclusive, end coords are exclusive. The first blocktype uses 75% chance, the second 25% chance. */
void ReplaceCuboidRandom(cChunkDesc & a_ChunkDesc, int a_StartX, int a_StartY, int a_StartZ, int a_EndX, int a_EndY, int a_EndZ, BLOCKTYPE a_DstBlockType1, BLOCKTYPE a_DstBlockType2)
{
int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
int RelStartX = Clamp(a_StartX - BlockX, 0, cChunkDef::Width - 1);
int RelStartZ = Clamp(a_StartZ - BlockZ, 0, cChunkDef::Width - 1);
int RelEndX = Clamp(a_EndX - BlockX, 0, cChunkDef::Width);
int RelEndZ = Clamp(a_EndZ - BlockZ, 0, cChunkDef::Width);
cFastRandom rnd;
for (int y = a_StartY; y < a_EndY; y++)
{
for (int z = RelStartZ; z < RelEndZ; z++)
{
for (int x = RelStartX; x < RelEndX; x++)
{
if (cBlockInfo::CanBeTerraformed(a_ChunkDesc.GetBlockType(x, y, z)))
{
BLOCKTYPE BlockType = (rnd.NextInt(101) < 75) ? a_DstBlockType1 : a_DstBlockType2;
a_ChunkDesc.SetBlockType(x, y, z, BlockType);
}
} // for x
} // for z
} // for z
}
/** Tries to place a chest at the specified (absolute) coords.
Does nothing if the coords are outside the chunk. */
void TryPlaceChest(cChunkDesc & a_ChunkDesc, const Vector3i & a_Chest)
{
int RelX = a_Chest.x - a_ChunkDesc.GetChunkX() * cChunkDef::Width;
int RelZ = a_Chest.z - a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
if (
(RelX < 0) || (RelX >= cChunkDef::Width) || // The X coord is not in this chunk
(RelZ < 0) || (RelZ >= cChunkDef::Width) // The Z coord is not in this chunk
)
{
return;
}
a_ChunkDesc.SetBlockTypeMeta(RelX, m_FloorHeight + 1, RelZ, E_BLOCK_CHEST, (NIBBLETYPE)a_Chest.y);
// TODO: Fill the chest with random loot
}
// cGridStructGen::cStructure override:
virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override
{
if (
(m_EndX < a_ChunkDesc.GetChunkX() * cChunkDef::Width) ||
(m_StartX >= a_ChunkDesc.GetChunkX() * cChunkDef::Width + cChunkDef::Width) ||
(m_EndZ < a_ChunkDesc.GetChunkZ() * cChunkDef::Width) ||
(m_StartZ >= a_ChunkDesc.GetChunkZ() * cChunkDef::Width + cChunkDef::Width)
)
{
// The chunk is not intersecting the room at all, bail out
return;
}
int b = m_FloorHeight + 1; // Bottom
int t = m_FloorHeight + 1 + ROOM_HEIGHT; // Top
ReplaceCuboidRandom(a_ChunkDesc, m_StartX, m_FloorHeight, m_StartZ, m_EndX + 1, b, m_EndZ + 1, E_BLOCK_MOSSY_COBBLESTONE, E_BLOCK_COBBLESTONE); // Floor
ReplaceCuboid(a_ChunkDesc, m_StartX + 1, b, m_StartZ + 1, m_EndX, t, m_EndZ, E_BLOCK_AIR); // Insides
// Walls:
ReplaceCuboid(a_ChunkDesc, m_StartX, b, m_StartZ, m_StartX + 1, t, m_EndZ, E_BLOCK_COBBLESTONE); // XM wall
ReplaceCuboid(a_ChunkDesc, m_EndX, b, m_StartZ, m_EndX + 1, t, m_EndZ, E_BLOCK_COBBLESTONE); // XP wall
ReplaceCuboid(a_ChunkDesc, m_StartX, b, m_StartZ, m_EndX + 1, t, m_StartZ + 1, E_BLOCK_COBBLESTONE); // ZM wall
ReplaceCuboid(a_ChunkDesc, m_StartX, b, m_EndZ, m_EndX + 1, t, m_EndZ + 1, E_BLOCK_COBBLESTONE); // ZP wall
// Place chests:
TryPlaceChest(a_ChunkDesc, m_Chest1);
TryPlaceChest(a_ChunkDesc, m_Chest2);
// Place the spawner:
int CenterX = (m_StartX + m_EndX) / 2 - a_ChunkDesc.GetChunkX() * cChunkDef::Width;
int CenterZ = (m_StartZ + m_EndZ) / 2 - a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
if (
(CenterX >= 0) && (CenterX < cChunkDef::Width) &&
(CenterZ >= 0) && (CenterZ < cChunkDef::Width)
)
{
a_ChunkDesc.SetBlockTypeMeta(CenterX, b, CenterZ, E_BLOCK_MOB_SPAWNER, 0);
// TODO: Set the spawned mob
}
}
} ;
////////////////////////////////////////////////////////////////////////////////
// cDungeonRoomsFinisher:
cDungeonRoomsFinisher::cDungeonRoomsFinisher(cTerrainHeightGen & a_HeightGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib) :
super(a_Seed + 100, a_GridSize, a_GridSize, a_GridSize, a_GridSize, a_MaxSize, a_MaxSize, 1024),
m_HeightGen(a_HeightGen),
m_MaxHalfSize((a_MaxSize + 1) / 2),
m_MinHalfSize((a_MinSize + 1) / 2),
m_HeightProbability(cChunkDef::Height)
{
// Initialize the height probability distribution:
m_HeightProbability.SetDefString(a_HeightDistrib);
// Normalize the min and max size:
if (m_MinHalfSize > m_MaxHalfSize)
{
std::swap(m_MinHalfSize, m_MaxHalfSize);
}
}
cDungeonRoomsFinisher::cStructurePtr cDungeonRoomsFinisher::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ)
{
// Select a random room size in each direction:
int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 7;
int HalfSizeX = m_MinHalfSize + (rnd % (m_MaxHalfSize - m_MinHalfSize + 1));
rnd = rnd / 32;
int HalfSizeZ = m_MinHalfSize + (rnd % (m_MaxHalfSize - m_MinHalfSize + 1));
rnd = rnd / 32;
// Select a random floor height for the room, based on the height generator:
int ChunkX, ChunkZ;
int RelX = a_OriginX, RelY = 0, RelZ = a_OriginZ;
cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ);
cChunkDef::HeightMap HeightMap;
m_HeightGen.GenHeightMap(ChunkX, ChunkZ, HeightMap);
int Height = cChunkDef::GetHeight(HeightMap, RelX, RelZ); // Max room height at {a_OriginX, a_OriginZ}
Height = Clamp(m_HeightProbability.MapValue(rnd % m_HeightProbability.GetSum()), 10, Height - 5);
// Create the dungeon room descriptor:
return cStructurePtr(new cDungeonRoom(a_GridX, a_GridZ, a_OriginX, a_OriginZ, HalfSizeX, HalfSizeZ, Height, m_Noise));
}
+52
View File
@@ -0,0 +1,52 @@
// DungeonRoomsFinisher.h
// Declares the cDungeonRoomsFinisher class representing the finisher that generates dungeon rooms
#pragma once
#include "GridStructGen.h"
#include "../ProbabDistrib.h"
class cDungeonRoomsFinisher :
public cGridStructGen
{
typedef cGridStructGen super;
public:
/** Creates a new dungeon room finisher.
a_HeightGen is the underlying height generator, so that the rooms can always be placed under the terrain.
a_MaxSize and a_MinSize are the maximum and minimum sizes of the room's internal (air) area, in blocks across.
a_HeightDistrib is the string defining the height distribution for the rooms (cProbabDistrib format). */
cDungeonRoomsFinisher(cTerrainHeightGen & a_HeightGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib);
protected:
/** The height gen that is used for limiting the rooms' Y coords */
cTerrainHeightGen & m_HeightGen;
/** Maximum half-size (from center to wall) of the dungeon room's inner (air) area. Default is 3 (vanilla). */
int m_MaxHalfSize;
/** Minimum half-size (from center to wall) of the dungeon room's inner (air) area. Default is 2 (vanilla). */
int m_MinHalfSize;
/** The height probability distribution to make the spawners more common in layers 10 - 40, less common outside this range. */
cProbabDistrib m_HeightProbability;
// cGridStructGen overrides:
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override;
} ;
+8 -2
View File
@@ -239,7 +239,13 @@ bool cHeiGenCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_Rel
cHeiGenClassic::cHeiGenClassic(int a_Seed) :
m_Seed(a_Seed),
m_Noise(a_Seed)
m_Noise(a_Seed),
m_HeightFreq1(1.0f),
m_HeightAmp1(1.0f),
m_HeightFreq2(0.5f),
m_HeightAmp2(0.5f),
m_HeightFreq3(0.1f),
m_HeightAmp3(0.1f)
{
}
@@ -432,7 +438,7 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] =
/* biExtremeHillsM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 131
/* biFlowerForest */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 132
/* biTaigaM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 133
/* biSwamplandM */ { 1.0f, 2.0f, 1.10f, 5.0f, 0.01f, 8.0f, 60}, // 134
/* biSwamplandM */ { 1.0f, 3.0f, 1.10f, 7.0f, 0.01f, 0.01f, 60}, // 134
// Biomes 135 .. 139 unused, 5 empty placeholders here:
{}, {}, {}, {}, {}, // 135 .. 139
+1 -1
View File
@@ -249,7 +249,7 @@ template class SizeChecker<UInt16, 2>;
#include "OSSupport/Event.h"
#include "OSSupport/Thread.h"
#include "OSSupport/File.h"
#include "MCLogger.h"
#include "Logger.h"
#else
// Logging functions
void inline LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2);
-41
View File
@@ -1,41 +0,0 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Group.h"
void cGroup::AddCommand( const AString & a_Command)
{
m_Commands[ a_Command ] = true;
}
void cGroup::AddPermission( const AString & a_Permission)
{
m_Permissions[ a_Permission ] = true;
}
void cGroup::InheritFrom( cGroup* a_Group)
{
m_Inherits.remove( a_Group);
m_Inherits.push_back( a_Group);
}
void cGroup::ClearPermission()
{
m_Permissions.clear();
}
-44
View File
@@ -1,44 +0,0 @@
#pragma once
// tolua_begin
class cGroup
{
public:
// tolua_end
cGroup() {}
~cGroup() {}
// tolua_begin
void SetName( const AString & a_Name) { m_Name = a_Name; }
const AString & GetName() const { return m_Name; }
void SetColor( const AString & a_Color) { m_Color = a_Color; }
void AddCommand( const AString & a_Command);
void AddPermission( const AString & a_Permission);
void InheritFrom( cGroup* a_Group);
// tolua_end
typedef std::map< AString, bool > PermissionMap;
const PermissionMap & GetPermissions() const { return m_Permissions; }
void ClearPermission(void);
typedef std::map< AString, bool > CommandMap;
const CommandMap & GetCommands() const { return m_Commands; }
const AString & GetColor() const { return m_Color; } // tolua_export
typedef std::list< cGroup* > GroupList;
const GroupList & GetInherits() const { return m_Inherits; }
private:
AString m_Name;
AString m_Color;
PermissionMap m_Permissions;
CommandMap m_Commands;
GroupList m_Inherits;
}; // tolua_export
-227
View File
@@ -1,227 +0,0 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "GroupManager.h"
#include "Group.h"
#include "inifile/iniFile.h"
#include "ChatColor.h"
#include "Root.h"
typedef std::map< AString, cGroup* > GroupMap;
struct cGroupManager::sGroupManagerState
{
GroupMap Groups;
};
cGroupManager::~cGroupManager()
{
for (GroupMap::iterator itr = m_pState->Groups.begin(); itr != m_pState->Groups.end(); ++itr)
{
delete itr->second;
itr->second = NULL;
}
m_pState->Groups.clear();
delete m_pState;
m_pState = NULL;
}
cGroupManager::cGroupManager()
: m_pState( new sGroupManagerState)
{
LOGD("-- Loading Groups --");
if (!LoadGroups())
{
LOGWARNING("ERROR: Groups could not load!");
}
if (!CheckUsers())
{
LOGWARNING("ERROR: User file could not be found!");
}
LOGD("-- Groups Successfully Loaded --");
}
void cGroupManager::GenerateDefaultUsersIni(cIniFile & a_IniFile)
{
LOGWARN("Regenerating users.ini, all users will be reset");
a_IniFile.AddHeaderComment(" This file stores the players' groups.");
a_IniFile.AddHeaderComment(" The format is:");
a_IniFile.AddHeaderComment(" [PlayerName]");
a_IniFile.AddHeaderComment(" Groups = GroupName1, GroupName2, ...");
a_IniFile.WriteFile("users.ini");
}
bool cGroupManager::CheckUsers()
{
cIniFile IniFile;
if (!IniFile.ReadFile("users.ini"))
{
GenerateDefaultUsersIni(IniFile);
return true;
}
int NumKeys = IniFile.GetNumKeys();
for (int i = 0; i < NumKeys; i++)
{
AString Player = IniFile.GetKeyName(i);
AString Groups = IniFile.GetValue(Player, "Groups", "");
if (Groups.empty())
{
continue;
}
AStringVector Split = StringSplitAndTrim(Groups, ",");
for (AStringVector::const_iterator itr = Split.begin(), end = Split.end(); itr != end; ++itr)
{
if (!ExistsGroup(*itr))
{
LOGWARNING("The group %s for player %s was not found!", Split[i].c_str(), Player.c_str());
}
} // for itr - Split[]
} // for i - ini file keys
// Always return true for now, just but we can handle writefile fails later.
return true;
}
bool cGroupManager::LoadGroups()
{
cIniFile IniFile;
if (!IniFile.ReadFile("groups.ini"))
{
LOGWARNING("Regenerating groups.ini, all groups will be reset");
IniFile.AddHeaderComment(" This is the MCServer permissions manager groups file");
IniFile.AddHeaderComment(" It stores all defined groups such as Administrators, Players, or Moderators");
IniFile.SetValue("Owner", "Permissions", "*", true);
IniFile.SetValue("Owner", "Color", "2", true);
IniFile.SetValue("Moderator", "Permissions", "core.time, core.item, core.tpa, core.tpaccept, core.ban, core.unban, core.save-all, core.toggledownfall");
IniFile.SetValue("Moderator", "Color", "2", true);
IniFile.SetValue("Moderator", "Inherits", "Player", true);
IniFile.SetValue("Player", "Permissions", "core.portal", true);
IniFile.SetValue("Player", "Color", "f", true);
IniFile.SetValue("Player", "Inherits", "Default", true);
IniFile.SetValue("Default", "Permissions", "core.help, core.plugins, core.spawn, core.worlds, core.back, core.motd, core.build, core.locate, core.viewdistance", true);
IniFile.SetValue("Default", "Color", "f", true);
IniFile.WriteFile("groups.ini");
}
int NumKeys = IniFile.GetNumKeys();
for (int i = 0; i < NumKeys; i++)
{
AString KeyName = IniFile.GetKeyName(i);
cGroup * Group = GetGroup(KeyName.c_str());
Group->ClearPermission(); // Needed in case the groups are reloaded.
LOGD("Loading group %s", KeyName.c_str());
Group->SetName(KeyName);
AString Color = IniFile.GetValue(KeyName, "Color", "-");
if ((Color != "-") && (Color.length() >= 1))
{
Group->SetColor(AString(cChatColor::Delimiter) + Color[0]);
}
else
{
Group->SetColor(cChatColor::White);
}
AString Commands = IniFile.GetValue(KeyName, "Commands", "");
if (!Commands.empty())
{
AStringVector Split = StringSplitAndTrim(Commands, ",");
for (size_t i = 0; i < Split.size(); i++)
{
Group->AddCommand(Split[i]);
}
}
AString Permissions = IniFile.GetValue(KeyName, "Permissions", "");
if (!Permissions.empty())
{
AStringVector Split = StringSplitAndTrim(Permissions, ",");
for (size_t i = 0; i < Split.size(); i++)
{
Group->AddPermission(Split[i]);
}
}
AString Groups = IniFile.GetValue(KeyName, "Inherits", "");
if (!Groups.empty())
{
AStringVector Split = StringSplitAndTrim(Groups, ",");
for (size_t i = 0; i < Split.size(); i++)
{
Group->InheritFrom(GetGroup(Split[i].c_str()));
}
}
}
// Always return true, we can handle writefile fails later.
return true;
}
bool cGroupManager::ExistsGroup( const AString & a_Name)
{
GroupMap::iterator itr = m_pState->Groups.find( a_Name);
return ( itr != m_pState->Groups.end());
}
cGroup* cGroupManager::GetGroup( const AString & a_Name)
{
GroupMap::iterator itr = m_pState->Groups.find( a_Name);
if (itr != m_pState->Groups.end())
{
return itr->second;
}
cGroup* Group = new cGroup();
m_pState->Groups[a_Name] = Group;
return Group;
}
-36
View File
@@ -1,36 +0,0 @@
#pragma once
class cGroup;
class cGroupManager
{
public:
bool ExistsGroup(const AString & a_Name);
cGroup * GetGroup(const AString & a_Name);
bool LoadGroups();
bool CheckUsers();
/** Writes the default header to the specified ini file, and saves it as "users.ini". */
static void GenerateDefaultUsersIni(cIniFile & a_IniFile);
private:
friend class cRoot;
cGroupManager();
~cGroupManager();
struct sGroupManagerState;
sGroupManagerState * m_pState;
} ;
+2 -1
View File
@@ -15,7 +15,8 @@
cHTTPConnection::cHTTPConnection(cHTTPServer & a_HTTPServer) :
m_HTTPServer(a_HTTPServer),
m_State(wcsRecvHeaders),
m_CurrentRequest(NULL)
m_CurrentRequest(NULL),
m_CurrentRequestBodyRemaining(0)
{
// LOGD("HTTP: New connection at %p", this);
}
+6 -2
View File
@@ -15,7 +15,9 @@
cHTTPFormParser::cHTTPFormParser(cHTTPRequest & a_Request, cCallbacks & a_Callbacks) :
m_Callbacks(a_Callbacks),
m_IsValid(true)
m_IsValid(true),
m_IsCurrentPartFile(false),
m_FileHasBeenAnnounced(false)
{
if (a_Request.GetMethod() == "GET")
{
@@ -55,7 +57,9 @@ cHTTPFormParser::cHTTPFormParser(cHTTPRequest & a_Request, cCallbacks & a_Callba
cHTTPFormParser::cHTTPFormParser(eKind a_Kind, const char * a_Data, size_t a_Size, cCallbacks & a_Callbacks) :
m_Callbacks(a_Callbacks),
m_Kind(a_Kind),
m_IsValid(true)
m_IsValid(true),
m_IsCurrentPartFile(false),
m_FileHasBeenAnnounced(false)
{
Parse(a_Data, a_Size);
}
+1 -1
View File
@@ -106,7 +106,7 @@ int cInventory::AddItem(const cItem & a_Item, bool a_AllowNewStacks, bool a_tryT
// When the item is a armor, try to set it directly to the armor slot.
if (ItemCategory::IsArmor(a_Item.m_ItemType))
{
for (size_t i = 0; i < (size_t)m_ArmorSlots.GetNumSlots(); i++)
for (int i = 0; i < m_ArmorSlots.GetNumSlots(); i++)
{
if (m_ArmorSlots.GetSlot(i).IsEmpty() && cSlotAreaArmor::CanPlaceArmorInSlot(i, a_Item))
{
+1 -1
View File
@@ -29,7 +29,7 @@ public:
a_Player->AddEntityEffect(cEntityEffect::effRegeneration, 100, 1);
// When the apple is a 'notch apple', give extra effects:
if (a_Item->m_ItemDamage > 0)
if (a_Item->m_ItemDamage >= E_META_GOLDEN_APPLE_ENCHANTED)
{
a_Player->AddEntityEffect(cEntityEffect::effRegeneration, 600, 4);
a_Player->AddEntityEffect(cEntityEffect::effResistance, 6000, 0);
-1
View File
@@ -19,7 +19,6 @@ public:
cItemShovelHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}
virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
+5 -1
View File
@@ -73,6 +73,8 @@ public:
HEIGHTTYPE * m_HeightMap; // 3x3 chunks of height map, organized as a single XZY blob of data (instead of 3x3 XZY blobs)
cReader(BLOCKTYPE * a_BlockTypes, HEIGHTTYPE * a_HeightMap) :
m_ReadingChunkX(0),
m_ReadingChunkZ(0),
m_MaxHeight(0),
m_BlockTypes(a_BlockTypes),
m_HeightMap(a_HeightMap)
@@ -89,7 +91,9 @@ public:
cLightingThread::cLightingThread(void) :
super("cLightingThread"),
m_World(NULL)
m_World(NULL),
m_MaxHeight(0),
m_NumSeeds(0)
{
}
-169
View File
@@ -1,169 +0,0 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Log.h"
#include <fstream>
#include <ctime>
#include "OSSupport/IsThread.h"
#if defined(ANDROID_NDK)
#include <android/log.h>
#include "ToJava.h"
#endif
cLog* cLog::s_Log = NULL;
cLog::cLog(const AString & a_FileName)
: m_File(NULL)
{
s_Log = this;
// create logs directory
cFile::CreateFolder(FILE_IO_PREFIX + AString("logs"));
OpenLog((FILE_IO_PREFIX + AString("logs/") + a_FileName).c_str());
}
cLog::~cLog()
{
CloseLog();
s_Log = NULL;
}
cLog * cLog::GetInstance()
{
if (s_Log != NULL)
{
return s_Log;
}
new cLog("log.txt");
return s_Log;
}
void cLog::CloseLog()
{
if (m_File)
fclose (m_File);
m_File = 0;
}
void cLog::OpenLog( const char* a_FileName)
{
if (m_File) fclose (m_File);
#ifdef _MSC_VER
fopen_s( &m_File, a_FileName, "a+");
#else
m_File = fopen(a_FileName, "a+");
#endif
}
void cLog::ClearLog()
{
#ifdef _MSC_VER
if (fopen_s( &m_File, "log.txt", "w") == 0)
fclose (m_File);
#else
m_File = fopen("log.txt", "w");
if (m_File)
fclose (m_File);
#endif
m_File = NULL;
}
void cLog::Log(const char * a_Format, va_list argList)
{
AString Message;
AppendVPrintf(Message, a_Format, argList);
time_t rawtime;
time ( &rawtime);
struct tm* timeinfo;
#ifdef _MSC_VER
struct tm timeinforeal;
timeinfo = &timeinforeal;
localtime_s(timeinfo, &rawtime);
#else
timeinfo = localtime( &rawtime);
#endif
AString Line;
#ifdef _DEBUG
Printf(Line, "[%04lx|%02d:%02d:%02d] %s", cIsThread::GetCurrentID(), timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, Message.c_str());
#else
Printf(Line, "[%02d:%02d:%02d] %s", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, Message.c_str());
#endif
if (m_File)
{
fprintf(m_File, "%s\n", Line.c_str());
fflush(m_File);
}
// Print to console:
#if defined(ANDROID_NDK)
// __android_log_vprint(ANDROID_LOG_ERROR, "MCServer", a_Format, argList);
__android_log_print(ANDROID_LOG_ERROR, "MCServer", "%s", Line.c_str());
// CallJavaFunction_Void_String(g_JavaThread, "AddToLog", Line);
#else
printf("%s", Line.c_str());
#endif
#if defined (_WIN32) && defined(_DEBUG)
// In a Windows Debug build, output the log to debug console as well:
OutputDebugStringA((Line + "\n").c_str());
#endif // _WIN32
}
void cLog::Log(const char * a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
Log(a_Format, argList);
va_end(argList);
}
void cLog::SimpleLog(const char * a_String)
{
Log("%s", a_String);
}
-30
View File
@@ -1,30 +0,0 @@
#pragma once
class cLog
{
private:
FILE * m_File;
static cLog * s_Log;
public:
cLog(const AString & a_FileName);
~cLog();
void Log(const char * a_Format, va_list argList) FORMATSTRING(2, 0);
void Log(const char * a_Format, ...) FORMATSTRING(2, 3);
// tolua_begin
void SimpleLog(const char * a_String);
void OpenLog(const char * a_FileName);
void CloseLog();
void ClearLog();
static cLog* GetInstance();
};
+145
View File
@@ -0,0 +1,145 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "OSSupport/IsThread.h"
#ifdef _WIN32
#include <time.h>
#endif
cLogger & cLogger::GetInstance(void)
{
static cLogger Instance;
return Instance;
}
void cLogger::InitiateMultithreading()
{
GetInstance();
}
void cLogger::LogSimple(AString a_Message, eLogLevel a_LogLevel)
{
time_t rawtime;
time(&rawtime);
struct tm * timeinfo;
#ifdef _MSC_VER
struct tm timeinforeal;
timeinfo = &timeinforeal;
localtime_s(timeinfo, &rawtime);
#else
timeinfo = localtime(&rawtime);
#endif
AString Line;
#ifdef _DEBUG
Printf(Line, "[%04lx|%02d:%02d:%02d] %s\n", cIsThread::GetCurrentID(), timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message.c_str());
#else
Printf(Line, "[%02d:%02d:%02d] %s\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message.c_str());
#endif
cCSLock Lock(m_CriticalSection);
for (size_t i = 0; i < m_LogListeners.size(); i++)
{
m_LogListeners[i]->Log(Line, a_LogLevel);
}
}
void cLogger::Log(const char * a_Format, eLogLevel a_LogLevel, va_list a_ArgList)
{
AString Message;
AppendVPrintf(Message, a_Format, a_ArgList);
LogSimple(Message, a_LogLevel);
}
void cLogger::AttachListener(cListener * a_Listener)
{
cCSLock Lock(m_CriticalSection);
m_LogListeners.push_back(a_Listener);
}
void cLogger::DetachListener(cListener * a_Listener)
{
cCSLock Lock(m_CriticalSection);
m_LogListeners.erase(std::remove(m_LogListeners.begin(), m_LogListeners.end(), a_Listener));
}
////////////////////////////////////////////////////////////////////////////////
// Global functions
void LOG(const char * a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
cLogger::GetInstance().Log(a_Format, cLogger::llRegular, argList);
va_end(argList);
}
void LOGINFO(const char * a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
cLogger::GetInstance().Log( a_Format, cLogger::llInfo, argList);
va_end(argList);
}
void LOGWARN(const char * a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
cLogger::GetInstance().Log( a_Format, cLogger::llWarning, argList);
va_end(argList);
}
void LOGERROR(const char * a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
cLogger::GetInstance().Log( a_Format, cLogger::llError, argList);
va_end(argList);
}
+73
View File
@@ -0,0 +1,73 @@
#pragma once
class cLogger
{
public:
enum eLogLevel
{
llRegular,
llInfo,
llWarning,
llError,
};
class cListener
{
public:
virtual void Log(AString a_Message, eLogLevel a_LogLevel) = 0;
virtual ~cListener(){}
};
void Log (const char * a_Format, eLogLevel a_LogLevel, va_list a_ArgList) FORMATSTRING(2, 0);
/** Logs the simple text message at the specified log level. */
void LogSimple(AString a_Message, eLogLevel a_LogLevel = llRegular);
void AttachListener(cListener * a_Listener);
void DetachListener(cListener * a_Listener);
static cLogger & GetInstance(void);
// Must be called before calling GetInstance in a multithreaded context
static void InitiateMultithreading();
private:
cCriticalSection m_CriticalSection;
std::vector<cListener *> m_LogListeners;
};
extern void LOG(const char* a_Format, ...) FORMATSTRING(1, 2);
extern void LOGINFO(const char* a_Format, ...) FORMATSTRING(1, 2);
extern void LOGWARN(const char* a_Format, ...) FORMATSTRING(1, 2);
extern void LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2);
// In debug builds, translate LOGD to LOG, otherwise leave it out altogether:
#ifdef _DEBUG
#define LOGD LOG
#else
#define LOGD(...)
#endif // _DEBUG
#define LOGWARNING LOGWARN
+322
View File
@@ -0,0 +1,322 @@
#include "Globals.h"
#include "LoggerListeners.h"
#if defined(_WIN32)
#include <io.h> // Needed for _isatty(), not available on Linux
#include <time.h>
#elif defined(__linux) && !defined(ANDROID_NDK)
#include <unistd.h> // Needed for isatty() on Linux
#elif defined(ANDROID_NDK)
#include <android/log.h>
#endif
#if defined(_WIN32) || (defined (__linux) && !defined(ANDROID_NDK))
class cColouredConsoleListener
: public cLogger::cListener
{
protected:
virtual void SetLogColour(cLogger::eLogLevel a_LogLevel) = 0;
virtual void SetDefaultLogColour() = 0;
virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
{
SetLogColour(a_LogLevel);
fputs(a_Message.c_str(), stdout);
SetDefaultLogColour();
}
};
#endif
#ifdef _WIN32
class cWindowsConsoleListener
: public cColouredConsoleListener
{
typedef cColouredConsoleListener super;
public:
cWindowsConsoleListener(HANDLE a_Console, WORD a_DefaultConsoleAttrib) :
m_Console(a_Console),
m_DefaultConsoleAttrib(a_DefaultConsoleAttrib)
{
}
#ifdef _DEBUG
virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
{
super::Log(a_Message, a_LogLevel);
// In a Windows Debug build, output the log to debug console as well:
OutputDebugStringA(a_Message.c_str());
}
#endif
virtual void SetLogColour(cLogger::eLogLevel a_LogLevel) override
{
// by default, gray on black
WORD Attrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
switch (a_LogLevel)
{
case cLogger::llRegular:
{
// Gray on black
Attrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
break;
}
case cLogger::llInfo:
{
// Yellow on black
Attrib = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
break;
}
case cLogger::llWarning:
{
// Red on black
Attrib = FOREGROUND_RED | FOREGROUND_INTENSITY;
break;
}
case cLogger::llError:
{
// Black on red
Attrib = BACKGROUND_RED | BACKGROUND_INTENSITY;
break;
}
}
SetConsoleTextAttribute(m_Console, Attrib);
}
virtual void SetDefaultLogColour() override
{
SetConsoleTextAttribute(m_Console, m_DefaultConsoleAttrib);
}
private:
HANDLE m_Console;
WORD m_DefaultConsoleAttrib;
};
#elif defined (__linux) && !defined(ANDROID_NDK)
class cLinuxConsoleListener
: public cColouredConsoleListener
{
public:
virtual void SetLogColour(cLogger::eLogLevel a_LogLevel) override
{
switch (a_LogLevel)
{
case cLogger::llRegular:
{
// Whatever the console default is
printf("\x1b[0m");
break;
}
case cLogger::llInfo:
{
// Yellow on black
printf("\x1b[33;1m");
break;
}
case cLogger::llWarning:
{
// Red on black
printf("\x1b[31;1m");
break;
}
case cLogger::llError:
{
// Yellow on red
printf("\x1b[1;33;41;1m");
break;
}
}
}
virtual void SetDefaultLogColour() override
{
// Whatever the console default is
printf("\x1b[0m");
}
};
#elif defined(ANDROID_NDK)
class cAndroidConsoleListener
: public cLogger::cListener
{
public:
virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
{
android_LogPriority AndroidLogLevel;
switch (a_LogLevel)
{
case cLogger::llRegular:
{
AndroidLogLevel = ANDROID_LOG_VERBOSE;
break;
}
case cLogger::llInfo:
{
AndroidLogLevel = ANDROID_LOG_INFO;
break;
}
case cLogger::llWarning:
{
AndroidLogLevel = ANDROID_LOG_WARNING;
break;
}
case cLogger::llError:
{
AndroidLogLevel = ANDROID_LOG_ERROR;
break;
}
}
__android_log_print(AndroidLogLevel, "MCServer", "%s", a_Message.c_str());
}
};
#endif
class cVanillaCPPConsoleListener
: public cLogger::cListener
{
public:
virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
{
AString LogLevelString;
switch (a_LogLevel)
{
case cLogger::llRegular:
{
LogLevelString = "Log";
break;
}
case cLogger::llInfo:
{
LogLevelString = "Info";
break;
}
case cLogger::llWarning:
{
LogLevelString = "Warning";
break;
}
case cLogger::llError:
{
LogLevelString = "Error";
break;
}
}
printf("%s: %s", LogLevelString.c_str(), a_Message.c_str());
}
};
cLogger::cListener * MakeConsoleListener(void)
{
#ifdef _WIN32
// See whether we are writing to a console the default console attrib:
bool ShouldColorOutput = (_isatty(_fileno(stdin)) != 0);
if (ShouldColorOutput)
{
CONSOLE_SCREEN_BUFFER_INFO sbi;
HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(Console, &sbi);
WORD DefaultConsoleAttrib = sbi.wAttributes;
return new cWindowsConsoleListener(Console, DefaultConsoleAttrib);
}
else
{
return new cVanillaCPPConsoleListener;
}
#elif defined (__linux) && !defined(ANDROID_NDK)
// TODO: lookup terminal in terminfo
if (isatty(fileno(stdout)))
{
return new cLinuxConsoleListener();
}
else
{
return new cVanillaCPPConsoleListener();
}
#else
return new cVanillaCPPConsoleListener();
#endif
}
////////////////////////////////////////////////////////////////////////////////
// cFileListener:
cFileListener::cFileListener(void)
{
cFile::CreateFolder(FILE_IO_PREFIX + AString("logs"));
AString FileName;
FileName = Printf("%s%sLOG_%d.txt", FILE_IO_PREFIX, "logs/", (int)time(NULL));
m_File.Open(FileName, cFile::fmAppend);
}
void cFileListener::Log(AString a_Message, cLogger::eLogLevel a_LogLevel)
{
const char * LogLevelPrefix = "Unkn ";
switch (a_LogLevel)
{
case cLogger::llRegular:
{
LogLevelPrefix = " ";
break;
}
case cLogger::llInfo:
{
LogLevelPrefix = "info ";
break;
}
case cLogger::llWarning:
{
LogLevelPrefix = "Warn ";
break;
}
case cLogger::llError:
{
LogLevelPrefix = "Err ";
break;
}
}
m_File.Printf("%s%s", LogLevelPrefix, a_Message.c_str());
}
+31
View File
@@ -0,0 +1,31 @@
#include "Logger.h"
class cFileListener
: public cLogger::cListener
{
public:
cFileListener();
cFileListener(AString a_Filename);
virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override;
private:
cFile m_File;
};
cLogger::cListener * MakeConsoleListener();
-267
View File
@@ -1,267 +0,0 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include <time.h>
#include "Log.h"
cMCLogger * cMCLogger::s_MCLogger = NULL;
#ifdef _WIN32
#include <io.h> // Needed for _isatty(), not available on Linux
HANDLE g_Console = GetStdHandle(STD_OUTPUT_HANDLE);
WORD g_DefaultConsoleAttrib = 0x07;
#elif defined (__linux) && !defined(ANDROID_NDK)
#include <unistd.h> // Needed for isatty() on Linux
#endif
cMCLogger * cMCLogger::GetInstance(void)
{
return s_MCLogger;
}
cMCLogger::cMCLogger(void):
m_ShouldColorOutput(false)
{
AString FileName;
Printf(FileName, "LOG_%d.txt", (int)time(NULL));
InitLog(FileName);
}
cMCLogger::cMCLogger(const AString & a_FileName)
{
InitLog(a_FileName);
}
cMCLogger::~cMCLogger()
{
m_Log->Log("--- Stopped Log ---\n");
delete m_Log;
m_Log = NULL;
if (this == s_MCLogger)
{
s_MCLogger = NULL;
}
}
void cMCLogger::InitLog(const AString & a_FileName)
{
m_Log = new cLog(a_FileName);
m_Log->Log("--- Started Log ---\n");
s_MCLogger = this;
#ifdef _WIN32
// See whether we are writing to a console the default console attrib:
m_ShouldColorOutput = (_isatty(_fileno(stdin)) != 0);
if (m_ShouldColorOutput)
{
CONSOLE_SCREEN_BUFFER_INFO sbi;
GetConsoleScreenBufferInfo(g_Console, &sbi);
g_DefaultConsoleAttrib = sbi.wAttributes;
}
#elif defined (__linux) && !defined(ANDROID_NDK)
m_ShouldColorOutput = isatty(fileno(stdout));
// TODO: Check if the terminal supports colors, somehow?
#endif
}
void cMCLogger::LogSimple(const char * a_Text, eLogLevel a_LogLevel)
{
switch (a_LogLevel)
{
case llRegular:
{
LOG("%s", a_Text);
break;
}
case llInfo:
{
LOGINFO("%s", a_Text);
break;
}
case llWarning:
{
LOGWARN("%s", a_Text);
break;
}
case llError:
{
LOGERROR("%s", a_Text);
break;
}
}
}
void cMCLogger::Log(const char * a_Format, va_list a_ArgList)
{
cCSLock Lock(m_CriticalSection);
SetColor(csRegular);
m_Log->Log(a_Format, a_ArgList);
ResetColor();
puts("");
}
void cMCLogger::Info(const char * a_Format, va_list a_ArgList)
{
cCSLock Lock(m_CriticalSection);
SetColor(csInfo);
m_Log->Log(a_Format, a_ArgList);
ResetColor();
puts("");
}
void cMCLogger::Warn(const char * a_Format, va_list a_ArgList)
{
cCSLock Lock(m_CriticalSection);
SetColor(csWarning);
m_Log->Log(a_Format, a_ArgList);
ResetColor();
puts("");
}
void cMCLogger::Error(const char * a_Format, va_list a_ArgList)
{
cCSLock Lock(m_CriticalSection);
SetColor(csError);
m_Log->Log(a_Format, a_ArgList);
ResetColor();
puts("");
}
void cMCLogger::SetColor(eColorScheme a_Scheme)
{
if (!m_ShouldColorOutput)
{
return;
}
#ifdef _WIN32
WORD Attrib = 0x07; // by default, gray on black
switch (a_Scheme)
{
case csRegular: Attrib = 0x07; break; // Gray on black
case csInfo: Attrib = 0x0e; break; // Yellow on black
case csWarning: Attrib = 0x0c; break; // Read on black
case csError: Attrib = 0xc0; break; // Black on red
default: ASSERT(!"Unhandled color scheme");
}
SetConsoleTextAttribute(g_Console, Attrib);
#elif defined(__linux) && !defined(ANDROID_NDK)
switch (a_Scheme)
{
case csRegular: printf("\x1b[0m"); break; // Whatever the console default is
case csInfo: printf("\x1b[33;1m"); break; // Yellow on black
case csWarning: printf("\x1b[31;1m"); break; // Red on black
case csError: printf("\x1b[1;33;41;1m"); break; // Yellow on red
default: ASSERT(!"Unhandled color scheme");
}
#endif
}
void cMCLogger::ResetColor(void)
{
if (!m_ShouldColorOutput)
{
return;
}
#ifdef _WIN32
SetConsoleTextAttribute(g_Console, g_DefaultConsoleAttrib);
#elif defined(__linux) && !defined(ANDROID_NDK)
printf("\x1b[0m");
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Global functions
void LOG(const char* a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
cMCLogger::GetInstance()->Log( a_Format, argList);
va_end(argList);
}
void LOGINFO(const char* a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
cMCLogger::GetInstance()->Info( a_Format, argList);
va_end(argList);
}
void LOGWARN(const char* a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
cMCLogger::GetInstance()->Warn( a_Format, argList);
va_end(argList);
}
void LOGERROR(const char* a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
cMCLogger::GetInstance()->Error( a_Format, argList);
va_end(argList);
}
-95
View File
@@ -1,95 +0,0 @@
#pragma once
class cLog;
class cMCLogger
{
public:
enum eLogLevel
{
llRegular,
llInfo,
llWarning,
llError,
};
// tolua_end
/** Creates a logger with the default filename, "logs/LOG_<timestamp>.log" */
cMCLogger(void);
/** Creates a logger with the specified filename inside "logs" folder */
cMCLogger(const AString & a_FileName);
~cMCLogger();
void Log (const char * a_Format, va_list a_ArgList) FORMATSTRING(2, 0);
void Info (const char * a_Format, va_list a_ArgList) FORMATSTRING(2, 0);
void Warn (const char * a_Format, va_list a_ArgList) FORMATSTRING(2, 0);
void Error(const char * a_Format, va_list a_ArgList) FORMATSTRING(2, 0);
/** Logs the simple text message at the specified log level. */
void LogSimple(const char * a_Text, eLogLevel a_LogLevel = llRegular);
static cMCLogger * GetInstance();
private:
enum eColorScheme
{
csRegular,
csInfo,
csWarning,
csError,
} ;
cCriticalSection m_CriticalSection;
cLog * m_Log;
static cMCLogger * s_MCLogger;
bool m_ShouldColorOutput;
/// Sets the specified color scheme in the terminal (TODO: if coloring available)
void SetColor(eColorScheme a_Scheme);
/// Resets the color back to whatever is the default in the terminal
void ResetColor(void);
/// Common initialization for all constructors, creates a logfile with the specified name and assigns s_MCLogger to this
void InitLog(const AString & a_FileName);
};
extern void LOG(const char* a_Format, ...) FORMATSTRING(1, 2);
extern void LOGINFO(const char* a_Format, ...) FORMATSTRING(1, 2);
extern void LOGWARN(const char* a_Format, ...) FORMATSTRING(1, 2);
extern void LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2);
// In debug builds, translate LOGD to LOG, otherwise leave it out altogether:
#ifdef _DEBUG
#define LOGD LOG
#else
#define LOGD(...)
#endif // _DEBUG
#define LOGWARNING LOGWARN
+1 -1
View File
@@ -1024,7 +1024,7 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk)
(a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand
(GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime
!IsOnFire() && // Not already burning
GetWorld()->IsWeatherWetAt(POSX_TOINT, POSZ_TOINT) // Not raining
GetWorld()->IsWeatherSunnyAt(POSX_TOINT, POSZ_TOINT) // Not raining
)
{
// Burn for 100 ticks, then decide again
+5
View File
@@ -146,6 +146,8 @@ cCubicCell2D::cCubicCell2D(
) :
m_Noise(a_Noise),
m_WorkRnds(&m_Workspace1),
m_CurFloorX(0),
m_CurFloorY(0),
m_Array(a_Array),
m_SizeX(a_SizeX),
m_SizeY(a_SizeY),
@@ -300,6 +302,9 @@ cCubicCell3D::cCubicCell3D(
) :
m_Noise(a_Noise),
m_WorkRnds(&m_Workspace1),
m_CurFloorX(0),
m_CurFloorY(0),
m_CurFloorZ(0),
m_Array(a_Array),
m_SizeX(a_SizeX),
m_SizeY(a_SizeY),
+4 -3
View File
@@ -70,6 +70,7 @@ bool cFile::Open(const AString & iFileName, eMode iMode)
case fmRead: Mode = "rb"; break;
case fmWrite: Mode = "wb"; break;
case fmReadWrite: Mode = "rb+"; break;
case fmAppend: Mode = "a+"; break;
}
if (Mode == NULL)
{
@@ -255,10 +256,10 @@ int cFile::ReadRestOfFile(AString & a_Contents)
return -1;
}
int DataSize = GetSize() - Tell();
size_t DataSize = GetSize() - Tell();
// HACK: This depends on the internal knowledge that AString's data() function returns the internal buffer directly
a_Contents.assign((size_t)DataSize, '\0');
a_Contents.assign(DataSize, '\0');
return Read((void *)a_Contents.data(), DataSize);
}
@@ -459,7 +460,7 @@ int cFile::Printf(const char * a_Fmt, ...)
va_start(args, a_Fmt);
AppendVPrintf(buf, a_Fmt, args);
va_end(args);
return Write(buf.c_str(), (int)buf.length());
return Write(buf.c_str(), buf.length());
}
+4 -3
View File
@@ -60,9 +60,10 @@ public:
/** The mode in which to open the file */
enum eMode
{
fmRead, // Read-only. If the file doesn't exist, object will not be valid
fmWrite, // Write-only. If the file already exists, it will be overwritten
fmReadWrite // Read/write. If the file already exists, it will be left intact; writing will overwrite the data from the beginning
fmRead, // Read-only. If the file doesn't exist, object will not be valid
fmWrite, // Write-only. If the file already exists, it will be overwritten
fmReadWrite, // Read/write. If the file already exists, it will be left intact; writing will overwrite the data from the beginning
fmAppend // Write-only. If the file already exists cursor will be moved to the end of the file
} ;
/** Simple constructor - creates an unopened file object, use Open() to open / create a real file */
+1
View File
@@ -16,6 +16,7 @@ cSslContext::cSslContext(void) :
m_IsValid(false),
m_HasHandshaken(false)
{
memset(&m_Ssl, 0, sizeof(m_Ssl));
}
+22 -3
View File
@@ -10,6 +10,7 @@
#include "inifile/iniFile.h"
#include "json/json.h"
#include "PolarSSL++/BlockingSslClientSocket.h"
#include "../RankManager.h"
@@ -300,6 +301,7 @@ void cMojangAPI::AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const
cCSLock Lock(m_CSUUIDToName);
m_UUIDToName[UUID] = sProfile(a_PlayerName, UUID, "", "", Now);
}
NotifyNameUUID(a_PlayerName, a_UUID);
}
@@ -322,6 +324,7 @@ void cMojangAPI::AddPlayerProfile(const AString & a_PlayerName, const AString &
cCSLock Lock(m_CSUUIDToProfile);
m_UUIDToProfile[UUID] = sProfile(a_PlayerName, UUID, a_Properties, Now);
}
NotifyNameUUID(a_PlayerName, a_UUID);
}
@@ -655,11 +658,11 @@ void cMojangAPI::CacheNamesToUUIDs(const AStringVector & a_PlayerNames)
}
// Store the returned results into cache:
size_t JsonCount = root.size();
Json::Value::UInt JsonCount = root.size();
Int64 Now = time(NULL);
{
cCSLock Lock(m_CSNameToUUID);
for (size_t idx = 0; idx < JsonCount; ++idx)
for (Json::Value::UInt idx = 0; idx < JsonCount; ++idx)
{
Json::Value & Val = root[idx];
AString JsonName = Val.get("name", "").asString();
@@ -669,13 +672,14 @@ void cMojangAPI::CacheNamesToUUIDs(const AStringVector & a_PlayerNames)
continue;
}
m_NameToUUID[StrToLower(JsonName)] = sProfile(JsonName, JsonUUID, "", "", Now);
NotifyNameUUID(JsonName, JsonUUID);
} // for idx - root[]
} // cCSLock (m_CSNameToUUID)
// Also cache the UUIDToName:
{
cCSLock Lock(m_CSUUIDToName);
for (size_t idx = 0; idx < JsonCount; ++idx)
for (Json::Value::UInt idx = 0; idx < JsonCount; ++idx)
{
Json::Value & Val = root[idx];
AString JsonName = Val.get("name", "").asString();
@@ -792,6 +796,21 @@ void cMojangAPI::CacheUUIDToProfile(const AString & a_UUID)
cCSLock Lock(m_CSNameToUUID);
m_NameToUUID[StrToLower(PlayerName)] = sProfile(PlayerName, a_UUID, Properties, Now);
}
NotifyNameUUID(PlayerName, a_UUID);
}
void cMojangAPI::NotifyNameUUID(const AString & a_PlayerName, const AString & a_UUID)
{
// Notify the rank manager:
cCSLock Lock(m_CSRankMgr);
if (m_RankMgr != NULL)
{
m_RankMgr->NotifyNameUUID(a_PlayerName, a_UUID);
}
}
+21 -5
View File
@@ -11,6 +11,13 @@
#include <time.h>
// fwd: ../RankManager.h"
class cRankManager;
namespace Json
{
class Value;
@@ -38,8 +45,6 @@ public:
Returns true if all was successful, false on failure. */
static bool SecureRequest(const AString & a_ServerName, const AString & a_Request, AString & a_Response);
// tolua_begin
/** Normalizes the given UUID to its short form (32 bytes, no dashes, lowercase).
Logs a warning and returns empty string if not a UUID.
Note: only checks the string's length, not the actual content. */
@@ -50,8 +55,6 @@ public:
Note: only checks the string's length, not the actual content. */
static AString MakeUUIDDashed(const AString & a_UUID);
// tolua_end
/** Converts a player name into a UUID.
The UUID will be empty on error.
If a_UseOnlyCached is true, the function only consults the cached values.
@@ -85,7 +88,10 @@ public:
/** Called by the Authenticator to add a profile that it has received from authenticating a user. Adds
the profile to the respective mapping caches and updtes their datetime stamp to now. */
void AddPlayerProfile(const AString & a_PlayerName, const AString & a_UUID, const Json::Value & a_Properties);
/** Sets the m_RankMgr that is used for name-uuid notifications. Accepts NULL to remove the binding. */
void SetRankManager(cRankManager * a_RankManager) { m_RankMgr = a_RankManager; }
protected:
/** Holds data for a single player profile. */
struct sProfile
@@ -165,6 +171,12 @@ protected:
/** Protects m_UUIDToProfile against simultaneous multi-threaded access. */
cCriticalSection m_CSUUIDToProfile;
/** The rank manager that is notified of the name-uuid pairings. May be NULL. Protected by m_CSRankMgr. */
cRankManager * m_RankMgr;
/** Protects m_RankMgr agains simultaneous multi-threaded access. */
cCriticalSection m_CSRankMgr;
/** Loads the caches from a disk storage. */
@@ -182,6 +194,10 @@ protected:
UUIDs that are not valid will not be added into the cache.
ASSUMEs that a_UUID is a lowercased short UUID. */
void CacheUUIDToProfile(const AString & a_UUID);
/** Called for each name-uuid pairing that is discovered.
If assigned, notifies the m_RankManager of the event. */
void NotifyNameUUID(const AString & a_PlayerName, const AString & a_PlayerUUID);
} ; // tolua_export
+75 -29
View File
@@ -41,6 +41,7 @@ Implements the 1.7.x protocol classes:
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/FlowerPotEntity.h"
#include "Bindings/PluginManager.h"
@@ -1720,21 +1721,41 @@ void cProtocol172::HandlePacketStatusPing(cByteBuffer & a_ByteBuffer)
void cProtocol172::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer)
{
// Send the response:
AString Response = "{\"version\":{\"name\":\"1.7.2\", \"protocol\":4}, \"players\":{";
cServer * Server = cRoot::Get()->GetServer();
AppendPrintf(Response, "\"max\":%u, \"online\":%u, \"sample\":[]},",
Server->GetMaxPlayers(),
Server->GetNumPlayers()
);
AppendPrintf(Response, "\"description\":{\"text\":\"%s\"},",
Server->GetDescription().c_str()
);
AppendPrintf(Response, "\"favicon\": \"data:image/png;base64,%s\"",
Server->GetFaviconData().c_str()
);
Response.append("}");
AString ServerDescription = Server->GetDescription();
int NumPlayers = Server->GetNumPlayers();
int MaxPlayers = Server->GetMaxPlayers();
AString Favicon = Server->GetFaviconData();
cRoot::Get()->GetPluginManager()->CallHookServerPing(*m_Client, ServerDescription, NumPlayers, MaxPlayers, Favicon);
// Version:
Json::Value Version;
Version["name"] = "1.7.2";
Version["protocol"] = 4;
// Players:
Json::Value Players;
Players["online"] = NumPlayers;
Players["max"] = MaxPlayers;
// TODO: Add "sample"
// Description:
Json::Value Description;
Description["text"] = ServerDescription.c_str();
// Create the response:
Json::Value ResponseValue;
ResponseValue["version"] = Version;
ResponseValue["players"] = Players;
ResponseValue["description"] = Description;
if (!Favicon.empty())
{
ResponseValue["favicon"] = Printf("data:image/png;base64,%s", Favicon.c_str());
}
Json::StyledWriter Writer;
AString Response = Writer.write(ResponseValue);
cPacketizer Pkt(*this, 0x00); // Response packet
Pkt.WriteString(Response);
}
@@ -1803,7 +1824,11 @@ void cProtocol172::HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffe
void cProtocol172::HandlePacketLoginStart(cByteBuffer & a_ByteBuffer)
{
AString Username;
a_ByteBuffer.ReadVarUTF8String(Username);
if (!a_ByteBuffer.ReadVarUTF8String(Username))
{
m_Client->Kick("Bad username");
return;
}
if (!m_Client->HandleHandshake(Username))
{
@@ -3070,20 +3095,41 @@ void cProtocol176::SendPlayerSpawn(const cPlayer & a_Player)
void cProtocol176::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer)
{
// Send the response:
AString Response = "{\"version\": {\"name\": \"1.7.6\", \"protocol\":5}, \"players\": {";
AppendPrintf(Response, "\"max\": %u, \"online\": %u, \"sample\": []},",
cRoot::Get()->GetServer()->GetMaxPlayers(),
cRoot::Get()->GetServer()->GetNumPlayers()
);
AppendPrintf(Response, "\"description\": {\"text\": \"%s\"},",
cRoot::Get()->GetServer()->GetDescription().c_str()
);
AppendPrintf(Response, "\"favicon\": \"data:image/png;base64,%s\"",
cRoot::Get()->GetServer()->GetFaviconData().c_str()
);
Response.append("}");
cServer * Server = cRoot::Get()->GetServer();
AString Motd = Server->GetDescription();
int NumPlayers = Server->GetNumPlayers();
int MaxPlayers = Server->GetMaxPlayers();
AString Favicon = Server->GetFaviconData();
cRoot::Get()->GetPluginManager()->CallHookServerPing(*m_Client, Motd, NumPlayers, MaxPlayers, Favicon);
// Version:
Json::Value Version;
Version["name"] = "1.7.6";
Version["protocol"] = 5;
// Players:
Json::Value Players;
Players["online"] = NumPlayers;
Players["max"] = MaxPlayers;
// TODO: Add "sample"
// Description:
Json::Value Description;
Description["text"] = Motd.c_str();
// Create the response:
Json::Value ResponseValue;
ResponseValue["version"] = Version;
ResponseValue["players"] = Players;
ResponseValue["description"] = Description;
if (!Favicon.empty())
{
ResponseValue["favicon"] = Printf("data:image/png;base64,%s", Favicon.c_str());
}
Json::StyledWriter Writer;
AString Response = Writer.write(ResponseValue);
cPacketizer Pkt(*this, 0x00); // Response packet
Pkt.WriteString(Response);
}
+15 -13
View File
@@ -18,6 +18,7 @@
#include "../Server.h"
#include "../World.h"
#include "../ChatColor.h"
#include "Bindings/PluginManager.h"
@@ -1013,6 +1014,13 @@ void cProtocolRecognizer::SendLengthlessServerPing(void)
{
AString Reply;
cServer * Server = cRoot::Get()->GetServer();
AString ServerDescription = Server->GetDescription();
int NumPlayers = Server->GetNumPlayers();
int MaxPlayers = Server->GetMaxPlayers();
AString Favicon = Server->GetFaviconData();
cRoot::Get()->GetPluginManager()->CallHookServerPing(*m_Client, ServerDescription, NumPlayers, MaxPlayers, Favicon);
switch (cRoot::Get()->GetPrimaryServerVersion())
{
case PROTO_VERSION_1_2_5:
@@ -1020,11 +1028,11 @@ void cProtocolRecognizer::SendLengthlessServerPing(void)
{
// http://wiki.vg/wiki/index.php?title=Protocol&oldid=3099#Server_List_Ping_.280xFE.29
Printf(Reply, "%s%s%i%s%i",
Server->GetDescription().c_str(),
ServerDescription.c_str(),
cChatColor::Delimiter,
Server->GetNumPlayers(),
NumPlayers,
cChatColor::Delimiter,
Server->GetMaxPlayers()
MaxPlayers
);
break;
}
@@ -1051,13 +1059,7 @@ void cProtocolRecognizer::SendLengthlessServerPing(void)
m_Buffer.ReadByte(val); // 0x01 magic value
ASSERT(val == 0x01);
}
// http://wiki.vg/wiki/index.php?title=Server_List_Ping&oldid=3100
AString NumPlayers;
Printf(NumPlayers, "%d", Server->GetNumPlayers());
AString MaxPlayers;
Printf(MaxPlayers, "%d", Server->GetMaxPlayers());
AString ProtocolVersionNum;
Printf(ProtocolVersionNum, "%d", cRoot::Get()->GetPrimaryServerVersion());
AString ProtocolVersionTxt(GetVersionTextFromInt(cRoot::Get()->GetPrimaryServerVersion()));
@@ -1070,11 +1072,11 @@ void cProtocolRecognizer::SendLengthlessServerPing(void)
Reply.push_back(0);
Reply.append(ProtocolVersionTxt);
Reply.push_back(0);
Reply.append(Server->GetDescription());
Reply.append(ServerDescription);
Reply.push_back(0);
Reply.append(NumPlayers);
Reply.append(Printf("%d", NumPlayers));
Reply.push_back(0);
Reply.append(MaxPlayers);
Reply.append(Printf("%d", MaxPlayers));
break;
}
} // switch (m_PrimaryServerVersion)
+1 -1
View File
@@ -18,7 +18,7 @@
// Adjust these if a new protocol is added or an old one is removed:
#define MCS_CLIENT_VERSIONS "1.2.4, 1.2.5, 1.3.1, 1.3.2, 1.4.2, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.5, 1.5.1, 1.5.2, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.7.2, 1.7.4, 1.7.5, 1.7.6, 1.7.7, 1.7.8, 1.7.9"
#define MCS_CLIENT_VERSIONS "1.2.4, 1.2.5, 1.3.1, 1.3.2, 1.4.2, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.5, 1.5.1, 1.5.2, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.7.2, 1.7.4, 1.7.5, 1.7.6, 1.7.7, 1.7.8, 1.7.9, 1.7.10"
#define MCS_PROTOCOL_VERSIONS "29, 39, 47, 49, 51, 60, 61, 73, 74, 77, 78, 4, 5"
+1837
View File
File diff suppressed because it is too large Load Diff
+246
View File
@@ -0,0 +1,246 @@
// RankManager.h
// Declares the cRankManager class that represents the rank manager responsible for assigning permissions and message visuals to players
#pragma once
#include "SQLiteCpp/Database.h"
#include "SQLiteCpp/Transaction.h"
class cMojangAPI;
class cRankManager
{
public:
/** Acquire this lock to perform mass changes.
Improves performance by wrapping everything into a transaction.
Makes sure that no other thread is accessing the DB. */
class cMassChangeLock
{
public:
cMassChangeLock(cRankManager & a_RankManager) :
m_Lock(a_RankManager.m_CS),
m_Transaction(a_RankManager.m_DB)
{
}
~cMassChangeLock()
{
m_Transaction.commit();
}
protected:
cCSLock m_Lock;
SQLite::Transaction m_Transaction;
};
/** Creates the rank manager. Needs to be initialized before other use. */
cRankManager(void);
~cRankManager();
/** Initializes the rank manager. Performs migration and default-setting if no data is found in the DB.
The a_MojangAPI param is used when migrating from old ini files, to look up player UUIDs. */
void Initialize(cMojangAPI & a_MojangAPI);
/** Returns the name of the rank that the specified player has assigned to them.
If the player has no rank assigned, returns an empty string (NOT the default rank). */
AString GetPlayerRankName(const AString & a_PlayerUUID);
/** Returns the names of Groups that the specified player has assigned to them. */
AStringVector GetPlayerGroups(const AString & a_PlayerUUID);
/** Returns the permissions that the specified player has assigned to them.
If the player has no rank assigned to them, returns the default rank's permissions. */
AStringVector GetPlayerPermissions(const AString & a_PlayerUUID);
/** Returns the names of groups that the specified rank has assigned to it.
Returns an empty vector if the rank doesn't exist. */
AStringVector GetRankGroups(const AString & a_RankName);
/** Returns the permissions that the specified group has assigned to it.
Returns an empty vector if the group doesn't exist. */
AStringVector GetGroupPermissions(const AString & a_GroupName);
/** Returns all permissions that the specified rank has assigned to it, through all its groups.
Returns an empty vector if the rank doesn't exist. Any non-existent groups are ignored. */
AStringVector GetRankPermissions(const AString & a_RankName);
/** Returns the names of all defined ranks. */
AStringVector GetAllRanks(void);
/** Returns the names of all permission groups. */
AStringVector GetAllGroups(void);
/** Returns all the distinct permissions that are stored in the DB. */
AStringVector GetAllPermissions(void);
/** Returns the message visuals (prefix, postfix, color) for the specified player.
Returns true if the visuals were read from the DB, false if not (player not found etc). */
bool GetPlayerMsgVisuals(
const AString & a_PlayerUUID,
AString & a_MsgPrefix,
AString & a_MsgSuffix,
AString & a_MsgNameColorCode
);
/** Adds a new rank. No action if the rank already exists. */
void AddRank(
const AString & a_RankName,
const AString & a_MsgPrefix,
const AString & a_MsgSuffix,
const AString & a_MsgNameColorCode
);
/** Adds a new permission group. No action if such a group already exists. */
void AddGroup(const AString & a_GroupName);
/** Bulk-adds groups. Group names that already exist are silently skipped. */
void AddGroups(const AStringVector & a_GroupNames);
/** Adds the specified permission group to the specified rank.
Fails if the rank or group names are not found.
Returns true if successful, false on error. */
bool AddGroupToRank(const AString & a_GroupName, const AString & a_RankName);
/** Adds the specified permission to the specified permission group.
Fails if the permission group name is not found.
Returns true if successful, false on error. */
bool AddPermissionToGroup(const AString & a_Permission, const AString & a_GroupName);
/** Adds the specified permissions to the specified permission group.
Fails if the permission group name is not found.
Returns true if successful, false on error. */
bool AddPermissionsToGroup(const AStringVector & a_Permissions, const AString & a_GroupName);
/** Removes the specified rank.
All players assigned to that rank will be re-assigned to a_ReplacementRankName.
If a_ReplacementRankName is empty or not a valid rank, the player will be removed from the DB,
which means they will receive the default rank the next time they are queried.
If the rank being removed is the default rank, the default will be changed to the replacement
rank; the operation fails if there's no replacement. */
void RemoveRank(const AString & a_RankName, const AString & a_ReplacementRankName);
/** Removes the specified group completely.
The group will first be removed from all ranks using it, and then removed itself. */
void RemoveGroup(const AString & a_GroupName);
/** Removes the specified group from the specified rank.
The group will stay defined, even if no rank is using it. */
void RemoveGroupFromRank(const AString & a_GroupName, const AString & a_RankName);
/** Removes the specified permission from the specified group. */
void RemovePermissionFromGroup(const AString & a_Permission, const AString & a_GroupName);
/** Renames the specified rank. No action if the rank name is not found.
Fails if the new name is already used.
Updates the cached m_DefaultRank if the default rank is being renamed.
Returns true on success, false on failure. */
bool RenameRank(const AString & a_OldName, const AString & a_NewName);
/** Renames the specified group. No action if the rank name is not found.
Fails if the new name is already used.
Returns true on success, false on failure. */
bool RenameGroup(const AString & a_OldName, const AString & a_NewName);
/** Sets the specified player's rank.
If the player already had rank assigned to them, it is overwritten with the new rank and name.
Note that this doesn't change the cPlayer if the player is already connected, you need to update all the
cPlayer instances manually.
The PlayerName is provided for reference, so that GetRankPlayerNames() can work. */
void SetPlayerRank(const AString & a_PlayerUUID, const AString & a_PlayerName, const AString & a_RankName);
/** Removes the player's rank assignment. The player is left without a rank.
Note that this doesn't change the cPlayer instances for the already connected players, you need to update
all the instances manually.
No action if the player has no rank assigned to them already. */
void RemovePlayerRank(const AString & a_PlayerUUID);
/** Sets the message visuals of an existing rank. No action if the rank name is not found. */
void SetRankVisuals(
const AString & a_RankName,
const AString & a_MsgPrefix,
const AString & a_MsgSuffix,
const AString & a_MsgNameColorCode
);
/** Returns the message visuals of an existing rank.
Returns true if successful, false on error (rank doesn't exist). */
bool GetRankVisuals(
const AString & a_RankName,
AString & a_MsgPrefix,
AString & a_MsgSuffix,
AString & a_MsgNameColorCode
);
/** Returns true iff the specified rank exists in the DB. */
bool RankExists(const AString & a_RankName);
/** Returns true iff the specified group exists in the DB. */
bool GroupExists(const AString & a_GroupName);
/** Returns true iff the specified player has a rank assigned to them in the DB. */
bool IsPlayerRankSet(const AString & a_PlayerUUID);
/** Returns true iff the specified rank contains the specified group. */
bool IsGroupInRank(const AString & a_GroupName, const AString & a_RankName);
/** Returns true iff the specified group contains the specified permission. */
bool IsPermissionInGroup(const AString & a_Permission, const AString & a_GroupName);
/** Called by cMojangAPI whenever the playername-uuid pairing is discovered. Updates the DB. */
void NotifyNameUUID(const AString & a_PlayerName, const AString & a_UUID);
/** Sets the specified rank as the default rank.
Returns true on success, false on failure (rank not found). */
bool SetDefaultRank(const AString & a_RankName);
/** Returns the name of the default rank. */
const AString & GetDefaultRank(void) const { return m_DefaultRank; }
protected:
/** The database storage for all the data. Protected by m_CS. */
SQLite::Database m_DB;
/** The name of the default rank. Kept as a cache so that queries for it don't need to go through the DB. */
AString m_DefaultRank;
/** The mutex protecting m_DB and m_DefaultRank against multi-threaded access. */
cCriticalSection m_CS;
/** Set to true once the manager is initialized. */
bool m_IsInitialized;
/** The MojangAPI instance that is used for translating playernames to UUIDs.
Set in Initialize(), may be NULL. */
cMojangAPI * m_MojangAPI;
/** Returns true if all the DB tables are empty, indicating a fresh new install. */
bool AreDBTablesEmpty(void);
/** Returns true iff the specified DB table is empty.
If there's an error while querying, returns false. */
bool IsDBTableEmpty(const AString & a_TableName);
/** Creates a default set of ranks / groups / permissions. */
void CreateDefaults(void);
} ;
+19 -24
View File
@@ -6,7 +6,6 @@
#include "World.h"
#include "WebAdmin.h"
#include "FurnaceRecipe.h"
#include "GroupManager.h"
#include "CraftingRecipes.h"
#include "Bindings/PluginManager.h"
#include "MonsterConfig.h"
@@ -18,6 +17,7 @@
#include "CommandOutput.h"
#include "DeadlockDetect.h"
#include "OSSupport/Timer.h"
#include "LoggerListeners.h"
#include "inifile/iniFile.h"
@@ -46,12 +46,10 @@ cRoot::cRoot(void) :
m_InputThread(NULL),
m_Server(NULL),
m_MonsterConfig(NULL),
m_GroupManager(NULL),
m_CraftingRecipes(NULL),
m_FurnaceRecipe(NULL),
m_WebAdmin(NULL),
m_PluginManager(NULL),
m_Log(NULL),
m_bStop(false),
m_bRestart(false)
{
@@ -105,10 +103,15 @@ void cRoot::Start(void)
HMENU hmenu = GetSystemMenu(hwnd, FALSE);
EnableMenuItem(hmenu, SC_CLOSE, MF_GRAYED); // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling
#endif
cLogger::cListener * consoleLogListener = MakeConsoleListener();
cLogger::cListener * fileLogListener = new cFileListener();
cLogger::GetInstance().AttachListener(consoleLogListener);
cLogger::GetInstance().AttachListener(fileLogListener);
LOG("--- Started Log ---\n");
cDeadlockDetect dd;
delete m_Log;
m_Log = new cMCLogger();
m_bStop = false;
while (!m_bStop)
@@ -156,7 +159,7 @@ void cRoot::Start(void)
m_WebAdmin->Init();
LOGD("Loading settings...");
m_GroupManager = new cGroupManager();
m_RankManager.Initialize(m_MojangAPI);
m_CraftingRecipes = new cCraftingRecipes;
m_FurnaceRecipe = new cFurnaceRecipe();
@@ -235,8 +238,6 @@ void cRoot::Start(void)
LOGD("Unloading recipes...");
delete m_FurnaceRecipe; m_FurnaceRecipe = NULL;
delete m_CraftingRecipes; m_CraftingRecipes = NULL;
LOGD("Forgetting groups...");
delete m_GroupManager; m_GroupManager = NULL;
LOGD("Unloading worlds...");
UnloadWorlds();
@@ -249,8 +250,13 @@ void cRoot::Start(void)
delete m_Server; m_Server = NULL;
LOG("Shutdown successful!");
}
delete m_Log; m_Log = NULL;
LOG("--- Stopped Log ---");
cLogger::GetInstance().DetachListener(consoleLogListener);
delete consoleLogListener;
cLogger::GetInstance().DetachListener(fileLogListener);
delete fileLogListener;
}
@@ -274,15 +280,15 @@ void cRoot::LoadWorlds(cIniFile & IniFile)
m_WorldsByName[ DefaultWorldName ] = m_pDefaultWorld;
// Then load the other worlds
unsigned int KeyNum = IniFile.FindKey("Worlds");
unsigned int NumWorlds = IniFile.GetNumValues(KeyNum);
int KeyNum = IniFile.FindKey("Worlds");
int NumWorlds = IniFile.GetNumValues(KeyNum);
if (NumWorlds <= 0)
{
return;
}
bool FoundAdditionalWorlds = false;
for (unsigned int i = 0; i < NumWorlds; i++)
for (int i = 0; i < NumWorlds; i++)
{
AString ValueName = IniFile.GetValueName(KeyNum, i);
if (ValueName.compare("World") != 0)
@@ -545,17 +551,6 @@ void cRoot::SaveAllChunks(void)
void cRoot::ReloadGroups(void)
{
LOG("Reload groups ...");
m_GroupManager->LoadGroups();
m_GroupManager->CheckUsers();
}
void cRoot::BroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix)
{
for (WorldMap::iterator itr = m_WorldsByName.begin(), end = m_WorldsByName.end(); itr != end; ++itr)
+3 -8
View File
@@ -5,6 +5,7 @@
#include "Protocol/MojangAPI.h"
#include "HTTPServer/HTTPServer.h"
#include "Defines.h"
#include "RankManager.h"
@@ -13,7 +14,6 @@
// fwd:
class cThread;
class cMonsterConfig;
class cGroupManager;
class cCraftingRecipes;
class cFurnaceRecipe;
class cWebAdmin;
@@ -78,7 +78,6 @@ public:
cMonsterConfig * GetMonsterConfig(void) { return m_MonsterConfig; }
cGroupManager * GetGroupManager (void) { return m_GroupManager; } // tolua_export
cCraftingRecipes * GetCraftingRecipes(void) { return m_CraftingRecipes; } // tolua_export
cFurnaceRecipe * GetFurnaceRecipe (void) { return m_FurnaceRecipe; } // Exported in ManualBindings.cpp with quite a different signature
@@ -89,6 +88,7 @@ public:
cPluginManager * GetPluginManager (void) { return m_PluginManager; } // tolua_export
cAuthenticator & GetAuthenticator (void) { return m_Authenticator; }
cMojangAPI & GetMojangAPI (void) { return m_MojangAPI; }
cRankManager & GetRankManager (void) { return m_RankManager; }
/** Queues a console command for execution through the cServer class.
The command will be executed in the tick thread
@@ -122,9 +122,6 @@ public:
/// Saves all chunks in all worlds
void SaveAllChunks(void); // tolua_export
/// Reloads all the groups
void ReloadGroups(void); // tolua_export
/// Calls the callback for each player in all worlds
bool ForEachPlayer(cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
@@ -187,17 +184,15 @@ private:
cServer * m_Server;
cMonsterConfig * m_MonsterConfig;
cGroupManager * m_GroupManager;
cCraftingRecipes * m_CraftingRecipes;
cFurnaceRecipe * m_FurnaceRecipe;
cWebAdmin * m_WebAdmin;
cPluginManager * m_PluginManager;
cAuthenticator m_Authenticator;
cMojangAPI m_MojangAPI;
cRankManager m_RankManager;
cHTTPServer m_HTTPServer;
cMCLogger * m_Log;
bool m_bStop;
bool m_bRestart;
+12 -20
View File
@@ -11,7 +11,6 @@
#include "World.h"
#include "ChunkDef.h"
#include "Bindings/PluginManager.h"
#include "GroupManager.h"
#include "ChatColor.h"
#include "Entities/Player.h"
#include "Inventory.h"
@@ -117,7 +116,9 @@ cServer::cServer(void) :
m_MaxPlayers(0),
m_bIsHardcore(false),
m_TickThread(*this),
m_ShouldAuthenticate(false)
m_ShouldAuthenticate(false),
m_ShouldLoadOfflinePlayerData(false),
m_ShouldLoadNamedPlayerData(true)
{
}
@@ -469,25 +470,17 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac
PrintHelp(split, a_Output);
return;
}
if (split[0] == "reload")
{
cPluginManager::Get()->ReloadPlugins();
cRoot::Get()->ReloadGroups();
return;
}
if (split[0] == "reloadplugins")
else if (split[0] == "reload")
{
cPluginManager::Get()->ReloadPlugins();
return;
}
if (split[0] == "reloadgroups")
else if (split[0] == "reloadplugins")
{
cRoot::Get()->ReloadGroups();
a_Output.Out("Groups reloaded!");
a_Output.Finished();
cPluginManager::Get()->ReloadPlugins();
return;
}
if (split[0] == "load")
else if (split[0] == "load")
{
if (split.size() > 1)
{
@@ -502,8 +495,7 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac
return;
}
}
if (split[0] == "unload")
else if (split[0] == "unload")
{
if (split.size() > 1)
{
@@ -519,21 +511,21 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac
}
// There is currently no way a plugin can do these (and probably won't ever be):
if (split[0].compare("chunkstats") == 0)
else if (split[0].compare("chunkstats") == 0)
{
cRoot::Get()->LogChunkStats(a_Output);
a_Output.Finished();
return;
}
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
if (split[0].compare("dumpmem") == 0)
else if (split[0].compare("dumpmem") == 0)
{
LeakFinderXmlOutput Output("memdump.xml");
DumpUsedMemory(&Output);
return;
}
if (split[0].compare("killmem") == 0)
else if (split[0].compare("killmem") == 0)
{
for (;;)
{
@@ -542,7 +534,7 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac
}
#endif
if (cPluginManager::Get()->ExecuteConsoleCommand(split, a_Output))
else if (cPluginManager::Get()->ExecuteConsoleCommand(split, a_Output))
{
a_Output.Finished();
return;
+1 -1
View File
@@ -120,7 +120,7 @@ public: // tolua_export
const AString & GetPublicKeyDER(void) const { return m_PublicKeyDER; }
/** Returns true if authentication has been turned on in server settings. */
bool ShouldAuthenticate(void) const { return m_ShouldAuthenticate; }
bool ShouldAuthenticate(void) const { return m_ShouldAuthenticate; } // tolua_export
/** Returns true if offline UUIDs should be used to load data for players whose normal UUIDs cannot be found.
Loaded from the settings.ini [PlayerData].LoadOfflinePlayerData setting. */
+3
View File
@@ -13,6 +13,9 @@
cSetChunkData::cSetChunkData(int a_ChunkX, int a_ChunkZ, bool a_ShouldMarkDirty) :
m_ChunkX(a_ChunkX),
m_ChunkZ(a_ChunkZ),
m_IsLightValid(false),
m_IsHeightMapValid(false),
m_AreBiomesValid(false),
m_ShouldMarkDirty(a_ShouldMarkDirty)
{
}
-1
View File
@@ -13,7 +13,6 @@
typedef std::string AString;
typedef std::vector<AString> AStringVector;
typedef std::list<AString> AStringList;
+5 -27
View File
@@ -159,28 +159,6 @@ void cWebAdmin::Stop(void)
AString cWebAdmin::GetTemplate()
{
AString retVal = "";
char SourceFile[] = "webadmin/template.html";
cFile f;
if (!f.Open(SourceFile, cFile::fmRead))
{
return "";
}
// copy the file into the buffer:
f.ReadRestOfFile(retVal);
return retVal;
}
void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
{
if (!a_Request.HasAuth())
@@ -198,9 +176,9 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
}
// Check if the contents should be wrapped in the template:
AString URL = a_Request.GetBareURL();
ASSERT(URL.length() > 0);
bool ShouldWrapInTemplate = ((URL.length() > 1) && (URL[1] != '~'));
AString BareURL = a_Request.GetBareURL();
ASSERT(BareURL.length() > 0);
bool ShouldWrapInTemplate = ((BareURL.length() > 1) && (BareURL[1] != '~'));
// Retrieve the request data:
cWebadminRequestData * Data = (cWebadminRequestData *)(a_Request.GetUserData());
@@ -215,7 +193,7 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
HTTPTemplateRequest TemplateRequest;
TemplateRequest.Request.Username = a_Request.GetAuthUsername();
TemplateRequest.Request.Method = a_Request.GetMethod();
TemplateRequest.Request.Path = URL.substr(1);
TemplateRequest.Request.Path = BareURL.substr(1);
if (Data->m_Form.Finish())
{
@@ -258,7 +236,7 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
return;
}
AString BaseURL = GetBaseURL(URL);
AString BaseURL = GetBaseURL(BareURL);
AString Menu;
Template = "{CONTENT}";
AString FoundPlugin;
-3
View File
@@ -208,9 +208,6 @@ protected:
/** The HTTP server which provides the underlying HTTP parsing, serialization and events */
cHTTPServer m_HTTPServer;
AString GetTemplate(void);
/** Handles requests coming to the "/webadmin" or "/~webadmin" URLs */
void HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
+33 -2
View File
@@ -1,3 +1,4 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "BlockID.h"
@@ -250,8 +251,38 @@ cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AStrin
m_TimeOfDay(0),
m_LastTimeUpdate(0),
m_SkyDarkness(0),
m_GameMode(gmNotSet),
m_bEnabledPVP(false),
m_IsDeepSnowEnabled(false),
m_ShouldLavaSpawnFire(true),
m_VillagersShouldHarvestCrops(true),
m_SimulatorManager(NULL),
m_SandSimulator(NULL),
m_WaterSimulator(NULL),
m_LavaSimulator(NULL),
m_FireSimulator(NULL),
m_RedstoneSimulator(NULL),
m_MaxPlayers(10),
m_ChunkMap(NULL),
m_bAnimals(true),
m_Weather(eWeather_Sunny),
m_WeatherInterval(24000), // Guaranteed 1 day of sunshine at server start :)
m_MaxCactusHeight(3),
m_MaxSugarcaneHeight(4),
m_IsCactusBonemealable(false),
m_IsCarrotsBonemealable(true),
m_IsCropsBonemealable(true),
m_IsGrassBonemealable(true),
m_IsMelonStemBonemealable(true),
m_IsMelonBonemealable(true),
m_IsPotatoesBonemealable(true),
m_IsPumpkinStemBonemealable(true),
m_IsPumpkinBonemealable(true),
m_IsSaplingBonemealable(true),
m_IsSugarcaneBonemealable(false),
m_bCommandBlocksEnabled(true),
m_bUseChatPrefixes(false),
m_TNTShrapnelLevel(slNone),
m_Scoreboard(this),
m_MapManager(this),
m_GeneratorCallbacks(*this),
@@ -406,7 +437,7 @@ void cWorld::InitializeSpawn(void)
int ViewDist = IniFile.GetValueSetI("SpawnPosition", "PregenerateDistance", DefaultViewDist);
IniFile.WriteFile(m_IniFileName);
LOG("Preparing spawn area in world \"%s\"...", m_WorldName.c_str());
LOG("Preparing spawn area in world \"%s\", %d x %d chunks, total %d chunks...", m_WorldName.c_str(), ViewDist, ViewDist, ViewDist * ViewDist);
for (int x = 0; x < ViewDist; x++)
{
for (int z = 0; z < ViewDist; z++)
@@ -3327,7 +3358,7 @@ void cWorld::AddQueuedPlayers(void)
cCSLock Lock(m_CSPlayers);
for (cPlayerList::iterator itr = PlayersToAdd.begin(), end = PlayersToAdd.end(); itr != end; ++itr)
{
ASSERT(std::find(m_Players.begin(), m_Players.end(), *itr) == m_Players.end()); // Is it already in the list? HOW?
ASSERT(std::find(m_Players.begin(), m_Players.end(), *itr) == m_Players.end()); // Is it already in the list? HOW?
LOGD("Adding player %s to world \"%s\".", (*itr)->GetName().c_str(), m_WorldName.c_str());
m_Players.push_back(*itr);

Some files were not shown because too many files have changed in this diff Show More