Unify DoWithBlockEntity (#5168)
+ DoWith calls now broadcast the block entity and mark the chunk dirty + Add block entity change queue to synchronise BE updates with block updates * Fixed a few incorrect assertions about BE type - Remove manual overloads
This commit is contained in:
parent
5123850db0
commit
748b121703
@ -211,228 +211,6 @@ public:
|
||||
|
||||
|
||||
|
||||
/** Template for the bindings for the DoWithXYZAt(X, Y, Z) functions that don't need to check their coords. */
|
||||
template <
|
||||
class SELF,
|
||||
class ITEM,
|
||||
bool (SELF::*DoWithFn)(int, int, int, cFunctionRef<bool(ITEM &)>)
|
||||
>
|
||||
static int DoWithXYZ(lua_State * tolua_S)
|
||||
{
|
||||
// Check params:
|
||||
cLuaState L(tolua_S);
|
||||
if (
|
||||
!L.CheckParamNumber(2, 4) ||
|
||||
!L.CheckParamFunction(5) ||
|
||||
!L.CheckParamEnd(6)
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get parameters:
|
||||
SELF * Self = nullptr;
|
||||
int BlockX = 0;
|
||||
int BlockY = 0;
|
||||
int BlockZ = 0;
|
||||
cLuaState::cRef FnRef;
|
||||
L.GetStackValues(1, Self, BlockX, BlockY, BlockZ, FnRef);
|
||||
if (Self == nullptr)
|
||||
{
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
|
||||
}
|
||||
if (!FnRef.IsValid())
|
||||
{
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #5");
|
||||
}
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, [&](ITEM & a_Item)
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Template for the bindings for the DoWithXYZAt(X, Y, Z) functions that need to check their coords. */
|
||||
template <
|
||||
class SELF,
|
||||
class ITEM,
|
||||
bool (SELF::*DoWithFn)(int, int, int, cFunctionRef<bool(ITEM &)>),
|
||||
bool (SELF::*CoordCheckFn)(int, int, int) const
|
||||
>
|
||||
static int DoWithXYZ(lua_State * tolua_S)
|
||||
{
|
||||
// Check params:
|
||||
cLuaState L(tolua_S);
|
||||
if (
|
||||
!L.CheckParamNumber(2, 4) ||
|
||||
!L.CheckParamFunction(5) ||
|
||||
!L.CheckParamEnd(6)
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get parameters:
|
||||
SELF * Self = nullptr;
|
||||
int BlockX = 0;
|
||||
int BlockY = 0;
|
||||
int BlockZ = 0;
|
||||
cLuaState::cRef FnRef;
|
||||
L.GetStackValues(1, Self, BlockX, BlockY, BlockZ, FnRef);
|
||||
if (Self == nullptr)
|
||||
{
|
||||
return L.ApiParamError("Invalid 'self'");
|
||||
}
|
||||
if (!FnRef.IsValid())
|
||||
{
|
||||
return L.ApiParamError("Expected a valid callback function for parameter #5");
|
||||
}
|
||||
if (!(Self->*CoordCheckFn)(BlockX, BlockY, BlockZ))
|
||||
{
|
||||
return L.FApiParamError("The provided coordinates ({0}) are not valid",
|
||||
Vector3i{BlockX, BlockY, BlockZ}
|
||||
);
|
||||
}
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, [&](ITEM & a_Item)
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <
|
||||
class Ty1,
|
||||
class Ty2,
|
||||
bool (Ty1::*ForEachFn)(int, int, cFunctionRef<bool(Ty2 &)>)
|
||||
>
|
||||
static int ForEachInChunk(lua_State * tolua_S)
|
||||
{
|
||||
// Check params:
|
||||
cLuaState L(tolua_S);
|
||||
if (
|
||||
!L.CheckParamNumber(2, 3) ||
|
||||
!L.CheckParamFunction(4) ||
|
||||
!L.CheckParamEnd(5)
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get parameters:
|
||||
Ty1 * Self = nullptr;
|
||||
int ChunkX = 0;
|
||||
int ChunkZ = 0;
|
||||
cLuaState::cRef FnRef;
|
||||
L.GetStackValues(1, Self, ChunkX, ChunkZ, FnRef);
|
||||
if (Self == nullptr)
|
||||
{
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
|
||||
}
|
||||
if (!FnRef.IsValid())
|
||||
{
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #4");
|
||||
}
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*ForEachFn)(ChunkX, ChunkZ, [&](Ty2 & a_Item)
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <
|
||||
class Ty1,
|
||||
class Ty2,
|
||||
bool (Ty1::*ForEachFn)(const cBoundingBox &, cFunctionRef<bool(Ty2 &)>)
|
||||
>
|
||||
static int 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 = nullptr;
|
||||
cBoundingBox * Box = nullptr;
|
||||
cLuaState::cRef FnRef;
|
||||
L.GetStackValues(1, Self, Box, FnRef);
|
||||
if ((Self == nullptr) || (Box == nullptr))
|
||||
{
|
||||
LOGWARNING("Invalid world (%p) or boundingbox (%p)", static_cast<void *>(Self), static_cast<void *>(Box));
|
||||
L.LogStackTrace();
|
||||
return 0;
|
||||
}
|
||||
if (!FnRef.IsValid())
|
||||
{
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2");
|
||||
}
|
||||
|
||||
bool res = (Self->*ForEachFn)(*Box, [&](Ty2 & a_Item)
|
||||
{
|
||||
bool ret = false;
|
||||
if (!L.Call(FnRef, &a_Item, cLuaState::Return, ret))
|
||||
{
|
||||
LOGWARNING("Failed to call Lua callback");
|
||||
L.LogStackTrace();
|
||||
return true; // Abort enumeration
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <
|
||||
class Ty1,
|
||||
class Ty2,
|
||||
|
@ -15,6 +15,66 @@
|
||||
|
||||
|
||||
|
||||
/** Template for the bindings for the DoWithXYZAt(X, Y, Z) functions that need to check their coords. */
|
||||
template <
|
||||
class SELF,
|
||||
class ITEM,
|
||||
bool (SELF::*DoWithFn)(int, int, int, cFunctionRef<bool(ITEM &)>),
|
||||
bool (SELF::*CoordCheckFn)(int, int, int) const
|
||||
>
|
||||
static int DoWithXYZ(lua_State * tolua_S)
|
||||
{
|
||||
// Check params:
|
||||
cLuaState L(tolua_S);
|
||||
if (
|
||||
!L.CheckParamNumber(2, 4) ||
|
||||
!L.CheckParamFunction(5) ||
|
||||
!L.CheckParamEnd(6)
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get parameters:
|
||||
SELF * Self = nullptr;
|
||||
int BlockX = 0;
|
||||
int BlockY = 0;
|
||||
int BlockZ = 0;
|
||||
cLuaState::cRef FnRef;
|
||||
L.GetStackValues(1, Self, BlockX, BlockY, BlockZ, FnRef);
|
||||
if (Self == nullptr)
|
||||
{
|
||||
return L.ApiParamError("Invalid 'self'");
|
||||
}
|
||||
if (!FnRef.IsValid())
|
||||
{
|
||||
return L.ApiParamError("Expected a valid callback function for parameter #5");
|
||||
}
|
||||
if (!(Self->*CoordCheckFn)(BlockX, BlockY, BlockZ))
|
||||
{
|
||||
return L.FApiParamError("The provided coordinates ({0}) are not valid",
|
||||
Vector3i{BlockX, BlockY, BlockZ}
|
||||
);
|
||||
}
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, [&](ITEM & a_Item)
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Reads params that together form a Cuboid.
|
||||
These can be:
|
||||
- 6 numbers (MinX, MaxX, MinY, MaxY, MinZ, MaxZ)
|
||||
|
@ -12,6 +12,23 @@
|
||||
#include "PluginLua.h"
|
||||
#include "LuaChunkStay.h"
|
||||
|
||||
#include "BlockEntities/BeaconEntity.h"
|
||||
#include "BlockEntities/BedEntity.h"
|
||||
#include "BlockEntities/BrewingstandEntity.h"
|
||||
#include "BlockEntities/ChestEntity.h"
|
||||
#include "BlockEntities/CommandBlockEntity.h"
|
||||
#include "BlockEntities/DispenserEntity.h"
|
||||
#include "BlockEntities/DropSpenserEntity.h"
|
||||
#include "BlockEntities/DropperEntity.h"
|
||||
#include "BlockEntities/FlowerPotEntity.h"
|
||||
#include "BlockEntities/FurnaceEntity.h"
|
||||
#include "BlockEntities/HopperEntity.h"
|
||||
#include "BlockEntities/MobHeadEntity.h"
|
||||
#include "BlockEntities/NoteEntity.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Check that a Lua parameter is either a vector or 3 numbers in sequence
|
||||
\param L The Lua state
|
||||
@ -50,6 +67,183 @@ static bool GetStackVectorOr3Numbers(cLuaState & L, int a_Index, Vector3<T> & a_
|
||||
|
||||
|
||||
|
||||
/** Template for the bindings for the DoWithXYZAt(X, Y, Z) functions that don't need to check their coords. */
|
||||
template <class BlockEntityType, BLOCKTYPE... BlockTypes>
|
||||
static int DoWithBlockEntityAt(lua_State * tolua_S)
|
||||
{
|
||||
cLuaState L(tolua_S);
|
||||
int OffsetIndex;
|
||||
|
||||
// Check params:
|
||||
if (
|
||||
!L.CheckParamSelf("cWorld") ||
|
||||
!CheckParamVectorOr3Numbers(L, "Vector3<int>", 2, OffsetIndex) ||
|
||||
!L.CheckParamFunction(OffsetIndex) ||
|
||||
!L.CheckParamEnd(OffsetIndex + 1)
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cWorld * Self = nullptr;
|
||||
Vector3i Position;
|
||||
cLuaState::cRef FnRef;
|
||||
|
||||
// Get parameters:
|
||||
if (
|
||||
!L.GetStackValues(1, Self) ||
|
||||
!GetStackVectorOr3Numbers(L, 2, Position) ||
|
||||
!L.GetStackValues(OffsetIndex, FnRef)
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Self == nullptr)
|
||||
{
|
||||
return L.ApiParamError("Invalid 'self'");
|
||||
}
|
||||
if (!FnRef.IsValid())
|
||||
{
|
||||
return L.ApiParamError("Expected a valid callback function for parameter %i", OffsetIndex);
|
||||
}
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = Self->DoWithBlockEntityAt(Position, [&L, &FnRef](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
if constexpr (sizeof...(BlockTypes) != 0)
|
||||
{
|
||||
if (((a_BlockEntity.GetBlockType() != BlockTypes) && ...))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
L.Call(FnRef, static_cast<BlockEntityType *>(&a_BlockEntity), cLuaState::Return, ret);
|
||||
return ret;
|
||||
});
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <
|
||||
class Ty1,
|
||||
class Ty2,
|
||||
bool (Ty1::*ForEachFn)(const cBoundingBox &, cFunctionRef<bool(Ty2 &)>)
|
||||
>
|
||||
static int 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 = nullptr;
|
||||
cBoundingBox * Box = nullptr;
|
||||
cLuaState::cRef FnRef;
|
||||
L.GetStackValues(1, Self, Box, FnRef);
|
||||
if ((Self == nullptr) || (Box == nullptr))
|
||||
{
|
||||
return L.ApiParamError("Invalid world (%p) or boundingbox (%p)", static_cast<void *>(Self), static_cast<void *>(Box));
|
||||
}
|
||||
if (!FnRef.IsValid())
|
||||
{
|
||||
return L.ApiParamError("Expected a valid callback function for parameter #2");
|
||||
}
|
||||
|
||||
bool res = (Self->*ForEachFn)(*Box, [&](Ty2 & a_Item)
|
||||
{
|
||||
bool ret = false;
|
||||
if (!L.Call(FnRef, &a_Item, cLuaState::Return, ret))
|
||||
{
|
||||
LOGWARNING("Failed to call Lua callback");
|
||||
L.LogStackTrace();
|
||||
return true; // Abort enumeration
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <class BlockEntityType, BLOCKTYPE... BlockTypes>
|
||||
static int ForEachBlockEntityInChunk(lua_State * tolua_S)
|
||||
{
|
||||
// Check params:
|
||||
cLuaState L(tolua_S);
|
||||
if (
|
||||
!L.CheckParamSelf("cWorld") ||
|
||||
!L.CheckParamNumber(2, 3) ||
|
||||
!L.CheckParamFunction(4) ||
|
||||
!L.CheckParamEnd(5)
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get parameters:
|
||||
cWorld * Self = nullptr;
|
||||
int ChunkX = 0;
|
||||
int ChunkZ = 0;
|
||||
cLuaState::cRef FnRef;
|
||||
L.GetStackValues(1, Self, ChunkX, ChunkZ, FnRef);
|
||||
if (Self == nullptr)
|
||||
{
|
||||
return L.ApiParamError("Error in function call '#funcname#': Invalid 'self'");
|
||||
}
|
||||
if (!FnRef.IsValid())
|
||||
{
|
||||
return L.ApiParamError("Expected a valid callback function for parameter #4");
|
||||
}
|
||||
|
||||
// Call the ForEach function:
|
||||
bool res = Self->ForEachBlockEntityInChunk(ChunkX, ChunkZ, [&L, &FnRef](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
if constexpr (sizeof...(BlockTypes) != 0)
|
||||
{
|
||||
if (((a_BlockEntity.GetBlockType() != BlockTypes) && ...))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
L.Call(FnRef, static_cast<BlockEntityType *>(&a_BlockEntity), cLuaState::Return, ret);
|
||||
return ret;
|
||||
});
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int tolua_cWorld_BroadcastBlockAction(lua_State * tolua_S)
|
||||
{
|
||||
/* Function signature:
|
||||
@ -566,6 +760,53 @@ static int tolua_cWorld_FastSetBlock(lua_State * tolua_S)
|
||||
|
||||
|
||||
|
||||
static int tolua_cWorld_ForEachEntityInChunk(lua_State * tolua_S)
|
||||
{
|
||||
// Check params:
|
||||
cLuaState L(tolua_S);
|
||||
if (
|
||||
!L.CheckParamUserType(1, "cWorld") ||
|
||||
!L.CheckParamNumber(2, 3) ||
|
||||
!L.CheckParamFunction(4) ||
|
||||
!L.CheckParamEnd(5)
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get parameters:
|
||||
cWorld * Self = nullptr;
|
||||
int ChunkX = 0;
|
||||
int ChunkZ = 0;
|
||||
cLuaState::cRef FnRef;
|
||||
L.GetStackValues(1, Self, ChunkX, ChunkZ, FnRef);
|
||||
if (Self == nullptr)
|
||||
{
|
||||
return L.ApiParamError("Invalid 'self'");
|
||||
}
|
||||
if (!FnRef.IsValid())
|
||||
{
|
||||
return L.ApiParamError("Expected a valid callback function for parameter #4");
|
||||
}
|
||||
|
||||
// Call the DoWith function:
|
||||
bool res = Self->ForEachEntityInChunk(ChunkX, ChunkZ, [&](cEntity & a_Item)
|
||||
{
|
||||
bool ret = false;
|
||||
L.Call(FnRef, &a_Item, cLuaState::Return, ret);
|
||||
return ret;
|
||||
}
|
||||
);
|
||||
|
||||
// Push the result as the return value:
|
||||
L.Push(res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int tolua_cWorld_ForEachLoadedChunk(lua_State * tolua_S)
|
||||
{
|
||||
// Exported manually, because tolua doesn't support converting functions to functor types.
|
||||
@ -1347,35 +1588,35 @@ void cManualBindings::BindWorld(lua_State * tolua_S)
|
||||
tolua_function(tolua_S, "BroadcastParticleEffect", tolua_cWorld_BroadcastParticleEffect);
|
||||
tolua_function(tolua_S, "ChunkStay", tolua_cWorld_ChunkStay);
|
||||
tolua_function(tolua_S, "DoExplosionAt", tolua_cWorld_DoExplosionAt);
|
||||
tolua_function(tolua_S, "DoWithBeaconAt", DoWithXYZ<cWorld, cBeaconEntity, &cWorld::DoWithBeaconAt>);
|
||||
tolua_function(tolua_S, "DoWithBedAt", DoWithXYZ<cWorld, cBedEntity, &cWorld::DoWithBedAt>);
|
||||
tolua_function(tolua_S, "DoWithBlockEntityAt", DoWithXYZ<cWorld, cBlockEntity, &cWorld::DoWithBlockEntityAt>);
|
||||
tolua_function(tolua_S, "DoWithBrewingstandAt", DoWithXYZ<cWorld, cBrewingstandEntity, &cWorld::DoWithBrewingstandAt>);
|
||||
tolua_function(tolua_S, "DoWithChestAt", DoWithXYZ<cWorld, cChestEntity, &cWorld::DoWithChestAt>);
|
||||
tolua_function(tolua_S, "DoWithCommandBlockAt", DoWithXYZ<cWorld, cCommandBlockEntity, &cWorld::DoWithCommandBlockAt>);
|
||||
tolua_function(tolua_S, "DoWithDispenserAt", DoWithXYZ<cWorld, cDispenserEntity, &cWorld::DoWithDispenserAt>);
|
||||
tolua_function(tolua_S, "DoWithDropSpenserAt", DoWithXYZ<cWorld, cDropSpenserEntity, &cWorld::DoWithDropSpenserAt>);
|
||||
tolua_function(tolua_S, "DoWithDropperAt", DoWithXYZ<cWorld, cDropperEntity, &cWorld::DoWithDropperAt>);
|
||||
tolua_function(tolua_S, "DoWithEntityByID", DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>);
|
||||
tolua_function(tolua_S, "DoWithFlowerPotAt", DoWithXYZ<cWorld, cFlowerPotEntity, &cWorld::DoWithFlowerPotAt>);
|
||||
tolua_function(tolua_S, "DoWithFurnaceAt", DoWithXYZ<cWorld, cFurnaceEntity, &cWorld::DoWithFurnaceAt>);
|
||||
tolua_function(tolua_S, "DoWithHopperAt", DoWithXYZ<cWorld, cHopperEntity, &cWorld::DoWithHopperAt>);
|
||||
tolua_function(tolua_S, "DoWithMobHeadAt", DoWithXYZ<cWorld, cMobHeadEntity, &cWorld::DoWithMobHeadAt>);
|
||||
tolua_function(tolua_S, "DoWithBeaconAt", DoWithBlockEntityAt<cBeaconEntity, E_BLOCK_BEACON>);
|
||||
tolua_function(tolua_S, "DoWithBedAt", DoWithBlockEntityAt<cBedEntity, E_BLOCK_BED>);
|
||||
tolua_function(tolua_S, "DoWithBlockEntityAt", DoWithBlockEntityAt<cBlockEntity>);
|
||||
tolua_function(tolua_S, "DoWithBrewingstandAt", DoWithBlockEntityAt<cBrewingstandEntity, E_BLOCK_BREWING_STAND>);
|
||||
tolua_function(tolua_S, "DoWithChestAt", DoWithBlockEntityAt<cChestEntity, E_BLOCK_CHEST, E_BLOCK_TRAPPED_CHEST>);
|
||||
tolua_function(tolua_S, "DoWithCommandBlockAt", DoWithBlockEntityAt<cCommandBlockEntity, E_BLOCK_COMMAND_BLOCK>);
|
||||
tolua_function(tolua_S, "DoWithDispenserAt", DoWithBlockEntityAt<cDispenserEntity, E_BLOCK_DISPENSER>);
|
||||
tolua_function(tolua_S, "DoWithDropSpenserAt", DoWithBlockEntityAt<cDropSpenserEntity, E_BLOCK_DISPENSER, E_BLOCK_DROPPER>);
|
||||
tolua_function(tolua_S, "DoWithDropperAt", DoWithBlockEntityAt<cDropperEntity, E_BLOCK_DROPPER>);
|
||||
tolua_function(tolua_S, "DoWithEntityByID", DoWithID<cWorld, cEntity, &cWorld::DoWithEntityByID>);
|
||||
tolua_function(tolua_S, "DoWithFlowerPotAt", DoWithBlockEntityAt<cFlowerPotEntity, E_BLOCK_FLOWER_POT>);
|
||||
tolua_function(tolua_S, "DoWithFurnaceAt", DoWithBlockEntityAt<cFurnaceEntity, E_BLOCK_FURNACE, E_BLOCK_LIT_FURNACE>);
|
||||
tolua_function(tolua_S, "DoWithHopperAt", DoWithBlockEntityAt<cHopperEntity, E_BLOCK_HOPPER>);
|
||||
tolua_function(tolua_S, "DoWithMobHeadAt", DoWithBlockEntityAt<cMobHeadEntity, E_BLOCK_HEAD>);
|
||||
tolua_function(tolua_S, "DoWithNearestPlayer", tolua_cWorld_DoWithNearestPlayer);
|
||||
tolua_function(tolua_S, "DoWithNoteBlockAt", DoWithXYZ<cWorld, cNoteEntity, &cWorld::DoWithNoteBlockAt>);
|
||||
tolua_function(tolua_S, "DoWithPlayer", DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>);
|
||||
tolua_function(tolua_S, "DoWithNoteBlockAt", DoWithBlockEntityAt<cNoteEntity, E_BLOCK_NOTE_BLOCK>);
|
||||
tolua_function(tolua_S, "DoWithPlayer", DoWith<cWorld, cPlayer, &cWorld::DoWithPlayer>);
|
||||
tolua_function(tolua_S, "DoWithPlayerByUUID", tolua_cWorld_DoWithPlayerByUUID);
|
||||
tolua_function(tolua_S, "FastSetBlock", tolua_cWorld_FastSetBlock);
|
||||
tolua_function(tolua_S, "FindAndDoWithPlayer", DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>);
|
||||
tolua_function(tolua_S, "ForEachBlockEntityInChunk", ForEachInChunk<cWorld, cBlockEntity, &cWorld::ForEachBlockEntityInChunk>);
|
||||
tolua_function(tolua_S, "ForEachBrewingstandInChunk", ForEachInChunk<cWorld, cBrewingstandEntity, &cWorld::ForEachBrewingstandInChunk>);
|
||||
tolua_function(tolua_S, "ForEachChestInChunk", ForEachInChunk<cWorld, cChestEntity, &cWorld::ForEachChestInChunk>);
|
||||
tolua_function(tolua_S, "ForEachEntity", ForEach< cWorld, cEntity, &cWorld::ForEachEntity>);
|
||||
tolua_function(tolua_S, "ForEachEntityInBox", ForEachInBox< cWorld, cEntity, &cWorld::ForEachEntityInBox>);
|
||||
tolua_function(tolua_S, "ForEachEntityInChunk", ForEachInChunk<cWorld, cEntity, &cWorld::ForEachEntityInChunk>);
|
||||
tolua_function(tolua_S, "ForEachFurnaceInChunk", ForEachInChunk<cWorld, cFurnaceEntity, &cWorld::ForEachFurnaceInChunk>);
|
||||
tolua_function(tolua_S, "FindAndDoWithPlayer", DoWith<cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>);
|
||||
tolua_function(tolua_S, "ForEachBlockEntityInChunk", ForEachBlockEntityInChunk<cBlockEntity>);
|
||||
tolua_function(tolua_S, "ForEachBrewingstandInChunk", ForEachBlockEntityInChunk<cBrewingstandEntity, E_BLOCK_BREWING_STAND>);
|
||||
tolua_function(tolua_S, "ForEachChestInChunk", ForEachBlockEntityInChunk<cChestEntity, E_BLOCK_CHEST, E_BLOCK_TRAPPED_CHEST>);
|
||||
tolua_function(tolua_S, "ForEachEntity", ForEach<cWorld, cEntity, &cWorld::ForEachEntity>);
|
||||
tolua_function(tolua_S, "ForEachEntityInBox", ForEachInBox<cWorld, cEntity, &cWorld::ForEachEntityInBox>);
|
||||
tolua_function(tolua_S, "ForEachEntityInChunk", tolua_cWorld_ForEachEntityInChunk);
|
||||
tolua_function(tolua_S, "ForEachFurnaceInChunk", ForEachBlockEntityInChunk<cFurnaceEntity, E_BLOCK_FURNACE, E_BLOCK_LIT_FURNACE>);
|
||||
tolua_function(tolua_S, "ForEachLoadedChunk", tolua_cWorld_ForEachLoadedChunk);
|
||||
tolua_function(tolua_S, "ForEachPlayer", ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>);
|
||||
tolua_function(tolua_S, "ForEachPlayer", ForEach<cWorld, cPlayer, &cWorld::ForEachPlayer>);
|
||||
tolua_function(tolua_S, "GetBlock", tolua_cWorld_GetBlock);
|
||||
tolua_function(tolua_S, "GetBlockBlockLight", tolua_cWorld_GetBlockBlockLight);
|
||||
tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo);
|
||||
|
@ -56,12 +56,4 @@ void cBedEntity::SendTo(cClientHandle & a_Client)
|
||||
void cBedEntity::SetColor(short a_Color)
|
||||
{
|
||||
m_Color = a_Color;
|
||||
auto Pos = GetPos();
|
||||
|
||||
// If the bed entity is send immediately, the client (maybe) still has not the bed.
|
||||
// Fix that by delaying the broadcast of the bed entity by a tick:
|
||||
m_World->ScheduleTask(1, [Pos](cWorld & a_World)
|
||||
{
|
||||
a_World.BroadcastBlockEntity(Pos);
|
||||
});
|
||||
}
|
||||
|
@ -146,24 +146,25 @@ bool cChestEntity::UsedBy(cPlayer * a_Player)
|
||||
|
||||
void cChestEntity::ScanNeighbours()
|
||||
{
|
||||
// Callback for finding neighbouring chest:
|
||||
auto FindNeighbour = [this](cChestEntity & a_Chest)
|
||||
// Callback for finding neighbouring chest.
|
||||
auto FindNeighbour = [this](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
if (a_Chest.GetBlockType() != m_BlockType)
|
||||
if (a_BlockEntity.GetBlockType() != m_BlockType)
|
||||
{
|
||||
// Neighboring block is not the same type of chest
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
m_Neighbour = &a_Chest;
|
||||
return false;
|
||||
|
||||
m_Neighbour = static_cast<cChestEntity *>(&a_BlockEntity);
|
||||
return true;
|
||||
};
|
||||
|
||||
// Scan horizontally adjacent blocks for any neighbouring chest of the same type:
|
||||
if (
|
||||
m_World->DoWithChestAt(m_Pos.x - 1, m_Pos.y, m_Pos.z, FindNeighbour) ||
|
||||
m_World->DoWithChestAt(m_Pos.x + 1, m_Pos.y, m_Pos.z, FindNeighbour) ||
|
||||
m_World->DoWithChestAt(m_Pos.x, m_Pos.y, m_Pos.z - 1, FindNeighbour) ||
|
||||
m_World->DoWithChestAt(m_Pos.x, m_Pos.y, m_Pos.z + 1, FindNeighbour)
|
||||
m_World->DoWithBlockEntityAt(m_Pos.addedX(-1), FindNeighbour) ||
|
||||
m_World->DoWithBlockEntityAt(m_Pos.addedX(+1), FindNeighbour) ||
|
||||
m_World->DoWithBlockEntityAt(m_Pos.addedZ(-1), FindNeighbour) ||
|
||||
m_World->DoWithBlockEntityAt(m_Pos.addedX(+1), FindNeighbour)
|
||||
)
|
||||
{
|
||||
m_Neighbour->m_Neighbour = this;
|
||||
|
@ -43,15 +43,6 @@ bool cCommandBlockEntity::UsedBy(cPlayer * a_Player)
|
||||
void cCommandBlockEntity::SetCommand(const AString & a_Cmd)
|
||||
{
|
||||
m_Command = a_Cmd;
|
||||
|
||||
/*
|
||||
Vanilla requires that the server send a Block Entity Update after a command has been set
|
||||
Therefore, command blocks don't support on-the-fly (when window is open) updating of a command and therefore...
|
||||
...the following code can't be put in UsedBy just before the window opens
|
||||
|
||||
Just documenting my experience in getting this to work :P
|
||||
*/
|
||||
m_World->BroadcastBlockEntity(GetPos());
|
||||
}
|
||||
|
||||
|
||||
@ -60,7 +51,6 @@ void cCommandBlockEntity::SetCommand(const AString & a_Cmd)
|
||||
|
||||
void cCommandBlockEntity::SetLastOutput(const AString & a_LastOut)
|
||||
{
|
||||
m_World->BroadcastBlockEntity(GetPos());
|
||||
m_LastOutput = a_LastOut;
|
||||
}
|
||||
|
||||
@ -180,7 +170,6 @@ void cCommandBlockEntity::Execute()
|
||||
{
|
||||
// Overwrite field
|
||||
m_CmdBlock->SetLastOutput(cClientHandle::FormatChatPrefix(m_CmdBlock->GetWorld()->ShouldUseChatPrefixes(), "SUCCESS", cChatColor::Green, cChatColor::White) + a_Text);
|
||||
m_CmdBlock->GetWorld()->BroadcastBlockEntity(m_CmdBlock->GetPos());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,6 @@ void cMobHeadEntity::SetType(const eMobHeadType & a_Type)
|
||||
m_OwnerUUID = cUUID{};
|
||||
}
|
||||
m_Type = a_Type;
|
||||
m_World->BroadcastBlockEntity(GetPos());
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +42,6 @@ void cMobHeadEntity::SetType(const eMobHeadType & a_Type)
|
||||
void cMobHeadEntity::SetRotation(eMobHeadRotation a_Rotation)
|
||||
{
|
||||
m_Rotation = a_Rotation;
|
||||
m_World->BroadcastBlockEntity(GetPos());
|
||||
}
|
||||
|
||||
|
||||
@ -70,8 +68,6 @@ void cMobHeadEntity::SetOwner(const cPlayer & a_Owner)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_World->BroadcastBlockEntity(GetPos());
|
||||
}
|
||||
|
||||
|
||||
@ -89,7 +85,6 @@ void cMobHeadEntity::SetOwner(const cUUID & a_OwnerUUID, const AString & a_Owner
|
||||
m_OwnerName = a_OwnerName;
|
||||
m_OwnerTexture = a_OwnerTexture;
|
||||
m_OwnerTextureSignature = a_OwnerTextureSignature;
|
||||
m_World->BroadcastBlockEntity(GetPos());
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,6 +70,7 @@ bool cMobSpawnerEntity::UsedBy(cPlayer * a_Player)
|
||||
{
|
||||
a_Player->GetInventory().RemoveOneEquippedItem();
|
||||
}
|
||||
m_World->BroadcastBlockEntity(GetPos());
|
||||
FLOGD("Changed monster spawner at {0} to type {1}.", GetPos(), cMonster::MobTypeToString(MonsterType));
|
||||
return true;
|
||||
}
|
||||
@ -105,6 +106,7 @@ bool cMobSpawnerEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
if (m_SpawnDelay <= 0)
|
||||
{
|
||||
SpawnEntity();
|
||||
m_World->BroadcastBlockEntity(GetPos());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@ -121,7 +123,6 @@ bool cMobSpawnerEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
void cMobSpawnerEntity::ResetTimer(void)
|
||||
{
|
||||
m_SpawnDelay = GetRandomProvider().RandInt<short>(m_MinSpawnDelay, m_MaxSpawnDelay);
|
||||
m_World->BroadcastBlockEntity(GetPos());
|
||||
}
|
||||
|
||||
|
||||
|
@ -1181,36 +1181,3 @@ extern AString ItemToFullString(const cItem & a_Item);
|
||||
extern cItem GetIniItemSet(cIniFile & a_IniFile, const char * a_Section, const char * a_Key, const char * a_Default);
|
||||
|
||||
// tolua_end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Base case for IsOneOf to handle empty template aguments. */
|
||||
template <class = void>
|
||||
bool IsOneOf(BLOCKTYPE a_BlockType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/** Returns true if a_BlockType is equal to any of the variadic template arguments.
|
||||
Some example usage:
|
||||
\code
|
||||
IsOneOf<>(E_BLOCK_AIR) == false
|
||||
IsOneOf<E_BLOCK_AIR>(E_BLOCK_DIRT) == false
|
||||
IsOneOf<E_BLOCK_AIR, E_BLOCK_DIRT>(E_BLOCK_DIRT) == true
|
||||
\endcode
|
||||
The implementation is ugly but it is equivalent to this C++17 fold expression:
|
||||
\code
|
||||
((a_BlockType == Types) || ...)
|
||||
\endcode
|
||||
Just written to be valid without fold expressions or SFINAE. */
|
||||
template <BLOCKTYPE Head, BLOCKTYPE ... Tail>
|
||||
bool IsOneOf(BLOCKTYPE a_BlockType)
|
||||
{
|
||||
return ((a_BlockType == Head) || (IsOneOf<Tail...>(a_BlockType)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -158,12 +158,12 @@ bool cBlockBedHandler::OnUse(
|
||||
|
||||
void cBlockBedHandler::OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const sSetBlock & a_BlockChange) const
|
||||
{
|
||||
a_Player.GetWorld()->DoWithBedAt(a_BlockChange.GetX(), a_BlockChange.GetY(), a_BlockChange.GetZ(), [&](cBedEntity & a_Bed)
|
||||
{
|
||||
a_Bed.SetColor(a_Player.GetEquippedItem().m_ItemDamage);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
a_Player.GetWorld()->DoWithBlockEntityAt(a_BlockChange.GetAbsolutePos(), [&a_Player](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_BED);
|
||||
static_cast<cBedEntity &>(a_BlockEntity).SetColor(a_Player.GetEquippedItem().m_ItemDamage);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,7 +32,7 @@ private:
|
||||
) const override
|
||||
{
|
||||
AString WindowName = "Enchant";
|
||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, [&WindowName](cBlockEntity & a_Entity)
|
||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockPos, [&WindowName](cBlockEntity & a_Entity)
|
||||
{
|
||||
if (a_Entity.GetBlockType() != E_BLOCK_ENCHANTMENT_TABLE)
|
||||
{
|
||||
@ -46,7 +46,7 @@ private:
|
||||
WindowName = CustomName;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
cWindow * Window = new cEnchantingWindow(a_BlockPos, std::move(WindowName));
|
||||
|
@ -26,18 +26,15 @@ private:
|
||||
const Vector3i a_BlockPos
|
||||
) const override
|
||||
{
|
||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, [](cBlockEntity & a_BlockEntity)
|
||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockPos, [](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
if (a_BlockEntity.GetBlockType() != E_BLOCK_NOTE_BLOCK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto & NoteEntity = static_cast<cNoteEntity &>(a_BlockEntity);
|
||||
|
||||
NoteEntity.MakeSound();
|
||||
|
||||
return true;
|
||||
static_cast<cNoteEntity &>(a_BlockEntity).MakeSound();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -4,13 +4,11 @@
|
||||
#include "../FunctionRef.h"
|
||||
#include "../Mobs/MonsterTypes.h"
|
||||
|
||||
class cBedEntity;
|
||||
class cBlockEntity;
|
||||
class cBroadcastInterface;
|
||||
class cItems;
|
||||
class cPlayer;
|
||||
|
||||
using cBedCallback = cFunctionRef<bool(cBedEntity &)>;
|
||||
using cBlockEntityCallback = cFunctionRef<bool(cBlockEntity &)>;
|
||||
using cPlayerListCallback = cFunctionRef<bool(cPlayer &)>;
|
||||
using cEntityCallback = cFunctionRef<bool(cEntity &)>;
|
||||
@ -32,10 +30,8 @@ public:
|
||||
|
||||
virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData) = 0;
|
||||
|
||||
virtual bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback a_Callback) = 0;
|
||||
|
||||
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
|
||||
virtual bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback a_Callback) = 0;
|
||||
virtual bool DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback) = 0;
|
||||
|
||||
/** Spawns item pickups for each item in the list. May compress pickups if too many entities: */
|
||||
virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed = 1.0, bool IsPlayerCreated = false) = 0;
|
||||
|
402
src/Chunk.cpp
402
src/Chunk.cpp
@ -12,21 +12,6 @@
|
||||
#include "ClientHandle.h"
|
||||
#include "Server.h"
|
||||
#include "Defines.h"
|
||||
#include "BlockEntities/BeaconEntity.h"
|
||||
#include "BlockEntities/BedEntity.h"
|
||||
#include "BlockEntities/BrewingstandEntity.h"
|
||||
#include "BlockEntities/ChestEntity.h"
|
||||
#include "BlockEntities/CommandBlockEntity.h"
|
||||
#include "BlockEntities/DispenserEntity.h"
|
||||
#include "BlockEntities/DropperEntity.h"
|
||||
#include "BlockEntities/FlowerPotEntity.h"
|
||||
#include "BlockEntities/FurnaceEntity.h"
|
||||
#include "BlockEntities/HopperEntity.h"
|
||||
#include "BlockEntities/JukeboxEntity.h"
|
||||
#include "BlockEntities/MobHeadEntity.h"
|
||||
#include "BlockEntities/MobSpawnerEntity.h"
|
||||
#include "BlockEntities/NoteEntity.h"
|
||||
#include "BlockEntities/SignEntity.h"
|
||||
#include "Entities/Pickup.h"
|
||||
#include "Item.h"
|
||||
#include "Noise/Noise.h"
|
||||
@ -468,7 +453,6 @@ void cChunk::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlock
|
||||
auto clone = be->Clone({posX, posY, posZ});
|
||||
clone->SetWorld(m_World);
|
||||
AddBlockEntity(std::move(clone));
|
||||
m_World->BroadcastBlockEntity({posX, posY, posZ});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -789,28 +773,34 @@ void cChunk::MoveEntityToNewChunk(OwnedEntity a_Entity)
|
||||
|
||||
void cChunk::BroadcastPendingBlockChanges(void)
|
||||
{
|
||||
if (m_PendingSendBlocks.empty())
|
||||
if (const auto PendingBlocksCount = m_PendingSendBlocks.size(); PendingBlocksCount >= 10240)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_PendingSendBlocks.size() >= 10240)
|
||||
{
|
||||
// Resend the full chunk
|
||||
for (auto ClientHandle : m_LoadedByClient)
|
||||
// Resend the full chunk:
|
||||
for (const auto ClientHandle : m_LoadedByClient)
|
||||
{
|
||||
m_World->ForceSendChunkTo(m_PosX, m_PosZ, cChunkSender::Priority::Medium, ClientHandle);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (PendingBlocksCount != 0)
|
||||
{
|
||||
// Only send block changes
|
||||
for (auto ClientHandle : m_LoadedByClient)
|
||||
// Send block changes:
|
||||
for (const auto ClientHandle : m_LoadedByClient)
|
||||
{
|
||||
ClientHandle->SendBlockChanges(m_PosX, m_PosZ, m_PendingSendBlocks);
|
||||
}
|
||||
}
|
||||
|
||||
// Send block entity changes:
|
||||
for (const auto Entity : m_PendingSendBlockEntities)
|
||||
{
|
||||
for (const auto ClientHandle : m_LoadedByClient)
|
||||
{
|
||||
Entity->SendTo(*ClientHandle);
|
||||
}
|
||||
}
|
||||
|
||||
m_PendingSendBlocks.clear();
|
||||
m_PendingSendBlockEntities.clear();
|
||||
}
|
||||
|
||||
|
||||
@ -823,12 +813,12 @@ void cChunk::CheckBlocks()
|
||||
cBlockInServerPluginInterface PluginInterface(*m_World);
|
||||
|
||||
// Process a limited number of blocks since cBlockHandler::Check may queue more to tick
|
||||
auto Count = m_ToTickBlocks.size();
|
||||
auto Count = m_BlocksToCheck.size();
|
||||
|
||||
while (Count != 0)
|
||||
{
|
||||
const auto Pos = m_ToTickBlocks.front();
|
||||
m_ToTickBlocks.pop();
|
||||
const auto Pos = m_BlocksToCheck.front();
|
||||
m_BlocksToCheck.pop();
|
||||
Count--;
|
||||
|
||||
cBlockHandler::For(GetBlock(Pos)).Check(ChunkInterface, PluginInterface, Pos, *this);
|
||||
@ -1265,8 +1255,8 @@ void cChunk::SetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_Blo
|
||||
{
|
||||
FastSetBlock(a_RelPos, a_BlockType, a_BlockMeta);
|
||||
|
||||
// Tick this block's neighbors via cBlockHandler::Check:
|
||||
m_ToTickBlocks.push(a_RelPos);
|
||||
// Queue a check of this block's neighbors:
|
||||
m_BlocksToCheck.push(a_RelPos);
|
||||
|
||||
// Wake up the simulators for this block:
|
||||
GetWorld()->GetSimulatorManager()->WakeUp(*this, a_RelPos);
|
||||
@ -1370,22 +1360,26 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
||||
|
||||
void cChunk::SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client)
|
||||
{
|
||||
const auto BlockEntity = GetBlockEntityRel({ a_RelX, a_RelY, a_RelZ });
|
||||
|
||||
if (a_Client == nullptr)
|
||||
{
|
||||
// Queue the block for all clients in the chunk (will be sent in Tick())
|
||||
// Queue the block (entity) for all clients in the chunk (will be sent in BroadcastPendingBlockChanges()):
|
||||
m_PendingSendBlocks.emplace_back(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, GetBlock(a_RelX, a_RelY, a_RelZ), GetMeta(a_RelX, a_RelY, a_RelZ));
|
||||
if (BlockEntity != nullptr)
|
||||
{
|
||||
m_PendingSendBlockEntities.push_back(BlockEntity);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3i wp = PositionToWorldPosition(a_RelX, a_RelY, a_RelZ);
|
||||
a_Client->SendBlockChange(wp.x, wp.y, wp.z, GetBlock(a_RelX, a_RelY, a_RelZ), GetMeta(a_RelX, a_RelY, a_RelZ));
|
||||
const auto Position = PositionToWorldPosition(a_RelX, a_RelY, a_RelZ);
|
||||
a_Client->SendBlockChange(Position.x, Position.y, Position.z, GetBlock(a_RelX, a_RelY, a_RelZ), GetMeta(a_RelX, a_RelY, a_RelZ));
|
||||
|
||||
// FS #268 - if a BlockEntity digging is cancelled by a plugin, the entire block entity must be re-sent to the client:
|
||||
cBlockEntity * Block = GetBlockEntity(wp.x, wp.y, wp.z);
|
||||
if (Block != nullptr)
|
||||
if (BlockEntity != nullptr)
|
||||
{
|
||||
Block->SendTo(*a_Client);
|
||||
BlockEntity->SendTo(*a_Client);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1508,39 +1502,12 @@ void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_Max
|
||||
|
||||
|
||||
|
||||
bool cChunk::SetSignLines(int a_PosX, int a_PosY, int a_PosZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
|
||||
{
|
||||
// Also sends update packets to all clients in the chunk
|
||||
auto Entity = GetBlockEntity(a_PosX, a_PosY, a_PosZ);
|
||||
if (Entity == nullptr)
|
||||
{
|
||||
return false; // Not a block entity
|
||||
}
|
||||
if (
|
||||
(Entity->GetBlockType() != E_BLOCK_WALLSIGN) &&
|
||||
(Entity->GetBlockType() != E_BLOCK_SIGN_POST)
|
||||
)
|
||||
{
|
||||
return false; // Not a sign
|
||||
}
|
||||
|
||||
MarkDirty();
|
||||
auto Sign = static_cast<cSignEntity *>(Entity);
|
||||
Sign->SetLines(a_Line1, a_Line2, a_Line3, a_Line4);
|
||||
m_World->BroadcastBlockEntity({a_PosX, a_PosY, a_PosZ});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunk::RemoveBlockEntity(cBlockEntity * a_BlockEntity)
|
||||
{
|
||||
MarkDirty();
|
||||
ASSERT(a_BlockEntity != nullptr);
|
||||
auto idx = static_cast<size_t>(cChunkDef::MakeIndex(a_BlockEntity->GetRelX(), a_BlockEntity->GetPosY(), a_BlockEntity->GetRelZ()));
|
||||
m_BlockEntities.erase(idx);
|
||||
m_BlockEntities.erase(static_cast<size_t>(cChunkDef::MakeIndex(a_BlockEntity->GetRelX(), a_BlockEntity->GetPosY(), a_BlockEntity->GetRelZ())));
|
||||
m_PendingSendBlockEntities.erase(std::remove(m_PendingSendBlockEntities.begin(), m_PendingSendBlockEntities.end(), a_BlockEntity), m_PendingSendBlockEntities.end());
|
||||
}
|
||||
|
||||
|
||||
@ -1745,125 +1712,19 @@ bool cChunk::DoWithEntityByID(UInt32 a_EntityID, cEntityCallback a_Callback, boo
|
||||
|
||||
|
||||
|
||||
template <class tyEntity, BLOCKTYPE... tBlocktype>
|
||||
bool cChunk::GenericForEachBlockEntity(cFunctionRef<bool(tyEntity &)> a_Callback)
|
||||
{
|
||||
// The blockentity list is locked by the parent chunkmap's CS
|
||||
for (auto & KeyPair : m_BlockEntities)
|
||||
{
|
||||
cBlockEntity * Block = KeyPair.second.get();
|
||||
if (
|
||||
(sizeof...(tBlocktype) == 0) || // Let empty list mean all block entities
|
||||
(IsOneOf<tBlocktype...>(Block->GetBlockType()))
|
||||
)
|
||||
{
|
||||
if (a_Callback(*static_cast<tyEntity *>(Block)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // for KeyPair - m_BlockEntitites[]
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachBlockEntity(cBlockEntityCallback a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cBlockEntity>(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachBrewingstand(cBrewingstandCallback a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cBrewingstandEntity,
|
||||
E_BLOCK_BREWING_STAND
|
||||
>(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachChest(cChestCallback a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cChestEntity,
|
||||
E_BLOCK_CHEST
|
||||
>(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachDispenser(cDispenserCallback a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cDispenserEntity,
|
||||
E_BLOCK_DISPENSER
|
||||
>(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachDropper(cDropperCallback a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cDropperEntity,
|
||||
E_BLOCK_DROPPER
|
||||
>(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachDropSpenser(cDropSpenserCallback a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cDropSpenserEntity,
|
||||
E_BLOCK_DISPENSER,
|
||||
E_BLOCK_DROPPER
|
||||
>(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachFurnace(cFurnaceCallback a_Callback)
|
||||
{
|
||||
return GenericForEachBlockEntity<cFurnaceEntity,
|
||||
E_BLOCK_FURNACE,
|
||||
E_BLOCK_LIT_FURNACE
|
||||
>(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <class tyEntity, BLOCKTYPE... tBlocktype>
|
||||
bool cChunk::GenericDoWithBlockEntityAt(Vector3i a_Position, cFunctionRef<bool(tyEntity &)> a_Callback)
|
||||
{
|
||||
// The blockentity list is locked by the parent chunkmap's CS
|
||||
cBlockEntity * Block = GetBlockEntityRel(a_Position);
|
||||
if (Block == nullptr)
|
||||
|
||||
for (auto & KeyPair : m_BlockEntities)
|
||||
{
|
||||
return false; // No block entity here
|
||||
if (a_Callback(*KeyPair.second))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (
|
||||
(sizeof...(tBlocktype) != 0) && // Let empty list mean all block entities
|
||||
(!IsOneOf<tBlocktype...>(Block->GetBlockType()))
|
||||
)
|
||||
{
|
||||
return false; // Not any of the given tBlocktypes
|
||||
}
|
||||
return !a_Callback(*static_cast<tyEntity *>(Block));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -1871,182 +1732,19 @@ bool cChunk::GenericDoWithBlockEntityAt(Vector3i a_Position, cFunctionRef<bool(t
|
||||
|
||||
|
||||
bool cChunk::DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cBlockEntity>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithBeaconAt(Vector3i a_Position, cBeaconCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cBeaconEntity,
|
||||
E_BLOCK_BEACON
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithBedAt(Vector3i a_Position, cBedCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cBedEntity,
|
||||
E_BLOCK_BED
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithBrewingstandAt(Vector3i a_Position, cBrewingstandCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cBrewingstandEntity,
|
||||
E_BLOCK_BREWING_STAND
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithChestAt(Vector3i a_Position, cChestCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cChestEntity,
|
||||
E_BLOCK_CHEST,
|
||||
E_BLOCK_TRAPPED_CHEST
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithDispenserAt(Vector3i a_Position, cDispenserCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cDispenserEntity,
|
||||
E_BLOCK_DISPENSER
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithDropperAt(Vector3i a_Position, cDropperCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cDropperEntity,
|
||||
E_BLOCK_DROPPER
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithDropSpenserAt(Vector3i a_Position, cDropSpenserCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cDropSpenserEntity,
|
||||
E_BLOCK_DISPENSER,
|
||||
E_BLOCK_DROPPER
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithFurnaceAt(Vector3i a_Position, cFurnaceCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cFurnaceEntity,
|
||||
E_BLOCK_FURNACE,
|
||||
E_BLOCK_LIT_FURNACE
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithHopperAt(Vector3i a_Position, cHopperCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cHopperEntity,
|
||||
E_BLOCK_HOPPER
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithNoteBlockAt(Vector3i a_Position, cNoteBlockCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cNoteEntity,
|
||||
E_BLOCK_NOTE_BLOCK
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithCommandBlockAt(Vector3i a_Position, cCommandBlockCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cCommandBlockEntity,
|
||||
E_BLOCK_COMMAND_BLOCK
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithMobHeadAt(Vector3i a_Position, cMobHeadCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cMobHeadEntity,
|
||||
E_BLOCK_HEAD
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithFlowerPotAt(Vector3i a_Position, cFlowerPotCallback a_Callback)
|
||||
{
|
||||
return GenericDoWithBlockEntityAt<cFlowerPotEntity,
|
||||
E_BLOCK_FLOWER_POT
|
||||
>(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::GetSignLines(Vector3i a_Position, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
|
||||
{
|
||||
// The blockentity list is locked by the parent chunkmap's CS
|
||||
auto Entity = GetBlockEntity(a_Position);
|
||||
if (Entity == nullptr)
|
||||
|
||||
const auto BlockEntity = GetBlockEntityRel(a_Position);
|
||||
if (BlockEntity == nullptr)
|
||||
{
|
||||
return false; // Not a block entity
|
||||
}
|
||||
if (
|
||||
(Entity->GetBlockType() != E_BLOCK_WALLSIGN) &&
|
||||
(Entity->GetBlockType() != E_BLOCK_SIGN_POST)
|
||||
)
|
||||
{
|
||||
return false; // Not a sign
|
||||
return false; // No block entity here
|
||||
}
|
||||
|
||||
auto Sign = static_cast<cSignEntity *>(Entity);
|
||||
a_Line1 = Sign->GetLine(0);
|
||||
a_Line2 = Sign->GetLine(1);
|
||||
a_Line3 = Sign->GetLine(2);
|
||||
a_Line4 = Sign->GetLine(3);
|
||||
return true;
|
||||
const bool Result = a_Callback(*BlockEntity);
|
||||
m_PendingSendBlockEntities.push_back(BlockEntity);
|
||||
MarkDirty();
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
|
108
src/Chunk.h
108
src/Chunk.h
@ -2,7 +2,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockEntities/BlockEntity.h"
|
||||
#include "Entities/Entity.h"
|
||||
#include "ChunkData.h"
|
||||
|
||||
#include "Simulator/FireSimulator.h"
|
||||
@ -19,19 +18,8 @@ class cWorld;
|
||||
class cClientHandle;
|
||||
class cPlayer;
|
||||
class cChunkMap;
|
||||
class cBeaconEntity;
|
||||
class cBedEntity;
|
||||
class cBrewingstandEntity;
|
||||
class cBoundingBox;
|
||||
class cChestEntity;
|
||||
class cChunkDataCallback;
|
||||
class cCommandBlockEntity;
|
||||
class cDispenserEntity;
|
||||
class cFurnaceEntity;
|
||||
class cHopperEntity;
|
||||
class cNoteEntity;
|
||||
class cMobHeadEntity;
|
||||
class cFlowerPotEntity;
|
||||
class cBlockArea;
|
||||
class cBlockArea;
|
||||
class cFluidSimulatorData;
|
||||
@ -212,9 +200,6 @@ public:
|
||||
Sends the chunk to all relevant clients. */
|
||||
void SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_MaxRelZ, EMCSBiome a_Biome);
|
||||
|
||||
/** Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk */
|
||||
bool SetSignLines(int a_RelX, int a_RelY, int a_RelZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
|
||||
|
||||
int GetHeight( int a_X, int a_Z) const;
|
||||
|
||||
/** Returns true if it is sunny at the specified location. This takes into account biomes. */
|
||||
@ -259,84 +244,12 @@ public:
|
||||
/** 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(UInt32 a_EntityID, cEntityCallback a_Callback, bool & a_CallbackResult) const; // Lua-accessible
|
||||
|
||||
/** Calls the callback for each tyEntity; returns true if all block entities processed, false if the callback aborted by returning true
|
||||
tBlocktypes are all blocktypes convertible to tyEntity which are to be called. If no block type is given the callback is called for every block entity
|
||||
Accessible only from within Chunk.cpp */
|
||||
template <class tyEntity, BLOCKTYPE... tBlocktype>
|
||||
bool GenericForEachBlockEntity(cFunctionRef<bool(tyEntity &)> a_Callback);
|
||||
|
||||
/** Calls the callback for each block entity; returns true if all block entities processed, false if the callback aborted by returning true */
|
||||
bool ForEachBlockEntity(cBlockEntityCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for each brewingstand; returns true if all brewingstands processed, false if the callback aborted by returning true */
|
||||
bool ForEachBrewingstand(cBrewingstandCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for each chest; returns true if all chests processed, false if the callback aborted by returning true */
|
||||
bool ForEachChest(cChestCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for each dispenser; returns true if all dispensers processed, false if the callback aborted by returning true */
|
||||
bool ForEachDispenser(cDispenserCallback a_Callback);
|
||||
|
||||
/** Calls the callback for each dropper; returns true if all droppers processed, false if the callback aborted by returning true */
|
||||
bool ForEachDropper(cDropperCallback a_Callback);
|
||||
|
||||
/** Calls the callback for each dropspenser; returns true if all dropspensers processed, false if the callback aborted by returning true */
|
||||
bool ForEachDropSpenser(cDropSpenserCallback a_Callback);
|
||||
|
||||
/** Calls the callback for each furnace; returns true if all furnaces processed, false if the callback aborted by returning true */
|
||||
bool ForEachFurnace(cFurnaceCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the tyEntity at the specified coords; returns false if there's no such block entity at those coords, true if found
|
||||
tBlocktype is a list of the blocktypes to be called. If no BLOCKTYPE template arguments are given the callback is called for any block entity
|
||||
Accessible only from within Chunk.cpp */
|
||||
template <class tyEntity, BLOCKTYPE... tBlocktype>
|
||||
bool GenericDoWithBlockEntityAt(Vector3i a_Position, cFunctionRef<bool(tyEntity &)> a_Callback);
|
||||
|
||||
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
|
||||
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, and whatever the callback returns if found. */
|
||||
bool DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
|
||||
bool DoWithBeaconAt(Vector3i a_Position, cBeaconCallback a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the brewingstand at the specified coords; returns false if there's no brewingstand at those coords, true if found */
|
||||
bool DoWithBrewingstandAt(Vector3i a_Position, cBrewingstandCallback a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the bed at the specified coords; returns false if there's no bed at those coords, true if found */
|
||||
bool DoWithBedAt(Vector3i a_Position, cBedCallback a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
|
||||
bool DoWithChestAt(Vector3i a_Position, cChestCallback a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found */
|
||||
bool DoWithDispenserAt(Vector3i a_Position, cDispenserCallback a_Callback);
|
||||
|
||||
/** Calls the callback for the dispenser at the specified coords; returns false if there's no dropper at those coords or callback returns true, returns true if found */
|
||||
bool DoWithDropperAt(Vector3i a_Position, cDropperCallback a_Callback);
|
||||
|
||||
/** Calls the callback for the dispenser at the specified coords; returns false if there's no dropspenser at those coords or callback returns true, returns true if found */
|
||||
bool DoWithDropSpenserAt(Vector3i a_Position, cDropSpenserCallback a_Callback);
|
||||
|
||||
/** Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found */
|
||||
bool DoWithFurnaceAt(Vector3i a_Position, cFurnaceCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the hopper at the specified coords; returns false if there's no hopper at those coords or callback returns true, returns true if found */
|
||||
bool DoWithHopperAt(Vector3i a_Position, cHopperCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found */
|
||||
bool DoWithNoteBlockAt(Vector3i a_Position, cNoteBlockCallback a_Callback);
|
||||
|
||||
/** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */
|
||||
bool DoWithCommandBlockAt(Vector3i a_Position, cCommandBlockCallback a_Callback);
|
||||
|
||||
/** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */
|
||||
bool DoWithMobHeadAt(Vector3i a_Position, cMobHeadCallback a_Callback);
|
||||
|
||||
/** Calls the callback for the flower pot at the specified coords; returns false if there's no flower pot at those coords or callback returns true, returns true if found */
|
||||
bool DoWithFlowerPotAt(Vector3i a_Position, cFlowerPotCallback a_Callback);
|
||||
|
||||
/** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */
|
||||
bool GetSignLines (Vector3i a_Position, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible
|
||||
|
||||
/** Use block entity on coordinate.
|
||||
returns true if the use was successful, return false to use the block as a "normal" block */
|
||||
bool UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // [x, y, z] in world block coords
|
||||
@ -529,9 +442,9 @@ public:
|
||||
as at least one requests is active the chunk will be ticked). */
|
||||
void SetAlwaysTicked(bool a_AlwaysTicked);
|
||||
|
||||
cChunkClientHandles GetAllClients(void) const
|
||||
const auto & GetAllClients(void) const
|
||||
{
|
||||
return cChunkClientHandles(m_LoadedByClient);
|
||||
return m_LoadedByClient;
|
||||
}
|
||||
|
||||
/** Converts the coord relative to this chunk into an absolute coord.
|
||||
@ -570,8 +483,19 @@ private:
|
||||
bool m_IsDirty; // True if the chunk has changed since it was last saved
|
||||
bool m_IsSaving; // True if the chunk is being saved
|
||||
|
||||
std::queue<Vector3i> m_ToTickBlocks;
|
||||
sSetBlockVector m_PendingSendBlocks; ///< Blocks that have changed and need to be sent to all clients
|
||||
/** Blocks that have changed and need to be sent to all clients.
|
||||
The protocol has a provision for coalescing block changes, and this is the buffer.
|
||||
It will collect the block changes that occur in a tick, before being flushed in BroadcastPendingSendBlocks. */
|
||||
sSetBlockVector m_PendingSendBlocks;
|
||||
|
||||
/** Block entities that have been touched and need to be sent to all clients.
|
||||
Because block changes are buffered and we need to happen after them, this buffer exists too.
|
||||
Pointers to block entities that were destroyed are guaranteed to be removed from this array by RemoveBlockEntity. */
|
||||
std::vector<cBlockEntity *> m_PendingSendBlockEntities;
|
||||
|
||||
/** A queue of relative positions to call cBlockHandler::Check on.
|
||||
Processed at the end of each tick by CheckBlocks. */
|
||||
std::queue<Vector3i> m_BlocksToCheck;
|
||||
|
||||
// A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers
|
||||
std::vector<cClientHandle *> m_LoadedByClient;
|
||||
|
@ -98,33 +98,6 @@ public:
|
||||
|
||||
|
||||
|
||||
/** Non-owning view of a chunk's client handles. */
|
||||
class cChunkClientHandles
|
||||
{
|
||||
public:
|
||||
using const_iterator = std::vector<cClientHandle *>::const_iterator;
|
||||
using iterator = const_iterator;
|
||||
|
||||
explicit cChunkClientHandles(const std::vector<cClientHandle *> & a_Container):
|
||||
m_Begin(a_Container.cbegin()),
|
||||
m_End(a_Container.cend())
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator begin() const { return m_Begin; }
|
||||
const_iterator cbegin() const { return m_Begin; }
|
||||
|
||||
const_iterator end() const { return m_End; }
|
||||
const_iterator cend() const { return m_End; }
|
||||
|
||||
private:
|
||||
const_iterator m_Begin, m_End;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Constants used throughout the code, useful typedefs and utility functions */
|
||||
class cChunkDef
|
||||
{
|
||||
|
376
src/ChunkMap.cpp
376
src/ChunkMap.cpp
@ -11,7 +11,6 @@
|
||||
#include "Generating/Trees.h" // used in cChunkMap::ReplaceTreeBlocks() for tree block discrimination
|
||||
#include "BlockArea.h"
|
||||
#include "Bindings/PluginManager.h"
|
||||
#include "Entities/TNTEntity.h"
|
||||
#include "Blocks/BlockHandler.h"
|
||||
#include "MobCensus.h"
|
||||
#include "MobSpawner.h"
|
||||
@ -20,7 +19,6 @@
|
||||
#include "Blocks/ChunkInterface.h"
|
||||
#include "Entities/Pickup.h"
|
||||
#include "DeadlockDetect.h"
|
||||
#include "BlockEntities/BlockEntity.h"
|
||||
|
||||
|
||||
|
||||
@ -840,8 +838,8 @@ void cChunkMap::CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2,
|
||||
|
||||
void cChunkMap::CompareChunkClients(cChunk * a_Chunk1, cChunk * a_Chunk2, cClientDiffCallback & a_Callback)
|
||||
{
|
||||
auto Clients1 = a_Chunk1->GetAllClients();
|
||||
auto Clients2 = a_Chunk2->GetAllClients();
|
||||
const auto & Clients1 = a_Chunk1->GetAllClients();
|
||||
const auto & Clients2 = a_Chunk2->GetAllClients();
|
||||
|
||||
// Find "removed" clients:
|
||||
for (auto * Client : Clients1)
|
||||
@ -1074,360 +1072,17 @@ bool cChunkMap::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEnti
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, cBrewingstandCallback a_Callback)
|
||||
bool cChunkMap::DoWithBlockEntityAt(const Vector3i a_Position, cBlockEntityCallback a_Callback)
|
||||
{
|
||||
const auto ChunkPosition = cChunkDef::BlockToChunk(a_Position);
|
||||
const auto Relative = cChunkDef::AbsoluteToRelative(a_Position, ChunkPosition);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
||||
const auto Chunk = FindChunk(ChunkPosition.m_ChunkX, ChunkPosition.m_ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->ForEachBrewingstand(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->ForEachChest(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->ForEachDispenser(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->ForEachDropper(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->ForEachDropSpenser(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->ForEachFurnace(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithBlockEntityAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithBeaconAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithBedAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithBrewingstandAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithChestAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithDispenserAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithDropperAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithDropSpenserAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithFurnaceAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithHopperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cHopperCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithHopperAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithNoteBlockAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithCommandBlockAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithMobHeadAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback a_Callback)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->DoWithFlowerPotAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cCSLock Lock(m_CSChunks);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->GetSignLines({ BlockX, BlockY, BlockZ }, a_Line1, a_Line2, a_Line3, a_Line4);
|
||||
return Chunk->DoWithBlockEntityAt(Relative, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
@ -1479,23 +1134,6 @@ void cChunkMap::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::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)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
int ChunkX, ChunkZ;
|
||||
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
|
||||
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Chunk->SetSignLines(a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSChunks);
|
||||
|
118
src/ChunkMap.h
118
src/ChunkMap.h
@ -18,19 +18,6 @@ class cItems;
|
||||
class cChunkStay;
|
||||
class cChunk;
|
||||
class cPlayer;
|
||||
class cBeaconEntity;
|
||||
class cBedEntity;
|
||||
class cBrewingstandEntity;
|
||||
class cChestEntity;
|
||||
class cDispenserEntity;
|
||||
class cDropperEntity;
|
||||
class cDropSpenserEntity;
|
||||
class cFurnaceEntity;
|
||||
class cHopperEntity;
|
||||
class cNoteEntity;
|
||||
class cCommandBlockEntity;
|
||||
class cMobHeadEntity;
|
||||
class cFlowerPotEntity;
|
||||
class cBlockArea;
|
||||
class cMobCensus;
|
||||
class cMobSpawner;
|
||||
@ -40,22 +27,9 @@ class cDeadlockDetect;
|
||||
struct SetChunkData;
|
||||
|
||||
typedef std::list<cClientHandle *> cClientHandleList;
|
||||
using cEntityCallback = cFunctionRef<bool(cEntity &)>;
|
||||
using cBeaconCallback = cFunctionRef<bool(cBeaconEntity &)>;
|
||||
using cBedCallback = cFunctionRef<bool(cBedEntity &)>;
|
||||
using cBlockEntityCallback = cFunctionRef<bool(cBlockEntity &)>;
|
||||
using cBrewingstandCallback = cFunctionRef<bool(cBrewingstandEntity &)>;
|
||||
using cChestCallback = cFunctionRef<bool(cChestEntity &)>;
|
||||
using cChunkCallback = cFunctionRef<bool(cChunk &)>;
|
||||
using cDispenserCallback = cFunctionRef<bool(cDispenserEntity &)>;
|
||||
using cDropperCallback = cFunctionRef<bool(cDropperEntity &)>;
|
||||
using cDropSpenserCallback = cFunctionRef<bool(cDropSpenserEntity &)>;
|
||||
using cFurnaceCallback = cFunctionRef<bool(cFurnaceEntity &)>;
|
||||
using cHopperCallback = cFunctionRef<bool(cHopperEntity &)>;
|
||||
using cNoteBlockCallback = cFunctionRef<bool(cNoteEntity &)>;
|
||||
using cCommandBlockCallback = cFunctionRef<bool(cCommandBlockEntity &)>;
|
||||
using cMobHeadCallback = cFunctionRef<bool(cMobHeadEntity &)>;
|
||||
using cFlowerPotCallback = cFunctionRef<bool(cFlowerPotEntity &)>;
|
||||
using cChunkCallback = cFunctionRef<bool(cChunk &)>;
|
||||
using cEntityCallback = cFunctionRef<bool(cEntity &)>;
|
||||
using cBlockEntityCallback = cFunctionRef<bool(cBlockEntity &)>;
|
||||
|
||||
|
||||
|
||||
@ -228,88 +202,9 @@ public:
|
||||
Returns true if all block entities processed, false if the callback aborted by returning true. */
|
||||
bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for brewingstand in the specified chunk.
|
||||
Returns true if all brewingstands processed, false if the callback aborted by returning true. */
|
||||
bool ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, cBrewingstandCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for each chest in the specified chunk.
|
||||
Returns true if all chests processed, false if the callback aborted by returning true. */
|
||||
bool ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for each dispenser in the specified chunk.
|
||||
Returns true if all dispensers processed, false if the callback aborted by returning true. */
|
||||
bool ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback a_Callback);
|
||||
|
||||
/** Calls the callback for each dropper in the specified chunk.
|
||||
Returns true if all droppers processed, false if the callback aborted by returning true. */
|
||||
bool ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback a_Callback);
|
||||
|
||||
/** Calls the callback for each dropspenser in the specified chunk.
|
||||
Returns true if all dropspensers processed, false if the callback aborted by returning true. */
|
||||
bool ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback a_Callback);
|
||||
|
||||
/** Calls the callback for each furnace in the specified chunk.
|
||||
Returns true if all furnaces processed, false if the callback aborted by returning true. */
|
||||
bool ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the block entity at the specified coords.
|
||||
Returns false if there's no block entity at those coords, true if found. */
|
||||
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the beacon at the specified coords.
|
||||
Returns false if there's no beacon at those coords, true if found. */
|
||||
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the bed at the specified coords.
|
||||
Returns false if there's no bed at those coords, true if found. */
|
||||
bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the brewingstand at the specified coords; returns false if there's no brewingstand at those coords, true if found */
|
||||
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the chest at the specified coords.
|
||||
Returns false if there's no chest at those coords, true if found. */
|
||||
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the dispenser at the specified coords.
|
||||
Returns false if there's no dispenser at those coords or callback returns true, returns true if found. */
|
||||
bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the dropper at the specified coords.
|
||||
Returns false if there's no dropper at those coords or callback returns true, returns true if found. */
|
||||
bool DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the dropspenser at the specified coords.
|
||||
Returns false if there's no dropspenser at those coords or callback returns true, returns true if found. */
|
||||
bool DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the furnace at the specified coords.
|
||||
Returns false if there's no furnace at those coords or callback returns true, returns true if found. */
|
||||
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the hopper at the specified coords.
|
||||
Returns false if there's no hopper at those coords or callback returns true, returns true if found. */
|
||||
bool DoWithHopperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cHopperCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the noteblock at the specified coords.
|
||||
Returns false if there's no noteblock at those coords or callback returns true, returns true if found. */
|
||||
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the command block at the specified coords.
|
||||
Returns false if there's no command block at those coords or callback returns true, returns true if found. */
|
||||
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the mob head block at the specified coords.
|
||||
Returns false if there's no mob head block at those coords or callback returns true, returns true if found. */
|
||||
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Calls the callback for the flower pot at the specified coords.
|
||||
Returns false if there's no flower pot at those coords or callback returns true, returns true if found. */
|
||||
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback a_Callback); // Lua-accessible
|
||||
|
||||
/** Retrieves the test on the sign at the specified coords.
|
||||
Returns false if there's no sign at those coords, true if found. */
|
||||
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
|
||||
Returns false if there's no block entity at those coords, and whatever the callback returns if found. */
|
||||
bool DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback); // Lua-acessible
|
||||
|
||||
/** Queues the chunk for preparing - making sure that it's generated and lit.
|
||||
The specified chunk is queued to be loaded or generated, and lit if needed.
|
||||
@ -324,9 +219,6 @@ public:
|
||||
/** Marks the chunk as failed-to-load */
|
||||
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);
|
||||
|
||||
/** Marks the chunk as being regenerated - all its clients want that chunk again (used by cWorld::RegenerateChunk()) */
|
||||
void MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
|
@ -121,7 +121,7 @@ void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, Priority a_Prior
|
||||
|
||||
|
||||
|
||||
void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, Priority a_Priority, cChunkClientHandles a_Clients)
|
||||
void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, Priority a_Priority, const std::vector<cClientHandle *> & a_Clients)
|
||||
{
|
||||
{
|
||||
cChunkCoords Chunk{a_ChunkX, a_ChunkZ};
|
||||
|
@ -72,7 +72,7 @@ public:
|
||||
|
||||
/** Queues a chunk to be sent to a specific client */
|
||||
void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, Priority a_Priority, cClientHandle * a_Client);
|
||||
void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, Priority a_Priority, cChunkClientHandles a_Client);
|
||||
void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, Priority a_Priority, const std::vector<cClientHandle *> & a_Clients);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -203,13 +203,15 @@ public:
|
||||
}
|
||||
|
||||
const auto BannerPos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace);
|
||||
return a_World.DoWithBlockEntityAt(BannerPos.x, BannerPos.y, BannerPos.z, [Color](cBlockEntity & a_BlockEntity)
|
||||
a_World.DoWithBlockEntityAt(BannerPos, [Color](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
ASSERT((a_BlockEntity.GetBlockType() == E_BLOCK_STANDING_BANNER) || (a_BlockEntity.GetBlockType() == E_BLOCK_WALL_BANNER));
|
||||
|
||||
auto & Banner = static_cast<cBannerEntity &>(a_BlockEntity);
|
||||
Banner.SetBaseColor(Color);
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -46,16 +46,12 @@ private:
|
||||
}
|
||||
|
||||
const auto PlacePos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace);
|
||||
a_World.DoWithBlockEntityAt(PlacePos.x, PlacePos.y, PlacePos.z, [&a_EquippedItem](cBlockEntity & a_Entity)
|
||||
a_World.DoWithBlockEntityAt(PlacePos, [&a_EquippedItem](cBlockEntity & a_Entity)
|
||||
{
|
||||
if (a_Entity.GetBlockType() != E_BLOCK_ENCHANTMENT_TABLE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
ASSERT(a_Entity.GetBlockType() == E_BLOCK_ENCHANTMENT_TABLE);
|
||||
|
||||
auto & EnchantingTable = static_cast<cEnchantingTableEntity &>(a_Entity);
|
||||
EnchantingTable.SetCustomName(a_EquippedItem.m_CustomName);
|
||||
return true;
|
||||
static_cast<cEnchantingTableEntity &>(a_Entity).SetCustomName(a_EquippedItem.m_CustomName);
|
||||
return false;
|
||||
});
|
||||
|
||||
return true;
|
||||
|
@ -75,26 +75,22 @@ public:
|
||||
auto BlockMeta = static_cast<NIBBLETYPE>(a_ClickedBlockFace);
|
||||
|
||||
// Use a callback to set the properties of the mob head block entity:
|
||||
a_World.DoWithBlockEntityAt(a_PlacePos.x, a_PlacePos.y, a_PlacePos.z, [&](cBlockEntity & a_BlockEntity)
|
||||
a_World.DoWithBlockEntityAt(a_PlacePos, [&](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_HEAD);
|
||||
|
||||
auto & MobHeadEntity = static_cast<cMobHeadEntity &>(a_BlockEntity);
|
||||
|
||||
int Rotation = 0;
|
||||
if (BlockMeta == 1)
|
||||
{
|
||||
if (a_BlockEntity.GetBlockType() != E_BLOCK_HEAD)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto & MobHeadEntity = static_cast<cMobHeadEntity &>(a_BlockEntity);
|
||||
|
||||
int Rotation = 0;
|
||||
if (BlockMeta == 1)
|
||||
{
|
||||
Rotation = FloorC(a_Player.GetYaw() * 16.0f / 360.0f + 0.5f) & 0x0f;
|
||||
}
|
||||
|
||||
MobHeadEntity.SetType(HeadType);
|
||||
MobHeadEntity.SetRotation(static_cast<eMobHeadRotation>(Rotation));
|
||||
MobHeadEntity.GetWorld()->BroadcastBlockEntity(MobHeadEntity.GetPos());
|
||||
return false;
|
||||
Rotation = FloorC(a_Player.GetYaw() * 16.0f / 360.0f + 0.5f) & 0x0f;
|
||||
}
|
||||
);
|
||||
|
||||
MobHeadEntity.SetType(HeadType);
|
||||
MobHeadEntity.SetRotation(static_cast<eMobHeadRotation>(Rotation));
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -243,23 +239,23 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it is a mob head, check the correct head type using the block entity:
|
||||
if (BlockType == E_BLOCK_HEAD)
|
||||
{
|
||||
bool IsWitherHead = false;
|
||||
a_World.DoWithBlockEntityAt(BlockX, BlockY, BlockZ, [&](cBlockEntity & a_Entity)
|
||||
{
|
||||
ASSERT(a_Entity.GetBlockType() == E_BLOCK_HEAD);
|
||||
auto & MobHead = static_cast<cMobHeadEntity &>(a_Entity);
|
||||
IsWitherHead = (MobHead.GetType() == SKULL_TYPE_WITHER);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
if (!IsWitherHead)
|
||||
// If it is a mob head, check it's a wither skull using the block entity:
|
||||
if (
|
||||
(BlockType == E_BLOCK_HEAD) &&
|
||||
!a_World.DoWithBlockEntityAt({ BlockX, BlockY, BlockZ }, [&](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (a_BlockEntity.GetBlockType() != E_BLOCK_HEAD)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return static_cast<cMobHeadEntity &>(a_BlockEntity).GetType() == SKULL_TYPE_WITHER;
|
||||
})
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Matched, continue checking
|
||||
AirBlocks.emplace_back(BlockX, BlockY, BlockZ, E_BLOCK_AIR, 0);
|
||||
} // for i - a_Image
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "Globals.h"
|
||||
|
||||
#include "Path.h"
|
||||
#include "BlockType.h"
|
||||
#include "../BlockInfo.h"
|
||||
#include "../Chunk.h"
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "Globals.h"
|
||||
#include "PathFinder.h"
|
||||
#include "BlockType.h"
|
||||
#include "../BlockInfo.h"
|
||||
#include "../Chunk.h"
|
||||
|
||||
|
@ -30,13 +30,8 @@ Implements the 1.11 protocol classes:
|
||||
|
||||
#include "../Mobs/IncludeAllMonsters.h"
|
||||
|
||||
#include "../BlockEntities/BannerEntity.h"
|
||||
#include "../BlockEntities/BeaconEntity.h"
|
||||
#include "../BlockEntities/BedEntity.h"
|
||||
#include "../BlockEntities/CommandBlockEntity.h"
|
||||
#include "../BlockEntities/MobHeadEntity.h"
|
||||
#include "../BlockEntities/MobSpawnerEntity.h"
|
||||
#include "../BlockEntities/FlowerPotEntity.h"
|
||||
|
||||
#include "../Root.h"
|
||||
#include "../Server.h"
|
||||
|
@ -45,13 +45,7 @@ Implements the 1.9 protocol classes:
|
||||
#include "../Mobs/IncludeAllMonsters.h"
|
||||
#include "../UI/HorseWindow.h"
|
||||
|
||||
#include "../BlockEntities/BannerEntity.h"
|
||||
#include "../BlockEntities/BeaconEntity.h"
|
||||
#include "../BlockEntities/CommandBlockEntity.h"
|
||||
#include "../BlockEntities/MobHeadEntity.h"
|
||||
#include "../BlockEntities/MobSpawnerEntity.h"
|
||||
#include "../BlockEntities/FlowerPotEntity.h"
|
||||
#include "../Bindings/PluginManager.h"
|
||||
|
||||
|
||||
|
||||
|
@ -31,9 +31,14 @@ namespace CommandBlockHandler
|
||||
return;
|
||||
}
|
||||
|
||||
a_Chunk.DoWithCommandBlockAt(a_Position, [](cCommandBlockEntity & a_CommandBlock)
|
||||
a_Chunk.DoWithBlockEntityAt(a_Position, [](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
a_CommandBlock.Activate();
|
||||
if (a_BlockEntity.GetBlockType() != E_BLOCK_COMMAND_BLOCK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static_cast<cCommandBlockEntity &>(a_BlockEntity).Activate();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
@ -46,9 +46,14 @@ namespace DropSpenserHandler
|
||||
|
||||
if (IsPoweredNow && !WasPoweredPreviously)
|
||||
{
|
||||
a_Chunk.DoWithDropSpenserAt(a_Position, [](cDropSpenserEntity & a_DropSpenser)
|
||||
a_Chunk.DoWithBlockEntityAt(a_Position, [](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
a_DropSpenser.Activate();
|
||||
if ((a_BlockEntity.GetBlockType() != E_BLOCK_DISPENSER) && (a_BlockEntity.GetBlockType() != E_BLOCK_DROPPER))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static_cast<cDropSpenserEntity &>(a_BlockEntity).Activate();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
@ -30,9 +30,14 @@ namespace HopperHandler
|
||||
return;
|
||||
}
|
||||
|
||||
a_Chunk.DoWithHopperAt(a_Position, [Power](cHopperEntity & a_Hopper)
|
||||
a_Chunk.DoWithBlockEntityAt(a_Position, [Power](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
a_Hopper.SetLocked(Power != 0);
|
||||
if (a_BlockEntity.GetBlockType() != E_BLOCK_HOPPER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static_cast<cHopperEntity &>(a_BlockEntity).SetLocked(Power != 0);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BlockType.h"
|
||||
#include "../RedstoneSimulator.h"
|
||||
#include "RedstoneSimulatorChunkData.h"
|
||||
|
||||
|
@ -31,9 +31,14 @@ namespace NoteBlockHandler
|
||||
return;
|
||||
}
|
||||
|
||||
a_Chunk.DoWithNoteBlockAt(a_Position, [](cNoteEntity & a_NoteBlock)
|
||||
a_Chunk.DoWithBlockEntityAt(a_Position, [](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
a_NoteBlock.MakeSound();
|
||||
if (a_BlockEntity.GetBlockType() != E_BLOCK_NOTE_BLOCK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static_cast<cNoteEntity &>(a_BlockEntity).MakeSound();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "RedstoneDataHelper.h"
|
||||
#include "ForEachSourceCallback.h"
|
||||
|
||||
#include "BlockType.h"
|
||||
#include "CommandBlockHandler.h"
|
||||
#include "DaylightSensorHandler.h"
|
||||
#include "DoorHandler.h"
|
||||
|
@ -22,14 +22,16 @@ namespace TrappedChestHandler
|
||||
static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i a_Position)
|
||||
{
|
||||
int NumberOfPlayers = 0;
|
||||
VERIFY(
|
||||
!a_Chunk.DoWithChestAt(a_Position, [&](cChestEntity & a_Chest)
|
||||
a_Chunk.DoWithBlockEntityAt(a_Position, [&NumberOfPlayers](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
if (a_BlockEntity.GetBlockType() != E_BLOCK_TRAPPED_CHEST)
|
||||
{
|
||||
ASSERT(a_Chest.GetBlockType() == E_BLOCK_TRAPPED_CHEST);
|
||||
NumberOfPlayers = a_Chest.GetNumberOfPlayers();
|
||||
return true;
|
||||
})
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
NumberOfPlayers = static_cast<cChestEntity &>(a_BlockEntity).GetNumberOfPlayers();
|
||||
return false;
|
||||
});
|
||||
|
||||
return static_cast<unsigned char>(std::min(NumberOfPlayers, 15));
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "Globals.h"
|
||||
#include "VaporizeFluidSimulator.h"
|
||||
#include "BlockType.h"
|
||||
#include "../OpaqueWorld.h"
|
||||
#include "../Chunk.h"
|
||||
#include "../Blocks/BroadcastInterface.h"
|
||||
|
217
src/World.cpp
217
src/World.cpp
@ -29,7 +29,7 @@
|
||||
#include "Entities/TNTEntity.h"
|
||||
|
||||
#include "BlockEntities/CommandBlockEntity.h"
|
||||
#include "BlockEntities/BeaconEntity.h"
|
||||
#include "BlockEntities/SignEntity.h"
|
||||
|
||||
// Simulators:
|
||||
#include "Simulator/FloodyFluidSimulator.h"
|
||||
@ -1342,60 +1342,6 @@ bool cWorld::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityC
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, cBrewingstandCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.ForEachBrewingstandInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.ForEachChestInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.ForEachDispenserInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.ForEachDropperInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.ForEachDropSpenserInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.ForEachFurnaceInChunk(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData)
|
||||
{
|
||||
cLock Lock(*this);
|
||||
@ -1431,126 +1377,9 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback a_Callback)
|
||||
bool cWorld::DoWithBlockEntityAt(const Vector3i a_Position, cBlockEntityCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithBeaconAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithBedAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithBrewingstandAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithChestAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithDispenserAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithDropperAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithDropSpenserAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithFurnaceAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithHopperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cHopperCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithHopperAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithNoteBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback a_Callback)
|
||||
{
|
||||
return m_ChunkMap.DoWithFlowerPotAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
|
||||
return m_ChunkMap.DoWithBlockEntityAt(a_Position, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
@ -1559,7 +1388,20 @@ bool cWorld::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlower
|
||||
|
||||
bool cWorld::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
|
||||
{
|
||||
return m_ChunkMap.GetSignLines(a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4);
|
||||
return DoWithBlockEntityAt({ a_BlockX, a_BlockY, a_BlockZ }, [&a_Line1, &a_Line2, &a_Line3, &a_Line4](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
if ((a_BlockEntity.GetBlockType() != E_BLOCK_WALLSIGN) && (a_BlockEntity.GetBlockType() != E_BLOCK_SIGN_POST))
|
||||
{
|
||||
return false; // Not a sign
|
||||
}
|
||||
|
||||
const auto & Sign = static_cast<cSignEntity &>(a_BlockEntity);
|
||||
a_Line1 = Sign.GetLine(0);
|
||||
a_Line2 = Sign.GetLine(1);
|
||||
a_Line3 = Sign.GetLine(2);
|
||||
a_Line4 = Sign.GetLine(3);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -2672,6 +2514,8 @@ void cWorld::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
|
||||
|
||||
bool cWorld::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)
|
||||
{
|
||||
// TODO: rvalue these strings
|
||||
|
||||
AString Line1(a_Line1);
|
||||
AString Line2(a_Line2);
|
||||
AString Line3(a_Line3);
|
||||
@ -2682,7 +2526,18 @@ bool cWorld::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AStrin
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_ChunkMap.SetSignLines(a_BlockX, a_BlockY, a_BlockZ, Line1, Line2, Line3, Line4))
|
||||
if (
|
||||
DoWithBlockEntityAt({ a_BlockX, a_BlockY, a_BlockZ }, [&Line1, &Line2, &Line3, &Line4](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
if ((a_BlockEntity.GetBlockType() != E_BLOCK_WALLSIGN) && (a_BlockEntity.GetBlockType() != E_BLOCK_SIGN_POST))
|
||||
{
|
||||
return false; // Not a sign
|
||||
}
|
||||
|
||||
static_cast<cSignEntity &>(a_BlockEntity).SetLines(Line1, Line2, Line3, Line4);
|
||||
return true;
|
||||
})
|
||||
)
|
||||
{
|
||||
cRoot::Get()->GetPluginManager()->CallHookUpdatedSign(*this, a_BlockX, a_BlockY, a_BlockZ, Line1, Line2, Line3, Line4, a_Player);
|
||||
return true;
|
||||
@ -2697,12 +2552,16 @@ bool cWorld::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AStrin
|
||||
|
||||
bool cWorld::SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command)
|
||||
{
|
||||
return DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, [&](cCommandBlockEntity & a_CommandBlock)
|
||||
return DoWithBlockEntityAt({ a_BlockX, a_BlockY, a_BlockZ }, [&](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
if (a_BlockEntity.GetBlockType() != E_BLOCK_COMMAND_BLOCK)
|
||||
{
|
||||
a_CommandBlock.SetCommand(a_Command);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
static_cast<cCommandBlockEntity &>(a_BlockEntity).SetCommand(a_Command);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
61
src/World.h
61
src/World.h
@ -615,71 +615,14 @@ public:
|
||||
/** Calls the callback for each block entity in the specified chunk; returns true if all block entities processed, false if the callback aborted by returning true */
|
||||
bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for each brewingstand in the specified chunk; returns true if all brewingstands processed, false if the callback aborted by returning true */
|
||||
bool ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, cBrewingstandCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for each chest in the specified chunk; returns true if all chests processed, false if the callback aborted by returning true */
|
||||
bool ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for each dispenser in the specified chunk; returns true if all dispensers processed, false if the callback aborted by returning true */
|
||||
bool ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback a_Callback);
|
||||
|
||||
/** Calls the callback for each dropper in the specified chunk; returns true if all droppers processed, false if the callback aborted by returning true */
|
||||
bool ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback a_Callback);
|
||||
|
||||
/** Calls the callback for each dropspenser in the specified chunk; returns true if all dropspensers processed, false if the callback aborted by returning true */
|
||||
bool ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback a_Callback);
|
||||
|
||||
/** Calls the callback for each furnace in the specified chunk; returns true if all furnaces processed, false if the callback aborted by returning true */
|
||||
bool ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Does an explosion with the specified strength at the specified coordinates.
|
||||
Executes the HOOK_EXPLODING and HOOK_EXPLODED hooks as part of the processing.
|
||||
a_SourceData exact type depends on the a_Source, see the declaration of the esXXX constants in Defines.h for details.
|
||||
Exported to Lua manually in ManualBindings_World.cpp in order to support the variable a_SourceData param. */
|
||||
virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData) override;
|
||||
|
||||
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
|
||||
virtual bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback a_Callback) override; // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
|
||||
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the bed at the specified coords; returns false if there's no bed at those coords, true if found */
|
||||
virtual bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback a_Callback) override; // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the brewingstand at the specified coords; returns false if there's no brewingstand at those coords, true if found */
|
||||
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback a_Callback); // Lua-acessible
|
||||
|
||||
/** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
|
||||
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the dispenser at the specified coords; returns false if there's no dispenser at those coords or callback returns true, returns true if found */
|
||||
bool DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the dropper at the specified coords; returns false if there's no dropper at those coords or callback returns true, returns true if found */
|
||||
bool DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the dropspenser at the specified coords; returns false if there's no dropspenser at those coords or callback returns true, returns true if found */
|
||||
bool DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found */
|
||||
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the hopper at the specified coords; returns false if there's no hopper at those coords or callback returns true, returns true if found */
|
||||
bool DoWithHopperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cHopperCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found */
|
||||
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */
|
||||
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */
|
||||
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/** Calls the callback for the flower pot at the specified coords; returns false if there's no flower pot at those coords or callback returns true, returns true if found */
|
||||
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback a_Callback); // Exported in ManualBindings.cpp
|
||||
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, and whatever the callback returns if found. */
|
||||
virtual bool DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback) override; // Exported in ManualBindings.cpp
|
||||
|
||||
/** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */
|
||||
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Exported in ManualBindings.cpp
|
||||
|
Loading…
x
Reference in New Issue
Block a user