From edbc2790e31f27195835ef184a9d452bc83b2c56 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sun, 26 May 2013 20:52:39 +0000 Subject: [PATCH] Fixed cItemGrid API, no more changeable GetSlot(). Also fixed possible water and lava duplication glitches in the dispenser. git-svn-id: http://mc-server.googlecode.com/svn/trunk@1520 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Bindings.cpp | 10 +-- source/Bindings.h | 2 +- source/DispenserEntity.cpp | 139 +++++++++++++++++++++++++---------- source/DispenserEntity.h | 6 ++ source/DropSpenserEntity.cpp | 25 ++++++- source/DropSpenserEntity.h | 5 +- source/DropperEntity.cpp | 10 +-- source/ItemGrid.cpp | 25 ------- source/ItemGrid.h | 7 +- 9 files changed, 142 insertions(+), 87 deletions(-) diff --git a/source/Bindings.cpp b/source/Bindings.cpp index a6229c761..a3a23acce 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 05/26/13 17:28:14. +** Generated automatically by tolua++-1.0.92 on 05/26/13 22:51:07. */ #ifndef __cplusplus @@ -15038,7 +15038,7 @@ static int tolua_AllToLua_cItemGrid_AddItem00(lua_State* tolua_S) if ( !tolua_isusertype(tolua_S,1,"cItemGrid",0,&tolua_err) || (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"cItem",0,&tolua_err)) || - !tolua_isboolean(tolua_S,3,0,&tolua_err) || + !tolua_isboolean(tolua_S,3,1,&tolua_err) || !tolua_isnoobj(tolua_S,4,&tolua_err) ) goto tolua_lerror; @@ -15047,7 +15047,7 @@ static int tolua_AllToLua_cItemGrid_AddItem00(lua_State* tolua_S) { cItemGrid* self = (cItemGrid*) tolua_tousertype(tolua_S,1,0); cItem* a_ItemStack = ((cItem*) tolua_tousertype(tolua_S,2,0)); - bool a_AllowNewStacks = ((bool) tolua_toboolean(tolua_S,3,0)); + bool a_AllowNewStacks = ((bool) tolua_toboolean(tolua_S,3,true)); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'AddItem'", NULL); #endif @@ -15074,7 +15074,7 @@ static int tolua_AllToLua_cItemGrid_AddItems00(lua_State* tolua_S) if ( !tolua_isusertype(tolua_S,1,"cItemGrid",0,&tolua_err) || (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"cItems",0,&tolua_err)) || - !tolua_isboolean(tolua_S,3,0,&tolua_err) || + !tolua_isboolean(tolua_S,3,1,&tolua_err) || !tolua_isnoobj(tolua_S,4,&tolua_err) ) goto tolua_lerror; @@ -15083,7 +15083,7 @@ static int tolua_AllToLua_cItemGrid_AddItems00(lua_State* tolua_S) { cItemGrid* self = (cItemGrid*) tolua_tousertype(tolua_S,1,0); cItems* a_ItemStackList = ((cItems*) tolua_tousertype(tolua_S,2,0)); - bool a_AllowNewStacks = ((bool) tolua_toboolean(tolua_S,3,0)); + bool a_AllowNewStacks = ((bool) tolua_toboolean(tolua_S,3,true)); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'AddItems'", NULL); #endif diff --git a/source/Bindings.h b/source/Bindings.h index ca0f4e02a..2b47c8dd7 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 05/26/13 17:28:14. +** Generated automatically by tolua++-1.0.92 on 05/26/13 22:51:07. */ /* Exported function */ diff --git a/source/DispenserEntity.cpp b/source/DispenserEntity.cpp index 73aed05a6..8d64c01e0 100644 --- a/source/DispenserEntity.cpp +++ b/source/DispenserEntity.cpp @@ -37,85 +37,81 @@ void cDispenserEntity::DropSpenseFromSlot(int a_SlotNum) NIBBLETYPE Meta = m_World->GetBlockMeta(m_PosX, m_PosY, m_PosZ); AddDropSpenserDir(DispX, DispY, DispZ, Meta); - cItem & Drop = m_Contents.GetSlot(a_SlotNum); - // Dispense the item: - switch (Drop.m_ItemType) + switch (m_Contents.GetSlot(a_SlotNum).m_ItemType) { case E_ITEM_BUCKET: { BLOCKTYPE DispBlock = m_World->GetBlock(DispX, DispY, DispZ); - if (DispBlock == E_BLOCK_STATIONARY_WATER) + switch (DispBlock) { - m_World->SetBlock(DispX, DispY, DispZ, E_BLOCK_AIR, 0); - Drop.m_ItemType = E_ITEM_WATER_BUCKET; // TODO: Duplication glitch - bucket stacking allows you to duplicate water - } - else if (DispBlock == E_BLOCK_STATIONARY_LAVA) - { - m_World->SetBlock(DispX, DispY, DispZ, E_BLOCK_AIR, 0); - Drop.m_ItemType = E_ITEM_LAVA_BUCKET; // TODO: Duplication glitch - bucket stacking allows you to duplicate lava - } - else - { - cItems Pickups; - Pickups.push_back(Drop.CopyOne()); - m_World->SpawnItemPickups(Pickups, DispX, DispY, DispZ); - Drop.m_ItemCount--; + case E_BLOCK_STATIONARY_WATER: + case E_BLOCK_WATER: + { + if (ScoopUpLiquid(a_SlotNum, E_ITEM_WATER_BUCKET)) + { + m_World->SetBlock(DispX, DispY, DispZ, E_BLOCK_AIR, 0); + } + break; + } + case E_BLOCK_STATIONARY_LAVA: + case E_BLOCK_LAVA: + { + if (ScoopUpLiquid(a_SlotNum, E_ITEM_LAVA_BUCKET)) + { + m_World->SetBlock(DispX, DispY, DispZ, E_BLOCK_AIR, 0); + } + break; + } + default: + { + DropFromSlot(a_SlotNum); + break; + } } break; - } + } // E_ITEM_BUCKET case E_ITEM_WATER_BUCKET: { BLOCKTYPE DispBlock = m_World->GetBlock(DispX, DispY, DispZ); - if ((DispBlock == E_BLOCK_AIR) || IsBlockLiquid(DispBlock) || cFluidSimulator::CanWashAway(DispBlock)) + if (PlaceLiquid(DispBlock, a_SlotNum)) { - m_World->SetBlock(DispX, DispY, DispZ, E_BLOCK_STATIONARY_WATER, 0); - Drop.m_ItemType = E_ITEM_BUCKET; + m_World->SetBlock(DispX, DispY, DispZ, E_BLOCK_WATER, 0); } else { - cItems Pickups; - Pickups.push_back(Drop.CopyOne()); - m_World->SpawnItemPickups(Pickups, DispX, DispY, DispZ); - Drop.m_ItemCount--; + DropFromSlot(a_SlotNum); } break; } case E_ITEM_LAVA_BUCKET: { - BLOCKTYPE DispBlock = m_World->GetBlock( DispX, DispY, DispZ ); - if ((DispBlock == E_BLOCK_AIR) || IsBlockLiquid(DispBlock) || cFluidSimulator::CanWashAway(DispBlock)) + BLOCKTYPE DispBlock = m_World->GetBlock(DispX, DispY, DispZ); + if (PlaceLiquid(DispBlock, a_SlotNum)) { - m_World->SetBlock(DispX, DispY, DispZ, E_BLOCK_STATIONARY_LAVA, 0); - Drop.m_ItemType = E_ITEM_BUCKET; + m_World->SetBlock(DispX, DispY, DispZ, E_BLOCK_LAVA, 0); } else { - cItems Pickups; - Pickups.push_back(Drop.CopyOne()); - m_World->SpawnItemPickups(Pickups, DispX, DispY, DispZ); - Drop.m_ItemCount--; + DropFromSlot(a_SlotNum); } break; } case E_ITEM_SPAWN_EGG: { - if (m_World->SpawnMob(DispX + 0.5, DispY, DispZ + 0.5, Drop.m_ItemDamage) >= 0) + if (m_World->SpawnMob(DispX + 0.5, DispY, DispZ + 0.5, m_Contents.GetSlot(a_SlotNum).m_ItemDamage) >= 0) { - Drop.m_ItemCount--; + m_Contents.ChangeSlotCount(a_SlotNum, -1); } break; } default: { - cItems Pickups; - Pickups.push_back(Drop.CopyOne()); - m_World->SpawnItemPickups(Pickups, DispX, DispY, DispZ); - Drop.m_ItemCount--; + DropFromSlot(a_SlotNum); break; } } // switch (ItemType) @@ -125,3 +121,66 @@ void cDispenserEntity::DropSpenseFromSlot(int a_SlotNum) + +bool cDispenserEntity::ScoopUpLiquid(int a_SlotNum, short a_BucketItemType) +{ + cItem LiquidBucket(a_BucketItemType, 1); + if (m_Contents.GetSlot(a_SlotNum).m_ItemCount == 1) + { + // Special case: replacing one empty bucket with one full bucket + m_Contents.SetSlot(a_SlotNum, LiquidBucket); + return true; + } + + // There are stacked buckets at the selected slot, see if a full bucket will fit somewhere else + if (m_Contents.HowManyCanFit(LiquidBucket) < 1) + { + // Cannot fit into m_Contents + return false; + } + + m_Contents.ChangeSlotCount(a_SlotNum, -1); + m_Contents.AddItem(LiquidBucket); + return true; +} + + + + + +bool cDispenserEntity::PlaceLiquid(BLOCKTYPE a_BlockInFront, int a_SlotNum) +{ + if ( + (a_BlockInFront != E_BLOCK_AIR) && + !IsBlockLiquid(a_BlockInFront) && + !cFluidSimulator::CanWashAway(a_BlockInFront) + ) + { + // Not a suitable block in front + return false; + } + + cItem EmptyBucket(E_ITEM_BUCKET, 1); + if (m_Contents.GetSlot(a_SlotNum).m_ItemCount == 1) + { + // Change the single full bucket present into a single empty bucket + m_Contents.SetSlot(a_SlotNum, EmptyBucket); + return true; + } + + // There are full buckets stacked at this slot, check if we can fit in the empty bucket + if (m_Contents.HowManyCanFit(EmptyBucket) < 1) + { + // The empty bucket wouldn't fit into m_Contents + return false; + } + + // The empty bucket fits in, remove one full bucket and add the empty one + m_Contents.ChangeSlotCount(a_SlotNum, -1); + m_Contents.AddItem(EmptyBucket); + return true; +} + + + + diff --git a/source/DispenserEntity.h b/source/DispenserEntity.h index 9d788128f..ad6400921 100644 --- a/source/DispenserEntity.h +++ b/source/DispenserEntity.h @@ -28,6 +28,12 @@ public: private: // cDropSpenser overrides: virtual void DropSpenseFromSlot(int a_SlotNum) override; + + /// If such a bucket can fit, adds it to m_Contents and returns true + bool ScoopUpLiquid(int a_SlotNum, short a_BucketItemType); + + /// If the a_BlockInFront is liquidable and the empty bucket can fit, does the m_Contents processing and returns true + bool PlaceLiquid(BLOCKTYPE a_BlockInFront, int a_SlotNum); } ; // tolua_export diff --git a/source/DropSpenserEntity.cpp b/source/DropSpenserEntity.cpp index 580f96944..3830e1d01 100644 --- a/source/DropSpenserEntity.cpp +++ b/source/DropSpenserEntity.cpp @@ -146,8 +146,14 @@ bool cDropSpenserEntity::LoadFromJson(const Json::Value & a_Value) int SlotIdx = 0; for (Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr) { - m_Contents.GetSlot(SlotIdx).FromJson(*itr); + cItem Contents; + Contents.FromJson(*itr); + m_Contents.SetSlot(SlotIdx, Contents); SlotIdx++; + if (SlotIdx >= m_Contents.GetNumSlots()) + { + return true; + } } return true; @@ -210,3 +216,20 @@ void cDropSpenserEntity::UsedBy(cPlayer * a_Player) + +void cDropSpenserEntity::DropFromSlot(int a_SlotNum) +{ + int DispX = m_PosX; + int DispY = m_PosY; + int DispZ = m_PosZ; + NIBBLETYPE Meta = m_World->GetBlockMeta(m_PosX, m_PosY, m_PosZ); + AddDropSpenserDir(DispX, DispY, DispZ, Meta); + + cItems Pickups; + Pickups.push_back(m_Contents.RemoveOneItem(a_SlotNum)); + m_World->SpawnItemPickups(Pickups, DispX, DispY, DispZ); +} + + + + diff --git a/source/DropSpenserEntity.h b/source/DropSpenserEntity.h index d6e1144b1..f4221808c 100644 --- a/source/DropSpenserEntity.h +++ b/source/DropSpenserEntity.h @@ -67,13 +67,16 @@ public: // tolua_end -private: +protected: bool m_ShouldDropSpense; ///< If true, the dropspenser will dropspense an item in the next tick void DropSpense(void); /// Override this function to provide the specific behavior for item dropspensing (drop / shoot / pour / ...) virtual void DropSpenseFromSlot(int a_SlotNum) = 0; + + /// Helper function, drops one item from the specified slot (like a dropper) + void DropFromSlot(int a_SlotNum); } ; // tolua_export diff --git a/source/DropperEntity.cpp b/source/DropperEntity.cpp index dab320eb1..39c2cf3bd 100644 --- a/source/DropperEntity.cpp +++ b/source/DropperEntity.cpp @@ -34,15 +34,7 @@ cDropperEntity::cDropperEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld void cDropperEntity::DropSpenseFromSlot(int a_SlotNum) { - int DispX = m_PosX; - int DispY = m_PosY; - int DispZ = m_PosZ; - NIBBLETYPE Meta = m_World->GetBlockMeta(m_PosX, m_PosY, m_PosZ); - AddDropSpenserDir(DispX, DispY, DispZ, Meta); - - cItems Pickups; - Pickups.push_back(m_Contents.RemoveOneItem(a_SlotNum).CopyOne()); - m_World->SpawnItemPickups(Pickups, DispX, DispY, DispZ); + DropFromSlot(a_SlotNum); } diff --git a/source/ItemGrid.cpp b/source/ItemGrid.cpp index 5a432e80f..33cae3e17 100644 --- a/source/ItemGrid.cpp +++ b/source/ItemGrid.cpp @@ -81,15 +81,6 @@ const cItem & cItemGrid::GetSlot(int a_X, int a_Y) const -cItem & cItemGrid::GetSlot(int a_X, int a_Y) -{ - return GetSlot(GetSlotNum(a_X, a_Y)); -} - - - - - const cItem & cItemGrid::GetSlot(int a_SlotNum) const { if ((a_SlotNum < 0) || (a_SlotNum >= m_NumSlots)) @@ -106,22 +97,6 @@ const cItem & cItemGrid::GetSlot(int a_SlotNum) const -cItem & cItemGrid::GetSlot(int a_SlotNum) -{ - if ((a_SlotNum < 0) || (a_SlotNum >= m_NumSlots)) - { - LOGWARNING("%s: Invalid slot number, %d out of %d slots", - __FUNCTION__, a_SlotNum, m_NumSlots - ); - return m_Slots[0]; - } - return m_Slots[a_SlotNum]; -} - - - - - void cItemGrid::SetSlot(int a_X, int a_Y, const cItem & a_Item) { SetSlot(GetSlotNum(a_X, a_Y), a_Item); diff --git a/source/ItemGrid.h b/source/ItemGrid.h index 80ea17c8b..72b7d3b03 100644 --- a/source/ItemGrid.h +++ b/source/ItemGrid.h @@ -46,9 +46,6 @@ public: /// Converts slot number into XY coords; sets coords to -1 on invalid slot number. Exported in ManualBindings.cpp void GetSlotCoords(int a_SlotNum, int & a_X, int & a_Y) const; - cItem & GetSlot(int a_X, int a_Y); // TODO: This will be removed! - cItem & GetSlot(int a_SlotNum); // TODO: This will be removed! - // tolua_begin // Retrieve slots by coords or slot number; Logs warning and returns the first slot on invalid coords / slotnum @@ -76,7 +73,7 @@ public: if a_AllowNewStacks is set to true, empty slots can be used for the rest Returns the number of items that fit. */ - int AddItem(cItem & a_ItemStack, bool a_AllowNewStacks); + int AddItem(cItem & a_ItemStack, bool a_AllowNewStacks = true); /** Same as AddItem, but works on an entire list of item stacks. The a_ItemStackList is modified to reflect the leftover items. @@ -84,7 +81,7 @@ public: if a_AllowNewStacks is set to true, empty slots can be used for the rest Returns the total number of items that fit. */ - int AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks); + int AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks = true); /** Adds (or subtracts, if a_AddToCount is negative) to the count of items in the specified slot. If the slot is empty, ignores the call.