summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHowaner <franzi.moos@googlemail.com>2014-09-12 19:13:46 +0200
committerHowaner <franzi.moos@googlemail.com>2014-09-12 19:13:46 +0200
commit1223a24d3c87832c08545e6f3e8e4c51ff1e7e3f (patch)
treef7cf72e49a7ca60d10af12ad9ff70910e089b028 /src
parentRenamed SetWalkSpeed() to SetRelativeWalkSpeed() (diff)
parentFixed iron ore drop. (diff)
downloadcuberite-1223a24d3c87832c08545e6f3e8e4c51ff1e7e3f.tar
cuberite-1223a24d3c87832c08545e6f3e8e4c51ff1e7e3f.tar.gz
cuberite-1223a24d3c87832c08545e6f3e8e4c51ff1e7e3f.tar.bz2
cuberite-1223a24d3c87832c08545e6f3e8e4c51ff1e7e3f.tar.lz
cuberite-1223a24d3c87832c08545e6f3e8e4c51ff1e7e3f.tar.xz
cuberite-1223a24d3c87832c08545e6f3e8e4c51ff1e7e3f.tar.zst
cuberite-1223a24d3c87832c08545e6f3e8e4c51ff1e7e3f.zip
Diffstat (limited to '')
-rw-r--r--src/Bindings/LuaChunkStay.cpp2
-rw-r--r--src/Bindings/LuaState.cpp26
-rw-r--r--src/Bindings/LuaState.h18
-rw-r--r--src/Bindings/ManualBindings.cpp70
-rw-r--r--src/Bindings/gen_LuaState_Call.lua2
-rw-r--r--src/BlockEntities/SignEntity.cpp1
-rw-r--r--src/BlockID.h2
-rw-r--r--src/BlockInfo.cpp167
-rw-r--r--src/BlockInfo.h4
-rw-r--r--src/Blocks/BlockBigFlower.h6
-rw-r--r--src/Blocks/BlockButton.h6
-rw-r--r--src/Blocks/BlockCactus.h6
-rw-r--r--src/Blocks/BlockCake.h5
-rw-r--r--src/Blocks/BlockCarpet.h6
-rw-r--r--src/Blocks/BlockChest.h6
-rw-r--r--src/Blocks/BlockCloth.h5
-rw-r--r--src/Blocks/BlockCommandBlock.h5
-rw-r--r--src/Blocks/BlockComparator.h6
-rw-r--r--src/Blocks/BlockCrops.h6
-rw-r--r--src/Blocks/BlockDirt.h6
-rw-r--r--src/Blocks/BlockDoor.cpp9
-rw-r--r--src/Blocks/BlockDoor.h1
-rw-r--r--src/Blocks/BlockEnderchest.h5
-rw-r--r--src/Blocks/BlockFenceGate.h6
-rw-r--r--src/Blocks/BlockFire.h5
-rw-r--r--src/Blocks/BlockFlower.h6
-rw-r--r--src/Blocks/BlockGravel.h10
-rw-r--r--src/Blocks/BlockHandler.cpp9
-rw-r--r--src/Blocks/BlockHandler.h3
-rw-r--r--src/Blocks/BlockHayBale.h6
-rw-r--r--src/Blocks/BlockLadder.h6
-rw-r--r--src/Blocks/BlockLeaves.h6
-rw-r--r--src/Blocks/BlockLever.h6
-rw-r--r--src/Blocks/BlockMelon.h6
-rw-r--r--src/Blocks/BlockMushroom.h6
-rw-r--r--src/Blocks/BlockMycelium.h5
-rw-r--r--src/Blocks/BlockOre.h3
-rw-r--r--src/Blocks/BlockPlanks.h6
-rw-r--r--src/Blocks/BlockRedstoneRepeater.h6
-rw-r--r--src/Blocks/BlockRedstoneTorch.h6
-rw-r--r--src/Blocks/BlockSand.h6
-rw-r--r--src/Blocks/BlockSapling.h6
-rw-r--r--src/Blocks/BlockSideways.h6
-rw-r--r--src/Blocks/BlockSignPost.h6
-rw-r--r--src/Blocks/BlockSlab.h23
-rw-r--r--src/Blocks/BlockSnow.h6
-rw-r--r--src/Blocks/BlockStairs.h18
-rw-r--r--src/Blocks/BlockStems.h6
-rw-r--r--src/Blocks/BlockSugarcane.h6
-rw-r--r--src/Blocks/BlockTNT.h5
-rw-r--r--src/Blocks/BlockTallGrass.h6
-rw-r--r--src/Blocks/BlockTorch.h6
-rw-r--r--src/Blocks/BlockTrapdoor.h5
-rw-r--r--src/Blocks/BlockTripwire.h5
-rw-r--r--src/Blocks/BlockTripwireHook.h5
-rw-r--r--src/Blocks/BlockVine.h6
-rw-r--r--src/Blocks/BlockWallSign.h6
-rw-r--r--src/Blocks/BlockWorkbench.h6
-rw-r--r--src/Blocks/WorldInterface.h4
-rw-r--r--src/BoundingBox.h11
-rw-r--r--src/BuildInfo.h.cmake15
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/Chunk.cpp90
-rw-r--r--src/Chunk.h53
-rw-r--r--src/ChunkDef.h31
-rw-r--r--src/ChunkMap.cpp355
-rw-r--r--src/ChunkMap.h27
-rw-r--r--src/ChunkSender.cpp14
-rw-r--r--src/ChunkSender.h7
-rw-r--r--src/ChunkStay.cpp2
-rw-r--r--src/ClientHandle.cpp44
-rw-r--r--src/ClientHandle.h6
-rw-r--r--src/Entities/Entity.cpp4
-rw-r--r--src/Entities/EntityEffect.cpp4
-rw-r--r--src/Entities/Player.cpp6
-rw-r--r--src/Generating/BioGen.cpp55
-rw-r--r--src/Generating/BioGen.h30
-rw-r--r--src/Generating/ChunkGenerator.cpp43
-rw-r--r--src/Generating/ChunkGenerator.h16
-rw-r--r--src/Generating/ComposableGenerator.cpp32
-rw-r--r--src/HTTPServer/HTTPServer.cpp3
-rw-r--r--src/Item.cpp80
-rw-r--r--src/Item.h6
-rw-r--r--src/Items/ItemFood.h6
-rw-r--r--src/Items/ItemHandler.cpp6
-rw-r--r--src/Items/ItemSeeds.h2
-rw-r--r--src/Mobs/Sheep.cpp7
-rw-r--r--src/Protocol/Protocol17x.cpp1
-rw-r--r--src/Protocol/Protocol17x.h14
-rw-r--r--src/Root.cpp7
-rw-r--r--src/SetChunkData.cpp1
-rw-r--r--src/StringCompression.cpp62
-rw-r--r--src/StringCompression.h2
-rw-r--r--src/UI/SlotArea.cpp189
-rw-r--r--src/UI/SlotArea.h7
-rw-r--r--src/UI/Window.cpp33
-rw-r--r--src/UI/Window.h3
-rw-r--r--src/WebAdmin.cpp150
-rw-r--r--src/WebAdmin.h12
-rw-r--r--src/World.cpp100
-rw-r--r--src/World.h31
-rw-r--r--src/WorldStorage/ScoreboardSerializer.cpp20
-rw-r--r--src/WorldStorage/WSSAnvil.cpp72
-rw-r--r--src/WorldStorage/WSSCompact.cpp6
-rw-r--r--src/WorldStorage/WorldStorage.cpp48
-rw-r--r--src/WorldStorage/WorldStorage.h45
106 files changed, 1428 insertions, 941 deletions
diff --git a/src/Bindings/LuaChunkStay.cpp b/src/Bindings/LuaChunkStay.cpp
index 59b02d8f7..154bcb200 100644
--- a/src/Bindings/LuaChunkStay.cpp
+++ b/src/Bindings/LuaChunkStay.cpp
@@ -107,7 +107,7 @@ void cLuaChunkStay::AddChunkCoord(cLuaState & L, int a_Index)
}
} // for itr - m_Chunks[]
- m_Chunks.push_back(cChunkCoords(ChunkX, ZERO_CHUNK_Y, ChunkZ));
+ m_Chunks.push_back(cChunkCoords(ChunkX, ChunkZ));
}
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index 9fe93ccc2..ba2f3c5e0 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -859,6 +859,32 @@ void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal)
+void cLuaState::GetStackValue(int a_StackPos, pBoundingBox & a_ReturnedVal)
+{
+ tolua_Error err;
+ if (tolua_isusertype(m_LuaState, a_StackPos, "cBoundingBox", false, &err))
+ {
+ a_ReturnedVal = *((cBoundingBox **)lua_touserdata(m_LuaState, a_StackPos));
+ }
+}
+
+
+
+
+
+void cLuaState::GetStackValue(int a_StackPos, pWorld & a_ReturnedVal)
+{
+ tolua_Error err;
+ if (tolua_isusertype(m_LuaState, a_StackPos, "cWorld", false, &err))
+ {
+ a_ReturnedVal = *((cWorld **)lua_touserdata(m_LuaState, a_StackPos));
+ }
+}
+
+
+
+
+
bool cLuaState::CallFunction(int a_NumResults)
{
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h
index eeb93fd4d..44f187701 100644
--- a/src/Bindings/LuaState.h
+++ b/src/Bindings/LuaState.h
@@ -59,6 +59,10 @@ class cTNTEntity;
class cCreeper;
class cHopperEntity;
class cBlockEntity;
+class cBoundingBox;
+
+typedef cBoundingBox * pBoundingBox;
+typedef cWorld * pWorld;
@@ -230,6 +234,12 @@ public:
/** Retrieve value at a_StackPos, if it is a valid number, converting and clamping it to eWeather.
If not, a_Value is unchanged. */
void GetStackValue(int a_StackPos, eWeather & a_Value);
+
+ /** Retrieve value at a_StackPos, if it is a valid cBoundingBox class. If not, a_Value is unchanged */
+ void GetStackValue(int a_StackPos, pBoundingBox & a_Value);
+
+ /** Retrieve value at a_StackPos, if it is a valid cWorld class. If not, a_Value is unchanged */
+ void GetStackValue(int a_StackPos, pWorld & a_Value);
// Include the cLuaState::Call() overload implementation that is generated by the gen_LuaState_Call.lua script:
@@ -328,6 +338,14 @@ protected:
*/
bool PushFunction(int a_FnRef);
+ /** Pushes a function that has been saved as a reference.
+ Returns true if successful. Logs a warning on failure
+ */
+ bool PushFunction(const cRef & a_FnRef)
+ {
+ return PushFunction((int)a_FnRef);
+ }
+
/** Pushes a function that is stored in a referenced table by name
Returns true if successful. Logs a warning on failure
*/
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index adf10a72f..b7ea65759 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -679,6 +679,75 @@ static int tolua_ForEachInChunk(lua_State * tolua_S)
template <
class Ty1,
class Ty2,
+ bool (Ty1::*Func1)(const cBoundingBox &, cItemCallback<Ty2> &)
+>
+static int tolua_ForEachInBox(lua_State * tolua_S)
+{
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamUserType(2, "cBoundingBox") ||
+ !L.CheckParamFunction(3) ||
+ !L.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ // Get the params:
+ Ty1 * Self = NULL;
+ cBoundingBox * Box = NULL;
+ L.GetStackValues(1, Self, Box);
+ ASSERT(Self != NULL); // We have verified the type at the top, so we should get valid objects here
+ ASSERT(Box != NULL);
+
+ // Create a reference for the function:
+ cLuaState::cRef FnRef(L, 3);
+
+ // Callback wrapper for the Lua function:
+ class cLuaCallback : public cItemCallback<Ty2>
+ {
+ public:
+ cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FuncRef) :
+ m_LuaState(a_LuaState),
+ m_FnRef(a_FuncRef)
+ {}
+
+ private:
+ // cItemCallback<Ty2> overrides:
+ virtual bool Item(Ty2 * a_Item) override
+ {
+ bool res = false;
+ if (!m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res))
+ {
+ LOGWARNING("Failed to call Lua callback");
+ m_LuaState.LogStackTrace();
+ return true; // Abort enumeration
+ }
+
+ return res;
+ }
+ cLuaState & m_LuaState;
+ cLuaState::cRef & m_FnRef;
+ } Callback(L, FnRef);
+
+ bool bRetVal = (Self->*Func1)(*Box, Callback);
+
+ FnRef.UnRef();
+
+ /* Push return value on stack */
+ tolua_pushboolean(tolua_S, bRetVal);
+ return 1;
+}
+
+
+
+
+
+template <
+ class Ty1,
+ class Ty2,
bool (Ty1::*Func1)(cItemCallback<Ty2> &)
>
static int tolua_ForEach(lua_State * tolua_S)
@@ -3327,6 +3396,7 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "ForEachBlockEntityInChunk", tolua_ForEachInChunk<cWorld, cBlockEntity, &cWorld::ForEachBlockEntityInChunk>);
tolua_function(tolua_S, "ForEachChestInChunk", tolua_ForEachInChunk<cWorld, cChestEntity, &cWorld::ForEachChestInChunk>);
tolua_function(tolua_S, "ForEachEntity", tolua_ForEach< cWorld, cEntity, &cWorld::ForEachEntity>);
+ tolua_function(tolua_S, "ForEachEntityInBox", tolua_ForEachInBox< cWorld, cEntity, &cWorld::ForEachEntityInBox>);
tolua_function(tolua_S, "ForEachEntityInChunk", tolua_ForEachInChunk<cWorld, cEntity, &cWorld::ForEachEntityInChunk>);
tolua_function(tolua_S, "ForEachFurnaceInChunk", tolua_ForEachInChunk<cWorld, cFurnaceEntity, &cWorld::ForEachFurnaceInChunk>);
tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>);
diff --git a/src/Bindings/gen_LuaState_Call.lua b/src/Bindings/gen_LuaState_Call.lua
index 2d8630d12..7f62573c7 100644
--- a/src/Bindings/gen_LuaState_Call.lua
+++ b/src/Bindings/gen_LuaState_Call.lua
@@ -109,7 +109,7 @@ local function WriteOverload(f, a_NumParams, a_NumReturns)
-- Write the function signature:
f:write("bool Call(")
- f:write("FnT a_Function")
+ f:write("const FnT & a_Function")
for i = 1, a_NumParams do
f:write(", ParamT", i, " a_Param", i)
end
diff --git a/src/BlockEntities/SignEntity.cpp b/src/BlockEntities/SignEntity.cpp
index 97fed0f04..23d9ef926 100644
--- a/src/BlockEntities/SignEntity.cpp
+++ b/src/BlockEntities/SignEntity.cpp
@@ -15,6 +15,7 @@
cSignEntity::cSignEntity(BLOCKTYPE a_BlockType, int a_X, int a_Y, int a_Z, cWorld * a_World) :
super(a_BlockType, a_X, a_Y, a_Z, a_World)
{
+ ASSERT((a_Y >= 0) && (a_Y < cChunkDef::Height));
}
diff --git a/src/BlockID.h b/src/BlockID.h
index 08c576886..d835f9518 100644
--- a/src/BlockID.h
+++ b/src/BlockID.h
@@ -362,6 +362,8 @@ enum ENUM_ITEM_ID
E_ITEM_LEAD = 420,
E_ITEM_NAME_TAG = 421,
E_ITEM_MINECART_WITH_COMMAND_BLOCK = 422,
+ E_ITEM_RAW_MUTTON = 423,
+ E_ITEM_MUTTON = 424,
// Keep these two as the last values of the consecutive list, without a number - they will get their correct number assigned automagically by C++
// IsValidItem() depends on this!
diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp
index a59229f87..9ac66d35d 100644
--- a/src/BlockInfo.cpp
+++ b/src/BlockInfo.cpp
@@ -18,6 +18,7 @@ cBlockInfo::cBlockInfo()
, m_IsSolid(true)
, m_FullyOccupiesVoxel(false)
, m_CanBeTerraformed(false)
+ , m_PlaceSound("")
, m_Handler(NULL)
{}
@@ -571,6 +572,172 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_SOULSAND ].m_CanBeTerraformed = true;
a_Info[E_BLOCK_STAINED_CLAY ].m_CanBeTerraformed = true;
a_Info[E_BLOCK_STONE ].m_CanBeTerraformed = true;
+
+
+ // Block place sounds:
+ a_Info[E_BLOCK_STONE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_GRASS ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_DIRT ].m_PlaceSound = "dig.gravel";
+ a_Info[E_BLOCK_COBBLESTONE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_PLANKS ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_SAPLING ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_BEDROCK ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_SAND ].m_PlaceSound = "dig.sand";
+ a_Info[E_BLOCK_GRAVEL ].m_PlaceSound = "dig.gravel";
+ a_Info[E_BLOCK_GOLD_ORE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_IRON_ORE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_COAL_ORE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_LOG ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_LEAVES ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_SPONGE ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_GLASS ].m_PlaceSound = "dig.glass";
+ a_Info[E_BLOCK_LAPIS_ORE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_LAPIS_BLOCK ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_DISPENSER ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_SANDSTONE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_NOTE_BLOCK ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_POWERED_RAIL ].m_PlaceSound = "dig.metal";
+ a_Info[E_BLOCK_DETECTOR_RAIL ].m_PlaceSound = "dig.metal";
+ a_Info[E_BLOCK_STICKY_PISTON ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_COBWEB ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_TALL_GRASS ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_DEAD_BUSH ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_PISTON ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_PISTON_EXTENSION ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_WOOL ].m_PlaceSound = "dig.cloth";
+ a_Info[E_BLOCK_PISTON_MOVED_BLOCK ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_DANDELION ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_FLOWER ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_BROWN_MUSHROOM ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_RED_MUSHROOM ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_GOLD_BLOCK ].m_PlaceSound = "dig.metal";
+ a_Info[E_BLOCK_IRON_BLOCK ].m_PlaceSound = "dig.metal";
+ a_Info[E_BLOCK_DOUBLE_STONE_SLAB ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_STONE_SLAB ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_BRICK ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_TNT ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_BOOKCASE ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_MOSSY_COBBLESTONE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_OBSIDIAN ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_TORCH ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_FIRE ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_MOB_SPAWNER ].m_PlaceSound = "dig.metal";
+ a_Info[E_BLOCK_WOODEN_STAIRS ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_CHEST ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_REDSTONE_WIRE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_DIAMOND_ORE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_DIAMOND_BLOCK ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_CRAFTING_TABLE ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_FARMLAND ].m_PlaceSound = "dig.gravel";
+ a_Info[E_BLOCK_FURNACE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_LIT_FURNACE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_SIGN_POST ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_WOODEN_DOOR ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_LADDER ].m_PlaceSound = "dig.ladder";
+ a_Info[E_BLOCK_RAIL ].m_PlaceSound = "dig.metal";
+ a_Info[E_BLOCK_COBBLESTONE_STAIRS ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_WALLSIGN ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_LEVER ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_STONE_PRESSURE_PLATE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_IRON_DOOR ].m_PlaceSound = "dig.metal";
+ a_Info[E_BLOCK_WOODEN_PRESSURE_PLATE ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_REDSTONE_ORE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_REDSTONE_ORE_GLOWING ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_REDSTONE_TORCH_OFF ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_REDSTONE_TORCH_ON ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_STONE_BUTTON ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_SNOW ].m_PlaceSound = "dig.snow";
+ a_Info[E_BLOCK_ICE ].m_PlaceSound = "dig.glass";
+ a_Info[E_BLOCK_SNOW_BLOCK ].m_PlaceSound = "dig.snow";
+ a_Info[E_BLOCK_CACTUS ].m_PlaceSound = "dig.cloth";
+ a_Info[E_BLOCK_CLAY ].m_PlaceSound = "dig.gravel";
+ a_Info[E_BLOCK_SUGARCANE ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_JUKEBOX ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_FENCE ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_PUMPKIN ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_NETHERRACK ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_SOULSAND ].m_PlaceSound = "dig.sand";
+ a_Info[E_BLOCK_GLOWSTONE ].m_PlaceSound = "dig.glass";
+ a_Info[E_BLOCK_NETHER_PORTAL ].m_PlaceSound = "dig.glass";
+ a_Info[E_BLOCK_JACK_O_LANTERN ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_CAKE ].m_PlaceSound = "dig.snow";
+ a_Info[E_BLOCK_REDSTONE_REPEATER_OFF ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_REDSTONE_REPEATER_ON ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_STAINED_GLASS ].m_PlaceSound = "dig.glass";
+ a_Info[E_BLOCK_TRAPDOOR ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_SILVERFISH_EGG ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_STONE_BRICKS ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_HUGE_BROWN_MUSHROOM ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_HUGE_RED_MUSHROOM ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_IRON_BARS ].m_PlaceSound = "dig.metal";
+ a_Info[E_BLOCK_GLASS_PANE ].m_PlaceSound = "dig.glass";
+ a_Info[E_BLOCK_MELON ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_PUMPKIN_STEM ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_MELON_STEM ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_VINES ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_FENCE_GATE ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_BRICK_STAIRS ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_STONE_BRICK_STAIRS ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_MYCELIUM ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_LILY_PAD ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_NETHER_BRICK ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_NETHER_BRICK_FENCE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_NETHER_BRICK_STAIRS ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_NETHER_WART ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_ENCHANTMENT_TABLE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_BREWING_STAND ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_CAULDRON ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_END_PORTAL ].m_PlaceSound = "dig.glass";
+ a_Info[E_BLOCK_END_PORTAL_FRAME ].m_PlaceSound = "dig.glass";
+ a_Info[E_BLOCK_END_STONE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_DRAGON_EGG ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_REDSTONE_LAMP_OFF ].m_PlaceSound = "dig.glass";
+ a_Info[E_BLOCK_REDSTONE_LAMP_ON ].m_PlaceSound = "dig.glass";
+ a_Info[E_BLOCK_DOUBLE_WOODEN_SLAB ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_WOODEN_SLAB ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_COCOA_POD ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_SANDSTONE_STAIRS ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_EMERALD_ORE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_ENDER_CHEST ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_TRIPWIRE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_EMERALD_BLOCK ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_SPRUCE_WOOD_STAIRS ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_BIRCH_WOOD_STAIRS ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_JUNGLE_WOOD_STAIRS ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_COMMAND_BLOCK ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_BEACON ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_COBBLESTONE_WALL ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_FLOWER_POT ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_CARROTS ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_POTATOES ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_HEAD ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_ANVIL ].m_PlaceSound = "dig.anvil";
+ a_Info[E_BLOCK_TRAPPED_CHEST ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_ACTIVE_COMPARATOR ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_DAYLIGHT_SENSOR ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_BLOCK_OF_REDSTONE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_NETHER_QUARTZ_ORE ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_HOPPER ].m_PlaceSound = "dig.metal";
+ a_Info[E_BLOCK_QUARTZ_BLOCK ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_QUARTZ_STAIRS ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_ACTIVATOR_RAIL ].m_PlaceSound = "dig.metal";
+ a_Info[E_BLOCK_DROPPER ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_STAINED_CLAY ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_STAINED_GLASS_PANE ].m_PlaceSound = "dig.glass";
+ a_Info[E_BLOCK_NEW_LEAVES ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_NEW_LOG ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_ACACIA_WOOD_STAIRS ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_DARK_OAK_WOOD_STAIRS ].m_PlaceSound = "dig.wood";
+ a_Info[E_BLOCK_HAY_BALE ].m_PlaceSound = "dig.grass";
+ a_Info[E_BLOCK_CARPET ].m_PlaceSound = "dig.cloth";
+ a_Info[E_BLOCK_HARDENED_CLAY ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_BLOCK_OF_COAL ].m_PlaceSound = "dig.stone";
+ a_Info[E_BLOCK_PACKED_ICE ].m_PlaceSound = "dig.glass";
+ a_Info[E_BLOCK_BIG_FLOWER ].m_PlaceSound = "dig.grass";
}
diff --git a/src/BlockInfo.h b/src/BlockInfo.h
index 4c66c095a..567070a7f 100644
--- a/src/BlockInfo.h
+++ b/src/BlockInfo.h
@@ -48,6 +48,9 @@ public:
/** Can a finisher change it? */
bool m_CanBeTerraformed;
+ /** Sound when placing this block */
+ AString m_PlaceSound;
+
// tolua_end
/** Associated block handler. */
@@ -64,6 +67,7 @@ public:
inline static bool IsSolid (BLOCKTYPE a_Type) { return Get(a_Type).m_IsSolid; }
inline static bool FullyOccupiesVoxel (BLOCKTYPE a_Type) { return Get(a_Type).m_FullyOccupiesVoxel; }
inline static bool CanBeTerraformed (BLOCKTYPE a_Type) { return Get(a_Type).m_CanBeTerraformed; }
+ inline static AString GetPlaceSound (BLOCKTYPE a_Type) { return Get(a_Type).m_PlaceSound; }
// tolua_end
diff --git a/src/Blocks/BlockBigFlower.h b/src/Blocks/BlockBigFlower.h
index 72e552dee..646980634 100644
--- a/src/Blocks/BlockBigFlower.h
+++ b/src/Blocks/BlockBigFlower.h
@@ -118,12 +118,6 @@ public:
}
}
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.grass";
- }
} ;
diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h
index 3b45afff8..8e4f04740 100644
--- a/src/Blocks/BlockButton.h
+++ b/src/Blocks/BlockButton.h
@@ -57,12 +57,6 @@ public:
}
- virtual const char * GetStepSound(void) override
- {
- return m_BlockType == E_BLOCK_WOODEN_BUTTON ? "step.wood" : "step.stone";
- }
-
-
inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace)
{
switch (a_BlockFace)
diff --git a/src/Blocks/BlockCactus.h b/src/Blocks/BlockCactus.h
index ed441517d..910966c43 100644
--- a/src/Blocks/BlockCactus.h
+++ b/src/Blocks/BlockCactus.h
@@ -69,12 +69,6 @@ public:
{
a_Chunk.GetWorld()->GrowCactus(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, 1);
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.cloth";
- }
} ;
diff --git a/src/Blocks/BlockCake.h b/src/Blocks/BlockCake.h
index f05f468e5..3a754ce18 100644
--- a/src/Blocks/BlockCake.h
+++ b/src/Blocks/BlockCake.h
@@ -43,11 +43,6 @@ public:
{
return true;
}
-
- virtual const char * GetStepSound(void) override
- {
- return "step.cloth";
- }
} ;
diff --git a/src/Blocks/BlockCarpet.h b/src/Blocks/BlockCarpet.h
index d1aa52687..4b287c664 100644
--- a/src/Blocks/BlockCarpet.h
+++ b/src/Blocks/BlockCarpet.h
@@ -22,12 +22,6 @@ public:
cBlockHandler(a_BlockType)
{
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.cloth";
- }
virtual bool GetPlacementBlockTypeMeta(
diff --git a/src/Blocks/BlockChest.h b/src/Blocks/BlockChest.h
index 28adbed4f..201f2309b 100644
--- a/src/Blocks/BlockChest.h
+++ b/src/Blocks/BlockChest.h
@@ -106,12 +106,6 @@ public:
// Single chest, no further processing needed
}
-
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
-
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
diff --git a/src/Blocks/BlockCloth.h b/src/Blocks/BlockCloth.h
index 3c1ae7c25..525176725 100644
--- a/src/Blocks/BlockCloth.h
+++ b/src/Blocks/BlockCloth.h
@@ -15,11 +15,6 @@ public:
: cBlockHandler(a_BlockType)
{
}
-
- virtual const char * GetStepSound(void) override
- {
- return "step.cloth";
- }
} ;
diff --git a/src/Blocks/BlockCommandBlock.h b/src/Blocks/BlockCommandBlock.h
index cf0103765..b66def201 100644
--- a/src/Blocks/BlockCommandBlock.h
+++ b/src/Blocks/BlockCommandBlock.h
@@ -20,11 +20,6 @@ public:
{
a_Pickups.push_back(cItem(E_BLOCK_AIR, 8, 0));
}
-
- virtual const char * GetStepSound(void) override
- {
- return "step.stone";
- }
} ;
diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h
index 6caaaab13..3443fc69e 100644
--- a/src/Blocks/BlockComparator.h
+++ b/src/Blocks/BlockComparator.h
@@ -64,12 +64,6 @@ public:
a_BlockMeta = cBlockRedstoneRepeaterHandler::RepeaterRotationToMetaData(a_Player->GetYaw());
return true;
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
} ;
diff --git a/src/Blocks/BlockCrops.h b/src/Blocks/BlockCrops.h
index ae6e490e1..53e996683 100644
--- a/src/Blocks/BlockCrops.h
+++ b/src/Blocks/BlockCrops.h
@@ -100,12 +100,6 @@ public:
{
return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) == E_BLOCK_FARMLAND));
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.grass";
- }
} ;
diff --git a/src/Blocks/BlockDirt.h b/src/Blocks/BlockDirt.h
index d458c6062..23e5a3cde 100644
--- a/src/Blocks/BlockDirt.h
+++ b/src/Blocks/BlockDirt.h
@@ -88,12 +88,6 @@ public:
}
} // for i - repeat twice
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.gravel";
- }
} ;
diff --git a/src/Blocks/BlockDoor.cpp b/src/Blocks/BlockDoor.cpp
index e80473cb5..1204debab 100644
--- a/src/Blocks/BlockDoor.cpp
+++ b/src/Blocks/BlockDoor.cpp
@@ -109,15 +109,6 @@ void cBlockDoorHandler::OnPlacedByPlayer(
-const char * cBlockDoorHandler::GetStepSound(void)
-{
- return (m_BlockType == E_BLOCK_WOODEN_DOOR) ? "step.wood" : "step.stone";
-}
-
-
-
-
-
NIBBLETYPE cBlockDoorHandler::MetaRotateCCW(NIBBLETYPE a_Meta)
{
if (a_Meta & 0x08)
diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h
index c86fe829b..69e30d9c8 100644
--- a/src/Blocks/BlockDoor.h
+++ b/src/Blocks/BlockDoor.h
@@ -19,7 +19,6 @@ public:
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override;
- virtual const char * GetStepSound(void) override;
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override;
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override;
diff --git a/src/Blocks/BlockEnderchest.h b/src/Blocks/BlockEnderchest.h
index 4672f1459..0bc67a8f5 100644
--- a/src/Blocks/BlockEnderchest.h
+++ b/src/Blocks/BlockEnderchest.h
@@ -33,11 +33,6 @@ public:
a_BlockMeta = RotationToMetaData(a_Player->GetYaw());
return true;
}
-
- virtual const char * GetStepSound(void) override
- {
- return "step.stone";
- }
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{
diff --git a/src/Blocks/BlockFenceGate.h b/src/Blocks/BlockFenceGate.h
index ae99a4f94..3041dd46c 100644
--- a/src/Blocks/BlockFenceGate.h
+++ b/src/Blocks/BlockFenceGate.h
@@ -17,6 +17,12 @@ public:
}
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ a_Pickups.Add(E_BLOCK_FENCE_GATE, 1, 0); // Reset meta to zero
+ }
+
+
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
diff --git a/src/Blocks/BlockFire.h b/src/Blocks/BlockFire.h
index b9f211042..b6d1d95f2 100644
--- a/src/Blocks/BlockFire.h
+++ b/src/Blocks/BlockFire.h
@@ -50,11 +50,6 @@ public:
return true;
}
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
-
/** Traces along YP until it finds an obsidian block, returns Y difference or 0 if no portal, and -1 for border
Takes the X, Y, and Z of the base block; with an optional MaxY for portal border finding */
int FindObsidianCeiling(int X, int Y, int Z, cChunkInterface & a_ChunkInterface, int MaxY = 0)
diff --git a/src/Blocks/BlockFlower.h b/src/Blocks/BlockFlower.h
index 6f64c062b..3eb8a0baa 100644
--- a/src/Blocks/BlockFlower.h
+++ b/src/Blocks/BlockFlower.h
@@ -28,12 +28,6 @@ public:
{
return (a_RelY > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ));
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.grass";
- }
} ;
diff --git a/src/Blocks/BlockGravel.h b/src/Blocks/BlockGravel.h
index e1c9ff390..3a9fbd170 100644
--- a/src/Blocks/BlockGravel.h
+++ b/src/Blocks/BlockGravel.h
@@ -16,9 +16,15 @@ public:
{
}
- virtual const char * GetStepSound(void) override
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- return "step.gravel";
+ a_Pickups.Add(E_BLOCK_GRAVEL, 1, 0);
+
+ cFastRandom Random;
+ if (Random.NextInt(30) == 0)
+ {
+ a_Pickups.Add(E_ITEM_FLINT, 1, 0);
+ }
}
} ;
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index 6767d4de4..34925a252 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -495,15 +495,6 @@ void cBlockHandler::DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterfac
-const char * cBlockHandler::GetStepSound()
-{
- return "step.stone";
-}
-
-
-
-
-
bool cBlockHandler::CanBeAt(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, const cChunk & a_Chunk)
{
return true;
diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h
index de90ce55b..b3ada279c 100644
--- a/src/Blocks/BlockHandler.h
+++ b/src/Blocks/BlockHandler.h
@@ -84,9 +84,6 @@ public:
*/
virtual void DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, bool a_CanDrop = true, bool a_DropVerbatim = false);
- /// Returns step sound name of block
- virtual const char * GetStepSound(void);
-
/// Checks if the block can stay at the specified relative coords in the chunk
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk);
diff --git a/src/Blocks/BlockHayBale.h b/src/Blocks/BlockHayBale.h
index 3c6472adb..8150b10d3 100644
--- a/src/Blocks/BlockHayBale.h
+++ b/src/Blocks/BlockHayBale.h
@@ -15,12 +15,6 @@ public:
: cBlockSidewaysHandler(a_BlockType)
{
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.grass";
- }
} ;
diff --git a/src/Blocks/BlockLadder.h b/src/Blocks/BlockLadder.h
index 284d1d732..ab3f55439 100644
--- a/src/Blocks/BlockLadder.h
+++ b/src/Blocks/BlockLadder.h
@@ -111,12 +111,6 @@ public:
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
return LadderCanBePlacedAt(a_ChunkInterface, BlockX, a_RelY, BlockZ, BlockFace);
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
} ;
diff --git a/src/Blocks/BlockLeaves.h b/src/Blocks/BlockLeaves.h
index a8aa28a0f..add571675 100644
--- a/src/Blocks/BlockLeaves.h
+++ b/src/Blocks/BlockLeaves.h
@@ -112,12 +112,6 @@ public:
DropBlock(a_ChunkInterface, a_WorldInterface, a_PluginInterface, NULL, BlockX, a_RelY, BlockZ);
a_ChunkInterface.DigBlock(a_WorldInterface, BlockX, a_RelY, BlockZ);
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.grass";
- }
} ;
diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h
index 4316fd06b..3b63b396c 100644
--- a/src/Blocks/BlockLever.h
+++ b/src/Blocks/BlockLever.h
@@ -70,12 +70,6 @@ public:
}
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
-
-
inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta)
{
switch (a_Meta & 0x7)
diff --git a/src/Blocks/BlockMelon.h b/src/Blocks/BlockMelon.h
index 60202d66e..22cdb4d29 100644
--- a/src/Blocks/BlockMelon.h
+++ b/src/Blocks/BlockMelon.h
@@ -22,12 +22,6 @@ public:
cFastRandom Random;
a_Pickups.push_back(cItem(E_ITEM_MELON_SLICE, (char)(3 + Random.NextInt(5)), 0));
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
} ;
diff --git a/src/Blocks/BlockMushroom.h b/src/Blocks/BlockMushroom.h
index 135d418d7..7c06fcc74 100644
--- a/src/Blocks/BlockMushroom.h
+++ b/src/Blocks/BlockMushroom.h
@@ -50,12 +50,6 @@ public:
}
return true;
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.grass";
- }
} ;
diff --git a/src/Blocks/BlockMycelium.h b/src/Blocks/BlockMycelium.h
index 2a8ef5fca..628e87181 100644
--- a/src/Blocks/BlockMycelium.h
+++ b/src/Blocks/BlockMycelium.h
@@ -22,11 +22,6 @@ public:
{
a_Pickups.push_back(cItem(E_BLOCK_DIRT, 1, 0));
}
-
- virtual const char * GetStepSound(void) override
- {
- return "step.gravel";
- }
} ;
diff --git a/src/Blocks/BlockOre.h b/src/Blocks/BlockOre.h
index 0067d475f..f6ea3aa3c 100644
--- a/src/Blocks/BlockOre.h
+++ b/src/Blocks/BlockOre.h
@@ -51,7 +51,8 @@ public:
}
default:
{
- ASSERT(!"Unhandled ore!");
+ a_Pickups.push_back(cItem(m_BlockType));
+ break;
}
}
}
diff --git a/src/Blocks/BlockPlanks.h b/src/Blocks/BlockPlanks.h
index 4c5bb4860..3c243ebdc 100644
--- a/src/Blocks/BlockPlanks.h
+++ b/src/Blocks/BlockPlanks.h
@@ -27,12 +27,6 @@ public:
a_BlockMeta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage);
return true;
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
} ;
diff --git a/src/Blocks/BlockRedstoneRepeater.h b/src/Blocks/BlockRedstoneRepeater.h
index 4b18add12..3e5259c56 100644
--- a/src/Blocks/BlockRedstoneRepeater.h
+++ b/src/Blocks/BlockRedstoneRepeater.h
@@ -63,12 +63,6 @@ public:
}
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
-
-
inline static NIBBLETYPE RepeaterRotationToMetaData(double a_Rotation)
{
a_Rotation += 90 + 45; // So its not aligned with axis
diff --git a/src/Blocks/BlockRedstoneTorch.h b/src/Blocks/BlockRedstoneTorch.h
index cb897ba3f..8416a415c 100644
--- a/src/Blocks/BlockRedstoneTorch.h
+++ b/src/Blocks/BlockRedstoneTorch.h
@@ -23,12 +23,6 @@ public:
// Always drop the ON torch, meta 0
a_Pickups.push_back(cItem(E_BLOCK_REDSTONE_TORCH_ON, 1, 0));
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
} ;
diff --git a/src/Blocks/BlockSand.h b/src/Blocks/BlockSand.h
index 3fc271483..48beab138 100644
--- a/src/Blocks/BlockSand.h
+++ b/src/Blocks/BlockSand.h
@@ -15,12 +15,6 @@ public:
: cBlockHandler(a_BlockType)
{
}
-
- virtual const char * GetStepSound(void) override
- {
- return "step.sand";
- }
-
};
diff --git a/src/Blocks/BlockSapling.h b/src/Blocks/BlockSapling.h
index de28273d5..bec79c6f3 100644
--- a/src/Blocks/BlockSapling.h
+++ b/src/Blocks/BlockSapling.h
@@ -46,12 +46,6 @@ public:
a_Chunk.SetMeta(a_RelX, a_RelY, a_RelZ, Meta | 0x08);
}
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.grass";
- }
} ;
diff --git a/src/Blocks/BlockSideways.h b/src/Blocks/BlockSideways.h
index f5f10899d..4b1e38d6d 100644
--- a/src/Blocks/BlockSideways.h
+++ b/src/Blocks/BlockSideways.h
@@ -65,12 +65,6 @@ public:
}
}
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
} ;
diff --git a/src/Blocks/BlockSignPost.h b/src/Blocks/BlockSignPost.h
index d0cc760b0..40e15c253 100644
--- a/src/Blocks/BlockSignPost.h
+++ b/src/Blocks/BlockSignPost.h
@@ -27,12 +27,6 @@ public:
}
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
-
-
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
if (a_RelY <= 0)
diff --git a/src/Blocks/BlockSlab.h b/src/Blocks/BlockSlab.h
index e67f0e8b3..0ad30bb2b 100644
--- a/src/Blocks/BlockSlab.h
+++ b/src/Blocks/BlockSlab.h
@@ -85,18 +85,6 @@ public:
return true;
}
-
-
- virtual const char * GetStepSound(void) override
- {
- switch (m_BlockType)
- {
- case E_BLOCK_WOODEN_SLAB: return "step.wood";
- case E_BLOCK_STONE_SLAB: return "step.stone";
- }
- ASSERT(!"Unhandled slab type!");
- return "";
- }
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
@@ -174,17 +162,6 @@ public:
ASSERT(!"Unhandled double slab type!");
return a_BlockType;
}
-
- virtual const char * GetStepSound(void) override
- {
- switch (m_BlockType)
- {
- case E_BLOCK_DOUBLE_STONE_SLAB: return "step.stone";
- case E_BLOCK_DOUBLE_WOODEN_SLAB: return "step.wood";
- }
- ASSERT(!"Unhandled double slab type!");
- return "";
- }
} ;
diff --git a/src/Blocks/BlockSnow.h b/src/Blocks/BlockSnow.h
index 977f19a16..7b6094c9f 100644
--- a/src/Blocks/BlockSnow.h
+++ b/src/Blocks/BlockSnow.h
@@ -87,12 +87,6 @@ public:
{
return false;
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.cloth";
- }
} ;
diff --git a/src/Blocks/BlockStairs.h b/src/Blocks/BlockStairs.h
index 417969a82..d396204e0 100644
--- a/src/Blocks/BlockStairs.h
+++ b/src/Blocks/BlockStairs.h
@@ -55,24 +55,6 @@ public:
}
- virtual const char * GetStepSound(void) override
- {
- if (
- (m_BlockType == E_BLOCK_WOODEN_STAIRS) ||
- (m_BlockType == E_BLOCK_SPRUCE_WOOD_STAIRS) ||
- (m_BlockType == E_BLOCK_JUNGLE_WOOD_STAIRS) ||
- (m_BlockType == E_BLOCK_ACACIA_WOOD_STAIRS) ||
- (m_BlockType == E_BLOCK_BIRCH_WOOD_STAIRS) ||
- (m_BlockType == E_BLOCK_DARK_OAK_WOOD_STAIRS)
- )
- {
- return "step.wood";
- }
-
- return "step.stone";
- }
-
-
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to zero
diff --git a/src/Blocks/BlockStems.h b/src/Blocks/BlockStems.h
index b726a0901..860c7dd45 100644
--- a/src/Blocks/BlockStems.h
+++ b/src/Blocks/BlockStems.h
@@ -47,12 +47,6 @@ public:
{
return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) == E_BLOCK_FARMLAND));
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
} ;
diff --git a/src/Blocks/BlockSugarcane.h b/src/Blocks/BlockSugarcane.h
index 5902c791b..c832ff218 100644
--- a/src/Blocks/BlockSugarcane.h
+++ b/src/Blocks/BlockSugarcane.h
@@ -78,12 +78,6 @@ public:
{
a_Chunk.GetWorld()->GrowSugarcane(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, 1);
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.grass";
- }
} ;
diff --git a/src/Blocks/BlockTNT.h b/src/Blocks/BlockTNT.h
index 283a03730..3a573ae67 100644
--- a/src/Blocks/BlockTNT.h
+++ b/src/Blocks/BlockTNT.h
@@ -16,11 +16,6 @@ public:
{
}
- virtual const char * GetStepSound(void) override
- {
- return "step.grass";
- }
-
virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
{
a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
diff --git a/src/Blocks/BlockTallGrass.h b/src/Blocks/BlockTallGrass.h
index 9c008f793..f520414a7 100644
--- a/src/Blocks/BlockTallGrass.h
+++ b/src/Blocks/BlockTallGrass.h
@@ -53,12 +53,6 @@ public:
{
return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) != E_BLOCK_AIR));
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.grass";
- }
} ;
diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h
index df5574d5d..fa46b37a8 100644
--- a/src/Blocks/BlockTorch.h
+++ b/src/Blocks/BlockTorch.h
@@ -184,12 +184,6 @@ public:
// Always drop meta = 0
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
} ;
diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h
index a6327b5c2..41256ae55 100644
--- a/src/Blocks/BlockTrapdoor.h
+++ b/src/Blocks/BlockTrapdoor.h
@@ -16,11 +16,6 @@ public:
{
}
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
-
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to zero
diff --git a/src/Blocks/BlockTripwire.h b/src/Blocks/BlockTripwire.h
index 3ab17bf4a..d03f37537 100644
--- a/src/Blocks/BlockTripwire.h
+++ b/src/Blocks/BlockTripwire.h
@@ -20,11 +20,6 @@ public:
{
a_Pickups.push_back(cItem(E_ITEM_STRING, 1, 0));
}
-
- virtual const char * GetStepSound(void) override
- {
- return "";
- }
};
diff --git a/src/Blocks/BlockTripwireHook.h b/src/Blocks/BlockTripwireHook.h
index 4f9d79483..88d389711 100644
--- a/src/Blocks/BlockTripwireHook.h
+++ b/src/Blocks/BlockTripwireHook.h
@@ -70,11 +70,6 @@ public:
return ((a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(BlockIsOn));
}
-
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
};
diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h
index 578224c61..b61673cc5 100644
--- a/src/Blocks/BlockVine.h
+++ b/src/Blocks/BlockVine.h
@@ -159,12 +159,6 @@ public:
{
return true;
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.grass";
- }
virtual bool DoesDropOnUnsuitable(void) override
diff --git a/src/Blocks/BlockWallSign.h b/src/Blocks/BlockWallSign.h
index 47649379e..0abe9c52c 100644
--- a/src/Blocks/BlockWallSign.h
+++ b/src/Blocks/BlockWallSign.h
@@ -27,12 +27,6 @@ public:
}
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
-
-
virtual void OnPlacedByPlayer(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
diff --git a/src/Blocks/BlockWorkbench.h b/src/Blocks/BlockWorkbench.h
index 70468369c..699badaf2 100644
--- a/src/Blocks/BlockWorkbench.h
+++ b/src/Blocks/BlockWorkbench.h
@@ -30,12 +30,6 @@ public:
{
return true;
}
-
-
- virtual const char * GetStepSound(void) override
- {
- return "step.wood";
- }
} ;
diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h
index d1c6f9bfc..b43d011d8 100644
--- a/src/Blocks/WorldInterface.h
+++ b/src/Blocks/WorldInterface.h
@@ -17,7 +17,7 @@ class cWorldInterface
public:
virtual ~cWorldInterface() {}
- virtual Int64 GetTimeOfDay(void) const = 0;
+ virtual int GetTimeOfDay(void) const = 0;
virtual Int64 GetWorldAge(void) const = 0;
virtual eDimension GetDimension(void) const = 0;
@@ -44,7 +44,7 @@ public:
/** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */
virtual bool ForEachPlayer(cItemCallback<cPlayer> & a_Callback) = 0;
- virtual void SetTimeOfDay(Int64 a_TimeOfDay) = 0;
+ virtual void SetTimeOfDay(int a_TimeOfDay) = 0;
/** Returns true if it is raining, stormy or snowing at the specified location. This takes into account biomes. */
virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) = 0;
diff --git a/src/BoundingBox.h b/src/BoundingBox.h
index 793466302..928e62afa 100644
--- a/src/BoundingBox.h
+++ b/src/BoundingBox.h
@@ -80,6 +80,17 @@ public:
/// Calculates the intersection of the two bounding boxes; returns true if nonempty
bool Intersect(const cBoundingBox & a_Other, cBoundingBox & a_Intersection);
+ double GetMinX(void) const { return m_Min.x; }
+ double GetMinY(void) const { return m_Min.y; }
+ double GetMinZ(void) const { return m_Min.z; }
+
+ double GetMaxX(void) const { return m_Max.x; }
+ double GetMaxY(void) const { return m_Max.y; }
+ double GetMaxZ(void) const { return m_Max.z; }
+
+ const Vector3d & GetMin(void) const { return m_Min; }
+ const Vector3d & GetMax(void) const { return m_Max; }
+
protected:
Vector3d m_Min;
Vector3d m_Max;
diff --git a/src/BuildInfo.h.cmake b/src/BuildInfo.h.cmake
new file mode 100644
index 000000000..6337dab3e
--- /dev/null
+++ b/src/BuildInfo.h.cmake
@@ -0,0 +1,15 @@
+
+#pragma once
+
+#cmakedefine BUILD_ID
+
+#ifdef BUILD_ID
+
+#undef BUILD_ID
+
+#define BUILD_SERIES_NAME "@BUILD_SERIES_NAME@"
+#define BUILD_ID "@BUILD_ID@"
+#define BUILD_COMMIT_ID "@BUILD_COMMIT_ID@"
+#define BUILD_DATETIME "@BUILD_DATETIME@"
+#endif
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2d96662a9..9d0e2cede 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -75,6 +75,7 @@ SET (HDRS
BlockInfo.h
BlockTracer.h
BoundingBox.h
+ BuildInfo.h.cmake
ByteBuffer.h
ChatColor.h
Chunk.h
@@ -140,6 +141,8 @@ include_directories(".")
include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/../lib/sqlite")
include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/../lib/SQLiteCpp/include")
+configure_file("BuildInfo.h.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/BuildInfo.h")
+
if (NOT MSVC)
# Bindings need to reference other folders, so they are done here instead
# lib dependencies are not included
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 40ffff834..e75acb03b 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -37,6 +37,7 @@
#include "MobSpawner.h"
#include "BlockInServerPluginInterface.h"
#include "SetChunkData.h"
+#include "BoundingBox.h"
#include "json/json.h"
@@ -65,19 +66,18 @@ sSetBlock::sSetBlock( int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_Bloc
// cChunk:
cChunk::cChunk(
- int a_ChunkX, int a_ChunkY, int a_ChunkZ,
+ int a_ChunkX, int a_ChunkZ,
cChunkMap * a_ChunkMap, cWorld * a_World,
cChunk * a_NeighborXM, cChunk * a_NeighborXP, cChunk * a_NeighborZM, cChunk * a_NeighborZP,
cAllocationPool<cChunkData::sChunkSection> & a_Pool
) :
- m_IsValid(false),
+ m_Presence(cpInvalid),
m_IsLightValid(false),
m_IsDirty(false),
m_IsSaving(false),
m_HasLoadFailed(false),
m_StayCount(0),
m_PosX(a_ChunkX),
- m_PosY(a_ChunkY),
m_PosZ(a_ChunkZ),
m_World(a_World),
m_ChunkMap(a_ChunkMap),
@@ -165,11 +165,22 @@ cChunk::~cChunk()
-void cChunk::SetValid(void)
+void cChunk::SetPresence(cChunk::ePresence a_Presence)
{
- m_IsValid = true;
-
- m_World->GetChunkMap()->ChunkValidated();
+ m_Presence = a_Presence;
+ if (a_Presence == cpPresent)
+ {
+ m_World->GetChunkMap()->ChunkValidated();
+ }
+}
+
+
+
+
+
+void cChunk::SetShouldGenerateIfLoadFailed(bool a_ShouldGenerateIfLoadFailed)
+{
+ m_ShouldGenerateIfLoadFailed = a_ShouldGenerateIfLoadFailed;
}
@@ -178,6 +189,9 @@ void cChunk::SetValid(void)
void cChunk::MarkRegenerating(void)
{
+ // Set as queued again:
+ SetPresence(cpQueued);
+
// Tell all clients attached to this chunk that they want this chunk:
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
@@ -191,7 +205,11 @@ void cChunk::MarkRegenerating(void)
bool cChunk::CanUnload(void)
{
- return m_LoadedByClient.empty() && !m_IsDirty && (m_StayCount == 0);
+ return
+ m_LoadedByClient.empty() && // The chunk is not used by any client
+ !m_IsDirty && // The chunk has been saved properly or hasn't been touched since the load / gen
+ (m_StayCount == 0) && // The chunk is not in a ChunkStay
+ (m_Presence != cpQueued) ; // The chunk is not queued for loading / generating (otherwise multi-load / multi-gen could occur)
}
@@ -223,7 +241,7 @@ void cChunk::MarkSaved(void)
void cChunk::MarkLoaded(void)
{
m_IsDirty = false;
- SetValid();
+ SetPresence(cpPresent);
}
@@ -232,12 +250,17 @@ void cChunk::MarkLoaded(void)
void cChunk::MarkLoadFailed(void)
{
- if (m_IsValid)
+ ASSERT(m_Presence == cpQueued);
+
+ // If the chunk is marked as needed, generate it:
+ if (m_ShouldGenerateIfLoadFailed)
{
- return;
+ m_World->GetGenerator().QueueGenerateChunk(m_PosX, m_PosZ, false);
+ }
+ else
+ {
+ m_Presence = cpInvalid;
}
-
- m_HasLoadFailed = true;
}
@@ -246,6 +269,8 @@ void cChunk::MarkLoadFailed(void)
void cChunk::GetAllData(cChunkDataCallback & a_Callback)
{
+ ASSERT(m_Presence == cpPresent);
+
a_Callback.HeightMap(&m_HeightMap);
a_Callback.BiomeData(&m_BiomeMap);
@@ -272,6 +297,7 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
{
ASSERT(a_SetChunkData.IsHeightMapValid());
ASSERT(a_SetChunkData.AreBiomesValid());
+ ASSERT(IsQueued());
memcpy(m_BiomeMap, a_SetChunkData.GetBiomes(), sizeof(m_BiomeMap));
memcpy(m_HeightMap, a_SetChunkData.GetHeightMap(), sizeof(m_HeightMap));
@@ -317,7 +343,7 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
CreateBlockEntities();
// Set the chunk data as valid. This may be needed for some simulators that perform actions upon block adding (Vaporize)
- SetValid();
+ SetPresence(cpPresent);
// Wake up all simulators for their respective blocks:
WakeUpSimulators();
@@ -653,7 +679,7 @@ void cChunk::MoveEntityToNewChunk(cEntity * a_Entity)
cChunk * Neighbor = GetNeighborChunk(a_Entity->GetChunkX() * cChunkDef::Width, a_Entity->GetChunkZ() * cChunkDef::Width);
if (Neighbor == NULL)
{
- Neighbor = m_ChunkMap->GetChunkNoLoad(a_Entity->GetChunkX(), ZERO_CHUNK_Y, a_Entity->GetChunkZ());
+ Neighbor = m_ChunkMap->GetChunkNoLoad(a_Entity->GetChunkX(), a_Entity->GetChunkZ());
if (Neighbor == NULL)
{
// TODO: What to do with this?
@@ -1319,11 +1345,11 @@ void cChunk::CreateBlockEntities(void)
case E_BLOCK_JUKEBOX:
case E_BLOCK_FLOWER_POT:
{
- if (!HasBlockEntityAt(x + m_PosX * Width, y + m_PosY * Height, z + m_PosZ * Width))
+ if (!HasBlockEntityAt(x + m_PosX * Width, y, z + m_PosZ * Width))
{
m_BlockEntities.push_back(cBlockEntity::CreateByBlockType(
BlockType, GetMeta(x, y, z),
- x + m_PosX * Width, y + m_PosY * Height, z + m_PosZ * Width, m_World
+ x + m_PosX * Width, y, z + m_PosZ * Width, m_World
));
}
break;
@@ -1960,6 +1986,30 @@ bool cChunk::ForEachEntity(cEntityCallback & a_Callback)
+bool cChunk::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback)
+{
+ // The entity list is locked by the parent chunkmap's CS
+ for (cEntityList::iterator itr = m_Entities.begin(), itr2 = itr; itr != m_Entities.end(); itr = itr2)
+ {
+ ++itr2;
+ cBoundingBox EntBox((*itr)->GetPosition(), (*itr)->GetWidth() / 2, (*itr)->GetHeight());
+ if (!EntBox.DoesIntersect(a_Box))
+ {
+ // The entity is not in the specified box
+ continue;
+ }
+ if (a_Callback.Item(*itr))
+ {
+ return false;
+ }
+ } // for itr - m_Entitites[]
+ return true;
+}
+
+
+
+
+
bool cChunk::DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult)
{
// The entity list is locked by the parent chunkmap's CS
@@ -2165,7 +2215,7 @@ bool cChunk::DoWithRedstonePoweredEntityAt(int a_BlockX, int a_BlockY, int a_Blo
}
}
- if (a_Callback.Item((cRedstonePoweredEntity *)*itr))
+ if (a_Callback.Item(dynamic_cast<cRedstonePoweredEntity *>(*itr))) // Needs dynamic_cast due to multiple inheritance
{
return false;
}
@@ -2603,7 +2653,7 @@ cChunk * cChunk::GetRelNeighborChunk(int a_RelX, int a_RelZ)
int BlockZ = m_PosZ * cChunkDef::Width + a_RelZ;
int ChunkX, ChunkZ;
BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
- return m_ChunkMap->GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ return m_ChunkMap->GetChunkNoLoad(ChunkX, ChunkZ);
}
// Walk the neighbors:
@@ -3128,7 +3178,7 @@ void cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ, int & a
Vector3i cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ)
{
- return Vector3i(m_PosX * Width + a_RelX, m_PosY * Height + a_RelY, m_PosZ * Width + a_RelZ);
+ return Vector3i(m_PosX * Width + a_RelX, a_RelY, m_PosZ * Width + a_RelZ);
}
diff --git a/src/Chunk.h b/src/Chunk.h
index e5de22e3b..f282694c2 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -66,8 +66,16 @@ class cChunk :
public cChunkDef // The inheritance is "misused" here only to inherit the functions and constants defined in cChunkDef
{
public:
+ /** Represents the presence state of the chunk */
+ enum ePresence
+ {
+ cpInvalid, /**< The chunk is not present at all and is not queued in the loader / generator */
+ cpQueued, /**< The chunk is not present, but is queued for loading / generation */
+ cpPresent, /**< The chunk is present */
+ };
+
cChunk(
- int a_ChunkX, int a_ChunkY, int a_ChunkZ, // Chunk coords
+ int a_ChunkX, int a_ChunkZ, // Chunk coords
cChunkMap * a_ChunkMap, cWorld * a_World, // Parent objects
cChunk * a_NeighborXM, cChunk * a_NeighborXP, cChunk * a_NeighborZM, cChunk * a_NeighborZP, // Neighbor chunks
cAllocationPool<cChunkData::sChunkSection> & a_Pool
@@ -75,11 +83,25 @@ public:
cChunk(cChunk & other);
~cChunk();
- bool IsValid(void) const {return m_IsValid; } // Returns true if the chunk block data is valid (loaded / generated)
- void SetValid(void); // Also wakes up any calls to cChunkMap::GetHeight()
- void MarkRegenerating(void); // Marks all clients attached to this chunk as wanting this chunk
- bool IsDirty(void) const {return m_IsDirty; } // Returns true if the chunk has changed since it was last saved
- bool HasLoadFailed(void) const {return m_HasLoadFailed; } // Returns true if the chunk failed to load and hasn't been generated since then
+ /** Returns true iff the chunk block data is valid (loaded / generated) */
+ bool IsValid(void) const {return (m_Presence == cpPresent); }
+
+ /** Returns true iff the chunk is in the queue for loading / generating */
+ bool IsQueued(void) const {return (m_Presence == cpQueued); }
+
+ /** Sets the chunk's presence.
+ Wakes up any calls to cChunkMap::GetHeight() when setting to cpPresent. */
+ void SetPresence(ePresence a_Presence);
+
+ /** Called to indicate whether the chunk should be queued in the generator if it fails to load. Set by cChunkMap::GetChunk(). */
+ void SetShouldGenerateIfLoadFailed(bool a_ShouldGenerateIfLoadFailed);
+
+ /** Marks all clients attached to this chunk as wanting this chunk. Also sets presence to cpQueued. */
+ void MarkRegenerating(void);
+
+ /** Returns true iff the chunk has changed since it was last saved. */
+ bool IsDirty(void) const {return m_IsDirty; }
+
bool CanUnload(void);
bool IsLightValid(void) const {return m_IsLightValid; }
@@ -94,7 +116,10 @@ public:
void MarkSaving(void); // Marks the chunk as being saved.
void MarkSaved(void); // Marks the chunk as saved, if it didn't change from the last call to MarkSaving()
void MarkLoaded(void); // Marks the chunk as freshly loaded. Fails if the chunk is already valid
- void MarkLoadFailed(void); // Marks the chunk as failed to load. Ignored is the chunk is already valid
+
+ /** Marks the chunk as failed to load.
+ If m_ShouldGenerateIfLoadFailed is set, queues the chunk for generating. */
+ void MarkLoadFailed(void);
/** Gets all chunk data, calls the a_Callback's methods for each data type */
void GetAllData(cChunkDataCallback & a_Callback);
@@ -135,7 +160,6 @@ public:
void TickBlock(int a_RelX, int a_RelY, int a_RelZ);
int GetPosX(void) const { return m_PosX; }
- int GetPosY(void) const { return m_PosY; }
int GetPosZ(void) const { return m_PosZ; }
cWorld * GetWorld(void) const { return m_World; }
@@ -216,6 +240,10 @@ public:
/** Calls the callback for each entity; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
+ /** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox.
+ Returns true if all entities processed, false if the callback aborted by returning true. */
+ bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback); // Lua-accessible
+
/** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found. */
bool DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult); // Lua-accessible
@@ -430,7 +458,12 @@ private:
typedef std::vector<sSetBlockQueueItem> sSetBlockQueueVector;
- bool m_IsValid; // True if the chunk is loaded / generated
+ /** Holds the presence status of the chunk - if it is present, or in the loader / generator queue, or unloaded */
+ ePresence m_Presence;
+
+ /** If the chunk fails to load, should it be queued in the generator or reset back to invalid? */
+ bool m_ShouldGenerateIfLoadFailed;
+
bool m_IsLightValid; // True if the blocklight and skylight are calculated
bool m_IsDirty; // True if the chunk has changed since it was last saved
bool m_IsSaving; // True if the chunk is being saved
@@ -449,7 +482,7 @@ private:
/** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
int m_StayCount;
- int m_PosX, m_PosY, m_PosZ;
+ int m_PosX, m_PosZ;
cWorld * m_World;
cChunkMap * m_ChunkMap;
diff --git a/src/ChunkDef.h b/src/ChunkDef.h
index b8b4291c7..f4ed66c4b 100644
--- a/src/ChunkDef.h
+++ b/src/ChunkDef.h
@@ -16,11 +16,6 @@
-/** This is really only a placeholder to be used in places where we need to "make up" a chunk's Y coord.
-It will help us when the new chunk format comes out and we need to patch everything up for compatibility.
-*/
-#define ZERO_CHUNK_Y 0
-
// Used to smoothly convert to new axis ordering. One will be removed when deemed stable.
#define AXIS_ORDER_YZX 1 // Original (1.1-)
#define AXIS_ORDER_XZY 2 // New (1.2+)
@@ -377,14 +372,13 @@ class cChunkCoords
{
public:
int m_ChunkX;
- int m_ChunkY;
int m_ChunkZ;
- cChunkCoords(int a_ChunkX, int a_ChunkY, int a_ChunkZ) : m_ChunkX(a_ChunkX), m_ChunkY(a_ChunkY), m_ChunkZ(a_ChunkZ) {}
+ cChunkCoords(int a_ChunkX, int a_ChunkZ) : m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ) {}
bool operator == (const cChunkCoords & a_Other) const
{
- return ((m_ChunkX == a_Other.m_ChunkX) && (m_ChunkY == a_Other.m_ChunkY) && (m_ChunkZ == a_Other.m_ChunkZ));
+ return ((m_ChunkX == a_Other.m_ChunkX) && (m_ChunkZ == a_Other.m_ChunkZ));
}
} ;
@@ -395,6 +389,27 @@ typedef std::vector<cChunkCoords> cChunkCoordsVector;
+class cChunkCoordsWithBool
+{
+public:
+ int m_ChunkX;
+ int m_ChunkZ;
+ bool m_ForceGenerate;
+
+ cChunkCoordsWithBool(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate) : m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ), m_ForceGenerate(a_ForceGenerate){}
+
+ bool operator == (const cChunkCoordsWithBool & a_Other) const
+ {
+ return ((m_ChunkX == a_Other.m_ChunkX) && (m_ChunkZ == a_Other.m_ChunkZ) && (m_ForceGenerate == a_Other.m_ForceGenerate));
+ }
+};
+
+typedef std::list<cChunkCoordsWithBool> cChunkCoordsWithBoolList;
+
+
+
+
+
/// Interface class used as a callback for operations that involve chunk coords
class cChunkCoordCallback
{
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index a3692ef11..9c105c5af 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -143,26 +143,27 @@ cChunkMap::cChunkLayer * cChunkMap::GetLayerForChunk(int a_ChunkX, int a_ChunkZ)
-cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkZ)
{
- // No need to lock m_CSLayers, since it's already locked by the operation that called us
- ASSERT(m_CSLayers.IsLockedByCurrentThread());
+ ASSERT(m_CSLayers.IsLockedByCurrentThread()); // m_CSLayers should already be locked by the operation that called us
- cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
+ cChunkLayer * Layer = GetLayerForChunk(a_ChunkX, a_ChunkZ);
if (Layer == NULL)
{
// An error must have occurred, since layers are automatically created if they don't exist
return NULL;
}
- cChunkPtr Chunk = Layer->GetChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
+ cChunkPtr Chunk = Layer->GetChunk(a_ChunkX, a_ChunkZ);
if (Chunk == NULL)
{
return NULL;
}
- if (!(Chunk->IsValid()))
+ if (!Chunk->IsValid() && !Chunk->IsQueued())
{
- m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkY, a_ChunkZ, true);
+ Chunk->SetPresence(cChunk::cpQueued);
+ Chunk->SetShouldGenerateIfLoadFailed(true);
+ m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ);
}
return Chunk;
}
@@ -171,24 +172,26 @@ cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
-cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+cChunkPtr cChunkMap::GetChunkNoGen(int a_ChunkX, int a_ChunkZ)
{
- // No need to lock m_CSLayers, since it's already locked by the operation that called us
- cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
+ ASSERT(m_CSLayers.IsLockedByCurrentThread()); // m_CSLayers should already be locked by the operation that called us
+
+ cChunkLayer * Layer = GetLayerForChunk(a_ChunkX, a_ChunkZ);
if (Layer == NULL)
{
// An error must have occurred, since layers are automatically created if they don't exist
return NULL;
}
- cChunkPtr Chunk = Layer->GetChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
+ cChunkPtr Chunk = Layer->GetChunk(a_ChunkX, a_ChunkZ);
if (Chunk == NULL)
{
return NULL;
}
- if (!(Chunk->IsValid()))
+ if (!Chunk->IsValid() && !Chunk->IsQueued())
{
- m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkY, a_ChunkZ, false);
+ Chunk->SetPresence(cChunk::cpQueued);
+ m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ);
}
return Chunk;
@@ -198,9 +201,10 @@ cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkY, int a_ChunkZ)
-cChunkPtr cChunkMap::GetChunkNoLoad( int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+cChunkPtr cChunkMap::GetChunkNoLoad( int a_ChunkX, int a_ChunkZ)
{
- // No need to lock m_CSLayers, since it's already locked by the operation that called us
+ ASSERT(m_CSLayers.IsLockedByCurrentThread()); // m_CSLayers should already be locked by the operation that called us
+
cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
if (Layer == NULL)
{
@@ -208,7 +212,7 @@ cChunkPtr cChunkMap::GetChunkNoLoad( int a_ChunkX, int a_ChunkY, int a_ChunkZ)
return NULL;
}
- return Layer->GetChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
+ return Layer->GetChunk(a_ChunkX, a_ChunkZ);
}
@@ -222,7 +226,7 @@ bool cChunkMap::LockedGetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTY
int ChunkX, ChunkZ;
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return false;
@@ -244,7 +248,7 @@ bool cChunkMap::LockedGetBlockType(int a_BlockX, int a_BlockY, int a_BlockZ, BLO
int ChunkX, ChunkZ;
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return false;
@@ -265,7 +269,7 @@ bool cChunkMap::LockedGetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIB
int ChunkX, ChunkZ;
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return false;
@@ -284,7 +288,7 @@ bool cChunkMap::LockedSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTY
// We already have m_CSLayers locked since this can be called only from within the tick thread
int ChunkX, ChunkZ;
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return false;
@@ -303,7 +307,7 @@ bool cChunkMap::LockedFastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLO
// We already have m_CSLayers locked since this can be called only from within the tick thread
int ChunkX, ChunkZ;
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return false;
@@ -336,7 +340,7 @@ cChunk * cChunkMap::FindChunk(int a_ChunkX, int a_ChunkZ)
void cChunkMap::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -356,7 +360,7 @@ void cChunkMap::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, c
x = a_BlockX;
z = a_BlockZ;
cChunkDef::BlockToChunk(x, z, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return;
@@ -375,7 +379,7 @@ void cChunkMap::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_blockX, a_blockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return;
@@ -393,7 +397,7 @@ void cChunkMap::BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, c
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return;
@@ -408,7 +412,7 @@ void cChunkMap::BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, c
void cChunkMap::BroadcastChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, 0, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if (Chunk == NULL)
{
return;
@@ -424,7 +428,7 @@ void cChunkMap::BroadcastChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSeriali
void cChunkMap::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -440,7 +444,7 @@ void cChunkMap::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer &
void cChunkMap::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -456,7 +460,7 @@ void cChunkMap::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHa
void cChunkMap::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -472,7 +476,7 @@ void cChunkMap::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID,
void cChunkMap::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -488,7 +492,7 @@ void cChunkMap::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotN
void cChunkMap::BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -504,7 +508,7 @@ void cChunkMap::BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientH
void cChunkMap::BroadcastEntityLook(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -520,7 +524,7 @@ void cChunkMap::BroadcastEntityLook(const cEntity & a_Entity, const cClientHandl
void cChunkMap::BroadcastEntityMetadata(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -536,7 +540,7 @@ void cChunkMap::BroadcastEntityMetadata(const cEntity & a_Entity, const cClientH
void cChunkMap::BroadcastEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -552,7 +556,7 @@ void cChunkMap::BroadcastEntityRelMove(const cEntity & a_Entity, char a_RelX, ch
void cChunkMap::BroadcastEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -568,7 +572,7 @@ void cChunkMap::BroadcastEntityRelMoveLook(const cEntity & a_Entity, char a_RelX
void cChunkMap::BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -584,7 +588,7 @@ void cChunkMap::BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, c
void cChunkMap::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -600,7 +604,7 @@ void cChunkMap::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientH
void cChunkMap::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -619,7 +623,7 @@ void cChunkMap::BroadcastParticleEffect(const AString & a_ParticleName, float a_
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk((int) a_SrcX, (int) a_SrcZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return;
@@ -636,7 +640,7 @@ void cChunkMap::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_Effe
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -655,7 +659,7 @@ void cChunkMap::BroadcastSoundEffect(const AString & a_SoundName, double a_X, do
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk((int)std::floor(a_X), (int)std::floor(a_Z), ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return;
@@ -674,7 +678,7 @@ void cChunkMap::BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_S
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_SrcX, a_SrcZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return;
@@ -690,7 +694,7 @@ void cChunkMap::BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_S
void cChunkMap::BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
@@ -708,7 +712,7 @@ void cChunkMap::BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, c
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return;
@@ -727,7 +731,7 @@ void cChunkMap::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_Bl
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return;
@@ -745,7 +749,7 @@ void cChunkMap::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClien
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return;
@@ -763,7 +767,7 @@ void cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, i
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return;
@@ -778,7 +782,7 @@ void cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, i
bool cChunkMap::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
if (Chunk == NULL)
{
return false;
@@ -795,7 +799,7 @@ void cChunkMap::WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ)
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return;
@@ -824,7 +828,7 @@ void cChunkMap::WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_M
int MaxZ = std::min(a_MaxBlockZ, z * cChunkDef::Width + cChunkDef::Width - 1);
for (int x = MinChunkX; x <= MaxChunkX; x++)
{
- cChunkPtr Chunk = GetChunkNoGen(x, 0, z);
+ cChunkPtr Chunk = GetChunkNoGen(x, z);
if ((Chunk == NULL) || !Chunk->IsValid())
{
continue;
@@ -852,7 +856,7 @@ void cChunkMap::WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_M
void cChunkMap::MarkRedstoneDirty(int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return;
@@ -867,7 +871,7 @@ void cChunkMap::MarkRedstoneDirty(int a_ChunkX, int a_ChunkZ)
void cChunkMap::MarkChunkDirty(int a_ChunkX, int a_ChunkZ, bool a_MarkRedstoneDirty)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return;
@@ -886,7 +890,7 @@ void cChunkMap::MarkChunkDirty(int a_ChunkX, int a_ChunkZ, bool a_MarkRedstoneDi
void cChunkMap::MarkChunkSaving(int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return;
@@ -901,7 +905,7 @@ void cChunkMap::MarkChunkSaving(int a_ChunkX, int a_ChunkZ)
void cChunkMap::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return;
@@ -919,7 +923,7 @@ void cChunkMap::SetChunkData(cSetChunkData & a_SetChunkData)
int ChunkZ = a_SetChunkData.GetChunkZ();
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return;
@@ -964,7 +968,7 @@ void cChunkMap::ChunkLighted(
)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
if (Chunk == NULL)
{
return;
@@ -980,7 +984,7 @@ void cChunkMap::ChunkLighted(
bool cChunkMap::GetChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataCallback & a_Callback)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -996,7 +1000,7 @@ bool cChunkMap::GetChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataCallback & a_
bool cChunkMap::GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockTypes)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -1009,10 +1013,21 @@ bool cChunkMap::GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_Blo
+bool cChunkMap::IsChunkQueued(int a_ChunkX, int a_ChunkZ)
+{
+ cCSLock Lock(m_CSLayers);
+ cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
+ return (Chunk != NULL) && Chunk->IsQueued();
+}
+
+
+
+
+
bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
return (Chunk != NULL) && Chunk->IsValid();
}
@@ -1023,7 +1038,7 @@ bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkZ)
bool cChunkMap::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
return (Chunk != NULL) && Chunk->HasAnyClients();
}
@@ -1038,7 +1053,7 @@ int cChunkMap::GetHeight(int a_BlockX, int a_BlockZ)
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ, BlockY = 0;
cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
if (Chunk == NULL)
{
return 0;
@@ -1065,7 +1080,7 @@ bool cChunkMap::TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height)
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ, BlockY = 0;
cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -1088,7 +1103,7 @@ void cChunkMap::FastSetBlocks(sSetBlockList & a_BlockList)
int ChunkX = a_BlockList.front().ChunkX;
int ChunkZ = a_BlockList.front().ChunkZ;
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
for (sSetBlockList::iterator itr = a_BlockList.begin(); itr != a_BlockList.end();)
@@ -1135,7 +1150,7 @@ void cChunkMap::CollectPickupsByPlayer(cPlayer * a_Player)
int BlockX = (int)(a_Player->GetPosX()); // Truncating doesn't matter much; we're scanning entire chunks anyway
int BlockY = (int)(a_Player->GetPosY());
int BlockZ = (int)(a_Player->GetPosZ());
- int ChunkX, ChunkZ, ChunkY = ZERO_CHUNK_Y;
+ int ChunkX = 0, ChunkZ = 0;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
int OtherChunkX = ChunkX + ((BlockX > 8) ? 1 : -1);
int OtherChunkZ = ChunkZ + ((BlockZ > 8) ? 1 : -1);
@@ -1144,13 +1159,13 @@ void cChunkMap::CollectPickupsByPlayer(cPlayer * a_Player)
// The only time the chunks are not valid is when the player is downloading the initial world and they should not call this at that moment
cCSLock Lock(m_CSLayers);
- GetChunkNoLoad(ChunkX, ChunkY, ChunkZ)->CollectPickupsByPlayer(a_Player);
+ GetChunkNoLoad(ChunkX, ChunkZ)->CollectPickupsByPlayer(a_Player);
// Check the neighboring chunks as well:
- GetChunkNoLoad(OtherChunkX, ChunkY, ChunkZ)->CollectPickupsByPlayer (a_Player);
- GetChunkNoLoad(OtherChunkX, ChunkY, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
- GetChunkNoLoad(ChunkX, ChunkY, ChunkZ)->CollectPickupsByPlayer (a_Player);
- GetChunkNoLoad(ChunkX, ChunkY, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
+ GetChunkNoLoad(OtherChunkX, ChunkZ)->CollectPickupsByPlayer (a_Player);
+ GetChunkNoLoad(OtherChunkX, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
+ GetChunkNoLoad(ChunkX, ChunkZ)->CollectPickupsByPlayer (a_Player);
+ GetChunkNoLoad(ChunkX, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
}
@@ -1177,7 +1192,7 @@ BLOCKTYPE cChunkMap::GetBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
return Chunk->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
@@ -1206,7 +1221,7 @@ NIBBLETYPE cChunkMap::GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ)
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk( ChunkX, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
return Chunk->GetMeta(a_BlockX, a_BlockY, a_BlockZ);
@@ -1224,7 +1239,7 @@ NIBBLETYPE cChunkMap::GetBlockSkyLight(int a_BlockX, int a_BlockY, int a_BlockZ)
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk( ChunkX, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
return Chunk->GetSkyLight(a_BlockX, a_BlockY, a_BlockZ);
@@ -1242,7 +1257,7 @@ NIBBLETYPE cChunkMap::GetBlockBlockLight(int a_BlockX, int a_BlockY, int a_Block
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk( ChunkX, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
return Chunk->GetBlockLight(a_BlockX, a_BlockY, a_BlockZ);
@@ -1261,7 +1276,7 @@ void cChunkMap::SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYP
// a_BlockXYZ now contains relative coords!
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
Chunk->SetMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta);
@@ -1284,7 +1299,7 @@ void cChunkMap::SetBlock(cWorldInterface & a_WorldInterface, int a_BlockX, int a
cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk( ChunkX, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
Chunk->SetBlock(X, Y, Z, a_BlockType, a_BlockMeta, a_SendToClients);
@@ -1303,7 +1318,7 @@ void cChunkMap::QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYP
cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
Chunk->QueueSetBlock(X, Y, Z, a_BlockType, a_BlockMeta, a_Tick, a_PreviousBlockType);
@@ -1320,7 +1335,7 @@ bool cChunkMap::GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCK
cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk( ChunkX, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
Chunk->GetBlockTypeMeta(X, Y, Z, a_BlockType, a_BlockMeta);
@@ -1339,7 +1354,7 @@ bool cChunkMap::GetBlockInfo(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE
cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk( ChunkX, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
Chunk->GetBlockInfo(X, Y, Z, a_BlockType, a_Meta, a_SkyLight, a_BlockLight);
@@ -1357,7 +1372,7 @@ void cChunkMap::ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_Filt
cCSLock Lock(m_CSLayers);
for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
{
- cChunkPtr Chunk = GetChunk(itr->ChunkX, ZERO_CHUNK_Y, itr->ChunkZ);
+ cChunkPtr Chunk = GetChunk(itr->ChunkX, itr->ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
continue;
@@ -1378,7 +1393,7 @@ void cChunkMap::ReplaceTreeBlocks(const sSetBlockVector & a_Blocks)
cCSLock Lock(m_CSLayers);
for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
{
- cChunkPtr Chunk = GetChunk(itr->ChunkX, ZERO_CHUNK_Y, itr->ChunkZ);
+ cChunkPtr Chunk = GetChunk(itr->ChunkX, itr->ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
continue;
@@ -1413,7 +1428,7 @@ EMCSBiome cChunkMap::GetBiomeAt (int a_BlockX, int a_BlockZ)
cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
return Chunk->GetBiomeAt(X, Z);
@@ -1434,7 +1449,7 @@ bool cChunkMap::SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome)
cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
Chunk->SetBiomeAt(X, Z, a_Biome);
@@ -1467,7 +1482,7 @@ bool cChunkMap::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMC
{
int MinRelZ = (z == MinChunkZ) ? MinZ : 0;
int MaxRelZ = (z == MaxChunkZ) ? MaxZ : cChunkDef::Width - 1;
- cChunkPtr Chunk = GetChunkNoLoad(x, ZERO_CHUNK_Y, z);
+ cChunkPtr Chunk = GetChunkNoLoad(x, z);
if ((Chunk != NULL) && Chunk->IsValid())
{
Chunk->SetAreaBiome(MinRelX, MaxRelX, MinRelZ, MaxRelZ, a_Biome);
@@ -1491,7 +1506,7 @@ bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
cCSLock Lock(m_CSLayers);
for (sSetBlockVector::iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
{
- cChunkPtr Chunk = GetChunk(itr->ChunkX, ZERO_CHUNK_Y, itr->ChunkZ);
+ cChunkPtr Chunk = GetChunk(itr->ChunkX, itr->ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
if (!a_ContinueOnFailure)
@@ -1519,7 +1534,7 @@ bool cChunkMap::DigBlock(int a_X, int a_Y, int a_Z)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr DestChunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr DestChunk = GetChunk( ChunkX, ChunkZ);
if ((DestChunk == NULL) || !DestChunk->IsValid())
{
return false;
@@ -1542,7 +1557,7 @@ void cChunkMap::SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player)
cChunkDef::AbsoluteToRelative(a_X, a_Y, a_Z, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
if ((Chunk != NULL) && (Chunk->IsValid()))
{
Chunk->SendBlockTo(a_X, a_Y, a_Z, a_Player->GetClientHandle());
@@ -1556,12 +1571,12 @@ void cChunkMap::SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player)
void cChunkMap::CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk1 = GetChunkNoGen(a_ChunkX1, ZERO_CHUNK_Y, a_ChunkZ1);
+ cChunkPtr Chunk1 = GetChunkNoGen(a_ChunkX1, a_ChunkZ1);
if (Chunk1 == NULL)
{
return;
}
- cChunkPtr Chunk2 = GetChunkNoGen(a_ChunkX2, ZERO_CHUNK_Y, a_ChunkZ2);
+ cChunkPtr Chunk2 = GetChunkNoGen(a_ChunkX2, a_ChunkZ2);
if (Chunk2 == NULL)
{
return;
@@ -1623,7 +1638,7 @@ void cChunkMap::CompareChunkClients(cChunk * a_Chunk1, cChunk * a_Chunk2, cClien
bool cChunkMap::AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunk(a_ChunkX, a_ChunkZ);
if (Chunk == NULL)
{
return false;
@@ -1638,7 +1653,7 @@ bool cChunkMap::AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Cli
void cChunkMap::RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if (Chunk == NULL)
{
return;
@@ -1667,7 +1682,7 @@ void cChunkMap::RemoveClientFromChunks(cClientHandle * a_Client)
void cChunkMap::AddEntity(cEntity * a_Entity)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity->GetChunkX(), ZERO_CHUNK_Y, a_Entity->GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity->GetChunkX(), a_Entity->GetChunkZ());
if (
(Chunk == NULL) || // Chunk not present at all
(!Chunk->IsValid() && !a_Entity->IsPlayer()) // Chunk present, but no valid data; players need to spawn in such chunks (#953)
@@ -1688,7 +1703,7 @@ void cChunkMap::AddEntity(cEntity * a_Entity)
void cChunkMap::AddEntityIfNotPresent(cEntity * a_Entity)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity->GetChunkX(), ZERO_CHUNK_Y, a_Entity->GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity->GetChunkX(), a_Entity->GetChunkZ());
if (
(Chunk == NULL) || // Chunk not present at all
(!Chunk->IsValid() && !a_Entity->IsPlayer()) // Chunk present, but no valid data; players need to spawn in such chunks (#953)
@@ -1729,7 +1744,7 @@ bool cChunkMap::HasEntity(int a_UniqueID)
void cChunkMap::RemoveEntity(cEntity * a_Entity)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Entity->GetChunkX(), ZERO_CHUNK_Y, a_Entity->GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity->GetChunkX(), a_Entity->GetChunkZ());
// Even if a chunk is not valid, it may still contain entities such as players; make sure to remove them (#1190)
if (Chunk == NULL)
@@ -1763,7 +1778,7 @@ bool cChunkMap::ForEachEntity(cEntityCallback & a_Callback)
bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -1775,6 +1790,38 @@ bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback
+bool cChunkMap::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback)
+{
+ // Calculate the chunk range for the box:
+ int MinChunkX = (int)floor(a_Box.GetMinX() / cChunkDef::Width);
+ int MinChunkZ = (int)floor(a_Box.GetMinZ() / cChunkDef::Width);
+ int MaxChunkX = (int)floor((a_Box.GetMaxX() + cChunkDef::Width) / cChunkDef::Width);
+ int MaxChunkZ = (int)floor((a_Box.GetMaxZ() + cChunkDef::Width) / cChunkDef::Width);
+
+ // Iterate over each chunk in the range:
+ cCSLock Lock(m_CSLayers);
+ for (int z = MinChunkZ; z <= MaxChunkZ; z++)
+ {
+ for (int x = MinChunkX; x <= MaxChunkX; x++)
+ {
+ cChunkPtr Chunk = GetChunkNoGen(x, z);
+ if ((Chunk == NULL) || !Chunk->IsValid())
+ {
+ continue;
+ }
+ if (!Chunk->ForEachEntityInBox(a_Box, a_Callback))
+ {
+ return false;
+ }
+ } // for x
+ } // for z
+ return true;
+}
+
+
+
+
+
void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlocksAffected)
{
// Don't explode if outside of Y range (prevents the following test running into unallocated memory):
@@ -1989,7 +2036,7 @@ bool cChunkMap::DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback)
bool cChunkMap::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback & a_Callback)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2004,7 +2051,7 @@ bool cChunkMap::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEnti
bool cChunkMap::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2019,7 +2066,7 @@ bool cChunkMap::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback &
bool cChunkMap::ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback & a_Callback)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2034,7 +2081,7 @@ bool cChunkMap::ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCa
bool cChunkMap::ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback & a_Callback)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2049,7 +2096,7 @@ bool cChunkMap::ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallba
bool cChunkMap::ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback & a_Callback)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2064,7 +2111,7 @@ bool cChunkMap::ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpens
bool cChunkMap::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback & a_Callback)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2082,7 +2129,7 @@ bool cChunkMap::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cB
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2100,7 +2147,7 @@ bool cChunkMap::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeacon
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2118,7 +2165,7 @@ bool cChunkMap::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCa
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2136,7 +2183,7 @@ bool cChunkMap::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDis
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2154,7 +2201,7 @@ bool cChunkMap::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropp
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2172,7 +2219,7 @@ bool cChunkMap::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cD
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2190,7 +2237,7 @@ bool cChunkMap::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurna
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2207,7 +2254,7 @@ bool cChunkMap::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNot
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2224,7 +2271,7 @@ bool cChunkMap::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, c
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2242,7 +2289,7 @@ bool cChunkMap::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHe
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2260,7 +2307,7 @@ bool cChunkMap::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlo
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2278,7 +2325,7 @@ bool cChunkMap::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString &
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2290,62 +2337,20 @@ bool cChunkMap::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString &
-void cChunkMap::TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cChunkMap::TouchChunk(int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
- GetChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
-}
-
-
-
-
-
-/// Loads the chunk synchronously, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before)
-bool cChunkMap::LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
-{
- {
- cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
- if (Chunk == NULL)
- {
- // Internal error
- return false;
- }
- if (Chunk->IsValid())
- {
- // Already loaded
- return true;
- }
- if (Chunk->HasLoadFailed())
- {
- // Already tried loading and it failed
- return false;
- }
- }
- return m_World->GetStorage().LoadChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
-}
-
-
-
-
-
-/// Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid()
-void cChunkMap::LoadChunks(const cChunkCoordsList & a_Chunks)
-{
- for (cChunkCoordsList::const_iterator itr = a_Chunks.begin(); itr != a_Chunks.end(); ++itr)
- {
- LoadChunk(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
- } // for itr - a_Chunks[]
+ GetChunk(a_ChunkX, a_ChunkZ);
}
-void cChunkMap::ChunkLoadFailed(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cChunkMap::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkY, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
if (Chunk == NULL)
{
return;
@@ -2362,7 +2367,7 @@ bool cChunkMap::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const ASt
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return false;
@@ -2377,7 +2382,7 @@ bool cChunkMap::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const ASt
void cChunkMap::MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
if (Chunk == NULL)
{
// Not present
@@ -2393,7 +2398,7 @@ void cChunkMap::MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ)
bool cChunkMap::IsChunkLighted(int a_ChunkX, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
if (Chunk == NULL)
{
// Not present
@@ -2414,7 +2419,7 @@ bool cChunkMap::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinCh
{
for (int x = a_MinChunkX; x <= a_MaxChunkX; x++)
{
- cChunkPtr Chunk = GetChunkNoLoad(x, ZERO_CHUNK_Y, z);
+ cChunkPtr Chunk = GetChunkNoLoad(x, z);
if ((Chunk == NULL) || (!Chunk->IsValid()))
{
// Not present / not valid
@@ -2456,7 +2461,7 @@ bool cChunkMap::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBl
{
for (int x = MinChunkX; x <= MaxChunkX; x++)
{
- cChunkPtr Chunk = GetChunkNoLoad(x, ZERO_CHUNK_Y, z);
+ cChunkPtr Chunk = GetChunkNoLoad(x, z);
if ((Chunk == NULL) || (!Chunk->IsValid()))
{
// Not present / not valid
@@ -2497,7 +2502,7 @@ void cChunkMap::GrowMelonPumpkin(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCK
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if (Chunk != NULL)
{
Chunk->GrowMelonPumpkin(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_Rand);
@@ -2514,7 +2519,7 @@ void cChunkMap::GrowSugarcane(int a_BlockX, int a_BlockY, int a_BlockZ, int a_Nu
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if (Chunk != NULL)
{
Chunk->GrowSugarcane(a_BlockX, a_BlockY, a_BlockZ, a_NumBlocksToGrow);
@@ -2531,7 +2536,7 @@ void cChunkMap::GrowCactus(int a_BlockX, int a_BlockY, int a_BlockZ, int a_NumBl
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if (Chunk != NULL)
{
Chunk->GrowCactus(a_BlockX, a_BlockY, a_BlockZ, a_NumBlocksToGrow);
@@ -2548,7 +2553,7 @@ void cChunkMap::SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ)
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if (Chunk != NULL)
{
Chunk->SetNextBlockTick(a_BlockX, a_BlockY, a_BlockZ);
@@ -2603,7 +2608,7 @@ void cChunkMap::TickBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return;
@@ -2672,7 +2677,7 @@ void cChunkMap::QueueTickBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
// a_BlockXYZ now contains relative coords!
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
if (Chunk != NULL)
{
Chunk->QueueTickBlock(a_BlockX, a_BlockY, a_BlockZ);
@@ -2686,7 +2691,7 @@ void cChunkMap::QueueTickBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
void cChunkMap::SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
if (Chunk != NULL)
{
Chunk->SetAlwaysTicked(a_AlwaysTicked);
@@ -2731,7 +2736,7 @@ cChunkMap::cChunkLayer::~cChunkLayer()
-cChunkPtr cChunkMap::cChunkLayer::GetChunk( int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+cChunkPtr cChunkMap::cChunkLayer::GetChunk( int a_ChunkX, int a_ChunkZ)
{
// Always returns an assigned chunkptr, but the chunk needn't be valid (loaded / generated) - callers must check
@@ -2751,7 +2756,7 @@ cChunkPtr cChunkMap::cChunkLayer::GetChunk( int a_ChunkX, int a_ChunkY, int a_Ch
cChunk * neixp = (LocalX < LAYER_SIZE - 1) ? m_Chunks[Index + 1] : m_Parent->FindChunk(a_ChunkX + 1, a_ChunkZ);
cChunk * neizm = (LocalZ > 0) ? m_Chunks[Index - LAYER_SIZE] : m_Parent->FindChunk(a_ChunkX, a_ChunkZ - 1);
cChunk * neizp = (LocalZ < LAYER_SIZE - 1) ? m_Chunks[Index + LAYER_SIZE] : m_Parent->FindChunk(a_ChunkX, a_ChunkZ + 1);
- m_Chunks[Index] = new cChunk(a_ChunkX, 0, a_ChunkZ, m_Parent, m_Parent->GetWorld(), neixm, neixp, neizm, neizp, m_Pool);
+ m_Chunks[Index] = new cChunk(a_ChunkX, a_ChunkZ, m_Parent, m_Parent->GetWorld(), neixm, neixp, neizm, neizp, m_Pool);
}
return m_Chunks[Index];
}
@@ -2951,7 +2956,7 @@ void cChunkMap::cChunkLayer::Save(void)
{
if ((m_Chunks[i] != NULL) && m_Chunks[i]->IsValid() && m_Chunks[i]->IsDirty())
{
- World->GetStorage().QueueSaveChunk(m_Chunks[i]->GetPosX(), m_Chunks[i]->GetPosY(), m_Chunks[i]->GetPosZ());
+ World->GetStorage().QueueSaveChunk(m_Chunks[i]->GetPosX(), m_Chunks[i]->GetPosZ());
}
} // for i - m_Chunks[]
}
@@ -3024,7 +3029,7 @@ void cChunkMap::AddChunkStay(cChunkStay & a_ChunkStay)
const cChunkCoordsVector & WantedChunks = a_ChunkStay.GetChunks();
for (cChunkCoordsVector::const_iterator itr = WantedChunks.begin(); itr != WantedChunks.end(); ++itr)
{
- cChunkPtr Chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
+ cChunkPtr Chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkZ);
if (Chunk == NULL)
{
continue;
@@ -3073,7 +3078,7 @@ void cChunkMap::DelChunkStay(cChunkStay & a_ChunkStay)
const cChunkCoordsVector & Chunks = a_ChunkStay.GetChunks();
for (cChunkCoordsVector::const_iterator itr = Chunks.begin(), end = Chunks.end(); itr != end; ++itr)
{
- cChunkPtr Chunk = GetChunkNoLoad(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(itr->m_ChunkX, itr->m_ChunkZ);
if (Chunk == NULL)
{
continue;
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index 1e9a0f982..7354536d4 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -36,6 +36,7 @@ class cBlockArea;
class cMobCensus;
class cMobSpawner;
class cSetChunkData;
+class cBoundingBox;
typedef std::list<cClientHandle *> cClientHandleList;
typedef cChunk * cChunkPtr;
@@ -132,6 +133,9 @@ public:
/** Copies the chunk's blocktypes into a_Blocks; returns true if successful */
bool GetChunkBlockTypes (int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_Blocks);
+ /** Returns true iff the chunk is in the loader / generator queue. */
+ bool IsChunkQueued(int a_ChunkX, int a_ChunkZ);
+
bool IsChunkValid (int a_ChunkX, int a_ChunkZ);
bool HasChunkAnyClients (int a_ChunkX, int a_ChunkZ);
int GetHeight (int a_BlockX, int a_BlockZ); // Waits for the chunk to get loaded / generated
@@ -209,6 +213,11 @@ public:
/** Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Lua-accessible
+ /** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox.
+ Returns true if all entities processed, false if the callback aborted by returning true.
+ If any chunk in the box is missing, ignores the entities in that chunk silently. */
+ bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback); // Lua-accessible
+
/** Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates */
void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlockAffected);
@@ -270,16 +279,10 @@ public:
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible
/** Touches the chunk, causing it to be loaded or generated */
- void TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void TouchChunk(int a_ChunkX, int a_ChunkZ);
- /** Loads the chunk, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before) */
- bool LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
-
- /** Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid() */
- void LoadChunks(const cChunkCoordsList & a_Chunks);
-
/** Marks the chunk as failed-to-load */
- void ChunkLoadFailed(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
/** Sets the sign text. Returns true if sign text changed. */
bool SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
@@ -363,7 +366,7 @@ private:
~cChunkLayer();
/** Always returns an assigned chunkptr, but the chunk needn't be valid (loaded / generated) - callers must check */
- cChunkPtr GetChunk( int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ cChunkPtr GetChunk( int a_ChunkX, int a_ChunkZ);
/** Returns the specified chunk, or NULL if not created yet */
cChunk * FindChunk(int a_ChunkX, int a_ChunkZ);
@@ -456,9 +459,9 @@ private:
std::auto_ptr<cAllocationPool<cChunkData::sChunkSection> > m_Pool;
- cChunkPtr GetChunk (int a_ChunkX, int a_ChunkY, int a_ChunkZ); // Also queues the chunk for loading / generating if not valid
- cChunkPtr GetChunkNoGen (int a_ChunkX, int a_ChunkY, int a_ChunkZ); // Also queues the chunk for loading if not valid; doesn't generate
- cChunkPtr GetChunkNoLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ); // Doesn't load, doesn't generate
+ cChunkPtr GetChunk (int a_ChunkX, int a_ChunkZ); // Also queues the chunk for loading / generating if not valid
+ cChunkPtr GetChunkNoGen (int a_ChunkX, int a_ChunkZ); // Also queues the chunk for loading if not valid; doesn't generate
+ cChunkPtr GetChunkNoLoad(int a_ChunkX, int a_ChunkZ); // Doesn't load, doesn't generate
/** Gets a block in any chunk while in the cChunk's Tick() method; returns true if successful, false if chunk not loaded (doesn't queue load) */
bool LockedGetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
diff --git a/src/ChunkSender.cpp b/src/ChunkSender.cpp
index ebcf0e272..95c4d03d2 100644
--- a/src/ChunkSender.cpp
+++ b/src/ChunkSender.cpp
@@ -81,7 +81,7 @@ void cChunkSender::ChunkReady(int a_ChunkX, int a_ChunkZ)
// This is probably never gonna be called twice for the same chunk, and if it is, we don't mind, so we don't check
{
cCSLock Lock(m_CS);
- m_ChunksReady.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
+ m_ChunksReady.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
}
m_evtQueue.Set();
}
@@ -95,12 +95,12 @@ void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle *
ASSERT(a_Client != NULL);
{
cCSLock Lock(m_CS);
- if (std::find(m_SendChunks.begin(), m_SendChunks.end(), sSendChunk(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ, a_Client)) != m_SendChunks.end())
+ if (std::find(m_SendChunks.begin(), m_SendChunks.end(), sSendChunk(a_ChunkX, a_ChunkZ, a_Client)) != m_SendChunks.end())
{
// Already queued, bail out
return;
}
- m_SendChunks.push_back(sSendChunk(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ, a_Client));
+ m_SendChunks.push_back(sSendChunk(a_ChunkX, a_ChunkZ, a_Client));
}
m_evtQueue.Set();
}
@@ -160,7 +160,7 @@ void cChunkSender::Execute(void)
m_ChunksReady.pop_front();
Lock.Unlock();
- SendChunk(Coords.m_ChunkX, Coords.m_ChunkY, Coords.m_ChunkZ, NULL);
+ SendChunk(Coords.m_ChunkX, Coords.m_ChunkZ, NULL);
}
else
{
@@ -169,7 +169,7 @@ void cChunkSender::Execute(void)
m_SendChunks.pop_front();
Lock.Unlock();
- SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkY, Chunk.m_ChunkZ, Chunk.m_Client);
+ SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkZ, Chunk.m_Client);
}
Lock.Lock();
int RemoveCount = m_RemoveCount;
@@ -186,14 +186,14 @@ void cChunkSender::Execute(void)
-void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
+void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
{
ASSERT(m_World != NULL);
// Ask the client if it still wants the chunk:
if (a_Client != NULL)
{
- if (!a_Client->WantsSendChunk(a_ChunkX, a_ChunkY, a_ChunkZ))
+ if (!a_Client->WantsSendChunk(a_ChunkX, a_ChunkZ))
{
return;
}
diff --git a/src/ChunkSender.h b/src/ChunkSender.h
index 624a3a0bd..a0e9087a9 100644
--- a/src/ChunkSender.h
+++ b/src/ChunkSender.h
@@ -95,13 +95,11 @@ protected:
struct sSendChunk
{
int m_ChunkX;
- int m_ChunkY;
int m_ChunkZ;
cClientHandle * m_Client;
- sSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client) :
+ sSendChunk(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) :
m_ChunkX(a_ChunkX),
- m_ChunkY(a_ChunkY),
m_ChunkZ(a_ChunkZ),
m_Client(a_Client)
{
@@ -111,7 +109,6 @@ protected:
{
return (
(a_Other.m_ChunkX == m_ChunkX) &&
- (a_Other.m_ChunkY == m_ChunkY) &&
(a_Other.m_ChunkZ == m_ChunkZ) &&
(a_Other.m_Client == m_Client)
);
@@ -162,7 +159,7 @@ protected:
virtual void BlockEntity (cBlockEntity * a_Entity) override;
/// Sends the specified chunk to a_Client, or to all chunk clients if a_Client == NULL
- void SendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
+ void SendChunk(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
} ;
diff --git a/src/ChunkStay.cpp b/src/ChunkStay.cpp
index b5002a63d..38aa89a37 100644
--- a/src/ChunkStay.cpp
+++ b/src/ChunkStay.cpp
@@ -51,7 +51,7 @@ void cChunkStay::Add(int a_ChunkX, int a_ChunkZ)
return;
}
} // for itr - Chunks[]
- m_Chunks.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
+ m_Chunks.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
}
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index 5ad9dc644..ce77967db 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -472,13 +472,13 @@ void cClientHandle::StreamChunks(void)
// For each distance touch chunks in a hollow square centered around current position:
for (int i = -d; i <= d; ++i)
{
- World->TouchChunk(ChunkPosX + d, ZERO_CHUNK_Y, ChunkPosZ + i);
- World->TouchChunk(ChunkPosX - d, ZERO_CHUNK_Y, ChunkPosZ + i);
+ World->TouchChunk(ChunkPosX + d, ChunkPosZ + i);
+ World->TouchChunk(ChunkPosX - d, ChunkPosZ + i);
} // for i
for (int i = -d + 1; i < d; ++i)
{
- World->TouchChunk(ChunkPosX + i, ZERO_CHUNK_Y, ChunkPosZ + d);
- World->TouchChunk(ChunkPosX + i, ZERO_CHUNK_Y, ChunkPosZ - d);
+ World->TouchChunk(ChunkPosX + i, ChunkPosZ + d);
+ World->TouchChunk(ChunkPosX + i, ChunkPosZ - d);
} // for i
} // for d
}
@@ -501,8 +501,8 @@ void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ)
{
{
cCSLock Lock(m_CSChunkLists);
- m_LoadedChunks.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
- m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
+ m_LoadedChunks.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
+ m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
}
World->SendChunkTo(a_ChunkX, a_ChunkZ, this);
}
@@ -1448,7 +1448,7 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, e
NewBlock->OnPlacedByPlayer(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
// Step sound with 0.8f pitch is used as block placement sound
- World->BroadcastSoundEffect(NewBlock->GetStepSound(), (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 1.0f, 0.8f);
+ World->BroadcastSoundEffect(cBlockInfo::GetPlaceSound(BlockType), (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 1.0f, 0.8f);
cRoot::Get()->GetPluginManager()->CallHookPlayerPlacedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
}
@@ -2734,7 +2734,7 @@ bool cClientHandle::HasPluginChannel(const AString & a_PluginChannel)
-bool cClientHandle::WantsSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+bool cClientHandle::WantsSendChunk(int a_ChunkX, int a_ChunkZ)
{
if (m_State >= csDestroying)
{
@@ -2742,7 +2742,7 @@ bool cClientHandle::WantsSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
}
cCSLock Lock(m_CSChunkLists);
- return (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)) != m_ChunksToSend.end());
+ return (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), cChunkCoords(a_ChunkX, a_ChunkZ)) != m_ChunksToSend.end());
}
@@ -2758,9 +2758,9 @@ void cClientHandle::AddWantedChunk(int a_ChunkX, int a_ChunkZ)
LOGD("Adding chunk [%d, %d] to wanted chunks for client %p", a_ChunkX, a_ChunkZ, this);
cCSLock Lock(m_CSChunkLists);
- if (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ)) == m_ChunksToSend.end())
+ if (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), cChunkCoords(a_ChunkX, a_ChunkZ)) == m_ChunksToSend.end())
{
- m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
+ m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
}
}
@@ -2858,11 +2858,27 @@ void cClientHandle::SocketClosed(void)
-void cClientHandle::HandleEnchantItem(Byte & WindowID, Byte & Enchantment)
+void cClientHandle::HandleEnchantItem(Byte & a_WindowID, Byte & a_Enchantment)
{
- cEnchantingWindow * Window = (cEnchantingWindow*)m_Player->GetWindow();
+ if (a_Enchantment > 2)
+ {
+ LOGWARNING("%s attempt to crash the server with invalid enchanting selection!", GetUsername().c_str());
+ Kick("Invalid enchanting!");
+ return;
+ }
+
+ if (
+ (m_Player->GetWindow() == NULL) ||
+ (m_Player->GetWindow()->GetWindowID() != a_WindowID) ||
+ (m_Player->GetWindow()->GetWindowType() != cWindow::wtEnchantment)
+ )
+ {
+ return;
+ }
+
+ cEnchantingWindow * Window = (cEnchantingWindow*) m_Player->GetWindow();
cItem Item = *Window->m_SlotArea->GetSlot(0, *m_Player);
- int BaseEnchantmentLevel = Window->GetPropertyValue(Enchantment);
+ int BaseEnchantmentLevel = Window->GetPropertyValue(a_Enchantment);
if (Item.EnchantByXPLevels(BaseEnchantmentLevel))
{
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index 7ae70a07f..74e89deee 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -62,7 +62,7 @@ public:
cClientHandle(const cSocket * a_Socket, int a_ViewDistance);
virtual ~cClientHandle();
- const AString & GetIPString(void) const { return m_IPString; }
+ const AString & GetIPString(void) const { return m_IPString; } // tolua_export
cPlayer * GetPlayer(void) { return m_Player; } // tolua_export
@@ -209,7 +209,7 @@ public:
// tolua_end
/** Returns true if the client wants the chunk specified to be sent (in m_ChunksToSend) */
- bool WantsSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ bool WantsSendChunk(int a_ChunkX, int a_ChunkZ);
/** Adds the chunk specified to the list of chunks wanted for sending (m_ChunksToSend) */
void AddWantedChunk(int a_ChunkX, int a_ChunkZ);
@@ -269,7 +269,7 @@ public:
void RemoveFromWorld(void);
/** Called when the player will enchant a Item */
- void HandleEnchantItem(Byte & WindowID, Byte & Enchantment);
+ void HandleEnchantItem(Byte & a_WindowID, Byte & a_Enchantment);
private:
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 89d1cffa1..9bcdcffeb 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -387,7 +387,7 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
case cMonster::mtGhast:
case cMonster::mtZombiePigman:
case cMonster::mtMagmaCube:
- {
+ {
break;
};
default: StartBurning(BurnTicks * 20);
@@ -417,7 +417,7 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
}
if (!Player->IsOnGround())
- {
+ {
if ((a_TDI.DamageType == dtAttack) || (a_TDI.DamageType == dtArrowAttack))
{
a_TDI.FinalDamage += 2;
diff --git a/src/Entities/EntityEffect.cpp b/src/Entities/EntityEffect.cpp
index 1ebbf1926..1a923930f 100644
--- a/src/Entities/EntityEffect.cpp
+++ b/src/Entities/EntityEffect.cpp
@@ -34,14 +34,14 @@ cEntityEffect::eType cEntityEffect::GetPotionEffectType(short a_ItemDamage)
case 0x08: return cEntityEffect::effWeakness;
case 0x09: return cEntityEffect::effStrength;
case 0x0a: return cEntityEffect::effSlowness;
+ case 0x0b: return cEntityEffect::effJumpBoost;
case 0x0c: return cEntityEffect::effInstantDamage;
case 0x0d: return cEntityEffect::effWaterBreathing;
case 0x0e: return cEntityEffect::effInvisibility;
-
+
// No effect potions
case 0x00:
case 0x07:
- case 0x0b: // Will be potion of leaping in 1.8
case 0x0f:
{
break;
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index b3bb1072e..e1f9c30ea 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -1668,7 +1668,11 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents);
m_LoadedWorldName = root.get("world", "world").asString();
- a_World = cRoot::Get()->GetWorld(GetLoadedWorldName(), true);
+ a_World = cRoot::Get()->GetWorld(GetLoadedWorldName(), false);
+ if (a_World == NULL)
+ {
+ a_World = cRoot::Get()->GetDefaultWorld();
+ }
m_LastBedPos.x = root.get("SpawnX", a_World->GetSpawnX()).asInt();
m_LastBedPos.y = root.get("SpawnY", a_World->GetSpawnY()).asInt();
diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp
index 8fad9f5c9..60ad4e3eb 100644
--- a/src/Generating/BioGen.cpp
+++ b/src/Generating/BioGen.cpp
@@ -151,7 +151,7 @@ void cBioGenCache::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a
LOGD("BioGenCache: %d hits, %d misses, saved %.2f %%", m_NumHits, m_NumMisses, 100.0 * m_NumHits / (m_NumHits + m_NumMisses));
LOGD("BioGenCache: Avg cache chain length: %.2f", (float)m_TotalChain / m_NumHits);
}
-
+
for (int i = 0; i < m_CacheSize; i++)
{
if (
@@ -208,6 +208,59 @@ void cBioGenCache::InitializeBiomeGen(cIniFile & a_IniFile)
+////////////////////////////////////////////////////////////////////////////////
+// cBioGenMulticache:
+
+cBioGenMulticache::cBioGenMulticache(cBiomeGen * a_BioGenToCache, size_t a_CacheSize, size_t a_CachesLength) :
+ m_CachesLength(a_CachesLength)
+{
+ m_Caches.reserve(a_CachesLength);
+ for (size_t i = 0; i < a_CachesLength; i++)
+ {
+ m_Caches.push_back(new cBioGenCache(a_BioGenToCache, a_CacheSize));
+ }
+}
+
+
+
+
+
+cBioGenMulticache::~cBioGenMulticache()
+{
+ for (cBiomeGens::iterator it = m_Caches.begin(); it != m_Caches.end(); it++)
+ {
+ delete *it;
+ }
+}
+
+
+
+
+
+void cBioGenMulticache::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap)
+{
+ const size_t coefficient = 3;
+ const size_t cacheIdx = ((size_t)a_ChunkX + coefficient * (size_t)a_ChunkZ) % m_CachesLength;
+
+ m_Caches[cacheIdx]->GenBiomes(a_ChunkX, a_ChunkZ, a_BiomeMap);
+}
+
+
+
+
+
+void cBioGenMulticache::InitializeBiomeGen(cIniFile & a_IniFile)
+{
+ for (cBiomeGens::iterator it = m_Caches.begin(); it != m_Caches.end(); it++)
+ {
+ cBiomeGen * tmp = *it;
+ tmp->InitializeBiomeGen(a_IniFile);
+ }
+}
+
+
+
+
////////////////////////////////////////////////////////////////////////////////
// cBiomeGenList:
diff --git a/src/Generating/BioGen.h b/src/Generating/BioGen.h
index 227ec97d7..20d199611 100644
--- a/src/Generating/BioGen.h
+++ b/src/Generating/BioGen.h
@@ -80,6 +80,36 @@ protected:
+class cBioGenMulticache :
+ public cBiomeGen
+{
+
+ typedef cBiomeGen super;
+
+public:
+ /*
+ a_CacheSize defines the size of each singular cache
+ a_CachesLength defines how many caches are used for the multicache
+ */
+ cBioGenMulticache(cBiomeGen * a_BioGenToCache, size_t a_CacheSize, size_t a_CachesLength); // Doesn't take ownership of a_BioGenToCache
+ ~cBioGenMulticache();
+
+protected:
+ typedef std::vector<cBiomeGen *> cBiomeGens;
+
+
+ size_t m_CachesLength;
+ cBiomeGens m_Caches;
+
+
+ virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
+ virtual void InitializeBiomeGen(cIniFile & a_IniFile) override;
+};
+
+
+
+
+
/// Base class for generators that use a list of available biomes. This class takes care of the list.
class cBiomeGenList :
public cBiomeGen
diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp
index a1188f984..d615456c1 100644
--- a/src/Generating/ChunkGenerator.cpp
+++ b/src/Generating/ChunkGenerator.cpp
@@ -52,10 +52,21 @@ bool cChunkGenerator::Start(cPluginInterface & a_PluginInterface, cChunkSink & a
m_PluginInterface = &a_PluginInterface;
m_ChunkSink = &a_ChunkSink;
- MTRand rnd;
- m_Seed = a_IniFile.GetValueSetI("Seed", "Seed", (int)rnd.randInt());
+ // Get the seed; create a new one and log it if not found in the INI file:
+ if (a_IniFile.HasValue("Seed", "Seed"))
+ {
+ m_Seed = a_IniFile.GetValueI("Seed", "Seed");
+ }
+ else
+ {
+ MTRand rnd;
+ m_Seed = rnd.randInt();
+ LOGINFO("Chosen a new random seed for world: %d", m_Seed);
+ a_IniFile.SetValueI("Seed", "Seed", m_Seed);
+ }
+
+ // Get the generator engine based on the INI file settings:
AString GeneratorName = a_IniFile.GetValueSet("Generator", "Generator", "Composable");
-
if (NoCaseCompare(GeneratorName, "Noise3D") == 0)
{
m_Generator = new cNoise3DGenerator(*this);
@@ -99,15 +110,17 @@ void cChunkGenerator::Stop(void)
-void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate)
{
+ ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ));
+
{
cCSLock Lock(m_CS);
// Check if it is already in the queue:
- for (cChunkCoordsList::iterator itr = m_Queue.begin(); itr != m_Queue.end(); ++itr)
+ for (cChunkCoordsWithBoolList::iterator itr = m_Queue.begin(); itr != m_Queue.end(); ++itr)
{
- if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkY == a_ChunkY) && (itr->m_ChunkZ == a_ChunkZ))
+ if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ))
{
// Already in the queue, bail out
return;
@@ -119,7 +132,7 @@ void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkY, int a_Chunk
{
LOGWARN("WARNING: Adding chunk [%i, %i] to generation queue; Queue is too big! (" SIZE_T_FMT ")", a_ChunkX, a_ChunkZ, m_Queue.size());
}
- m_Queue.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
+ m_Queue.push_back(cChunkCoordsWithBool(a_ChunkX, a_ChunkZ, a_ForceGenerate));
}
m_Event.Set();
@@ -229,9 +242,9 @@ void cChunkGenerator::Execute(void)
continue;
}
- cChunkCoords coords = m_Queue.front(); // Get next coord from queue
- m_Queue.erase( m_Queue.begin()); // Remove coordinate from queue
+ cChunkCoordsWithBool coords = m_Queue.front(); // Get next coord from queue
bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT);
+ m_Queue.erase(m_Queue.begin()); // Remove coordinate from queue
Lock.Unlock(); // Unlock ASAP
m_evtRemoved.Set();
@@ -245,8 +258,7 @@ void cChunkGenerator::Execute(void)
LastReportTick = clock();
}
- // Hack for regenerating chunks: if Y != 0, the chunk is considered invalid, even if it has its data set
- if ((coords.m_ChunkY == 0) && m_ChunkSink->IsChunkValid(coords.m_ChunkX, coords.m_ChunkZ))
+ if (!coords.m_ForceGenerate && m_ChunkSink->IsChunkValid(coords.m_ChunkX, coords.m_ChunkZ))
{
LOGD("Chunk [%d, %d] already generated, skipping generation", coords.m_ChunkX, coords.m_ChunkZ);
// Already generated, ignore request
@@ -259,8 +271,8 @@ void cChunkGenerator::Execute(void)
continue;
}
- LOGD("Generating chunk [%d, %d, %d]", coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
- DoGenerate(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
+ LOGD("Generating chunk [%d, %d]", coords.m_ChunkX, coords.m_ChunkZ);
+ DoGenerate(coords.m_ChunkX, coords.m_ChunkZ);
NumChunksGenerated++;
} // while (!bStop)
@@ -269,11 +281,12 @@ void cChunkGenerator::Execute(void)
-void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ)
{
ASSERT(m_PluginInterface != NULL);
ASSERT(m_ChunkSink != NULL);
-
+ ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ));
+
cChunkDesc ChunkDesc(a_ChunkX, a_ChunkZ);
m_PluginInterface->CallHookChunkGenerating(ChunkDesc);
m_Generator->DoGenerate(a_ChunkX, a_ChunkZ, ChunkDesc);
diff --git a/src/Generating/ChunkGenerator.h b/src/Generating/ChunkGenerator.h
index 88d71f3f9..190d9e616 100644
--- a/src/Generating/ChunkGenerator.h
+++ b/src/Generating/ChunkGenerator.h
@@ -106,6 +106,10 @@ public:
If this callback returns false, the chunk is not generated.
*/
virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) = 0;
+
+ /** Called to check whether the specified chunk is in the queued state.
+ Currently used only in Debug-mode asserts. */
+ virtual bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) = 0;
} ;
@@ -116,7 +120,7 @@ public:
void Stop(void);
/// Queues the chunk for generation; removes duplicate requests
- void QueueGenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate);
/// Generates the biomes for the specified chunk (directly, not in a separate thread). Used by the world loader if biomes failed loading.
void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap);
@@ -137,10 +141,10 @@ private:
int m_Seed;
- cCriticalSection m_CS;
- cChunkCoordsList m_Queue;
- cEvent m_Event; ///< Set when an item is added to the queue or the thread should terminate
- cEvent m_evtRemoved; ///< Set when an item is removed from the queue
+ cCriticalSection m_CS;
+ cChunkCoordsWithBoolList m_Queue;
+ cEvent m_Event; ///< Set when an item is added to the queue or the thread should terminate
+ cEvent m_evtRemoved; ///< Set when an item is removed from the queue
cGenerator * m_Generator; ///< The actual generator engine used to generate chunks
@@ -154,7 +158,7 @@ private:
// cIsThread override:
virtual void Execute(void) override;
- void DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void DoGenerate(int a_ChunkX, int a_ChunkZ);
};
diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp
index 6f4007d24..69068d231 100644
--- a/src/Generating/ComposableGenerator.cpp
+++ b/src/Generating/ComposableGenerator.cpp
@@ -230,17 +230,29 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile)
// Add a cache, if requested:
int CacheSize = a_IniFile.GetValueSetI("Generator", "BiomeGenCacheSize", CacheOffByDefault ? 0 : 64);
- if (CacheSize > 0)
+
+ if (CacheSize <= 0)
+ {
+ return;
+ }
+
+ int MultiCacheLength = a_IniFile.GetValueSetI("Generator", "BiomeGenMultiCacheLength", 4);
+ if (CacheSize < 4)
+ {
+ LOGWARNING("Biomegen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d",
+ CacheSize, 4
+ );
+ CacheSize = 4;
+ }
+ LOGD("Using a cache for biomegen of size %d.", CacheSize);
+ m_UnderlyingBiomeGen = m_BiomeGen;
+ if (MultiCacheLength > 0)
+ {
+ LOGD("Enabling multicache for biomegen of length %d.", MultiCacheLength);
+ m_BiomeGen = new cBioGenMulticache(m_UnderlyingBiomeGen, CacheSize, MultiCacheLength);
+ }
+ else
{
- if (CacheSize < 4)
- {
- LOGWARNING("Biomegen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d",
- CacheSize, 4
- );
- CacheSize = 4;
- }
- LOGD("Using a cache for biomegen of size %d.", CacheSize);
- m_UnderlyingBiomeGen = m_BiomeGen;
m_BiomeGen = new cBioGenCache(m_UnderlyingBiomeGen, CacheSize);
}
}
diff --git a/src/HTTPServer/HTTPServer.cpp b/src/HTTPServer/HTTPServer.cpp
index 8eabe5cb2..0c41b54b2 100644
--- a/src/HTTPServer/HTTPServer.cpp
+++ b/src/HTTPServer/HTTPServer.cpp
@@ -170,7 +170,8 @@ bool cHTTPServer::Initialize(const AString & a_PortsIPv4, const AString & a_Port
// Notify the admin about the HTTPS / HTTP status
if (m_Cert.get() == NULL)
{
- LOGWARNING("WebServer: The server is running in unsecure HTTP mode.");
+ LOGWARNING("WebServer: The server is running in unsecured HTTP mode.");
+ LOGINFO("Put a valid HTTPS certificate in file 'webadmin/httpscert.crt' and its corresponding private key to 'webadmin/httpskey.pem' (without any password) to enable HTTPS support");
}
else
{
diff --git a/src/Item.cpp b/src/Item.cpp
index 2c5deaddf..ebdf99ca5 100644
--- a/src/Item.cpp
+++ b/src/Item.cpp
@@ -190,31 +190,35 @@ void cItem::FromJson(const Json::Value & a_Value)
-bool cItem::IsEnchantable(short item)
+bool cItem::IsEnchantable(short a_ItemType, bool a_WithBook)
{
- if ((item >= 256) && (item <= 259))
+ if (
+ ItemCategory::IsAxe(a_ItemType) ||
+ ItemCategory::IsSword(a_ItemType) ||
+ ItemCategory::IsShovel(a_ItemType) ||
+ ItemCategory::IsPickaxe(a_ItemType) ||
+ (a_WithBook && ItemCategory::IsHoe(a_ItemType)) ||
+ ItemCategory::IsArmor(a_ItemType)
+ )
{
return true;
}
- if ((item >= 267) && (item <= 279))
- {
- return true;
- }
- if ((item >= 283) && (item <= 286))
- {
- return true;
- }
- if ((item >= 290) && (item <= 294))
- {
- return true;
- }
- if ((item >= 298) && (item <= 317))
- {
- return true;
- }
- if ((item == 346) || (item == 359) || (item == 261))
+
+ switch (a_ItemType)
{
- return true;
+ case E_ITEM_BOOK:
+ case E_ITEM_BOW:
+ case E_ITEM_FISHING_ROD:
+ {
+ return true;
+ }
+
+ case E_ITEM_CARROT_ON_STICK:
+ case E_ITEM_SHEARS:
+ case E_ITEM_FLINT_AND_STEEL:
+ {
+ return a_WithBook;
+ }
}
return false;
@@ -299,73 +303,77 @@ int cItem::GetEnchantability()
bool cItem::EnchantByXPLevels(int a_NumXPLevels)
{
- if (!cItem::IsEnchantable(m_ItemType) && (m_ItemType != E_ITEM_BOOK))
+ if (!cItem::IsEnchantable(m_ItemType))
{
return false;
}
int Enchantability = GetEnchantability();
+ if (Enchantability == 0)
+ {
+ return false;
+ }
cFastRandom Random;
int ModifiedEnchantmentLevel = a_NumXPLevels + (int)Random.NextFloat((float)Enchantability / 4) + (int)Random.NextFloat((float)Enchantability / 4) + 1;
float RandomBonus = 1.0F + (Random.NextFloat(1) + Random.NextFloat(1) - 1.0F) * 0.15F;
int FinalEnchantmentLevel = (int)(ModifiedEnchantmentLevel * RandomBonus + 0.5F);
- cWeightedEnchantments enchantments;
- cEnchantments::AddItemEnchantmentWeights(enchantments, m_ItemType, FinalEnchantmentLevel);
+ cWeightedEnchantments Enchantments;
+ cEnchantments::AddItemEnchantmentWeights(Enchantments, m_ItemType, FinalEnchantmentLevel);
if (m_ItemType == E_ITEM_BOOK)
{
m_ItemType = E_ITEM_ENCHANTED_BOOK;
}
- cEnchantments Enchantment1 = cEnchantments::GetRandomEnchantmentFromVector(enchantments);
+ cEnchantments Enchantment1 = cEnchantments::GetRandomEnchantmentFromVector(Enchantments);
m_Enchantments.AddFromString(Enchantment1.ToString());
- cEnchantments::RemoveEnchantmentWeightFromVector(enchantments, Enchantment1);
+ cEnchantments::RemoveEnchantmentWeightFromVector(Enchantments, Enchantment1);
// Checking for conflicting enchantments
- cEnchantments::CheckEnchantmentConflictsFromVector(enchantments, Enchantment1);
+ cEnchantments::CheckEnchantmentConflictsFromVector(Enchantments, Enchantment1);
float NewEnchantmentLevel = (float)a_NumXPLevels;
// Next Enchantment (Second)
NewEnchantmentLevel = NewEnchantmentLevel / 2;
float SecondEnchantmentChance = (NewEnchantmentLevel + 1) / 50 * 100;
- if (enchantments.empty() || (Random.NextFloat(100) > SecondEnchantmentChance))
+ if (Enchantments.empty() || (Random.NextFloat(100) > SecondEnchantmentChance))
{
return true;
}
- cEnchantments Enchantment2 = cEnchantments::GetRandomEnchantmentFromVector(enchantments);
+ cEnchantments Enchantment2 = cEnchantments::GetRandomEnchantmentFromVector(Enchantments);
m_Enchantments.AddFromString(Enchantment2.ToString());
- cEnchantments::RemoveEnchantmentWeightFromVector(enchantments, Enchantment2);
+ cEnchantments::RemoveEnchantmentWeightFromVector(Enchantments, Enchantment2);
// Checking for conflicting enchantments
- cEnchantments::CheckEnchantmentConflictsFromVector(enchantments, Enchantment2);
+ cEnchantments::CheckEnchantmentConflictsFromVector(Enchantments, Enchantment2);
// Next Enchantment (Third)
NewEnchantmentLevel = NewEnchantmentLevel / 2;
float ThirdEnchantmentChance = (NewEnchantmentLevel + 1) / 50 * 100;
- if (enchantments.empty() || (Random.NextFloat(100) > ThirdEnchantmentChance))
+ if (Enchantments.empty() || (Random.NextFloat(100) > ThirdEnchantmentChance))
{
return true;
}
- cEnchantments Enchantment3 = cEnchantments::GetRandomEnchantmentFromVector(enchantments);
+ cEnchantments Enchantment3 = cEnchantments::GetRandomEnchantmentFromVector(Enchantments);
m_Enchantments.AddFromString(Enchantment3.ToString());
- cEnchantments::RemoveEnchantmentWeightFromVector(enchantments, Enchantment3);
+ cEnchantments::RemoveEnchantmentWeightFromVector(Enchantments, Enchantment3);
// Checking for conflicting enchantments
- cEnchantments::CheckEnchantmentConflictsFromVector(enchantments, Enchantment3);
+ cEnchantments::CheckEnchantmentConflictsFromVector(Enchantments, Enchantment3);
// Next Enchantment (Fourth)
NewEnchantmentLevel = NewEnchantmentLevel / 2;
float FourthEnchantmentChance = (NewEnchantmentLevel + 1) / 50 * 100;
- if (enchantments.empty() || (Random.NextFloat(100) > FourthEnchantmentChance))
+ if (Enchantments.empty() || (Random.NextFloat(100) > FourthEnchantmentChance))
{
return true;
}
- cEnchantments Enchantment4 = cEnchantments::GetRandomEnchantmentFromVector(enchantments);
+ cEnchantments Enchantment4 = cEnchantments::GetRandomEnchantmentFromVector(Enchantments);
m_Enchantments.AddFromString(Enchantment4.ToString());
return true;
diff --git a/src/Item.h b/src/Item.h
index d8b9e78a0..056b5eb8a 100644
--- a/src/Item.h
+++ b/src/Item.h
@@ -183,8 +183,10 @@ public:
/** Loads the item data from JSON representation */
void FromJson(const Json::Value & a_Value);
- /** Returns true if the specified item type is enchantable (as per 1.2.5 protocol requirements) */
- static bool IsEnchantable(short a_ItemType); // tolua_export
+ /** Returns true if the specified item type is enchantable.
+ If WithBook is true, the function is used in the anvil inventory with book enchantments.
+ So it checks the "only book enchantments" too. Example: You can only enchant a hoe with a book. */
+ static bool IsEnchantable(short a_ItemType, bool a_WithBook = false); // tolua_export
/** Returns the enchantability of the item. When the item hasn't a enchantability, it will returns 0 */
int GetEnchantability(); // tolua_export
diff --git a/src/Items/ItemFood.h b/src/Items/ItemFood.h
index 98050cad8..9035344df 100644
--- a/src/Items/ItemFood.h
+++ b/src/Items/ItemFood.h
@@ -29,7 +29,7 @@ public:
switch (m_ItemType)
{
// Please keep alpha-sorted.
- case E_ITEM_BAKED_POTATO: return FoodInfo(6, 7.2);
+ case E_ITEM_BAKED_POTATO: return FoodInfo(5, 7.2);
case E_ITEM_BREAD: return FoodInfo(5, 6);
// Carrots handled in ItemSeeds
case E_ITEM_COOKED_CHICKEN: return FoodInfo(6, 7.2);
@@ -43,14 +43,16 @@ public:
case E_ITEM_POISONOUS_POTATO: return FoodInfo(2, 1.2);
// Potatoes handled in ItemSeeds
case E_ITEM_PUMPKIN_PIE: return FoodInfo(8, 4.8);
+ case E_ITEM_RED_APPLE: return FoodInfo(4, 2.4);
case E_ITEM_RAW_BEEF: return FoodInfo(3, 1.8);
case E_ITEM_RAW_CHICKEN: return FoodInfo(2, 1.2);
case E_ITEM_RAW_FISH: return FoodInfo(2, 1.2);
+ case E_ITEM_RAW_MUTTON: return FoodInfo(2, 1.2);
case E_ITEM_RAW_PORKCHOP: return FoodInfo(3, 1.8);
- case E_ITEM_RED_APPLE: return FoodInfo(4, 2.4);
case E_ITEM_ROTTEN_FLESH: return FoodInfo(4, 0.8);
case E_ITEM_SPIDER_EYE: return FoodInfo(2, 3.2);
case E_ITEM_STEAK: return FoodInfo(8, 12.8);
+ case E_ITEM_MUTTON: return FoodInfo(6, 9.6);
}
LOGWARNING("%s: Unknown food item (%d), returning zero nutrition", __FUNCTION__, m_ItemType);
return FoodInfo(0, 0.f);
diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp
index ca0f04dcc..e425be627 100644
--- a/src/Items/ItemHandler.cpp
+++ b/src/Items/ItemHandler.cpp
@@ -207,7 +207,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
}
// Food (please keep alpha-sorted):
- // (carrots and potatoes handled in SeedHandler as both seed and food
+ // (carrots and potatoes handled separately in SeedHandler as they're both seed and food)
case E_ITEM_BAKED_POTATO:
case E_ITEM_BREAD:
case E_ITEM_COOKED_CHICKEN:
@@ -217,13 +217,15 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
case E_ITEM_GOLDEN_CARROT:
case E_ITEM_MELON_SLICE:
case E_ITEM_MUSHROOM_SOUP:
+ case E_ITEM_MUTTON:
case E_ITEM_POISONOUS_POTATO:
case E_ITEM_PUMPKIN_PIE:
+ case E_ITEM_RED_APPLE:
case E_ITEM_RAW_BEEF:
case E_ITEM_RAW_CHICKEN:
case E_ITEM_RAW_FISH:
+ case E_ITEM_RAW_MUTTON:
case E_ITEM_RAW_PORKCHOP:
- case E_ITEM_RED_APPLE:
case E_ITEM_ROTTEN_FLESH:
case E_ITEM_SPIDER_EYE:
case E_ITEM_STEAK:
diff --git a/src/Items/ItemSeeds.h b/src/Items/ItemSeeds.h
index 54a1183d7..e1db7c5f4 100644
--- a/src/Items/ItemSeeds.h
+++ b/src/Items/ItemSeeds.h
@@ -37,7 +37,7 @@ public:
{
switch (m_ItemType)
{
- case E_ITEM_CARROT: return FoodInfo(4, 4.8);
+ case E_ITEM_CARROT: return FoodInfo(3, 4.8);
case E_ITEM_POTATO: return FoodInfo(1, 0.6);
default: return FoodInfo(0, 0);
}
diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp
index 9fb47201d..1a82115d2 100644
--- a/src/Mobs/Sheep.cpp
+++ b/src/Mobs/Sheep.cpp
@@ -39,6 +39,13 @@ void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer)
{
a_Drops.push_back(cItem(E_BLOCK_WOOL, 1, m_WoolColor));
}
+
+ int LootingLevel = 0;
+ if (a_Killer != NULL)
+ {
+ LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting);
+ }
+ AddRandomDropItem(a_Drops, 1, 3 + LootingLevel, IsOnFire() ? E_ITEM_MUTTON : E_ITEM_RAW_MUTTON);
}
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 1091b877f..f24ef320d 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -1355,6 +1355,7 @@ void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
void cProtocol172::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
{
ASSERT(m_State == 3); // In game mode?
+ ASSERT((a_BlockY >= 0) && (a_BlockY < cChunkDef::Height));
cPacketizer Pkt(*this, 0x33);
Pkt.WriteInt(a_BlockX);
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index ccfa19eb6..d3100d0fb 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -71,7 +71,9 @@ public:
virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
virtual void SendDisconnect (const AString & a_Reason) override;
+ virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
+ virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendEntityHeadLook (const cEntity & a_Entity) override;
@@ -82,6 +84,8 @@ public:
virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override;
virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override;
virtual void SendEntityVelocity (const cEntity & a_Entity) override;
+ virtual void SendExperience (void) override;
+ virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override;
virtual void SendGameMode (eGameMode a_GameMode) override;
virtual void SendHealth (void) override;
@@ -93,10 +97,9 @@ public:
virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override;
virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override;
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
+ virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override;
virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendPlayerAbilities (void) override;
- virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
- virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override;
virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override;
virtual void SendPlayerMaxSpeed (void) override;
virtual void SendPlayerMoveLook (void) override;
@@ -105,12 +108,9 @@ public:
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override;
- virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override;
- virtual void SendExperience (void) override;
- virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
- virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override;
- virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override;
+ virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
+ virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override;
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override;
diff --git a/src/Root.cpp b/src/Root.cpp
index f04cbf08b..86a497a76 100644
--- a/src/Root.cpp
+++ b/src/Root.cpp
@@ -18,6 +18,7 @@
#include "DeadlockDetect.h"
#include "OSSupport/Timer.h"
#include "LoggerListeners.h"
+#include "BuildInfo.h"
#include "inifile/iniFile.h"
@@ -111,6 +112,11 @@ void cRoot::Start(void)
LOG("--- Started Log ---\n");
+ #ifdef BUILD_ID
+ LOG("MCServer " BUILD_SERIES_NAME " build id: " BUILD_ID );
+ LOG("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME );
+ #endif
+
cDeadlockDetect dd;
m_bStop = false;
@@ -151,6 +157,7 @@ void cRoot::Start(void)
m_MojangAPI.Start(IniFile); // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init
if (!m_Server->InitServer(IniFile))
{
+ IniFile.WriteFile("settings.ini");
LOGERROR("Failure starting server, aborting...");
return;
}
diff --git a/src/SetChunkData.cpp b/src/SetChunkData.cpp
index bfe59fbcb..707dfb9e8 100644
--- a/src/SetChunkData.cpp
+++ b/src/SetChunkData.cpp
@@ -44,7 +44,6 @@ cSetChunkData::cSetChunkData(
// Check the params' validity:
ASSERT(a_BlockTypes != NULL);
ASSERT(a_BlockMetas != NULL);
- ASSERT(a_Biomes != NULL);
// Copy block types and metas:
memcpy(m_BlockTypes, a_BlockTypes, sizeof(cChunkDef::BlockTypes));
diff --git a/src/StringCompression.cpp b/src/StringCompression.cpp
index 71d64e71e..af9f1687f 100644
--- a/src/StringCompression.cpp
+++ b/src/StringCompression.cpp
@@ -180,3 +180,65 @@ extern int UncompressStringGZIP(const char * a_Data, size_t a_Length, AString &
+
+extern int InflateString(const char * a_Data, size_t a_Length, AString & a_Uncompressed)
+{
+ a_Uncompressed.reserve(a_Length);
+
+ char Buffer[64 KiB];
+ z_stream strm;
+ memset(&strm, 0, sizeof(strm));
+ strm.next_in = (Bytef *)a_Data;
+ strm.avail_in = (uInt)a_Length;
+ strm.next_out = (Bytef *)Buffer;
+ strm.avail_out = sizeof(Buffer);
+
+ int res = inflateInit(&strm); // Force GZIP decoding
+ if (res != Z_OK)
+ {
+ LOG("%s: inflation initialization failed: %d (\"%s\").", __FUNCTION__, res, strm.msg);
+ return res;
+ }
+
+ for (;;)
+ {
+ res = inflate(&strm, Z_NO_FLUSH);
+ switch (res)
+ {
+ case Z_OK:
+ {
+ // Some data has been uncompressed. Consume the buffer and continue uncompressing
+ a_Uncompressed.append(Buffer, sizeof(Buffer) - strm.avail_out);
+ strm.next_out = (Bytef *)Buffer;
+ strm.avail_out = sizeof(Buffer);
+ if (strm.avail_in == 0)
+ {
+ // All data has been uncompressed
+ inflateEnd(&strm);
+ return Z_OK;
+ }
+ break;
+ }
+
+ case Z_STREAM_END:
+ {
+ // Finished uncompressing. Consume the rest of the buffer and return
+ a_Uncompressed.append(Buffer, sizeof(Buffer) - strm.avail_out);
+ inflateEnd(&strm);
+ return Z_OK;
+ }
+
+ default:
+ {
+ // An error has occurred, log it and return the error value
+ LOG("%s: inflation failed: %d (\"%s\").", __FUNCTION__, res, strm.msg);
+ inflateEnd(&strm);
+ return res;
+ }
+ } // switch (res)
+ } // while (true)
+}
+
+
+
+
diff --git a/src/StringCompression.h b/src/StringCompression.h
index 038240797..dde17ce30 100644
--- a/src/StringCompression.h
+++ b/src/StringCompression.h
@@ -21,5 +21,7 @@ extern int CompressStringGZIP(const char * a_Data, size_t a_Length, AString & a_
/// Uncompresses a_Data into a_Uncompressed using GZIP; returns Z_OK for success or Z_XXX error constants same as zlib
extern int UncompressStringGZIP(const char * a_Data, size_t a_Length, AString & a_Uncompressed);
+/** Uncompresses a_Data into a_Uncompressed using Inflate; returns Z_OK for success or Z_XXX error constants same as zlib */
+extern int InflateString(const char * a_Data, size_t a_Length, AString & a_Uncompressed);
diff --git a/src/UI/SlotArea.cpp b/src/UI/SlotArea.cpp
index 4199bbf56..b4facb2d3 100644
--- a/src/UI/SlotArea.cpp
+++ b/src/UI/SlotArea.cpp
@@ -207,7 +207,7 @@ void cSlotArea::ShiftClicked(cPlayer & a_Player, int a_SlotNum, const cItem & a_
m_ParentWindow.DistributeStack(Slot, a_Player, this, true);
if (Slot.IsEmpty())
{
- // Empty the slot completely, the cilent doesn't like left-over ItemType with zero count
+ // Empty the slot completely, the client doesn't like left-over ItemType with zero count
Slot.Empty();
}
SetSlot(a_SlotNum, a_Player, Slot);
@@ -1389,8 +1389,11 @@ void cSlotAreaBeacon::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
////////////////////////////////////////////////////////////////////////////////
// cSlotAreaEnchanting:
-cSlotAreaEnchanting::cSlotAreaEnchanting(cEnchantingWindow & a_ParentWindow) :
- cSlotAreaTemporary(1, a_ParentWindow)
+cSlotAreaEnchanting::cSlotAreaEnchanting(cEnchantingWindow & a_ParentWindow, int a_BlockX, int a_BlockY, int a_BlockZ) :
+ cSlotAreaTemporary(1, a_ParentWindow),
+ m_BlockX(a_BlockX),
+ m_BlockY(a_BlockY),
+ m_BlockZ(a_BlockZ)
{
a_ParentWindow.m_SlotArea = this;
}
@@ -1409,7 +1412,7 @@ void cSlotAreaEnchanting::Clicked(cPlayer & a_Player, int a_SlotNum, eClickActio
LOGWARNING("GetSlot(%d) returned NULL! Ignoring click", a_SlotNum);
return;
}
-
+
switch (a_ClickAction)
{
case caShiftLeftClick:
@@ -1428,6 +1431,25 @@ void cSlotAreaEnchanting::Clicked(cPlayer & a_Player, int a_SlotNum, eClickActio
MiddleClicked(a_Player, a_SlotNum);
return;
}
+ case caDropKey:
+ case caCtrlDropKey:
+ {
+ DropClicked(a_Player, a_SlotNum, false);
+ return;
+ }
+ case caNumber1:
+ case caNumber2:
+ case caNumber3:
+ case caNumber4:
+ case caNumber5:
+ case caNumber6:
+ case caNumber7:
+ case caNumber8:
+ case caNumber9:
+ {
+ NumberClicked(a_Player, a_SlotNum, a_ClickAction);
+ return;
+ }
default:
{
break;
@@ -1443,106 +1465,36 @@ void cSlotAreaEnchanting::Clicked(cPlayer & a_Player, int a_SlotNum, eClickActio
bAsync = true;
}
cItem & DraggingItem = a_Player.GetDraggingItem();
- switch (a_ClickAction)
+
+ if (DraggingItem.IsEmpty())
{
- case caRightClick:
+ // DraggingItem is empty -> Switch draggingitem and slot
+ if (!Slot.IsEmpty())
{
- // Right-clicked
- if (DraggingItem.IsEmpty())
- {
- DraggingItem = Slot.CopyOne();
- Slot.Empty();
- break;
- }
-
- if (Slot.IsEmpty())
- {
- Slot = DraggingItem.CopyOne();
- DraggingItem.m_ItemCount -= 1;
- if (DraggingItem.m_ItemCount <= 0)
- {
- DraggingItem.Empty();
- }
- }
- else if ((!DraggingItem.IsEqual(Slot)) && (DraggingItem.m_ItemCount == 1))
- {
- // Swap contents
- cItem tmp(DraggingItem);
- DraggingItem = Slot;
- Slot = tmp;
- }
- break;
+ std::swap(DraggingItem, Slot);
}
-
- case caLeftClick:
- {
- // Left-clicked
- if (DraggingItem.IsEmpty())
- {
- DraggingItem = Slot.CopyOne();
- Slot.Empty();
- break;
- }
-
- if (DraggingItem.IsEqual(Slot))
- {
- // Do nothing
- break;
- }
-
- if (!Slot.IsEmpty())
- {
- if (DraggingItem.m_ItemCount == 1)
- {
- // Swap contents
- cItem tmp(DraggingItem);
- DraggingItem = Slot;
- Slot = tmp;
- }
- }
- else
- {
- Slot = DraggingItem.CopyOne();
- DraggingItem.m_ItemCount -= 1;
- if (DraggingItem.m_ItemCount <= 0)
- {
- DraggingItem.Empty();
- }
- }
- break;
- }
- default:
+ }
+ else if (Slot.IsEmpty())
+ {
+ // DraggingItem isn't empty and slot is empty -> Set one dragging item in the slot
+ Slot = DraggingItem.CopyOne();
+ DraggingItem.m_ItemCount -= 1;
+
+ if (DraggingItem.m_ItemCount <= 0)
{
- LOGWARNING("SlotArea: Unhandled click action: %d (%s)", a_ClickAction, ClickActionToString(a_ClickAction));
- m_ParentWindow.BroadcastWholeWindow();
- return;
+ DraggingItem.Empty();
}
- } // switch (a_ClickAction
-
- SetSlot(a_SlotNum, a_Player, Slot);
- if (bAsync)
- {
- m_ParentWindow.BroadcastWholeWindow();
}
- UpdateResult(a_Player);
-}
-
-
-
-
-
-void cSlotAreaEnchanting::DblClicked(cPlayer & a_Player, int a_SlotNum)
-{
- cItem & Dragging = a_Player.GetDraggingItem();
- if ((!Dragging.IsEmpty()) || (a_SlotNum != 0))
+ else if ((DraggingItem.m_ItemCount == 1) && !DraggingItem.IsEqual(Slot))
{
- return;
+ // DraggingItem and slot aren't empty -> Switch items
+ std::swap(DraggingItem, Slot);
}
-
- cItem Item = *GetSlot(0, a_Player);
- if (!m_ParentWindow.CollectItemsToHand(Item, *this, a_Player, false))
+
+ SetSlot(a_SlotNum, a_Player, Slot);
+ if (bAsync)
{
- m_ParentWindow.CollectItemsToHand(Item, *this, a_Player, true);
+ m_ParentWindow.BroadcastWholeWindow();
}
}
@@ -1567,7 +1519,15 @@ void cSlotAreaEnchanting::DistributeStack(cItem & a_ItemStack, cPlayer & a_Playe
{
a_ItemStack.Empty();
}
+}
+
+
+
+
+void cSlotAreaEnchanting::OnPlayerAdded(cPlayer & a_Player)
+{
+ super::OnPlayerAdded(a_Player);
UpdateResult(a_Player);
}
@@ -1587,29 +1547,33 @@ void cSlotAreaEnchanting::OnPlayerRemoved(cPlayer & a_Player)
+void cSlotAreaEnchanting::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item)
+{
+ super::SetSlot(a_SlotNum, a_Player, a_Item);
+ UpdateResult(a_Player);
+}
+
+
+
+
+
void cSlotAreaEnchanting::UpdateResult(cPlayer & a_Player)
{
cItem Item = *GetSlot(0, a_Player);
- if (Item.IsEmpty() || !Item.m_Enchantments.IsEmpty())
- {
- m_ParentWindow.SetProperty(0, 0, a_Player);
- m_ParentWindow.SetProperty(1, 0, a_Player);
- m_ParentWindow.SetProperty(2, 0, a_Player);
- }
- else if (cItem::IsEnchantable(Item.m_ItemType) || Item.m_ItemType == E_ITEM_BOOK)
+ if (cItem::IsEnchantable(Item.m_ItemType) && Item.m_Enchantments.IsEmpty())
{
int Bookshelves = std::min(GetBookshelvesCount(a_Player.GetWorld()), 15);
cFastRandom Random;
- int base = (Random.GenerateRandomInteger(1, 8) + (int)floor((float)Bookshelves / 2) + Random.GenerateRandomInteger(0, Bookshelves));
- int topSlot = std::max(base / 3, 1);
- int middleSlot = (base * 2) / 3 + 1;
- int bottomSlot = std::max(base, Bookshelves * 2);
+ int Base = (Random.GenerateRandomInteger(1, 8) + (int)floor((float)Bookshelves / 2) + Random.GenerateRandomInteger(0, Bookshelves));
+ int TopSlot = std::max(Base / 3, 1);
+ int MiddleSlot = (Base * 2) / 3 + 1;
+ int BottomSlot = std::max(Base, Bookshelves * 2);
- m_ParentWindow.SetProperty(0, topSlot, a_Player);
- m_ParentWindow.SetProperty(1, middleSlot, a_Player);
- m_ParentWindow.SetProperty(2, bottomSlot, a_Player);
+ m_ParentWindow.SetProperty(0, TopSlot, a_Player);
+ m_ParentWindow.SetProperty(1, MiddleSlot, a_Player);
+ m_ParentWindow.SetProperty(2, BottomSlot, a_Player);
}
else
{
@@ -1625,12 +1589,9 @@ void cSlotAreaEnchanting::UpdateResult(cPlayer & a_Player)
int cSlotAreaEnchanting::GetBookshelvesCount(cWorld * a_World)
{
- int PosX, PosY, PosZ;
- ((cEnchantingWindow*)&m_ParentWindow)->GetBlockPos(PosX, PosY, PosZ);
-
int Bookshelves = 0;
cBlockArea Area;
- Area.Read(a_World, PosX - 2, PosX + 2, PosY, PosY + 1, PosZ - 2, PosZ + 2);
+ Area.Read(a_World, m_BlockX - 2, m_BlockX + 2, m_BlockY, m_BlockY + 1, m_BlockZ - 2, m_BlockZ + 2);
static const struct
{
@@ -1678,7 +1639,7 @@ int cSlotAreaEnchanting::GetBookshelvesCount(cWorld * a_World)
if (
(Area.GetRelBlockType(CheckCoords[i].m_AirX, CheckCoords[i].m_AirY, CheckCoords[i].m_AirZ) == E_BLOCK_AIR) && // There's air in the checkspot
(Area.GetRelBlockType(CheckCoords[i].m_BookX, CheckCoords[i].m_BookY, CheckCoords[i].m_BookZ) == E_BLOCK_BOOKCASE) // There's bookcase in the wanted place
- )
+ )
{
Bookshelves++;
}
diff --git a/src/UI/SlotArea.h b/src/UI/SlotArea.h
index 9a96f2f3c..6bbc87b76 100644
--- a/src/UI/SlotArea.h
+++ b/src/UI/SlotArea.h
@@ -349,14 +349,15 @@ class cSlotAreaEnchanting :
typedef cSlotAreaTemporary super;
public:
- cSlotAreaEnchanting(cEnchantingWindow & a_ParentWindow);
+ cSlotAreaEnchanting(cEnchantingWindow & a_ParentWindow, int a_BlockX, int a_BlockY, int a_BlockZ);
// cSlotArea overrides:
virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
- virtual void DblClicked(cPlayer & a_Player, int a_SlotNum) override;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override;
+ virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
// cSlotAreaTemporary overrides:
+ virtual void OnPlayerAdded (cPlayer & a_Player) override;
virtual void OnPlayerRemoved(cPlayer & a_Player) override;
/* Get the count of bookshelves who stand in the near of the enchanting table */
@@ -365,6 +366,8 @@ public:
protected:
/** Handles a click in the item slot. */
void UpdateResult(cPlayer & a_Player);
+
+ int m_BlockX, m_BlockY, m_BlockZ;
};
diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp
index 8f4913030..66900269f 100644
--- a/src/UI/Window.cpp
+++ b/src/UI/Window.cpp
@@ -881,7 +881,7 @@ cEnchantingWindow::cEnchantingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
m_BlockY(a_BlockY),
m_BlockZ(a_BlockZ)
{
- m_SlotAreas.push_back(new cSlotAreaEnchanting(*this));
+ m_SlotAreas.push_back(new cSlotAreaEnchanting(*this, m_BlockX, m_BlockY, m_BlockZ));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
@@ -892,8 +892,13 @@ cEnchantingWindow::cEnchantingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
void cEnchantingWindow::SetProperty(int a_Property, int a_Value)
{
- m_PropertyValue[a_Property] = a_Value;
+ if ((a_Property < 0) || ((size_t)a_Property >= ARRAYCOUNT(m_PropertyValue)))
+ {
+ ASSERT(!"a_Property is invalid");
+ return;
+ }
+ m_PropertyValue[a_Property] = a_Value;
super::SetProperty(a_Property, a_Value);
}
@@ -903,8 +908,13 @@ void cEnchantingWindow::SetProperty(int a_Property, int a_Value)
void cEnchantingWindow::SetProperty(int a_Property, int a_Value, cPlayer & a_Player)
{
- m_PropertyValue[a_Property] = a_Value;
+ if ((a_Property < 0) || ((size_t)a_Property >= ARRAYCOUNT(m_PropertyValue)))
+ {
+ ASSERT(!"a_Property is invalid");
+ return;
+ }
+ m_PropertyValue[a_Property] = a_Value;
super::SetProperty(a_Property, a_Value, a_Player);
}
@@ -914,18 +924,13 @@ void cEnchantingWindow::SetProperty(int a_Property, int a_Value, cPlayer & a_Pla
int cEnchantingWindow::GetPropertyValue(int a_Property)
{
- return m_PropertyValue[a_Property];
-}
-
-
-
-
+ if ((a_Property < 0) || ((size_t)a_Property >= ARRAYCOUNT(m_PropertyValue)))
+ {
+ ASSERT(!"a_Property is invalid");
+ return 0;
+ }
-void cEnchantingWindow::GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ)
-{
- a_PosX = m_BlockX;
- a_PosY = m_BlockY;
- a_PosZ = m_BlockZ;
+ return m_PropertyValue[a_Property];
}
diff --git a/src/UI/Window.h b/src/UI/Window.h
index 9fb0e3b38..3d860407f 100644
--- a/src/UI/Window.h
+++ b/src/UI/Window.h
@@ -291,9 +291,6 @@ public:
/** Return the Value of a Property */
int GetPropertyValue(int a_Property);
- /** Get the Position from the Enchantment Table */
- void GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ);
-
cSlotArea * m_SlotArea;
protected:
diff --git a/src/WebAdmin.cpp b/src/WebAdmin.cpp
index 23eedbd14..db2ace386 100644
--- a/src/WebAdmin.cpp
+++ b/src/WebAdmin.cpp
@@ -43,6 +43,8 @@ public:
cWebAdmin::cWebAdmin(void) :
m_IsInitialized(false),
m_IsRunning(false),
+ m_PortsIPv4("8080"),
+ m_PortsIPv6(""),
m_TemplateScript("<webadmin_template>")
{
}
@@ -89,6 +91,8 @@ bool cWebAdmin::Init(void)
m_IniFile.AddHeaderComment(" Password format: Password=*password*; for example:");
m_IniFile.AddHeaderComment(" [User:admin]");
m_IniFile.AddHeaderComment(" Password=admin");
+ m_IniFile.SetValue("WebAdmin", "Port", m_PortsIPv4);
+ m_IniFile.SetValue("WebAdmin", "PortsIPv6", m_PortsIPv6);
m_IniFile.WriteFile("webadmin.ini");
}
@@ -100,8 +104,8 @@ bool cWebAdmin::Init(void)
LOGD("Initialising WebAdmin...");
- m_PortsIPv4 = m_IniFile.GetValueSet("WebAdmin", "Port", "8080");
- m_PortsIPv6 = m_IniFile.GetValueSet("WebAdmin", "PortsIPv6", "");
+ m_PortsIPv4 = m_IniFile.GetValueSet("WebAdmin", "Port", m_PortsIPv4);
+ m_PortsIPv6 = m_IniFile.GetValueSet("WebAdmin", "PortsIPv6", m_PortsIPv6);
if (!m_HTTPServer.Initialize(m_PortsIPv4, m_PortsIPv6))
{
@@ -131,8 +135,24 @@ bool cWebAdmin::Start(void)
m_TemplateScript.RegisterAPILibs();
if (!m_TemplateScript.LoadFile(FILE_IO_PREFIX "webadmin/template.lua"))
{
- LOGWARN("Could not load WebAdmin template \"%s\", using default template.", FILE_IO_PREFIX "webadmin/template.lua");
+ LOGWARN("Could not load WebAdmin template \"%s\". WebAdmin disabled!", FILE_IO_PREFIX "webadmin/template.lua");
m_TemplateScript.Close();
+ m_HTTPServer.Stop();
+ return false;
+ }
+
+ if (!LoadLoginTemplate())
+ {
+ LOGWARN("Could not load WebAdmin login template \"%s\", using fallback template.", FILE_IO_PREFIX "webadmin/login_template.html");
+
+ // Sets the fallback template:
+ m_LoginTemplate = \
+ "<h1>MCServer WebAdmin</h1>" \
+ "<center>" \
+ "<form method='get' action='webadmin/'>" \
+ "<input type='submit' value='Log in'>" \
+ "</form>" \
+ "</center>";
}
m_IsRunning = m_HTTPServer.Start(*this);
@@ -159,6 +179,28 @@ void cWebAdmin::Stop(void)
+bool cWebAdmin::LoadLoginTemplate(void)
+{
+ cFile File(FILE_IO_PREFIX "webadmin/login_template.html", cFile::fmRead);
+ if (!File.IsOpen())
+ {
+ return false;
+ }
+
+ AString TemplateContent;
+ if (File.ReadRestOfFile(TemplateContent) == -1)
+ {
+ return false;
+ }
+
+ m_LoginTemplate = TemplateContent;
+ return true;
+}
+
+
+
+
+
void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
{
if (!a_Request.HasAuth())
@@ -298,17 +340,64 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
void cWebAdmin::HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
{
UNUSED(a_Request);
- static const char LoginForm[] = \
- "<h1>MCServer WebAdmin</h1>" \
- "<center>" \
- "<form method='get' action='webadmin/'>" \
- "<input type='submit' value='Log in'>" \
- "</form>" \
- "</center>";
+
cHTTPResponse Resp;
Resp.SetContentType("text/html");
a_Connection.Send(Resp);
- a_Connection.Send(LoginForm, sizeof(LoginForm) - 1);
+ a_Connection.Send(m_LoginTemplate);
+ a_Connection.FinishResponse();
+}
+
+
+
+
+
+void cWebAdmin::HandleFileRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
+{
+ AString FileURL = a_Request.GetURL();
+ std::replace(FileURL.begin(), FileURL.end(), '\\', '/');
+
+ // Remove all leading backslashes:
+ if (FileURL[0] == '/')
+ {
+ size_t FirstCharToRead = FileURL.find_first_not_of('/');
+ if (FirstCharToRead != AString::npos)
+ {
+ FileURL = FileURL.substr(FirstCharToRead);
+ }
+ }
+
+ // Remove all "../" strings:
+ ReplaceString(FileURL, "../", "");
+
+ bool LoadedSuccessfull = false;
+ AString Content = "<h2>404 Not Found</h2>";
+ AString Path = Printf(FILE_IO_PREFIX "webadmin/files/%s", FileURL.c_str());
+ if (cFile::IsFile(Path))
+ {
+ cFile File(Path, cFile::fmRead);
+ AString FileContent;
+ if (File.IsOpen() && (File.ReadRestOfFile(FileContent) != -1))
+ {
+ LoadedSuccessfull = true;
+ Content = FileContent;
+ }
+ }
+
+ // Find content type (The currently method is very bad. We should change it later)
+ AString ContentType = "text/html";
+ size_t LastPointPosition = Path.find_last_of('.');
+ if (LoadedSuccessfull && (LastPointPosition != AString::npos) && (LastPointPosition < Path.length()))
+ {
+ AString FileExtension = Path.substr(LastPointPosition + 1);
+ ContentType = GetContentTypeFromFileExt(FileExtension);
+ }
+
+ // Send the response:
+ cHTTPResponse Resp;
+ Resp.SetContentType(ContentType);
+ a_Connection.Send(Resp);
+ a_Connection.Send(Content);
a_Connection.FinishResponse();
}
@@ -316,6 +405,41 @@ void cWebAdmin::HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest &
+AString cWebAdmin::GetContentTypeFromFileExt(const AString & a_FileExtension)
+{
+ static bool IsInitialized = false;
+ static std::map<AString, AString> ContentTypeMap;
+ if (!IsInitialized)
+ {
+ // Initialize the ContentTypeMap:
+ ContentTypeMap["png"] = "image/png";
+ ContentTypeMap["fif"] = "image/fif";
+ ContentTypeMap["gif"] = "image/gif";
+ ContentTypeMap["jpeg"] = "image/jpeg";
+ ContentTypeMap["jpg"] = "image/jpeg";
+ ContentTypeMap["jpe"] = "image/jpeg";
+ ContentTypeMap["tiff"] = "image/tiff";
+ ContentTypeMap["ico"] = "image/ico";
+ ContentTypeMap["csv"] = "image/comma-separated-values";
+ ContentTypeMap["css"] = "text/css";
+ ContentTypeMap["js"] = "text/javascript";
+ ContentTypeMap["txt"] = "text/plain";
+ ContentTypeMap["rtx"] = "text/richtext";
+ ContentTypeMap["xml"] = "text/xml";
+ }
+
+ AString FileExtension = StrToLower(a_FileExtension);
+ if (ContentTypeMap.find(a_FileExtension) == ContentTypeMap.end())
+ {
+ return "text/html";
+ }
+ return ContentTypeMap[FileExtension];
+}
+
+
+
+
+
sWebAdminPage cWebAdmin::GetPage(const HTTPRequest & a_Request)
{
sWebAdminPage Page;
@@ -382,6 +506,7 @@ AString cWebAdmin::GetDefaultPage(void)
+
AString cWebAdmin::GetBaseURL( const AString& a_URL)
{
return GetBaseURL(StringSplit(a_URL, "/"));
@@ -528,7 +653,7 @@ void cWebAdmin::OnRequestFinished(cHTTPConnection & a_Connection, cHTTPRequest &
}
else
{
- // TODO: Handle other requests
+ HandleFileRequest(a_Connection, a_Request);
}
// Delete any request data assigned to the request:
@@ -551,4 +676,3 @@ void cWebAdmin::cWebadminRequestData::OnBody(const char * a_Data, size_t a_Size)
-
diff --git a/src/WebAdmin.h b/src/WebAdmin.h
index aefc1d145..94b95dbcf 100644
--- a/src/WebAdmin.h
+++ b/src/WebAdmin.h
@@ -116,6 +116,9 @@ public:
/** Stops the HTTP server, if it was started. */
void Stop(void);
+ /** Loads the login template. Returns true if the loading succeeds, false if not. */
+ bool LoadLoginTemplate(void);
+
void AddPlugin(cWebPlugin * a_Plugin);
void RemovePlugin(cWebPlugin * a_Plugin);
@@ -146,6 +149,9 @@ public:
/** Returns the prefix needed for making a link point to the webadmin root from the given URL ("../../../webadmin"-style) */
static AString GetBaseURL(const AStringVector & a_URLSplit);
+ /** Returns the content type from the file extension. If the extension isn't in the list, the function returns "text/html" */
+ static AString GetContentTypeFromFileExt(const AString & a_FileExtension);
+
protected:
/** Common base class for request body data handlers */
class cRequestData
@@ -205,6 +211,9 @@ protected:
/** The Lua template script to provide templates: */
cLuaState m_TemplateScript;
+ /** The template that provides the login site: */
+ AString m_LoginTemplate;
+
/** The HTTP server which provides the underlying HTTP parsing, serialization and events */
cHTTPServer m_HTTPServer;
@@ -214,6 +223,9 @@ protected:
/** Handles requests for the root page */
void HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
+ /** Handles requests for a file */
+ void HandleFileRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
+
// cHTTPServer::cCallbacks overrides:
virtual void OnRequestBegun (cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override;
virtual void OnRequestBody (cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size) override;
diff --git a/src/World.cpp b/src/World.cpp
index 99e09c658..fdc0aebad 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -442,7 +442,7 @@ void cWorld::InitializeSpawn(void)
{
for (int z = 0; z < ViewDist; z++)
{
- m_ChunkMap->TouchChunk(x + ChunkX-(ViewDist - 1) / 2, ZERO_CHUNK_Y, z + ChunkZ-(ViewDist - 1) / 2); // Queue the chunk in the generator / loader
+ m_ChunkMap->TouchChunk(x + ChunkX-(ViewDist - 1) / 2, z + ChunkZ-(ViewDist - 1) / 2); // Queue the chunk in the generator / loader
}
}
@@ -757,6 +757,11 @@ void cWorld::InitialiseGeneratorDefaults(cIniFile & a_IniFile)
a_IniFile.GetValueSet("Generator", "BottomLavaHeight", "30");
break;
}
+ case dimNotSet:
+ {
+ ASSERT(!"Dimension not set");
+ break;
+ }
}
}
@@ -772,6 +777,7 @@ void cWorld::InitialiseAndLoadMobSpawningValues(cIniFile & a_IniFile)
case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, enderman, horse, mooshroom, ocelot, pig, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break;
case dimNether: DefaultMonsters = "blaze, ghast, magmacube, skeleton, zombie, zombiepigman"; break;
case dimEnd: DefaultMonsters = "enderman"; break;
+ case dimNotSet: ASSERT(!"Dimension not set"); break;
}
m_bAnimals = a_IniFile.GetValueSetB("Monsters", "AnimalsOn", true);
@@ -876,7 +882,7 @@ void cWorld::Tick(float a_Dt, int a_LastTickDurationMSec)
m_TimeOfDaySecs -= 1200.0;
}
- m_TimeOfDay = (Int64)(m_TimeOfDaySecs * 20.0);
+ m_TimeOfDay = static_cast<int>(m_TimeOfDaySecs * 20.0);
// Updates the sky darkness based on current time of day
UpdateSkyDarkness();
@@ -1130,7 +1136,7 @@ void cWorld::UpdateSkyDarkness(void)
}
else if (TempTime <= TIME_NIGHT_START)
{
- m_SkyDarkness = (TIME_NIGHT_START - TempTime) / TIME_SPAWN_DIVISOR;
+ m_SkyDarkness = static_cast<NIBBLETYPE>((TIME_NIGHT_START - TempTime) / TIME_SPAWN_DIVISOR);
}
else if (TempTime <= TIME_NIGHT_END)
{
@@ -1138,7 +1144,7 @@ void cWorld::UpdateSkyDarkness(void)
}
else
{
- m_SkyDarkness = (TIME_SUNRISE - TempTime) / TIME_SPAWN_DIVISOR;
+ m_SkyDarkness = static_cast<NIBBLETYPE>((TIME_SUNRISE - TempTime) / TIME_SPAWN_DIVISOR);
}
}
@@ -1592,9 +1598,9 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
MTRand r1;
for (int i = 0; i < 60; i++)
{
- int OfsX = (r1.randInt(3) + r1.randInt(3) + r1.randInt(3) + r1.randInt(3)) / 2 - 3;
- int OfsY = r1.randInt(3) + r1.randInt(3) - 3;
- int OfsZ = (r1.randInt(3) + r1.randInt(3) + r1.randInt(3) + r1.randInt(3)) / 2 - 3;
+ int OfsX = static_cast<int>(r1.randInt(3) + r1.randInt(3) + r1.randInt(3) + r1.randInt(3)) / 2 - 3;
+ int OfsY = static_cast<int>(r1.randInt(3) + r1.randInt(3)) - 3;
+ int OfsZ = static_cast<int>(r1.randInt(3) + r1.randInt(3) + r1.randInt(3) + r1.randInt(3)) / 2 - 3;
BLOCKTYPE Ground = GetBlock(a_BlockX + OfsX, a_BlockY + OfsY, a_BlockZ + OfsZ);
if (Ground != E_BLOCK_GRASS)
{
@@ -2374,6 +2380,8 @@ void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
void cWorld::QueueSetChunkData(const cSetChunkDataPtr & a_SetChunkData)
{
+ ASSERT(IsChunkQueued(a_SetChunkData->GetChunkX(), a_SetChunkData->GetChunkZ()));
+
// Validate biomes, if needed:
if (!a_SetChunkData->AreBiomesValid())
{
@@ -2424,7 +2432,7 @@ void cWorld::SetChunkData(cSetChunkData & a_SetChunkData)
// Save the chunk right after generating, so that we don't have to generate it again on next run
if (a_SetChunkData.ShouldMarkDirty())
{
- m_Storage.QueueSaveChunk(ChunkX, 0, ChunkZ);
+ m_Storage.QueueSaveChunk(ChunkX, ChunkZ);
}
}
@@ -2463,6 +2471,15 @@ bool cWorld::GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockT
+bool cWorld::IsChunkQueued(int a_ChunkX, int a_ChunkZ) const
+{
+ return m_ChunkMap->IsChunkQueued(a_ChunkX, a_ChunkZ);
+}
+
+
+
+
+
bool cWorld::IsChunkValid(int a_ChunkX, int a_ChunkZ) const
{
return m_ChunkMap->IsChunkValid(a_ChunkX, a_ChunkZ);
@@ -2696,6 +2713,15 @@ bool cWorld::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback &
+bool cWorld::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback)
+{
+ return m_ChunkMap->ForEachEntityInBox(a_Box, a_Callback);
+}
+
+
+
+
+
bool cWorld::DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback)
{
return m_ChunkMap->DoWithEntityByID(a_UniqueID, a_Callback);
@@ -2769,36 +2795,18 @@ void cWorld::RemoveClientFromChunkSender(cClientHandle * a_Client)
-void cWorld::TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
-{
- m_ChunkMap->TouchChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
-}
-
-
-
-
-
-bool cWorld::LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
-{
- return m_ChunkMap->LoadChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
-}
-
-
-
-
-
-void cWorld::LoadChunks(const cChunkCoordsList & a_Chunks)
+void cWorld::TouchChunk(int a_ChunkX, int a_ChunkZ)
{
- m_ChunkMap->LoadChunks(a_Chunks);
+ m_ChunkMap->TouchChunk(a_ChunkX, a_ChunkZ);
}
-void cWorld::ChunkLoadFailed(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cWorld::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
{
- m_ChunkMap->ChunkLoadFailed(a_ChunkX, a_ChunkY, a_ChunkZ);
+ m_ChunkMap->ChunkLoadFailed(a_ChunkX, a_ChunkZ);
}
@@ -2842,7 +2850,7 @@ bool cWorld::SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, co
{
AString m_Command;
public:
- cUpdateCommandBlock(const AString & a_Command) : m_Command(a_Command) {}
+ cUpdateCommandBlock(const AString & a_CallbackCommand) : m_Command(a_CallbackCommand) {}
virtual bool Item(cCommandBlockEntity * a_CommandBlock) override
{
@@ -2903,8 +2911,7 @@ void cWorld::RegenerateChunk(int a_ChunkX, int a_ChunkZ)
{
m_ChunkMap->MarkChunkRegenerating(a_ChunkX, a_ChunkZ);
- // Trick: use Y=1 to force the chunk generation even though the chunk data is already present
- m_Generator.QueueGenerateChunk(a_ChunkX, 1, a_ChunkZ);
+ m_Generator.QueueGenerateChunk(a_ChunkX, a_ChunkZ, true);
}
@@ -2913,7 +2920,7 @@ void cWorld::RegenerateChunk(int a_ChunkX, int a_ChunkZ)
void cWorld::GenerateChunk(int a_ChunkX, int a_ChunkZ)
{
- m_Generator.QueueGenerateChunk(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ m_Generator.QueueGenerateChunk(a_ChunkX, a_ChunkZ, false);
}
@@ -3318,20 +3325,26 @@ cFluidSimulator * cWorld::InitializeFluidSimulator(cIniFile & a_IniFile, const c
int Falloff = a_IniFile.GetValueSetI(SimulatorSectionName, "Falloff", IsWater ? 1 : 2);
int TickDelay = a_IniFile.GetValueSetI(SimulatorSectionName, "TickDelay", IsWater ? 5 : 30);
int NumNeighborsForSource = a_IniFile.GetValueSetI(SimulatorSectionName, "NumNeighborsForSource", IsWater ? 2 : -1);
+
+ if ((Falloff > 15) || (Falloff < 0))
+ {
+ LOGWARNING("Falloff for %s simulator is out of range, assuming default of %d", a_FluidName, IsWater ? 1 : 2);
+ Falloff = IsWater ? 1 : 2;
+ }
if (NoCaseCompare(SimulatorName, "floody") == 0)
{
- res = new cFloodyFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, Falloff, TickDelay, NumNeighborsForSource);
+ res = new cFloodyFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, static_cast<NIBBLETYPE>(Falloff), TickDelay, NumNeighborsForSource);
}
else if (NoCaseCompare(SimulatorName, "vanilla") == 0)
{
- res = new cVanillaFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, Falloff, TickDelay, NumNeighborsForSource);
+ res = new cVanillaFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, static_cast<NIBBLETYPE>(Falloff), TickDelay, NumNeighborsForSource);
}
else
{
// The simulator name doesn't match anything we have, issue a warning:
LOGWARNING("%s [Physics]:%s specifies an unknown simulator, using the default \"Vanilla\".", GetIniFileName().c_str(), SimulatorNameKey.c_str());
- res = new cVanillaFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, Falloff, TickDelay, NumNeighborsForSource);
+ res = new cVanillaFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, static_cast<NIBBLETYPE>(Falloff), TickDelay, NumNeighborsForSource);
}
}
@@ -3441,9 +3454,9 @@ void cWorld::cTaskSendBlockToAllPlayers::Run(cWorld & a_World)
public cPlayerListCallback
{
public:
- cPlayerCallback(std::vector<Vector3i> & a_SendQueue, cWorld & a_World) :
+ cPlayerCallback(std::vector<Vector3i> & a_SendQueue, cWorld & a_CallbackWorld) :
m_SendQueue(a_SendQueue),
- m_World(a_World)
+ m_World(a_CallbackWorld)
{
}
@@ -3512,6 +3525,15 @@ bool cWorld::cChunkGeneratorCallbacks::IsChunkValid(int a_ChunkX, int a_ChunkZ)
+bool cWorld::cChunkGeneratorCallbacks::IsChunkQueued(int a_ChunkX, int a_ChunkZ)
+{
+ return m_World->IsChunkQueued(a_ChunkX, a_ChunkZ);
+}
+
+
+
+
+
bool cWorld::cChunkGeneratorCallbacks::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ)
{
return m_World->HasChunkAnyClients(a_ChunkX, a_ChunkZ);
diff --git a/src/World.h b/src/World.h
index 578c9682b..274bd2dcf 100644
--- a/src/World.h
+++ b/src/World.h
@@ -157,14 +157,14 @@ public:
}
virtual Int64 GetWorldAge (void) const override { return m_WorldAge; }
- virtual Int64 GetTimeOfDay(void) const override { return m_TimeOfDay; }
+ virtual int GetTimeOfDay(void) const override { return m_TimeOfDay; }
void SetTicksUntilWeatherChange(int a_WeatherInterval)
{
m_WeatherInterval = a_WeatherInterval;
}
- virtual void SetTimeOfDay(Int64 a_TimeOfDay) override
+ virtual void SetTimeOfDay(int a_TimeOfDay) override
{
m_TimeOfDay = a_TimeOfDay;
m_TimeOfDaySecs = (double)a_TimeOfDay / 20.0;
@@ -279,7 +279,12 @@ public:
/** Gets the chunk's blocks, only the block types */
bool GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockTypes);
- bool IsChunkValid (int a_ChunkX, int a_ChunkZ) const;
+ /** Returns true iff the chunk is in the loader / generator queue. */
+ bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) const;
+
+ /** Returns true iff the chunk is present and valid. */
+ bool IsChunkValid(int a_ChunkX, int a_ChunkZ) const;
+
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const;
/** Queues a task to unload unused chunks onto the tick thread. The prefferred way of unloading*/
@@ -324,6 +329,11 @@ public:
/** Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
+ /** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox.
+ Returns true if all entities processed, false if the callback aborted by returning true.
+ If any chunk in the box is missing, ignores the entities in that chunk silently. */
+ bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
+
/** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false. */
bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
@@ -351,16 +361,10 @@ public:
void RemoveClientFromChunkSender(cClientHandle * a_Client);
/** Touches the chunk, causing it to be loaded or generated */
- void TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
-
- /** Loads the chunk, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before) */
- bool LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
-
- /** Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid() */
- void LoadChunks(const cChunkCoordsList & a_Chunks);
+ void TouchChunk(int a_ChunkX, int a_ChunkZ);
/** Marks the chunk as failed-to-load: */
- void ChunkLoadFailed(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
/** Sets the sign text, asking plugins for permission first. a_Player is the player who this change belongs to, may be NULL. Returns true if sign text changed. Same as UpdateSign() */
bool SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player = NULL); // Exported in ManualBindings.cpp
@@ -380,7 +384,7 @@ public:
/** Regenerate the given chunk: */
void RegenerateChunk(int a_ChunkX, int a_ChunkZ); // tolua_export
- /** Generates the given chunk, if not already generated */
+ /** Generates the given chunk */
void GenerateChunk(int a_ChunkX, int a_ChunkZ); // tolua_export
/** Queues a chunk for lighting; a_Callback is called after the chunk is lighted */
@@ -817,6 +821,7 @@ private:
virtual void OnChunkGenerated (cChunkDesc & a_ChunkDesc) override;
virtual bool IsChunkValid (int a_ChunkX, int a_ChunkZ) override;
virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) override;
+ virtual bool IsChunkQueued (int a_ChunkX, int a_ChunkZ) override;
// cPluginInterface overrides:
virtual void CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) override;
@@ -883,7 +888,7 @@ private:
double m_WorldAgeSecs; // World age, in seconds. Is only incremented, cannot be set by plugins.
double m_TimeOfDaySecs; // Time of day in seconds. Can be adjusted. Is wrapped to zero each day.
Int64 m_WorldAge; // World age in ticks, calculated off of m_WorldAgeSecs
- Int64 m_TimeOfDay; // Time in ticks, calculated off of m_TimeOfDaySecs
+ int m_TimeOfDay; // Time in ticks, calculated off of m_TimeOfDaySecs
Int64 m_LastTimeUpdate; // The tick in which the last time update has been sent.
Int64 m_LastUnload; // The last WorldAge (in ticks) in which unloading was triggerred
Int64 m_LastSave; // The last WorldAge (in ticks) in which save-all was triggerred
diff --git a/src/WorldStorage/ScoreboardSerializer.cpp b/src/WorldStorage/ScoreboardSerializer.cpp
index da8236e0d..e30eecf67 100644
--- a/src/WorldStorage/ScoreboardSerializer.cpp
+++ b/src/WorldStorage/ScoreboardSerializer.cpp
@@ -283,37 +283,37 @@ bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT)
bool AllowsFriendlyFire = true, CanSeeFriendlyInvisible = false;
int CurrLine = a_NBT.FindChildByName(Child, "Name");
- if (CurrLine >= 0)
+ if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
{
- Name = a_NBT.GetInt(CurrLine);
+ Name = a_NBT.GetString(CurrLine);
}
CurrLine = a_NBT.FindChildByName(Child, "DisplayName");
- if (CurrLine >= 0)
+ if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
{
- DisplayName = a_NBT.GetInt(CurrLine);
+ DisplayName = a_NBT.GetString(CurrLine);
}
CurrLine = a_NBT.FindChildByName(Child, "Prefix");
- if (CurrLine >= 0)
+ if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
{
- Prefix = a_NBT.GetInt(CurrLine);
+ Prefix = a_NBT.GetString(CurrLine);
}
CurrLine = a_NBT.FindChildByName(Child, "Suffix");
- if (CurrLine >= 0)
+ if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
{
- Suffix = a_NBT.GetInt(CurrLine);
+ Suffix = a_NBT.GetString(CurrLine);
}
CurrLine = a_NBT.FindChildByName(Child, "AllowFriendlyFire");
- if (CurrLine >= 0)
+ if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int))
{
AllowsFriendlyFire = (a_NBT.GetInt(CurrLine) != 0);
}
CurrLine = a_NBT.FindChildByName(Child, "SeeFriendlyInvisibles");
- if (CurrLine >= 0)
+ if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int))
{
CanSeeFriendlyInvisible = (a_NBT.GetInt(CurrLine) != 0);
}
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index e79cc291d..fe309ce4e 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -66,8 +66,17 @@ Since only the header is actually in the memory, this number can be high, but st
*/
#define MAX_MCA_FILES 32
-/// The maximum size of an inflated chunk; raw chunk data is 192 KiB, allow 64 KiB more of entities
-#define CHUNK_INFLATE_MAX 256 KiB
+#define LOAD_FAILED(CHX, CHZ) \
+ { \
+ const int RegionX = FAST_FLOOR_DIV(CHX, 32); \
+ const int RegionZ = FAST_FLOOR_DIV(CHZ, 32); \
+ LOGERROR("%s (%d): Loading chunk [%d, %d] from file r.%d.%d.mca failed. " \
+ "The server will now abort in order to avoid further data loss. " \
+ "Please add the reported file and this message to the issue report.", \
+ __FUNCTION__, __LINE__, CHX, CHZ, RegionX, RegionZ \
+ ); \
+ *((volatile int *)0) = 0; /* Crash intentionally */ \
+ }
@@ -248,29 +257,22 @@ cWSSAnvil::cMCAFile * cWSSAnvil::LoadMCAFile(const cChunkCoords & a_Chunk)
bool cWSSAnvil::LoadChunkFromData(const cChunkCoords & a_Chunk, const AString & a_Data)
{
- // Decompress the data:
- char Uncompressed[CHUNK_INFLATE_MAX];
- z_stream strm;
- strm.zalloc = (alloc_func)NULL;
- strm.zfree = (free_func)NULL;
- strm.opaque = NULL;
- inflateInit(&strm);
- strm.next_out = (Bytef *)Uncompressed;
- strm.avail_out = sizeof(Uncompressed);
- strm.next_in = (Bytef *)a_Data.data();
- strm.avail_in = (uInt)a_Data.size();
- int res = inflate(&strm, Z_FINISH);
- inflateEnd(&strm);
- if (res != Z_STREAM_END)
+ // Uncompress the data:
+ AString Uncompressed;
+ int res = InflateString(a_Data.data(), a_Data.size(), Uncompressed);
+ if (res != Z_OK)
{
+ LOGWARNING("Uncompressing chunk [%d, %d] failed: %d", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, res);
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
// Parse the NBT data:
- cParsedNBT NBT(Uncompressed, strm.total_out);
+ cParsedNBT NBT(Uncompressed.data(), Uncompressed.size());
if (!NBT.IsValid())
{
// NBT Parsing failed
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
@@ -317,11 +319,19 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
int Level = a_NBT.FindChildByName(0, "Level");
if (Level < 0)
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
int Sections = a_NBT.FindChildByName(Level, "Sections");
- if ((Sections < 0) || (a_NBT.GetType(Sections) != TAG_List) || (a_NBT.GetChildrenType(Sections) != TAG_Compound))
+ if ((Sections < 0) || (a_NBT.GetType(Sections) != TAG_List))
+ {
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
+ return false;
+ }
+ eTagType SectionsType = a_NBT.GetChildrenType(Sections);
+ if ((SectionsType != TAG_Compound) && (SectionsType != TAG_End))
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
for (int Child = a_NBT.GetFirstChild(Sections); Child >= 0; Child = a_NBT.GetNextSibling(Child))
@@ -585,7 +595,7 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
// Get the BlockEntity's position
int x, y, z;
- if (!GetBlockEntityNBTPos(a_NBT, Child, x, y, z))
+ if (!GetBlockEntityNBTPos(a_NBT, Child, x, y, z) || (y < 0) || (y >= cChunkDef::Height))
{
LOGWARNING("Bad block entity, missing the coords. Will be ignored.");
continue;
@@ -613,6 +623,8 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
cBlockEntity * cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int a_Tag, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
+ ASSERT((a_BlockY >= 0) && (a_BlockY < cChunkDef::Height));
+
// Load the specific BlockEntity type:
switch (a_BlockType)
{
@@ -2811,30 +2823,42 @@ bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, AString & a
}
unsigned ChunkLocation = ntohl(m_Header[LocalX + 32 * LocalZ]);
unsigned ChunkOffset = ChunkLocation >> 8;
+ if (ChunkOffset < 2)
+ {
+ return false;
+ }
m_File.Seek((int)ChunkOffset * 4096);
int ChunkSize = 0;
if (m_File.Read(&ChunkSize, 4) != 4)
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
ChunkSize = ntohl((u_long)ChunkSize);
char CompressionType = 0;
if (m_File.Read(&CompressionType, 1) != 1)
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
if (CompressionType != 2)
{
// Chunk is in an unknown compression
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
ChunkSize--;
// HACK: This depends on the internal knowledge that AString's data() function returns the internal buffer directly
a_Data.assign(ChunkSize, '\0');
- return (m_File.Read((void *)a_Data.data(), ChunkSize) == ChunkSize);
+ if (m_File.Read((void *)a_Data.data(), ChunkSize) == ChunkSize)
+ {
+ return true;
+ }
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
+ return false;
}
@@ -2889,7 +2913,13 @@ bool cWSSAnvil::cMCAFile::SetChunkData(const cChunkCoords & a_Chunk, const AStri
// Store the header:
ChunkSize = ((u_long)a_Data.size() + MCA_CHUNK_HEADER_LENGTH + 4095) / 4096; // Round data size *up* to nearest 4KB sector, make it a sector number
- ASSERT(ChunkSize < 256);
+ if (ChunkSize > 255)
+ {
+ LOGWARNING("Cannot save chunk [%d, %d], the data is too large (%u KiB, maximum is 1024 KiB). Remove some entities and retry.",
+ a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, (unsigned)(ChunkSize * 4)
+ );
+ return false;
+ }
m_Header[LocalX + 32 * LocalZ] = htonl((ChunkSector << 8) | ChunkSize);
if (m_File.Seek(0) < 0)
{
diff --git a/src/WorldStorage/WSSCompact.cpp b/src/WorldStorage/WSSCompact.cpp
index 58f9e3cab..6760186b2 100644
--- a/src/WorldStorage/WSSCompact.cpp
+++ b/src/WorldStorage/WSSCompact.cpp
@@ -980,7 +980,7 @@ bool cWSSCompact::cPAKFile::SaveChunkToData(const cChunkCoords & a_Chunk, cWorld
if (!a_World->GetChunkData(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, Serializer))
{
// Chunk not valid
- LOG("cWSSCompact: Trying to save chunk [%d, %d, %d] that has no data, ignoring request.", a_Chunk.m_ChunkX, a_Chunk.m_ChunkY, a_Chunk.m_ChunkZ);
+ LOG("cWSSCompact: Trying to save chunk [%d, %d] that has no data, ignoring request.", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
@@ -999,7 +999,7 @@ bool cWSSCompact::cPAKFile::SaveChunkToData(const cChunkCoords & a_Chunk, cWorld
int errorcode = CompressString(Data.data(), Data.size(), CompressedData, m_CompressionFactor);
if (errorcode != Z_OK)
{
- LOGERROR("Error %i compressing data for chunk [%d, %d, %d]", errorcode, a_Chunk.m_ChunkX, a_Chunk.m_ChunkY, a_Chunk.m_ChunkZ);
+ LOGERROR("Error %i compressing data for chunk [%d, %d]", errorcode, a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
@@ -1010,7 +1010,7 @@ bool cWSSCompact::cPAKFile::SaveChunkToData(const cChunkCoords & a_Chunk, cWorld
sChunkHeader * Header = new sChunkHeader;
if (Header == NULL)
{
- LOGWARNING("Cannot create a new chunk header to save chunk [%d, %d, %d]", a_Chunk.m_ChunkX, a_Chunk.m_ChunkY, a_Chunk.m_ChunkZ);
+ LOGWARNING("Cannot create a new chunk header to save chunk [%d, %d]", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
Header->m_CompressedSize = (int)CompressedData.size();
diff --git a/src/WorldStorage/WorldStorage.cpp b/src/WorldStorage/WorldStorage.cpp
index 707e8f929..179cf9393 100644
--- a/src/WorldStorage/WorldStorage.cpp
+++ b/src/WorldStorage/WorldStorage.cpp
@@ -141,9 +141,11 @@ size_t cWorldStorage::GetSaveQueueLength(void)
-void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate)
+void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkZ)
{
- m_LoadQueue.EnqueueItem(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ, a_Generate));
+ ASSERT(m_World->IsChunkQueued(a_ChunkX, a_ChunkZ));
+
+ m_LoadQueue.EnqueueItem(cChunkCoords(a_ChunkX, a_ChunkZ));
m_Event.Set();
}
@@ -151,9 +153,11 @@ void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, boo
-void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkZ)
{
- m_SaveQueue.EnqueueItemIfNotPresent(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
+ ASSERT(m_World->IsChunkValid(a_ChunkX, a_ChunkZ));
+
+ m_SaveQueue.EnqueueItemIfNotPresent(cChunkCoords(a_ChunkX, a_ChunkZ));
m_Event.Set();
}
@@ -161,9 +165,9 @@ void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
-void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkZ)
{
- m_LoadQueue.Remove(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ, true));
+ m_LoadQueue.Remove(cChunkCoords(a_ChunkX, a_ChunkZ));
}
@@ -242,22 +246,14 @@ void cWorldStorage::Execute(void)
bool cWorldStorage::LoadOneChunk(void)
{
- sChunkLoad ToLoad(0, 0, 0, false);
+ cChunkCoords ToLoad(0, 0);
bool ShouldLoad = m_LoadQueue.TryDequeueItem(ToLoad);
- if (ShouldLoad && !LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ))
+
+ if (ShouldLoad)
{
- if (ToLoad.m_Generate)
- {
- // The chunk couldn't be loaded, generate it:
- m_World->GetGenerator().QueueGenerateChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ);
- }
- else
- {
- // TODO: Notify the world that the load has failed:
- // m_World->ChunkLoadFailed(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ);
- }
+ return LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkZ);
}
- return ShouldLoad;
+ return false;
}
@@ -266,7 +262,7 @@ bool cWorldStorage::LoadOneChunk(void)
bool cWorldStorage::SaveOneChunk(void)
{
- cChunkCoords ToSave(0, 0, 0);
+ cChunkCoords ToSave(0, 0);
bool ShouldSave = m_SaveQueue.TryDequeueItem(ToSave);
if (ShouldSave && m_World->IsChunkValid(ToSave.m_ChunkX, ToSave.m_ChunkZ))
{
@@ -283,15 +279,11 @@ bool cWorldStorage::SaveOneChunk(void)
-bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkZ)
{
- if (m_World->IsChunkValid(a_ChunkX, a_ChunkZ))
- {
- // Already loaded (can happen, since the queue is async)
- return true;
- }
+ ASSERT(m_World->IsChunkQueued(a_ChunkX, a_ChunkZ));
- cChunkCoords Coords(a_ChunkX, a_ChunkY, a_ChunkZ);
+ cChunkCoords Coords(a_ChunkX, a_ChunkZ);
// First try the schema that is used for saving
if (m_SaveSchema->LoadChunk(Coords))
@@ -309,7 +301,7 @@ bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
}
// Notify the chunk owner that the chunk failed to load (sets cChunk::m_HasLoadFailed to true):
- m_World->ChunkLoadFailed(a_ChunkX, a_ChunkY, a_ChunkZ);
+ m_World->ChunkLoadFailed(a_ChunkX, a_ChunkZ);
return false;
}
diff --git a/src/WorldStorage/WorldStorage.h b/src/WorldStorage/WorldStorage.h
index dd07ecb64..fc7e9f84c 100644
--- a/src/WorldStorage/WorldStorage.h
+++ b/src/WorldStorage/WorldStorage.h
@@ -64,13 +64,10 @@ public:
cWorldStorage(void);
~cWorldStorage();
- void QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate); // Queues the chunk for loading; if not loaded, the chunk will be generated if a_Generate is true
- void QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void QueueLoadChunk(int a_ChunkX, int a_ChunkZ);
+ void QueueSaveChunk(int a_ChunkX, int a_ChunkZ);
- /// Loads the chunk specified; returns true on success, false on failure
- bool LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
-
- void UnqueueLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void UnqueueLoad(int a_ChunkX, int a_ChunkZ);
void UnqueueSave(const cChunkCoords & a_Chunk);
bool Start(cWorld * a_World, const AString & a_StorageSchemaName, int a_StorageCompressionFactor); // Hide the cIsThread's Start() method, we need to provide args
@@ -84,40 +81,10 @@ public:
protected:
- struct sChunkLoad
- {
- int m_ChunkX;
- int m_ChunkY;
- int m_ChunkZ;
- bool m_Generate; // If true, the chunk will be generated if it cannot be loaded
-
- sChunkLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate) : m_ChunkX(a_ChunkX), m_ChunkY(a_ChunkY), m_ChunkZ(a_ChunkZ), m_Generate(a_Generate) {}
-
- bool operator ==(const sChunkLoad other) const
- {
- return (
- (this->m_ChunkX == other.m_ChunkX) &&
- (this->m_ChunkY == other.m_ChunkY) &&
- (this->m_ChunkZ == other.m_ChunkZ)
- );
- }
- } ;
-
- struct FuncTable
- {
- static void Delete(sChunkLoad) {}
- static void Combine(sChunkLoad & a_orig, const sChunkLoad a_new)
- {
- a_orig.m_Generate |= a_new.m_Generate;
- }
- };
-
- typedef cQueue<sChunkLoad, FuncTable> sChunkLoadQueue;
-
cWorld * m_World;
AString m_StorageSchemaName;
- sChunkLoadQueue m_LoadQueue;
+ cChunkCoordsQueue m_LoadQueue;
cChunkCoordsQueue m_SaveQueue;
/// All the storage schemas (all used for loading)
@@ -125,7 +92,11 @@ protected:
/// The one storage schema used for saving
cWSSchema * m_SaveSchema;
+
+ /// Loads the chunk specified; returns true on success, false on failure
+ bool LoadChunk(int a_ChunkX, int a_ChunkZ);
+
void InitSchemas(int a_StorageCompressionFactor);
virtual void Execute(void) override;