summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Blocks/BlockAnvil.h2
-rw-r--r--src/Blocks/BlockBed.h2
-rw-r--r--src/Blocks/BlockBigFlower.h7
-rw-r--r--src/Blocks/BlockBrewingStand.h2
-rw-r--r--src/Blocks/BlockButton.h2
-rw-r--r--src/Blocks/BlockCactus.h36
-rw-r--r--src/Blocks/BlockCarpet.h3
-rw-r--r--src/Blocks/BlockChest.h2
-rw-r--r--src/Blocks/BlockCocoaPod.h7
-rw-r--r--src/Blocks/BlockComparator.h43
-rw-r--r--src/Blocks/BlockCrops.h9
-rw-r--r--src/Blocks/BlockDeadBush.h5
-rw-r--r--src/Blocks/BlockDoor.h22
-rw-r--r--src/Blocks/BlockDropSpenser.h2
-rw-r--r--src/Blocks/BlockEnderChest.h2
-rw-r--r--src/Blocks/BlockFenceGate.h2
-rw-r--r--src/Blocks/BlockFlower.h14
-rw-r--r--src/Blocks/BlockFurnace.h2
-rw-r--r--src/Blocks/BlockGlazedTerracotta.h2
-rw-r--r--src/Blocks/BlockHandler.cpp7
-rw-r--r--src/Blocks/BlockHopper.h2
-rw-r--r--src/Blocks/BlockJukebox.h2
-rw-r--r--src/Blocks/BlockLadder.h2
-rw-r--r--src/Blocks/BlockLever.h2
-rw-r--r--src/Blocks/BlockMushroom.h5
-rw-r--r--src/Blocks/BlockNetherWart.h3
-rw-r--r--src/Blocks/BlockObserver.h2
-rw-r--r--src/Blocks/BlockPiston.cpp59
-rw-r--r--src/Blocks/BlockPiston.h2
-rw-r--r--src/Blocks/BlockPortal.h4
-rw-r--r--src/Blocks/BlockPressurePlate.h5
-rw-r--r--src/Blocks/BlockPumpkin.h2
-rw-r--r--src/Blocks/BlockRail.h28
-rw-r--r--src/Blocks/BlockRedstoneRepeater.h44
-rw-r--r--src/Blocks/BlockRedstoneWire.h43
-rw-r--r--src/Blocks/BlockSapling.h14
-rw-r--r--src/Blocks/BlockSignPost.h5
-rw-r--r--src/Blocks/BlockSnow.h4
-rw-r--r--src/Blocks/BlockStairs.h2
-rw-r--r--src/Blocks/BlockStandingBanner.h (renamed from src/Blocks/BlockBanner.h)23
-rw-r--r--src/Blocks/BlockStems.h3
-rw-r--r--src/Blocks/BlockSugarCane.h44
-rw-r--r--src/Blocks/BlockTallGrass.h25
-rw-r--r--src/Blocks/BlockTorch.h4
-rw-r--r--src/Blocks/BlockTrapdoor.h2
-rw-r--r--src/Blocks/BlockTripwireHook.h2
-rw-r--r--src/Blocks/BlockVines.h7
-rw-r--r--src/Blocks/BlockWallBanner.h64
-rw-r--r--src/Blocks/CMakeLists.txt5
-rw-r--r--src/Blocks/Mixins/DirtLikeUnderneath.h42
-rw-r--r--src/Blocks/Mixins/Mixins.h (renamed from src/Blocks/Mixins.h)2
-rw-r--r--src/Blocks/Mixins/SolidSurfaceUnderneath.h65
-rw-r--r--src/ByteBuffer.cpp78
-rw-r--r--src/ChunkMap.cpp22
-rw-r--r--src/ChunkMap.h4
-rw-r--r--src/ClientHandle.cpp11
-rw-r--r--src/Endianness.h183
-rw-r--r--src/Entities/Player.cpp14
-rw-r--r--src/Generating/CompoGenBiomal.cpp5
-rw-r--r--src/Items/ItemBed.h5
-rw-r--r--src/Items/ItemBigFlower.h5
-rw-r--r--src/Items/ItemDoor.h5
-rw-r--r--src/Items/ItemDye.h6
-rw-r--r--src/Items/ItemEyeOfEnder.h4
-rw-r--r--src/Items/ItemHoe.h5
-rw-r--r--src/Items/ItemShears.h5
-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/Protocol/ChunkDataSerializer.cpp2
-rw-r--r--src/StringUtils.cpp59
-rw-r--r--src/StringUtils.h14
-rw-r--r--src/UI/SlotArea.cpp7
-rw-r--r--src/Vector3.h9
-rw-r--r--src/World.cpp34
-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/WSSAnvil.cpp2
-rw-r--r--src/mbedTLS++/CryptoKey.cpp9
-rw-r--r--src/mbedTLS++/RsaPrivateKey.cpp6
84 files changed, 791 insertions, 592 deletions
diff --git a/src/Blocks/BlockAnvil.h b/src/Blocks/BlockAnvil.h
index bc031216a..eb8053af1 100644
--- a/src/Blocks/BlockAnvil.h
+++ b/src/Blocks/BlockAnvil.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
#include "../Entities/Player.h"
#include "../UI/AnvilWindow.h"
diff --git a/src/Blocks/BlockBed.h b/src/Blocks/BlockBed.h
index a6b2814b9..fcf7d58a0 100644
--- a/src/Blocks/BlockBed.h
+++ b/src/Blocks/BlockBed.h
@@ -6,7 +6,7 @@
#include "BlockEntity.h"
#include "ChunkInterface.h"
#include "Entities/Player.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockBigFlower.h b/src/Blocks/BlockBigFlower.h
index 1b2c0d735..d8270dc6c 100644
--- a/src/Blocks/BlockBigFlower.h
+++ b/src/Blocks/BlockBigFlower.h
@@ -25,9 +25,10 @@ private:
if (IsMetaTopPart(a_Meta))
{
BLOCKTYPE BottomType;
+ const auto BottomPosition = a_Position.addedY(-1);
if (
- (a_Position.y < 1) ||
- !a_World.GetBlockTypeMeta(a_Position - Vector3i(0, 1, 0), BottomType, a_Meta) ||
+ !cChunkDef::IsValidHeight(BottomPosition) ||
+ !a_World.GetBlockTypeMeta(BottomPosition, BottomType, a_Meta) ||
(BottomType != E_BLOCK_BIG_FLOWER)
)
{
@@ -104,7 +105,7 @@ private:
// Both parts can only that they're rooted in grass.
const auto RootPosition = a_Position.addedY(IsMetaTopPart(a_Meta) ? -2 : -1);
- return (RootPosition.y >= 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(RootPosition));
+ return cChunkDef::IsValidHeight(RootPosition) && IsBlockTypeOfDirt(a_Chunk.GetBlock(RootPosition));
}
diff --git a/src/Blocks/BlockBrewingStand.h b/src/Blocks/BlockBrewingStand.h
index d1595c690..5f41525d7 100644
--- a/src/Blocks/BlockBrewingStand.h
+++ b/src/Blocks/BlockBrewingStand.h
@@ -1,7 +1,7 @@
#pragma once
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h
index 1a141eff3..e8affb290 100644
--- a/src/Blocks/BlockButton.h
+++ b/src/Blocks/BlockButton.h
@@ -7,7 +7,7 @@
#include "../Chunk.h"
#include "Defines.h"
#include "Entities/Player.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
#include "ChunkInterface.h"
#include "World.h"
diff --git a/src/Blocks/BlockCactus.h b/src/Blocks/BlockCactus.h
index 23c4d3421..9b1461cb8 100644
--- a/src/Blocks/BlockCactus.h
+++ b/src/Blocks/BlockCactus.h
@@ -20,11 +20,12 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
- if (a_Position.y <= 0)
+ const auto SurfacePosition = a_Position.addedY(-1);
+ if (!cChunkDef::IsValidHeight(SurfacePosition))
{
return false;
}
- BLOCKTYPE Surface = a_Chunk.GetBlock(a_Position.addedY(-1));
+ BLOCKTYPE Surface = a_Chunk.GetBlock(SurfacePosition);
if ((Surface != E_BLOCK_SAND) && (Surface != E_BLOCK_CACTUS))
{
// Cactus can only be placed on sand and itself
@@ -75,25 +76,25 @@ private:
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override
{
// Check the total height of the cacti blocks here:
- int top = a_RelPos.y + 1;
+ auto Top = a_RelPos.addedY(1);
while (
- (top < cChunkDef::Height) &&
- (a_Chunk.GetBlock({a_RelPos.x, top, a_RelPos.z}) == E_BLOCK_CACTUS)
+ cChunkDef::IsValidHeight(Top) &&
+ (a_Chunk.GetBlock(Top) == E_BLOCK_CACTUS)
)
{
- ++top;
+ Top.y++;
}
- int bottom = a_RelPos.y - 1;
+ auto Bottom = a_RelPos.addedY(-1);
while (
- (bottom > 0) &&
- (a_Chunk.GetBlock({a_RelPos.x, bottom, a_RelPos.z}) == E_BLOCK_CACTUS)
+ cChunkDef::IsValidHeight(Bottom) &&
+ (a_Chunk.GetBlock(Bottom) == E_BLOCK_CACTUS)
)
{
- --bottom;
+ --Bottom.y;
}
// Refuse if already too high:
- auto numToGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxCactusHeight() + 1 - (top - bottom));
+ auto numToGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxCactusHeight() + 1 - (Top.y - Bottom.y));
if (numToGrow <= 0)
{
return 0;
@@ -102,14 +103,14 @@ private:
BLOCKTYPE blockType;
for (int i = 0; i < numToGrow; ++i)
{
- Vector3i pos(a_RelPos.x, top + i, a_RelPos.z);
- if (!a_Chunk.UnboundedRelGetBlockType(pos, blockType) || (blockType != E_BLOCK_AIR))
+ auto NewTop = Top.addedY(i);
+ if (!a_Chunk.UnboundedRelGetBlockType(NewTop, blockType) || (blockType != E_BLOCK_AIR))
{
// Cannot grow there
return i;
}
- a_Chunk.UnboundedRelFastSetBlock(pos, E_BLOCK_CACTUS, 0);
+ a_Chunk.UnboundedRelFastSetBlock(NewTop, E_BLOCK_CACTUS, 0);
// Check surroundings. Cacti may ONLY be surrounded by non-solid blocks; if they aren't, drop as pickup and bail out the growing
static const Vector3i neighborOffsets[] =
@@ -122,7 +123,7 @@ private:
for (const auto & ofs: neighborOffsets)
{
if (
- a_Chunk.UnboundedRelGetBlockType(pos + ofs, blockType) &&
+ a_Chunk.UnboundedRelGetBlockType(NewTop + ofs, blockType) &&
(
cBlockInfo::IsSolid(blockType) ||
(blockType == E_BLOCK_LAVA) ||
@@ -131,7 +132,7 @@ private:
)
{
// Remove the cactus
- auto absPos = a_Chunk.RelativeToAbsolute(pos);
+ auto absPos = a_Chunk.RelativeToAbsolute(NewTop);
a_Chunk.GetWorld()->DropBlockAsPickups(absPos);
return i + 1;
}
@@ -143,7 +144,8 @@ private:
virtual PlantAction CanGrow(cChunk & a_Chunk, Vector3i a_RelPos) const override
{
// Only allow growing if there's an air block above:
- if (((a_RelPos.y + 1) < cChunkDef::Height) && (a_Chunk.GetBlock(a_RelPos.addedY(1)) == E_BLOCK_AIR))
+ const auto RelPosAbove = a_RelPos.addedY(1);
+ if (cChunkDef::IsValidHeight(RelPosAbove) && (a_Chunk.GetBlock(RelPosAbove) == E_BLOCK_AIR))
{
return Super::CanGrow(a_Chunk, a_RelPos);
}
diff --git a/src/Blocks/BlockCarpet.h b/src/Blocks/BlockCarpet.h
index 841e94b11..2477ee344 100644
--- a/src/Blocks/BlockCarpet.h
+++ b/src/Blocks/BlockCarpet.h
@@ -27,7 +27,8 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
- return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) != E_BLOCK_AIR);
+ const auto PosBelow = a_Position.addedY(-1);
+ return cChunkDef::IsValidHeight(PosBelow) && (a_Chunk.GetBlock(PosBelow) != E_BLOCK_AIR);
}
diff --git a/src/Blocks/BlockChest.h b/src/Blocks/BlockChest.h
index 119216d00..99a95e692 100644
--- a/src/Blocks/BlockChest.h
+++ b/src/Blocks/BlockChest.h
@@ -3,7 +3,7 @@
#include "../BlockArea.h"
#include "../Entities/Player.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockCocoaPod.h b/src/Blocks/BlockCocoaPod.h
index e018388c5..7906a1888 100644
--- a/src/Blocks/BlockCocoaPod.h
+++ b/src/Blocks/BlockCocoaPod.h
@@ -43,7 +43,12 @@ private:
auto LogPos = AddFaceDirection(a_Position, BlockFace, true);
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
- a_Chunk.UnboundedRelGetBlock(LogPos, BlockType, BlockMeta);
+ if (!a_Chunk.UnboundedRelGetBlock(LogPos, BlockType, BlockMeta))
+ {
+ // Don't pop if chunk not loaded.
+ return true;
+ }
+
return ((BlockType == E_BLOCK_LOG) && ((BlockMeta & 0x03) == E_META_LOG_JUNGLE));
}
diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h
index 18aa2a8b9..9ce9d3dbd 100644
--- a/src/Blocks/BlockComparator.h
+++ b/src/Blocks/BlockComparator.h
@@ -2,17 +2,17 @@
#pragma once
#include "BlockHandler.h"
-#include "BlockRedstoneRepeater.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
+#include "Mixins/SolidSurfaceUnderneath.h"
class cBlockComparatorHandler final :
- public cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>
+ public cSolidSurfaceUnderneath<cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>>
{
- using Super = cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>;
+ using Super = cSolidSurfaceUnderneath<cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>>;
public:
@@ -152,41 +152,6 @@ private:
- virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
- {
- if (a_Position.y <= 0)
- {
- return false;
- }
-
- BLOCKTYPE BelowBlock;
- NIBBLETYPE BelowBlockMeta;
- a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta);
-
- if (cBlockInfo::FullyOccupiesVoxel(BelowBlock))
- {
- return true;
- }
-
- // upside down slabs
- if (cBlockSlabHandler::IsAnySlabType(BelowBlock))
- {
- return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN;
- }
-
- // upside down stairs
- if (cBlockStairsHandler::IsAnyStairType(BelowBlock))
- {
- return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN;
- }
-
- return false;
- }
-
-
-
-
-
virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
{
return cItem(E_ITEM_COMPARATOR, 1, 0);
diff --git a/src/Blocks/BlockCrops.h b/src/Blocks/BlockCrops.h
index b323ace10..59413ba08 100644
--- a/src/Blocks/BlockCrops.h
+++ b/src/Blocks/BlockCrops.h
@@ -118,7 +118,14 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
- return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) == E_BLOCK_FARMLAND);
+ const auto BlockBelow = a_Position.addedY(-1);
+
+ if (!cChunkDef::IsValidHeight(BlockBelow))
+ {
+ return false;
+ }
+
+ return a_Chunk.GetBlock(BlockBelow) == E_BLOCK_FARMLAND;
}
diff --git a/src/Blocks/BlockDeadBush.h b/src/Blocks/BlockDeadBush.h
index 080dd150c..884b6f686 100644
--- a/src/Blocks/BlockDeadBush.h
+++ b/src/Blocks/BlockDeadBush.h
@@ -29,12 +29,13 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
- if (a_Position.y <= 0)
+ const auto PosBelow = a_Position.addedY(-1);
+ if (!cChunkDef::IsValidHeight(PosBelow))
{
return false;
}
- BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_Position.addedY(-1));
+ BLOCKTYPE BelowBlock = a_Chunk.GetBlock(PosBelow);
switch (BelowBlock)
{
case E_BLOCK_CLAY:
diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h
index 1b5c33d46..c394bda39 100644
--- a/src/Blocks/BlockDoor.h
+++ b/src/Blocks/BlockDoor.h
@@ -5,7 +5,7 @@
#include "../BlockInfo.h"
#include "../Entities/Player.h"
#include "../Chunk.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
#include "ChunkInterface.h"
#include "BlockSlab.h"
@@ -191,14 +191,18 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
// CanBeAt is also called on placement, so the top part can't check for the bottom part.
- // Both parts can only that their base is a valid block.
+ // Both parts can only check that the base of the door (i.e. -2 for a door top) is a valid block.
+ const auto BasePosition = a_Position.addedY(((a_Meta & 0x8) == 0x8) ? -2 : -1);
+ if (!cChunkDef::IsValidHeight(BasePosition))
+ {
+ return false;
+ }
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
- const auto BasePosition = a_Position.addedY(((a_Meta & 0x8) == 0x8) ? -2 : -1);
a_Chunk.GetBlockTypeMeta(BasePosition, BlockType, BlockMeta);
- return (BasePosition.y >= 0) && CanBeOn(BlockType, BlockMeta);
+ return CanBeOn(BlockType, BlockMeta);
}
@@ -216,9 +220,10 @@ private:
if ((Meta & 0x08) != 0)
{
// The coords are pointing at the top part of the door
- if (a_BlockPos.y > 0)
+ const auto BottomPos = a_BlockPos.addedY(-1);
+ if (cChunkDef::IsValidHeight(BottomPos))
{
- NIBBLETYPE DownMeta = a_ChunkInterface.GetBlockMeta(a_BlockPos.addedY(-1));
+ NIBBLETYPE DownMeta = a_ChunkInterface.GetBlockMeta(BottomPos);
return static_cast<NIBBLETYPE>((DownMeta & 0x07) | 0x08 | (Meta << 4));
}
// This is the top part of the door at the bottommost layer of the world, there's no bottom:
@@ -227,9 +232,10 @@ private:
else
{
// The coords are pointing at the bottom part of the door
- if (a_BlockPos.y < cChunkDef::Height - 1)
+ const auto TopPos = a_BlockPos.addedY(1);
+ if (cChunkDef::IsValidHeight(TopPos))
{
- NIBBLETYPE UpMeta = a_ChunkInterface.GetBlockMeta(a_BlockPos.addedY(1));
+ NIBBLETYPE UpMeta = a_ChunkInterface.GetBlockMeta(TopPos);
return static_cast<NIBBLETYPE>(Meta | (UpMeta << 4));
}
// This is the bottom part of the door at the topmost layer of the world, there's no top:
diff --git a/src/Blocks/BlockDropSpenser.h b/src/Blocks/BlockDropSpenser.h
index 050adf0f1..7b18eb8da 100644
--- a/src/Blocks/BlockDropSpenser.h
+++ b/src/Blocks/BlockDropSpenser.h
@@ -5,7 +5,7 @@
#pragma once
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockEnderChest.h b/src/Blocks/BlockEnderChest.h
index 2e0da0f17..a944ab263 100644
--- a/src/Blocks/BlockEnderChest.h
+++ b/src/Blocks/BlockEnderChest.h
@@ -1,7 +1,7 @@
#pragma once
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockFenceGate.h b/src/Blocks/BlockFenceGate.h
index f52d8df9c..75a0ded06 100644
--- a/src/Blocks/BlockFenceGate.h
+++ b/src/Blocks/BlockFenceGate.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
#include "../EffectID.h"
diff --git a/src/Blocks/BlockFlower.h b/src/Blocks/BlockFlower.h
index 023ba4a37..aaa532c0c 100644
--- a/src/Blocks/BlockFlower.h
+++ b/src/Blocks/BlockFlower.h
@@ -2,15 +2,16 @@
#pragma once
#include "BlockHandler.h"
+#include "Mixins/DirtLikeUnderneath.h"
class cBlockFlowerHandler final :
- public cBlockHandler
+ public cDirtLikeUnderneath<cBlockHandler>
{
- using Super = cBlockHandler;
+ using Super = cDirtLikeUnderneath<cBlockHandler>;
public:
@@ -28,15 +29,6 @@ private:
- virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
- {
- return (a_Position.y > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_Position.addedY(-1)));
- }
-
-
-
-
-
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
{
UNUSED(a_Meta);
diff --git a/src/Blocks/BlockFurnace.h b/src/Blocks/BlockFurnace.h
index 8cdc9489a..968ea398c 100644
--- a/src/Blocks/BlockFurnace.h
+++ b/src/Blocks/BlockFurnace.h
@@ -1,7 +1,7 @@
#pragma once
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockGlazedTerracotta.h b/src/Blocks/BlockGlazedTerracotta.h
index 0975f1ecd..21206ab77 100644
--- a/src/Blocks/BlockGlazedTerracotta.h
+++ b/src/Blocks/BlockGlazedTerracotta.h
@@ -1,7 +1,7 @@
#pragma once
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
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/BlockHopper.h b/src/Blocks/BlockHopper.h
index 930f1e0bc..91ad91bff 100644
--- a/src/Blocks/BlockHopper.h
+++ b/src/Blocks/BlockHopper.h
@@ -3,7 +3,7 @@
// Declares the cBlockHopperHandler class representing the handler for the Hopper block
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockJukebox.h b/src/Blocks/BlockJukebox.h
index 970f10fc1..79475d30b 100644
--- a/src/Blocks/BlockJukebox.h
+++ b/src/Blocks/BlockJukebox.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockEntity.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockLadder.h b/src/Blocks/BlockLadder.h
index bab51b2d3..4bca19930 100644
--- a/src/Blocks/BlockLadder.h
+++ b/src/Blocks/BlockLadder.h
@@ -3,7 +3,7 @@
#include "BlockHandler.h"
#include "BlockInfo.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h
index 60db4ddee..2a676ce00 100644
--- a/src/Blocks/BlockLever.h
+++ b/src/Blocks/BlockLever.h
@@ -5,7 +5,7 @@
#include "Blocks/BlockStairs.h"
#include "ChunkDef.h"
#include "Defines.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
#include "BlockSlab.h"
diff --git a/src/Blocks/BlockMushroom.h b/src/Blocks/BlockMushroom.h
index bed16c557..9e4378d4e 100644
--- a/src/Blocks/BlockMushroom.h
+++ b/src/Blocks/BlockMushroom.h
@@ -23,14 +23,15 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
- if (a_Position.y <= 0)
+ const auto BasePos = a_Position.addedY(-1);
+ if (!cChunkDef::IsValidHeight(BasePos))
{
return false;
}
// TODO: Cannot be at too much daylight
- switch (a_Chunk.GetBlock(a_Position.addedY(-1)))
+ switch (a_Chunk.GetBlock(BasePos))
{
case E_BLOCK_GLASS:
case E_BLOCK_CACTUS:
diff --git a/src/Blocks/BlockNetherWart.h b/src/Blocks/BlockNetherWart.h
index 43081d511..c0686afc6 100644
--- a/src/Blocks/BlockNetherWart.h
+++ b/src/Blocks/BlockNetherWart.h
@@ -60,7 +60,8 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
// Needs to be placed on top of a Soulsand block:
- return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) == E_BLOCK_SOULSAND);
+ const auto BasePos = a_Position.addedY(-1);
+ return cChunkDef::IsValidHeight(BasePos) && (a_Chunk.GetBlock(BasePos) == E_BLOCK_SOULSAND);
}
diff --git a/src/Blocks/BlockObserver.h b/src/Blocks/BlockObserver.h
index 13ffa4631..c2cab3068 100644
--- a/src/Blocks/BlockObserver.h
+++ b/src/Blocks/BlockObserver.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
class cBlockObserverHandler final :
diff --git a/src/Blocks/BlockPiston.cpp b/src/Blocks/BlockPiston.cpp
index 124757b44..568e2eaa5 100644
--- a/src/Blocks/BlockPiston.cpp
+++ b/src/Blocks/BlockPiston.cpp
@@ -48,8 +48,12 @@ void cBlockPistonHandler::ExtendPiston(Vector3i a_BlockPos, cWorld & a_World)
BLOCKTYPE pistonBlock;
NIBBLETYPE pistonMeta;
- a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta);
- a_World.BroadcastBlockAction(a_BlockPos, PistonExtendAction, pistonMeta, pistonBlock);
+ if (a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta))
+ {
+ a_World.BroadcastBlockAction(
+ a_BlockPos, PistonExtendAction, pistonMeta, pistonBlock
+ );
+ }
}
// Client expects the server to "play" the animation before setting the final blocks
@@ -60,9 +64,12 @@ void cBlockPistonHandler::ExtendPiston(Vector3i a_BlockPos, cWorld & a_World)
{
BLOCKTYPE pistonBlock;
NIBBLETYPE pistonMeta;
- World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta);
- if ((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock))
+
+ if (
+ !World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta) ||
+ ((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock))
+ )
{
// Ensure we operate on a piston to avoid spurious behaviour
// Note that the scheduled task may result in the block type of a_BlockPos changing
@@ -104,17 +111,23 @@ void cBlockPistonHandler::RetractPiston(Vector3i a_BlockPos, cWorld & a_World)
{
BLOCKTYPE pistonBlock;
NIBBLETYPE pistonMeta;
- a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta);
- a_World.BroadcastBlockAction(a_BlockPos, PistonRetractAction, pistonMeta, pistonBlock);
+ if (a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta))
+ {
+ a_World.BroadcastBlockAction(
+ a_BlockPos, PistonRetractAction, pistonMeta, pistonBlock
+ );
+ }
}
a_World.ScheduleTask(1_tick, [a_BlockPos](cWorld & World)
{
BLOCKTYPE pistonBlock;
NIBBLETYPE pistonMeta;
- World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta);
- if ((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock))
+ if (
+ !World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta) ||
+ ((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock))
+ )
{
// Ensure we operate on a piston to avoid spurious behaviour
// Note that the scheduled task may result in the block type of a_BlockPos changing
@@ -189,19 +202,20 @@ void cBlockPistonHandler::PushBlocks(
NIBBLETYPE moveMeta;
for (auto & moveBlockPos : sortedBlocks)
{
- a_World.GetBlockTypeMeta(moveBlockPos, moveBlock, moveMeta);
-
- if (cBlockInfo::IsPistonBreakable(moveBlock))
- {
- // Block is breakable, drop it:
- a_World.DropBlockAsPickups(moveBlockPos, nullptr, nullptr);
- }
- else
+ if (a_World.GetBlockTypeMeta(moveBlockPos, moveBlock, moveMeta))
{
- // Not breakable, just move it
- a_World.SetBlock(moveBlockPos, E_BLOCK_AIR, 0);
- moveBlockPos += a_PushDir;
- a_World.SetBlock(moveBlockPos, moveBlock, moveMeta);
+ if (cBlockInfo::IsPistonBreakable(moveBlock))
+ {
+ // Block is breakable, drop it:
+ a_World.DropBlockAsPickups(moveBlockPos, nullptr, nullptr);
+ }
+ else
+ {
+ // Not breakable, just move it
+ a_World.SetBlock(moveBlockPos, E_BLOCK_AIR, 0);
+ moveBlockPos += a_PushDir;
+ a_World.SetBlock(moveBlockPos, moveBlock, moveMeta);
+ }
}
}
}
@@ -232,7 +246,10 @@ bool cBlockPistonHandler::CanPushBlock(
BLOCKTYPE currBlock;
NIBBLETYPE currMeta;
- a_World.GetBlockTypeMeta(a_BlockPos, currBlock, currMeta);
+ if (!a_World.GetBlockTypeMeta(a_BlockPos, currBlock, currMeta))
+ {
+ return !a_RequirePushable;
+ }
if (currBlock == E_BLOCK_AIR)
{
diff --git a/src/Blocks/BlockPiston.h b/src/Blocks/BlockPiston.h
index 4afeb4767..275214036 100644
--- a/src/Blocks/BlockPiston.h
+++ b/src/Blocks/BlockPiston.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
#include "../Item.h"
diff --git a/src/Blocks/BlockPortal.h b/src/Blocks/BlockPortal.h
index 05daa9337..f4b5a50bd 100644
--- a/src/Blocks/BlockPortal.h
+++ b/src/Blocks/BlockPortal.h
@@ -51,9 +51,9 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
- if ((a_Position.y <= 0) || (a_Position.y >= cChunkDef::Height - 1))
+ if (!cChunkDef::IsValidHeight(a_Position.addedY(-1)) || !cChunkDef::IsValidHeight(a_Position.addedY(1)))
{
- return false; // In case someone places a portal with meta 1 or 2 at boundaries, and server tries to get invalid coords at Y - 1 or Y + 1.
+ return false; // Must be 1 away from the boundary, there will always be another portal or an obsidian between the portal block and the boundary.
}
switch (a_Meta)
diff --git a/src/Blocks/BlockPressurePlate.h b/src/Blocks/BlockPressurePlate.h
index 6d852bfc0..d69234cee 100644
--- a/src/Blocks/BlockPressurePlate.h
+++ b/src/Blocks/BlockPressurePlate.h
@@ -22,14 +22,15 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
- if (a_Position.y <= 0)
+ const auto PosBelow = a_Position.addedY(-1);
+ if (!cChunkDef::IsValidHeight(PosBelow))
{
return false;
}
BLOCKTYPE Block;
NIBBLETYPE BlockMeta;
- a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), Block, BlockMeta);
+ a_Chunk.GetBlockTypeMeta(PosBelow, Block, BlockMeta);
// upside down slabs
if (cBlockSlabHandler::IsAnySlabType(Block))
diff --git a/src/Blocks/BlockPumpkin.h b/src/Blocks/BlockPumpkin.h
index e627eeaee..fa73db56a 100644
--- a/src/Blocks/BlockPumpkin.h
+++ b/src/Blocks/BlockPumpkin.h
@@ -1,7 +1,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h
index 4e2e6211f..dea84296f 100644
--- a/src/Blocks/BlockRail.h
+++ b/src/Blocks/BlockRail.h
@@ -1,10 +1,9 @@
#pragma once
#include "BlockHandler.h"
-#include "BlockSlab.h"
-#include "BlockStairs.h"
#include "BlockType.h"
-#include "Blocks/Mixins.h"
+#include "Mixins/Mixins.h"
+#include "Mixins/SolidSurfaceUnderneath.h"
#include "../BlockInfo.h"
#include "../Chunk.h"
#include "ChunkDef.h"
@@ -25,9 +24,9 @@ enum ENUM_PURE
class cBlockRailHandler final :
- public cClearMetaOnDrop<cBlockHandler>
+ public cSolidSurfaceUnderneath<cClearMetaOnDrop<cBlockHandler>>
{
- using Super = cClearMetaOnDrop<cBlockHandler>;
+ using Super = cSolidSurfaceUnderneath<cClearMetaOnDrop<cBlockHandler>>;
public:
@@ -162,26 +161,9 @@ public:
private:
- static bool CanBeSupportedBy(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
- {
- if (cBlockSlabHandler::IsAnySlabType(a_BlockType))
- {
- return (a_BlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN);
- }
- else if (cBlockStairsHandler::IsAnyStairType(a_BlockType))
- {
- return (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN);
- }
- return cBlockInfo::FullyOccupiesVoxel(a_BlockType);
- }
-
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta) const override
{
- BLOCKTYPE BelowBlock;
- NIBBLETYPE BelowBlockMeta;
- a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta);
-
- if ((a_Position.y <= 0) || !CanBeSupportedBy(BelowBlock, BelowBlockMeta))
+ if (!Super::CanBeAt(a_Chunk, a_Position, a_Meta))
{
return false;
}
diff --git a/src/Blocks/BlockRedstoneRepeater.h b/src/Blocks/BlockRedstoneRepeater.h
index 893691d7b..92b4b3917 100644
--- a/src/Blocks/BlockRedstoneRepeater.h
+++ b/src/Blocks/BlockRedstoneRepeater.h
@@ -3,10 +3,9 @@
#include "BlockHandler.h"
#include "BlockType.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
+#include "Mixins/SolidSurfaceUnderneath.h"
#include "ChunkInterface.h"
-#include "BlockSlab.h"
-#include "BlockStairs.h"
#include "../Chunk.h"
@@ -14,9 +13,9 @@
class cBlockRedstoneRepeaterHandler final :
- public cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>
+ public cSolidSurfaceUnderneath<cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>>
{
- using Super = cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>;
+ using Super = cSolidSurfaceUnderneath<cYawRotator<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03>>;
public:
@@ -107,41 +106,6 @@ private:
- virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
- {
- if (a_Position.y <= 0)
- {
- return false;
- }
-
- BLOCKTYPE BelowBlock;
- NIBBLETYPE BelowBlockMeta;
- a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta);
-
- if (cBlockInfo::FullyOccupiesVoxel(BelowBlock))
- {
- return true;
- }
-
- // upside down slabs
- if (cBlockSlabHandler::IsAnySlabType(BelowBlock))
- {
- return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN;
- }
-
- // upside down stairs
- if (cBlockStairsHandler::IsAnyStairType(BelowBlock))
- {
- return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN;
- }
-
- return false;
- }
-
-
-
-
-
virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
{
return cItem(E_ITEM_REDSTONE_REPEATER, 1, 0);
diff --git a/src/Blocks/BlockRedstoneWire.h b/src/Blocks/BlockRedstoneWire.h
index de8e59a40..edea704f4 100644
--- a/src/Blocks/BlockRedstoneWire.h
+++ b/src/Blocks/BlockRedstoneWire.h
@@ -2,17 +2,15 @@
#pragma once
#include "BlockHandler.h"
-#include "BlockSlab.h"
-#include "BlockStairs.h"
-#include "../Chunk.h"
+#include "Mixins/SolidSurfaceUnderneath.h"
class cBlockRedstoneWireHandler final :
- public cBlockHandler
+ public cSolidSurfaceUnderneath<cBlockHandler>
{
- using Super = cBlockHandler;
+ using Super = cSolidSurfaceUnderneath<cBlockHandler>;
public:
@@ -20,41 +18,6 @@ public:
private:
- virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
- {
- if (a_Position.y <= 0)
- {
- return false;
- }
-
- BLOCKTYPE BelowBlock;
- NIBBLETYPE BelowBlockMeta;
- a_Chunk.GetBlockTypeMeta(a_Position.addedY(-1), BelowBlock, BelowBlockMeta);
-
- if (cBlockInfo::FullyOccupiesVoxel(BelowBlock))
- {
- return true;
- }
-
- // upside down slabs
- if (cBlockSlabHandler::IsAnySlabType(BelowBlock))
- {
- return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN;
- }
-
- // upside down stairs
- if (cBlockStairsHandler::IsAnyStairType(BelowBlock))
- {
- return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN;
- }
-
- return false;
- }
-
-
-
-
-
virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
{
return cItem(E_ITEM_REDSTONE_DUST, 1, 0);
diff --git a/src/Blocks/BlockSapling.h b/src/Blocks/BlockSapling.h
index d32b9b449..db953946a 100644
--- a/src/Blocks/BlockSapling.h
+++ b/src/Blocks/BlockSapling.h
@@ -3,15 +3,16 @@
#include "BlockHandler.h"
#include "../FastRandom.h"
+#include "Mixins/DirtLikeUnderneath.h"
class cBlockSaplingHandler final :
- public cBlockHandler
+ public cDirtLikeUnderneath<cBlockHandler>
{
- using Super = cBlockHandler;
+ using Super = cDirtLikeUnderneath<cBlockHandler>;
public:
@@ -29,15 +30,6 @@ private:
- virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
- {
- return (a_Position.y > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_Position.addedY(-1)));
- }
-
-
-
-
-
virtual void OnUpdate(
cChunkInterface & a_ChunkInterface,
cWorldInterface & a_WorldInterface,
diff --git a/src/Blocks/BlockSignPost.h b/src/Blocks/BlockSignPost.h
index b96498cbd..89da77fbb 100644
--- a/src/Blocks/BlockSignPost.h
+++ b/src/Blocks/BlockSignPost.h
@@ -30,12 +30,13 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
- if (a_Position.y <= 0)
+ const auto BelowPos = a_Position.addedY(-1);
+ if (!cChunkDef::IsValidHeight(BelowPos))
{
return false;
}
- BLOCKTYPE Type = a_Chunk.GetBlock(a_Position.addedY(-1));
+ BLOCKTYPE Type = a_Chunk.GetBlock(BelowPos);
return (Type == E_BLOCK_SIGN_POST) || (Type == E_BLOCK_WALLSIGN) || cBlockInfo::IsSolid(Type);
}
diff --git a/src/Blocks/BlockSnow.h b/src/Blocks/BlockSnow.h
index f3fa87a1b..51361ce17 100644
--- a/src/Blocks/BlockSnow.h
+++ b/src/Blocks/BlockSnow.h
@@ -69,11 +69,11 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
- if (a_Position.y <= 0)
+ const auto BelowPos = a_Position.addedY(-1);
+ if (!cChunkDef::IsValidHeight(BelowPos))
{
return false;
}
- auto BelowPos = a_Position.addedY(-1);
auto BlockBelow = a_Chunk.GetBlock(BelowPos);
auto MetaBelow = a_Chunk.GetMeta(BelowPos);
return CanBeOn(BlockBelow, MetaBelow);
diff --git a/src/Blocks/BlockStairs.h b/src/Blocks/BlockStairs.h
index 76614bb62..6c37a8464 100644
--- a/src/Blocks/BlockStairs.h
+++ b/src/Blocks/BlockStairs.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockBanner.h b/src/Blocks/BlockStandingBanner.h
index e6a159bd4..0cc7c28eb 100644
--- a/src/Blocks/BlockBanner.h
+++ b/src/Blocks/BlockStandingBanner.h
@@ -1,19 +1,20 @@
-// BlockBanner.h
+// BlockStandingBanner.h
#pragma once
#include "../BlockInfo.h"
#include "BlockEntity.h"
+#include "Mixins/SolidSurfaceUnderneath.h"
-class cBlockBannerHandler final :
- public cBlockEntityHandler
+class cBlockStandingBannerHandler final :
+ public cSolidSurfaceUnderneath<cBlockEntityHandler>
{
- using Super = cBlockEntityHandler;
+ using Super = cSolidSurfaceUnderneath<cBlockEntityHandler>;
public:
@@ -29,20 +30,6 @@ public:
- virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
- {
- if (a_Position.y < 1)
- {
- return false;
- }
-
- return cBlockInfo::IsSolid(a_Chunk.GetBlock(a_Position.addedY(-1)));
- }
-
-
-
-
-
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
{
UNUSED(a_Meta);
diff --git a/src/Blocks/BlockStems.h b/src/Blocks/BlockStems.h
index 11cd83967..9d598003d 100644
--- a/src/Blocks/BlockStems.h
+++ b/src/Blocks/BlockStems.h
@@ -58,7 +58,8 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
- return (a_Position.y > 0) && (a_Chunk.GetBlock(a_Position.addedY(-1)) == E_BLOCK_FARMLAND);
+ const auto BelowPos = a_Position.addedY(-1);
+ return cChunkDef::IsValidHeight(BelowPos) && (a_Chunk.GetBlock(BelowPos) == E_BLOCK_FARMLAND);
}
diff --git a/src/Blocks/BlockSugarCane.h b/src/Blocks/BlockSugarCane.h
index cffe667e5..1f6c8a8fa 100644
--- a/src/Blocks/BlockSugarCane.h
+++ b/src/Blocks/BlockSugarCane.h
@@ -29,12 +29,13 @@ private:
virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
{
- if (a_Position.y <= 0)
+ const auto BelowPos = a_Position.addedY(-1);
+ if (!cChunkDef::IsValidHeight(BelowPos))
{
return false;
}
- switch (a_Chunk.GetBlock(a_Position.addedY(-1)))
+ switch (a_Chunk.GetBlock(BelowPos))
{
case E_BLOCK_DIRT:
case E_BLOCK_GRASS:
@@ -43,16 +44,16 @@ private:
{
static const Vector3i Coords[] =
{
- {-1, -1, 0},
- { 1, -1, 0},
- { 0, -1, -1},
- { 0, -1, 1},
+ {-1, 0, 0},
+ { 1, 0, 0},
+ { 0, 0, -1},
+ { 0, 0, 1},
} ;
for (size_t i = 0; i < ARRAYCOUNT(Coords); i++)
{
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
- if (!a_Chunk.UnboundedRelGetBlock(a_Position + Coords[i], BlockType, BlockMeta))
+ if (!a_Chunk.UnboundedRelGetBlock(BelowPos + Coords[i], BlockType, BlockMeta))
{
// Too close to the edge, cannot simulate
return true;
@@ -90,31 +91,36 @@ private:
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override
{
// Check the total height of the sugarcane blocks here:
- int top = a_RelPos.y + 1;
+ auto top = a_RelPos.addedY(1);
while (
- (top < cChunkDef::Height) &&
- (a_Chunk.GetBlock({a_RelPos.x, top, a_RelPos.z}) == E_BLOCK_SUGARCANE)
+ cChunkDef::IsValidHeight(top) &&
+ (a_Chunk.GetBlock(top) == E_BLOCK_SUGARCANE)
)
{
- ++top;
+ ++top.y;
}
- int bottom = a_RelPos.y - 1;
+ auto bottom = a_RelPos.addedY(-1);
while (
- (bottom > 0) &&
- (a_Chunk.GetBlock({a_RelPos.x, bottom, a_RelPos.z}) == E_BLOCK_SUGARCANE)
+ cChunkDef::IsValidHeight(bottom) &&
+ (a_Chunk.GetBlock(bottom) == E_BLOCK_SUGARCANE)
)
{
- --bottom;
+ --bottom.y;
}
// Grow by at most a_NumStages, but no more than max height:
- auto toGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxSugarcaneHeight() + 1 - (top - bottom));
- Vector3i topPos(a_RelPos.x, top, a_RelPos.z);
+ auto toGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxSugarcaneHeight() + 1 - (top.y - bottom.y));
for (int i = 0; i < toGrow; i++)
{
- if (a_Chunk.GetBlock(topPos.addedY(i)) == E_BLOCK_AIR)
+ const auto NewTop = top.addedY(i);
+ if (!cChunkDef::IsValidHeight(NewTop))
{
- a_Chunk.SetBlock(topPos.addedY(i), E_BLOCK_SUGARCANE, 0);
+ return i;
+ }
+
+ if (a_Chunk.GetBlock(NewTop) == E_BLOCK_AIR)
+ {
+ a_Chunk.SetBlock(NewTop, E_BLOCK_SUGARCANE, 0);
}
else
{
diff --git a/src/Blocks/BlockTallGrass.h b/src/Blocks/BlockTallGrass.h
index ea638c878..47ad2f93d 100644
--- a/src/Blocks/BlockTallGrass.h
+++ b/src/Blocks/BlockTallGrass.h
@@ -2,6 +2,7 @@
#pragma once
#include "BlockHandler.h"
+#include "Mixins/DirtLikeUnderneath.h"
#include "ChunkInterface.h"
@@ -10,9 +11,9 @@
/** Handles the grass that is 1 block tall */
class cBlockTallGrassHandler final :
- public cBlockHandler
+ public cDirtLikeUnderneath<cBlockHandler>
{
- using Super = cBlockHandler;
+ using Super = cDirtLikeUnderneath<cBlockHandler>;
public:
@@ -52,25 +53,11 @@ private:
- virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
- {
- if (a_Position.y <= 0)
- {
- return false;
- }
-
- BLOCKTYPE BelowBlock = a_Chunk.GetBlock(a_Position.addedY(-1));
- return IsBlockTypeOfDirt(BelowBlock);
- }
-
-
-
-
-
/** Growing a tall grass produces a big flower (2-block high fern or double-tall grass). */
virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override
{
- if (a_RelPos.y > (cChunkDef::Height - 2))
+ const auto TopPos = a_RelPos.addedY(1);
+ if (!cChunkDef::IsValidHeight(TopPos))
{
return 0;
}
@@ -83,7 +70,7 @@ private:
default: return 0;
}
a_Chunk.SetBlock(a_RelPos, E_BLOCK_BIG_FLOWER, largeFlowerMeta);
- a_Chunk.SetBlock(a_RelPos.addedY(1), E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP);
+ a_Chunk.SetBlock(TopPos, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP);
return 1;
}
diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h
index ad69cf5eb..99f685cb6 100644
--- a/src/Blocks/BlockTorch.h
+++ b/src/Blocks/BlockTorch.h
@@ -7,7 +7,7 @@
#include "BlockType.h"
#include "ChunkInterface.h"
#include "Defines.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
@@ -126,7 +126,7 @@ private:
NIBBLETYPE NeighborBlockMeta;
if (!a_Chunk.UnboundedRelGetBlock(NeighborRelPos, NeighborBlockType, NeighborBlockMeta))
{
- // Neighbor in an unloaded chunk, bail out without changint this.
+ // Neighbor in an unloaded chunk, bail out without changing this.
return false;
}
diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h
index 7f6f70e1e..3fb4f4ca3 100644
--- a/src/Blocks/BlockTrapdoor.h
+++ b/src/Blocks/BlockTrapdoor.h
@@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
#include "../EffectID.h"
diff --git a/src/Blocks/BlockTripwireHook.h b/src/Blocks/BlockTripwireHook.h
index ae553d66f..ede6ca311 100644
--- a/src/Blocks/BlockTripwireHook.h
+++ b/src/Blocks/BlockTripwireHook.h
@@ -1,7 +1,7 @@
#pragma once
#include "BlockHandler.h"
-#include "Mixins.h"
+#include "Mixins/Mixins.h"
diff --git a/src/Blocks/BlockVines.h b/src/Blocks/BlockVines.h
index a23ba1489..edbd30f36 100644
--- a/src/Blocks/BlockVines.h
+++ b/src/Blocks/BlockVines.h
@@ -119,15 +119,16 @@ private:
}
// Check if vine above us, add its meta to MaxMeta:
- if ((a_Position.y < cChunkDef::Height - 1) && (a_Chunk.GetBlock(a_Position.addedY(1)) == E_BLOCK_VINES))
+ const auto AbovePos = a_Position.addedY(1);
+ if (cChunkDef::IsValidHeight(AbovePos) && (a_Chunk.GetBlock(AbovePos) == E_BLOCK_VINES))
{
- MaxMeta |= a_Chunk.GetMeta(a_Position.addedY(1));
+ MaxMeta |= a_Chunk.GetMeta(AbovePos);
}
NIBBLETYPE Common = a_CurrentMeta & MaxMeta; // Neighbors that we have and are legal.
if (Common != a_CurrentMeta)
{
- bool HasTop = (a_Position.y < (cChunkDef::Height - 1)) && IsBlockAttachable(a_Chunk.GetBlock(a_Position.addedY(1)));
+ bool HasTop = cChunkDef::IsValidHeight(AbovePos) && IsBlockAttachable(a_Chunk.GetBlock(AbovePos));
if ((Common == 0) && !HasTop) // Meta equals 0 also means top. Make a last-ditch attempt to save the vine.
{
return VINE_LOST_SUPPORT;
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..7e3047451 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,11 +104,12 @@ target_sources(
BlockTripwire.h
BlockTripwireHook.h
BlockVines.h
+ BlockWallBanner.h
BlockWallSign.h
BlockWorkbench.h
BroadcastInterface.h
ChunkInterface.h
GetHandlerCompileTimeTemplate.h
- Mixins.h
+ Mixins/Mixins.h
WorldInterface.h
)
diff --git a/src/Blocks/Mixins/DirtLikeUnderneath.h b/src/Blocks/Mixins/DirtLikeUnderneath.h
new file mode 100644
index 000000000..909f1601e
--- /dev/null
+++ b/src/Blocks/Mixins/DirtLikeUnderneath.h
@@ -0,0 +1,42 @@
+
+#pragma once
+
+#include "../../Chunk.h"
+
+/** Mixin to ensure the block has a dirt-like block underneath. */
+template <class Base>
+class cDirtLikeUnderneath :
+ public Base
+{
+ using Super = Base;
+public:
+
+ using Super::Super;
+
+ constexpr cDirtLikeUnderneath(BLOCKTYPE a_BlockType):
+ Base(a_BlockType)
+ {
+ }
+
+protected:
+
+ ~cDirtLikeUnderneath() = default;
+
+protected:
+
+ virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
+ {
+ if (!Super::CanBeAt(a_Chunk, a_Position, a_Meta))
+ {
+ return false;
+ }
+
+ const auto BelowPos = a_Position.addedY(-1);
+ if (!cChunkDef::IsValidHeight(BelowPos))
+ {
+ return false;
+ }
+
+ return IsBlockTypeOfDirt(a_Chunk.GetBlock(BelowPos));
+ }
+};
diff --git a/src/Blocks/Mixins.h b/src/Blocks/Mixins/Mixins.h
index fa8985737..d9a233bad 100644
--- a/src/Blocks/Mixins.h
+++ b/src/Blocks/Mixins/Mixins.h
@@ -9,7 +9,7 @@ class cBlockLadder: public cMetaRotator<cClearMetaOnDrop, ...>
#pragma once
-#include "../Item.h"
+#include "../../Item.h"
diff --git a/src/Blocks/Mixins/SolidSurfaceUnderneath.h b/src/Blocks/Mixins/SolidSurfaceUnderneath.h
new file mode 100644
index 000000000..c54c064d6
--- /dev/null
+++ b/src/Blocks/Mixins/SolidSurfaceUnderneath.h
@@ -0,0 +1,65 @@
+
+#pragma once
+
+#include "../../Chunk.h"
+#include "../BlockSlab.h"
+#include "../BlockStairs.h"
+
+/** Mixin to ensure the block has a solid surface underneath. */
+template <class Base>
+class cSolidSurfaceUnderneath :
+ public Base
+{
+ using Super = Base;
+public:
+
+ using Super::Super;
+
+ constexpr cSolidSurfaceUnderneath(BLOCKTYPE a_BlockType):
+ Base(a_BlockType)
+ {
+ }
+
+protected:
+
+ ~cSolidSurfaceUnderneath() = default;
+
+protected:
+
+ virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override
+ {
+ if (!Super::CanBeAt(a_Chunk, a_Position, a_Meta))
+ {
+ return false;
+ }
+
+ const auto BelowPos = a_Position.addedY(-1);
+ if (!cChunkDef::IsValidHeight(BelowPos))
+ {
+ return false;
+ }
+
+ BLOCKTYPE BelowBlock;
+ NIBBLETYPE BelowBlockMeta;
+ a_Chunk.GetBlockTypeMeta(BelowPos, BelowBlock, BelowBlockMeta);
+
+ if (cBlockInfo::FullyOccupiesVoxel(BelowBlock))
+ {
+ return true;
+ }
+
+ // upside down slabs
+ if (cBlockSlabHandler::IsAnySlabType(BelowBlock))
+ {
+ return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN;
+ }
+
+ // upside down stairs
+ if (cBlockStairsHandler::IsAnyStairType(BelowBlock))
+ {
+ return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN;
+ }
+
+ return false;
+ }
+};
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/ChunkMap.cpp b/src/ChunkMap.cpp
index a2bc50fe9..d982d0cf3 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -474,6 +474,11 @@ void cChunkMap::CollectPickupsByEntity(cEntity & a_Entity)
BLOCKTYPE cChunkMap::GetBlock(Vector3i a_BlockPos) const
{
+ if (!cChunkDef::IsValidHeight(a_BlockPos))
+ {
+ return 0;
+ }
+
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
@@ -493,6 +498,11 @@ BLOCKTYPE cChunkMap::GetBlock(Vector3i a_BlockPos) const
NIBBLETYPE cChunkMap::GetBlockMeta(Vector3i a_BlockPos) const
{
+ if (!cChunkDef::IsValidHeight(a_BlockPos))
+ {
+ return 0;
+ }
+
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
@@ -585,6 +595,14 @@ void cChunkMap::SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE
bool cChunkMap::GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const
{
+ if (!cChunkDef::IsValidHeight(a_BlockPos))
+ {
+ // Initialise the params to fulfil our contract.
+ a_BlockType = 0;
+ a_BlockMeta = 0;
+ return false;
+ }
+
auto chunkCoord = cChunkDef::BlockToChunk(a_BlockPos);
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkCoord);
@@ -595,6 +613,10 @@ bool cChunkMap::GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, N
Chunk->GetBlockTypeMeta(relPos, a_BlockType, a_BlockMeta);
return true;
}
+
+ // Initialise the params to fulfil our contract.
+ a_BlockType = 0;
+ a_BlockMeta = 0;
return false;
}
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index 578c49b8a..8538b7624 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -115,6 +115,10 @@ public:
void SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_BlockMeta);
void SetBlock (Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
+ /** Get the block type and meta at the specified coords
+ Will always initialise a_BlockType and a_BlockMeta if called.
+ Returns false if the data could not be retrieved, either because the chunk is invalid or the height is invalid.
+ Otherwise, returns true. */
bool GetBlockTypeMeta (Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
bool GetBlockInfo (Vector3i, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) const;
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index b726e5c6f..2b32c5c07 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()),
@@ -1253,7 +1254,10 @@ void cClientHandle::HandleBlockDigStarted(Vector3i a_BlockPos, eBlockFace a_Bloc
BLOCKTYPE DiggingBlock;
NIBBLETYPE DiggingMeta;
- m_Player->GetWorld()->GetBlockTypeMeta(a_BlockPos, DiggingBlock, DiggingMeta);
+ if (!m_Player->GetWorld()->GetBlockTypeMeta(a_BlockPos, DiggingBlock, DiggingMeta))
+ {
+ return;
+ }
if (
m_Player->IsGameModeCreative() &&
@@ -1321,7 +1325,10 @@ void cClientHandle::HandleBlockDigFinished(Vector3i a_BlockPos, eBlockFace a_Blo
BLOCKTYPE DugBlock;
NIBBLETYPE DugMeta;
- m_Player->GetWorld()->GetBlockTypeMeta(a_BlockPos, DugBlock, DugMeta);
+ if (!m_Player->GetWorld()->GetBlockTypeMeta(a_BlockPos, DugBlock, DugMeta))
+ {
+ return;
+ }
if (!m_Player->IsGameModeCreative())
{
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..50fd034a5 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);
}
@@ -2587,9 +2594,10 @@ bool cPlayer::IsInsideWater()
BLOCKTYPE Block;
NIBBLETYPE Meta;
- m_World->GetBlockTypeMeta(EyePos, Block, Meta);
-
- if ((Block != E_BLOCK_WATER) && (Block != E_BLOCK_STATIONARY_WATER))
+ if (
+ !m_World->GetBlockTypeMeta(GetEyePosition().Floor(), Block, Meta) ||
+ ((Block != E_BLOCK_WATER) && (Block != E_BLOCK_STATIONARY_WATER))
+ )
{
return false;
}
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/Items/ItemBed.h b/src/Items/ItemBed.h
index a2e254171..77818e7c7 100644
--- a/src/Items/ItemBed.h
+++ b/src/Items/ItemBed.h
@@ -27,7 +27,10 @@ public:
auto & World = *a_Player.GetWorld();
BLOCKTYPE HeadType;
NIBBLETYPE HeadMeta;
- World.GetBlockTypeMeta(HeadPosition, HeadType, HeadMeta);
+ if (!World.GetBlockTypeMeta(HeadPosition, HeadType, HeadMeta))
+ {
+ return false;
+ }
// Vanilla only allows beds to be placed into air.
// Check if there is empty space for the "head" block:
diff --git a/src/Items/ItemBigFlower.h b/src/Items/ItemBigFlower.h
index cbdecbed7..a135a220d 100644
--- a/src/Items/ItemBigFlower.h
+++ b/src/Items/ItemBigFlower.h
@@ -29,7 +29,10 @@ public:
const auto TopPos = a_PlacePosition.addedY(1);
BLOCKTYPE TopType;
NIBBLETYPE TopMeta;
- World.GetBlockTypeMeta(TopPos, TopType, TopMeta);
+ if (!World.GetBlockTypeMeta(TopPos, TopType, TopMeta))
+ {
+ return false;
+ }
if (!cBlockHandler::For(TopType).DoesIgnoreBuildCollision(World, a_HeldItem, TopPos, TopMeta, a_ClickedBlockFace, false))
{
diff --git a/src/Items/ItemDoor.h b/src/Items/ItemDoor.h
index 6538a5bef..f28d3ad36 100644
--- a/src/Items/ItemDoor.h
+++ b/src/Items/ItemDoor.h
@@ -54,7 +54,10 @@ public:
{
BLOCKTYPE TopType;
NIBBLETYPE TopMeta;
- World.GetBlockTypeMeta(UpperBlockPosition, TopType, TopMeta);
+ if (!World.GetBlockTypeMeta(UpperBlockPosition, TopType, TopMeta))
+ {
+ return false;
+ }
if (!cBlockHandler::For(TopType).DoesIgnoreBuildCollision(World, a_HeldItem, UpperBlockPosition, TopMeta, a_ClickedBlockFace, false))
{
diff --git a/src/Items/ItemDye.h b/src/Items/ItemDye.h
index 636a1b477..b0f00b9ba 100644
--- a/src/Items/ItemDye.h
+++ b/src/Items/ItemDye.h
@@ -54,10 +54,12 @@ public:
// Cocoa (brown dye) can be planted on jungle logs:
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
- a_World->GetBlockTypeMeta(a_ClickedBlockPos, BlockType, BlockMeta);
// Check if the block that the player clicked is a jungle log.
- if ((BlockType != E_BLOCK_LOG) || ((BlockMeta & 0x03) != E_META_LOG_JUNGLE))
+ if (
+ !a_World->GetBlockTypeMeta(a_ClickedBlockPos, BlockType, BlockMeta) ||
+ ((BlockType != E_BLOCK_LOG) || ((BlockMeta & 0x03) != E_META_LOG_JUNGLE))
+ )
{
return false;
}
diff --git a/src/Items/ItemEyeOfEnder.h b/src/Items/ItemEyeOfEnder.h
index fc6fac336..414d81c39 100644
--- a/src/Items/ItemEyeOfEnder.h
+++ b/src/Items/ItemEyeOfEnder.h
@@ -35,8 +35,8 @@ public:
{
BLOCKTYPE FacingBlock;
NIBBLETYPE FacingMeta;
- a_World->GetBlockTypeMeta(a_ClickedBlockPos, FacingBlock, FacingMeta);
- if (FacingBlock == E_BLOCK_END_PORTAL_FRAME)
+
+ if (a_World->GetBlockTypeMeta(a_ClickedBlockPos, FacingBlock, FacingMeta) && (FacingBlock == E_BLOCK_END_PORTAL_FRAME))
{
// Fill the portal frame. E_META_END_PORTAL_EYE is the bit for holding the eye of ender.
if ((FacingMeta & E_META_END_PORTAL_FRAME_EYE) != E_META_END_PORTAL_FRAME_EYE)
diff --git a/src/Items/ItemHoe.h b/src/Items/ItemHoe.h
index 2bca5f5ca..503047328 100644
--- a/src/Items/ItemHoe.h
+++ b/src/Items/ItemHoe.h
@@ -46,7 +46,10 @@ public:
// Can only transform dirt or grass blocks:
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
- a_World->GetBlockTypeMeta(a_ClickedBlockPos, BlockType, BlockMeta);
+ if (!a_World->GetBlockTypeMeta(a_ClickedBlockPos, BlockType, BlockMeta))
+ {
+ return false;
+ }
if ((BlockType != E_BLOCK_DIRT) && (BlockType != E_BLOCK_GRASS))
{
return false;
diff --git a/src/Items/ItemShears.h b/src/Items/ItemShears.h
index 5f8e9e2f1..00504884c 100644
--- a/src/Items/ItemShears.h
+++ b/src/Items/ItemShears.h
@@ -32,7 +32,10 @@ public:
{
BLOCKTYPE Block;
NIBBLETYPE BlockMeta;
- a_World->GetBlockTypeMeta(a_ClickedBlockPos, Block, BlockMeta);
+ if (!a_World->GetBlockTypeMeta(a_ClickedBlockPos, Block, BlockMeta))
+ {
+ return false;
+ }
if ((Block == E_BLOCK_LEAVES) || (Block == E_BLOCK_NEW_LEAVES))
{
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/Protocol/ChunkDataSerializer.cpp b/src/Protocol/ChunkDataSerializer.cpp
index cfabc6e31..6b5553ee7 100644
--- a/src/Protocol/ChunkDataSerializer.cpp
+++ b/src/Protocol/ChunkDataSerializer.cpp
@@ -502,7 +502,7 @@ inline void cChunkDataSerializer::Serialize477(const int a_ChunkX, const int a_C
// Write each chunk section...
ChunkDef_ForEachSection(a_BlockData, a_LightData,
{
- m_Packet.WriteBEInt16(-1);
+ m_Packet.WriteBEInt16(ChunkBlockData::SectionBlockCount); // a temp fix to make sure sections don't disappear
m_Packet.WriteBEUInt8(BitsPerEntry);
m_Packet.WriteVarInt32(static_cast<UInt32>(ChunkSectionDataArraySize));
WriteBlockSectionSeamless<&Palette477>(Blocks, Metas, BitsPerEntry);
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/UI/SlotArea.cpp b/src/UI/SlotArea.cpp
index 4085dc816..ef5f7382e 100644
--- a/src/UI/SlotArea.cpp
+++ b/src/UI/SlotArea.cpp
@@ -1065,9 +1065,12 @@ void cSlotAreaAnvil::OnTakeResult(cPlayer & a_Player)
BLOCKTYPE Block;
NIBBLETYPE BlockMeta;
- a_Player.GetWorld()->GetBlockTypeMeta(BlockPos, Block, BlockMeta);
- if (!a_Player.IsGameModeCreative() && (Block == E_BLOCK_ANVIL) && GetRandomProvider().RandBool(0.12))
+ if (
+ a_Player.GetWorld()->GetBlockTypeMeta(BlockPos, Block, BlockMeta) &&
+ !a_Player.IsGameModeCreative() && (Block == E_BLOCK_ANVIL) &&
+ GetRandomProvider().RandBool(0.12)
+ )
{
NIBBLETYPE Orientation = BlockMeta & 0x3;
NIBBLETYPE AnvilDamage = BlockMeta >> 2;
diff --git a/src/Vector3.h b/src/Vector3.h
index 0e275e9b3..5df14b3ac 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>
+ 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(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(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/World.cpp b/src/World.cpp
index 2f92020bf..781d44c3a 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -1539,8 +1539,7 @@ bool cWorld::GetLargeTreeAdjustment(Vector3i & a_BlockPos, NIBBLETYPE a_Meta)
{
NIBBLETYPE meta;
BLOCKTYPE type;
- GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta);
- IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
+ IsLarge = IsLarge && GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta) && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
}
}
@@ -1557,8 +1556,7 @@ bool cWorld::GetLargeTreeAdjustment(Vector3i & a_BlockPos, NIBBLETYPE a_Meta)
{
NIBBLETYPE meta;
BLOCKTYPE type;
- GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta);
- IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
+ IsLarge = IsLarge && GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta) && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
}
}
@@ -1576,8 +1574,7 @@ bool cWorld::GetLargeTreeAdjustment(Vector3i & a_BlockPos, NIBBLETYPE a_Meta)
{
NIBBLETYPE meta;
BLOCKTYPE type;
- GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta);
- IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
+ IsLarge = IsLarge && GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta) && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
}
}
@@ -1596,8 +1593,7 @@ bool cWorld::GetLargeTreeAdjustment(Vector3i & a_BlockPos, NIBBLETYPE a_Meta)
{
NIBBLETYPE meta;
BLOCKTYPE type;
- GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta);
- IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
+ IsLarge = IsLarge && GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta) && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta);
}
}
@@ -2044,7 +2040,10 @@ void cWorld::PlaceBlock(const Vector3i a_Position, const BLOCKTYPE a_BlockType,
{
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
- GetBlockTypeMeta(a_Position, BlockType, BlockMeta);
+ if (!GetBlockTypeMeta(a_Position, BlockType, BlockMeta))
+ {
+ return;
+ }
SetBlock(a_Position, a_BlockType, a_BlockMeta);
@@ -2070,7 +2069,10 @@ bool cWorld::DigBlock(Vector3i a_BlockPos, const cEntity * a_Digger)
{
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
- GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta);
+ if (!GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta))
+ {
+ return false;
+ }
if (!m_ChunkMap.DigBlock(a_BlockPos))
{
@@ -2617,7 +2619,11 @@ bool cWorld::IsTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ)
{
BLOCKTYPE Block;
NIBBLETYPE Meta;
- GetBlockTypeMeta({ a_BlockX, a_BlockY, a_BlockZ }, Block, Meta);
+ if (!GetBlockTypeMeta({ a_BlockX, a_BlockY, a_BlockZ }, Block, Meta))
+ {
+ return false;
+ }
+
if ((Block != E_BLOCK_TRAPDOOR) && (Block != E_BLOCK_IRON_TRAPDOOR))
{
return false;
@@ -2634,7 +2640,11 @@ bool cWorld::SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Op
{
BLOCKTYPE Block;
NIBBLETYPE Meta;
- GetBlockTypeMeta({ a_BlockX, a_BlockY, a_BlockZ }, Block, Meta);
+ if (!GetBlockTypeMeta({ a_BlockX, a_BlockY, a_BlockZ }, Block, Meta))
+ {
+ return false;
+ }
+
if ((Block != E_BLOCK_TRAPDOOR) && (Block != E_BLOCK_IRON_TRAPDOOR))
{
return false;
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/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 6b425c4dc..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())
{
diff --git a/src/mbedTLS++/CryptoKey.cpp b/src/mbedTLS++/CryptoKey.cpp
index 742d9c73c..ea01bfc80 100644
--- a/src/mbedTLS++/CryptoKey.cpp
+++ b/src/mbedTLS++/CryptoKey.cpp
@@ -124,15 +124,18 @@ int cCryptoKey::ParsePrivate(const void * a_Data, size_t a_NumBytes, const AStri
if (a_Password.empty())
{
- return mbedtls_pk_parse_key(&m_Pk, reinterpret_cast<const unsigned char *>(keyData.data()), a_NumBytes + 1, nullptr, 0, mbedtls_ctr_drbg_random, m_CtrDrbg.GetInternal());
+ return mbedtls_pk_parse_key(
+ &m_Pk,
+ reinterpret_cast<const unsigned char *>(keyData.data()), a_NumBytes + 1,
+ nullptr, 0
+ );
}
else
{
return mbedtls_pk_parse_key(
&m_Pk,
reinterpret_cast<const unsigned char *>(keyData.data()), a_NumBytes + 1,
- reinterpret_cast<const unsigned char *>(a_Password.c_str()), a_Password.size(),
- mbedtls_ctr_drbg_random, m_CtrDrbg.GetInternal()
+ reinterpret_cast<const unsigned char *>(a_Password.c_str()), a_Password.size()
);
}
}
diff --git a/src/mbedTLS++/RsaPrivateKey.cpp b/src/mbedTLS++/RsaPrivateKey.cpp
index d0c5b7c8b..81cd2db44 100644
--- a/src/mbedTLS++/RsaPrivateKey.cpp
+++ b/src/mbedTLS++/RsaPrivateKey.cpp
@@ -11,7 +11,7 @@
cRsaPrivateKey::cRsaPrivateKey(void)
{
- mbedtls_rsa_init(&m_Rsa);
+ mbedtls_rsa_init(&m_Rsa, MBEDTLS_RSA_PKCS_V15, 0);
m_CtrDrbg.Initialize("RSA", 3);
}
@@ -21,7 +21,7 @@ cRsaPrivateKey::cRsaPrivateKey(void)
cRsaPrivateKey::cRsaPrivateKey(const cRsaPrivateKey & a_Other)
{
- mbedtls_rsa_init(&m_Rsa);
+ mbedtls_rsa_init(&m_Rsa, MBEDTLS_RSA_PKCS_V15, 0);
mbedtls_rsa_copy(&m_Rsa, &a_Other.m_Rsa);
m_CtrDrbg.Initialize("RSA", 3);
}
@@ -122,7 +122,7 @@ int cRsaPrivateKey::Decrypt(const ContiguousByteBufferView a_EncryptedData, Byte
}
size_t DecryptedLength;
int res = mbedtls_rsa_pkcs1_decrypt(
- &m_Rsa, mbedtls_ctr_drbg_random, m_CtrDrbg.GetInternal(), &DecryptedLength,
+ &m_Rsa, mbedtls_ctr_drbg_random, m_CtrDrbg.GetInternal(), MBEDTLS_RSA_PRIVATE, &DecryptedLength,
reinterpret_cast<const unsigned char *>(a_EncryptedData.data()), a_DecryptedData, a_DecryptedMaxLength
);
if (res != 0)