From cc26f1646308a71ea78f0656efa670915e5e7345 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Wed, 10 Apr 2013 19:52:03 +0000 Subject: Added cItemGrid to represent an XY grid of items; converted chests to use cItemGrid. http://forum.mc-server.org/showthread.php?tid=831 git-svn-id: http://mc-server.googlecode.com/svn/trunk@1380 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/ItemGrid.cpp | 349 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 source/ItemGrid.cpp (limited to 'source/ItemGrid.cpp') diff --git a/source/ItemGrid.cpp b/source/ItemGrid.cpp new file mode 100644 index 000000000..f79bb5537 --- /dev/null +++ b/source/ItemGrid.cpp @@ -0,0 +1,349 @@ + +// ItemGrid.cpp + +// Implements the cItemGrid class representing a storage for items in a XY grid (chests, dispensers, inventory etc.) + +#include "Globals.h" +#include "ItemGrid.h" +#include "Items/ItemHandler.h" +#include "Noise.h" + + + + + +cItemGrid::cItemGrid(int a_Width, int a_Height) : + m_Width(a_Width), + m_Height(a_Height), + m_NumSlots(a_Width * a_Height), + m_Items(new cItem[a_Width * a_Height]) +{ +} + + + + + +cItemGrid::~cItemGrid() +{ + delete[] m_Items; +} + + + + + +int cItemGrid::GetSlotNum(int a_X, int a_Y) const +{ + if ( + (a_X < 0) || (a_X >= m_Width) || + (a_Y < 0) || (a_Y >= m_Height) + ) + { + LOGWARNING("%s: coords out of range: (%d, %d) in grid of size (%d, %d)", + __FUNCTION__, a_X, a_Y, m_Width, m_Height + ); + return -1; + } + return a_X + m_Width * a_Y; +} + + + + + +void cItemGrid::GetSlotCoords(int a_SlotNum, int & a_X, int & a_Y) const +{ + if ((a_SlotNum < 0) || (a_SlotNum >= m_NumSlots)) + { + LOGWARNING("%s: SlotNum out of range: %d in grid of range %d", + __FUNCTION__, a_SlotNum, m_NumSlots + ); + a_X = -1; + a_Y = -1; + return; + } + a_X = a_SlotNum % m_Width; + a_Y = a_SlotNum / m_Width; +} + + + + + +const cItem & cItemGrid::GetItem(int a_X, int a_Y) const +{ + return GetItem(GetSlotNum(a_X, a_Y)); +} + + + + + +cItem & cItemGrid::GetItem(int a_X, int a_Y) +{ + return GetItem(GetSlotNum(a_X, a_Y)); +} + + + + + +const cItem & cItemGrid::GetItem(int a_SlotNum) const +{ + 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_Items[0]; + } + return m_Items[a_SlotNum]; +} + + + + + +cItem & cItemGrid::GetItem(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_Items[0]; + } + return m_Items[a_SlotNum]; +} + + + + + +void cItemGrid::SetItem(int a_X, int a_Y, const cItem & a_Item) +{ + SetItem(GetSlotNum(a_X, a_Y), a_Item); +} + + + + + +void cItemGrid::SetItem(int a_X, int a_Y, short a_ItemType, char a_ItemCount, short a_ItemDamage) +{ + SetItem(GetSlotNum(a_X, a_Y), cItem(a_ItemType, a_ItemCount, a_ItemDamage)); +} + + + + + +void cItemGrid::SetItem(int a_SlotNum, const cItem & a_Item) +{ + 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_Items[a_SlotNum] = a_Item; +} + + + + + +void cItemGrid::SetItem(int a_SlotNum, short a_ItemType, char a_ItemCount, short a_ItemDamage) +{ + SetItem(a_SlotNum, cItem(a_ItemType, a_ItemCount, a_ItemDamage)); +} + + + + + +void cItemGrid::Clear(void) +{ + for (int i = 0; i < m_NumSlots; i++) + { + m_Items[i].Empty(); + } +} + + + + + +int cItemGrid::HowManyCanFit(const cItem & a_ItemStack) +{ + char NumLeft = a_ItemStack.m_ItemCount; + int MaxStack = ItemHandler(a_ItemStack.m_ItemType)->GetMaxStackSize(); + for (int i = m_NumSlots - 1; i >= 0; i--) + { + if (m_Items[i].IsEmpty()) + { + NumLeft -= MaxStack; + } + else if (m_Items[i].IsStackableWith(a_ItemStack)) + { + NumLeft -= MaxStack - m_Items[i].m_ItemCount; + } + if (NumLeft <= 0) + { + // All items fit + return a_ItemStack.m_ItemCount; + } + } // for i - m_Items[] + return a_ItemStack.m_ItemCount - NumLeft; +} + + + + + +bool cItemGrid::AddItem(cItem & a_ItemStack) +{ + int NumLeft = a_ItemStack.m_ItemCount; + int MaxStack = ItemHandler(a_ItemStack.m_ItemType)->GetMaxStackSize(); + for (int i = m_NumSlots - 1; i >= 0; i--) + { + if (m_Items[i].IsEmpty()) + { + m_Items[i] = a_ItemStack; + m_Items[i].m_ItemCount = std::min(MaxStack, NumLeft); + NumLeft -= m_Items[i].m_ItemCount; + } + else if (m_Items[i].IsStackableWith(a_ItemStack)) + { + int PrevCount = m_Items[i].m_ItemCount; + m_Items[i].m_ItemCount = std::min(MaxStack, PrevCount + NumLeft); + NumLeft -= m_Items[i].m_ItemCount - PrevCount; + } + if (NumLeft <= 0) + { + // All items fit + return true; + } + } // for i - m_Items[] + return (a_ItemStack.m_ItemCount > NumLeft); +} + + + + + +bool cItemGrid::AddItems(cItems & a_ItemStackList) +{ + bool res; + for (cItems::iterator itr = a_ItemStackList.begin(); itr != a_ItemStackList.end();) + { + res = AddItem(*itr) | res; + if (itr->IsEmpty()) + { + itr = a_ItemStackList.erase(itr); + } + else + { + ++itr; + } + } + return res; +} + + + + + +int cItemGrid::GetFirstEmptySlot(void) const +{ + return GetNextEmptySlot(-1); +} + + + + + +int cItemGrid::GetLastEmptySlot(void) const +{ + for (int i = m_NumSlots - 1; i >= 0; i--) + { + if (m_Items[i].IsEmpty()) + { + return i; + } + } + return -1; +} + + + + + +int cItemGrid::GetNextEmptySlot(int a_StartFrom) const +{ + for (int i = a_StartFrom + 1; i < m_NumSlots; i++) + { + if (m_Items[i].IsEmpty()) + { + return i; + } + } + return -1; +} + + + + + +void cItemGrid::CopyToItems(cItems & a_Items) const +{ + for (int i = 0; i < m_NumSlots; i++) + { + if (!m_Items[i].IsEmpty()) + { + a_Items.push_back(m_Items[i]); + } + } // for i - m_Items[] +} + + + + + +void cItemGrid::GenerateRandomLootWithBooks(const cLootProbab * a_LootProbabs, int a_CountLootProbabs, int a_NumSlots, int a_Seed) +{ + // Calculate the total weight: + int TotalProbab = 1; + for (int i = 0; i < a_CountLootProbabs; i++) + { + TotalProbab += a_LootProbabs[i].m_Weight; + } + + // Pick the loot items: + cNoise Noise(a_Seed); + for (int i = 0; i < a_NumSlots; i++) + { + int Rnd = (Noise.IntNoise1DInt(i) / 7); + int LootRnd = Rnd % TotalProbab; + Rnd >>= 8; + cItem CurrentLoot = cItem(E_ITEM_BOOK, 1, 0); // TODO: enchantment + for (int j = 0; j < a_CountLootProbabs; j++) + { + LootRnd -= a_LootProbabs[i].m_Weight; + if (LootRnd < 0) + { + CurrentLoot = a_LootProbabs[i].m_Item; + CurrentLoot.m_ItemCount = a_LootProbabs[i].m_MinAmount + (Rnd % (a_LootProbabs[i].m_MaxAmount - a_LootProbabs[i].m_MinAmount)); + Rnd >>= 8; + break; + } + } // for j - a_LootProbabs[] + SetItem(Rnd % m_NumSlots, CurrentLoot); + } // for i - NumSlots +} + + + + -- cgit v1.2.3