Merge remote-tracking branch 'origin/master' into CraftingFixes
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../MCLogger.h"
|
||||
#include "Logger.h"
|
||||
#include <time.h>
|
||||
// tolua_begin
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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));
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ public:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ))
|
||||
{
|
||||
case E_BLOCK_DIRT:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -57,8 +57,6 @@ SET (HDRS
|
||||
BlockMushroom.h
|
||||
BlockMycelium.h
|
||||
BlockNetherWart.h
|
||||
BlockNewLeaves.h
|
||||
BlockNote.h
|
||||
BlockOre.h
|
||||
BlockPiston.h
|
||||
BlockPlanks.h
|
||||
|
||||
+1
-1
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -16,6 +16,7 @@ cSslContext::cSslContext(void) :
|
||||
m_IsValid(false),
|
||||
m_HasHandshaken(false)
|
||||
{
|
||||
memset(&m_Ssl, 0, sizeof(m_Ssl));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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. */
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
typedef std::string AString;
|
||||
typedef std::vector<AString> AStringVector;
|
||||
typedef std::list<AString> AStringList;
|
||||
|
||||
+5
-27
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user