summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS3
-rw-r--r--Server/Plugins/DumpInfo/Init.lua4
-rw-r--r--Tools/QtBiomeVisualiser/ChunkSource.cpp7
-rwxr-xr-xcibuild.sh2
-rw-r--r--src/BlockEntities/BannerEntity.cpp37
-rw-r--r--src/BlockEntities/BannerEntity.h12
-rw-r--r--src/Blocks/BlockHandler.cpp7
-rw-r--r--src/Blocks/BlockStandingBanner.h (renamed from src/Blocks/BlockBanner.h)4
-rw-r--r--src/Blocks/BlockWallBanner.h64
-rw-r--r--src/Blocks/CMakeLists.txt3
-rw-r--r--src/ByteBuffer.cpp78
-rw-r--r--src/ClientHandle.cpp1
-rw-r--r--src/Endianness.h183
-rw-r--r--src/Entities/Player.cpp7
-rw-r--r--src/Generating/CompoGenBiomal.cpp5
-rw-r--r--src/Globals.h1
-rw-r--r--src/Items/ItemBanner.h4
-rw-r--r--src/Map.cpp10
-rw-r--r--src/Map.h3
-rw-r--r--src/MapManager.cpp37
-rw-r--r--src/MapManager.h4
-rw-r--r--src/Noise/InterpolNoise.h27
-rw-r--r--src/Noise/Noise.cpp45
-rw-r--r--src/OSSupport/ServerHandleImpl.cpp3
-rw-r--r--src/Protocol/Protocol_1_13.cpp6
-rw-r--r--src/Protocol/Protocol_1_14.cpp7
-rw-r--r--src/StringUtils.cpp59
-rw-r--r--src/StringUtils.h14
-rw-r--r--src/Vector3.h11
-rw-r--r--src/WorldStorage/FastNBT.cpp55
-rw-r--r--src/WorldStorage/FastNBT.h13
-rw-r--r--src/WorldStorage/FireworksSerializer.cpp4
-rw-r--r--src/WorldStorage/MapSerializer.cpp2
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp4
-rw-r--r--src/WorldStorage/WSSAnvil.cpp18
-rw-r--r--tests/HTTP/UrlClientTest.cpp56
36 files changed, 477 insertions, 323 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 660746445..1ef873ea8 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -9,6 +9,7 @@ as provided in the LICENSE file.
9caihezi
AirOne01
Altenius
+ashquarky
BasedDoge (Donated AlchemistVillage prefabs)
bearbin (Alexander Harkness)
beeduck
@@ -59,6 +60,7 @@ mcfadyeni
MeMuXin
mgueydan
MikeHunsinger
+mjagdis (Mike Jagdis)
Morritz (TJ)
morsmordere (Anzhelika Iugai)
mtilden
@@ -79,6 +81,7 @@ Schwertspize
Seadragon91 (Lukas Pioch)
sleirsgoevy (Sergey Lisov)
Sofapriester
+solvictor
Spekdrum (Pablo Beltran)
SphinxC0re
Spongecade (Updated wiki links)
diff --git a/Server/Plugins/DumpInfo/Init.lua b/Server/Plugins/DumpInfo/Init.lua
index 723ab3d94..6f51aa4a6 100644
--- a/Server/Plugins/DumpInfo/Init.lua
+++ b/Server/Plugins/DumpInfo/Init.lua
@@ -23,7 +23,7 @@ function HandleDumpPluginRequest(a_Request)
-- Check if it already was requested to dump a plugin.
if (a_Request.PostParams["DumpInfo"] ~= nil) then
local F = loadfile("Plugins/InfoDump.lua")
- F("Plugins/" .. a_Request.PostParams["DumpInfo"])
+ F("Plugins/" .. cPluginManager:Get():GetPluginFolderName(a_Request.PostParams["DumpInfo"]))
end
Content = Content .. [[
@@ -36,7 +36,7 @@ function HandleDumpPluginRequest(a_Request)
cPluginManager:Get():ForEachPlugin(
function(a_Plugin)
-- Check if there is a file called 'Info.lua'
- if (cFile:IsFile("Plugins/" .. a_Plugin:GetName() .. "/Info.lua")) then
+ if (cFile:IsFile(a_Plugin:GetLocalFolder() .. "/Info.lua")) then
Content = Content .. "\n<tr>\n"
Content = Content .. "\t<td>" .. a_Plugin:GetName() .. "</td>\n"
Content = Content .. "\t<td><form method='POST'> <input type='hidden' value='" .. a_Plugin:GetName() .. "' name='DumpInfo'> <input type='submit' value='DumpInfo'></form></td>\n"
diff --git a/Tools/QtBiomeVisualiser/ChunkSource.cpp b/Tools/QtBiomeVisualiser/ChunkSource.cpp
index ea3346f04..120b72474 100644
--- a/Tools/QtBiomeVisualiser/ChunkSource.cpp
+++ b/Tools/QtBiomeVisualiser/ChunkSource.cpp
@@ -5,6 +5,7 @@
#include "src/StringCompression.h"
#include "src/WorldStorage/FastNBT.h"
#include "src/IniFile.h"
+#include "src/Endianness.h"
@@ -143,7 +144,7 @@ public:
// Get the real data size:
const char * chunkData = m_FileData.data() + chunkOffset * 4096;
- UInt32 chunkSize = GetBEInt(chunkData);
+ UInt32 chunkSize = NetworkBufToHost(chunkData);
if ((chunkSize < 2) || (chunkSize / 4096 > numChunkSectors))
{
// Bad data, bail out
@@ -181,7 +182,7 @@ protected:
const char * hdr = m_FileData.data();
for (size_t i = 0; i < ARRAYCOUNT(m_Header); i++)
{
- m_Header[i] = GetBEInt(hdr + 4 * i);
+ m_Header[i] = NetworkBufToHost(hdr + 4 * i);
}
m_IsValid = true;
}
@@ -241,7 +242,7 @@ void AnvilSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, Chunk & a_DestChunk
const char * beBiomes = nbt.GetData(mcsBiomes);
for (size_t i = 0; i < ARRAYCOUNT(biomeMap); i++)
{
- biomeMap[i] = (EMCSBiome)GetBEInt(beBiomes + 4 * i);
+ biomeMap[i] = (EMCSBiome)NetworkBufToHost<Int32>(beBiomes + 4 * i);
}
a_DestChunk.setBiomes(biomeMap);
return;
diff --git a/cibuild.sh b/cibuild.sh
index 0c5dd4f31..fafed3be6 100755
--- a/cibuild.sh
+++ b/cibuild.sh
@@ -39,7 +39,7 @@ cmake --build . --parallel 3;
if [ `which ccache` ]; then
echo "Built with ccache, outputting cache stats..."
- ccache --show-stats
+ ccache --show-stats --verbose
fi
echo "Testing..."
diff --git a/src/BlockEntities/BannerEntity.cpp b/src/BlockEntities/BannerEntity.cpp
index f39263ac4..10f185bfd 100644
--- a/src/BlockEntities/BannerEntity.cpp
+++ b/src/BlockEntities/BannerEntity.cpp
@@ -13,18 +13,10 @@
-cBannerEntity::cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World) :
- cBannerEntity(a_BlockType, a_BlockMeta, a_Pos, a_World, 1)
-{
-}
-
-
-
-
-
-cBannerEntity::cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World, unsigned char a_BaseColor):
+cBannerEntity::cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World, unsigned char a_BaseColor, AString a_CustomName):
Super(a_BlockType, a_BlockMeta, a_Pos, a_World),
- m_BaseColor(a_BaseColor)
+ m_BaseColor(a_BaseColor),
+ m_CustomName(std::move(a_CustomName))
{
ASSERT((a_BlockType == E_BLOCK_WALL_BANNER) || (a_BlockType == E_BLOCK_STANDING_BANNER));
}
@@ -33,27 +25,11 @@ cBannerEntity::cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vect
-unsigned char cBannerEntity::GetBaseColor() const
-{
- return m_BaseColor;
-}
-
-
-
-
-
-void cBannerEntity::SetBaseColor(const unsigned char a_Color)
-{
- m_BaseColor = a_Color;
-}
-
-
-
-
-
cItems cBannerEntity::ConvertToPickups() const
{
- return cItem(E_ITEM_BANNER, 1, static_cast<NIBBLETYPE>(GetBaseColor()));
+ cItem Item(E_ITEM_BANNER, 1, static_cast<NIBBLETYPE>(GetBaseColor()));
+ Item.m_CustomName = m_CustomName;
+ return Item;
}
@@ -65,6 +41,7 @@ void cBannerEntity::CopyFrom(const cBlockEntity & a_Src)
Super::CopyFrom(a_Src);
auto & src = static_cast<const cBannerEntity &>(a_Src);
m_BaseColor = src.m_BaseColor;
+ m_CustomName = src.m_CustomName;
}
diff --git a/src/BlockEntities/BannerEntity.h b/src/BlockEntities/BannerEntity.h
index b6d27f53b..91ef87e8c 100644
--- a/src/BlockEntities/BannerEntity.h
+++ b/src/BlockEntities/BannerEntity.h
@@ -25,16 +25,20 @@ class cBannerEntity :
public:
- cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World);
- cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World, unsigned char a_BaseColor);
+ cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World, unsigned char a_BaseColor = 1, AString a_CustomName = "");
- unsigned char GetBaseColor() const;
- void SetBaseColor(unsigned char a_Color);
+ unsigned char GetBaseColor() const { return m_BaseColor; }
+ void SetBaseColor(unsigned char a_Color) { m_BaseColor = a_Color; }
+
+ const AString & GetCustomName() const { return m_CustomName; }
+ void SetCustomName(const AString & a_CustomName) { m_CustomName = a_CustomName; }
private:
unsigned char m_BaseColor;
+ AString m_CustomName;
+
// cBlockEntity overrides:
virtual cItems ConvertToPickups() const override;
virtual void CopyFrom(const cBlockEntity & a_Src) override;
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index 4b0d7e5ec..6691f151f 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -7,7 +7,6 @@
#include "BlockPluginInterface.h"
#include "BlockAir.h"
#include "BlockAnvil.h"
-#include "BlockBanner.h"
#include "BlockBed.h"
#include "BlockBigFlower.h"
#include "BlockBookShelf.h"
@@ -89,6 +88,7 @@
#include "BlockSnow.h"
#include "BlockSponge.h"
#include "BlockStairs.h"
+#include "BlockStandingBanner.h"
#include "BlockStems.h"
#include "BlockStone.h"
#include "BlockSugarCane.h"
@@ -99,6 +99,7 @@
#include "BlockTripwire.h"
#include "BlockTripwireHook.h"
#include "BlockVines.h"
+#include "BlockWallBanner.h"
#include "BlockWallSign.h"
#include "BlockWorkbench.h"
@@ -413,7 +414,7 @@ namespace
constexpr cDefaultBlockHandler BlockStainedClayHandler (E_BLOCK_STAINED_CLAY);
constexpr cBlockGlassHandler BlockStainedGlassHandler (E_BLOCK_STAINED_GLASS);
constexpr cBlockGlassHandler BlockStainedGlassPaneHandler (E_BLOCK_STAINED_GLASS_PANE);
- constexpr cBlockBannerHandler BlockStandingBannerHandler (E_BLOCK_STANDING_BANNER);
+ constexpr cBlockStandingBannerHandler BlockStandingBannerHandler (E_BLOCK_STANDING_BANNER);
constexpr cBlockLavaHandler BlockStationaryLavaHandler (E_BLOCK_STATIONARY_LAVA);
constexpr cBlockWaterHandler BlockStationaryWaterHandler (E_BLOCK_STATIONARY_WATER);
constexpr cBlockPistonHandler BlockStickyPistonHandler (E_BLOCK_STICKY_PISTON);
@@ -434,7 +435,7 @@ namespace
constexpr cBlockTripwireHandler BlockTripwireHandler (E_BLOCK_TRIPWIRE);
constexpr cBlockTripwireHookHandler BlockTripwireHookHandler (E_BLOCK_TRIPWIRE_HOOK);
constexpr cBlockVinesHandler BlockVinesHandler (E_BLOCK_VINES);
- constexpr cBlockBannerHandler BlockWallBannerHandler (E_BLOCK_WALL_BANNER);
+ constexpr cBlockWallBannerHandler BlockWallBannerHandler (E_BLOCK_WALL_BANNER);
constexpr cBlockWallSignHandler BlockWallsignHandler (E_BLOCK_WALLSIGN);
constexpr cBlockWaterHandler BlockWaterHandler (E_BLOCK_WATER);
constexpr cBlockGlazedTerracottaHandler BlockWhiteGlazedTerracottaHandler (E_BLOCK_WHITE_GLAZED_TERRACOTTA);
diff --git a/src/Blocks/BlockBanner.h b/src/Blocks/BlockStandingBanner.h
index e6a159bd4..391b7fde7 100644
--- a/src/Blocks/BlockBanner.h
+++ b/src/Blocks/BlockStandingBanner.h
@@ -1,5 +1,5 @@
-// BlockBanner.h
+// BlockStandingBanner.h
#pragma once
@@ -10,7 +10,7 @@
-class cBlockBannerHandler final :
+class cBlockStandingBannerHandler final :
public cBlockEntityHandler
{
using Super = cBlockEntityHandler;
diff --git a/src/Blocks/BlockWallBanner.h b/src/Blocks/BlockWallBanner.h
new file mode 100644
index 000000000..e0ebb8eee
--- /dev/null
+++ b/src/Blocks/BlockWallBanner.h
@@ -0,0 +1,64 @@
+
+// BlockWallBanner.h
+
+#pragma once
+
+#include "../BlockInfo.h"
+#include "BlockEntity.h"
+
+
+
+
+
+class cBlockWallBannerHandler final :
+ public cBlockEntityHandler
+{
+ using Super = cBlockEntityHandler;
+
+public:
+
+ using Super::Super;
+
+ virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
+ {
+ // Drops handled by the block entity:
+ return {};
+ }
+
+
+
+
+
+ virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
+ {
+ Vector3i Offset;
+
+ switch (a_Meta)
+ {
+ case BLOCK_FACE_ZM: Offset = Vector3i( 0, 0, 1); break;
+ case BLOCK_FACE_ZP: Offset = Vector3i( 0, 0, -1); break;
+ case BLOCK_FACE_XM: Offset = Vector3i( 1, 0, 0); break;
+ case BLOCK_FACE_XP: Offset = Vector3i(-1, 0, 0); break;
+ default: return false;
+ }
+
+ auto NeighborPos = a_Position + Offset;
+ BLOCKTYPE NeighborType;
+ if (!a_Chunk.UnboundedRelGetBlockType(NeighborPos, NeighborType))
+ {
+ // The neighbour is not accessible (unloaded chunk), we'll allow it for now.
+ return true;
+ }
+ return cBlockInfo::IsSolid(NeighborType);
+ }
+
+
+
+
+
+ virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
+ {
+ UNUSED(a_Meta);
+ return 0;
+ }
+} ;
diff --git a/src/Blocks/CMakeLists.txt b/src/Blocks/CMakeLists.txt
index a7dd7b675..38a60d5b7 100644
--- a/src/Blocks/CMakeLists.txt
+++ b/src/Blocks/CMakeLists.txt
@@ -9,7 +9,6 @@ target_sources(
BlockAir.h
BlockAnvil.h
- BlockBanner.h
BlockBed.h
BlockBigFlower.h
BlockBookShelf.h
@@ -94,6 +93,7 @@ target_sources(
BlockSnow.h
BlockSponge.h
BlockStairs.h
+ BlockStandingBanner.h
BlockStems.h
BlockStone.h
BlockSugarCane.h
@@ -104,6 +104,7 @@ target_sources(
BlockTripwire.h
BlockTripwireHook.h
BlockVines.h
+ BlockWallBanner.h
BlockWallSign.h
BlockWorkbench.h
BroadcastInterface.h
diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp
index 8121fc3ef..c5fe0a7c0 100644
--- a/src/ByteBuffer.cpp
+++ b/src/ByteBuffer.cpp
@@ -285,10 +285,9 @@ bool cByteBuffer::ReadBEInt16(Int16 & a_Value)
CHECK_THREAD
CheckValid();
NEEDBYTES(2);
- UInt16 val;
- ReadBuf(&val, 2);
- val = ntohs(val);
- memcpy(&a_Value, &val, 2);
+ Bytes<Int16> bytes;
+ ReadBuf(bytes.data(), bytes.size());
+ a_Value = NetworkToHost<Int16>(bytes);
return true;
}
@@ -301,8 +300,9 @@ bool cByteBuffer::ReadBEUInt16(UInt16 & a_Value)
CHECK_THREAD
CheckValid();
NEEDBYTES(2);
- ReadBuf(&a_Value, 2);
- a_Value = ntohs(a_Value);
+ Bytes<UInt16> bytes;
+ ReadBuf(bytes.data(), bytes.size());
+ a_Value = NetworkToHost<UInt16>(bytes);
return true;
}
@@ -315,10 +315,9 @@ bool cByteBuffer::ReadBEInt32(Int32 & a_Value)
CHECK_THREAD
CheckValid();
NEEDBYTES(4);
- UInt32 val;
- ReadBuf(&val, 4);
- val = ntohl(val);
- memcpy(&a_Value, &val, 4);
+ Bytes<Int32> bytes;
+ ReadBuf(bytes.data(), bytes.size());
+ a_Value = NetworkToHost<Int32>(bytes);
return true;
}
@@ -331,8 +330,9 @@ bool cByteBuffer::ReadBEUInt32(UInt32 & a_Value)
CHECK_THREAD
CheckValid();
NEEDBYTES(4);
- ReadBuf(&a_Value, 4);
- a_Value = ntohl(a_Value);
+ Bytes<UInt32> bytes;
+ ReadBuf(bytes.data(), bytes.size());
+ a_Value = NetworkToHost<UInt32>(bytes);
return true;
}
@@ -345,8 +345,9 @@ bool cByteBuffer::ReadBEInt64(Int64 & a_Value)
CHECK_THREAD
CheckValid();
NEEDBYTES(8);
- ReadBuf(&a_Value, 8);
- a_Value = NetworkToHostLong8(&a_Value);
+ Bytes<Int64> bytes;
+ ReadBuf(bytes.data(), bytes.size());
+ a_Value = NetworkToHost<Int64>(bytes);
return true;
}
@@ -359,8 +360,9 @@ bool cByteBuffer::ReadBEUInt64(UInt64 & a_Value)
CHECK_THREAD
CheckValid();
NEEDBYTES(8);
- ReadBuf(&a_Value, 8);
- a_Value = NetworkToHostULong8(&a_Value);
+ Bytes<UInt64> bytes;
+ ReadBuf(bytes.data(), bytes.size());
+ a_Value = NetworkToHost<UInt64>(bytes);
return true;
}
@@ -373,8 +375,9 @@ bool cByteBuffer::ReadBEFloat(float & a_Value)
CHECK_THREAD
CheckValid();
NEEDBYTES(4);
- ReadBuf(&a_Value, 4);
- a_Value = NetworkToHostFloat4(&a_Value);
+ Bytes<float> bytes;
+ ReadBuf(bytes.data(), bytes.size());
+ a_Value = NetworkToHost<float>(bytes);
return true;
}
@@ -387,8 +390,9 @@ bool cByteBuffer::ReadBEDouble(double & a_Value)
CHECK_THREAD
CheckValid();
NEEDBYTES(8);
- ReadBuf(&a_Value, 8);
- a_Value = NetworkToHostDouble8(&a_Value);
+ Bytes<double> bytes;
+ ReadBuf(bytes.data(), bytes.size());
+ a_Value = NetworkToHost<double>(bytes);
return true;
}
@@ -629,10 +633,8 @@ bool cByteBuffer::WriteBEInt16(Int16 a_Value)
CHECK_THREAD
CheckValid();
PUTBYTES(2);
- UInt16 val;
- memcpy(&val, &a_Value, 2);
- val = htons(val);
- return WriteBuf(&val, 2);
+ auto Converted = HostToNetwork(a_Value);
+ return WriteBuf(Converted.data(), Converted.size());
}
@@ -644,8 +646,8 @@ bool cByteBuffer::WriteBEUInt16(UInt16 a_Value)
CHECK_THREAD
CheckValid();
PUTBYTES(2);
- a_Value = htons(a_Value);
- return WriteBuf(&a_Value, 2);
+ auto Converted = HostToNetwork(a_Value);
+ return WriteBuf(Converted.data(), Converted.size());
}
@@ -657,8 +659,8 @@ bool cByteBuffer::WriteBEInt32(Int32 a_Value)
CHECK_THREAD
CheckValid();
PUTBYTES(4);
- UInt32 Converted = HostToNetwork4(&a_Value);
- return WriteBuf(&Converted, 4);
+ auto Converted = HostToNetwork(a_Value);
+ return WriteBuf(Converted.data(), Converted.size());
}
@@ -670,8 +672,8 @@ bool cByteBuffer::WriteBEUInt32(UInt32 a_Value)
CHECK_THREAD
CheckValid();
PUTBYTES(4);
- UInt32 Converted = HostToNetwork4(&a_Value);
- return WriteBuf(&Converted, 4);
+ auto Converted = HostToNetwork(a_Value);
+ return WriteBuf(Converted.data(), Converted.size());
}
@@ -683,8 +685,8 @@ bool cByteBuffer::WriteBEInt64(Int64 a_Value)
CHECK_THREAD
CheckValid();
PUTBYTES(8);
- UInt64 Converted = HostToNetwork8(&a_Value);
- return WriteBuf(&Converted, 8);
+ auto Converted = HostToNetwork(a_Value);
+ return WriteBuf(Converted.data(), Converted.size());
}
@@ -696,8 +698,8 @@ bool cByteBuffer::WriteBEUInt64(UInt64 a_Value)
CHECK_THREAD
CheckValid();
PUTBYTES(8);
- UInt64 Converted = HostToNetwork8(&a_Value);
- return WriteBuf(&Converted, 8);
+ auto Converted = HostToNetwork(a_Value);
+ return WriteBuf(Converted.data(), Converted.size());
}
@@ -709,8 +711,8 @@ bool cByteBuffer::WriteBEFloat(float a_Value)
CHECK_THREAD
CheckValid();
PUTBYTES(4);
- UInt32 Converted = HostToNetwork4(&a_Value);
- return WriteBuf(&Converted, 4);
+ auto Converted = HostToNetwork(a_Value);
+ return WriteBuf(Converted.data(), Converted.size());
}
@@ -722,8 +724,8 @@ bool cByteBuffer::WriteBEDouble(double a_Value)
CHECK_THREAD
CheckValid();
PUTBYTES(8);
- UInt64 Converted = HostToNetwork8(&a_Value);
- return WriteBuf(&Converted, 8);
+ auto Converted = HostToNetwork(a_Value);
+ return WriteBuf(Converted.data(), Converted.size());
}
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index b726e5c6f..01c95095a 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -74,6 +74,7 @@ cClientHandle::cClientHandle(const AString & a_IPString, int a_ViewDistance) :
m_IPString(a_IPString),
m_Player(nullptr),
m_CachedSentChunk(std::numeric_limits<decltype(m_CachedSentChunk.m_ChunkX)>::max(), std::numeric_limits<decltype(m_CachedSentChunk.m_ChunkZ)>::max()),
+ m_ProxyConnection(false),
m_HasSentDC(false),
m_LastStreamedChunkX(std::numeric_limits<decltype(m_LastStreamedChunkX)>::max()), // bogus chunk coords to force streaming upon login
m_LastStreamedChunkZ(std::numeric_limits<decltype(m_LastStreamedChunkZ)>::max()),
diff --git a/src/Endianness.h b/src/Endianness.h
index 0e8bc8e99..c75698587 100644
--- a/src/Endianness.h
+++ b/src/Endianness.h
@@ -1,86 +1,143 @@
-
#pragma once
-#undef ntohll
-#define ntohll(x) (((static_cast<UInt64>(ntohl(static_cast<UInt32>(x)))) << 32) + ntohl(x >> 32))
-
-
-
-
-
-// Changes endianness
-inline UInt64 HostToNetwork8(const void * a_Value)
+#include <array>
+template <typename T>
+using Bytes = std::array<std::byte, sizeof(T)>;
+
+// bit_cast used for going between ulong, float, etc. It's a new C++20 feature
+#ifdef __cpp_lib_bit_cast
+#include <bit>
+using std::bit_cast;
+
+// Fallback in case we're using C++17
+#else
+// bit-for-bit convert one type to another. In C++ the only non-UB way to do this is *memcpy*. Nearly every other
+// option is a strict aliasing violation.
+template<class To, class From>
+std::enable_if_t<
+ sizeof(To) == sizeof(From),
+ To>
+bit_cast(const From &src) noexcept
{
- UInt64 buf;
- memcpy( &buf, a_Value, sizeof( buf));
- buf = (( ( static_cast<UInt64>(htonl(static_cast<UInt32>(buf)))) << 32) + htonl(buf >> 32));
- return buf;
+ To dst;
+ std::memcpy(&dst, &src, sizeof(To));
+ return dst;
}
+#endif
-
-
-
-inline UInt32 HostToNetwork4(const void * a_Value)
+/** Converts a 16-bit host integer or float value to bytes in big-endian (Network) order.
+@tparam Value The host 16-bit type (Int16, UInt16). Usually inferred.
+@param a_Value The input integer or float value.
+@return The resulting bytes. */
+template<typename Value, std::enable_if_t<sizeof(Value) == 2, bool> = true>
+inline Bytes<Value> HostToNetwork(Value a_Value)
{
- UInt32 buf;
- memcpy( &buf, a_Value, sizeof( buf));
- buf = ntohl( buf);
- return buf;
+ UInt16 Bits = bit_cast<UInt16>(a_Value);
+ return
+ {
+ std::byte(Bits >> 8),
+ std::byte(Bits)
+ };
}
-
-
-
-
-inline double NetworkToHostDouble8(const void * a_Value)
+/** Converts a 32-bit host integer or float value to bytes in big-endian (Network) order.
+@tparam Value The host 32-bit type (Int32, UInt32, float). Usually inferred.
+@param a_Value The input integer or float value.
+@return The resulting bytes. */
+template<typename Value, std::enable_if_t<sizeof(Value) == 4, bool> = true>
+inline Bytes<Value> HostToNetwork(Value a_Value)
{
- UInt64 buf = 0;
- memcpy(&buf, a_Value, 8);
- buf = ntohll(buf);
- double x;
- memcpy(&x, &buf, sizeof(double));
- return x;
+ UInt32 Bits = bit_cast<UInt32>(a_Value);
+ return
+ {
+ std::byte(Bits >> 24),
+ std::byte(Bits >> 16),
+ std::byte(Bits >> 8),
+ std::byte(Bits)
+ };
}
-
-
-
-
-inline Int64 NetworkToHostLong8(const void * a_Value)
+/** Converts a 64-bit host integer or float value to bytes in big-endian (Network) order.
+@tparam Value The host 64-bit type (Int64, UInt64, double). Usually inferred.
+@param a_Value The input integer or float value.
+@return The resulting bytes. */
+template<typename Value, std::enable_if_t<sizeof(Value) == 8, bool> = true>
+inline Bytes<Value> HostToNetwork(Value a_Value)
{
- UInt64 buf;
- memcpy(&buf, a_Value, 8);
- buf = ntohll(buf);
- return *reinterpret_cast<Int64 *>(&buf);
+ UInt64 Bits = bit_cast<UInt64>(a_Value);
+ return
+ {
+ std::byte(Bits >> 56),
+ std::byte(Bits >> 48),
+ std::byte(Bits >> 40),
+ std::byte(Bits >> 32),
+ std::byte(Bits >> 24),
+ std::byte(Bits >> 16),
+ std::byte(Bits >> 8),
+ std::byte(Bits)
+ };
}
-
-
-
-
-inline UInt64 NetworkToHostULong8(const void * a_Value)
+/** Reads a 16-bit integer or float value from big-endian (Network) bytes.
+@tparam Value The desired 16-bit type (Int16, UInt16)
+@param a_Value The input bytes.
+@return The resulting integer or float value. */
+template<typename Value, std::enable_if_t<sizeof(Value) == 2, bool> = true>
+inline Value NetworkToHost(Bytes<Value> a_Value)
{
- UInt64 buf;
- memcpy(&buf, a_Value, 8);
- buf = ntohll(buf);
- return buf;
+ UInt16 val = UInt16(
+ UInt16(a_Value[0]) << 8 |
+ UInt16(a_Value[1]));
+ return bit_cast<Value>(val);
}
-
-
-
-
-inline float NetworkToHostFloat4(const void * a_Value)
+/** Reads a 32-bit integer or float value from big-endian (Network) bytes.
+@tparam Value The desired 32-bit type (Int32, UInt32, float)
+@param a_Value The input bytes.
+@return The resulting integer or float value. */
+template<typename Value, std::enable_if_t<sizeof(Value) == 4, bool> = true>
+inline Value NetworkToHost(Bytes<Value> a_Value)
{
- UInt32 buf;
- float x;
- memcpy(&buf, a_Value, 4);
- buf = ntohl(buf);
- memcpy(&x, &buf, sizeof(float));
- return x;
+ UInt32 val = UInt32(
+ UInt32(a_Value[0]) << 24 |
+ UInt32(a_Value[1]) << 16 |
+ UInt32(a_Value[2]) << 8 |
+ UInt32(a_Value[3]));
+ return bit_cast<Value>(val);
}
+/** Reads a 64-bit integer or float value from big-endian (Network) bytes.
+@tparam Value The desired 64-bit type (Int64, UInt64, double)
+@param a_Value The input bytes.
+@return The resulting integer or float value. */
+template<typename Value, std::enable_if_t<sizeof(Value) == 8, bool> = true>
+inline Value NetworkToHost(Bytes<Value> a_Value)
+{
+ UInt64 val = UInt64(
+ UInt64(a_Value[0]) << 56 |
+ UInt64(a_Value[1]) << 48 |
+ UInt64(a_Value[2]) << 40 |
+ UInt64(a_Value[3]) << 32 |
+ UInt64(a_Value[4]) << 24 |
+ UInt64(a_Value[5]) << 16 |
+ UInt64(a_Value[6]) << 8 |
+ UInt64(a_Value[7]));
+ return bit_cast<Value>(val);
+}
+/** Reads an integer or float type from its big-endian (Network) bytes.
+@tparam Value The desired result type (Int16 / 32 / 64, UInt16 / 32 / 64, float, double).
+@param a_Mem A pointer to the first input byte. Length is inferred from the result type.
+@return The resulting integer or float value.
-
+Consider using NetworkToHost when the data is owned since it provides additional type safety (length is known). */
+template<typename Value>
+inline Value NetworkBufToHost(const std::byte* a_Mem)
+{
+ // Copy unfortunately needed to add the length information required by the rest of the API.
+ // Gets completely optimised out in my testing.
+ Bytes<Value> bytes;
+ std::copy(a_Mem, a_Mem + sizeof(Value), bytes.begin());
+ return NetworkToHost<Value>(bytes);
+}
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index c580d8293..de99a299d 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -982,6 +982,13 @@ void cPlayer::Respawn(void)
TeleportToCoords(m_RespawnPosition.x, m_RespawnPosition.y, m_RespawnPosition.z);
}
+ // The Notchian client enters a weird glitched state when trying to "resurrect" dead players
+ // To prevent that, destroy the existing client-side entity, and create a new one with the same ID
+ // This does not make any difference to more modern clients
+ m_World->BroadcastDestroyEntity(*this, &*m_ClientHandle);
+ m_World->BroadcastSpawnEntity(*this, &*m_ClientHandle);
+
+
SetVisible(true);
}
diff --git a/src/Generating/CompoGenBiomal.cpp b/src/Generating/CompoGenBiomal.cpp
index 967a4a89c..fb7b89422 100644
--- a/src/Generating/CompoGenBiomal.cpp
+++ b/src/Generating/CompoGenBiomal.cpp
@@ -456,7 +456,10 @@ protected:
}
HasHadWater = true;
} // for y
- a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK);
+ if (a_ShapeColumn[0] > 0)
+ {
+ a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK);
+ }
}
diff --git a/src/Globals.h b/src/Globals.h
index 0b6ff8ac5..7c2af3d11 100644
--- a/src/Globals.h
+++ b/src/Globals.h
@@ -98,6 +98,7 @@
#include <arpa/inet.h>
#include <netinet/in.h>
+ #include <netinet/tcp.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
diff --git a/src/Items/ItemBanner.h b/src/Items/ItemBanner.h
index a404af336..551c41429 100644
--- a/src/Items/ItemBanner.h
+++ b/src/Items/ItemBanner.h
@@ -40,7 +40,9 @@ private:
{
ASSERT((a_BlockEntity.GetBlockType() == E_BLOCK_STANDING_BANNER) || (a_BlockEntity.GetBlockType() == E_BLOCK_WALL_BANNER));
- static_cast<cBannerEntity &>(a_BlockEntity).SetBaseColor(static_cast<NIBBLETYPE>(a_HeldItem.m_ItemDamage));
+ cBannerEntity & BannerEntity = static_cast<cBannerEntity &>(a_BlockEntity);
+ BannerEntity.SetBaseColor(static_cast<NIBBLETYPE>(a_HeldItem.m_ItemDamage));
+ BannerEntity.SetCustomName(a_HeldItem.m_CustomName);
return false;
});
diff --git a/src/Map.cpp b/src/Map.cpp
index 9e3c364b1..3691d0ab0 100644
--- a/src/Map.cpp
+++ b/src/Map.cpp
@@ -23,6 +23,7 @@ cMap::cMap(unsigned int a_ID, cWorld * a_World):
m_Scale(3),
m_CenterX(0),
m_CenterZ(0),
+ m_Dirty(false), // This constructor is for an empty map object which will be filled by the caller with the correct values - it does not need saving.
m_World(a_World),
m_Name(fmt::format(FMT_STRING("map_{}"), m_ID))
{
@@ -40,6 +41,7 @@ cMap::cMap(unsigned int a_ID, int a_CenterX, int a_CenterZ, cWorld * a_World, un
m_Scale(a_Scale),
m_CenterX(a_CenterX),
m_CenterZ(a_CenterZ),
+ m_Dirty(true), // This constructor is for creating a brand new map in game, it will always need saving.
m_World(a_World),
m_Name(fmt::format(FMT_STRING("map_{}"), m_ID))
{
@@ -223,7 +225,13 @@ bool cMap::SetPixel(unsigned int a_X, unsigned int a_Z, cMap::ColorID a_Data)
{
if ((a_X < m_Width) && (a_Z < m_Height))
{
- m_Data[a_Z * m_Width + a_X] = a_Data;
+ auto index = a_Z * m_Width + a_X;
+
+ if (m_Data[index] != a_Data)
+ {
+ m_Data[index] = a_Data;
+ m_Dirty = true;
+ }
return true;
}
diff --git a/src/Map.h b/src/Map.h
index 493b0883e..645f84c08 100644
--- a/src/Map.h
+++ b/src/Map.h
@@ -185,6 +185,8 @@ private:
int m_CenterX;
int m_CenterZ;
+ bool m_Dirty;
+
/** Column-major array of colours */
cColorList m_Data;
@@ -196,6 +198,7 @@ private:
AString m_Name;
+ friend class cMapManager;
friend class cMapSerializer;
}; // tolua_export
diff --git a/src/MapManager.cpp b/src/MapManager.cpp
index ae020d800..f7b393648 100644
--- a/src/MapManager.cpp
+++ b/src/MapManager.cpp
@@ -12,8 +12,16 @@
-cMapManager::cMapManager(cWorld * a_World)
- : m_World(a_World)
+// 6000 ticks or 5 minutes
+#define MAP_DATA_SAVE_INTERVAL 6000
+
+
+
+
+
+cMapManager::cMapManager(cWorld * a_World) :
+ m_World(a_World),
+ m_TicksUntilNextSave(MAP_DATA_SAVE_INTERVAL)
{
ASSERT(m_World != nullptr);
}
@@ -49,6 +57,16 @@ void cMapManager::TickMaps()
{
Map.Tick();
}
+
+ if (m_TicksUntilNextSave == 0)
+ {
+ m_TicksUntilNextSave = MAP_DATA_SAVE_INTERVAL;
+ SaveMapData();
+ }
+ else
+ {
+ m_TicksUntilNextSave--;
+ }
}
@@ -149,11 +167,18 @@ void cMapManager::SaveMapData(void)
{
cMap & Map = *it;
- cMapSerializer Serializer(m_World->GetDataPath(), &Map);
-
- if (!Serializer.Save())
+ if (Map.m_Dirty)
{
- LOGWARN("Could not save map #%i", Map.GetID());
+ cMapSerializer Serializer(m_World->GetDataPath(), &Map);
+
+ if (Serializer.Save())
+ {
+ Map.m_Dirty = false;
+ }
+ else
+ {
+ LOGWARN("Could not save map #%i", Map.GetID());
+ }
}
}
}
diff --git a/src/MapManager.h b/src/MapManager.h
index 8959b1d8b..d20fe6683 100644
--- a/src/MapManager.h
+++ b/src/MapManager.h
@@ -64,6 +64,10 @@ private:
cWorld * m_World;
+ /** How long till the map data will be saved
+ Default save interval is #defined in MAP_DATA_SAVE_INTERVAL */
+ unsigned int m_TicksUntilNextSave;
+
}; // tolua_export
diff --git a/src/Noise/InterpolNoise.h b/src/Noise/InterpolNoise.h
index 447796739..12b167dbe 100644
--- a/src/Noise/InterpolNoise.h
+++ b/src/Noise/InterpolNoise.h
@@ -427,28 +427,37 @@ public:
// Calculate query values using Cell:
int FromZ = 0;
- for (int z = 0; z < NumSameZ; z++)
+ for (int z = 0; z < NumSameZ;)
{
int ToZ = FromZ + SameZ[z];
int CurFloorZ = FloorZ[FromZ];
int FromY = 0;
- for (int y = 0; y < NumSameY; y++)
+ for (int y = 0; y < NumSameY;)
{
int ToY = FromY + SameY[y];
int CurFloorY = FloorY[FromY];
int FromX = 0;
- for (int x = 0; x < NumSameX; x++)
+ for (int x = 0; x < NumSameX;)
{
int ToX = FromX + SameX[x];
Cell.Generate(FromX, ToX, FromY, ToY, FromZ, ToZ);
- Cell.Move(FloorX[ToX], CurFloorY, CurFloorZ);
- FromX = ToX;
+ if (++x < NumSameX) // Call Move() every time except for the last loop iteration
+ {
+ Cell.Move(FloorX[ToX], CurFloorY, CurFloorZ);
+ FromX = ToX;
+ }
+ }
+ if (++y < NumSameY) // Call Move() every time except for the last loop iteration
+ {
+ Cell.Move(FloorX[0], FloorY[ToY], CurFloorZ);
+ FromY = ToY;
}
- Cell.Move(FloorX[0], FloorY[ToY], CurFloorZ);
- FromY = ToY;
} // for y
- Cell.Move(FloorX[0], FloorY[0], FloorZ[ToZ]);
- FromZ = ToZ;
+ if (++z < NumSameZ) // Call Move() every time except for the last loop iteration
+ {
+ Cell.Move(FloorX[0], FloorY[0], FloorZ[ToZ]);
+ FromZ = ToZ;
+ }
} // for z
}
diff --git a/src/Noise/Noise.cpp b/src/Noise/Noise.cpp
index cbdc6bc72..136d124a0 100644
--- a/src/Noise/Noise.cpp
+++ b/src/Noise/Noise.cpp
@@ -734,20 +734,26 @@ void cCubicNoise::Generate2D(
// Calculate query values using Cell:
int FromY = 0;
- for (int y = 0; y < NumSameY; y++)
+ for (int y = 0; y < NumSameY;)
{
int ToY = FromY + SameY[y];
int FromX = 0;
int CurFloorY = FloorY[FromY];
- for (int x = 0; x < NumSameX; x++)
+ for (int x = 0; x < NumSameX;)
{
int ToX = FromX + SameX[x];
Cell.Generate(FromX, ToX, FromY, ToY);
- Cell.Move(FloorX[ToX], CurFloorY);
- FromX = ToX;
+ if (++x < NumSameX) // Call Move() every time except for the last loop iteration
+ {
+ Cell.Move(FloorX[ToX], CurFloorY);
+ FromX = ToX;
+ }
+ }
+ if (++y < NumSameY) // Call Move() every time except for the last loop iteration
+ {
+ Cell.Move(FloorX[0], FloorY[ToY]);
+ FromY = ToY;
}
- Cell.Move(FloorX[0], FloorY[ToY]);
- FromY = ToY;
}
}
@@ -795,28 +801,37 @@ void cCubicNoise::Generate3D(
// Calculate query values using Cell:
int FromZ = 0;
- for (int z = 0; z < NumSameZ; z++)
+ for (int z = 0; z < NumSameZ;)
{
int ToZ = FromZ + SameZ[z];
int CurFloorZ = FloorZ[FromZ];
int FromY = 0;
- for (int y = 0; y < NumSameY; y++)
+ for (int y = 0; y < NumSameY;)
{
int ToY = FromY + SameY[y];
int CurFloorY = FloorY[FromY];
int FromX = 0;
- for (int x = 0; x < NumSameX; x++)
+ for (int x = 0; x < NumSameX;)
{
int ToX = FromX + SameX[x];
Cell.Generate(FromX, ToX, FromY, ToY, FromZ, ToZ);
- Cell.Move(FloorX[ToX], CurFloorY, CurFloorZ);
- FromX = ToX;
+ if (++x < NumSameX) // Call Move() every time except for the last loop iteration
+ {
+ Cell.Move(FloorX[ToX], CurFloorY, CurFloorZ);
+ FromX = ToX;
+ }
+ }
+ if (++y < NumSameY) // Call Move() every time except for the last loop iteration
+ {
+ Cell.Move(FloorX[0], FloorY[ToY], CurFloorZ);
+ FromY = ToY;
}
- Cell.Move(FloorX[0], FloorY[ToY], CurFloorZ);
- FromY = ToY;
} // for y
- Cell.Move(FloorX[0], FloorY[0], FloorZ[ToZ]);
- FromZ = ToZ;
+ if (++z < NumSameZ) // Call Move() every time except for the last loop iteration
+ {
+ Cell.Move(FloorX[0], FloorY[0], FloorZ[ToZ]);
+ FromZ = ToZ;
+ }
} // for z
}
diff --git a/src/OSSupport/ServerHandleImpl.cpp b/src/OSSupport/ServerHandleImpl.cpp
index e68f82757..669a0f83f 100644
--- a/src/OSSupport/ServerHandleImpl.cpp
+++ b/src/OSSupport/ServerHandleImpl.cpp
@@ -328,6 +328,9 @@ void cServerHandleImpl::Callback(evconnlistener * a_Listener, evutil_socket_t a_
return;
}
+ const int one = 1;
+ setsockopt(a_Socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char *>(&one), sizeof(one));
+
// Create a new cTCPLink for the incoming connection:
cTCPLinkImplPtr Link = std::make_shared<cTCPLinkImpl>(a_Socket, LinkCallbacks, Self->m_SelfPtr, a_Addr, static_cast<socklen_t>(a_Len));
{
diff --git a/src/Protocol/Protocol_1_13.cpp b/src/Protocol/Protocol_1_13.cpp
index eb452ec79..8bffe0f85 100644
--- a/src/Protocol/Protocol_1_13.cpp
+++ b/src/Protocol/Protocol_1_13.cpp
@@ -900,7 +900,11 @@ void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_
case cEntity::etItemFrame:
{
- // TODO
+ const auto & Frame = static_cast<const cItemFrame &>(a_Entity);
+ WriteEntityMetadata(a_Pkt, EntityMetadata::ItemFrameItem, EntityMetadataType::Item);
+ WriteItem(a_Pkt, Frame.GetItem());
+ WriteEntityMetadata(a_Pkt, EntityMetadata::ItemFrameRotation, EntityMetadataType::VarInt);
+ a_Pkt.WriteVarInt32(Frame.GetItemRotation());
break;
} // case etItemFrame
diff --git a/src/Protocol/Protocol_1_14.cpp b/src/Protocol/Protocol_1_14.cpp
index 4b306a2c3..beb929ce3 100644
--- a/src/Protocol/Protocol_1_14.cpp
+++ b/src/Protocol/Protocol_1_14.cpp
@@ -19,6 +19,7 @@ Implements the 1.14 protocol classes:
#include "../BlockEntities/BlockEntity.h"
#include "../Entities/ArrowEntity.h"
+#include "../Entities/ItemFrame.h"
#include "../Mobs/Bat.h"
#include "../Entities/Boat.h"
#include "../Mobs/Chicken.h"
@@ -1213,7 +1214,11 @@ void cProtocol_1_14::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_
case cEntity::etItemFrame:
{
- // TODO
+ const auto & Frame = static_cast<const cItemFrame &>(a_Entity);
+ WriteEntityMetadata(a_Pkt, EntityMetadata::ItemFrameItem, EntityMetadataType::Item);
+ WriteItem(a_Pkt, Frame.GetItem());
+ WriteEntityMetadata(a_Pkt, EntityMetadata::ItemFrameRotation, EntityMetadataType::VarInt);
+ a_Pkt.WriteVarInt32(Frame.GetItemRotation());
break;
} // case etItemFrame
diff --git a/src/StringUtils.cpp b/src/StringUtils.cpp
index e6d5e3812..cf4a69319 100644
--- a/src/StringUtils.cpp
+++ b/src/StringUtils.cpp
@@ -5,13 +5,9 @@
#include "Globals.h"
+#include "Endianness.h"
#include "fmt/printf.h"
-#ifdef _MSC_VER
- // Under MSVC, link to WinSock2 (needed by RawBEToUTF8's byteswapping)
- #pragma comment(lib, "ws2_32.lib")
-#endif
-
@@ -339,13 +335,14 @@ void ReplaceURL(AString & iHayStack, const AString & iNeedle, const AString & iR
-AString & RawBEToUTF8(const char * a_RawData, size_t a_NumShorts, AString & a_UTF8)
+AString & RawBEUTF16ToUTF8(const char * a_RawData, size_t a_NumShorts, AString & a_UTF8)
{
a_UTF8.clear();
a_UTF8.reserve(3 * a_NumShorts / 2); // a quick guess of the resulting size
for (size_t i = 0; i < a_NumShorts; i++)
{
- a_UTF8.append(UnicodeCharToUtf8(GetBEUShort(&a_RawData[i * 2])));
+ auto UTF16 = NetworkBufToHost<UInt16>(reinterpret_cast<const std::byte *>(&a_RawData[i * 2]));
+ a_UTF8.append(UnicodeCharToUtf8(UTF16));
}
return a_UTF8;
}
@@ -946,54 +943,6 @@ AString Base64Encode(const AString & a_Input)
-short GetBEShort(const std::byte * const a_Mem)
-{
- return static_cast<short>(
- (static_cast<short>(a_Mem[0]) << 8) |
- static_cast<short>(a_Mem[1])
- );
-}
-
-
-
-
-
-unsigned short GetBEUShort(const char * a_Mem)
-{
- const Byte * Bytes = reinterpret_cast<const Byte *>(a_Mem);
- return static_cast<unsigned short>((Bytes[0] << 8) | Bytes[1]);
-}
-
-
-
-
-
-int GetBEInt(const std::byte * const a_Mem)
-{
- return
- (static_cast<int>(a_Mem[0]) << 24) |
- (static_cast<int>(a_Mem[1]) << 16) |
- (static_cast<int>(a_Mem[2]) << 8) |
- static_cast<int>(a_Mem[3])
- ;
-}
-
-
-
-
-
-void SetBEInt(std::byte * a_Mem, Int32 a_Value)
-{
- a_Mem[0] = std::byte(a_Value >> 24);
- a_Mem[1] = std::byte((a_Value >> 16) & 0xff);
- a_Mem[2] = std::byte((a_Value >> 8) & 0xff);
- a_Mem[3] = std::byte(a_Value & 0xff);
-}
-
-
-
-
-
bool SplitZeroTerminatedStrings(const AString & a_Strings, AStringVector & a_Output)
{
a_Output.clear();
diff --git a/src/StringUtils.h b/src/StringUtils.h
index efb6a8566..f096d9b66 100644
--- a/src/StringUtils.h
+++ b/src/StringUtils.h
@@ -67,7 +67,7 @@ extern void ReplaceString(AString & iHayStack, const AString & iNeedle, const AS
extern void ReplaceURL(AString & iHayStack, const AString & iNeedle, const AString & iReplaceWith);
/** Converts a stream of BE shorts into UTF-8 string; returns a_UTF8. */
-extern AString & RawBEToUTF8(const char * a_RawData, size_t a_NumShorts, AString & a_UTF8);
+extern AString & RawBEUTF16ToUTF8(const char * a_RawData, size_t a_NumShorts, AString & a_UTF8);
/** Converts a unicode character to its UTF8 representation. */
extern AString UnicodeCharToUtf8(unsigned a_UnicodeChar);
@@ -101,18 +101,6 @@ extern AString Base64Decode(const AString & a_Base64String); // Exported manual
/** Encodes a string into Base64 */
extern AString Base64Encode(const AString & a_Input); // Exported manually due to embedded NULs and extra parameter
-/** Reads two bytes from the specified memory location and interprets them as BigEndian short */
-extern short GetBEShort(const std::byte * a_Mem);
-
-/** Reads two bytes from the specified memory location and interprets them as BigEndian unsigned short */
-extern unsigned short GetBEUShort(const char * a_Mem);
-
-/** Reads four bytes from the specified memory location and interprets them as BigEndian int */
-extern int GetBEInt(const std::byte * a_Mem);
-
-/** Writes four bytes to the specified memory location so that they interpret as BigEndian int */
-extern void SetBEInt(std::byte * a_Mem, Int32 a_Value);
-
/** Splits a string that has embedded \0 characters, on those characters.
a_Output is first cleared and then each separate string is pushed back into a_Output.
Returns true if there are at least two strings in a_Output (there was at least one \0 separator). */
diff --git a/src/Vector3.h b/src/Vector3.h
index 0e275e9b3..b48f35786 100644
--- a/src/Vector3.h
+++ b/src/Vector3.h
@@ -30,13 +30,20 @@ public:
// tolua_end
// Conversion constructors where U is not the same as T leaving the copy-constructor implicitly generated
- template <typename U, typename = typename std::enable_if<!std::is_same<U, T>::value>::type>
- constexpr Vector3(const Vector3<U> & a_Rhs):
+ template <typename U, std::enable_if_t<(!std::is_same<U, T>::value) && ((!std::is_integral<T>::value) || (std::is_integral<U>::value)), bool> = true>
+ constexpr Vector3<T>(const Vector3<U> & a_Rhs):
x(static_cast<T>(a_Rhs.x)),
y(static_cast<T>(a_Rhs.y)),
z(static_cast<T>(a_Rhs.z))
{
}
+ template <typename U, std::enable_if_t<(!std::is_same<U, T>::value) && ((std::is_integral<T>::value) && (!std::is_integral<U>::value)), bool> = true>
+ constexpr Vector3<T>(const Vector3<U> & a_Rhs):
+ x(static_cast<T>(std::floor(a_Rhs.x))),
+ y(static_cast<T>(std::floor(a_Rhs.y))),
+ z(static_cast<T>(std::floor(a_Rhs.z)))
+ {
+ }
// tolua_begin
inline void Set(T a_x, T a_y, T a_z)
diff --git a/src/WorldStorage/FastNBT.cpp b/src/WorldStorage/FastNBT.cpp
index df93e21e4..030300387 100644
--- a/src/WorldStorage/FastNBT.cpp
+++ b/src/WorldStorage/FastNBT.cpp
@@ -189,7 +189,7 @@ eNBTParseError cParsedNBT::ReadString(size_t & a_StringStart, size_t & a_StringL
{
NEEDBYTES(2, eNBTParseError::npStringMissingLength);
a_StringStart = m_Pos + 2;
- a_StringLen = static_cast<size_t>(GetBEShort(m_Data.data() + m_Pos));
+ a_StringLen = static_cast<size_t>(NetworkBufToHost<UInt16>(m_Data.data() + m_Pos));
NEEDBYTES(2 + a_StringLen, eNBTParseError::npStringInvalidLength);
m_Pos += 2 + a_StringLen;
return eNBTParseError::npSuccess;
@@ -247,7 +247,7 @@ eNBTParseError cParsedNBT::ReadList(eTagType a_ChildrenType)
// Read the count:
NEEDBYTES(4, eNBTParseError::npListMissingLength);
- int Count = GetBEInt(m_Data.data() + m_Pos);
+ int Count = NetworkBufToHost<int>(m_Data.data() + m_Pos);
m_Pos += 4;
auto MinChildSize = GetMinTagSize(a_ChildrenType);
if ((Count < 0) || (Count > static_cast<int>((m_Data.size() - m_Pos) / MinChildSize)))
@@ -311,7 +311,7 @@ eNBTParseError cParsedNBT::ReadTag(void)
case TAG_ByteArray:
{
NEEDBYTES(4, eNBTParseError::npArrayMissingLength);
- int len = GetBEInt(m_Data.data() + m_Pos);
+ int len = NetworkBufToHost<int>(m_Data.data() + m_Pos);
m_Pos += 4;
if (len < 0)
{
@@ -343,7 +343,7 @@ eNBTParseError cParsedNBT::ReadTag(void)
case TAG_IntArray:
{
NEEDBYTES(4, eNBTParseError::npArrayMissingLength);
- int len = GetBEInt(m_Data.data() + m_Pos);
+ int len = NetworkBufToHost<int>(m_Data.data() + m_Pos);
m_Pos += 4;
if (len < 0)
{
@@ -539,7 +539,8 @@ void cFastNBTWriter::EndList(void)
ASSERT(m_Stack[m_CurrentStack].m_Type == TAG_List);
// Update the list count:
- SetBEInt(m_Result.data() + m_Stack[m_CurrentStack].m_Pos, m_Stack[m_CurrentStack].m_Count);
+ auto Value = HostToNetwork(m_Stack[m_CurrentStack].m_Count);
+ std::copy(Value.begin(), Value.end(), m_Result.data() + m_Stack[m_CurrentStack].m_Pos);
--m_CurrentStack;
}
@@ -561,8 +562,8 @@ void cFastNBTWriter::AddByte(const AString & a_Name, unsigned char a_Value)
void cFastNBTWriter::AddShort(const AString & a_Name, Int16 a_Value)
{
TagCommon(a_Name, TAG_Short);
- UInt16 Value = htons(static_cast<UInt16>(a_Value));
- m_Result.append(reinterpret_cast<const std::byte *>(&Value), 2);
+ auto Value = HostToNetwork(a_Value);
+ m_Result.append(Value.begin(), Value.end());
}
@@ -572,8 +573,8 @@ void cFastNBTWriter::AddShort(const AString & a_Name, Int16 a_Value)
void cFastNBTWriter::AddInt(const AString & a_Name, Int32 a_Value)
{
TagCommon(a_Name, TAG_Int);
- UInt32 Value = htonl(static_cast<UInt32>(a_Value));
- m_Result.append(reinterpret_cast<const std::byte *>(&Value), 4);
+ auto Value = HostToNetwork(a_Value);
+ m_Result.append(Value.begin(), Value.end());
}
@@ -583,8 +584,8 @@ void cFastNBTWriter::AddInt(const AString & a_Name, Int32 a_Value)
void cFastNBTWriter::AddLong(const AString & a_Name, Int64 a_Value)
{
TagCommon(a_Name, TAG_Long);
- UInt64 Value = HostToNetwork8(&a_Value);
- m_Result.append(reinterpret_cast<const std::byte *>(&Value), 8);
+ auto Value = HostToNetwork(a_Value);
+ m_Result.append(Value.begin(), Value.end());
}
@@ -594,8 +595,8 @@ void cFastNBTWriter::AddLong(const AString & a_Name, Int64 a_Value)
void cFastNBTWriter::AddFloat(const AString & a_Name, float a_Value)
{
TagCommon(a_Name, TAG_Float);
- UInt32 Value = HostToNetwork4(&a_Value);
- m_Result.append(reinterpret_cast<const std::byte *>(&Value), 4);
+ auto Value = HostToNetwork(a_Value);
+ m_Result.append(Value.begin(), Value.end());
}
@@ -605,8 +606,8 @@ void cFastNBTWriter::AddFloat(const AString & a_Name, float a_Value)
void cFastNBTWriter::AddDouble(const AString & a_Name, double a_Value)
{
TagCommon(a_Name, TAG_Double);
- UInt64 Value = HostToNetwork8(&a_Value);
- m_Result.append(reinterpret_cast<const std::byte *>(&Value), 8);
+ auto Value = HostToNetwork(a_Value);
+ m_Result.append(Value.begin(), Value.end());
}
@@ -616,8 +617,8 @@ void cFastNBTWriter::AddDouble(const AString & a_Name, double a_Value)
void cFastNBTWriter::AddString(const AString & a_Name, const std::string_view a_Value)
{
TagCommon(a_Name, TAG_String);
- const UInt16 Length = htons(static_cast<UInt16>(a_Value.size()));
- m_Result.append(reinterpret_cast<const std::byte *>(&Length), sizeof(Length));
+ auto Length = HostToNetwork(static_cast<UInt16>(a_Value.size()));
+ m_Result.append(Length.begin(), Length.end());
m_Result.append({ reinterpret_cast<const std::byte *>(a_Value.data()), a_Value.size() });
}
@@ -628,8 +629,8 @@ void cFastNBTWriter::AddString(const AString & a_Name, const std::string_view a_
void cFastNBTWriter::AddByteArray(const AString & a_Name, const char * a_Value, size_t a_NumElements)
{
TagCommon(a_Name, TAG_ByteArray);
- UInt32 len = htonl(static_cast<UInt32>(a_NumElements));
- m_Result.append(reinterpret_cast<const std::byte *>(&len), 4);
+ auto Length = HostToNetwork(static_cast<UInt32>(a_NumElements));
+ m_Result.append(Length.begin(), Length.end());
m_Result.append(reinterpret_cast<const std::byte *>(a_Value), a_NumElements);
}
@@ -640,8 +641,8 @@ void cFastNBTWriter::AddByteArray(const AString & a_Name, const char * a_Value,
void cFastNBTWriter::AddByteArray(const AString & a_Name, size_t a_NumElements, unsigned char a_Value)
{
TagCommon(a_Name, TAG_ByteArray);
- UInt32 len = htonl(static_cast<UInt32>(a_NumElements));
- m_Result.append(reinterpret_cast<const std::byte *>(&len), 4);
+ auto Length = HostToNetwork(static_cast<UInt32>(a_NumElements));
+ m_Result.append(Length.begin(), Length.end());
m_Result.append(a_NumElements, std::byte(a_Value));
}
@@ -652,18 +653,18 @@ void cFastNBTWriter::AddByteArray(const AString & a_Name, size_t a_NumElements,
void cFastNBTWriter::AddIntArray(const AString & a_Name, const Int32 * a_Value, size_t a_NumElements)
{
TagCommon(a_Name, TAG_IntArray);
- UInt32 len = htonl(static_cast<UInt32>(a_NumElements));
+ auto Length = HostToNetwork(static_cast<UInt32>(a_NumElements));
size_t cap = m_Result.capacity();
size_t size = m_Result.length();
if ((cap - size) < (4 + a_NumElements * 4))
{
m_Result.reserve(size + 4 + (a_NumElements * 4));
}
- m_Result.append(reinterpret_cast<const std::byte *>(&len), sizeof(len));
+ m_Result.append(Length.begin(), Length.end());
for (size_t i = 0; i < a_NumElements; i++)
{
- UInt32 Element = htonl(static_cast<UInt32>(a_Value[i]));
- m_Result.append(reinterpret_cast<const std::byte *>(&Element), sizeof(Element));
+ auto Element = HostToNetwork(a_Value[i]);
+ m_Result.append(Element.begin(), Element.end());
}
}
@@ -684,7 +685,7 @@ void cFastNBTWriter::Finish(void)
void cFastNBTWriter::WriteString(const std::string_view a_Data)
{
// TODO check size <= short max
- UInt16 Len = htons(static_cast<unsigned short>(a_Data.size()));
- m_Result.append(reinterpret_cast<const std::byte *>(&Len), sizeof(Len));
+ auto Length = HostToNetwork(static_cast<UInt16>(a_Data.size()));
+ m_Result.append(Length.begin(), Length.end());
m_Result.append(reinterpret_cast<const std::byte *>(a_Data.data()), a_Data.size());
}
diff --git a/src/WorldStorage/FastNBT.h b/src/WorldStorage/FastNBT.h
index d9c388179..b2eb851d7 100644
--- a/src/WorldStorage/FastNBT.h
+++ b/src/WorldStorage/FastNBT.h
@@ -227,21 +227,21 @@ public:
inline Int16 GetShort(int a_Tag) const
{
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type == TAG_Short);
- return GetBEShort(GetData(a_Tag));
+ return NetworkBufToHost<Int16>(GetData(a_Tag));
}
/** Returns the value stored in an Int tag. Not valid for any other tag type. */
inline Int32 GetInt(int a_Tag) const
{
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type == TAG_Int);
- return GetBEInt(GetData(a_Tag));
+ return NetworkBufToHost<Int32>(GetData(a_Tag));
}
/** Returns the value stored in a Long tag. Not valid for any other tag type. */
inline Int64 GetLong(int a_Tag) const
{
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type == TAG_Long);
- return NetworkToHostLong8(GetData(a_Tag));
+ return NetworkBufToHost<Int64>(GetData(a_Tag));
}
/** Returns the value stored in a Float tag. Not valid for any other tag type. */
@@ -256,10 +256,7 @@ public:
UNUSED_VAR(Check1);
UNUSED_VAR(Check2);
- Int32 i = GetBEInt(GetData(a_Tag));
- float f;
- memcpy(&f, &i, sizeof(f));
- return f;
+ return NetworkBufToHost<float>(GetData(a_Tag));
}
/** Returns the value stored in a Double tag. Not valid for any other tag type. */
@@ -273,7 +270,7 @@ public:
UNUSED_VAR(Check2);
ASSERT(m_Tags[static_cast<size_t>(a_Tag)].m_Type == TAG_Double);
- return NetworkToHostDouble8(GetData(a_Tag));
+ return NetworkBufToHost<double>(GetData(a_Tag));
}
/** Returns the value stored in a String tag. Not valid for any other tag type. */
diff --git a/src/WorldStorage/FireworksSerializer.cpp b/src/WorldStorage/FireworksSerializer.cpp
index f0fe7e48e..6616196e2 100644
--- a/src/WorldStorage/FireworksSerializer.cpp
+++ b/src/WorldStorage/FireworksSerializer.cpp
@@ -108,7 +108,7 @@ void cFireworkItem::ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNB
const auto * ColourData = (a_NBT.GetData(explosiontag));
for (size_t i = 0; i < DataLength; i += 4)
{
- a_FireworkItem.m_Colours.push_back(GetBEInt(ColourData + i));
+ a_FireworkItem.m_Colours.push_back(NetworkBufToHost<Int32>(ColourData + i));
}
}
else if (ExplosionName == "FadeColors")
@@ -124,7 +124,7 @@ void cFireworkItem::ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNB
const auto * FadeColourData = (a_NBT.GetData(explosiontag));
for (size_t i = 0; i < DataLength; i += 4)
{
- a_FireworkItem.m_FadeColours.push_back(GetBEInt(FadeColourData + i));
+ a_FireworkItem.m_FadeColours.push_back(NetworkBufToHost<Int32>(FadeColourData + i));
}
}
}
diff --git a/src/WorldStorage/MapSerializer.cpp b/src/WorldStorage/MapSerializer.cpp
index e68ad00e6..3e50740b3 100644
--- a/src/WorldStorage/MapSerializer.cpp
+++ b/src/WorldStorage/MapSerializer.cpp
@@ -18,7 +18,7 @@ cMapSerializer::cMapSerializer(const AString & a_WorldName, cMap * a_Map):
m_Map(a_Map)
{
auto DataPath = fmt::format(FMT_STRING("{}{}data"), a_WorldName, cFile::PathSeparator());
- m_Path = fmt::format(FMT_STRING("{}{}map_%i.dat"), DataPath, cFile::PathSeparator(), a_Map->GetID());
+ m_Path = fmt::format(FMT_STRING("{}{}map_{}.dat"), DataPath, cFile::PathSeparator(), a_Map->GetID());
cFile::CreateFolder(DataPath);
}
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index fb6459c88..c61e6d185 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -376,6 +376,10 @@ public:
mWriter.BeginCompound("");
AddBasicTileEntity(a_Entity,"Banner");
mWriter.AddInt("Base", static_cast<int>(a_Entity->GetBaseColor()));
+ if (!a_Entity->GetCustomName().empty())
+ {
+ mWriter.AddString("CustomName", a_Entity->GetCustomName());
+ }
mWriter.EndCompound();
}
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index dec05f351..0f91b033b 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -510,7 +510,7 @@ bool cWSSAnvil::LoadHeightMapFromNBT(cChunkDef::HeightMap & a_HeightMap, const c
for (int RelX = 0; RelX < cChunkDef::Width; RelX++)
{
const int Index = 4 * (RelX + RelZ * cChunkDef::Width);
- const int Height = GetBEInt(HeightData + Index);
+ const int Height = NetworkBufToHost<Int32>(HeightData + Index);
if (Height > std::numeric_limits<HEIGHTTYPE>::max())
{
@@ -890,15 +890,23 @@ OwnedBlockEntity cWSSAnvil::LoadBannerFromNBT(const cParsedNBT & a_NBT, int a_Ta
return nullptr;
}
+ unsigned char Color = 15;
+ AString CustomName;
+
// Reads base color from NBT
int CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Base");
if (CurrentLine >= 0)
{
- const auto Color = static_cast<unsigned char>(a_NBT.GetInt(CurrentLine));
- return std::make_unique<cBannerEntity>(a_BlockType, a_BlockMeta, a_Pos, m_World, Color);
+ Color = static_cast<unsigned char>(a_NBT.GetInt(CurrentLine));
}
- return nullptr;
+ CurrentLine = a_NBT.FindChildByName(a_TagIdx, "CustomName");
+ if ((CurrentLine >= 0) && (a_NBT.GetType(CurrentLine) == TAG_String))
+ {
+ CustomName = a_NBT.GetString(CurrentLine);
+ }
+
+ return std::make_unique<cBannerEntity>(a_BlockType, a_BlockMeta, a_Pos, m_World, Color, CustomName);
}
@@ -3640,7 +3648,7 @@ bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_N
Rotation[1] = 0;
}
a_Entity.SetYaw(Rotation[0]);
- a_Entity.SetRoll(Rotation[1]);
+ a_Entity.SetPitch(Rotation[1]);
// Depending on the Minecraft version, the entity's health is
// stored either as a float Health tag (HealF prior to 1.9) or
diff --git a/tests/HTTP/UrlClientTest.cpp b/tests/HTTP/UrlClientTest.cpp
index 44e39e666..eeeaf774b 100644
--- a/tests/HTTP/UrlClientTest.cpp
+++ b/tests/HTTP/UrlClientTest.cpp
@@ -204,35 +204,35 @@ namespace TrustedCAs
// The root cert used by cuberite.org
static const char CuberiteOrg[] =
"-----BEGIN CERTIFICATE-----\n"
- "MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/\n"
- "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
- "DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow\n"
+ "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n"
"TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n"
- "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB\n"
- "AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC\n"
- "ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL\n"
- "wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D\n"
- "LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK\n"
- "4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5\n"
- "bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y\n"
- "sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ\n"
- "Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4\n"
- "FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc\n"
- "SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql\n"
- "PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND\n"
- "TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw\n"
- "SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1\n"
- "c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx\n"
- "+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB\n"
- "ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu\n"
- "b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E\n"
- "U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu\n"
- "MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC\n"
- "5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW\n"
- "9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG\n"
- "WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O\n"
- "he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC\n"
- "Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5\n"
+ "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n"
+ "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n"
+ "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n"
+ "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n"
+ "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n"
+ "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n"
+ "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n"
+ "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n"
+ "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n"
+ "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n"
+ "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n"
+ "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n"
+ "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n"
+ "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n"
+ "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n"
+ "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n"
+ "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n"
+ "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n"
+ "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n"
+ "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n"
+ "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n"
+ "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n"
+ "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n"
+ "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n"
+ "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n"
+ "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n"
+ "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n"
"-----END CERTIFICATE-----\n";
}