Merge pull request #1154 from mc-server/trappedchests
Implemented trapped chests & others
This commit is contained in:
commit
5f72cdac38
@ -28,24 +28,26 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
|
||||
switch (a_BlockType)
|
||||
{
|
||||
case E_BLOCK_BEACON: return new cBeaconEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World, a_BlockType);
|
||||
case E_BLOCK_COMMAND_BLOCK: return new cCommandBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_DISPENSER: return new cDispenserEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_DROPPER: return new cDropperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_FLOWER_POT: return new cFlowerPotEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
||||
case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
||||
case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
||||
case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_TRAPPED_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World, a_BlockType);
|
||||
case E_BLOCK_WALLSIGN: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_NOTE_BLOCK: return new cNoteEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
}
|
||||
LOGD("%s: Requesting creation of an unknown block entity - block type %d (%s)",
|
||||
__FUNCTION__, a_BlockType, ItemTypeToString(a_BlockType).c_str()
|
||||
);
|
||||
ASSERT(!"Requesting creation of an unknown block entity");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,9 @@
|
||||
|
||||
|
||||
|
||||
cChestEntity::cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
|
||||
super(E_BLOCK_CHEST, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World)
|
||||
cChestEntity::cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World, BLOCKTYPE a_Type) :
|
||||
super(a_Type, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
|
||||
m_NumActivePlayers(0)
|
||||
{
|
||||
cBlockEntityWindowOwner::SetBlockEntity(this);
|
||||
}
|
||||
@ -113,7 +114,7 @@ void cChestEntity::UsedBy(cPlayer * a_Player)
|
||||
// The few false positives aren't much to worry about
|
||||
int ChunkX, ChunkZ;
|
||||
cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ);
|
||||
m_World->MarkChunkDirty(ChunkX, ChunkZ);
|
||||
m_World->MarkChunkDirty(ChunkX, ChunkZ, true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,8 +34,8 @@ public:
|
||||
|
||||
// tolua_end
|
||||
|
||||
/// Constructor used for normal operation
|
||||
cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
|
||||
/** Constructor used for normal operation */
|
||||
cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World, BLOCKTYPE a_Type);
|
||||
|
||||
virtual ~cChestEntity();
|
||||
|
||||
@ -48,8 +48,20 @@ public:
|
||||
virtual void SendTo(cClientHandle & a_Client) override;
|
||||
virtual void UsedBy(cPlayer * a_Player) override;
|
||||
|
||||
/// Opens a new chest window for this chest. Scans for neighbors to open a double chest window, if appropriate.
|
||||
/** Opens a new chest window for this chest.
|
||||
Scans for neighbors to open a double chest window, if appropriate. */
|
||||
void OpenNewWindow(void);
|
||||
|
||||
/** Gets the number of players who currently have this chest open */
|
||||
int GetNumberOfPlayers(void) const { return m_NumActivePlayers; }
|
||||
|
||||
/** Sets the number of players who currently have this chest open */
|
||||
void SetNumberOfPlayers(int a_NumActivePlayers) { m_NumActivePlayers = a_NumActivePlayers; }
|
||||
|
||||
private:
|
||||
|
||||
/** Number of players who currently have this chest open */
|
||||
int m_NumActivePlayers;
|
||||
} ; // tolua_export
|
||||
|
||||
|
||||
|
@ -157,6 +157,7 @@ bool cHopperEntity::MoveItemsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
||||
bool res = false;
|
||||
switch (a_Chunk.GetBlock(m_RelX, m_PosY + 1, m_RelZ))
|
||||
{
|
||||
case E_BLOCK_TRAPPED_CHEST:
|
||||
case E_BLOCK_CHEST:
|
||||
{
|
||||
// Chests have special handling because of double-chests
|
||||
@ -322,6 +323,7 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
|
||||
bool res = false;
|
||||
switch (DestChunk->GetBlock(OutRelX, OutY, OutRelZ))
|
||||
{
|
||||
case E_BLOCK_TRAPPED_CHEST:
|
||||
case E_BLOCK_CHEST:
|
||||
{
|
||||
// Chests have special handling because of double-chests
|
||||
@ -378,7 +380,7 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the chest is a double-chest, if so, try to move from there:
|
||||
// Check if the chest is a double-chest (chest directly above was empty), if so, try to move from there:
|
||||
static const struct
|
||||
{
|
||||
int x, z;
|
||||
@ -395,13 +397,18 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk)
|
||||
int x = m_RelX + Coords[i].x;
|
||||
int z = m_RelZ + Coords[i].z;
|
||||
cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z);
|
||||
if (
|
||||
(Neighbor == NULL) ||
|
||||
(Neighbor->GetBlock(x, m_PosY + 1, z) != E_BLOCK_CHEST)
|
||||
)
|
||||
if (Neighbor == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BLOCKTYPE Block = Neighbor->GetBlock(x, m_PosY + 1, z);
|
||||
if (Block != Chest->GetBlockType())
|
||||
{
|
||||
// Not the same kind of chest
|
||||
continue;
|
||||
}
|
||||
|
||||
Chest = (cChestEntity *)Neighbor->GetBlockEntity(m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z);
|
||||
if (Chest == NULL)
|
||||
{
|
||||
@ -550,10 +557,11 @@ bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_Block
|
||||
}
|
||||
if (MoveItemsToGrid(*Chest))
|
||||
{
|
||||
// Chest block directly connected was not full
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the chest is a double-chest, if so, try to move into the other half:
|
||||
// Check if the chest is a double-chest (chest block directly connected was full), if so, try to move into the other half:
|
||||
static const struct
|
||||
{
|
||||
int x, z;
|
||||
@ -572,13 +580,18 @@ bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_Block
|
||||
int x = RelX + Coords[i].x;
|
||||
int z = RelZ + Coords[i].z;
|
||||
cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z);
|
||||
if (
|
||||
(Neighbor == NULL) ||
|
||||
(Neighbor->GetBlock(x, a_BlockY, z) != E_BLOCK_CHEST)
|
||||
)
|
||||
if (Neighbor == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BLOCKTYPE Block = Neighbor->GetBlock(x, a_BlockY, z);
|
||||
if (Block != Chest->GetBlockType())
|
||||
{
|
||||
// Not the same kind of chest
|
||||
continue;
|
||||
}
|
||||
|
||||
Chest = (cChestEntity *)Neighbor->GetBlockEntity(a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z);
|
||||
if (Chest == NULL)
|
||||
{
|
||||
|
@ -101,6 +101,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
|
||||
a_Info[E_BLOCK_NEW_LEAVES ].m_SpreadLightFalloff = 1;
|
||||
a_Info[E_BLOCK_SIGN_POST ].m_SpreadLightFalloff = 1;
|
||||
a_Info[E_BLOCK_TORCH ].m_SpreadLightFalloff = 1;
|
||||
a_Info[E_BLOCK_TRAPPED_CHEST ].m_SpreadLightFalloff = 1;
|
||||
a_Info[E_BLOCK_TRIPWIRE ].m_SpreadLightFalloff = 1;
|
||||
a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_SpreadLightFalloff = 1;
|
||||
a_Info[E_BLOCK_VINES ].m_SpreadLightFalloff = 1;
|
||||
@ -162,6 +163,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
|
||||
a_Info[E_BLOCK_STATIONARY_WATER ].m_Transparent = true;
|
||||
a_Info[E_BLOCK_STONE_BUTTON ].m_Transparent = true;
|
||||
a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_Transparent = true;
|
||||
a_Info[E_BLOCK_TRAPPED_CHEST ].m_Transparent = true;
|
||||
a_Info[E_BLOCK_TRIPWIRE ].m_Transparent = true;
|
||||
a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_Transparent = true;
|
||||
a_Info[E_BLOCK_TALL_GRASS ].m_Transparent = true;
|
||||
@ -287,6 +289,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
|
||||
a_Info[E_BLOCK_TALL_GRASS ].m_IsSnowable = false;
|
||||
a_Info[E_BLOCK_TNT ].m_IsSnowable = false;
|
||||
a_Info[E_BLOCK_TORCH ].m_IsSnowable = false;
|
||||
a_Info[E_BLOCK_TRAPPED_CHEST ].m_IsSnowable = false;
|
||||
a_Info[E_BLOCK_TRIPWIRE ].m_IsSnowable = false;
|
||||
a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_IsSnowable = false;
|
||||
a_Info[E_BLOCK_VINES ].m_IsSnowable = false;
|
||||
|
@ -44,16 +44,16 @@ public:
|
||||
}
|
||||
double yaw = a_Player->GetYaw();
|
||||
if (
|
||||
(Area.GetRelBlockType(0, 0, 1) == E_BLOCK_CHEST) ||
|
||||
(Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
|
||||
(Area.GetRelBlockType(0, 0, 1) == m_BlockType) ||
|
||||
(Area.GetRelBlockType(2, 0, 1) == m_BlockType)
|
||||
)
|
||||
{
|
||||
a_BlockMeta = ((yaw >= -90) && (yaw < 90)) ? 2 : 3;
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
(Area.GetRelBlockType(0, 0, 1) == E_BLOCK_CHEST) ||
|
||||
(Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
|
||||
(Area.GetRelBlockType(0, 0, 1) == m_BlockType) ||
|
||||
(Area.GetRelBlockType(2, 0, 1) == m_BlockType)
|
||||
)
|
||||
{
|
||||
// FIXME: This is unreachable, as the condition is the same as the above one
|
||||
@ -130,12 +130,12 @@ public:
|
||||
}
|
||||
|
||||
int NumChestNeighbors = 0;
|
||||
if (Area.GetRelBlockType(1, 0, 2) == E_BLOCK_CHEST)
|
||||
if (Area.GetRelBlockType(1, 0, 2) == m_BlockType)
|
||||
{
|
||||
if (
|
||||
(Area.GetRelBlockType(0, 0, 2) == E_BLOCK_CHEST) ||
|
||||
(Area.GetRelBlockType(1, 0, 1) == E_BLOCK_CHEST) ||
|
||||
(Area.GetRelBlockType(1, 0, 3) == E_BLOCK_CHEST)
|
||||
(Area.GetRelBlockType(0, 0, 2) == m_BlockType) ||
|
||||
(Area.GetRelBlockType(1, 0, 1) == m_BlockType) ||
|
||||
(Area.GetRelBlockType(1, 0, 3) == m_BlockType)
|
||||
)
|
||||
{
|
||||
// Already a doublechest neighbor, disallow:
|
||||
@ -143,12 +143,12 @@ public:
|
||||
}
|
||||
NumChestNeighbors += 1;
|
||||
}
|
||||
if (Area.GetRelBlockType(3, 0, 2) == E_BLOCK_CHEST)
|
||||
if (Area.GetRelBlockType(3, 0, 2) == m_BlockType)
|
||||
{
|
||||
if (
|
||||
(Area.GetRelBlockType(4, 0, 2) == E_BLOCK_CHEST) ||
|
||||
(Area.GetRelBlockType(3, 0, 1) == E_BLOCK_CHEST) ||
|
||||
(Area.GetRelBlockType(3, 0, 3) == E_BLOCK_CHEST)
|
||||
(Area.GetRelBlockType(4, 0, 2) == m_BlockType) ||
|
||||
(Area.GetRelBlockType(3, 0, 1) == m_BlockType) ||
|
||||
(Area.GetRelBlockType(3, 0, 3) == m_BlockType)
|
||||
)
|
||||
{
|
||||
// Already a doublechest neighbor, disallow:
|
||||
@ -156,12 +156,12 @@ public:
|
||||
}
|
||||
NumChestNeighbors += 1;
|
||||
}
|
||||
if (Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
|
||||
if (Area.GetRelBlockType(2, 0, 1) == m_BlockType)
|
||||
{
|
||||
if (
|
||||
(Area.GetRelBlockType(2, 0, 0) == E_BLOCK_CHEST) ||
|
||||
(Area.GetRelBlockType(1, 0, 1) == E_BLOCK_CHEST) ||
|
||||
(Area.GetRelBlockType(3, 0, 1) == E_BLOCK_CHEST)
|
||||
(Area.GetRelBlockType(2, 0, 0) == m_BlockType) ||
|
||||
(Area.GetRelBlockType(1, 0, 1) == m_BlockType) ||
|
||||
(Area.GetRelBlockType(3, 0, 1) == m_BlockType)
|
||||
)
|
||||
{
|
||||
// Already a doublechest neighbor, disallow:
|
||||
@ -169,12 +169,12 @@ public:
|
||||
}
|
||||
NumChestNeighbors += 1;
|
||||
}
|
||||
if (Area.GetRelBlockType(2, 0, 3) == E_BLOCK_CHEST)
|
||||
if (Area.GetRelBlockType(2, 0, 3) == m_BlockType)
|
||||
{
|
||||
if (
|
||||
(Area.GetRelBlockType(2, 0, 4) == E_BLOCK_CHEST) ||
|
||||
(Area.GetRelBlockType(1, 0, 3) == E_BLOCK_CHEST) ||
|
||||
(Area.GetRelBlockType(3, 0, 3) == E_BLOCK_CHEST)
|
||||
(Area.GetRelBlockType(2, 0, 4) == m_BlockType) ||
|
||||
(Area.GetRelBlockType(1, 0, 3) == m_BlockType) ||
|
||||
(Area.GetRelBlockType(3, 0, 3) == m_BlockType)
|
||||
)
|
||||
{
|
||||
// Already a doublechest neighbor, disallow:
|
||||
@ -217,7 +217,7 @@ public:
|
||||
/// If there's a chest in the a_Area in the specified coords, modifies its meta to a_NewMeta and returns true.
|
||||
bool CheckAndAdjustNeighbor(cChunkInterface & a_ChunkInterface, const cBlockArea & a_Area, int a_RelX, int a_RelZ, NIBBLETYPE a_NewMeta)
|
||||
{
|
||||
if (a_Area.GetRelBlockType(a_RelX, 0, a_RelZ) != E_BLOCK_CHEST)
|
||||
if (a_Area.GetRelBlockType(a_RelX, 0, a_RelZ) != m_BlockType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -228,7 +228,7 @@ public:
|
||||
|
||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||
{
|
||||
a_Pickups.push_back(cItem(E_BLOCK_CHEST, 1, 0));
|
||||
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
|
||||
}
|
||||
} ;
|
||||
|
||||
|
@ -176,7 +176,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
{
|
||||
switch(a_BlockType)
|
||||
{
|
||||
// Block handlers, alphabetically sorted:
|
||||
// Block handlers, alphabetically sorted:
|
||||
case E_BLOCK_ACACIA_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||
case E_BLOCK_ACTIVATOR_RAIL: return new cBlockRailHandler (a_BlockType);
|
||||
case E_BLOCK_ANVIL: return new cBlockAnvilHandler (a_BlockType);
|
||||
@ -238,9 +238,9 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_LAPIS_ORE: return new cBlockOreHandler (a_BlockType);
|
||||
case E_BLOCK_LAVA: return new cBlockLavaHandler (a_BlockType);
|
||||
case E_BLOCK_LEAVES: return new cBlockLeavesHandler (a_BlockType);
|
||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return new cBlockPressurePlateHandler(a_BlockType);
|
||||
case E_BLOCK_LILY_PAD: return new cBlockLilypadHandler (a_BlockType);
|
||||
case E_BLOCK_LIT_FURNACE: return new cBlockFurnaceHandler (a_BlockType);
|
||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return new cBlockPressurePlateHandler(a_BlockType);
|
||||
case E_BLOCK_LOG: return new cBlockSidewaysHandler (a_BlockType);
|
||||
case E_BLOCK_MELON: return new cBlockMelonHandler (a_BlockType);
|
||||
case E_BLOCK_MELON_STEM: return new cBlockStemsHandler (a_BlockType);
|
||||
@ -293,6 +293,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||
case E_BLOCK_TORCH: return new cBlockTorchHandler (a_BlockType);
|
||||
case E_BLOCK_TRAPDOOR: return new cBlockTrapdoorHandler (a_BlockType);
|
||||
case E_BLOCK_TNT: return new cBlockTNTHandler (a_BlockType);
|
||||
case E_BLOCK_TRAPPED_CHEST: return new cBlockChestHandler (a_BlockType);
|
||||
case E_BLOCK_TRIPWIRE: return new cBlockTripwireHandler (a_BlockType);
|
||||
case E_BLOCK_TRIPWIRE_HOOK: return new cBlockTripwireHookHandler (a_BlockType);
|
||||
case E_BLOCK_VINES: return new cBlockVineHandler (a_BlockType);
|
||||
|
@ -85,7 +85,7 @@ int cBlockPistonHandler::FirstPassthroughBlock(int a_PistonX, int a_PistonY, int
|
||||
NIBBLETYPE currMeta;
|
||||
AddPistonDir(a_PistonX, a_PistonY, a_PistonZ, pistonmeta, 1);
|
||||
a_World->GetBlockTypeMeta(a_PistonX, a_PistonY, a_PistonZ, currBlock, currMeta);
|
||||
if (CanBreakPush(currBlock))
|
||||
if (cBlockInfo::IsPistonBreakable(currBlock))
|
||||
{
|
||||
// This block breaks when pushed, extend up to here
|
||||
return ret;
|
||||
|
@ -104,6 +104,7 @@ private:
|
||||
case E_BLOCK_ENCHANTMENT_TABLE:
|
||||
case E_BLOCK_END_PORTAL:
|
||||
case E_BLOCK_END_PORTAL_FRAME:
|
||||
// Notice the lack of an E_BLOCK_ENDER_CHEST here; its because ender chests can totally be pushed/pulled in MCS :)
|
||||
case E_BLOCK_FURNACE:
|
||||
case E_BLOCK_LIT_FURNACE:
|
||||
case E_BLOCK_HOPPER:
|
||||
@ -113,6 +114,7 @@ private:
|
||||
case E_BLOCK_NOTE_BLOCK:
|
||||
case E_BLOCK_OBSIDIAN:
|
||||
case E_BLOCK_PISTON_EXTENSION:
|
||||
case E_BLOCK_TRAPPED_CHEST:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -126,24 +128,10 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Returns true if the specified block can be pushed by a piston and broken / replaced
|
||||
static inline bool CanBreakPush(BLOCKTYPE a_BlockType) { return cBlockInfo::IsPistonBreakable(a_BlockType); }
|
||||
|
||||
/// Returns true if the specified block can be pulled by a sticky piston
|
||||
static inline bool CanPull(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
||||
{
|
||||
switch (a_BlockType)
|
||||
{
|
||||
case E_BLOCK_LAVA:
|
||||
case E_BLOCK_STATIONARY_LAVA:
|
||||
case E_BLOCK_STATIONARY_WATER:
|
||||
case E_BLOCK_WATER:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (CanBreakPush(a_BlockType))
|
||||
if (cBlockInfo::IsPistonBreakable(a_BlockType))
|
||||
{
|
||||
return false; // CanBreakPush returns true, but we need false to prevent pulling
|
||||
}
|
||||
|
@ -1301,6 +1301,7 @@ void cChunk::CreateBlockEntities(void)
|
||||
switch (BlockType)
|
||||
{
|
||||
case E_BLOCK_BEACON:
|
||||
case E_BLOCK_TRAPPED_CHEST:
|
||||
case E_BLOCK_CHEST:
|
||||
case E_BLOCK_COMMAND_BLOCK:
|
||||
case E_BLOCK_DISPENSER:
|
||||
@ -1431,6 +1432,7 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType,
|
||||
switch (a_BlockType)
|
||||
{
|
||||
case E_BLOCK_BEACON:
|
||||
case E_BLOCK_TRAPPED_CHEST:
|
||||
case E_BLOCK_CHEST:
|
||||
case E_BLOCK_COMMAND_BLOCK:
|
||||
case E_BLOCK_DISPENSER:
|
||||
@ -2150,7 +2152,7 @@ bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallb
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((*itr)->GetBlockType() != E_BLOCK_CHEST)
|
||||
if (((*itr)->GetBlockType() != E_BLOCK_CHEST) && ((*itr)->GetBlockType() != E_BLOCK_TRAPPED_CHEST)) // Trapped chests use normal chests' handlers
|
||||
{
|
||||
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
||||
return false;
|
||||
@ -2530,8 +2532,8 @@ cChunk * cChunk::GetRelNeighborChunk(int a_RelX, int a_RelZ)
|
||||
{
|
||||
int BlockX = m_PosX * cChunkDef::Width + a_RelX;
|
||||
int BlockZ = m_PosZ * cChunkDef::Width + a_RelZ;
|
||||
int BlockY, ChunkX, ChunkZ;
|
||||
AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
int ChunkX, ChunkZ;
|
||||
BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
|
||||
return m_ChunkMap->GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
|
||||
}
|
||||
|
||||
|
@ -847,7 +847,22 @@ void cChunkMap::WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_M
|
||||
|
||||
|
||||
|
||||
void cChunkMap::MarkChunkDirty (int a_ChunkX, int a_ChunkZ)
|
||||
void cChunkMap::MarkRedstoneDirty(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
if ((Chunk == NULL) || !Chunk->IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Chunk->SetIsRedstoneDirty(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::MarkChunkDirty(int a_ChunkX, int a_ChunkZ, bool a_MarkRedstoneDirty)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
@ -856,6 +871,10 @@ void cChunkMap::MarkChunkDirty (int a_ChunkX, int a_ChunkZ)
|
||||
return;
|
||||
}
|
||||
Chunk->MarkDirty();
|
||||
if (a_MarkRedstoneDirty)
|
||||
{
|
||||
Chunk->SetIsRedstoneDirty(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -106,7 +106,8 @@ public:
|
||||
/** Wakes up the simulators for the specified area of blocks */
|
||||
void WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ);
|
||||
|
||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkZ);
|
||||
void MarkRedstoneDirty (int a_ChunkX, int a_ChunkZ);
|
||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkZ, bool a_MarkRedstoneDirty = false);
|
||||
void MarkChunkSaving (int a_ChunkX, int a_ChunkZ);
|
||||
void MarkChunkSaved (int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
class cExpOrb :
|
||||
public cEntity
|
||||
{
|
||||
typedef cExpOrb super;
|
||||
typedef cEntity super;
|
||||
|
||||
public:
|
||||
// tolua_end
|
||||
|
@ -200,8 +200,8 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z)
|
||||
int BlockX = m_CenterX + ((a_X - (m_Width / 2)) * PixelWidth);
|
||||
int BlockZ = m_CenterZ + ((a_Z - (m_Height / 2)) * PixelWidth);
|
||||
|
||||
int ChunkX, ChunkY, ChunkZ;
|
||||
m_World->BlockToChunk(BlockX, 0, BlockZ, ChunkX, ChunkY, ChunkZ);
|
||||
int ChunkX, ChunkZ;
|
||||
cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
|
||||
|
||||
int RelX = BlockX - (ChunkX * cChunkDef::Width);
|
||||
int RelZ = BlockZ - (ChunkZ * cChunkDef::Width);
|
||||
|
@ -262,7 +262,7 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
|
||||
AString HexDump;
|
||||
if (Response.compare(0, prefix.size(), prefix))
|
||||
{
|
||||
LOGINFO("User \"%s\" failed to auth, bad http status line received", a_UserName.c_str());
|
||||
LOGINFO("User %s failed to auth, bad http status line received", a_UserName.c_str());
|
||||
LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
|
||||
return false;
|
||||
}
|
||||
@ -271,7 +271,7 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
|
||||
size_t idxHeadersEnd = Response.find("\r\n\r\n");
|
||||
if (idxHeadersEnd == AString::npos)
|
||||
{
|
||||
LOGINFO("User \"%s\" failed to authenticate, bad http response header received", a_UserName.c_str());
|
||||
LOGINFO("User %s failed to authenticate, bad http response header received", a_UserName.c_str());
|
||||
LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
|
||||
return false;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "BoundingBox.h"
|
||||
#include "../BlockEntities/DropSpenserEntity.h"
|
||||
#include "../BlockEntities/NoteEntity.h"
|
||||
#include "../BlockEntities/ChestEntity.h"
|
||||
#include "../BlockEntities/CommandBlockEntity.h"
|
||||
#include "../Entities/TNTEntity.h"
|
||||
#include "../Entities/Pickup.h"
|
||||
@ -15,8 +16,6 @@
|
||||
#include "../Blocks/BlockPiston.h"
|
||||
#include "../Blocks/BlockTripwireHook.h"
|
||||
|
||||
#define WAKE_SIMULATOR_IF_DIRTY(a_Chunk, a_BlockX, a_BlockY, a_BlockZ) if (a_Chunk->IsRedstoneDirty()) WakeUp(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
|
||||
|
||||
|
||||
|
||||
|
||||
@ -63,14 +62,16 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
|
||||
int RelZ = 0;
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE Meta;
|
||||
cChunk * OtherChunk = a_Chunk;
|
||||
|
||||
if (a_OtherChunk != NULL)
|
||||
{
|
||||
RelX = a_BlockX - a_OtherChunk->GetPosX() * cChunkDef::Width;
|
||||
RelZ = a_BlockZ - a_OtherChunk->GetPosZ() * cChunkDef::Width;
|
||||
a_OtherChunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta);
|
||||
OtherChunk = a_OtherChunk;
|
||||
|
||||
// If a_OtherChunk is passed (not NULL), it is the chunk that had a block change, and a_Chunk will be the neighbouring chunk of that block
|
||||
// Because said neighbouring chunk does not know of this change but still needs to update its redstone, we set it to dirty
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -95,8 +96,6 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
|
||||
{
|
||||
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list as it no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
|
||||
itr = PoweredBlocks->erase(itr);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
OtherChunk->SetIsRedstoneDirty(true);
|
||||
continue;
|
||||
}
|
||||
else if (
|
||||
@ -105,34 +104,13 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
|
||||
((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) ||
|
||||
((Block == E_BLOCK_DETECTOR_RAIL) && ((Meta & 0x08) == 0)) ||
|
||||
(((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) ||
|
||||
(((Block == E_BLOCK_STONE_PRESSURE_PLATE) || (Block == E_BLOCK_WOODEN_PRESSURE_PLATE)) && (Meta == 0)) ||
|
||||
(((Block == E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE) || (Block == E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE)) && (Meta == 0)) ||
|
||||
((Block == E_BLOCK_TRIPWIRE_HOOK) && ((Meta & 0x08) == 0))
|
||||
)
|
||||
{
|
||||
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
|
||||
itr = PoweredBlocks->erase(itr);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
OtherChunk->SetIsRedstoneDirty(true);
|
||||
continue;
|
||||
}
|
||||
else if (Block == E_BLOCK_DAYLIGHT_SENSOR)
|
||||
{
|
||||
if (!m_World.IsChunkLighted(OtherChunk->GetPosX(), OtherChunk->GetPosZ()))
|
||||
{
|
||||
m_World.QueueLightChunk(OtherChunk->GetPosX(), OtherChunk->GetPosZ());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (OtherChunk->GetTimeAlteredLight(OtherChunk->GetSkyLight(RelX, a_BlockY + 1, RelZ)) <= 7)
|
||||
{
|
||||
itr = PoweredBlocks->erase(itr);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
OtherChunk->SetIsRedstoneDirty(true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
|
||||
@ -146,23 +124,17 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
|
||||
{
|
||||
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
|
||||
itr = LinkedPoweredBlocks->erase(itr);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
OtherChunk->SetIsRedstoneDirty(true);
|
||||
continue;
|
||||
}
|
||||
else if (
|
||||
// Things that can send power through a block but which depends on meta
|
||||
((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) ||
|
||||
((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) ||
|
||||
(((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) ||
|
||||
(((Block == E_BLOCK_STONE_PRESSURE_PLATE) || (Block == E_BLOCK_WOODEN_PRESSURE_PLATE)) && (Meta == 0)) ||
|
||||
(((Block == E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE) || (Block == E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE)) && (Meta == 0))
|
||||
(((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta)))
|
||||
)
|
||||
{
|
||||
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
|
||||
itr = LinkedPoweredBlocks->erase(itr);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
OtherChunk->SetIsRedstoneDirty(true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -172,8 +144,6 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
|
||||
{
|
||||
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer powered through a valid middle block", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
|
||||
itr = LinkedPoweredBlocks->erase(itr);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
OtherChunk->SetIsRedstoneDirty(true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -320,6 +290,7 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
|
||||
case E_BLOCK_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break;
|
||||
case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break;
|
||||
case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break;
|
||||
case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->x, dataitr->y, dataitr->z); break;
|
||||
|
||||
case E_BLOCK_ACTIVATOR_RAIL:
|
||||
case E_BLOCK_DETECTOR_RAIL:
|
||||
@ -382,18 +353,13 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
|
||||
|
||||
void cIncrementalRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
|
||||
{
|
||||
if (
|
||||
((a_BlockX % cChunkDef::Width) <= 1) ||
|
||||
((a_BlockX % cChunkDef::Width) >= 14) ||
|
||||
((a_BlockZ % cChunkDef::Width) <= 1) ||
|
||||
((a_BlockZ % cChunkDef::Width) >= 14)
|
||||
) // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks
|
||||
if (AreCoordsOnChunkBoundary(a_BlockX, a_BlockY, a_BlockZ))
|
||||
{
|
||||
// On a chunk boundary, alert all four sides (i.e. at least one neighbouring chunk)
|
||||
AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
|
||||
|
||||
// Pass the original coordinates, because when adding things to our simulator lists, we get the chunk that they are in, and therefore any updates need to preseve their position
|
||||
// RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordiantes are in and +- 2 in GetNeighbour() to accomodate for LinkedPowered blocks being 2 away from chunk boundaries
|
||||
// RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordinates are in and +- 2 in GetNeighbour() to accomodate for LinkedPowered blocks being 2 away from chunk boundaries
|
||||
RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 2, a_BlockZ), a_Chunk);
|
||||
RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 2, a_BlockZ), a_Chunk);
|
||||
RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 2), a_Chunk);
|
||||
@ -448,7 +414,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_RelBlockX, int a_R
|
||||
if (i + 1 < ARRAYCOUNT(gCrossCoords)) // Sides of torch, not top (top is last)
|
||||
{
|
||||
if (
|
||||
((IsMechanism(Type)) || (Type == E_BLOCK_REDSTONE_WIRE)) && // Is it a mechanism or wire? Not block/other torch etc.
|
||||
IsMechanism(Type) && // Is it a mechanism? Not block/other torch etc.
|
||||
(!Vector3i(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z).Equals(Vector3i(X, Y, Z))) // CAN'T power block is that it is on
|
||||
)
|
||||
{
|
||||
@ -468,7 +434,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_RelBlockX, int a_R
|
||||
{
|
||||
BLOCKTYPE Type = m_Chunk->GetBlock(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ);
|
||||
|
||||
if ((IsMechanism(Type)) || (Type == E_BLOCK_REDSTONE_WIRE)) // Still can't make a normal block powered though!
|
||||
if (IsMechanism(Type)) // Still can't make a normal block powered though!
|
||||
{
|
||||
SetBlockPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
||||
}
|
||||
@ -780,17 +746,20 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
|
||||
{
|
||||
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end();)
|
||||
{
|
||||
|
||||
if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks?
|
||||
{
|
||||
int RelBlockX = itr->a_RelBlockPos.x;
|
||||
int RelBlockY = itr->a_RelBlockPos.y;
|
||||
int RelBlockZ = itr->a_RelBlockPos.z;
|
||||
NIBBLETYPE Meta = m_Chunk->GetMeta(RelBlockX, RelBlockY, RelBlockZ);
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE Meta;
|
||||
m_Chunk->GetBlockTypeMeta(RelBlockX, RelBlockY, RelBlockZ, Block, Meta);
|
||||
if (itr->ShouldPowerOn)
|
||||
{
|
||||
|
||||
m_Chunk->SetBlock(itr->a_RelBlockPos, E_BLOCK_REDSTONE_REPEATER_ON, Meta); // For performance
|
||||
if (Block != E_BLOCK_REDSTONE_REPEATER_ON) // For performance
|
||||
{
|
||||
m_Chunk->SetBlock(itr->a_RelBlockPos, E_BLOCK_REDSTONE_REPEATER_ON, Meta);
|
||||
}
|
||||
|
||||
switch (Meta & 0x3) // We only want the direction (bottom) bits
|
||||
{
|
||||
@ -820,17 +789,14 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (Block != E_BLOCK_REDSTONE_REPEATER_OFF)
|
||||
{
|
||||
m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta);
|
||||
m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta);
|
||||
}
|
||||
itr = m_RepeatersDelayList->erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apparently, incrementing ticks only works reliably here, and not in SimChunk;
|
||||
// With a world with lots of redstone, the repeaters simply do not delay
|
||||
// I am confounded to say why. Perhaps optimisation failure.
|
||||
LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->a_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks);
|
||||
itr->a_ElapsedTicks++;
|
||||
itr++;
|
||||
@ -1139,7 +1105,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
|
||||
else
|
||||
{
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x0);
|
||||
WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
|
||||
SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1206,7 +1172,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
|
||||
m_Chunk->BroadcastSoundEffect("random.click", (int)((BlockX + 0.5) * 8.0), (int)((a_RelBlockY + 0.1) * 8.0), (int)((BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
|
||||
}
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED);
|
||||
WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
|
||||
SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -1274,7 +1240,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
|
||||
m_Chunk->BroadcastSoundEffect("random.click", (int)((BlockX + 0.5) * 8.0), (int)((a_RelBlockY + 0.1) * 8.0), (int)((BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
|
||||
}
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED);
|
||||
WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
|
||||
SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -1341,7 +1307,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
|
||||
m_Chunk->BroadcastSoundEffect("random.click", (int)((BlockX + 0.5) * 8.0), (int)((a_RelBlockY + 0.1) * 8.0), (int)((BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
|
||||
}
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED);
|
||||
WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
|
||||
SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1384,14 +1350,14 @@ void cIncrementalRedstoneSimulator::HandleTripwireHook(int a_RelBlockX, int a_Re
|
||||
{
|
||||
if (ReverseBlockFace(cBlockTripwireHookHandler::MetadataToDirection(Meta)) == FaceToGoTowards)
|
||||
{
|
||||
// Other hook not facing in opposite direction
|
||||
// Other hook facing in opposite direction - circuit completed!
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tripwire hook not connected at all, AND away all the power state bits
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x3);
|
||||
WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
|
||||
SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1399,7 +1365,7 @@ void cIncrementalRedstoneSimulator::HandleTripwireHook(int a_RelBlockX, int a_Re
|
||||
{
|
||||
// Tripwire hook not connected at all, AND away all the power state bits
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x3);
|
||||
WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
|
||||
SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1414,7 +1380,51 @@ void cIncrementalRedstoneSimulator::HandleTripwireHook(int a_RelBlockX, int a_Re
|
||||
{
|
||||
// Connected but not activated, AND away the highest bit
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, (m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7) | 0x4);
|
||||
WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
|
||||
SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cIncrementalRedstoneSimulator::HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
|
||||
{
|
||||
class cGetTrappedChestPlayers :
|
||||
public cChestCallback
|
||||
{
|
||||
public:
|
||||
cGetTrappedChestPlayers(void) :
|
||||
m_NumberOfPlayers(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cChestEntity * a_Chest) override
|
||||
{
|
||||
ASSERT(a_Chest->GetBlockType() == E_BLOCK_TRAPPED_CHEST);
|
||||
m_NumberOfPlayers = a_Chest->GetNumberOfPlayers();
|
||||
return (m_NumberOfPlayers <= 0);
|
||||
}
|
||||
|
||||
unsigned char GetPowerLevel(void) const
|
||||
{
|
||||
return std::min(m_NumberOfPlayers, MAX_POWER_LEVEL);
|
||||
}
|
||||
|
||||
private:
|
||||
int m_NumberOfPlayers;
|
||||
|
||||
} GTCP;
|
||||
|
||||
int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX;
|
||||
int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ;
|
||||
if (m_Chunk->DoWithChestAt(BlockX, a_RelBlockY, BlockZ, GTCP))
|
||||
{
|
||||
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, GTCP.GetPowerLevel());
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1691,8 +1701,8 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBl
|
||||
bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel)
|
||||
{
|
||||
a_PowerLevel = 0;
|
||||
int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
|
||||
int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
|
||||
int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX;
|
||||
int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ;
|
||||
|
||||
for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) // Check powered list
|
||||
{
|
||||
@ -1709,6 +1719,14 @@ bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBloc
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BLOCKTYPE Type = E_BLOCK_AIR;
|
||||
int RelSourceX = itr->a_SourcePos.x - m_Chunk->GetPosX() * cChunkDef::Width;
|
||||
int RelSourceZ = itr->a_SourcePos.z - m_Chunk->GetPosZ() * cChunkDef::Width;
|
||||
if (!m_Chunk->UnboundedRelGetBlockType(RelSourceX, itr->a_SourcePos.y, RelSourceZ, Type) || (Type == E_BLOCK_REDSTONE_WIRE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
a_PowerLevel = std::max(itr->a_PowerLevel, a_PowerLevel);
|
||||
}
|
||||
|
||||
@ -1881,20 +1899,9 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_RelBlockX, int a_RelBl
|
||||
int SourceX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelSourceX;
|
||||
int SourceZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelSourceZ;
|
||||
|
||||
BLOCKTYPE Block = 0;
|
||||
if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Block))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Block == E_BLOCK_AIR)
|
||||
{
|
||||
// Don't set air, fixes some bugs (wires powering themselves)
|
||||
return;
|
||||
}
|
||||
|
||||
cChunk * Neighbour = m_Chunk->GetNeighborChunk(BlockX, BlockZ);
|
||||
PoweredBlocksList * Powered = Neighbour->GetRedstoneSimulatorPoweredBlocksList();
|
||||
for (PoweredBlocksList::iterator itr = Powered->begin(); itr != Powered->end(); ++itr) // Check powered list
|
||||
cChunk * Neighbour = m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelBlockX, a_RelBlockZ); // Adjust coordinates for the later call using these values
|
||||
PoweredBlocksList * Powered = Neighbour->GetRedstoneSimulatorPoweredBlocksList(); // We need to insert the value into the chunk who owns the block position
|
||||
for (PoweredBlocksList::iterator itr = Powered->begin(); itr != Powered->end(); ++itr)
|
||||
{
|
||||
if (
|
||||
itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) &&
|
||||
@ -1907,16 +1914,33 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_RelBlockX, int a_RelBl
|
||||
}
|
||||
}
|
||||
|
||||
PoweredBlocksList * OtherPowered = m_Chunk->GetNeighborChunk(SourceX, SourceZ)->GetRedstoneSimulatorPoweredBlocksList();
|
||||
for (PoweredBlocksList::const_iterator itr = OtherPowered->begin(); itr != OtherPowered->end(); ++itr) // Check powered list
|
||||
// No need to get neighbouring chunk as we can guarantee that when something is powering us, the entry will be in our chunk
|
||||
// TODO: on C++11 support, change this to a llama function pased to a std::remove_if
|
||||
for (PoweredBlocksList::iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr)
|
||||
{
|
||||
if (
|
||||
itr->a_BlockPos.Equals(Vector3i(SourceX, a_RelSourceY, SourceZ)) &&
|
||||
itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))
|
||||
itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) &&
|
||||
(m_Chunk->GetBlock(a_RelSourceX, a_RelSourceY, a_RelSourceZ) == E_BLOCK_REDSTONE_WIRE)
|
||||
)
|
||||
{
|
||||
// Powered wires try to power their source - don't let them!
|
||||
return;
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE Meta;
|
||||
Neighbour->GetBlockTypeMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Block, Meta);
|
||||
|
||||
if (Block == E_BLOCK_REDSTONE_WIRE)
|
||||
{
|
||||
if (Meta < a_PowerLevel)
|
||||
{
|
||||
m_PoweredBlocks->erase(itr); // Powering source with higher power level, allow it
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Powered wires try to power their source - don't let them!
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1947,20 +1971,6 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered(
|
||||
int SourceX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelSourceX;
|
||||
int SourceZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelSourceZ;
|
||||
|
||||
BLOCKTYPE DestBlock = 0;
|
||||
if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ, DestBlock))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (DestBlock == E_BLOCK_AIR)
|
||||
{
|
||||
// Don't set air, fixes some bugs (wires powering themselves)
|
||||
return;
|
||||
}
|
||||
if ((DestBlock == E_BLOCK_REDSTONE_WIRE) && (m_Chunk->GetBlock(a_RelSourceX, a_RelSourceY, a_RelSourceZ) == E_BLOCK_REDSTONE_WIRE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!IsViableMiddleBlock(a_MiddleBlock))
|
||||
{
|
||||
return;
|
||||
@ -2066,6 +2076,45 @@ bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, in
|
||||
|
||||
|
||||
|
||||
void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_SourceX, int a_SourceY, int a_SourceZ, cChunk * a_Chunk, bool a_IsFirstCall)
|
||||
{
|
||||
// TODO: on C++11 support, change both of these to llama functions pased to a std::remove_if
|
||||
|
||||
for (PoweredBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end();)
|
||||
{
|
||||
if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)))
|
||||
{
|
||||
itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->erase(itr);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
continue;
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
for (LinkedBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->end();)
|
||||
{
|
||||
if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)))
|
||||
{
|
||||
itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->erase(itr);
|
||||
a_Chunk->SetIsRedstoneDirty(true);
|
||||
continue;
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
|
||||
if (a_IsFirstCall && AreCoordsOnChunkBoundary(a_SourceX, a_SourceY, a_SourceZ))
|
||||
{
|
||||
// +- 2 to accomodate linked powered blocks
|
||||
SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX - 2, a_SourceZ), false);
|
||||
SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX + 2, a_SourceZ), false);
|
||||
SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ - 2), false);
|
||||
SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ + 2), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cIncrementalRedstoneSimulator::eRedstoneDirection cIncrementalRedstoneSimulator::GetWireDirection(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
|
||||
{
|
||||
int Dir = REDSTONE_NONE;
|
||||
|
@ -107,6 +107,8 @@ private:
|
||||
If this line is complete, it verifies that at least on wire reports an entity is on top (via its meta), and performs its task
|
||||
*/
|
||||
void HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
/** Handles trapped chests */
|
||||
void HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
/* ==================== */
|
||||
|
||||
/* ====== CARRIERS ====== */
|
||||
@ -114,8 +116,6 @@ private:
|
||||
void HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
/** Handles repeaters */
|
||||
void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
|
||||
/** Handles delayed updates to Repeaters **/
|
||||
void HandleRedstoneRepeaterDelays();
|
||||
/* ====================== */
|
||||
|
||||
/* ====== DEVICES ====== */
|
||||
@ -156,6 +156,10 @@ private:
|
||||
void SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
|
||||
/** Queues a repeater to be powered or unpowered and returns if the m_RepeatersDelayList iterators were invalidated */
|
||||
bool QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
|
||||
/** Removes a block from the Powered and LinkedPowered lists
|
||||
Used for variable sources such as tripwire hooks, daylight sensors, and trapped chests
|
||||
*/
|
||||
void SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, cChunk * a_Chunk, bool a_IsFirstCall = true);
|
||||
|
||||
/** Returns if a coordinate is powered or linked powered */
|
||||
bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }
|
||||
@ -174,7 +178,8 @@ private:
|
||||
/** Returns if a wire is powered
|
||||
The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire */
|
||||
bool IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel);
|
||||
|
||||
/** Handles delayed updates to repeaters **/
|
||||
void HandleRedstoneRepeaterDelays(void);
|
||||
|
||||
/** Returns if lever metadata marks it as emitting power */
|
||||
bool IsLeverOn(NIBBLETYPE a_BlockMeta);
|
||||
@ -186,7 +191,9 @@ private:
|
||||
/** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */
|
||||
inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { return cBlockInfo::FullyOccupiesVoxel(Block); }
|
||||
|
||||
/** Returns if a block is a mechanism (something that accepts power and does something) */
|
||||
/** Returns if a block is a mechanism (something that accepts power and does something)
|
||||
Used by torches to determine if they power a block whilst not standing on the ground
|
||||
*/
|
||||
inline static bool IsMechanism(BLOCKTYPE Block)
|
||||
{
|
||||
switch (Block)
|
||||
@ -209,6 +216,7 @@ private:
|
||||
case E_BLOCK_REDSTONE_REPEATER_OFF:
|
||||
case E_BLOCK_REDSTONE_REPEATER_ON:
|
||||
case E_BLOCK_POWERED_RAIL:
|
||||
case E_BLOCK_REDSTONE_WIRE:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -235,6 +243,7 @@ private:
|
||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
|
||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
||||
case E_BLOCK_TRAPPED_CHEST:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -277,6 +286,7 @@ private:
|
||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||
case E_BLOCK_TNT:
|
||||
case E_BLOCK_TRAPDOOR:
|
||||
case E_BLOCK_TRAPPED_CHEST:
|
||||
case E_BLOCK_TRIPWIRE_HOOK:
|
||||
case E_BLOCK_TRIPWIRE:
|
||||
case E_BLOCK_WOODEN_BUTTON:
|
||||
@ -289,6 +299,16 @@ private:
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline static bool AreCoordsOnChunkBoundary(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
{
|
||||
return ( // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks
|
||||
((a_BlockX % cChunkDef::Width) <= 1) ||
|
||||
((a_BlockX % cChunkDef::Width) >= 14) ||
|
||||
((a_BlockZ % cChunkDef::Width) <= 1) ||
|
||||
((a_BlockZ % cChunkDef::Width) >= 14)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -905,11 +905,13 @@ void cEnchantingWindow::GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ)
|
||||
// cChestWindow:
|
||||
|
||||
cChestWindow::cChestWindow(cChestEntity * a_Chest) :
|
||||
cWindow(wtChest, "Chest"),
|
||||
cWindow(wtChest, (a_Chest->GetBlockType() == E_BLOCK_CHEST) ? "Chest" : "Trapped Chest"),
|
||||
m_World(a_Chest->GetWorld()),
|
||||
m_BlockX(a_Chest->GetPosX()),
|
||||
m_BlockY(a_Chest->GetPosY()),
|
||||
m_BlockZ(a_Chest->GetPosZ())
|
||||
m_BlockZ(a_Chest->GetPosZ()),
|
||||
m_PrimaryChest(a_Chest),
|
||||
m_SecondaryChest(NULL)
|
||||
{
|
||||
m_SlotAreas.push_back(new cSlotAreaChest(a_Chest, *this));
|
||||
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
|
||||
@ -919,7 +921,7 @@ cChestWindow::cChestWindow(cChestEntity * a_Chest) :
|
||||
m_World->BroadcastSoundEffect("random.chestopen", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
|
||||
|
||||
// Send out the chest-open packet:
|
||||
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, E_BLOCK_CHEST);
|
||||
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, a_Chest->GetBlockType());
|
||||
}
|
||||
|
||||
|
||||
@ -927,11 +929,13 @@ cChestWindow::cChestWindow(cChestEntity * a_Chest) :
|
||||
|
||||
|
||||
cChestWindow::cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest) :
|
||||
cWindow(wtChest, "Double Chest"),
|
||||
cWindow(wtChest, (a_PrimaryChest->GetBlockType() == E_BLOCK_CHEST) ? "Double Chest" : "Double Trapped Chest"),
|
||||
m_World(a_PrimaryChest->GetWorld()),
|
||||
m_BlockX(a_PrimaryChest->GetPosX()),
|
||||
m_BlockY(a_PrimaryChest->GetPosY()),
|
||||
m_BlockZ(a_PrimaryChest->GetPosZ())
|
||||
m_BlockZ(a_PrimaryChest->GetPosZ()),
|
||||
m_PrimaryChest(a_PrimaryChest),
|
||||
m_SecondaryChest(a_SecondaryChest)
|
||||
{
|
||||
m_SlotAreas.push_back(new cSlotAreaDoubleChest(a_PrimaryChest, a_SecondaryChest, *this));
|
||||
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
|
||||
@ -943,7 +947,52 @@ cChestWindow::cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_Secon
|
||||
m_World->BroadcastSoundEffect("random.chestopen", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
|
||||
|
||||
// Send out the chest-open packet:
|
||||
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, E_BLOCK_CHEST);
|
||||
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, a_PrimaryChest->GetBlockType());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChestWindow::OpenedByPlayer(cPlayer & a_Player)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
|
||||
m_PrimaryChest->SetNumberOfPlayers(m_PrimaryChest->GetNumberOfPlayers() + 1);
|
||||
cChunkDef::BlockToChunk(m_PrimaryChest->GetPosX(), m_PrimaryChest->GetPosZ(), ChunkX, ChunkZ);
|
||||
m_PrimaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
|
||||
|
||||
if (m_SecondaryChest != NULL)
|
||||
{
|
||||
m_SecondaryChest->SetNumberOfPlayers(m_SecondaryChest->GetNumberOfPlayers() + 1);
|
||||
cChunkDef::BlockToChunk(m_SecondaryChest->GetPosX(), m_SecondaryChest->GetPosZ(), ChunkX, ChunkZ);
|
||||
m_SecondaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
|
||||
}
|
||||
|
||||
cWindow::OpenedByPlayer(a_Player);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChestWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
|
||||
m_PrimaryChest->SetNumberOfPlayers(m_PrimaryChest->GetNumberOfPlayers() - 1);
|
||||
cChunkDef::BlockToChunk(m_PrimaryChest->GetPosX(), m_PrimaryChest->GetPosZ(), ChunkX, ChunkZ);
|
||||
m_PrimaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
|
||||
|
||||
if (m_SecondaryChest != NULL)
|
||||
{
|
||||
m_SecondaryChest->SetNumberOfPlayers(m_SecondaryChest->GetNumberOfPlayers() - 1);
|
||||
cChunkDef::BlockToChunk(m_SecondaryChest->GetPosX(), m_SecondaryChest->GetPosZ(), ChunkX, ChunkZ);
|
||||
m_SecondaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
|
||||
}
|
||||
|
||||
cWindow::ClosedByPlayer(a_Player, a_CanRefuse);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -953,7 +1002,7 @@ cChestWindow::cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_Secon
|
||||
cChestWindow::~cChestWindow()
|
||||
{
|
||||
// Send out the chest-close packet:
|
||||
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 0, E_BLOCK_CHEST);
|
||||
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 0, m_PrimaryChest->GetBlockType());
|
||||
|
||||
m_World->BroadcastSoundEffect("random.chestclosed", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
|
||||
}
|
||||
@ -966,7 +1015,7 @@ cChestWindow::~cChestWindow()
|
||||
// cDropSpenserWindow:
|
||||
|
||||
cDropSpenserWindow::cDropSpenserWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserEntity * a_DropSpenser) :
|
||||
cWindow(wtDropSpenser, "Dropspenser")
|
||||
cWindow(wtDropSpenser, (a_DropSpenser->GetBlockType() == E_BLOCK_DISPENSER) ? "Dispenser" : "Dropper")
|
||||
{
|
||||
m_ShouldDistributeToHotbarFirst = false;
|
||||
m_SlotAreas.push_back(new cSlotAreaItemGrid(a_DropSpenser->GetContents(), *this));
|
||||
|
@ -114,7 +114,7 @@ public:
|
||||
const cItem & a_ClickedItem
|
||||
);
|
||||
|
||||
void OpenedByPlayer(cPlayer & a_Player);
|
||||
virtual void OpenedByPlayer(cPlayer & a_Player);
|
||||
|
||||
/// Called when a player closes this window; notifies all slot areas. Returns true if close accepted
|
||||
virtual bool ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse);
|
||||
@ -327,10 +327,15 @@ public:
|
||||
cChestWindow(cChestEntity * a_Chest);
|
||||
cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest);
|
||||
~cChestWindow();
|
||||
|
||||
virtual bool ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) override;
|
||||
virtual void OpenedByPlayer(cPlayer & a_Player) override;
|
||||
|
||||
protected:
|
||||
cWorld * m_World;
|
||||
int m_BlockX, m_BlockY, m_BlockZ; // Position of the chest, for the window-close packet
|
||||
cChestEntity * m_PrimaryChest;
|
||||
cChestEntity * m_SecondaryChest;
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -389,8 +389,8 @@ void cWorld::InitializeSpawn(void)
|
||||
IniFile.WriteFile(m_IniFileName);
|
||||
}
|
||||
|
||||
int ChunkX = 0, ChunkY = 0, ChunkZ = 0;
|
||||
BlockToChunk((int)m_SpawnX, (int)m_SpawnY, (int)m_SpawnZ, ChunkX, ChunkY, ChunkZ);
|
||||
int ChunkX = 0, ChunkZ = 0;
|
||||
cChunkDef::BlockToChunk((int)m_SpawnX, (int)m_SpawnZ, ChunkX, ChunkZ);
|
||||
|
||||
// For the debugging builds, don't make the server build too much world upon start:
|
||||
#if defined(_DEBUG) || defined(ANDROID_NDK)
|
||||
@ -2182,9 +2182,18 @@ void cWorld::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHa
|
||||
|
||||
|
||||
|
||||
void cWorld::MarkChunkDirty (int a_ChunkX, int a_ChunkZ)
|
||||
void cWorld::MarkRedstoneDirty(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
m_ChunkMap->MarkChunkDirty (a_ChunkX, a_ChunkZ);
|
||||
m_ChunkMap->MarkRedstoneDirty(a_ChunkX, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::MarkChunkDirty(int a_ChunkX, int a_ChunkZ, bool a_MarkRedstoneDirty)
|
||||
{
|
||||
m_ChunkMap->MarkChunkDirty(a_ChunkX, a_ChunkZ, a_MarkRedstoneDirty);
|
||||
}
|
||||
|
||||
|
||||
|
15
src/World.h
15
src/World.h
@ -241,7 +241,8 @@ public:
|
||||
/** If there is a block entity at the specified coords, sends it to the client specified */
|
||||
void SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client);
|
||||
|
||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkZ);
|
||||
void MarkRedstoneDirty(int a_ChunkX, int a_ChunkZ);
|
||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkZ, bool a_MarkRedstoneDirty = false);
|
||||
void MarkChunkSaving(int a_ChunkX, int a_ChunkZ);
|
||||
void MarkChunkSaved (int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
@ -634,18 +635,6 @@ public:
|
||||
|
||||
// tolua_end
|
||||
|
||||
inline static void BlockToChunk( int a_X, int a_Y, int a_Z, int & a_ChunkX, int & a_ChunkY, int & a_ChunkZ )
|
||||
{
|
||||
// TODO: Use floor() instead of weird if statements
|
||||
// Also fix Y
|
||||
(void)a_Y; // not unused anymore
|
||||
a_ChunkX = a_X/cChunkDef::Width;
|
||||
if(a_X < 0 && a_X % cChunkDef::Width != 0) a_ChunkX--;
|
||||
a_ChunkY = 0;
|
||||
a_ChunkZ = a_Z/cChunkDef::Width;
|
||||
if(a_Z < 0 && a_Z % cChunkDef::Width != 0) a_ChunkZ--;
|
||||
}
|
||||
|
||||
/** Saves all chunks immediately. Dangerous interface, may deadlock, use QueueSaveAllChunks() instead */
|
||||
void SaveAllChunks(void);
|
||||
|
||||
|
@ -175,10 +175,10 @@ void cNBTChunkSerializer::AddBasicTileEntity(cBlockEntity * a_Entity, const char
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddChestEntity(cChestEntity * a_Entity)
|
||||
void cNBTChunkSerializer::AddChestEntity(cChestEntity * a_Entity, BLOCKTYPE a_ChestType)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Entity, "Chest");
|
||||
AddBasicTileEntity(a_Entity, (a_ChestType == E_BLOCK_CHEST) ? "Chest" : "TrappedChest");
|
||||
m_Writer.BeginList("Items", TAG_Compound);
|
||||
AddItemGrid(a_Entity->GetContents());
|
||||
m_Writer.EndList();
|
||||
@ -813,19 +813,21 @@ void cNBTChunkSerializer::BlockEntity(cBlockEntity * a_Entity)
|
||||
// Add tile-entity into NBT:
|
||||
switch (a_Entity->GetBlockType())
|
||||
{
|
||||
case E_BLOCK_CHEST: AddChestEntity ((cChestEntity *) a_Entity); break;
|
||||
case E_BLOCK_DISPENSER: AddDispenserEntity ((cDispenserEntity *) a_Entity); break;
|
||||
case E_BLOCK_DROPPER: AddDropperEntity ((cDropperEntity *) a_Entity); break;
|
||||
case E_BLOCK_ENDER_CHEST: /* No need to be saved */ break;
|
||||
case E_BLOCK_FLOWER_POT: AddFlowerPotEntity ((cFlowerPotEntity *) a_Entity); break;
|
||||
case E_BLOCK_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break;
|
||||
case E_BLOCK_HOPPER: AddHopperEntity ((cHopperEntity *) a_Entity); break;
|
||||
case E_BLOCK_SIGN_POST:
|
||||
case E_BLOCK_WALLSIGN: AddSignEntity ((cSignEntity *) a_Entity); break;
|
||||
case E_BLOCK_HEAD: AddMobHeadEntity ((cMobHeadEntity *) a_Entity); break;
|
||||
case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break;
|
||||
case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break;
|
||||
case E_BLOCK_COMMAND_BLOCK: AddCommandBlockEntity((cCommandBlockEntity *) a_Entity); break;
|
||||
case E_BLOCK_CHEST: AddChestEntity ((cChestEntity *) a_Entity, a_Entity->GetBlockType()); break;
|
||||
case E_BLOCK_COMMAND_BLOCK: AddCommandBlockEntity((cCommandBlockEntity *)a_Entity); break;
|
||||
case E_BLOCK_DISPENSER: AddDispenserEntity ((cDispenserEntity *) a_Entity); break;
|
||||
case E_BLOCK_DROPPER: AddDropperEntity ((cDropperEntity *) a_Entity); break;
|
||||
case E_BLOCK_ENDER_CHEST: /* No data to be saved */ break;
|
||||
case E_BLOCK_FLOWER_POT: AddFlowerPotEntity ((cFlowerPotEntity *) a_Entity); break;
|
||||
case E_BLOCK_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break;
|
||||
case E_BLOCK_HEAD: AddMobHeadEntity ((cMobHeadEntity *) a_Entity); break;
|
||||
case E_BLOCK_HOPPER: AddHopperEntity ((cHopperEntity *) a_Entity); break;
|
||||
case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break;
|
||||
case E_BLOCK_LIT_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break;
|
||||
case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break;
|
||||
case E_BLOCK_SIGN_POST: AddSignEntity ((cSignEntity *) a_Entity); break;
|
||||
case E_BLOCK_TRAPPED_CHEST: AddChestEntity ((cChestEntity *) a_Entity, a_Entity->GetBlockType()); break;
|
||||
case E_BLOCK_WALLSIGN: AddSignEntity ((cSignEntity *) a_Entity); break;
|
||||
|
||||
default:
|
||||
{
|
||||
|
@ -92,7 +92,7 @@ protected:
|
||||
|
||||
// Block entities:
|
||||
void AddBasicTileEntity(cBlockEntity * a_Entity, const char * a_EntityTypeID);
|
||||
void AddChestEntity (cChestEntity * a_Entity);
|
||||
void AddChestEntity (cChestEntity * a_Entity, BLOCKTYPE a_ChestType);
|
||||
void AddDispenserEntity(cDispenserEntity * a_Entity);
|
||||
void AddDropperEntity (cDropperEntity * a_Entity);
|
||||
void AddFurnaceEntity (cFurnaceEntity * a_Furnace);
|
||||
|
@ -582,7 +582,7 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
|
||||
}
|
||||
if (strncmp(a_NBT.GetData(sID), "Chest", a_NBT.GetDataLength(sID)) == 0)
|
||||
{
|
||||
LoadChestFromNBT(a_BlockEntities, a_NBT, Child);
|
||||
LoadChestFromNBT(a_BlockEntities, a_NBT, Child, E_BLOCK_CHEST);
|
||||
}
|
||||
else if (strncmp(a_NBT.GetData(sID), "Control", a_NBT.GetDataLength(sID)) == 0)
|
||||
{
|
||||
@ -624,6 +624,10 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
|
||||
{
|
||||
LoadDispenserFromNBT(a_BlockEntities, a_NBT, Child);
|
||||
}
|
||||
else if (strncmp(a_NBT.GetData(sID), "TrappedChest", a_NBT.GetDataLength(sID)) == 0)
|
||||
{
|
||||
LoadChestFromNBT(a_BlockEntities, a_NBT, Child, E_BLOCK_TRAPPED_CHEST);
|
||||
}
|
||||
// TODO: Other block entities
|
||||
} // for Child - tag children
|
||||
}
|
||||
@ -740,7 +744,7 @@ void cWSSAnvil::LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
void cWSSAnvil::LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_ChestType)
|
||||
{
|
||||
ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
|
||||
int x, y, z;
|
||||
@ -753,7 +757,7 @@ void cWSSAnvil::LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cPars
|
||||
{
|
||||
return; // Make it an empty chest - the chunk loader will provide an empty cChestEntity for this
|
||||
}
|
||||
std::auto_ptr<cChestEntity> Chest(new cChestEntity(x, y, z, m_World));
|
||||
std::auto_ptr<cChestEntity> Chest(new cChestEntity(x, y, z, m_World, a_ChestType));
|
||||
LoadItemGridFromNBT(Chest->GetContents(), a_NBT, Items);
|
||||
a_BlockEntities.push_back(Chest.release());
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ protected:
|
||||
*/
|
||||
void LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a_NBT, int a_ItemsTagIdx, int s_SlotOffset = 0);
|
||||
|
||||
void LoadChestFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadChestFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_ChestType);
|
||||
void LoadDispenserFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadDropperFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadFlowerPotFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
|
@ -273,7 +273,7 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En
|
||||
{
|
||||
for (Json::Value::iterator itr = AllChests.begin(); itr != AllChests.end(); ++itr )
|
||||
{
|
||||
std::auto_ptr<cChestEntity> ChestEntity(new cChestEntity(0, 0, 0, a_World));
|
||||
std::auto_ptr<cChestEntity> ChestEntity(new cChestEntity(0, 0, 0, a_World, E_BLOCK_CHEST));
|
||||
if (!ChestEntity->LoadFromJson(*itr))
|
||||
{
|
||||
LOGWARNING("ERROR READING CHEST FROM JSON!" );
|
||||
|
Loading…
Reference in New Issue
Block a user