1
0

Lock hopper when powered by redstone (#4347)

* Lock hopper when powered by redstone

* Add to manual bindings

* Add hopper API documentation

Co-authored-by: Mat <mail@mathias.is>
This commit is contained in:
Bond-009 2020-03-27 13:03:28 +01:00 committed by GitHub
parent 3a2f364c95
commit ea386eaab1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 172 additions and 4 deletions

View File

@ -939,6 +939,35 @@ function OnAllChunksAvailable()</pre> All return values from the callbacks are i
}, },
Notes = "If there is a furnace at the specified coords, calls the CallbackFunction with the {{cFurnaceEntity}} parameter representing the furnace. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cFurnaceEntity|FurnaceEntity}})</pre> The function returns false if there is no furnace, or if there is, it returns the bool value that the callback has returned.", Notes = "If there is a furnace at the specified coords, calls the CallbackFunction with the {{cFurnaceEntity}} parameter representing the furnace. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cFurnaceEntity|FurnaceEntity}})</pre> The function returns false if there is no furnace, or if there is, it returns the bool value that the callback has returned.",
}, },
DoWithHopperAt =
{
Params =
{
{
Name = "BlockX",
Type = "number",
},
{
Name = "BlockY",
Type = "number",
},
{
Name = "BlockZ",
Type = "number",
},
{
Name = "CallbackFunction",
Type = "function",
},
},
Returns =
{
{
Type = "boolean",
},
},
Notes = "If there is a hopper at the specified coords, calls the CallbackFunction with the {{cHopperEntity}} parameter representing the hopper. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cHopperEntity|cHopperEntity}})</pre> The function returns false if there is no hopper, or if there is, it returns the bool value that the callback has returned.",
},
DoWithMobHeadAt = DoWithMobHeadAt =
{ {
Params = Params =

View File

@ -984,6 +984,7 @@ void cManualBindings::BindWorld(lua_State * tolua_S)
tolua_function(tolua_S, "DoWithEntityByID", DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>); tolua_function(tolua_S, "DoWithEntityByID", DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>);
tolua_function(tolua_S, "DoWithFlowerPotAt", DoWithXYZ<cWorld, cFlowerPotEntity, &cWorld::DoWithFlowerPotAt>); tolua_function(tolua_S, "DoWithFlowerPotAt", DoWithXYZ<cWorld, cFlowerPotEntity, &cWorld::DoWithFlowerPotAt>);
tolua_function(tolua_S, "DoWithFurnaceAt", DoWithXYZ<cWorld, cFurnaceEntity, &cWorld::DoWithFurnaceAt>); 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, "DoWithMobHeadAt", DoWithXYZ<cWorld, cMobHeadEntity, &cWorld::DoWithMobHeadAt>);
tolua_function(tolua_S, "DoWithNearestPlayer", tolua_cWorld_DoWithNearestPlayer); tolua_function(tolua_S, "DoWithNearestPlayer", tolua_cWorld_DoWithNearestPlayer);
tolua_function(tolua_S, "DoWithNoteBlockAt", DoWithXYZ<cWorld, cNoteEntity, &cWorld::DoWithNoteBlockAt>); tolua_function(tolua_S, "DoWithNoteBlockAt", DoWithXYZ<cWorld, cNoteEntity, &cWorld::DoWithNoteBlockAt>);

View File

@ -20,7 +20,8 @@
cHopperEntity::cHopperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): cHopperEntity::cHopperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World), super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World),
m_LastMoveItemsInTick(0), m_LastMoveItemsInTick(0),
m_LastMoveItemsOutTick(0) m_LastMoveItemsOutTick(0),
m_Locked(false)
{ {
ASSERT(a_BlockType == E_BLOCK_HOPPER); ASSERT(a_BlockType == E_BLOCK_HOPPER);
} }
@ -29,6 +30,15 @@ cHopperEntity::cHopperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vect
void cHopperEntity::SetLocked(bool a_Value)
{
m_Locked = a_Value;
}
std::pair<bool, Vector3i> cHopperEntity::GetOutputBlockPos(NIBBLETYPE a_BlockMeta) std::pair<bool, Vector3i> cHopperEntity::GetOutputBlockPos(NIBBLETYPE a_BlockMeta)
{ {
auto pos = GetPos(); auto pos = GetPos();
@ -69,9 +79,12 @@ bool cHopperEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
Int64 CurrentTick = a_Chunk.GetWorld()->GetWorldAge(); Int64 CurrentTick = a_Chunk.GetWorld()->GetWorldAge();
bool isDirty = false; bool isDirty = false;
if (!m_Locked)
{
isDirty = MoveItemsIn (a_Chunk, CurrentTick) || isDirty; isDirty = MoveItemsIn (a_Chunk, CurrentTick) || isDirty;
isDirty = MovePickupsIn(a_Chunk, CurrentTick) || isDirty; isDirty = MovePickupsIn(a_Chunk, CurrentTick) || isDirty;
isDirty = MoveItemsOut (a_Chunk, CurrentTick) || isDirty; isDirty = MoveItemsOut (a_Chunk, CurrentTick) || isDirty;
}
return isDirty; return isDirty;
} }

View File

@ -33,6 +33,8 @@ public:
TICKS_PER_TRANSFER = 8, ///< How many ticks at minimum between two item transfers to or from the hopper TICKS_PER_TRANSFER = 8, ///< How many ticks at minimum between two item transfers to or from the hopper
} ; } ;
// tolua_end // tolua_end
BLOCKENTITY_PROTODEF(cHopperEntity) BLOCKENTITY_PROTODEF(cHopperEntity)
@ -45,6 +47,8 @@ public:
Exported in ManualBindings.cpp. */ Exported in ManualBindings.cpp. */
std::pair<bool, Vector3i> GetOutputBlockPos(NIBBLETYPE a_BlockMeta); std::pair<bool, Vector3i> GetOutputBlockPos(NIBBLETYPE a_BlockMeta);
void SetLocked(bool a_Value);
protected: protected:
Int64 m_LastMoveItemsInTick; Int64 m_LastMoveItemsInTick;
@ -91,6 +95,10 @@ protected:
/** Moves one piece to the specified entity's contents' slot. Returns true if contents have changed. */ /** Moves one piece to the specified entity's contents' slot. Returns true if contents have changed. */
bool MoveItemsToSlot(cBlockEntityWithItems & a_Entity, int a_DstSlotNum); bool MoveItemsToSlot(cBlockEntityWithItems & a_Entity, int a_DstSlotNum);
private:
bool m_Locked;
} ; // tolua_export } ; // tolua_export

View File

@ -2177,6 +2177,17 @@ bool cChunk::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceC
bool cChunk::DoWithHopperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cHopperCallback a_Callback)
{
return GenericDoWithBlockEntityAt<cHopperEntity,
E_BLOCK_HOPPER
>(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback) bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback)
{ {
return GenericDoWithBlockEntityAt<cNoteEntity, return GenericDoWithBlockEntityAt<cNoteEntity,

View File

@ -27,6 +27,7 @@ class cChunkDataCallback;
class cCommandBlockEntity; class cCommandBlockEntity;
class cDispenserEntity; class cDispenserEntity;
class cFurnaceEntity; class cFurnaceEntity;
class cHopperEntity;
class cNoteEntity; class cNoteEntity;
class cMobHeadEntity; class cMobHeadEntity;
class cFlowerPotEntity; class cFlowerPotEntity;
@ -332,6 +333,9 @@ public:
/** 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 */ /** 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 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 */ /** 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); bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback);

View File

@ -1629,6 +1629,24 @@ bool cChunkMap::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurna
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);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == nullptr) || !Chunk->IsValid())
{
return false;
}
return Chunk->DoWithHopperAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
bool cChunkMap::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback) bool cChunkMap::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback)
{ {
int ChunkX, ChunkZ; int ChunkX, ChunkZ;

View File

@ -29,6 +29,7 @@ class cDispenserEntity;
class cDropperEntity; class cDropperEntity;
class cDropSpenserEntity; class cDropSpenserEntity;
class cFurnaceEntity; class cFurnaceEntity;
class cHopperEntity;
class cNoteEntity; class cNoteEntity;
class cCommandBlockEntity; class cCommandBlockEntity;
class cMobHeadEntity; class cMobHeadEntity;
@ -53,6 +54,7 @@ using cDispenserCallback = cFunctionRef<bool(cDispenserEntity &)>;
using cDropperCallback = cFunctionRef<bool(cDropperEntity &)>; using cDropperCallback = cFunctionRef<bool(cDropperEntity &)>;
using cDropSpenserCallback = cFunctionRef<bool(cDropSpenserEntity &)>; using cDropSpenserCallback = cFunctionRef<bool(cDropSpenserEntity &)>;
using cFurnaceCallback = cFunctionRef<bool(cFurnaceEntity &)>; using cFurnaceCallback = cFunctionRef<bool(cFurnaceEntity &)>;
using cHopperCallback = cFunctionRef<bool(cHopperEntity &)>;
using cNoteBlockCallback = cFunctionRef<bool(cNoteEntity &)>; using cNoteBlockCallback = cFunctionRef<bool(cNoteEntity &)>;
using cCommandBlockCallback = cFunctionRef<bool(cCommandBlockEntity &)>; using cCommandBlockCallback = cFunctionRef<bool(cCommandBlockEntity &)>;
using cMobHeadCallback = cFunctionRef<bool(cMobHeadEntity &)>; using cMobHeadCallback = cFunctionRef<bool(cMobHeadEntity &)>;
@ -302,6 +304,10 @@ public:
Returns false if there's no furnace at those coords or callback returns true, returns true if found. */ 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 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. /** 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. */ 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 bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback); // Lua-accessible

View File

@ -7,6 +7,7 @@ set (HDRS
CommandBlockHandler.h CommandBlockHandler.h
DoorHandler.h DoorHandler.h
DropSpenserHandler.h DropSpenserHandler.h
HopperHandler.h
IncrementalRedstoneSimulator.h IncrementalRedstoneSimulator.h
RedstoneHandler.h RedstoneHandler.h
RedstoneSimulatorChunkData.h RedstoneSimulatorChunkData.h

View File

@ -0,0 +1,62 @@
#pragma once
#include "RedstoneHandler.h"
#include "../../BlockEntities/HopperEntity.h"
class cHopperHandler : public cRedstoneHandler
{
typedef cRedstoneHandler super;
public:
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
{
UNUSED(a_World);
UNUSED(a_Position);
UNUSED(a_BlockType);
UNUSED(a_Meta);
UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType);
return 0;
}
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
{
UNUSED(a_World);
UNUSED(a_Position);
UNUSED(a_BlockType);
UNUSED(a_Meta);
return 0;
}
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
{
// LOGD("Evaluating commander the cmdblck (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
auto Previous = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData);
if (Previous.PowerLevel != a_PoweringData.PowerLevel)
{
return {};
}
a_World.DoWithHopperAt(a_Position.x, a_Position.y, a_Position.z, [a_PoweringData](cHopperEntity & a_Hopper)
{
a_Hopper.SetLocked(a_PoweringData.PowerLevel != 0);
return false;
}
);
return {};
}
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
{
UNUSED(a_World);
UNUSED(a_BlockType);
UNUSED(a_Meta);
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
}
};

View File

@ -25,6 +25,7 @@
#include "DropSpenserHandler.h" #include "DropSpenserHandler.h"
#include "RedstoneComparatorHandler.h" #include "RedstoneComparatorHandler.h"
#include "TrappedChestHandler.h" #include "TrappedChestHandler.h"
#include "HopperHandler.h"
@ -98,6 +99,7 @@ std::unique_ptr<cRedstoneHandler> cIncrementalRedstoneSimulator::CreateComponent
case E_BLOCK_BLOCK_OF_REDSTONE: return cpp14::make_unique<cRedstoneBlockHandler>(); case E_BLOCK_BLOCK_OF_REDSTONE: return cpp14::make_unique<cRedstoneBlockHandler>();
case E_BLOCK_COMMAND_BLOCK: return cpp14::make_unique<cCommandBlockHandler>(); case E_BLOCK_COMMAND_BLOCK: return cpp14::make_unique<cCommandBlockHandler>();
case E_BLOCK_HOPPER: return cpp14::make_unique<cHopperHandler>();
case E_BLOCK_NOTE_BLOCK: return cpp14::make_unique<cNoteBlockHandler>(); case E_BLOCK_NOTE_BLOCK: return cpp14::make_unique<cNoteBlockHandler>();
case E_BLOCK_REDSTONE_WIRE: return cpp14::make_unique<cRedstoneWireHandler>(); case E_BLOCK_REDSTONE_WIRE: return cpp14::make_unique<cRedstoneWireHandler>();
case E_BLOCK_TNT: return cpp14::make_unique<cTNTHandler>(); case E_BLOCK_TNT: return cpp14::make_unique<cTNTHandler>();

View File

@ -1531,6 +1531,15 @@ bool cWorld::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceC
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) 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); return m_ChunkMap->DoWithNoteBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);

View File

@ -45,6 +45,7 @@ class cCuboid;
class cDispenserEntity; class cDispenserEntity;
class cFlowerPotEntity; class cFlowerPotEntity;
class cFurnaceEntity; class cFurnaceEntity;
class cHopperEntity;
class cNoteEntity; class cNoteEntity;
class cMobHeadEntity; class cMobHeadEntity;
class cCompositeChat; class cCompositeChat;
@ -769,6 +770,9 @@ public:
/** 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 */ /** 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 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 */ /** 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 bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback); // Exported in ManualBindings.cpp