Updated the crafting recipes architecture to better support crafting hooks. Removed the old recipe file and implementation altogether.

git-svn-id: http://mc-server.googlecode.com/svn/trunk@597 0a769ca7-a7f5-676a-18bf-c427514a06d6
master
madmaxoft@gmail.com 2012-06-12 20:03:46 +00:00
parent e147996f06
commit 5e6c736859
19 changed files with 1401 additions and 1040 deletions

View File

@ -467,14 +467,6 @@
RelativePath="..\source\CraftingRecipes.h"
>
</File>
<File
RelativePath="..\source\cRecipeChecker.cpp"
>
</File>
<File
RelativePath="..\source\cRecipeChecker.h"
>
</File>
<File
RelativePath="..\source\cRedstone.cpp"
>

View File

@ -357,7 +357,6 @@
<ClCompile Include="..\Source\cPluginManager.cpp" />
<ClCompile Include="..\source\cPlugin_NewLua.cpp" />
<ClCompile Include="..\source\CraftingRecipes.cpp" />
<ClCompile Include="..\Source\cRecipeChecker.cpp" />
<ClCompile Include="..\source\cRedstone.cpp" />
<ClCompile Include="..\source\cRedstoneSimulator.cpp" />
<ClCompile Include="..\Source\cReferenceManager.cpp" />
@ -539,7 +538,6 @@
<ClInclude Include="..\Source\cPluginManager.h" />
<ClInclude Include="..\source\cPlugin_NewLua.h" />
<ClInclude Include="..\source\CraftingRecipes.h" />
<ClInclude Include="..\Source\cRecipeChecker.h" />
<ClInclude Include="..\source\cRedstone.h" />
<ClInclude Include="..\source\cRedstoneSimulator.h" />
<ClInclude Include="..\Source\cReferenceManager.h" />

View File

@ -55,9 +55,6 @@
<Filter Include="cWindow\cWindowOwner">
<UniqueIdentifier>{014bf50c-1589-4fda-8b62-1a8100e451f2}</UniqueIdentifier>
</Filter>
<Filter Include="cRecipeChecker">
<UniqueIdentifier>{f7875f7a-f596-4690-8f0d-678989b9d7c3}</UniqueIdentifier>
</Filter>
<Filter Include="cWindow\cCraftingWindow">
<UniqueIdentifier>{0047a86b-b12e-4b61-987f-1e558719226f}</UniqueIdentifier>
</Filter>
@ -490,9 +487,6 @@
<ClCompile Include="..\source\cWindow.cpp">
<Filter>cWindow</Filter>
</ClCompile>
<ClCompile Include="..\Source\cRecipeChecker.cpp">
<Filter>cRecipeChecker</Filter>
</ClCompile>
<ClCompile Include="..\source\cCraftingWindow.cpp">
<Filter>cWindow\cCraftingWindow</Filter>
</ClCompile>
@ -975,9 +969,6 @@
<Filter>cWindow\cWindowOwner</Filter>
</ClInclude>
<ClInclude Include="..\Source\MemoryLeak.h" />
<ClInclude Include="..\Source\cRecipeChecker.h">
<Filter>cRecipeChecker</Filter>
</ClInclude>
<ClInclude Include="..\source\cCraftingWindow.h">
<Filter>cWindow\cCraftingWindow</Filter>
</ClInclude>

View File

@ -1,338 +0,0 @@
#***********************************#
# Default Crafting Recipes #
#***********************************#
# #
# Coded by: FakeTruth #
# Written by: Aelux #
# #
# Contributors: Luksor #
# xoft #
# #
#***********************************#
#******************************************************#
# Basic Notation Help
#
# 1x1,1:1:17:1@5:4 -> Produces 4 Planks
#
#
# --How does the above notation work?
#
# Ans- Think about the crafting table as coordiantes
# on a graph where you have an "X" axis and a
# "Y" axis. The "X" is the horizantle axis and
# the "Y" is the vertical axis.
#
# Syntax: <dimensions>,<ingredient1>,<ingredient2>,...<ingredientN>@<result>
# <dimensions> = <Width>x<Height>
# <ingredientN> = x:y:<ItemID>:<Amount>
# <result> = <ResultingItemID>:<Amount>
#--------------------Basic EXAMPLE---------------------
#
# Example- 3x3,2:3:280:8@5:2
#
# Recipe- w=3,h=3,x=2,y=3,Item=Stick,Amount=8
# Result- 2 Wood Planks (2 of ItemID 5)
#
# Table grid is set to 3 by 3 (O = empty, X = full)
# +---+
# |OOO|
# |OOO|
# |OXO|
# +---+
#
# --How does the above example work?
#
# Ans- This means, if you place a stack of 8 sticks
# at that exact location on the Work Bench,
# which is a 3x3 grid, you will recieve 2 Wood
# Planks PER 8 sticks.
#
#
#
#******************************************************
#---------------Grid Abstraction EXAMPLE------------------#
#
# Example- 1x1,1:1:280:8@5:2
# Recipe- w=1,h=1,x=1,y=1,Item=Stick,Amount=8
# Result- 2 Wood Planks (2 of ItemID 5)
#
# Table grid is set to 1 by 1 (O = empty,X = full)
# +-+
# |X|
# +-+
#
# -- How does the above example compare to the Basic
# example?
#
# Ans- This means, you can place a stack of 8 sticks
# ANYwhere a 1x1 grid can fit. Obviously since a 1x1
# grid is a single slot, it can be abstracted to fill
# any single slot on any size grid.
#
# There are 9 positions for the 1x1 grid in the
# work bench (3x3) and 4 positions within the
# inventory grid (2x2).
#********************************************************
#******************************************************#
# Utilities
#
3x2,1:2:265:1,2:3:265:1@325:1 # -> Bucket
1x2,1:1:265:1,1:2:318:1@259:1 # -> Lighter
3x3,1:3:280:1,2:2:280:1,3:1:280:1,3:2:287:1,3:3:287:1@346:1 # -> Fishing Rod
3x3,1:2:265:1,2:1:265:1,2:2:331:1,3:2:265:1,2:3:265:1@345:1 # -> Compass
3x3,1:2:266:1,2:1:266:1,2:2:331:1,3:2:266:1,2:3:266:1@345:1 # -> Watch
3x3,1:*:287:1,2:1:280:1,3:2:280:1,2:3:280:1@261:1 # -> Bow
1x3,1:1:318:1,1:2:280:1,1:3:288:1@262:4 # -> Arrow
2x3,*:*:5:1@64:1 # -> Wooden Door
3x3,*:1:280:-1@85:2 # -> Fence
3x2,*:*:265:1@101:16 # -> Iron Bars
3x2,*:*:20:1@102:16 # -> Glass Pane
3x3,1:*:280:1,3:*:280:1,2:2:280:1@65:1 # -> Ladder
3x2,*:*:5:1,2:3:280:1@323:1 # -> Sign
1x2,1:1:368:1,1:2:377:1@381:1 # -> Eye of Ender
3x2,1:1:20:1,2:2:20:1,3:1:20:1@374:3 # -> Glass Bottle
3x3,1:*:265:1,2:3:265:1,3:*:265:1@380:1 # -> Cauldron
3x2,2:1:369:1,*:2:4:1@379:1 # -> Brewing Stand
#******************************************************#
# Travel Utilities
#
3x3,1:*:265:1,3:*:265:1,2:2:280:1@66:16 # -> Rails
3x3,1:*:266:1,3:*:266:1,2:2:280:1,2:3:331:1@27:6 # -> Powered Rail
3x3,1:*:265:1,3:*:265:1,2:2:70:1,2:3:331:1@28:6 # -> Detector Rail
3x2,1:2:265:1,3:2:265:1,*:3:265:1@328:1 # -> Minecart
1x2,1:1:61:1,1:2:328:1@343:1 # -> Powered Minecart
1x2,1:1:54:1,1:2:328:1@342:1 # -> Storage Minecart
3x2,1:2:5:1,3:2:5:1,*:3:5:1@333:1 # -> Boat
#******************************************************#
# Control Utilities
#
1x2,1:1:331:1,1:2:280:1@76:1 # -> Redstone Torch
1x2,1:1:280:1,1:2:4:1@69:1 # -> Lever
2x1,*:*:5:1@72:1 # -> Wooden Preassure Plate
2x1,*:*:4:1@70:1 # -> Stone Preassure Plate
1x2,1:1:1:1,1:2:1:1@77:1 # -> Button
2x3,*:*:265:1@71:1 # -> Iron Door
3x2,*:2:1:1,1:1:76:1,2:1:331:1,3:1:76:1@356:1 # -> Repeater
3x3,2:1:331:1,1:2:331:1,2:2:89:1,3:2:331:1,2:3:331:1@123:1 # -> Lamp
3x3,*:1:5:1,1:2:4:1,2:2:265:1,3:2:4:1,1:3:4:1,2:3:331:1,3:3:4:1@33:1 # -> Piston
1x2,1:1:341:1,1:2:33:1@29:1 # -> Sticky Piston
#******************************************************#
# Material Blocks
#
3x3,*:*:265:1@42:1 # -> Iron
3x3,*:*:266:1@41:1 # -> Gold
3x3,*:*:264:1@57:1 # -> Diamond
2x2,*:*:287:1@35:1 # -> Wool
2x2,*:*:337:1@82:1 # -> Clay
2x2,*:*:336:1@45:1 # -> Brick
2x2,*:*:341:1@80:1 # -> Snow
#******************************************************#
# Special Blocks
#
3x1,*:*:1:1@44:3 # -> Stone Step
3x3,*:3:5:1,1:1:5:1,1:2:5:1,2:2:5:1@53:4 # -> Wood Stairs
3x3,*:3:4:1,1:1:4:1,1:2:4:1,2:2:4:1@67:4 # -> Cobblestone Stairs
3x3,1:1:289:1,3:1:289:1,2:2:289:1,1:3:289:1,3:3:289:1,2:1:12:1,1:2:12:1,3:2:12:1,2:3:12:1@46:1 # -> TNT
3x3,2:2:5:-1,2:2:264:1@84:1 # -> Jukebox
2x2,*:*:348:1@89:1 # -> Glow Stone
2x2,*:*:1:1@98:4 # -> Stone Brick
2x2,*:*:12:1@24:1 # -> Sandstone
3x2,*:1:35:1,*:2:5:1@355:1 # -> Bed
3x3,2:1:340:1,1:2:264:1,2:2:49:1,3:2:264:1,*:3:49:1@116:1 # -> Enchantment Table
#******************************************************#
# Block To Ingot
#
1x1,1:1:42:1@265:9 # -> Iron
1x1,1:1:41:1@266:9 # -> Gold
3x3,*:*:371:1@266:1 # -> Gold (from Nuggets)
1x1,1:1:57:1@264:9 # -> Diamond
#******************************************************#
# Shovel
#
1x3,1:1:5:1,1:2:280:1,1:3:280:1@269:1 # -> Wooden
1x3,1:1:4:1,1:2:280:1,1:3:280:1@273:1 # -> Stone
1x3,1:1:266:1,1:2:280:1,1:3:280:1@284:1 # -> Gold
1x3,1:1:265:1,1:2:280:1,1:3:280:1@256:1 # -> Iron
1x3,1:1:264:1,1:2:280:1,1:3:280:1@277:1 #.-> Diamond
#******************************************************#
# Pickaxe
#
3x3,*:1:5:1,2:2:280:1,2:3:280:1@270:1 # -> Wooden
3x3,*:1:4:1,2:2:280:1,2:3:280:1@274:1 # -> Stone
3x3,*:1:266:1,2:2:280:1,2:3:280:1@285:1 # -> Gold
3x3,*:1:265:1,2:2:280:1,2:3:280:1@257:1 # -> Iron
3x3,*:1:264:1,2:2:280:1,2:3:280:1@278:1 # -> Diamond
#******************************************************#
# Axe
#
2x2,2:2:5:-1,2:2:280:1,2:3:280:1@271:1 # -> Wooden (L)
2x2,1:2:5:-1,1:2:280:1,1:3:280:1@271:1 # -> Wooden (R)
2x2,2:2:4:-1,2:2:280:1,2:3:280:1@275:1 # -> Stone (L)
2x2,1:2:4:-1,1:2:280:1,1:3:280:1@275:1 # -> Stone (R)
2x2,2:2:266:-1,2:2:280:1,2:3:280:1@286:1 # -> Gold (L)
2x2,1:2:266:-1,1:2:280:1,1:3:280:1@286:1 # -> Gold (R)
2x2,2:2:265:-1,2:2:280:1,2:3:280:1@258:1 # -> Iron (L)
2x2,1:2:265:-1,1:2:280:1,1:3:280:1@258:1 #.-> Iron (R)
2x2,2:2:264:-1,2:2:280:1,2:3:280:1@279:1 #.-> Diamond (L)
2x2,1:2:264:-1,1:2:280:1,1:3:280:1@279:1 #.-> Diamond (R)
#******************************************************#
# Sword
#
1x2,*:*:5:1,1:3:280:1@268:1 # -> Wooden
1x2,*:*:4:1,1:3:280:1@272:1 # -> Stone
1x2,*:*:266:1,1:3:280:1@283:1 # -> Gold
1x2,*:*:265:1,1:3:280:1@267:1 # -> Iron
1x2,*:*:264:1,1:3:280:1@276:1 # -> Diamond
#******************************************************#
# Hoe
#
2x1,*:*:5:1,2:2:280:1,2:3:280:1@290:1 # -> Wooden (L)
2x1,*:*:5:1,1:2:280:1,1:3:280:1@290:1 # -> Wooden (R)
2x1,*:*:4:1,2:2:280:1,2:3:280:1@291:1 # -> Stone (L)
2x1,*:*:4:1,1:2:280:1,1:3:280:1@291:1 # -> Stone (R)
2x1,*:*:266:1,2:2:280:1,2:3:280:1@294:1 # -> Gold (L)
2x1,*:*:266:1,1:2:280:1,1:3:280:1@294:1 # -> Gold (R)
2x1,*:*:265:1,2:2:280:1,2:3:280:1@292:1 # -> Iron (L)
2x1,*:*:265:1,1:2:280:1,1:3:280:1@292:1 # -> Iron (R)
2x1,*:*:264:1,2:2:280:1,2:3:280:1@293:1 # -> Diamond (L)
2x1,*:*:264:1,1:2:280:1,1:3:280:1@293:1 # -> Diamond (R)
#******************************************************#
# Leather Armor
#
3x2,2:2:334:-1@298:1 #-> Helmet
3x3,2:1:334:-1@299:1 #-> Chest Piece
3x3,1:*:334:1,3:*:334:1,2:1:334:1@300:1 #-> Leggings
3x2,2:*:334:-1@301:1 #-> Boots
#*******************************************************#
# Gold Armor
#
3x2,2:2:266:-1@314:1 #-> Helmet
3x3,2:1:266:-1@315:1 #-> Chest Piece
3x3,1:*:266:1,3:*:266:1,2:1:266:1@316:1 #-> Leggings
3x2,2:*:266:-1@317:1 #-> Boots
#*******************************************************#
# Iron Armor
#
3x2,2:2:265:-1@306:1 #-> Helmet
3x3,2:1:265:-1@307:1 #-> Chest Piece
3x3,1:*:265:1,3:*:265:1,2:1:265:1@308:1 #-> Leggings
3x2,2:*:265:-1@309:1 #-> Boots
#*******************************************************#
# Diamond Armor
#
3x2,2:2:264:-1@310:1 #-> Helmet
3x3,2:1:264:-1@311:1 #-> Chest Piece
3x3,1:*:264:1,3:*:264:1,2:1:264:1@312:1 #-> Leggings
3x2,2:*:264:-1@313:1 #-> Boots
#*******************************************************#
# Decorative
#
3x1,*:3:338:1@339:3 #-> Paper
1x3,2:*:338:1@340:1 #-> Book
3x3,*:1:5:1,*:2:349:1,*:3:5:1@47:1 #-> Book Shelf
3x3,2:2:280:-1,2:2:35:1@321:1 #-> Painting
1x2,1:1:86:1,1:2:50:1@91:1 #-> Jack-O-Lantern
#*******************************************************#
# O t h e r I t e m s
#
1x1,1:1:369:1@377:2 #-> Blaze Powder
1x2,1:1:341:1,1:2:377:1@378:1 #-> Magma Cream
1x1,1:1:266:1@371:9 #-> Gold Nugget

View File

@ -45,4 +45,5 @@ $cfile "cGroup.h"
$cfile "packets/cPacket_Login.h"
$cfile "packets/cPacket_BlockDig.h"
$cfile "packets/cPacket_BlockPlace.h"
$cfile "cLuaChunk.h"
$cfile "cLuaChunk.h"
$cfile "CraftingRecipes.h"

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 06/10/12 15:55:56.
** Generated automatically by tolua++-1.0.92 on 06/12/12 21:57:04.
*/
/* Exported function */

View File

@ -10,6 +10,253 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cCraftingGrid:
cCraftingGrid::cCraftingGrid(int a_Width, int a_Height) :
m_Width(a_Width),
m_Height(a_Height),
m_Items(new cItem[a_Width * a_Height])
{
}
cCraftingGrid::cCraftingGrid(cItem * a_Items, int a_Width, int a_Height) :
m_Width(a_Width),
m_Height(a_Height),
m_Items(new cItem[a_Width * a_Height])
{
for (int i = a_Width * a_Height - 1; i >= 0; i--)
{
m_Items[i] = a_Items[i];
}
}
cCraftingGrid::cCraftingGrid(const cCraftingGrid & a_Original) :
m_Width(a_Original.m_Width),
m_Height(a_Original.m_Height),
m_Items(new cItem[a_Original.m_Width * a_Original.m_Height])
{
for (int i = m_Width * m_Height - 1; i >= 0; i--)
{
m_Items[i] = a_Original.m_Items[i];
}
}
cCraftingGrid::~cCraftingGrid()
{
delete[] m_Items;
}
cItem & cCraftingGrid::GetItem(int x, int y) const
{
// Accessible through scripting, must verify parameters:
if ((x < 0) || (x >= m_Width) || (y < 0) || (y >= m_Height))
{
LOGERROR("Attempted to get an invalid item from a crafting grid: (%d, %d), grid dimensions: (%d, %d).",
x, y, m_Width, m_Height
);
return m_Items[0];
}
return m_Items[x + m_Width * y];
}
void cCraftingGrid::SetItem(int x, int y, ENUM_ITEM_ID a_ItemType, short a_ItemHealth, int a_ItemCount)
{
// Accessible through scripting, must verify parameters:
if ((x < 0) || (x >= m_Width) || (y < 0) || (y >= m_Height))
{
LOGERROR("Attempted to set an invalid item in a crafting grid: (%d, %d), grid dimensions: (%d, %d).",
x, y, m_Width, m_Height
);
return;
}
m_Items[x + m_Width * y] = cItem(a_ItemType, a_ItemCount, a_ItemHealth);
}
void cCraftingGrid::SetItem(int x, int y, const cItem & a_Item)
{
// Accessible through scripting, must verify parameters:
if ((x < 0) || (x >= m_Width) || (y < 0) || (y >= m_Height))
{
LOGERROR("Attempted to set an invalid item in a crafting grid: (%d, %d), grid dimensions: (%d, %d).",
x, y, m_Width, m_Height
);
return;
}
m_Items[x + m_Width * y] = a_Item;
}
void cCraftingGrid::Clear(void)
{
for (int y = 0; y < m_Height; y++) for (int x = 0; x < m_Width; x++)
{
m_Items[x + m_Width * y].Empty();
}
}
void cCraftingGrid::ConsumeGrid(const cCraftingGrid & a_Grid)
{
if ((a_Grid.m_Width != m_Width) || (a_Grid.m_Height != m_Height))
{
LOGWARNING("Consuming a grid of different dimensions: (%d, %d) vs (%d, %d)",
a_Grid.m_Width, a_Grid.m_Height, m_Width, m_Height
);
}
int MinX = std::min(a_Grid.m_Width, m_Width);
int MinY = std::min(a_Grid.m_Height, m_Height);
for (int y = 0; y < MinY; y++) for (int x = 0; x < MinX; x++)
{
int ThatIdx = x + a_Grid.m_Width * y;
if (a_Grid.m_Items[ThatIdx].IsEmpty())
{
continue;
}
int ThisIdx = x + m_Width * y;
if (a_Grid.m_Items[ThatIdx].m_ItemID != m_Items[ThisIdx].m_ItemID)
{
LOGWARNING("Consuming incompatible grids: item at (%d, %d) is %d in grid and %d in ingredients. Item not consumed.",
x, y, m_Items[ThisIdx].m_ItemID, a_Grid.m_Items[ThatIdx].m_ItemID
);
continue;
}
char NumWantedItems = a_Grid.m_Items[ThatIdx].m_ItemCount;
if (NumWantedItems > m_Items[ThisIdx].m_ItemCount)
{
LOGWARNING("Consuming more items than there actually are in slot (%d, %d), item %d (want %d, have %d). Item zeroed out.",
x, y, m_Items[ThisIdx].m_ItemID,
NumWantedItems, m_Items[ThisIdx].m_ItemCount
);
NumWantedItems = m_Items[ThisIdx].m_ItemCount;
}
m_Items[ThisIdx].m_ItemCount -= NumWantedItems;
if (m_Items[ThisIdx].m_ItemCount == 0)
{
m_Items[ThisIdx].Clear();
}
} // for x, for y
}
void cCraftingGrid::CopyToItems(cItem * a_Items) const
{
for (int i = m_Height * m_Width - 1; i >= 0; i--)
{
a_Items[i] = m_Items[i];
} // for x, for y
}
void cCraftingGrid::Dump(void)
{
for (int y = 0; y < m_Height; y++) for (int x = 0; x < m_Width; x++)
{
int idx = x + m_Width * y;
LOGD("Slot (%d, %d): Type %d, health %d, count %d",
x, y, m_Items[idx].m_ItemID, m_Items[idx].m_ItemHealth, m_Items[idx].m_ItemCount
);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cCraftingRecipe:
cCraftingRecipe::cCraftingRecipe(const cCraftingGrid & a_CraftingGrid) :
m_Ingredients(a_CraftingGrid)
{
}
void cCraftingRecipe::Clear(void)
{
m_Ingredients.Clear();
m_Result.Clear();
}
void cCraftingRecipe::SetResult(ENUM_ITEM_ID a_ItemType, short a_ItemHealth, int a_ItemCount)
{
m_Result = cItem(a_ItemType, a_ItemCount, a_ItemHealth);
}
void cCraftingRecipe::ConsumeIngredients(cCraftingGrid & a_CraftingGrid)
{
a_CraftingGrid.ConsumeGrid(m_Ingredients);
}
void cCraftingRecipe::Dump(void)
{
LOGD("Recipe ingredients:");
m_Ingredients.Dump();
LOGD("Result: Type %d, health %d, count %d",
m_Result.m_ItemID, m_Result.m_ItemHealth, m_Result.m_ItemCount
);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cCraftingRecipes:
cCraftingRecipes::cCraftingRecipes(void)
{
LoadRecipes();
@ -28,42 +275,22 @@ cCraftingRecipes::~cCraftingRecipes()
/// Offers an item resulting from the crafting grid setup. Doesn't modify the grid
cItem cCraftingRecipes::Offer(const cItem * a_CraftingGrid, int a_GridWidth, int a_GridHeight)
void cCraftingRecipes::GetRecipe(const cCraftingGrid & a_CraftingGrid, cCraftingRecipe & a_Recipe)
{
std::auto_ptr<cRecipe> Recipe(FindRecipe(a_CraftingGrid, a_GridWidth, a_GridHeight));
// TODO: Allow plugins to intercept recipes, add a pre-craft hook here
std::auto_ptr<cRecipe> Recipe(FindRecipe(a_CraftingGrid.GetItems(), a_CraftingGrid.GetWidth(), a_CraftingGrid.GetHeight()));
a_Recipe.Clear();
if (Recipe.get() == NULL)
{
return cItem();
// TODO: Allow plugins to intercept recipes, add a post-craft hook here
return;
}
return Recipe->m_Result;
}
/// Crafts the item resulting from the crafting grid setup. Modifies the grid, returns the crafted item
cItem cCraftingRecipes::Craft(cItem * a_CraftingGrid, int a_GridWidth, int a_GridHeight)
{
std::auto_ptr<cRecipe> Recipe(FindRecipe(a_CraftingGrid, a_GridWidth, a_GridHeight));
if (Recipe.get() == NULL)
{
return cItem();
}
// Consume the ingredients from the grid:
for (cRecipeSlots::const_iterator itr = Recipe->m_Ingredients.begin(); itr != Recipe->m_Ingredients.end(); ++itr)
{
int GridIdx = itr->x + a_GridWidth * itr->y;
a_CraftingGrid[GridIdx].m_ItemCount -= itr->m_Item.m_ItemCount;
if (a_CraftingGrid[GridIdx].m_ItemCount <= 0)
{
a_CraftingGrid[GridIdx].Empty();
}
}
return Recipe->m_Result;
a_Recipe.SetIngredient(itr->x, itr->y, itr->m_Item);
} // for itr
a_Recipe.SetResult(Recipe->m_Result);
// TODO: Allow plugins to intercept recipes, add a post-craft hook here
}

View File

@ -14,6 +14,90 @@
class cCraftingGrid // tolua_export
{ // tolua_export
public:
cCraftingGrid(const cCraftingGrid & a_Original);
cCraftingGrid(int a_Width, int a_Height); // tolua_export
cCraftingGrid(cItem * a_Items, int a_Width, int a_Height);
~cCraftingGrid();
// tolua_begin
int GetWidth (void) const {return m_Width; }
int GetHeight(void) const {return m_Height; }
cItem & GetItem (int x, int y) const;
void SetItem (int x, int y, ENUM_ITEM_ID a_ItemType, short a_ItemHealth, int a_ItemCount);
void SetItem (int x, int y, const cItem & a_Item);
void Clear (void);
/// Removes items in a_Grid from m_Items[] (used by cCraftingRecipe::ConsumeIngredients())
void ConsumeGrid(const cCraftingGrid & a_Grid);
/// Dumps the entire crafting grid using LOGD()
void Dump(void);
// tolua_end
cItem * GetItems(void) const {return m_Items; }
/// Copies internal contents into the item array specified. Assumes that the array has the same dimensions as self
void CopyToItems(cItem * a_Items) const;
protected:
int m_Width;
int m_Height;
cItem * m_Items;
} ; // tolua_export
class cCraftingRecipe // tolua_export
{ // tolua_export
public:
cCraftingRecipe(const cCraftingGrid & a_CraftingGrid);
// tolua_begin
void Clear (void);
int GetIngredientsWidth (void) const {return m_Ingredients.GetWidth(); }
int GetIngredientsHeight(void) const {return m_Ingredients.GetHeight(); }
cItem & GetIngredient (int x, int y) const {return m_Ingredients.GetItem(x, y); }
const cItem & GetResult (void) const {return m_Result; }
void SetResult (ENUM_ITEM_ID a_ItemType, short a_ItemHealth, int a_ItemCount);
void SetResult (const cItem & a_Item)
{
m_Result = a_Item;
}
void SetIngredient (int x, int y, ENUM_ITEM_ID a_ItemType, short a_ItemHealth, int a_ItemCount)
{
m_Ingredients.SetItem(x, y, a_ItemType, a_ItemHealth, a_ItemCount);
}
void SetIngredient (int x, int y, const cItem & a_Item)
{
m_Ingredients.SetItem(x, y, a_Item);
}
/// Consumes ingredients from the crafting grid specified
void ConsumeIngredients(cCraftingGrid & a_CraftingGrid);
/// Dumps the entire recipe using LOGD()
void Dump(void);
// tolua_end
protected:
cCraftingGrid m_Ingredients; // Adjusted to correspond to the input crafting grid!
cItem m_Result;
} ; // tolua_export
class cCraftingRecipes
{
public:
@ -23,11 +107,8 @@ public:
cCraftingRecipes(void);
~cCraftingRecipes();
/// Offers an item resulting from the crafting grid setup. Doesn't modify the grid
cItem Offer(const cItem * a_CraftingGrid, int a_GridWidth, int a_GridHeight);
/// Crafts the item resulting from the crafting grid setup. Modifies the grid, returns the crafted item
cItem Craft(cItem * a_CraftingGrid, int a_GridWidth, int a_GridHeight);
/// Returns the recipe for current crafting grid. Doesn't modify the grid. Clears a_Recipe if no recipe found.
void GetRecipe(const cCraftingGrid & a_CraftingGrid, cCraftingRecipe & a_Recipe);
protected:
@ -38,7 +119,9 @@ protected:
} ;
typedef std::vector<cRecipeSlot> cRecipeSlots;
// A single recipe, stored. Each recipe is normalized right after parsing (NormalizeIngredients())
/** A single recipe, stored. Each recipe is normalized right after parsing (NormalizeIngredients())
A normalized recipe starts at (0,0)
*/
struct cRecipe
{
cRecipeSlots m_Ingredients;

View File

@ -3,7 +3,6 @@
#include "cCraftingWindow.h"
#include "cItem.h"
#include "cRecipeChecker.h"
#include "CraftingRecipes.h"
#include "cPlayer.h"
#include "cClientHandle.h"
@ -71,34 +70,24 @@ void cCraftingWindow::Clicked( cPacket_WindowClick* a_ClickPacket, cPlayer & a_P
if ((a_ClickPacket->m_SlotNum >= 0) && (a_ClickPacket->m_SlotNum < 10))
{
cItem CookedItem;
cCraftingGrid Grid(GetSlots() + 1, 3, 3);
cCraftingRecipe Recipe(Grid);
cRoot::Get()->GetCraftingRecipes()->GetRecipe(Grid, Recipe);
if ((a_ClickPacket->m_SlotNum == 0) && !bDontCook)
{
// Consume the ingredients from the crafting grid:
CookedItem = cRoot::Get()->GetCraftingRecipes()->Craft(GetSlots() + 1, 3, 3);
LOGD("New recipes crafted: %i x %i", CookedItem.m_ItemID, CookedItem.m_ItemCount);
// Upgrade the crafting result from the new crafting grid contents:
CookedItem = cRoot::Get()->GetCraftingRecipes()->Offer(GetSlots() + 1, 3, 3);
if (CookedItem.IsEmpty())
{
// Fallback to the old recipes:
CookedItem = cRoot::Get()->GetRecipeChecker()->CookIngredients( GetSlots()+1, 3, 3, true );
LOGD("Old recipes crafted: %i x %i", CookedItem.m_ItemID, CookedItem.m_ItemCount );
}
// Consume the items from the crafting grid:
Recipe.ConsumeIngredients(Grid);
// Propagate grid back to m_Slots:
Grid.CopyToItems(GetSlots() + 1);
// Get the recipe for the new grid contents:
cRoot::Get()->GetCraftingRecipes()->GetRecipe(Grid, Recipe);
}
else
{
CookedItem = cRoot::Get()->GetCraftingRecipes()->Offer(GetSlots() + 1, 3, 3);
LOGD("New recipes offer: %i x %i", CookedItem.m_ItemID, CookedItem.m_ItemCount );
if (CookedItem.IsEmpty())
{
// Fallback to the old recipes
CookedItem = cRoot::Get()->GetRecipeChecker()->CookIngredients( GetSlots()+1, 3, 3 );
LOGD("Old recipes offer: %i x %i", CookedItem.m_ItemID, CookedItem.m_ItemCount );
}
}
*GetSlot(0) = CookedItem;
LOG("You cooked: %i x %i !!", GetSlot(0)->m_ItemID, GetSlot(0)->m_ItemCount );
*GetSlot(0) = Recipe.GetResult();
LOGD("You cooked: %i x %i !!", GetSlot(0)->m_ItemID, GetSlot(0)->m_ItemCount );
}
SendWholeWindow( a_Player.GetClientHandle() );
a_Player.GetInventory().SendWholeInventory( a_Player.GetClientHandle() );

View File

@ -6,7 +6,6 @@
#include "cClientHandle.h"
#include "cWindow.h"
#include "cItem.h"
#include "cRecipeChecker.h"
#include "cRoot.h"
#include <json/json.h>

View File

@ -6,7 +6,6 @@
#include "cClientHandle.h"
#include "cWindow.h"
#include "cItem.h"
#include "cRecipeChecker.h"
#include "cRoot.h"
#include <json/json.h>
@ -27,6 +26,10 @@ cInventory::~cInventory()
CloseWindow();
}
cInventory::cInventory(cPlayer* a_Owner)
{
m_Owner = a_Owner;
@ -52,6 +55,10 @@ cInventory::cInventory(cPlayer* a_Owner)
}
}
bool cInventory::AddItem( cItem & a_Item )
{
cItem BackupSlots[c_NumSlots];
@ -84,6 +91,10 @@ bool cInventory::AddItem( cItem & a_Item )
return (a_Item.m_ItemCount == 0);
}
// TODO: Right now if you dont have enough items, the items you did have are removed, and the function returns false anyway
bool cInventory::RemoveItem( cItem & a_Item )
{
@ -138,13 +149,21 @@ bool cInventory::RemoveItem( cItem & a_Item )
return false;
}
void cInventory::Clear()
{
for(unsigned int i = 0; i < c_NumSlots; i++)
m_Slots[i].Empty();
}
cItem* cInventory::GetSlotsForType( int a_Type )
cItem * cInventory::GetSlotsForType( int a_Type )
{
switch( a_Type )
{
@ -158,19 +177,26 @@ cItem* cInventory::GetSlotsForType( int a_Type )
return 0;
}
int cInventory::GetSlotCountForType( int a_Type )
{
switch( a_Type )
switch (a_Type)
{
case -1:
return 36;
case -2:
case -3:
return 4;
case -1:
return 36;
case -2:
case -3:
return 4;
}
return 0;
}
cItem* cInventory::GetSlot( int a_SlotNum )
{
@ -178,18 +204,33 @@ cItem* cInventory::GetSlot( int a_SlotNum )
return &m_Slots[a_SlotNum];
}
cItem* cInventory::GetFromHotBar( int a_SlotNum )
{
if( a_SlotNum < 0 || a_SlotNum >= 9 ) return 0;
if ((a_SlotNum < 0) || (a_SlotNum >= 9))
{
return NULL;
}
return &m_HotSlots[a_SlotNum];
}
void cInventory::SetEquippedSlot( int a_SlotNum )
{
if( a_SlotNum < 0 || a_SlotNum >= 9 ) m_EquippedSlot = 0;
else m_EquippedSlot = (short)a_SlotNum;
}
cItem & cInventory::GetEquippedItem()
{
cItem* Item = GetFromHotBar( m_EquippedSlot );
@ -205,12 +246,20 @@ cItem & cInventory::GetEquippedItem()
return *m_EquippedItem;
}
void cInventory::SendWholeInventory( cClientHandle* a_Client )
{
cPacket_WholeInventory Inventory( this );
a_Client->Send( Inventory );
}
void cInventory::SendSlot( int a_SlotNum )
{
cItem* Item = GetSlot( a_SlotNum );
@ -226,6 +275,10 @@ void cInventory::SendSlot( int a_SlotNum )
}
}
bool cInventory::AddToBar( cItem & a_Item, const int a_Offset, const int a_Size, bool* a_bChangedSlots, int a_Mode /* = 0 */ )
{
// Fill already present stacks
@ -273,6 +326,10 @@ bool cInventory::AddToBar( cItem & a_Item, const int a_Offset, const int a_Size,
return true;
}
void cInventory::SaveToJson(Json::Value & a_Value)
{
for(unsigned int i = 0; i < c_NumSlots; i++)
@ -283,6 +340,10 @@ void cInventory::SaveToJson(Json::Value & a_Value)
}
}
bool cInventory::LoadFromJson(Json::Value & a_Value)
{
int SlotIdx = 0;
@ -293,3 +354,7 @@ bool cInventory::LoadFromJson(Json::Value & a_Value)
}
return true;
}

View File

@ -12,34 +12,41 @@ namespace Json
class cItem //tolua_export
{ //tolua_export
// tolua_begin
class cItem
{
public:
cItem( ENUM_ITEM_ID a_ItemID = E_ITEM_EMPTY, char a_ItemCount = 0, short a_ItemHealth = 0 ) //tolua_export
cItem( ENUM_ITEM_ID a_ItemID = E_ITEM_EMPTY, char a_ItemCount = 0, short a_ItemHealth = 0 )
: m_ItemID ( a_ItemID )
, m_ItemCount ( a_ItemCount )
, m_ItemHealth ( a_ItemHealth )
{ //tolua_export
{
if(!IsValidItem( m_ItemID ) ) m_ItemID = E_ITEM_EMPTY;
} //tolua_export
void Empty() //tolua_export
{ //tolua_export
}
void Empty()
{
m_ItemID = E_ITEM_EMPTY;
m_ItemCount = 0;
m_ItemHealth = 0;
} //tolua_export
bool IsEmpty(void) const //tolua_export
{ //tolua_export
}
void Clear(void)
{
m_ItemID = E_ITEM_EMPTY;
m_ItemCount = 0;
m_ItemHealth = 0;
}
bool IsEmpty(void) const
{
return (m_ItemID <= 0 || m_ItemCount <= 0);
} //tolua_export
bool Equals( cItem & a_Item ) const //tolua_export
{ //tolua_export
}
bool Equals( cItem & a_Item ) const
{
return ( (m_ItemID == a_Item.m_ItemID) && (m_ItemHealth == a_Item.m_ItemHealth) );
} //tolua_export
}
//TODO Sorry for writing the functions in the header. But somehow it doesn´t worked when I put them into the cpp File :s
// TODO Sorry for writing the functions in the header. But somehow it doesn´t worked when I put them into the cpp File :s
inline int GetMaxDuration()
inline int GetMaxDuration(void) const
{
switch(m_ItemID)
{
@ -74,31 +81,31 @@ public:
}
}
//Damages a weapon. Returns true when destroyed
inline bool DamageItem() {
if(HasDuration())
// Damages a weapon / tool. Returns true when destroyed
inline bool DamageItem()
{
if (HasDuration())
{
m_ItemHealth++;
if(m_ItemHealth >= GetMaxDuration())
return true;
}
return false;
}
inline bool HasDuration() { return GetMaxDuration() > 0; }
void GetJson( Json::Value & a_OutValue ) const; //tolua_export
void FromJson( const Json::Value & a_Value ); //tolua_export
void GetJson( Json::Value & a_OutValue ) const;
void FromJson( const Json::Value & a_Value );
static bool IsEnchantable(ENUM_ITEM_ID item);
ENUM_ITEM_ID m_ItemID; //tolua_export
char m_ItemCount; //tolua_export
short m_ItemHealth; //tolua_export
ENUM_ITEM_ID m_ItemID;
char m_ItemCount;
short m_ItemHealth;
}; //tolua_export
};
// tolua_end
typedef std::vector<cItem> cItems;

View File

@ -1,467 +0,0 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "cRecipeChecker.h"
#include <fstream>
#include <sstream>
#ifndef _WIN32
#include <cstdlib>
#endif
#include "Defines.h"
#include "cRoot.h"
typedef std::list< cRecipeChecker::Recipe* > RecipeList;
struct cRecipeChecker::sRecipeCheckerState
{
RecipeList Recipes;
};
cRecipeChecker* cRecipeChecker::GetRecipeChecker()
{
LOGWARN("WARNING: Using deprecated function cRecipeChecker::GetRecipeChecker() use cRoot::Get()->GetRecipeChecker() instead!");
return cRoot::Get()->GetRecipeChecker();
}
cRecipeChecker::Recipe::~Recipe()
{
delete [] Slots;
Slots = 0;
}
cRecipeChecker::~cRecipeChecker()
{
ClearRecipes();
delete m_pState;
}
cRecipeChecker::cRecipeChecker()
: m_pState( new sRecipeCheckerState )
{
ReloadRecipes();
}
void cRecipeChecker::ClearRecipes()
{
while( m_pState->Recipes.size() > 0 )
{
delete *m_pState->Recipes.begin();
m_pState->Recipes.remove( *m_pState->Recipes.begin() );
}
}
void PrintRecipe( std::vector< cRecipeChecker::RecipeSlot > & RecipeSlots )
{
LOG("Recipe:");
for(unsigned int i = 0; i < RecipeSlots.size(); i++)
{
cRecipeChecker::RecipeSlot Slot = RecipeSlots[i];
LOG("x:%i y:%i id:%i #%i", Slot.x, Slot.y, Slot.Item.m_ItemID, Slot.Item.m_ItemCount );
}
}
void PrintNear( std::ifstream & f, int a_History = 64 )
{
f.clear();
// Calculate how far we can move pointer back
std::streamoff Position = f.tellg();
f.seekg( 0, std::ios_base::beg );
std::streamoff Difference = Position - f.tellg();
if( Difference > a_History ) Difference = a_History;
f.seekg( Position - Difference, std::ios_base::beg );
std::string Near;
if( f.good() )
{
while( f.good() && Near.size() < (unsigned int)Difference )
{
char c;
f.get(c);
Near.push_back( c );
}
}
LOGERROR("Error near: \"%s\"", Near.c_str() );
}
void cRecipeChecker::ReloadRecipes()
{
LOG("-- Loading recipes from recipes.txt --");
ClearRecipes();
std::ifstream f;
char a_File[] = "recipes.txt";
f.open(a_File, std::ios::in);
std::string input;
if( !f.good() )
{
f.close();
LOG("Could not open file for recipes: %s", a_File);
return;
}
std::vector< RecipeSlot > RecipeSlots;
bool bError = false;
while( f.good() )
{
bool bLoadSlot = false;
bool bLoadResult = false;
char c;
f >> c;
f.unget();
if( c == '#' )
{
//LOG("Ignoring comment");
while( f.good() && c != '\n' )
{
f.get( c );
}
continue;
}
f.get( c );
while( f.good() && ( c == '\n' || c == '\r' ) ) { f.get( c ); }
if( f.eof() ) break;
f.unget();
int width, height;
f >> width;
f >> c; if( c != 'x' ) { bError=true; break; }
f >> height;
f >> c;
if( c == ',' ) bLoadSlot = true;
while( f.good() && bLoadSlot )
{
bool bDontAddRecipe = false;
int x, y, ItemID, Amount;
if( f.peek() == '*' )
{
f >> c;
x = -1;
}
else
{
f >> x;
}
f >> c; if( c != ':' ) { bError=true; break; }
if( f.peek() == '*' )
{
f >> c;
y = -1;
}
else
{
f >> y;
}
f >> c; if( c != ':' ) { bError=true; break; }
f >> ItemID;
f >> c; if( c != ':' ) { bError=true; break; }
f >> Amount;
f >> c;
if( c == '@' ) bLoadResult = true;
if( c != ',' ) bLoadSlot = false;
if( !IsValidItem( ItemID ) )
{
LOGERROR("Error in recipes file (%s): Invalid Item ID %i", a_File, ItemID );
bDontAddRecipe = true;
}
if( x < 0 && y < 0 )
{
if( Amount < 0 )
{
LOGERROR("Error in recipes file (%s): Invalid use of negative amount on wildcard coordinates", a_File );
bDontAddRecipe = true;
}
for(int x = 0; x < width; ++x) for(int y = 0; y < height; ++y )
{
cItem Item( (ENUM_ITEM_ID)ItemID, (char)Amount );
RecipeSlot Slot;
Slot.Item = Item;
Slot.x = x;
Slot.y = y;
RecipeSlots.push_back( Slot );
}
}
else if( x < 0 )
{
if( Amount < 0 )
{
for(int x = 0; x < width; ++x) for(int yy = 0; yy < height; ++yy )
{
if( yy == y-1 ) continue;
cItem Item( (ENUM_ITEM_ID)ItemID, (char)abs(Amount) );
RecipeSlot Slot;
Slot.Item = Item;
Slot.x = x;
Slot.y = yy;
RecipeSlots.push_back( Slot );
}
}
else
{
for(int x = 0; x < width; ++x)
{
cItem Item( (ENUM_ITEM_ID)ItemID, (char)Amount );
RecipeSlot Slot;
Slot.Item = Item;
Slot.x = x;
Slot.y = y-1;
RecipeSlots.push_back( Slot );
}
}
}
else if( y < 0 )
{
if( Amount < 0 )
{
for(int xx = 0; xx < width; ++xx) for(int y = 0; y < height; ++y )
{
if( xx == x-1 ) continue;
cItem Item( (ENUM_ITEM_ID)ItemID, (char)abs(Amount) );
RecipeSlot Slot;
Slot.Item = Item;
Slot.x = xx;
Slot.y = y;
RecipeSlots.push_back( Slot );
}
}
else
{
for(int y = 0; y < height; ++y)
{
cItem Item( (ENUM_ITEM_ID)ItemID, (char)Amount );
RecipeSlot Slot;
Slot.Item = Item;
Slot.x = x-1;
Slot.y = y;
RecipeSlots.push_back( Slot );
}
}
}
else
{
if( Amount < 0 )
{
for(int xx = 0; xx < width; ++xx) for(int yy = 0; yy < height; ++yy )
{
if( xx == x-1 && yy == y-1 ) continue;
cItem Item( (ENUM_ITEM_ID)ItemID, (char)abs(Amount) );
RecipeSlot Slot;
Slot.Item = Item;
Slot.x = xx;
Slot.y = yy;
RecipeSlots.push_back( Slot );
}
}
else
{
cItem Item( (ENUM_ITEM_ID)ItemID, (char)Amount );
RecipeSlot Slot;
Slot.Item = Item;
Slot.x = x-1;
Slot.y = y-1;
RecipeSlots.push_back( Slot );
}
}
//LOG("%i %i %i %i", x, y, ItemID, Amount );
if( bLoadResult )
{
bLoadResult = false;
f >> ItemID;
f >> c; if( c != ':' ) { bError=true; break; }
f >> Amount;
//LOG("%i %i", ItemID, Amount );
if( !IsValidItem( ItemID ) )
{
LOGERROR("Error in recipes file (%s): Invalid Item ID %i", a_File, ItemID );
bDontAddRecipe = true;
}
// Do a sanity check - Handshake algorithm :)
bool bDuplicateEntries = false;
for(unsigned int i = 0; i < RecipeSlots.size(); i++)
{
for(unsigned int j = i+1; j < RecipeSlots.size(); j++)
{
if( RecipeSlots[i].x == RecipeSlots[j].x && RecipeSlots[i].y == RecipeSlots[j].y )
{
LOGERROR("Error in recipes file (%s): Duplicate item on coordinates %i:%i", a_File, RecipeSlots[i].x+1, RecipeSlots[i].y+1 );
bDontAddRecipe = true;
bDuplicateEntries = true;
break;
}
}
}
if( bDuplicateEntries )
{
PrintNear( f, 64 );
PrintRecipe( RecipeSlots );
}
if( bDontAddRecipe == false )
{
cItem Item( (ENUM_ITEM_ID)ItemID, (char)Amount );
Recipe* recipe = new Recipe;
recipe->Result = Item;
recipe->NumItems = RecipeSlots.size();
recipe->Slots = new RecipeSlot[ recipe->NumItems ];
memcpy( recipe->Slots, &RecipeSlots[0], sizeof(RecipeSlot)*recipe->NumItems );
m_pState->Recipes.push_back( recipe );
//LOG("Loaded recipe for %i times %i", Amount, ItemID );
}
RecipeSlots.clear();
}
}
if( bError ) break;
}
if( bError || ( !f.eof() && !f.good() ) )
{
LOGERROR("Error: Wrong format");
PrintNear( f, 128 );
}
f.close();
LOG("-- Done loading recipes, found %i recipes --", m_pState->Recipes.size() );
}
cItem cRecipeChecker::CookIngredients( cItem* a_Items, int a_Width, int a_Height, bool a_bConsumeIngredients /* = false */ )
{
int iLeft = 999, iTop = 999;
int iRight = 0, iBottom = 0;
for(int y = 0; y < a_Height; y++ ) for(int x = 0; x < a_Width; x++)
{
cItem Item = a_Items[x + y*a_Width];
if( Item.m_ItemID != E_ITEM_EMPTY && Item.m_ItemCount > 0 )
{
iRight = MAX(x, iRight);
iBottom = MAX(y, iBottom);
iLeft = MIN(x, iLeft);
iTop = MIN(y, iTop);
}
}
for(RecipeList::iterator itr = m_pState->Recipes.begin(); itr != m_pState->Recipes.end(); ++itr )
{
Recipe* recipe = (*itr);
int Left = 999, Top = 999;
int Right = 0, Bottom = 0;
for(unsigned int i = 0; i < recipe->NumItems; i++)
{
Right = MAX(recipe->Slots[i].x, Right);
Bottom = MAX(recipe->Slots[i].y, Bottom);
Left = MIN(recipe->Slots[i].x, Left);
Top = MIN(recipe->Slots[i].y, Top);
}
if( Right-Left != iRight-iLeft || Bottom-Top != iBottom-iTop ) continue;
// it has the right dimensions
// Check for empty spaces
unsigned int Hash = 0;
for(unsigned int i = 0; i < recipe->NumItems; i++)
{
int x = recipe->Slots[i].x - Left + iLeft +1;
int y = recipe->Slots[i].y - Top + iTop +1;
Hash += x + y * a_Width;
}
for(int y = 0; y < a_Height; y++ ) for(int x = 0; x < a_Width; x++)
{
cItem & Item = a_Items[x + y*a_Width];
if( Item.m_ItemID != E_ITEM_EMPTY && Item.m_ItemCount > 0 )
{
Hash -= (x+1) + (y+1)*a_Width;
}
}
if( Hash != 0 ) continue; // Empty spaces not in right place
bool bWrong = false;
for(unsigned int i = 0; i < recipe->NumItems; i++)
{
int x = recipe->Slots[i].x - Left + iLeft;
int y = recipe->Slots[i].y - Top + iTop;
cItem Item = a_Items[x + y*a_Width];
if( Item.m_ItemID != recipe->Slots[i].Item.m_ItemID
|| Item.m_ItemCount < recipe->Slots[i].Item.m_ItemCount )
{
bWrong = true;
break;
}
}
if( bWrong ) continue;
cItem Dish = recipe->Result;
// else
if( a_bConsumeIngredients )
{
// Consume! nomnom~
for(unsigned int i = 0; i < recipe->NumItems; i++)
{
int x = recipe->Slots[i].x - Left + iLeft;
int y = recipe->Slots[i].y - Top + iTop;
a_Items[x + y*a_Width].m_ItemCount -= recipe->Slots[i].Item.m_ItemCount;
if( a_Items[x + y*a_Width].m_ItemCount <= 0 ) a_Items[x + y*a_Width].Empty();
}
Dish = CookIngredients( a_Items, a_Width, a_Height, false );
}
// Return the resulting dish!
return Dish;
}
return cItem();
}

View File

@ -1,39 +0,0 @@
#pragma once
#include "cItem.h"
class cRecipeChecker
{
public:
static cRecipeChecker * GetRecipeChecker();
// Grid of cItems of a_Width width and a_Height Height
cItem CookIngredients( cItem* a_Items, int a_Width, int a_Height, bool a_bConsumeIngredients = false );
struct RecipeSlot
{
cItem Item;
int x, y;
};
struct Recipe
{
Recipe() : Slots( 0 ), NumItems( 0 ) {}
~Recipe();
RecipeSlot* Slots; // Array of RecipeSlots
unsigned int NumItems;
cItem Result;
};
void ReloadRecipes();
static void DeleteMe();
private:
friend class cRoot;
cRecipeChecker();
~cRecipeChecker();
struct sRecipeCheckerState;
sRecipeCheckerState* m_pState;
void ClearRecipes();
};

View File

@ -7,7 +7,6 @@
#include "cWebAdmin.h"
#include "cFurnaceRecipe.h"
#include "cGroupManager.h"
#include "cRecipeChecker.h"
#include "CraftingRecipes.h"
#include "cPluginManager.h"
#include "cMonsterConfig.h"
@ -41,7 +40,6 @@ cRoot::cRoot()
: m_Server( 0 )
, m_MonsterConfig( 0 )
, m_GroupManager( 0 )
, m_RecipeChecker(NULL)
, m_CraftingRecipes(NULL)
, m_FurnaceRecipe( 0 )
, m_WebAdmin( 0 )
@ -125,7 +123,6 @@ void cRoot::Start()
LOG("Loading settings...");
m_GroupManager = new cGroupManager();
m_RecipeChecker = new cRecipeChecker();
m_CraftingRecipes = new cCraftingRecipes;
m_FurnaceRecipe = new cFurnaceRecipe();
@ -175,7 +172,6 @@ void cRoot::Start()
delete m_WebAdmin; m_WebAdmin = 0;
LOG("Unloading recipes...");
delete m_FurnaceRecipe; m_FurnaceRecipe = NULL;
delete m_RecipeChecker; m_RecipeChecker = NULL;
delete m_CraftingRecipes; m_CraftingRecipes = NULL;
LOG("Forgetting groups...");
delete m_GroupManager; m_GroupManager = 0;

View File

@ -13,7 +13,6 @@
class cThread;
class cMonsterConfig;
class cGroupManager;
class cRecipeChecker;
class cCraftingRecipes;
class cFurnaceRecipe;
class cWebAdmin;
@ -48,7 +47,6 @@ public:
cMonsterConfig * GetMonsterConfig() { return m_MonsterConfig; }
cGroupManager * GetGroupManager (void) { return m_GroupManager; } // tolua_export
cRecipeChecker * GetRecipeChecker (void) { return m_RecipeChecker; } // tolua_export
cCraftingRecipes * GetCraftingRecipes(void) { return m_CraftingRecipes; } // tolua_export
cFurnaceRecipe * GetFurnaceRecipe (void) { return m_FurnaceRecipe; } // tolua_export
cWebAdmin * GetWebAdmin (void) { return m_WebAdmin; } // tolua_export
@ -86,7 +84,6 @@ private:
cMonsterConfig * m_MonsterConfig;
cGroupManager * m_GroupManager;
cRecipeChecker * m_RecipeChecker;
cCraftingRecipes * m_CraftingRecipes;
cFurnaceRecipe * m_FurnaceRecipe;
cWebAdmin * m_WebAdmin;

View File

@ -18,7 +18,6 @@
#include "cPlayer.h"
#include "cInventory.h"
#include "cItem.h"
#include "cRecipeChecker.h"
#include "cFurnaceRecipe.h"
#include "cTracer.h"
#include "cWebAdmin.h"

View File

@ -6,7 +6,6 @@
#include "cClientHandle.h"
#include "cWindow.h"
#include "cItem.h"
#include "cRecipeChecker.h"
#include "CraftingRecipes.h"
#include "cRoot.h"
#include "packets/cPacket_WindowClick.h"
@ -72,30 +71,24 @@ void cSurvivalInventory::Clicked( cPacket* a_ClickPacket )
if ((Packet->m_SlotNum >= (short)c_CraftOffset) && (Packet->m_SlotNum < (short)(c_CraftOffset + c_CraftSlots + 1)))
{
cItem CookedItem;
cCraftingGrid Grid(m_Slots + c_CraftOffset + 1, 2, 2);
cCraftingRecipe Recipe(Grid);
cRoot::Get()->GetCraftingRecipes()->GetRecipe(Grid, Recipe);
if ((Packet->m_SlotNum == 0) && !bDontCook)
{
// Consume the items from the crafting grid:
CookedItem = cRoot::Get()->GetCraftingRecipes()->Craft(m_Slots + c_CraftOffset + 1, 2, 2);
// Upgrade the crafting result from the new crafting grid contents:
CookedItem = cRoot::Get()->GetCraftingRecipes()->Offer(m_Slots + c_CraftOffset + 1, 2, 2);
if (CookedItem.IsEmpty())
{
// Fallback to the old recipes:
CookedItem = cRoot::Get()->GetRecipeChecker()->CookIngredients( m_Slots+c_CraftOffset+1, 2, 2, true );
}
Recipe.ConsumeIngredients(Grid);
// Propagate grid back to m_Slots:
Grid.CopyToItems(m_Slots + c_CraftOffset + 1);
// Get the recipe for the new grid contents:
cRoot::Get()->GetCraftingRecipes()->GetRecipe(Grid, Recipe);
}
else
{
CookedItem = cRoot::Get()->GetCraftingRecipes()->Offer(m_Slots + c_CraftOffset + 1, 2, 2);
if (CookedItem.IsEmpty())
{
// Fallback to the old recipes:
CookedItem = cRoot::Get()->GetRecipeChecker()->CookIngredients( m_Slots+c_CraftOffset+1, 2, 2 );
}
}
m_Slots[c_CraftOffset] = CookedItem;
LOG("You cooked: %i x %i !!", m_Slots[c_CraftOffset].m_ItemID, m_Slots[c_CraftOffset].m_ItemCount );
m_Slots[c_CraftOffset] = Recipe.GetResult();
LOGD("You cooked: %i x %i !!", m_Slots[c_CraftOffset].m_ItemID, m_Slots[c_CraftOffset].m_ItemCount );
SendWholeInventory( m_Owner->GetClientHandle() );
}
SendSlot( 0 );