summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Bindings/ManualBindings.cpp58
-rw-r--r--src/BlockArea.cpp59
-rw-r--r--src/BlockArea.h9
-rw-r--r--src/BlockEntities/FurnaceEntity.cpp42
-rw-r--r--src/BlockEntities/FurnaceEntity.h8
-rw-r--r--src/Blocks/BlockButton.h6
-rw-r--r--src/Blocks/BlockCocoaPod.h4
-rw-r--r--src/Blocks/BlockLadder.h4
-rw-r--r--src/Blocks/BlockLever.h4
-rw-r--r--src/Blocks/BlockQuartz.h5
-rw-r--r--src/Blocks/BlockSideways.h4
-rw-r--r--src/Blocks/BlockTrapdoor.h7
-rw-r--r--src/Blocks/BlockTripwireHook.h8
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/ClientHandle.cpp58
-rw-r--r--src/ClientHandle.h4
-rw-r--r--src/CraftingRecipes.cpp9
-rw-r--r--src/Defines.h36
-rw-r--r--src/Entities/HangingEntity.h15
-rw-r--r--src/Entities/Player.h21
-rw-r--r--src/Generating/MineShafts.cpp7
-rw-r--r--src/Globals.h2
-rw-r--r--src/LineBlockTracer.cpp19
-rw-r--r--src/LoggerListeners.cpp20
-rw-r--r--src/LoggerListeners.h2
-rw-r--r--src/MobCensus.cpp4
-rw-r--r--src/OSSupport/CMakeLists.txt2
-rw-r--r--src/OSSupport/Event.cpp4
-rw-r--r--src/OSSupport/Semaphore.cpp107
-rw-r--r--src/OSSupport/Semaphore.h17
-rw-r--r--src/Protocol/Protocol.h6
-rw-r--r--src/Protocol/Protocol17x.cpp72
-rw-r--r--src/Protocol/Protocol17x.h6
-rw-r--r--src/Protocol/Protocol18x.cpp60
-rw-r--r--src/Protocol/Protocol18x.h6
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp60
-rw-r--r--src/Protocol/ProtocolRecognizer.h6
-rw-r--r--src/Root.cpp2
-rw-r--r--src/WorldStorage/FastNBT.cpp3
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.cpp5
-rw-r--r--src/main.cpp204
41 files changed, 699 insertions, 277 deletions
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index bce1891e2..7655d8c83 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -34,6 +34,7 @@
#include "../CompositeChat.h"
#include "../StringCompression.h"
#include "../CommandOutput.h"
+#include "../BuildInfo.h"
@@ -2079,6 +2080,50 @@ static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S)
+static int tolua_cRoot_GetBuildCommitID(lua_State * tolua_S)
+{
+ cLuaState L(tolua_S);
+ L.Push(BUILD_COMMIT_ID);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cRoot_GetBuildDateTime(lua_State * tolua_S)
+{
+ cLuaState L(tolua_S);
+ L.Push(BUILD_DATETIME);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cRoot_GetBuildID(lua_State * tolua_S)
+{
+ cLuaState L(tolua_S);
+ L.Push(BUILD_ID);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cRoot_GetBuildSeriesName(lua_State * tolua_S)
+{
+ cLuaState L(tolua_S);
+ L.Push(BUILD_SERIES_NAME);
+ return 1;
+}
+
+
+
+
+
static int tolua_cRoot_GetFurnaceRecipe(lua_State * tolua_S)
{
cLuaState L(tolua_S);
@@ -2092,7 +2137,8 @@ static int tolua_cRoot_GetFurnaceRecipe(lua_State * tolua_S)
}
// Check the input param:
- cItem * Input = (cItem *)tolua_tousertype(L, 2, nullptr);
+ cItem * Input = nullptr;
+ L.GetStackValue(2, Input);
if (Input == nullptr)
{
LOGWARNING("cRoot:GetFurnaceRecipe: the Input parameter is nil or missing.");
@@ -2109,9 +2155,9 @@ static int tolua_cRoot_GetFurnaceRecipe(lua_State * tolua_S)
}
// Push the output, number of ticks and input as the three return values:
- tolua_pushusertype(L, Recipe->Out, "const cItem");
- tolua_pushnumber (L, (lua_Number)(Recipe->CookTime));
- tolua_pushusertype(L, Recipe->In, "const cItem");
+ L.Push(Recipe->Out);
+ L.Push(Recipe->CookTime);
+ L.Push(Recipe->In);
return 3;
}
@@ -2868,6 +2914,10 @@ void cManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "DoWithPlayerByUUID", DoWith <cRoot, cPlayer, &cRoot::DoWithPlayerByUUID>);
tolua_function(tolua_S, "ForEachPlayer", ForEach<cRoot, cPlayer, &cRoot::ForEachPlayer>);
tolua_function(tolua_S, "ForEachWorld", ForEach<cRoot, cWorld, &cRoot::ForEachWorld>);
+ tolua_function(tolua_S, "GetBuildCommitID", tolua_cRoot_GetBuildCommitID);
+ tolua_function(tolua_S, "GetBuildDateTime", tolua_cRoot_GetBuildDateTime);
+ tolua_function(tolua_S, "GetBuildID", tolua_cRoot_GetBuildID);
+ tolua_function(tolua_S, "GetBuildSeriesName", tolua_cRoot_GetBuildSeriesName);
tolua_function(tolua_S, "GetFurnaceRecipe", tolua_cRoot_GetFurnaceRecipe);
tolua_endmodule(tolua_S);
diff --git a/src/BlockArea.cpp b/src/BlockArea.cpp
index 7982afc31..938351207 100644
--- a/src/BlockArea.cpp
+++ b/src/BlockArea.cpp
@@ -1665,6 +1665,65 @@ size_t cBlockArea::CountNonAirBlocks(void) const
+size_t cBlockArea::CountSpecificBlocks(BLOCKTYPE a_BlockType) const
+{
+ // If blocktypes are not valid, log a warning and return zero occurences:
+ if (m_BlockTypes == nullptr)
+ {
+ LOGWARNING("%s: BlockTypes not available!", __FUNCTION__);
+ return 0;
+ }
+
+ // Count the blocks:
+ size_t num = GetBlockCount();
+ size_t res = 0;
+ for (size_t i = 0; i < num; i++)
+ {
+ if (m_BlockTypes[i] == a_BlockType)
+ {
+ res++;
+ }
+ }
+ return res;
+}
+
+
+
+
+
+size_t cBlockArea::CountSpecificBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) const
+{
+ // If blocktypes are not valid, log a warning and return zero occurences:
+ if (m_BlockTypes == nullptr)
+ {
+ LOGWARNING("%s: BlockTypes not available!", __FUNCTION__);
+ return 0;
+ }
+
+ // If blockmetas are not valid, log a warning and count only blocktypes:
+ if (m_BlockMetas == nullptr)
+ {
+ LOGWARNING("%s: BlockMetas not available, comparing blocktypes only!", __FUNCTION__);
+ return CountSpecificBlocks(a_BlockType);
+ }
+
+ // Count the blocks:
+ size_t num = GetBlockCount();
+ size_t res = 0;
+ for (size_t i = 0; i < num; i++)
+ {
+ if ((m_BlockTypes[i] == a_BlockType) && (m_BlockMetas[i] == a_BlockMeta))
+ {
+ res++;
+ }
+ }
+ return res;
+}
+
+
+
+
+
void cBlockArea::GetNonAirCropRelCoords(int & a_MinRelX, int & a_MinRelY, int & a_MinRelZ, int & a_MaxRelX, int & a_MaxRelY, int & a_MaxRelZ, BLOCKTYPE a_IgnoreBlockType)
{
// Check if blocktypes are valid:
diff --git a/src/BlockArea.h b/src/BlockArea.h
index 4b672029b..a9963b4ef 100644
--- a/src/BlockArea.h
+++ b/src/BlockArea.h
@@ -308,6 +308,15 @@ public:
Returns 0 if blocktypes not available. Block metas are ignored (if present, air with any meta is still considered air). */
size_t CountNonAirBlocks(void) const;
+ /** Returns how many times the specified block is contained in the area.
+ The blocks' meta values are ignored, only the blocktype is compared. */
+ size_t CountSpecificBlocks(BLOCKTYPE a_BlockType) const;
+
+ /** Returns how many times the specified block is contained in the area.
+ Both the block's type and meta must match in order to be counted in.
+ If the block metas aren't present in the area, logs a warning and ignores the meta specification. */
+ size_t CountSpecificBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) const;
+
// tolua_end
/** Returns the minimum and maximum coords in each direction for the first non-ignored block in each direction.
diff --git a/src/BlockEntities/FurnaceEntity.cpp b/src/BlockEntities/FurnaceEntity.cpp
index 2621b560b..d1588160d 100644
--- a/src/BlockEntities/FurnaceEntity.cpp
+++ b/src/BlockEntities/FurnaceEntity.cpp
@@ -32,7 +32,8 @@ cFurnaceEntity::cFurnaceEntity(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTY
m_NeedCookTime(0),
m_TimeCooked(0),
m_FuelBurnTime(0),
- m_TimeBurned(0)
+ m_TimeBurned(0),
+ m_IsLoading(false)
{
m_Contents.AddListener(*this);
}
@@ -178,20 +179,15 @@ void cFurnaceEntity::BurnNewFuel(void)
{
cFurnaceRecipe * FR = cRoot::Get()->GetFurnaceRecipe();
int NewTime = FR->GetBurnTime(m_Contents.GetSlot(fsFuel));
- if (NewTime == 0)
+ if ((NewTime == 0) || !CanCookInputToOutput())
{
// The item in the fuel slot is not suitable
+ // or the input and output isn't available for cooking
SetBurnTimes(0, 0);
SetIsCooking(false);
return;
}
- // Is the input and output ready for cooking?
- if (!CanCookInputToOutput())
- {
- return;
- }
-
// Burn one new fuel:
SetBurnTimes(NewTime, 0);
SetIsCooking(true);
@@ -218,6 +214,11 @@ void cFurnaceEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
return;
}
+ if (m_IsLoading)
+ {
+ return;
+ }
+
ASSERT(a_ItemGrid == &m_Contents);
switch (a_SlotNum)
{
@@ -238,7 +239,10 @@ void cFurnaceEntity::UpdateInput(void)
if (!m_Contents.GetSlot(fsInput).IsEqual(m_LastInput))
{
// The input is different from what we had before, reset the cooking time
- m_TimeCooked = 0;
+ if (!m_IsLoading)
+ {
+ m_TimeCooked = 0;
+ }
}
m_LastInput = m_Contents.GetSlot(fsInput);
@@ -253,13 +257,17 @@ void cFurnaceEntity::UpdateInput(void)
else
{
m_NeedCookTime = m_CurrentRecipe->CookTime;
- SetIsCooking(true);
// Start burning new fuel if there's no flame now:
if (GetFuelBurnTimeLeft() <= 0)
{
BurnNewFuel();
}
+ // Already burning, set cooking to ensure that cooking is occuring
+ else
+ {
+ SetIsCooking(true);
+ }
}
}
@@ -293,11 +301,19 @@ void cFurnaceEntity::UpdateOutput(void)
return;
}
- // No need to burn new fuel, the Tick() function will take care of that
-
// Can cook, start cooking if not already underway:
m_NeedCookTime = m_CurrentRecipe->CookTime;
- SetIsCooking(m_FuelBurnTime > 0);
+
+ // Check if fuel needs to start a burn
+ if (GetFuelBurnTimeLeft() <= 0)
+ {
+ BurnNewFuel();
+ }
+ // Already burning, set cooking to ensure that cooking is occuring
+ else
+ {
+ SetIsCooking(true);
+ }
}
diff --git a/src/BlockEntities/FurnaceEntity.h b/src/BlockEntities/FurnaceEntity.h
index 8b3ba3e36..8734d763c 100644
--- a/src/BlockEntities/FurnaceEntity.h
+++ b/src/BlockEntities/FurnaceEntity.h
@@ -101,6 +101,11 @@ public:
m_TimeCooked = a_TimeCooked;
}
+ void SetLoading(bool a_IsLoading)
+ {
+ m_IsLoading = a_IsLoading;
+ }
+
protected:
/** Block meta of the block currently represented by this entity */
@@ -129,6 +134,9 @@ protected:
/** Amount of ticks that the current fuel has been burning */
int m_TimeBurned;
+
+ /** Is the block currently being loaded into the world? */
+ bool m_IsLoading;
/** Sends the specified progressbar value to all clients of the window */
void BroadcastProgress(short a_ProgressbarID, short a_Value);
diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h
index d65d9722d..154cd610e 100644
--- a/src/Blocks/BlockButton.h
+++ b/src/Blocks/BlockButton.h
@@ -73,8 +73,13 @@ public:
return 0x0;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
+
inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta)
{
switch (a_Meta & 0x7)
@@ -93,6 +98,7 @@ public:
}
}
+
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
NIBBLETYPE Meta;
diff --git a/src/Blocks/BlockCocoaPod.h b/src/Blocks/BlockCocoaPod.h
index 50552c788..4d16d2552 100644
--- a/src/Blocks/BlockCocoaPod.h
+++ b/src/Blocks/BlockCocoaPod.h
@@ -89,6 +89,10 @@ public:
return 0;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
} ;
diff --git a/src/Blocks/BlockLadder.h b/src/Blocks/BlockLadder.h
index f49f1adc7..d727f8f8e 100644
--- a/src/Blocks/BlockLadder.h
+++ b/src/Blocks/BlockLadder.h
@@ -64,6 +64,10 @@ public:
return 0x2;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h
index 5792d280b..8d676b56f 100644
--- a/src/Blocks/BlockLever.h
+++ b/src/Blocks/BlockLever.h
@@ -67,6 +67,10 @@ public:
case BLOCK_FACE_YM: return 0x0;
case BLOCK_FACE_NONE: return 0x6;
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
diff --git a/src/Blocks/BlockQuartz.h b/src/Blocks/BlockQuartz.h
index 6f5c23902..b936a7e4a 100644
--- a/src/Blocks/BlockQuartz.h
+++ b/src/Blocks/BlockQuartz.h
@@ -36,6 +36,7 @@ public:
return true;
}
+
inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace, NIBBLETYPE a_QuartzMeta)
{
switch (a_BlockFace)
@@ -64,5 +65,9 @@ public:
return a_QuartzMeta; // No idea, give a special meta (all sides the same)
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
} ;
diff --git a/src/Blocks/BlockSideways.h b/src/Blocks/BlockSideways.h
index 74b05e33c..e52fbaa2f 100644
--- a/src/Blocks/BlockSideways.h
+++ b/src/Blocks/BlockSideways.h
@@ -64,6 +64,10 @@ public:
return a_Meta | 0xC; // No idea, give a special meta
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
} ;
diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h
index 2841e3e08..a1d2dff6f 100644
--- a/src/Blocks/BlockTrapdoor.h
+++ b/src/Blocks/BlockTrapdoor.h
@@ -66,6 +66,7 @@ public:
return true;
}
+
inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace)
{
switch (a_BlockFace)
@@ -82,8 +83,13 @@ public:
return 0;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
+
inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta)
{
switch (a_Meta & 0x3)
@@ -100,6 +106,7 @@ public:
}
}
+
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
NIBBLETYPE Meta;
diff --git a/src/Blocks/BlockTripwireHook.h b/src/Blocks/BlockTripwireHook.h
index c7a96d393..39892af5a 100644
--- a/src/Blocks/BlockTripwireHook.h
+++ b/src/Blocks/BlockTripwireHook.h
@@ -16,6 +16,7 @@ public:
{
}
+
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
@@ -29,6 +30,7 @@ public:
return true;
}
+
inline static NIBBLETYPE DirectionToMetadata(eBlockFace a_Direction)
{
switch (a_Direction)
@@ -45,8 +47,13 @@ public:
return 0x0;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
+
inline static eBlockFace MetadataToDirection(NIBBLETYPE a_Meta)
{
switch (a_Meta & 0x03)
@@ -59,6 +66,7 @@ public:
}
}
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to zero
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5556ddc4d..c68795bb3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -83,6 +83,7 @@ SET (HDRS
BlockTracer.h
Broadcaster.h
BoundingBox.h
+ BuildInfo.h
BuildInfo.h.cmake
ByteBuffer.h
ChatColor.h
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index e3f63b091..d89f7ab77 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -2113,6 +2113,64 @@ void cClientHandle::SendChat(const cCompositeChat & a_Message)
+void cClientHandle::SendChatAboveActionBar(const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData)
+{
+ cWorld * World = GetPlayer()->GetWorld();
+ if (World == nullptr)
+ {
+ World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName());
+ if (World == nullptr)
+ {
+ World = cRoot::Get()->GetDefaultWorld();
+ }
+ }
+
+ AString Message = FormatMessageType(World->ShouldUseChatPrefixes(), a_ChatPrefix, a_AdditionalData);
+ m_Protocol->SendChatAboveActionBar(Message.append(a_Message));
+}
+
+
+
+
+
+void cClientHandle::SendChatAboveActionBar(const cCompositeChat & a_Message)
+{
+ m_Protocol->SendChatAboveActionBar(a_Message);
+}
+
+
+
+
+
+void cClientHandle::SendChatSystem(const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData)
+{
+ cWorld * World = GetPlayer()->GetWorld();
+ if (World == nullptr)
+ {
+ World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName());
+ if (World == nullptr)
+ {
+ World = cRoot::Get()->GetDefaultWorld();
+ }
+ }
+
+ AString Message = FormatMessageType(World->ShouldUseChatPrefixes(), a_ChatPrefix, a_AdditionalData);
+ m_Protocol->SendChatSystem(Message.append(a_Message));
+}
+
+
+
+
+
+void cClientHandle::SendChatSystem(const cCompositeChat & a_Message)
+{
+ m_Protocol->SendChatSystem(a_Message);
+}
+
+
+
+
+
void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer)
{
ASSERT(m_Player != nullptr);
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index bcfa55825..13b5f87e4 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -150,6 +150,10 @@ public: // tolua_export
void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes);
void SendChat (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = "");
void SendChat (const cCompositeChat & a_Message);
+ void SendChatAboveActionBar (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = "");
+ void SendChatAboveActionBar (const cCompositeChat & a_Message);
+ void SendChatSystem (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = "");
+ void SendChatSystem (const cCompositeChat & a_Message);
void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer);
void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player);
void SendDestroyEntity (const cEntity & a_Entity);
diff --git a/src/CraftingRecipes.cpp b/src/CraftingRecipes.cpp
index a95ac5f84..c6a407d4b 100644
--- a/src/CraftingRecipes.cpp
+++ b/src/CraftingRecipes.cpp
@@ -168,7 +168,14 @@ void cCraftingGrid::ConsumeGrid(const cCraftingGrid & a_Grid)
m_Items[ThisIdx].m_ItemCount -= NumWantedItems;
if (m_Items[ThisIdx].m_ItemCount == 0)
{
- m_Items[ThisIdx].Clear();
+ if ((m_Items[ThisIdx].m_ItemType == E_ITEM_MILK) || (m_Items[ThisIdx].m_ItemType == E_ITEM_WATER_BUCKET) || (m_Items[ThisIdx].m_ItemType == E_ITEM_LAVA_BUCKET))
+ {
+ m_Items[ThisIdx] = cItem(E_ITEM_BUCKET, m_Items[ThisIdx].m_ItemCount);
+ }
+ else
+ {
+ m_Items[ThisIdx].Clear();
+ }
}
} // for x, for y
}
diff --git a/src/Defines.h b/src/Defines.h
index bbc69f79c..b167f69e3 100644
--- a/src/Defines.h
+++ b/src/Defines.h
@@ -133,6 +133,17 @@ enum eGameMode
+enum eChatType
+{
+ ctChatBox = 0,
+ ctSystem = 1,
+ ctAboveActionBar = 2,
+} ;
+
+
+
+
+
enum eWeather
{
eWeather_Sunny = 0,
@@ -245,6 +256,10 @@ inline eBlockFace MirrorBlockFaceY(eBlockFace a_BlockFace)
return a_BlockFace;
};
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return a_BlockFace;
+ #endif
}
@@ -267,6 +282,10 @@ inline eBlockFace RotateBlockFaceCCW(eBlockFace a_BlockFace)
return a_BlockFace;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return a_BlockFace;
+ #endif
}
@@ -288,8 +307,16 @@ inline eBlockFace RotateBlockFaceCW(eBlockFace a_BlockFace)
return a_BlockFace;
};
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return a_BlockFace;
+ #endif
}
+
+
+
+
inline eBlockFace ReverseBlockFace(eBlockFace a_BlockFace)
{
switch (a_BlockFace)
@@ -302,9 +329,16 @@ inline eBlockFace ReverseBlockFace(eBlockFace a_BlockFace)
case BLOCK_FACE_ZM: return BLOCK_FACE_ZP;
case BLOCK_FACE_NONE: return a_BlockFace;
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return a_BlockFace;
+ #endif
}
+
+
+
/** Returns the textual representation of the BlockFace constant. */
inline AString BlockFaceToString(eBlockFace a_BlockFace)
{
@@ -320,7 +354,7 @@ inline AString BlockFaceToString(eBlockFace a_BlockFace)
}
// clang optimisises this line away then warns that it has done so.
#if !defined(__clang__)
- return Printf("Unknown BLOCK_FACE: %d", a_BlockFace);
+ return Printf("Unknown BLOCK_FACE: %d", a_BlockFace);
#endif
}
diff --git a/src/Entities/HangingEntity.h b/src/Entities/HangingEntity.h
index 4d70cd1a0..5d0aa17b3 100644
--- a/src/Entities/HangingEntity.h
+++ b/src/Entities/HangingEntity.h
@@ -46,6 +46,9 @@ public:
protected:
+ Byte m_Facing;
+
+
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override
{
@@ -53,6 +56,7 @@ protected:
UNUSED(a_Chunk);
}
+
/** Converts protocol hanging item facing to eBlockFace values */
inline static eBlockFace ProtocolFaceToBlockFace(Byte a_ProtocolFace)
{
@@ -77,6 +81,7 @@ protected:
return Dir;
}
+
/** Converts eBlockFace values to protocol hanging item faces */
inline static Byte BlockFaceToProtocolFace(eBlockFace a_BlockFace)
{
@@ -99,13 +104,17 @@ protected:
Dir = cHangingEntity::BlockFaceToProtocolFace(BLOCK_FACE_XP);
}
+ #if !defined(__clang__)
+ default:
+ {
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ }
+ #endif
}
return Dir;
}
-
- Byte m_Facing;
-
}; // tolua_export
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index a84fdd0c7..799990bf2 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -235,14 +235,19 @@ public:
// tolua_begin
- void SendMessage (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtCustom); }
- void SendMessageInfo (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtInformation); }
- void SendMessageFailure (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); }
- void SendMessageSuccess (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtSuccess); }
- void SendMessageWarning (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtWarning); }
- void SendMessageFatal (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); }
- void SendMessagePrivateMsg(const AString & a_Message, const AString & a_Sender) { m_ClientHandle->SendChat(a_Message, mtPrivateMessage, a_Sender); }
- void SendMessage (const cCompositeChat & a_Message) { m_ClientHandle->SendChat(a_Message); }
+ void SendMessage (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtCustom); }
+ void SendMessageInfo (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtInformation); }
+ void SendMessageFailure (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); }
+ void SendMessageSuccess (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtSuccess); }
+ void SendMessageWarning (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtWarning); }
+ void SendMessageFatal (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); }
+ void SendMessagePrivateMsg (const AString & a_Message, const AString & a_Sender) { m_ClientHandle->SendChat(a_Message, mtPrivateMessage, a_Sender); }
+ void SendMessage (const cCompositeChat & a_Message) { m_ClientHandle->SendChat(a_Message); }
+
+ void SendSystemMessage (const AString & a_Message) { m_ClientHandle->SendChatSystem(a_Message, mtCustom); }
+ void SendAboveActionBarMessage(const AString & a_Message) { m_ClientHandle->SendChatAboveActionBar(a_Message, mtCustom); }
+ void SendSystemMessage (const cCompositeChat & a_Message) { m_ClientHandle->SendChatSystem(a_Message); }
+ void SendAboveActionBarMessage(const cCompositeChat & a_Message) { m_ClientHandle->SendChatAboveActionBar(a_Message); }
const AString & GetName(void) const { return m_PlayerName; }
void SetName(const AString & a_Name) { m_PlayerName = a_Name; }
diff --git a/src/Generating/MineShafts.cpp b/src/Generating/MineShafts.cpp
index 88dade240..4ba896ef6 100644
--- a/src/Generating/MineShafts.cpp
+++ b/src/Generating/MineShafts.cpp
@@ -787,6 +787,13 @@ void cMineShaftCorridor::PlaceChest(cChunkDesc & a_ChunkDesc)
Meta = E_META_CHEST_FACING_XP;
break;
}
+ #if !defined(__clang__)
+ default:
+ {
+ ASSERT(!"Unknown direction");
+ return;
+ }
+ #endif
} // switch (Dir)
if (
diff --git a/src/Globals.h b/src/Globals.h
index 8ff7b6894..b787a94da 100644
--- a/src/Globals.h
+++ b/src/Globals.h
@@ -220,6 +220,7 @@ template class SizeChecker<UInt8, 1>;
#include <semaphore.h>
#include <errno.h>
#include <fcntl.h>
+ #include <unistd.h>
#endif
#if defined(ANDROID_NDK)
@@ -264,7 +265,6 @@ template class SizeChecker<UInt8, 1>;
// Common headers (part 1, without macros):
#include "StringUtils.h"
#include "OSSupport/CriticalSection.h"
- #include "OSSupport/Semaphore.h"
#include "OSSupport/Event.h"
#include "OSSupport/File.h"
#include "Logger.h"
diff --git a/src/LineBlockTracer.cpp b/src/LineBlockTracer.cpp
index 315e8d082..587fa0e7c 100644
--- a/src/LineBlockTracer.cpp
+++ b/src/LineBlockTracer.cpp
@@ -154,38 +154,45 @@ bool cLineBlockTracer::MoveToNextBlock(void)
{
// Find out which of the current block's walls gets hit by the path:
static const double EPS = 0.00001;
- double Coeff = 1;
- enum eDirection
+ enum
{
dirNONE,
dirX,
dirY,
dirZ,
} Direction = dirNONE;
+
+ // Calculate the next YZ wall hit:
+ double Coeff = 1;
if (std::abs(m_DiffX) > EPS)
{
double DestX = (m_DirX > 0) ? (m_CurrentX + 1) : m_CurrentX;
- Coeff = (DestX - m_StartX) / m_DiffX;
- if (Coeff <= 1)
+ double CoeffX = (DestX - m_StartX) / m_DiffX;
+ if (CoeffX <= 1) // We need to include equality for the last block in the trace
{
+ Coeff = CoeffX;
Direction = dirX;
}
}
+
+ // If the next XZ wall hit is closer, use it instead:
if (std::abs(m_DiffY) > EPS)
{
double DestY = (m_DirY > 0) ? (m_CurrentY + 1) : m_CurrentY;
double CoeffY = (DestY - m_StartY) / m_DiffY;
- if (CoeffY < Coeff)
+ if (CoeffY <= Coeff) // We need to include equality for the last block in the trace
{
Coeff = CoeffY;
Direction = dirY;
}
}
+
+ // If the next XY wall hit is closer, use it instead:
if (std::abs(m_DiffZ) > EPS)
{
double DestZ = (m_DirZ > 0) ? (m_CurrentZ + 1) : m_CurrentZ;
double CoeffZ = (DestZ - m_StartZ) / m_DiffZ;
- if (CoeffZ < Coeff)
+ if (CoeffZ <= Coeff) // We need to include equality for the last block in the trace
{
Direction = dirZ;
}
diff --git a/src/LoggerListeners.cpp b/src/LoggerListeners.cpp
index 31b12af1e..132751e8e 100644
--- a/src/LoggerListeners.cpp
+++ b/src/LoggerListeners.cpp
@@ -238,8 +238,26 @@ public:
-cLogger::cListener * MakeConsoleListener(void)
+// Listener for when stdout is closed, i.e. When running as a daemon.
+class cNullConsoleListener
+ : public cLogger::cListener
+{
+ virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
+ {
+ }
+};
+
+
+
+
+
+cLogger::cListener * MakeConsoleListener(bool a_IsService)
{
+ if (a_IsService)
+ {
+ return new cNullConsoleListener;
+ }
+
#ifdef _WIN32
// See whether we are writing to a console the default console attrib:
bool ShouldColorOutput = (_isatty(_fileno(stdin)) != 0);
diff --git a/src/LoggerListeners.h b/src/LoggerListeners.h
index c419aa75a..a7f9a35a5 100644
--- a/src/LoggerListeners.h
+++ b/src/LoggerListeners.h
@@ -25,7 +25,7 @@ private:
-cLogger::cListener * MakeConsoleListener();
+cLogger::cListener * MakeConsoleListener(bool a_IsService);
diff --git a/src/MobCensus.cpp b/src/MobCensus.cpp
index ca960a2bc..79b5176d2 100644
--- a/src/MobCensus.cpp
+++ b/src/MobCensus.cpp
@@ -48,6 +48,10 @@ int cMobCensus::GetCapMultiplier(cMonster::eFamily a_MobFamily)
return -1;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown mob family");
+ return -1;
+ #endif
}
diff --git a/src/OSSupport/CMakeLists.txt b/src/OSSupport/CMakeLists.txt
index d1db0373d..df47394ae 100644
--- a/src/OSSupport/CMakeLists.txt
+++ b/src/OSSupport/CMakeLists.txt
@@ -15,7 +15,6 @@ SET (SRCS
IsThread.cpp
NetworkInterfaceEnum.cpp
NetworkSingleton.cpp
- Semaphore.cpp
ServerHandleImpl.cpp
StackTrace.cpp
TCPLinkImpl.cpp
@@ -34,7 +33,6 @@ SET (HDRS
Network.h
NetworkSingleton.h
Queue.h
- Semaphore.h
ServerHandleImpl.h
StackTrace.h
TCPLinkImpl.h
diff --git a/src/OSSupport/Event.cpp b/src/OSSupport/Event.cpp
index 760e536a1..38144ead3 100644
--- a/src/OSSupport/Event.cpp
+++ b/src/OSSupport/Event.cpp
@@ -1,8 +1,8 @@
// Event.cpp
-// Implements the cEvent object representing an OS-specific synchronization primitive that can be waited-for
-// Implemented as an Event on Win and as a 1-semaphore on *nix
+// Interfaces to the cEvent object representing a synchronization primitive that can be waited-for
+// Implemented using C++11 condition variable and mutex
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
diff --git a/src/OSSupport/Semaphore.cpp b/src/OSSupport/Semaphore.cpp
deleted file mode 100644
index 6a2d57901..000000000
--- a/src/OSSupport/Semaphore.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-
-
-
-
-cSemaphore::cSemaphore( unsigned int a_MaxCount, unsigned int a_InitialCount /* = 0 */)
-#ifndef _WIN32
- : m_bNamed( false)
-#endif
-{
-#ifndef _WIN32
- (void)a_MaxCount;
- m_Handle = new sem_t;
- if (sem_init( (sem_t*)m_Handle, 0, 0))
- {
- LOG("WARNING cSemaphore: Could not create unnamed semaphore, fallback to named.");
- delete (sem_t*)m_Handle; // named semaphores return their own address
- m_bNamed = true;
-
- AString Name;
- Printf(Name, "cSemaphore%p", this);
- m_Handle = sem_open(Name.c_str(), O_CREAT, 777, a_InitialCount);
- if (m_Handle == SEM_FAILED)
- {
- LOG("ERROR: Could not create Semaphore. (%i)", errno);
- }
- else
- {
- if (sem_unlink(Name.c_str()) != 0)
- {
- LOG("ERROR: Could not unlink cSemaphore. (%i)", errno);
- }
- }
- }
-#else
- m_Handle = CreateSemaphore(
- nullptr, // security attribute
- a_InitialCount, // initial count
- a_MaxCount, // maximum count
- 0 // name (optional)
- );
-#endif
-}
-
-
-
-
-
-cSemaphore::~cSemaphore()
-{
-#ifdef _WIN32
- CloseHandle( m_Handle);
-#else
- if (m_bNamed)
- {
- if (sem_close( (sem_t*)m_Handle) != 0)
- {
- LOG("ERROR: Could not close cSemaphore. (%i)", errno);
- }
- }
- else
- {
- sem_destroy( (sem_t*)m_Handle);
- delete (sem_t*)m_Handle;
- }
- m_Handle = 0;
-
-#endif
-}
-
-
-
-
-
-void cSemaphore::Wait()
-{
-#ifndef _WIN32
- if (sem_wait( (sem_t*)m_Handle) != 0)
- {
- LOG("ERROR: Could not wait for cSemaphore. (%i)", errno);
- }
-#else
- WaitForSingleObject( m_Handle, INFINITE);
-#endif
-}
-
-
-
-
-
-void cSemaphore::Signal()
-{
-#ifndef _WIN32
- if (sem_post( (sem_t*)m_Handle) != 0)
- {
- LOG("ERROR: Could not signal cSemaphore. (%i)", errno);
- }
-#else
- ReleaseSemaphore( m_Handle, 1, nullptr);
-#endif
-}
-
-
-
-
diff --git a/src/OSSupport/Semaphore.h b/src/OSSupport/Semaphore.h
deleted file mode 100644
index 57fa4bdb2..000000000
--- a/src/OSSupport/Semaphore.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-class cSemaphore
-{
-public:
- cSemaphore( unsigned int a_MaxCount, unsigned int a_InitialCount = 0);
- ~cSemaphore();
-
- void Wait();
- void Signal();
-private:
- void * m_Handle; // HANDLE pointer
-
-#ifndef _WIN32
- bool m_bNamed;
-#endif
-};
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index 7be72014a..1a19249bf 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -70,6 +70,12 @@ public:
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) = 0;
virtual void SendChat (const AString & a_Message) = 0;
virtual void SendChat (const cCompositeChat & a_Message) = 0;
+ virtual void SendChatAboveActionBar (const AString & a_Message) = 0;
+ virtual void SendChatAboveActionBar (const cCompositeChat & a_Message) = 0;
+ virtual void SendChatSystem (const AString & a_Message) = 0;
+ virtual void SendChatSystem (const cCompositeChat & a_Message) = 0;
+ virtual void SendChatType (const AString & a_Message, eChatType type) = 0;
+ virtual void SendChatType (const cCompositeChat & a_Message, eChatType type) = 0;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) = 0;
virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) = 0;
virtual void SendDestroyEntity (const cEntity & a_Entity) = 0;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 6aa36e2a5..3d96071b5 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -247,8 +247,67 @@ void cProtocol172::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockV
void cProtocol172::SendChat(const AString & a_Message)
{
+ this->SendChatType(a_Message, ctChatBox);
+}
+
+
+
+
+
+void cProtocol172::SendChat(const cCompositeChat & a_Message)
+{
+ this->SendChatType(a_Message, ctChatBox);
+}
+
+
+
+
+
+void cProtocol172::SendChatSystem(const AString & a_Message)
+{
+ this->SendChatType(a_Message, ctSystem);
+}
+
+
+
+
+
+void cProtocol172::SendChatSystem(const cCompositeChat & a_Message)
+{
+ this->SendChatType(a_Message, ctSystem);
+}
+
+
+
+
+
+void cProtocol172::SendChatAboveActionBar(const AString & a_Message)
+{
+ this->SendChatType(a_Message, ctAboveActionBar);
+}
+
+
+
+
+
+void cProtocol172::SendChatAboveActionBar(const cCompositeChat & a_Message)
+{
+ this->SendChatType(a_Message, ctAboveActionBar);
+}
+
+
+
+
+
+void cProtocol172::SendChatType(const AString & a_Message, eChatType type)
+{
ASSERT(m_State == 3); // In game mode?
-
+
+ if (type != ctChatBox) // 1.7.2 doesn't support anything else
+ {
+ return;
+ }
+
cPacketizer Pkt(*this, 0x02); // Chat Message packet
Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str()));
}
@@ -257,10 +316,15 @@ void cProtocol172::SendChat(const AString & a_Message)
-void cProtocol172::SendChat(const cCompositeChat & a_Message)
+void cProtocol172::SendChatType(const cCompositeChat & a_Message, eChatType type)
{
ASSERT(m_State == 3); // In game mode?
+ if (type != ctChatBox) // 1.7.2 doesn't support anything else
+ {
+ return;
+ }
+
cWorld * World = m_Client->GetPlayer()->GetWorld();
bool ShouldUseChatPrefixes = (World == nullptr) ? false : World->ShouldUseChatPrefixes();
@@ -1041,8 +1105,8 @@ void cProtocol172::SendExperience (void)
cPacketizer Pkt(*this, 0x1f); // Experience Packet
cPlayer * Player = m_Client->GetPlayer();
Pkt.WriteBEFloat(Player->GetXpPercentage());
- Pkt.WriteBEInt16(static_cast<Int16>(std::max<int>(Player->GetXpLevel(), std::numeric_limits<Int16>::max())));
- Pkt.WriteBEInt16(static_cast<Int16>(std::max<int>(Player->GetCurrentXp(), std::numeric_limits<Int16>::max())));
+ Pkt.WriteBEInt16(static_cast<Int16>(std::min<int>(Player->GetXpLevel(), std::numeric_limits<Int16>::max())));
+ Pkt.WriteBEInt16(static_cast<Int16>(std::min<int>(Player->GetCurrentXp(), std::numeric_limits<Int16>::max())));
}
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index ead2935b0..b07fa9ed9 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -68,6 +68,12 @@ public:
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override;
virtual void SendChat (const AString & a_Message) override;
virtual void SendChat (const cCompositeChat & a_Message) override;
+ virtual void SendChatAboveActionBar (const AString & a_Message) override;
+ virtual void SendChatAboveActionBar (const cCompositeChat & a_Message) override;
+ virtual void SendChatSystem (const AString & a_Message) override;
+ virtual void SendChatSystem (const cCompositeChat & a_Message) override;
+ virtual void SendChatType (const AString & a_Message, eChatType type) override;
+ virtual void SendChatType (const cCompositeChat & a_Message, eChatType type) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp
index d06022ce0..d9449283b 100644
--- a/src/Protocol/Protocol18x.cpp
+++ b/src/Protocol/Protocol18x.cpp
@@ -234,18 +234,72 @@ void cProtocol180::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockV
void cProtocol180::SendChat(const AString & a_Message)
{
+ this->SendChatType(a_Message, ctChatBox);
+}
+
+
+
+
+
+void cProtocol180::SendChat(const cCompositeChat & a_Message)
+{
+ this->SendChatType(a_Message, ctChatBox);
+}
+
+
+
+
+
+void cProtocol180::SendChatSystem(const AString & a_Message)
+{
+ this->SendChatType(a_Message, ctSystem);
+}
+
+
+
+
+
+void cProtocol180::SendChatSystem(const cCompositeChat & a_Message)
+{
+ this->SendChatType(a_Message, ctSystem);
+}
+
+
+
+
+
+void cProtocol180::SendChatAboveActionBar(const AString & a_Message)
+{
+ this->SendChatType(a_Message, ctAboveActionBar);
+}
+
+
+
+
+
+void cProtocol180::SendChatAboveActionBar(const cCompositeChat & a_Message)
+{
+ this->SendChatType(a_Message, ctAboveActionBar);
+}
+
+
+
+
+
+void cProtocol180::SendChatType(const AString & a_Message, eChatType type)
+{
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x02); // Chat Message packet
Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str()));
- Pkt.WriteBEInt8(0);
+ Pkt.WriteBEInt8(type);
}
-void cProtocol180::SendChat(const cCompositeChat & a_Message)
+void cProtocol180::SendChatType(const cCompositeChat & a_Message, eChatType type)
{
ASSERT(m_State == 3); // In game mode?
@@ -255,7 +309,7 @@ void cProtocol180::SendChat(const cCompositeChat & a_Message)
// Send the message to the client:
cPacketizer Pkt(*this, 0x02);
Pkt.WriteString(a_Message.CreateJsonString(ShouldUseChatPrefixes));
- Pkt.WriteBEInt8(0);
+ Pkt.WriteBEInt8(type);
}
diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h
index 6143e8b4e..36ed251fe 100644
--- a/src/Protocol/Protocol18x.h
+++ b/src/Protocol/Protocol18x.h
@@ -67,6 +67,12 @@ public:
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override;
virtual void SendChat (const AString & a_Message) override;
virtual void SendChat (const cCompositeChat & a_Message) override;
+ virtual void SendChatAboveActionBar (const AString & a_Message) override;
+ virtual void SendChatAboveActionBar (const cCompositeChat & a_Message) override;
+ virtual void SendChatSystem (const AString & a_Message) override;
+ virtual void SendChatSystem (const cCompositeChat & a_Message) override;
+ virtual void SendChatType (const AString & a_Message, eChatType type) override;
+ virtual void SendChatType (const cCompositeChat & a_Message, eChatType type) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index 477f2d71e..c89c745a4 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -158,6 +158,66 @@ void cProtocolRecognizer::SendChat(const cCompositeChat & a_Message)
+void cProtocolRecognizer::SendChatAboveActionBar(const AString & a_Message)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendChatAboveActionBar(a_Message);
+}
+
+
+
+
+
+void cProtocolRecognizer::SendChatAboveActionBar(const cCompositeChat & a_Message)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendChatAboveActionBar(a_Message);
+}
+
+
+
+
+
+void cProtocolRecognizer::SendChatSystem(const AString & a_Message)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendChatSystem(a_Message);
+}
+
+
+
+
+
+void cProtocolRecognizer::SendChatSystem(const cCompositeChat & a_Message)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendChatSystem(a_Message);
+}
+
+
+
+
+
+void cProtocolRecognizer::SendChatType(const AString & a_Message, eChatType type)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendChatType(a_Message, type);
+}
+
+
+
+
+
+void cProtocolRecognizer::SendChatType(const cCompositeChat & a_Message, eChatType type)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendChatType(a_Message, type);
+}
+
+
+
+
+
void cProtocolRecognizer::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer)
{
ASSERT(m_Protocol != nullptr);
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index 956b5dcc0..29eddcbc9 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -55,6 +55,12 @@ public:
virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override;
virtual void SendChat (const AString & a_Message) override;
virtual void SendChat (const cCompositeChat & a_Message) override;
+ virtual void SendChatAboveActionBar (const AString & a_Message) override;
+ virtual void SendChatAboveActionBar (const cCompositeChat & a_Message) override;
+ virtual void SendChatSystem (const AString & a_Message) override;
+ virtual void SendChatSystem (const cCompositeChat & a_Message) override;
+ virtual void SendChatType (const AString & a_Message, eChatType type) override;
+ virtual void SendChatType (const cCompositeChat & a_Message, eChatType type) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
diff --git a/src/Root.cpp b/src/Root.cpp
index 54e65b6da..8d344ee65 100644
--- a/src/Root.cpp
+++ b/src/Root.cpp
@@ -106,7 +106,7 @@ void cRoot::Start(std::unique_ptr<cSettingsRepositoryInterface> overridesRepo)
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 * consoleLogListener = MakeConsoleListener(m_RunAsService);
cLogger::cListener * fileLogListener = new cFileListener();
cLogger::GetInstance().AttachListener(consoleLogListener);
cLogger::GetInstance().AttachListener(fileLogListener);
diff --git a/src/WorldStorage/FastNBT.cpp b/src/WorldStorage/FastNBT.cpp
index f77197914..860eb3a4a 100644
--- a/src/WorldStorage/FastNBT.cpp
+++ b/src/WorldStorage/FastNBT.cpp
@@ -257,6 +257,9 @@ bool cParsedNBT::ReadTag(void)
return true;
}
+ #if !defined(__clang__)
+ default:
+ #endif
case TAG_Min:
{
ASSERT(!"Unhandled NBT tag type");
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 392b9bf83..8ca49c2c0 100755
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -1052,7 +1052,8 @@ cBlockEntity * cWSSAnvil::LoadFurnaceFromNBT(const cParsedNBT & a_NBT, int a_Tag
}
std::unique_ptr<cFurnaceEntity> Furnace(new cFurnaceEntity(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, m_World));
-
+ Furnace->SetLoading(true);
+
// Load slots:
for (int Child = a_NBT.GetFirstChild(Items); Child != -1; Child = a_NBT.GetNextSibling(Child))
{
@@ -1085,9 +1086,9 @@ cBlockEntity * cWSSAnvil::LoadFurnaceFromNBT(const cParsedNBT & a_NBT, int a_Tag
// Anvil doesn't store the time that an item takes to cook. We simply use the default - 10 seconds (200 ticks)
Furnace->SetCookTimes(200, ct);
}
-
// Restart cooking:
Furnace->ContinueCooking();
+ Furnace->SetLoading(false);
return Furnace.release();
}
diff --git a/src/main.cpp b/src/main.cpp
index 5cd057278..2103f3356 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -39,7 +39,7 @@ bool cRoot::m_RunAsService = false;
#if defined(_WIN32)
- SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
+ SERVICE_STATUS_HANDLE g_StatusHandle = nullptr;
HANDLE g_ServiceThread = INVALID_HANDLE_VALUE;
#define SERVICE_NAME "MCServerService"
#endif
@@ -145,7 +145,7 @@ Its purpose is to create the crashdump using the dbghlp DLLs
*/
LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_ExceptionInfo)
{
- char * newStack = &g_ExceptionStack[sizeof(g_ExceptionStack)];
+ char * newStack = &g_ExceptionStack[sizeof(g_ExceptionStack) - 1];
char * oldStack;
// Use the substitute stack:
@@ -249,7 +249,8 @@ void universalMain(std::unique_ptr<cSettingsRepositoryInterface> overridesRepo)
-#if defined(_WIN32)
+
+#if defined(_WIN32) // Windows service support.
////////////////////////////////////////////////////////////////////////////////
// serviceWorkerThread: Keep the service alive
@@ -266,6 +267,7 @@ DWORD WINAPI serviceWorkerThread(LPVOID lpParam)
+
////////////////////////////////////////////////////////////////////////////////
// serviceSetState: Set the internal status of the service
@@ -319,14 +321,10 @@ void WINAPI serviceCtrlHandler(DWORD CtrlCode)
void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
{
- #if defined(_DEBUG) && defined(DEBUG_SERVICE_STARTUP)
- Sleep(10000);
- #endif
-
char applicationFilename[MAX_PATH];
char applicationDirectory[MAX_PATH];
- GetModuleFileName(NULL, applicationFilename, sizeof(applicationFilename)); // This binary's file path.
+ GetModuleFileName(nullptr, applicationFilename, sizeof(applicationFilename)); // This binary's file path.
// Strip off the filename, keep only the path:
strncpy_s(applicationDirectory, sizeof(applicationDirectory), applicationFilename, (strrchr(applicationFilename, '\\') - applicationFilename));
@@ -337,8 +335,7 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
SetCurrentDirectory(applicationDirectory);
g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, serviceCtrlHandler);
-
- if (g_StatusHandle == NULL)
+ if (g_StatusHandle == nullptr)
{
OutputDebugStringA("RegisterServiceCtrlHandler() failed\n");
serviceSetState(0, SERVICE_STOPPED, GetLastError());
@@ -347,8 +344,9 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
serviceSetState(SERVICE_ACCEPT_STOP, SERVICE_RUNNING, 0);
- g_ServiceThread = CreateThread(NULL, 0, serviceWorkerThread, NULL, 0, NULL);
- if (g_ServiceThread == NULL)
+ DWORD ThreadID;
+ g_ServiceThread = CreateThread(nullptr, 0, serviceWorkerThread, nullptr, 0, &ThreadID);
+ if (g_ServiceThread == nullptr)
{
OutputDebugStringA("CreateThread() failed\n");
serviceSetState(0, SERVICE_STOPPED, GetLastError());
@@ -360,7 +358,9 @@ void WINAPI serviceMain(DWORD argc, TCHAR *argv[])
serviceSetState(0, SERVICE_STOPPED, 0);
}
-#endif
+#endif // Windows service support.
+
+
@@ -368,42 +368,33 @@ std::unique_ptr<cMemorySettingsRepository> parseArguments(int argc, char **argv)
{
try
{
+ // Parse the comand line args:
TCLAP::CmdLine cmd("MCServer");
-
- TCLAP::ValueArg<int> slotsArg("s", "max-players", "Maximum number of slots for the server to use, overrides setting in setting.ini", false, -1, "number", cmd);
-
- TCLAP::MultiArg<int> portsArg("p", "port", "The port number the server should listen to", false, "port", cmd);
-
- TCLAP::SwitchArg commLogArg("", "log-comm", "Log server client communications to file", cmd);
-
- TCLAP::SwitchArg commLogInArg("", "log-comm-in", "Log inbound server client communications to file", cmd);
-
- TCLAP::SwitchArg commLogOutArg("", "log-comm-out", "Log outbound server client communications to file", cmd);
-
- TCLAP::SwitchArg noBufArg("", "no-output-buffering", "Disable output buffering", cmd);
-
+ TCLAP::ValueArg<int> slotsArg ("s", "max-players", "Maximum number of slots for the server to use, overrides setting in setting.ini", false, -1, "number", cmd);
+ TCLAP::MultiArg<int> portsArg ("p", "port", "The port number the server should listen to", false, "port", cmd);
+ TCLAP::SwitchArg commLogArg ("", "log-comm", "Log server client communications to file", cmd);
+ TCLAP::SwitchArg commLogInArg ("", "log-comm-in", "Log inbound server client communications to file", cmd);
+ TCLAP::SwitchArg commLogOutArg ("", "log-comm-out", "Log outbound server client communications to file", cmd);
+ TCLAP::SwitchArg crashDumpFull ("", "crash-dump-full", "Crashdumps created by the server will contain full server memory", cmd);
+ TCLAP::SwitchArg crashDumpGlobals("", "crash-dump-globals", "Crashdumps created by the server will contain the global variables' values", cmd);
+ TCLAP::SwitchArg noBufArg ("", "no-output-buffering", "Disable output buffering", cmd);
+ TCLAP::SwitchArg runAsServiceArg ("d", "service", "Run as a service on Windows, or daemon on UNIX like systems", cmd);
cmd.parse(argc, argv);
+ // Copy the parsed args' values into a settings repository:
auto repo = cpp14::make_unique<cMemorySettingsRepository>();
-
if (slotsArg.isSet())
{
-
int slots = slotsArg.getValue();
-
repo->AddValue("Server", "MaxPlayers", static_cast<Int64>(slots));
-
}
-
if (portsArg.isSet())
{
- std::vector<int> ports = portsArg.getValue();
- for (auto port : ports)
+ for (auto port: portsArg.getValue())
{
repo->AddValue("Server", "Port", static_cast<Int64>(port));
}
}
-
if (commLogArg.getValue())
{
g_ShouldLogCommIn = true;
@@ -414,120 +405,133 @@ std::unique_ptr<cMemorySettingsRepository> parseArguments(int argc, char **argv)
g_ShouldLogCommIn = commLogInArg.getValue();
g_ShouldLogCommOut = commLogOutArg.getValue();
}
-
if (noBufArg.getValue())
{
setvbuf(stdout, nullptr, _IONBF, 0);
}
-
repo->SetReadOnly();
+ // Set the service flag directly to cRoot:
+ if (runAsServiceArg.getValue())
+ {
+ cRoot::m_RunAsService = true;
+ }
+
+ // Apply the CrashDump flags for platforms that support them:
+ #if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER) // 32-bit Windows app compiled in MSVC
+ if (crashDumpGlobals.getValue())
+ {
+ g_DumpFlags = static_cast<MINIDUMP_TYPE>(g_DumpFlags | MiniDumpWithDataSegs);
+ }
+ if (crashDumpFull.getValue())
+ {
+ g_DumpFlags = static_cast<MINIDUMP_TYPE>(g_DumpFlags | MiniDumpWithFullMemory);
+ }
+ #endif // 32-bit Windows app compiled in MSVC
+
return repo;
}
- catch (TCLAP::ArgException &e)
+ catch (const TCLAP::ArgException & exc)
{
- printf("error reading command line %s for arg %s", e.error().c_str(), e.argId().c_str());
+ printf("Error reading command line %s for arg %s", exc.error().c_str(), exc.argId().c_str());
return cpp14::make_unique<cMemorySettingsRepository>();
}
}
+
+
+
////////////////////////////////////////////////////////////////////////////////
// main:
int main(int argc, char **argv)
{
-
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
- InitLeakFinder();
+ InitLeakFinder();
#endif
// Magic code to produce dump-files on Windows if the server crashes:
- #if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER)
- HINSTANCE hDbgHelp = LoadLibrary("DBGHELP.DLL");
- g_WriteMiniDump = (pMiniDumpWriteDump)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
- if (g_WriteMiniDump != nullptr)
- {
- _snprintf_s(g_DumpFileName, ARRAYCOUNT(g_DumpFileName), _TRUNCATE, "crash_mcs_%x.dmp", GetCurrentProcessId());
- SetUnhandledExceptionFilter(LastChanceExceptionFilter);
-
- // Parse arguments for minidump flags:
- for (int i = 0; i < argc; i++)
+ #if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER) // 32-bit Windows app compiled in MSVC
+ HINSTANCE hDbgHelp = LoadLibrary("DBGHELP.DLL");
+ g_WriteMiniDump = (pMiniDumpWriteDump)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
+ if (g_WriteMiniDump != nullptr)
{
- if (_stricmp(argv[i], "/cdg") == 0)
- {
- // Add globals to the dump
- g_DumpFlags = (MINIDUMP_TYPE)(g_DumpFlags | MiniDumpWithDataSegs);
- }
- else if (_stricmp(argv[i], "/cdf") == 0)
- {
- // Add full memory to the dump (HUUUGE file)
- g_DumpFlags = (MINIDUMP_TYPE)(g_DumpFlags | MiniDumpWithFullMemory);
- }
- } // for i - argv[]
- }
- #endif // _WIN32 && !_WIN64
+ _snprintf_s(g_DumpFileName, ARRAYCOUNT(g_DumpFileName), _TRUNCATE, "crash_mcs_%x.dmp", GetCurrentProcessId());
+ SetUnhandledExceptionFilter(LastChanceExceptionFilter);
+ }
+ #endif // 32-bit Windows app compiled in MSVC
// End of dump-file magic
+
#if defined(_DEBUG) && defined(_MSC_VER)
- _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+ _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
- // _X: The simple built-in CRT leak finder - simply break when allocating the Nth block ({N} is listed in the leak output)
- // Only useful when the leak is in the same sequence all the time
- // _CrtSetBreakAlloc(85950);
+ // _X: The simple built-in CRT leak finder - simply break when allocating the Nth block ({N} is listed in the leak output)
+ // Only useful when the leak is in the same sequence all the time
+ // _CrtSetBreakAlloc(85950);
#endif // _DEBUG && _MSC_VER
#ifndef _DEBUG
- std::signal(SIGSEGV, NonCtrlHandler);
- std::signal(SIGTERM, NonCtrlHandler);
- std::signal(SIGINT, NonCtrlHandler);
- std::signal(SIGABRT, NonCtrlHandler);
- #ifdef SIGABRT_COMPAT
- std::signal(SIGABRT_COMPAT, NonCtrlHandler);
- #endif // SIGABRT_COMPAT
+ std::signal(SIGSEGV, NonCtrlHandler);
+ std::signal(SIGTERM, NonCtrlHandler);
+ std::signal(SIGINT, NonCtrlHandler);
+ std::signal(SIGABRT, NonCtrlHandler);
+ #ifdef SIGABRT_COMPAT
+ std::signal(SIGABRT_COMPAT, NonCtrlHandler);
+ #endif // SIGABRT_COMPAT
#endif
- // DEBUG: test the dumpfile creation:
- // *((int *)0) = 0;
-
auto argsRepo = parseArguments(argc, argv);
-
- // Check if comm logging is to be enabled:
- for (int i = 0; i < argc; i++)
- {
- AString Arg(argv[i]);
- if (NoCaseCompare(Arg, "/service") == 0)
- {
- cRoot::m_RunAsService = true;
- }
- } // for i - argv[]
- #if defined(_WIN32)
// Attempt to run as a service
if (cRoot::m_RunAsService)
{
- SERVICE_TABLE_ENTRY ServiceTable[] =
- {
- { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)serviceMain },
- { NULL, NULL }
- };
+ #if defined(_WIN32) // Windows service.
+ SERVICE_TABLE_ENTRY ServiceTable[] =
+ {
+ { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)serviceMain },
+ { nullptr, nullptr }
+ };
- if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
- {
- LOGERROR("Attempted, but failed, service startup.");
- return GetLastError();
- }
+ if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
+ {
+ LOGERROR("Attempted, but failed, service startup.");
+ return GetLastError();
+ }
+ #else // UNIX daemon.
+ pid_t pid = fork();
+
+ // fork() returns a negative value on error.
+ if (pid < 0)
+ {
+ LOGERROR("Could not fork process.");
+ return EXIT_FAILURE;
+ }
+
+ // Check if we are the parent or child process. Parent stops here.
+ if (pid > 0)
+ {
+ return EXIT_SUCCESS;
+ }
+
+ // Child process now goes quiet, running in the background.
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+
+ universalMain(std::move(argsRepo));
+ #endif
}
else
- #endif
{
// Not running as a service, do normal startup
universalMain(std::move(argsRepo));
}
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
- DeinitLeakFinder();
+ DeinitLeakFinder();
#endif
return EXIT_SUCCESS;