diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Bindings/AllToLua.pkg | 1 | ||||
-rw-r--r-- | src/Bindings/ManualBindings.cpp | 5 | ||||
-rw-r--r-- | src/BlockEntities/JukeboxEntity.cpp | 48 | ||||
-rw-r--r-- | src/BlockEntities/JukeboxEntity.h | 17 | ||||
-rw-r--r-- | src/BlockID.h | 4 | ||||
-rw-r--r-- | src/Blocks/ChunkInterface.h | 31 | ||||
-rw-r--r-- | src/Entities/Painting.cpp | 11 | ||||
-rw-r--r-- | src/Entities/Painting.h | 2 | ||||
-rw-r--r-- | src/Entities/Player.cpp | 44 | ||||
-rw-r--r-- | src/GroupManager.cpp | 58 | ||||
-rw-r--r-- | src/GroupManager.h | 5 | ||||
-rw-r--r-- | src/HTTPServer/HTTPServer.cpp | 4 | ||||
-rw-r--r-- | src/Items/ItemHandler.cpp | 26 | ||||
-rw-r--r-- | src/Log.cpp | 4 | ||||
-rw-r--r-- | src/Mobs/Mooshroom.cpp | 2 | ||||
-rw-r--r-- | src/OSSupport/BlockingTCPLink.cpp | 4 | ||||
-rw-r--r-- | src/Root.cpp | 4 | ||||
-rw-r--r-- | src/Scoreboard.cpp | 135 | ||||
-rw-r--r-- | src/Scoreboard.h | 131 | ||||
-rw-r--r-- | src/Server.cpp | 2 | ||||
-rw-r--r-- | src/UI/SlotArea.cpp | 30 | ||||
-rw-r--r-- | src/UI/SlotArea.h | 6 | ||||
-rw-r--r-- | src/WorldStorage/FastNBT.h | 9 | ||||
-rw-r--r-- | src/WorldStorage/ScoreboardSerializer.cpp | 14 | ||||
-rw-r--r-- | src/main.cpp | 27 |
25 files changed, 459 insertions, 165 deletions
diff --git a/src/Bindings/AllToLua.pkg b/src/Bindings/AllToLua.pkg index 6537437cd..1a2140771 100644 --- a/src/Bindings/AllToLua.pkg +++ b/src/Bindings/AllToLua.pkg @@ -75,6 +75,7 @@ $cfile "../Mobs/Monster.h" $cfile "../CompositeChat.h" $cfile "../Map.h" $cfile "../MapManager.h" +$cfile "../Scoreboard.h" diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index 461186d3b..fcdd728be 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -2583,6 +2583,11 @@ void ManualBindings::Bind(lua_State * tolua_S) tolua_beginmodule(tolua_S, "cMapManager"); tolua_function(tolua_S, "DoWithMap", tolua_DoWithID<cMapManager, cMap, &cMapManager::DoWithMap>); tolua_endmodule(tolua_S); + + tolua_beginmodule(tolua_S, "cScoreboard"); + tolua_function(tolua_S, "ForEachObjective", tolua_ForEach<cScoreboard, cObjective, &cScoreboard::ForEachObjective>); + tolua_function(tolua_S, "ForEachTeam", tolua_ForEach<cScoreboard, cTeam, &cScoreboard::ForEachTeam>); + tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cPlugin"); tolua_function(tolua_S, "Call", tolua_cPlugin_Call); diff --git a/src/BlockEntities/JukeboxEntity.cpp b/src/BlockEntities/JukeboxEntity.cpp index 33042179d..c96253b11 100644 --- a/src/BlockEntities/JukeboxEntity.cpp +++ b/src/BlockEntities/JukeboxEntity.cpp @@ -30,48 +30,70 @@ cJukeboxEntity::~cJukeboxEntity() void cJukeboxEntity::UsedBy(cPlayer * a_Player) { - if (m_Record == 0) + if (IsPlayingRecord()) + { + EjectRecord(); + } + else { const cItem & HeldItem = a_Player->GetEquippedItem(); - if (HeldItem.m_ItemType >= 2256 && HeldItem.m_ItemType <= 2267) + if (PlayRecord(HeldItem.m_ItemType)) { - m_Record = HeldItem.m_ItemType; a_Player->GetInventory().RemoveOneEquippedItem(); - PlayRecord(); } } - else - { - EjectRecord(); - } } -void cJukeboxEntity::PlayRecord(void) +bool cJukeboxEntity::PlayRecord(int a_Record) { + if (!IsRecordItem(a_Record)) + { + // This isn't a Record Item + return false; + } + if (IsPlayingRecord()) + { + // A Record is already in the Jukebox. + EjectRecord(); + } + m_Record = a_Record; m_World->BroadcastSoundParticleEffect(1005, m_PosX, m_PosY, m_PosZ, m_Record); + m_World->SetBlockMeta(m_PosX, m_PosY, m_PosZ, E_META_JUKEBOX_ON); + return true; } -void cJukeboxEntity::EjectRecord(void) +bool cJukeboxEntity::EjectRecord(void) { - if ((m_Record < E_ITEM_FIRST_DISC) || (m_Record > E_ITEM_LAST_DISC)) + if (!IsPlayingRecord()) { // There's no record here - return; + return false; } cItems Drops; Drops.push_back(cItem(m_Record, 1, 0)); + m_Record = 0; m_World->SpawnItemPickups(Drops, m_PosX + 0.5, m_PosY + 1, m_PosZ + 0.5, 8); m_World->BroadcastSoundParticleEffect(1005, m_PosX, m_PosY, m_PosZ, 0); - m_Record = 0; + m_World->SetBlockMeta(m_PosX, m_PosY, m_PosZ, E_META_JUKEBOX_OFF); + return true; +} + + + + + +bool cJukeboxEntity::IsPlayingRecord(void) +{ + return (m_Record != 0); } diff --git a/src/BlockEntities/JukeboxEntity.h b/src/BlockEntities/JukeboxEntity.h index 734d7bb66..3d1d604f7 100644 --- a/src/BlockEntities/JukeboxEntity.h +++ b/src/BlockEntities/JukeboxEntity.h @@ -37,10 +37,21 @@ public: int GetRecord(void); void SetRecord(int a_Record); - void PlayRecord(void); - /// Ejects the currently held record as a pickup. Does nothing when no record inserted. - void EjectRecord(void); + /** Plays the specified Record. Return false if a_Record isn't a playable Record (E_ITEM_XXX_DISC). + If there is a record already playing, ejects it first. */ + bool PlayRecord(int a_Record); + + /** Ejects the currently held record as a pickup. Return false when no record had been inserted. */ + bool EjectRecord(void); + + /** Is in the Jukebox a Record? */ + bool IsPlayingRecord(void); + + static bool IsRecordItem(int a_Item) + { + return ((a_Item >= E_ITEM_FIRST_DISC) && (a_Item <= E_ITEM_LAST_DISC)); + } // tolua_end diff --git a/src/BlockID.h b/src/BlockID.h index 3413555f4..861bb8dae 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -466,6 +466,10 @@ enum E_META_FLOWER_PINK_TULIP = 7, E_META_FLOWER_OXEYE_DAISY = 8, + // E_BLOCK_JUKEBOX metas + E_META_JUKEBOX_OFF = 0, + E_META_JUKEBOX_ON = 1, + // E_BLOCK_HOPPER metas: E_META_HOPPER_FACING_YM = 0, E_META_HOPPER_UNATTACHED = 1, // Hopper doesn't move items up, there's no YP diff --git a/src/Blocks/ChunkInterface.h b/src/Blocks/ChunkInterface.h index b30eff1e4..be7c2e0e5 100644 --- a/src/Blocks/ChunkInterface.h +++ b/src/Blocks/ChunkInterface.h @@ -5,31 +5,35 @@ #include "../ForEachChunkProvider.h" #include "WorldInterface.h" -class cBlockHandler; -class cChunkInterface : public cForEachChunkProvider + + + +class cChunkInterface: + public cForEachChunkProvider { public: cChunkInterface(cChunkMap * a_ChunkMap) : m_ChunkMap(a_ChunkMap) {} - BLOCKTYPE GetBlock (int a_BlockX, int a_BlockY, int a_BlockZ) + BLOCKTYPE GetBlock(int a_BlockX, int a_BlockY, int a_BlockZ) { return m_ChunkMap->GetBlock(a_BlockX,a_BlockY,a_BlockZ); } - BLOCKTYPE GetBlock (const Vector3i & a_Pos ) + BLOCKTYPE GetBlock(const Vector3i & a_Pos) { - return GetBlock( a_Pos.x, a_Pos.y, a_Pos.z ); + return GetBlock(a_Pos.x, a_Pos.y, a_Pos.z); } - NIBBLETYPE GetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ) + NIBBLETYPE GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ) { return m_ChunkMap->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); } - bool GetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) + bool GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) { return m_ChunkMap->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); } + /** Sets the block at the specified coords to the specified value. Full processing, incl. updating neighbors, is performed. */ @@ -37,7 +41,8 @@ public: { m_ChunkMap->SetBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); } - void SetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData) + + void SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData) { m_ChunkMap->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_MetaData); } @@ -55,7 +60,11 @@ public: { m_ChunkMap->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); } - void FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta ); } + + void FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) + { + FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta ); + } void UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) { @@ -77,3 +86,7 @@ public: private: cChunkMap * m_ChunkMap; }; + + + + diff --git a/src/Entities/Painting.cpp b/src/Entities/Painting.cpp index b98c1e67a..e217556c7 100644 --- a/src/Entities/Painting.cpp +++ b/src/Entities/Painting.cpp @@ -4,6 +4,7 @@ #include "Painting.h" #include "ClientHandle.h" #include "Player.h" +#include "../Chunk.h" @@ -30,6 +31,16 @@ void cPainting::SpawnOn(cClientHandle & a_Client) +void cPainting::Tick(float a_Dt, cChunk & a_Chunk) +{ + UNUSED(a_Dt); + UNUSED(a_Chunk); +} + + + + + void cPainting::GetDrops(cItems & a_Items, cEntity * a_Killer) { if ((a_Killer != NULL) && a_Killer->IsPlayer() && !((cPlayer *)a_Killer)->IsGameModeCreative()) diff --git a/src/Entities/Painting.h b/src/Entities/Painting.h index 95afbed1e..c1024bd1b 100644 --- a/src/Entities/Painting.h +++ b/src/Entities/Painting.h @@ -24,7 +24,7 @@ public: private: virtual void SpawnOn(cClientHandle & a_Client) override; - virtual void Tick(float a_Dt, cChunk & a_Chunk) override {}; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override; virtual void KilledBy(cEntity * a_Killer) override { diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 0152bfc5b..8f94f1feb 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -858,6 +858,8 @@ void cPlayer::KilledBy(cEntity * a_Killer) else if (a_Killer->IsPlayer()) { GetWorld()->BroadcastChatDeath(Printf("%s was killed by %s", GetName().c_str(), ((cPlayer *)a_Killer)->GetName().c_str())); + + m_World->GetScoreBoard().AddPlayerScore(((cPlayer *)a_Killer)->GetName(), cObjective::otPlayerKillCount, 1); } else { @@ -867,24 +869,7 @@ void cPlayer::KilledBy(cEntity * a_Killer) GetWorld()->BroadcastChatDeath(Printf("%s was killed by a %s", GetName().c_str(), KillerClass.c_str())); } - class cIncrementCounterCB - : public cObjectiveCallback - { - AString m_Name; - public: - cIncrementCounterCB(const AString & a_Name) : m_Name(a_Name) {} - - virtual bool Item(cObjective * a_Objective) override - { - a_Objective->AddScore(m_Name, 1); - return true; - } - } IncrementCounter (GetName()); - - cScoreboard & Scoreboard = m_World->GetScoreBoard(); - - // Update scoreboard objectives - Scoreboard.ForEachObjectiveWith(cObjective::E_TYPE_DEATH_COUNT, IncrementCounter); + m_World->GetScoreBoard().AddPlayerScore(GetName(), cObjective::otDeathCount, 1); } @@ -1529,10 +1514,14 @@ void cPlayer::LoadPermissionsFromDisk() std::string Groups = IniFile.GetValue(m_PlayerName, "Groups", ""); if (!Groups.empty()) { - AStringVector Split = StringSplit( Groups, "," ); - for( unsigned int i = 0; i < Split.size(); i++ ) + AStringVector Split = StringSplitAndTrim(Groups, ","); + for (AStringVector::const_iterator itr = Split.begin(), end = Split.end(); itr != end; ++itr) { - AddToGroup( Split[i].c_str() ); + if (!cRoot::Get()->GetGroupManager()->ExistsGroup(*itr)) + { + LOGWARNING("The group %s for player %s was not found!", itr->c_str(), m_PlayerName.c_str()); + } + AddToGroup(*itr); } } else @@ -1540,16 +1529,15 @@ void cPlayer::LoadPermissionsFromDisk() AddToGroup("Default"); } - m_Color = IniFile.GetValue(m_PlayerName, "Color", "-")[0]; + AString Color = IniFile.GetValue(m_PlayerName, "Color", "-"); + if (!Color.empty()) + { + m_Color = Color[0]; + } } else { - LOGWARN("Regenerating users.ini, player %s will be added to the \"Default\" group", m_PlayerName.c_str()); - IniFile.AddHeaderComment(" This is the file in which the group the player belongs to is stored"); - IniFile.AddHeaderComment(" The format is: [PlayerName] | Groups=GroupName"); - - IniFile.SetValue(m_PlayerName, "Groups", "Default"); - IniFile.WriteFile("users.ini"); + cGroupManager::GenerateDefaultUsersIni(IniFile); AddToGroup("Default"); } ResolvePermissions(); diff --git a/src/GroupManager.cpp b/src/GroupManager.cpp index 723b86f94..33b601e82 100644 --- a/src/GroupManager.cpp +++ b/src/GroupManager.cpp @@ -46,6 +46,7 @@ cGroupManager::cGroupManager() LOGD("-- Loading Groups --"); LoadGroups(); + CheckUsers(); LOGD("-- Groups Successfully Loaded --"); } @@ -54,6 +55,53 @@ cGroupManager::cGroupManager() +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"); +} + + + + + +void cGroupManager::CheckUsers(void) +{ + cIniFile IniFile; + if (!IniFile.ReadFile("users.ini")) + { + GenerateDefaultUsersIni(IniFile); + return; + } + + unsigned int NumKeys = IniFile.GetNumKeys(); + for (size_t i = 0; i < NumKeys; i++) + { + AString Player = IniFile.GetKeyName( i ); + AString Groups = IniFile.GetValue(Player, "Groups", ""); + if (!Groups.empty()) + { + AStringVector Split = StringSplit( Groups, "," ); + for( unsigned int i = 0; i < Split.size(); i++ ) + { + if (!ExistsGroup(Split[i])) + { + LOGWARNING("The group %s for player %s was not found!", Split[i].c_str(), Player.c_str()); + } + } + } + } +} + + + + + void cGroupManager::LoadGroups() { cIniFile IniFile; @@ -137,6 +185,16 @@ void cGroupManager::LoadGroups() +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 ); diff --git a/src/GroupManager.h b/src/GroupManager.h index 02a58fe4e..9e1689a76 100644 --- a/src/GroupManager.h +++ b/src/GroupManager.h @@ -14,8 +14,13 @@ class cGroup; class cGroupManager { public: + bool ExistsGroup(const AString & a_Name); cGroup * GetGroup(const AString & a_Name); void LoadGroups(void); + void CheckUsers(void); + + /** 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; diff --git a/src/HTTPServer/HTTPServer.cpp b/src/HTTPServer/HTTPServer.cpp index f6f5b0f8b..4e9195a00 100644 --- a/src/HTTPServer/HTTPServer.cpp +++ b/src/HTTPServer/HTTPServer.cpp @@ -29,6 +29,8 @@ class cDebugCallbacks : { virtual void OnRequestBegun(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override { + UNUSED(a_Connection); + if (cHTTPFormParser::HasFormData(a_Request)) { a_Request.SetUserData(new cHTTPFormParser(a_Request, *this)); @@ -38,6 +40,8 @@ class cDebugCallbacks : virtual void OnRequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, int a_Size) override { + UNUSED(a_Connection); + cHTTPFormParser * FormParser = (cHTTPFormParser *)(a_Request.GetUserData()); if (FormParser != NULL) { diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index c10d13edc..507f7fa86 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -248,6 +248,14 @@ cItemHandler::cItemHandler(int a_ItemType) bool cItemHandler::OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) { + UNUSED(a_World); + UNUSED(a_Player); + UNUSED(a_Item); + UNUSED(a_BlockX); + UNUSED(a_BlockY); + UNUSED(a_BlockZ); + UNUSED(a_Dir); + return false; } @@ -257,6 +265,14 @@ bool cItemHandler::OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & bool cItemHandler::OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) { + UNUSED(a_World); + UNUSED(a_Player); + UNUSED(a_Item); + UNUSED(a_BlockX); + UNUSED(a_BlockY); + UNUSED(a_BlockZ); + UNUSED(a_Dir); + return false; } @@ -266,6 +282,8 @@ bool cItemHandler::OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cI void cItemHandler::OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ) { + UNUSED(a_Item); + BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); cBlockHandler * Handler = cBlockHandler::GetBlockHandler(Block); @@ -288,7 +306,9 @@ void cItemHandler::OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const void cItemHandler::OnFoodEaten(cWorld * a_World, cPlayer * a_Player, cItem * a_Item) { - + UNUSED(a_World); + UNUSED(a_Player); + UNUSED(a_Item); } @@ -461,6 +481,8 @@ bool cItemHandler::IsPlaceable(void) bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType) { + UNUSED(a_BlockType); + return false; } @@ -499,6 +521,8 @@ bool cItemHandler::GetPlacementBlockTypeMeta( bool cItemHandler::EatItem(cPlayer * a_Player, cItem * a_Item) { + UNUSED(a_Item); + FoodInfo Info = GetFoodInfo(); if ((Info.FoodLevel > 0) || (Info.Saturation > 0.f)) diff --git a/src/Log.cpp b/src/Log.cpp index 2d6be0f59..1ea327d5d 100644 --- a/src/Log.cpp +++ b/src/Log.cpp @@ -42,7 +42,7 @@ cLog::~cLog() -cLog* cLog::GetInstance() +cLog * cLog::GetInstance() { if (s_Log != NULL) { @@ -92,7 +92,7 @@ void cLog::ClearLog() if( m_File ) fclose (m_File); #endif - m_File = 0; + m_File = NULL; } diff --git a/src/Mobs/Mooshroom.cpp b/src/Mobs/Mooshroom.cpp index 8e4c52ae6..81bd3e3b4 100644 --- a/src/Mobs/Mooshroom.cpp +++ b/src/Mobs/Mooshroom.cpp @@ -67,6 +67,8 @@ void cMooshroom::OnRightClicked(cPlayer & a_Player) cItems Drops; Drops.push_back(cItem(E_BLOCK_RED_MUSHROOM, 5, 0)); m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); + m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), cMonster::mtCow); + Destroy(); } break; } } diff --git a/src/OSSupport/BlockingTCPLink.cpp b/src/OSSupport/BlockingTCPLink.cpp index af50eda5d..e9c00d6d4 100644 --- a/src/OSSupport/BlockingTCPLink.cpp +++ b/src/OSSupport/BlockingTCPLink.cpp @@ -89,6 +89,8 @@ bool cBlockingTCPLink::Connect(const char * iAddress, unsigned int iPort) int cBlockingTCPLink::Send(char * a_Data, unsigned int a_Size, int a_Flags /* = 0 */ ) { + UNUSED(a_Flags); + ASSERT(m_Socket.IsValid()); if (!m_Socket.IsValid()) { @@ -104,6 +106,8 @@ int cBlockingTCPLink::Send(char * a_Data, unsigned int a_Size, int a_Flags /* = int cBlockingTCPLink::SendMessage( const char* a_Message, int a_Flags /* = 0 */ ) { + UNUSED(a_Flags); + ASSERT(m_Socket.IsValid()); if (!m_Socket.IsValid()) { diff --git a/src/Root.cpp b/src/Root.cpp index 206255916..af2cb9e4b 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -194,7 +194,7 @@ void cRoot::Start(void) #if !defined(ANDROID_NDK) LOGD("Starting InputThread..."); m_InputThread = new cThread( InputThread, this, "cRoot::InputThread" ); - m_InputThread->Start( false ); // We should NOT wait? Otherwise we canīt stop the server from other threads than the input thread + m_InputThread->Start( false ); // We should NOT wait? Otherwise we can't stop the server from other threads than the input thread #endif long long finishmseconds = Time.GetNowTime(); @@ -536,7 +536,9 @@ void cRoot::SaveAllChunks(void) void cRoot::ReloadGroups(void) { + LOG("Reload groups ..."); m_GroupManager->LoadGroups(); + m_GroupManager->CheckUsers(); } diff --git a/src/Scoreboard.cpp b/src/Scoreboard.cpp index 61ecac5b7..05fd0314d 100644 --- a/src/Scoreboard.cpp +++ b/src/Scoreboard.cpp @@ -17,19 +17,19 @@ AString cObjective::TypeToString(eType a_Type) { switch (a_Type) { - case E_TYPE_DUMMY: return "dummy"; - case E_TYPE_DEATH_COUNT: return "deathCount"; - case E_TYPE_PLAYER_KILL_COUNT: return "playerKillCount"; - case E_TYPE_TOTAL_KILL_COUNT: return "totalKillCount"; - case E_TYPE_HEALTH: return "health"; - case E_TYPE_ACHIEVEMENT: return "achievement"; - case E_TYPE_STAT: return "stat"; - case E_TYPE_STAT_ITEM_CRAFT: return "stat.craftItem"; - case E_TYPE_STAT_ITEM_USE: return "stat.useItem"; - case E_TYPE_STAT_ITEM_BREAK: return "stat.breakItem"; - case E_TYPE_STAT_BLOCK_MINE: return "stat.mineBlock"; - case E_TYPE_STAT_ENTITY_KILL: return "stat.killEntity"; - case E_TYPE_STAT_ENTITY_KILLED_BY: return "stat.entityKilledBy"; + case otDummy: return "dummy"; + case otDeathCount: return "deathCount"; + case otPlayerKillCount: return "playerKillCount"; + case otTotalKillCount: return "totalKillCount"; + case otHealth: return "health"; + case otAchievement: return "achievement"; + case otStat: return "stat"; + case otStatItemCraft: return "stat.craftItem"; + case otStatItemUse: return "stat.useItem"; + case otStatItemBreak: return "stat.breakItem"; + case otStatBlockMine: return "stat.mineBlock"; + case otStatEntityKill: return "stat.killEntity"; + case otStatEntityKilledBy: return "stat.entityKilledBy"; default: return ""; } @@ -46,19 +46,19 @@ cObjective::eType cObjective::StringToType(const AString & a_Name) const char * m_String; } TypeMap [] = { - {E_TYPE_DUMMY, "dummy"}, - {E_TYPE_DEATH_COUNT, "deathCount"}, - {E_TYPE_PLAYER_KILL_COUNT, "playerKillCount"}, - {E_TYPE_TOTAL_KILL_COUNT, "totalKillCount"}, - {E_TYPE_HEALTH, "health"}, - {E_TYPE_ACHIEVEMENT, "achievement"}, - {E_TYPE_STAT, "stat"}, - {E_TYPE_STAT_ITEM_CRAFT, "stat.craftItem"}, - {E_TYPE_STAT_ITEM_USE, "stat.useItem"}, - {E_TYPE_STAT_ITEM_BREAK, "stat.breakItem"}, - {E_TYPE_STAT_BLOCK_MINE, "stat.mineBlock"}, - {E_TYPE_STAT_ENTITY_KILL, "stat.killEntity"}, - {E_TYPE_STAT_ENTITY_KILLED_BY, "stat.entityKilledBy"} + {otDummy, "dummy" }, + {otDeathCount, "deathCount" }, + {otPlayerKillCount, "playerKillCount" }, + {otTotalKillCount, "totalKillCount" }, + {otHealth, "health" }, + {otAchievement, "achievement" }, + {otStat, "stat" }, + {otStatItemCraft, "stat.craftItem" }, + {otStatItemUse, "stat.useItem" }, + {otStatItemBreak, "stat.breakItem" }, + {otStatBlockMine, "stat.mineBlock" }, + {otStatEntityKill, "stat.killEntity" }, + {otStatEntityKilledBy, "stat.entityKilledBy"} }; for (size_t i = 0; i < ARRAYCOUNT(TypeMap); i++) { @@ -67,7 +67,7 @@ cObjective::eType cObjective::StringToType(const AString & a_Name) return TypeMap[i].m_Type; } } // for i - TypeMap[] - return E_TYPE_DUMMY; + return otDummy; } @@ -246,6 +246,17 @@ void cTeam::Reset(void) +void cTeam::SetDisplayName(const AString & a_Name) +{ + m_DisplayName = a_Name; + + // TODO 2014-03-01 xdot: Update clients +} + + + + + unsigned int cTeam::GetNumPlayers(void) const { return m_Players.size(); @@ -257,7 +268,7 @@ unsigned int cTeam::GetNumPlayers(void) const cScoreboard::cScoreboard(cWorld * a_World) : m_World(a_World) { - for (int i = 0; i < (int) E_DISPLAY_SLOT_COUNT; ++i) + for (int i = 0; i < (int) dsCount; ++i) { m_Display[i] = NULL; } @@ -306,6 +317,8 @@ bool cScoreboard::RemoveObjective(const AString & a_Name) ASSERT(m_World != NULL); m_World->BroadcastScoreboardObjective(it->second.GetName(), it->second.GetDisplayName(), 1); + // TODO 2014-03-01 xdot: Remove objective from display slot + return true; } @@ -410,7 +423,7 @@ cTeam * cScoreboard::QueryPlayerTeam(const AString & a_Name) void cScoreboard::SetDisplay(const AString & a_Objective, eDisplaySlot a_Slot) { - ASSERT(a_Slot < E_DISPLAY_SLOT_COUNT); + ASSERT(a_Slot < dsCount); cObjective * Objective = GetObjective(a_Objective); @@ -435,7 +448,7 @@ void cScoreboard::SetDisplay(cObjective * a_Objective, eDisplaySlot a_Slot) cObjective * cScoreboard::GetObjectiveIn(eDisplaySlot a_Slot) { - ASSERT(a_Slot < E_DISPLAY_SLOT_COUNT); + ASSERT(a_Slot < dsCount); return m_Display[a_Slot]; } @@ -444,7 +457,7 @@ cObjective * cScoreboard::GetObjectiveIn(eDisplaySlot a_Slot) -void cScoreboard::ForEachObjectiveWith(cObjective::eType a_Type, cObjectiveCallback& a_Callback) +bool cScoreboard::ForEachObjectiveWith(cObjective::eType a_Type, cObjectiveCallback& a_Callback) { cCSLock Lock(m_CSObjectives); @@ -455,10 +468,66 @@ void cScoreboard::ForEachObjectiveWith(cObjective::eType a_Type, cObjectiveCallb // Call callback if (a_Callback.Item(&it->second)) { - return; + return false; } } } + return true; +} + + + + + +bool cScoreboard::ForEachObjective(cObjectiveCallback& a_Callback) +{ + cCSLock Lock(m_CSObjectives); + + for (cObjectiveMap::iterator it = m_Objectives.begin(); it != m_Objectives.end(); ++it) + { + // Call callback + if (a_Callback.Item(&it->second)) + { + return false; + } + } + return true; +} + + + + + +bool cScoreboard::ForEachTeam(cTeamCallback& a_Callback) +{ + cCSLock Lock(m_CSObjectives); + + for (cTeamMap::iterator it = m_Teams.begin(); it != m_Teams.end(); ++it) + { + // Call callback + if (a_Callback.Item(&it->second)) + { + return false; + } + } + return true; +} + + + + + +void cScoreboard::AddPlayerScore(const AString & a_Name, cObjective::eType a_Type, cObjective::Score a_Value) +{ + cCSLock Lock(m_CSObjectives); + + for (cObjectiveMap::iterator it = m_Objectives.begin(); it != m_Objectives.end(); ++it) + { + if (it->second.GetType() == a_Type) + { + it->second.AddScore(a_Name, a_Value); + } + } } @@ -474,7 +543,7 @@ void cScoreboard::SendTo(cClientHandle & a_Client) it->second.SendTo(a_Client); } - for (int i = 0; i < (int) E_DISPLAY_SLOT_COUNT; ++i) + for (int i = 0; i < (int) dsCount; ++i) { // Avoid race conditions cObjective * Objective = m_Display[i]; diff --git a/src/Scoreboard.h b/src/Scoreboard.h index f64ba2bce..e22ecaeb1 100644 --- a/src/Scoreboard.h +++ b/src/Scoreboard.h @@ -14,9 +14,11 @@ class cObjective; +class cTeam; class cWorld; typedef cItemCallback<cObjective> cObjectiveCallback; +typedef cItemCallback<cTeam> cTeamCallback; @@ -31,23 +33,23 @@ public: enum eType { - E_TYPE_DUMMY, + otDummy, - E_TYPE_DEATH_COUNT, - E_TYPE_PLAYER_KILL_COUNT, - E_TYPE_TOTAL_KILL_COUNT, - E_TYPE_HEALTH, + otDeathCount, + otPlayerKillCount, + otTotalKillCount, + otHealth, - E_TYPE_ACHIEVEMENT, + otAchievement, - E_TYPE_STAT, - E_TYPE_STAT_ITEM_CRAFT, - E_TYPE_STAT_ITEM_USE, - E_TYPE_STAT_ITEM_BREAK, + otStat, + otStatItemCraft, + otStatItemUse, + otStatItemBreak, - E_TYPE_STAT_BLOCK_MINE, - E_TYPE_STAT_ENTITY_KILL, - E_TYPE_STAT_ENTITY_KILLED_BY + otStatBlockMine, + otStatEntityKill, + otStatEntityKilledBy }; // tolua_end @@ -67,31 +69,37 @@ public: const AString & GetName(void) const { return m_Name; } const AString & GetDisplayName(void) const { return m_DisplayName; } - /// Resets the objective + /** Resets the objective */ void Reset(void); - /// Returns the score of the specified player + /** Returns the score of the specified player */ Score GetScore(const AString & a_Name) const; - /// Sets the score of the specified player + /** Sets the score of the specified player */ void SetScore(const AString & a_Name, Score a_Score); - /// Resets the score of the specified player + /** Resets the score of the specified player */ void ResetScore(const AString & a_Name); - /// Adds a_Delta and returns the new score + /** Adds a_Delta and returns the new score */ Score AddScore(const AString & a_Name, Score a_Delta); - /// Subtracts a_Delta and returns the new score + /** Subtracts a_Delta and returns the new score */ Score SubScore(const AString & a_Name, Score a_Delta); void SetDisplayName(const AString & a_Name); // tolua_end - /// Send this objective to the specified client + /** Send this objective to the specified client */ void SendTo(cClientHandle & a_Client); + static const char * GetClassStatic(void) // Needed for ManualBindings's ForEach templates + { + return "cObjective"; + } + + private: typedef std::pair<AString, Score> cTrackedPlayer; @@ -109,7 +117,8 @@ private: friend class cScoreboardSerializer; -}; + +}; // tolua_export @@ -127,21 +136,21 @@ public: const AString & a_Prefix, const AString & a_Suffix ); - /// Adds a new player to the team + // tolua_begin + + /** Adds a new player to the team */ bool AddPlayer(const AString & a_Name); - /// Removes a player from the team + /** Removes a player from the team */ bool RemovePlayer(const AString & a_Name); - /// Returns whether the specified player is in this team + /** Returns whether the specified player is in this team */ bool HasPlayer(const AString & a_Name) const; - /// Removes all registered players + /** Removes all registered players */ void Reset(void); - // tolua_begin - - /// Returns the number of registered players + /** Returns the number of registered players */ unsigned int GetNumPlayers(void) const; bool AllowsFriendlyFire(void) const { return m_AllowsFriendlyFire; } @@ -163,6 +172,11 @@ public: // tolua_end + static const char * GetClassStatic(void) // Needed for ManualBindings's ForEach templates + { + return "cTeam"; + } + private: typedef std::set<AString> cPlayerNameSet; @@ -180,7 +194,8 @@ private: friend class cScoreboardSerializer; -}; + +}; // tolua_export @@ -193,11 +208,11 @@ public: enum eDisplaySlot { - E_DISPLAY_SLOT_LIST = 0, - E_DISPLAY_SLOT_SIDEBAR, - E_DISPLAY_SLOT_NAME, + dsList = 0, + dsSidebar, + dsName, - E_DISPLAY_SLOT_COUNT + dsCount }; // tolua_end @@ -209,44 +224,61 @@ public: // tolua_begin - /// Registers a new scoreboard objective, returns the cObjective instance, NULL on name collision + /** Registers a new scoreboard objective, returns the cObjective instance, NULL on name collision */ cObjective * RegisterObjective(const AString & a_Name, const AString & a_DisplayName, cObjective::eType a_Type); - /// Removes a registered objective, returns true if operation was successful + /** Removes a registered objective, returns true if operation was successful */ bool RemoveObjective(const AString & a_Name); - /// Retrieves the objective with the specified name, NULL if not found + /** Retrieves the objective with the specified name, NULL if not found */ cObjective * GetObjective(const AString & a_Name); - /// Registers a new team, returns the cTeam instance, NULL on name collision + /** Registers a new team, returns the cTeam instance, NULL on name collision */ cTeam * RegisterTeam(const AString & a_Name, const AString & a_DisplayName, const AString & a_Prefix, const AString & a_Suffix); - /// Removes a registered team, returns true if operation was successful + /** Removes a registered team, returns true if operation was successful */ bool RemoveTeam(const AString & a_Name); - /// Retrieves the team with the specified name, NULL if not found + /** Retrieves the team with the specified name, NULL if not found */ cTeam * GetTeam(const AString & a_Name); - cTeam * QueryPlayerTeam(const AString & a_Name); // WARNING: O(n logn) - void SetDisplay(const AString & a_Objective, eDisplaySlot a_Slot); - void SetDisplay(cObjective * a_Objective, eDisplaySlot a_Slot); - cObjective * GetObjectiveIn(eDisplaySlot a_Slot); - /// Execute callback for each objective with the specified type - void ForEachObjectiveWith(cObjective::eType a_Type, cObjectiveCallback& a_Callback); - unsigned int GetNumObjectives(void) const; unsigned int GetNumTeams(void) const; + void AddPlayerScore(const AString & a_Name, cObjective::eType a_Type, cObjective::Score a_Value = 1); + // tolua_end - /// Send this scoreboard to the specified client + /** Send this scoreboard to the specified client */ void SendTo(cClientHandle & a_Client); + cTeam * QueryPlayerTeam(const AString & a_Name); // WARNING: O(n logn) + + /** Execute callback for each objective with the specified type + * + * Returns true if all objectives processed, false if the callback aborted by returning true. + */ + bool ForEachObjectiveWith(cObjective::eType a_Type, cObjectiveCallback& a_Callback); + + /** Execute callback for each objective. + * + * Returns true if all objectives have been processed, false if the callback aborted by returning true. + */ + bool ForEachObjective(cObjectiveCallback& a_Callback); // Exported in ManualBindings.cpp + + /** Execute callback for each team. + * + * Returns true if all teams have been processed, false if the callback aborted by returning true. + */ + bool ForEachTeam(cTeamCallback& a_Callback); // Exported in ManualBindings.cpp + + void SetDisplay(cObjective * a_Objective, eDisplaySlot a_Slot); + private: @@ -265,11 +297,12 @@ private: cWorld * m_World; - cObjective* m_Display[E_DISPLAY_SLOT_COUNT]; + cObjective * m_Display[dsCount]; friend class cScoreboardSerializer; -} ; + +}; // tolua_export diff --git a/src/Server.cpp b/src/Server.cpp index c60418b41..fcbcaa919 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -472,6 +472,8 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac if (split[0] == "reloadgroups") { cRoot::Get()->ReloadGroups(); + a_Output.Out("Groups reloaded!"); + a_Output.Finished(); return; } diff --git a/src/UI/SlotArea.cpp b/src/UI/SlotArea.cpp index bfcad3d92..88977e005 100644 --- a/src/UI/SlotArea.cpp +++ b/src/UI/SlotArea.cpp @@ -224,6 +224,24 @@ void cSlotArea::DblClicked(cPlayer & a_Player, int a_SlotNum) +void cSlotArea::OnPlayerAdded(cPlayer & a_Player) +{ + UNUSED(a_Player); +} + + + + + +void cSlotArea::OnPlayerRemoved(cPlayer & a_Player) +{ + UNUSED(a_Player); +} + + + + + void cSlotArea::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_Apply, bool a_KeepEmptySlots) { for (int i = 0; i < m_NumSlots; i++) @@ -447,6 +465,18 @@ void cSlotAreaCrafting::OnPlayerRemoved(cPlayer & a_Player) + +void cSlotAreaCrafting::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) +{ + UNUSED(a_ItemStack); + UNUSED(a_Player); + UNUSED(a_ShouldApply); + UNUSED(a_KeepEmptySlots); +} + + + + void cSlotAreaCrafting::ClickedResult(cPlayer & a_Player) { cItem & DraggingItem = a_Player.GetDraggingItem(); diff --git a/src/UI/SlotArea.h b/src/UI/SlotArea.h index d31c87e0c..25b367cff 100644 --- a/src/UI/SlotArea.h +++ b/src/UI/SlotArea.h @@ -48,10 +48,10 @@ public: virtual void DblClicked(cPlayer & a_Player, int a_SlotNum); /// Called when a new player opens the same parent window. The window already tracks the player. CS-locked. - virtual void OnPlayerAdded(cPlayer & a_Player) {} ; + virtual void OnPlayerAdded(cPlayer & a_Player); /// Called when one of the players closes the parent window. The window already doesn't track the player. CS-locked. - virtual void OnPlayerRemoved(cPlayer & a_Player) {} ; + virtual void OnPlayerRemoved(cPlayer & a_Player); /** Called to store as much of a_ItemStack in the area as possible. a_ItemStack is modified to reflect the change. The default implementation searches each slot for available space and distributes the stack there. @@ -226,7 +226,7 @@ public: virtual void OnPlayerRemoved(cPlayer & a_Player) override; // Distributing items into this area is completely disabled - virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override {} + virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override; protected: /// Maps player's EntityID -> current recipe; not a std::map because cCraftingGrid needs proper constructor params diff --git a/src/WorldStorage/FastNBT.h b/src/WorldStorage/FastNBT.h index a78b610cb..d68ebd54c 100644 --- a/src/WorldStorage/FastNBT.h +++ b/src/WorldStorage/FastNBT.h @@ -173,13 +173,14 @@ public: { ASSERT(m_Tags[a_Tag].m_Type == TAG_Float); - // Cause a compile-time error if sizeof(int) != sizeof(float) - char Check1[sizeof(int) - sizeof(float) + 1]; // sizeof(int) >= sizeof(float) - char Check2[sizeof(float) - sizeof(int) + 1]; // sizeof(float) >= sizeof(int) + // Cause a compile-time error if sizeof(float) != 4 + // If your platform produces a compiler error here, you'll need to add code that manually decodes 32-bit floats + char Check1[5 - sizeof(float)]; // Fails if sizeof(float) > 4 + char Check2[sizeof(float) - 3]; // Fails if sizeof(float) < 4 UNUSED(Check1); UNUSED(Check2); - int i = GetBEInt(m_Data + m_Tags[a_Tag].m_DataStart); + Int32 i = GetBEInt(m_Data + m_Tags[a_Tag].m_DataStart); float f; memcpy(&f, &i, sizeof(f)); return f; diff --git a/src/WorldStorage/ScoreboardSerializer.cpp b/src/WorldStorage/ScoreboardSerializer.cpp index 9b8b661c4..6c885bb45 100644 --- a/src/WorldStorage/ScoreboardSerializer.cpp +++ b/src/WorldStorage/ScoreboardSerializer.cpp @@ -173,13 +173,13 @@ void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer) a_Writer.BeginCompound("DisplaySlots"); - cObjective * Objective = m_ScoreBoard->GetObjectiveIn(cScoreboard::E_DISPLAY_SLOT_LIST); + cObjective * Objective = m_ScoreBoard->GetObjectiveIn(cScoreboard::dsList); a_Writer.AddString("slot_0", (Objective == NULL) ? "" : Objective->GetName()); - Objective = m_ScoreBoard->GetObjectiveIn(cScoreboard::E_DISPLAY_SLOT_SIDEBAR); + Objective = m_ScoreBoard->GetObjectiveIn(cScoreboard::dsSidebar); a_Writer.AddString("slot_1", (Objective == NULL) ? "" : Objective->GetName()); - Objective = m_ScoreBoard->GetObjectiveIn(cScoreboard::E_DISPLAY_SLOT_NAME); + Objective = m_ScoreBoard->GetObjectiveIn(cScoreboard::dsName); a_Writer.AddString("slot_2", (Objective == NULL) ? "" : Objective->GetName()); a_Writer.EndCompound(); // DisplaySlots @@ -280,7 +280,7 @@ bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT) { AString Name, DisplayName, Prefix, Suffix; - bool AllowsFriendlyFire = false, CanSeeFriendlyInvisible = false; + bool AllowsFriendlyFire = true, CanSeeFriendlyInvisible = false; int CurrLine = a_NBT.FindChildByName(Child, "Name"); if (CurrLine >= 0) @@ -346,7 +346,7 @@ bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT) { AString Name = a_NBT.GetString(CurrLine); - m_ScoreBoard->SetDisplay(Name, cScoreboard::E_DISPLAY_SLOT_LIST); + m_ScoreBoard->SetDisplay(Name, cScoreboard::dsList); } CurrLine = a_NBT.FindChildByName(DisplaySlots, "slot_1"); @@ -354,7 +354,7 @@ bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT) { AString Name = a_NBT.GetString(CurrLine); - m_ScoreBoard->SetDisplay(Name, cScoreboard::E_DISPLAY_SLOT_SIDEBAR); + m_ScoreBoard->SetDisplay(Name, cScoreboard::dsSidebar); } CurrLine = a_NBT.FindChildByName(DisplaySlots, "slot_2"); @@ -362,7 +362,7 @@ bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT) { AString Name = a_NBT.GetString(CurrLine); - m_ScoreBoard->SetDisplay(Name, cScoreboard::E_DISPLAY_SLOT_NAME); + m_ScoreBoard->SetDisplay(Name, cScoreboard::dsName); } return true; diff --git a/src/main.cpp b/src/main.cpp index 4d2801926..2ae8a413b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -243,31 +243,36 @@ int main( int argc, char **argv ) // Check if comm logging is to be enabled: for (int i = 0; i < argc; i++) { + AString Arg(argv[i]); if ( - (NoCaseCompare(argv[i], "/commlog") == 0) || - (NoCaseCompare(argv[i], "/logcomm") == 0) + (NoCaseCompare(Arg, "/commlog") == 0) || + (NoCaseCompare(Arg, "/logcomm") == 0) ) { g_ShouldLogCommIn = true; g_ShouldLogCommOut = true; } - if ( - (NoCaseCompare(argv[i], "/commlogin") == 0) || - (NoCaseCompare(argv[i], "/comminlog") == 0) || - (NoCaseCompare(argv[i], "/logcommin") == 0) + else if ( + (NoCaseCompare(Arg, "/commlogin") == 0) || + (NoCaseCompare(Arg, "/comminlog") == 0) || + (NoCaseCompare(Arg, "/logcommin") == 0) ) { g_ShouldLogCommIn = true; } - if ( - (NoCaseCompare(argv[i], "/commlogout") == 0) || - (NoCaseCompare(argv[i], "/commoutlog") == 0) || - (NoCaseCompare(argv[i], "/logcommout") == 0) + else if ( + (NoCaseCompare(Arg, "/commlogout") == 0) || + (NoCaseCompare(Arg, "/commoutlog") == 0) || + (NoCaseCompare(Arg, "/logcommout") == 0) ) { g_ShouldLogCommOut = true; } - } + else if (NoCaseCompare(Arg, "nooutbuf") == 0) + { + setvbuf(stdout, NULL, _IONBF, 0); + } + } // for i - argv[] #if !defined(ANDROID_NDK) try |