From 97eda34a9437abe732cf6b60711828bbe4f0cb2e Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sun, 16 Jun 2013 20:24:07 +0000 Subject: Rewritten furnaces Furnaces now smelt the correct number of items. Furnaces store their contents in a cItemGrid. Furnace window is updated with correct items and progressbars. Furnace recipes now use ticks instead of milliseconds. Furnaces save and load their state completely, not missing a smelt operation. Hoppers take items out of furnaces. Dropped the cSlotAreaDropSpenser class, replaced it with generic cSlotAreaItemGrid git-svn-id: http://mc-server.googlecode.com/svn/trunk@1601 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- MCServer/furnace.txt | 101 +++--- source/AllToLua.pkg | 1 + source/Bindings.cpp | 507 ++++++++++++++++++++++++++-- source/Bindings.h | 2 +- source/BlockEntities/ChestEntity.cpp | 4 +- source/BlockEntities/FurnaceEntity.cpp | 514 +++++++++++++++++------------ source/BlockEntities/FurnaceEntity.h | 128 +++++-- source/BlockEntities/HopperEntity.cpp | 24 +- source/FurnaceRecipe.cpp | 64 ++-- source/FurnaceRecipe.h | 26 +- source/UI/SlotArea.cpp | 61 ++-- source/UI/SlotArea.h | 27 +- source/UI/Window.cpp | 3 +- source/WorldStorage/NBTChunkSerializer.cpp | 14 +- source/WorldStorage/NBTChunkSerializer.h | 2 +- source/WorldStorage/WSSAnvil.cpp | 6 +- 16 files changed, 1072 insertions(+), 412 deletions(-) diff --git a/MCServer/furnace.txt b/MCServer/furnace.txt index 2ca4f441e..b25c79ab7 100644 --- a/MCServer/furnace.txt +++ b/MCServer/furnace.txt @@ -1,70 +1,75 @@ -#************************** -# Default Furnace Recipes # -#*************************# +#*****************# +# Furnace Recipes # +#*****************# # # #******************************************************# # Basic Notation Help -#******************************************************# # -# **** Item Definition **** -# An Item is defined by an Item ID, an amount (and health) -# The health is optional, and if not specified it's -# assumed to be 0 +# **** Item Definition **** +# An Item is defined by an Item Type, an amount (and damage) +# The damage is optional, and if not specified it's assumed to be 0 # # -Cactus Green: -# 351 : 1 ( : 2 ) -# ItemID : Amount ( : Health ) +# 351 : 1 ( : 2 ) +# ItemType : Amount ( : Damage ) +# # +# **** Recipe and result **** # -# **** Recipe and result **** +# 4:1@200=1:1 -> Produces 1 smooth stone from 1 cobblestone in 200 ticks (10 seconds) # -# 4:1@10000=1:1 -> Produces 1 smooth stone from -# 1 cobblestone in 10 second +# 4 : 1 @ 200 = 1 : 1 +# ItemType : Amount @ ticks = ItemID : Amount # -# 4 : 1 @ 10000 = 1 : 1 -# ItemID : Amount @ milliseconds = ItemID : Amount # -# **** Burnable Materials / Fuel **** +# **** Fuel **** # -# !17:1=15000 -> 1 Wood burns for 15000 milliseconds -# (15 s) +# !17:1 = 300 -> 1 Wood burns for 300 ticks (15 s) # -# ! 17 : 1 = 15000 -# Fuel ItemID : Amount = milliseconds +# ! 17 : 1 = 300 +# Fuel ItemType : Amount = ticks # #******************************************************# + + + + #-------------------------- -# Let's get cookin' :D +# Smelting recipes + +4:1 @ 200 = 1:1 # 1 Cobblestone -> 1 Rock +15:1 @ 200 = 265:1 # 1 Iron Ore -> 1 Iron Ingot +14:1 @ 200 = 266:1 # 1 Gold Ore -> 1 Gold Ingot +153:1 @ 200 = 406:1 # 1 Quartz Ore -> 1 Quartz +12:1 @ 200 = 20:1 # 1 Sand -> 1 Glass +319:1 @ 200 = 320:1 # 1 Raw Pork -> 1 Cooked Pork +363:1 @ 200 = 364:1 # 1 Raw Beef -> 1 Cooked Beef (steak) +365:1 @ 200 = 366:1 # 1 Raw Chicken -> 1 Cooked Chicken +337:1 @ 200 = 336:1 # 1 Clay -> 1 Clay Brick +87:1 @ 200 = 405:1 # 1 NetherRack -> 1 NetherBrick +349:1 @ 200 = 350:1 # 1 Raw Fish -> 1 Cooked Fish +17:1 @ 200 = 263:1:1 # 1 Log -> 1 Charcoal +81:1 @ 200 = 351:1:2 # 1 Cactus -> 1 Green Dye + + + -4:1 @10000=1:1 #-> 1 Cobblestone -> 1 Rock -15:1 @10000=265:1 #-> 1 Iron Ore -> 1 Iron Ingot -14:1 @10000=266:1 #-> 1 Gold Ore -> 1 Gold Ingot -153:1 @10000=406:1 #-> 1 Quartz Ore -> 1 Quartz -12:1 @10000=20:1 #-> 1 Sand -> 1 Glass -319:1@10000=320:1 #-> 1 Raw Pork -> 1 Cooked Pork -363:1@10000=364:1 #-> 1 Raw Beef -> 1 Cooked Beef (steak) -365:1@10000=366:1 #-> 1 Raw Chicken -> 1 Cooked Chicken -337:1@10000=336:1 #-> 1 Clay -> 1 Clay Brick -87:1@10000=405:1 #-> 1 NetherRack -> 1 NetherBrick -349:1@10000=350:1 #-> 1 Raw Fish -> 1 Cooked Fish -17:1 @10000=263:1 #-> 1 Wood -> 1 Charcoal -81:1 @10000=351:1:2 #-> 1 Cactus -> 1 Dye #-------------------------- -# Burn baby! Buuurn! +# Fuels -!263:1 = 80000 #-> 1 Charcoal -> 80 sec -!42:126:1 = 7500 #-> 1 halfslab -> 7.5 seconds -!5:1 = 15000 #-> 1 Planks -> 15 sec -!280:1 = 5000 #-> 1 Stick -> 5 sec -!85:1 = 15000 #-> 1 Fence -> 15 sec -!53:1 = 15000 #-> 1 Wooden Stairs -> 15 sec -!58:1 = 15000 #-> 1 Crafting Table -> 15 sec -!47:1 = 15000 #-> 1 Bookshelf -> 15 sec -!54:1 = 15000 #-> 1 Chest -> 15 sec -!84:1 = 15000 #-> 1 Jukebox -> 15 sec -!327:1 = 1000000 #-> 1 Lava Bucket -> 1000 sec -!17:1 = 15000 #-> 1 Wood -> 15 sec -!6:1 = 5000 #-> 1 Sapling -> 5 sec \ No newline at end of file +! 263:1 = 1600 # 1 Charcoal -> 80 sec +! 42:126:1 = 150 # 1 Halfslab -> 7.5 seconds +! 5:1 = 300 # 1 Planks -> 15 sec +! 280:1 = 100 # 1 Stick -> 5 sec +! 85:1 = 300 # 1 Fence -> 15 sec +! 53:1 = 300 # 1 Wooden Stairs -> 15 sec +! 58:1 = 300 # 1 Crafting Table -> 15 sec +! 47:1 = 300 # 1 Bookshelf -> 15 sec +! 54:1 = 300 # 1 Chest -> 15 sec +! 84:1 = 300 # 1 Jukebox -> 15 sec +! 327:1 = 200000 # 1 Lava Bucket -> 1000 sec +! 17:1 = 300 # 1 Wood -> 15 sec +! 6:1 = 100 # 1 Sapling -> 5 sec diff --git a/source/AllToLua.pkg b/source/AllToLua.pkg index f36443329..9e6f8cf8b 100644 --- a/source/AllToLua.pkg +++ b/source/AllToLua.pkg @@ -41,6 +41,7 @@ $cfile "BlockEntities/ChestEntity.h" $cfile "BlockEntities/DropSpenserEntity.h" $cfile "BlockEntities/DispenserEntity.h" $cfile "BlockEntities/DropperEntity.h" +$cfile "BlockEntities/FurnaceEntity.h" $cfile "WebAdmin.h" $cfile "WebPlugin.h" $cfile "Pickup.h" diff --git a/source/Bindings.cpp b/source/Bindings.cpp index 7f992c6bd..07b2feab3 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 06/15/13 20:05:13. +** Generated automatically by tolua++-1.0.92 on 06/16/13 22:21:21. */ #ifndef __cplusplus @@ -41,6 +41,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S); #include "BlockEntities/DropSpenserEntity.h" #include "BlockEntities/DispenserEntity.h" #include "BlockEntities/DropperEntity.h" +#include "BlockEntities/FurnaceEntity.h" #include "WebAdmin.h" #include "WebPlugin.h" #include "Pickup.h" @@ -152,6 +153,13 @@ static int tolua_collect_cCraftingGrid (lua_State* tolua_S) return 0; } +static int tolua_collect_cTracer (lua_State* tolua_S) +{ + cTracer* self = (cTracer*) tolua_tousertype(tolua_S,1,0); + Mtolua_delete(self); + return 0; +} + static int tolua_collect_Vector3i (lua_State* tolua_S) { Vector3i* self = (Vector3i*) tolua_tousertype(tolua_S,1,0); @@ -159,16 +167,16 @@ static int tolua_collect_Vector3i (lua_State* tolua_S) return 0; } -static int tolua_collect_cIniFile (lua_State* tolua_S) +static int tolua_collect_cFurnaceEntity (lua_State* tolua_S) { - cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0); + cFurnaceEntity* self = (cFurnaceEntity*) tolua_tousertype(tolua_S,1,0); Mtolua_delete(self); return 0; } -static int tolua_collect_cTracer (lua_State* tolua_S) +static int tolua_collect_cIniFile (lua_State* tolua_S) { - cTracer* self = (cTracer*) tolua_tousertype(tolua_S,1,0); + cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0); Mtolua_delete(self); return 0; } @@ -197,34 +205,35 @@ static void tolua_reg_types (lua_State* tolua_S) tolua_usertype(tolua_S,"cRoot"); tolua_usertype(tolua_S,"cWindow"); tolua_usertype(tolua_S,"cCraftingGrid"); + tolua_usertype(tolua_S,"cTracer"); tolua_usertype(tolua_S,"cPickup"); tolua_usertype(tolua_S,"cItems"); tolua_usertype(tolua_S,"cGroup"); tolua_usertype(tolua_S,"cClientHandle"); tolua_usertype(tolua_S,"cChunkDesc"); tolua_usertype(tolua_S,"cFurnaceRecipe"); - tolua_usertype(tolua_S,"cTracer"); - tolua_usertype(tolua_S,"cChatColor"); tolua_usertype(tolua_S,"cCuboid"); + tolua_usertype(tolua_S,"cChatColor"); tolua_usertype(tolua_S,"Vector3i"); + tolua_usertype(tolua_S,"cPlugin_NewLua"); tolua_usertype(tolua_S,"Lua__cWebPlugin"); tolua_usertype(tolua_S,"Lua__cPawn"); - tolua_usertype(tolua_S,"cPlugin_NewLua"); + tolua_usertype(tolua_S,"cWebAdmin"); tolua_usertype(tolua_S,"cItem"); tolua_usertype(tolua_S,"Vector3f"); - tolua_usertype(tolua_S,"cWebAdmin"); + tolua_usertype(tolua_S,"cCraftingRecipes"); tolua_usertype(tolua_S,"cDropSpenserEntity"); tolua_usertype(tolua_S,"Lua__cPlayer"); - tolua_usertype(tolua_S,"cCraftingRecipes"); + tolua_usertype(tolua_S,"cItemGrid::cListener"); tolua_usertype(tolua_S,"cChestEntity"); tolua_usertype(tolua_S,"cDispenserEntity"); - tolua_usertype(tolua_S,"cItemGrid::cListener"); + tolua_usertype(tolua_S,"Lua__cPickup"); tolua_usertype(tolua_S,"cBlockEntity"); tolua_usertype(tolua_S,"cCriticalSection"); - tolua_usertype(tolua_S,"Lua__cPickup"); tolua_usertype(tolua_S,"cWebPlugin"); tolua_usertype(tolua_S,"HTTPRequest"); tolua_usertype(tolua_S,"HTTPFormData"); + tolua_usertype(tolua_S,"cFurnaceEntity"); tolua_usertype(tolua_S,"cDropperEntity"); tolua_usertype(tolua_S,"cPluginManager"); tolua_usertype(tolua_S,"cWorld"); @@ -14519,6 +14528,40 @@ static int tolua_AllToLua_cItem_CopyOne00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE +/* method: AddCount of class cItem */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cItem_AddCount00 +static int tolua_AllToLua_cItem_AddCount00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cItem",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cItem* self = (cItem*) tolua_tousertype(tolua_S,1,0); + char a_AmountToAdd = ((char) tolua_tonumber(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'AddCount'", NULL); +#endif + { + cItem& tolua_ret = (cItem&) self->AddCount(a_AmountToAdd); + tolua_pushusertype(tolua_S,(void*)&tolua_ret,"cItem"); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'AddCount'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* method: GetMaxDamage of class cItem */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cItem_GetMaxDamage00 static int tolua_AllToLua_cItem_GetMaxDamage00(lua_State* tolua_S) @@ -14651,31 +14694,33 @@ static int tolua_AllToLua_cItem_IsStackableWith00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE -/* method: IsEnchantable of class cItem */ -#ifndef TOLUA_DISABLE_tolua_AllToLua_cItem_IsEnchantable00 -static int tolua_AllToLua_cItem_IsEnchantable00(lua_State* tolua_S) +/* method: IsFullStack of class cItem */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cItem_IsFullStack00 +static int tolua_AllToLua_cItem_IsFullStack00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( - !tolua_isusertable(tolua_S,1,"cItem",0,&tolua_err) || - !tolua_isnumber(tolua_S,2,0,&tolua_err) || - !tolua_isnoobj(tolua_S,3,&tolua_err) + !tolua_isusertype(tolua_S,1,"const cItem",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) ) goto tolua_lerror; else #endif { - short a_ItemType = ((short) tolua_tonumber(tolua_S,2,0)); + const cItem* self = (const cItem*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsFullStack'", NULL); +#endif { - bool tolua_ret = (bool) cItem::IsEnchantable(a_ItemType); + bool tolua_ret = (bool) self->IsFullStack(); tolua_pushboolean(tolua_S,(bool)tolua_ret); } } return 1; #ifndef TOLUA_RELEASE tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'IsEnchantable'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'IsFullStack'.",&tolua_err); return 0; #endif } @@ -17023,6 +17068,398 @@ static int tolua_AllToLua_cDropperEntity_new00_local(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE +/* method: new of class cFurnaceEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_new00 +static int tolua_AllToLua_cFurnaceEntity_new00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertable(tolua_S,1,"cFurnaceEntity",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnumber(tolua_S,3,0,&tolua_err) || + !tolua_isnumber(tolua_S,4,0,&tolua_err) || + !tolua_isnoobj(tolua_S,5,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + int a_BlockX = ((int) tolua_tonumber(tolua_S,2,0)); + int a_BlockY = ((int) tolua_tonumber(tolua_S,3,0)); + int a_BlockZ = ((int) tolua_tonumber(tolua_S,4,0)); + { + cFurnaceEntity* tolua_ret = (cFurnaceEntity*) Mtolua_new((cFurnaceEntity)(a_BlockX,a_BlockY,a_BlockZ)); + tolua_pushusertype(tolua_S,(void*)tolua_ret,"cFurnaceEntity"); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: new_local of class cFurnaceEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_new00_local +static int tolua_AllToLua_cFurnaceEntity_new00_local(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertable(tolua_S,1,"cFurnaceEntity",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnumber(tolua_S,3,0,&tolua_err) || + !tolua_isnumber(tolua_S,4,0,&tolua_err) || + !tolua_isnoobj(tolua_S,5,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + int a_BlockX = ((int) tolua_tonumber(tolua_S,2,0)); + int a_BlockY = ((int) tolua_tonumber(tolua_S,3,0)); + int a_BlockZ = ((int) tolua_tonumber(tolua_S,4,0)); + { + cFurnaceEntity* tolua_ret = (cFurnaceEntity*) Mtolua_new((cFurnaceEntity)(a_BlockX,a_BlockY,a_BlockZ)); + tolua_pushusertype(tolua_S,(void*)tolua_ret,"cFurnaceEntity"); + tolua_register_gc(tolua_S,lua_gettop(tolua_S)); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: GetInputSlot of class cFurnaceEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_GetInputSlot00 +static int tolua_AllToLua_cFurnaceEntity_GetInputSlot00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cFurnaceEntity",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cFurnaceEntity* self = (const cFurnaceEntity*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetInputSlot'", NULL); +#endif + { + const cItem& tolua_ret = (const cItem&) self->GetInputSlot(); + tolua_pushusertype(tolua_S,(void*)&tolua_ret,"const cItem"); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetInputSlot'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: GetFuelSlot of class cFurnaceEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_GetFuelSlot00 +static int tolua_AllToLua_cFurnaceEntity_GetFuelSlot00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cFurnaceEntity",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cFurnaceEntity* self = (const cFurnaceEntity*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetFuelSlot'", NULL); +#endif + { + const cItem& tolua_ret = (const cItem&) self->GetFuelSlot(); + tolua_pushusertype(tolua_S,(void*)&tolua_ret,"const cItem"); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetFuelSlot'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: GetOutputSlot of class cFurnaceEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_GetOutputSlot00 +static int tolua_AllToLua_cFurnaceEntity_GetOutputSlot00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cFurnaceEntity",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cFurnaceEntity* self = (const cFurnaceEntity*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetOutputSlot'", NULL); +#endif + { + const cItem& tolua_ret = (const cItem&) self->GetOutputSlot(); + tolua_pushusertype(tolua_S,(void*)&tolua_ret,"const cItem"); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetOutputSlot'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: SetInputSlot of class cFurnaceEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_SetInputSlot00 +static int tolua_AllToLua_cFurnaceEntity_SetInputSlot00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cFurnaceEntity",0,&tolua_err) || + (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cItem",0,&tolua_err)) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cFurnaceEntity* self = (cFurnaceEntity*) tolua_tousertype(tolua_S,1,0); + const cItem* a_Item = ((const cItem*) tolua_tousertype(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetInputSlot'", NULL); +#endif + { + self->SetInputSlot(*a_Item); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'SetInputSlot'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: SetFuelSlot of class cFurnaceEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_SetFuelSlot00 +static int tolua_AllToLua_cFurnaceEntity_SetFuelSlot00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cFurnaceEntity",0,&tolua_err) || + (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cItem",0,&tolua_err)) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cFurnaceEntity* self = (cFurnaceEntity*) tolua_tousertype(tolua_S,1,0); + const cItem* a_Item = ((const cItem*) tolua_tousertype(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetFuelSlot'", NULL); +#endif + { + self->SetFuelSlot(*a_Item); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'SetFuelSlot'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: SetOutputSlot of class cFurnaceEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_SetOutputSlot00 +static int tolua_AllToLua_cFurnaceEntity_SetOutputSlot00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cFurnaceEntity",0,&tolua_err) || + (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const cItem",0,&tolua_err)) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cFurnaceEntity* self = (cFurnaceEntity*) tolua_tousertype(tolua_S,1,0); + const cItem* a_Item = ((const cItem*) tolua_tousertype(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetOutputSlot'", NULL); +#endif + { + self->SetOutputSlot(*a_Item); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'SetOutputSlot'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: GetTimeCooked of class cFurnaceEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_GetTimeCooked00 +static int tolua_AllToLua_cFurnaceEntity_GetTimeCooked00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cFurnaceEntity",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cFurnaceEntity* self = (const cFurnaceEntity*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetTimeCooked'", NULL); +#endif + { + int tolua_ret = (int) self->GetTimeCooked(); + tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetTimeCooked'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: GetCookTimeLeft of class cFurnaceEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_GetCookTimeLeft00 +static int tolua_AllToLua_cFurnaceEntity_GetCookTimeLeft00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cFurnaceEntity",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cFurnaceEntity* self = (const cFurnaceEntity*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetCookTimeLeft'", NULL); +#endif + { + int tolua_ret = (int) self->GetCookTimeLeft(); + tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetCookTimeLeft'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: GetFuelBurnTimeLeft of class cFurnaceEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_GetFuelBurnTimeLeft00 +static int tolua_AllToLua_cFurnaceEntity_GetFuelBurnTimeLeft00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cFurnaceEntity",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cFurnaceEntity* self = (const cFurnaceEntity*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetFuelBurnTimeLeft'", NULL); +#endif + { + int tolua_ret = (int) self->GetFuelBurnTimeLeft(); + tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetFuelBurnTimeLeft'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: HasFuelTimeLeft of class cFurnaceEntity */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_HasFuelTimeLeft00 +static int tolua_AllToLua_cFurnaceEntity_HasFuelTimeLeft00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cFurnaceEntity",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cFurnaceEntity* self = (const cFurnaceEntity*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'HasFuelTimeLeft'", NULL); +#endif + { + bool tolua_ret = (bool) self->HasFuelTimeLeft(); + tolua_pushboolean(tolua_S,(bool)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'HasFuelTimeLeft'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* get function: Name of class HTTPFormData */ #ifndef TOLUA_DISABLE_tolua_get_HTTPFormData_Name static int tolua_get_HTTPFormData_Name(lua_State* tolua_S) @@ -27754,11 +28191,12 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"IsEqual",tolua_AllToLua_cItem_IsEqual00); tolua_function(tolua_S,"IsSameType",tolua_AllToLua_cItem_IsSameType00); tolua_function(tolua_S,"CopyOne",tolua_AllToLua_cItem_CopyOne00); + tolua_function(tolua_S,"AddCount",tolua_AllToLua_cItem_AddCount00); tolua_function(tolua_S,"GetMaxDamage",tolua_AllToLua_cItem_GetMaxDamage00); tolua_function(tolua_S,"DamageItem",tolua_AllToLua_cItem_DamageItem00); tolua_function(tolua_S,"IsDamageable",tolua_AllToLua_cItem_IsDamageable00); tolua_function(tolua_S,"IsStackableWith",tolua_AllToLua_cItem_IsStackableWith00); - tolua_function(tolua_S,"IsEnchantable",tolua_AllToLua_cItem_IsEnchantable00); + tolua_function(tolua_S,"IsFullStack",tolua_AllToLua_cItem_IsFullStack00); tolua_variable(tolua_S,"m_ItemType",tolua_get_cItem_m_ItemType,tolua_set_cItem_m_ItemType); tolua_variable(tolua_S,"m_ItemCount",tolua_get_cItem_m_ItemCount,tolua_set_cItem_m_ItemCount); tolua_variable(tolua_S,"m_ItemDamage",tolua_get_cItem_m_ItemDamage,tolua_set_cItem_m_ItemDamage); @@ -27883,6 +28321,31 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"new_local",tolua_AllToLua_cDropperEntity_new00_local); tolua_function(tolua_S,".call",tolua_AllToLua_cDropperEntity_new00_local); tolua_endmodule(tolua_S); + #ifdef __cplusplus + tolua_cclass(tolua_S,"cFurnaceEntity","cFurnaceEntity","cBlockEntityWithItems",tolua_collect_cFurnaceEntity); + #else + tolua_cclass(tolua_S,"cFurnaceEntity","cFurnaceEntity","cBlockEntityWithItems",NULL); + #endif + tolua_beginmodule(tolua_S,"cFurnaceEntity"); + tolua_constant(tolua_S,"fsInput",cFurnaceEntity::fsInput); + tolua_constant(tolua_S,"fsFuel",cFurnaceEntity::fsFuel); + tolua_constant(tolua_S,"fsOutput",cFurnaceEntity::fsOutput); + tolua_constant(tolua_S,"ContentsWidth",cFurnaceEntity::ContentsWidth); + tolua_constant(tolua_S,"ContentsHeight",cFurnaceEntity::ContentsHeight); + tolua_function(tolua_S,"new",tolua_AllToLua_cFurnaceEntity_new00); + tolua_function(tolua_S,"new_local",tolua_AllToLua_cFurnaceEntity_new00_local); + tolua_function(tolua_S,".call",tolua_AllToLua_cFurnaceEntity_new00_local); + tolua_function(tolua_S,"GetInputSlot",tolua_AllToLua_cFurnaceEntity_GetInputSlot00); + tolua_function(tolua_S,"GetFuelSlot",tolua_AllToLua_cFurnaceEntity_GetFuelSlot00); + tolua_function(tolua_S,"GetOutputSlot",tolua_AllToLua_cFurnaceEntity_GetOutputSlot00); + tolua_function(tolua_S,"SetInputSlot",tolua_AllToLua_cFurnaceEntity_SetInputSlot00); + tolua_function(tolua_S,"SetFuelSlot",tolua_AllToLua_cFurnaceEntity_SetFuelSlot00); + tolua_function(tolua_S,"SetOutputSlot",tolua_AllToLua_cFurnaceEntity_SetOutputSlot00); + tolua_function(tolua_S,"GetTimeCooked",tolua_AllToLua_cFurnaceEntity_GetTimeCooked00); + tolua_function(tolua_S,"GetCookTimeLeft",tolua_AllToLua_cFurnaceEntity_GetCookTimeLeft00); + tolua_function(tolua_S,"GetFuelBurnTimeLeft",tolua_AllToLua_cFurnaceEntity_GetFuelBurnTimeLeft00); + tolua_function(tolua_S,"HasFuelTimeLeft",tolua_AllToLua_cFurnaceEntity_HasFuelTimeLeft00); + tolua_endmodule(tolua_S); tolua_cclass(tolua_S,"HTTPFormData","HTTPFormData","",NULL); tolua_beginmodule(tolua_S,"HTTPFormData"); tolua_variable(tolua_S,"Name",tolua_get_HTTPFormData_Name,tolua_set_HTTPFormData_Name); diff --git a/source/Bindings.h b/source/Bindings.h index 8925e328b..fda904950 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 06/15/13 20:05:14. +** Generated automatically by tolua++-1.0.92 on 06/16/13 22:21:22. */ /* Exported function */ diff --git a/source/BlockEntities/ChestEntity.cpp b/source/BlockEntities/ChestEntity.cpp index 3e75d5100..24d2aef11 100644 --- a/source/BlockEntities/ChestEntity.cpp +++ b/source/BlockEntities/ChestEntity.cpp @@ -56,8 +56,8 @@ bool cChestEntity::LoadFromJson(const Json::Value & a_Value) for (Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr) { cItem Item; - Item.FromJson( *itr ); - SetSlot( SlotIdx, Item ); + Item.FromJson(*itr); + SetSlot(SlotIdx, Item); SlotIdx++; } return true; diff --git a/source/BlockEntities/FurnaceEntity.cpp b/source/BlockEntities/FurnaceEntity.cpp index d4cdf3f89..ecbf715f2 100644 --- a/source/BlockEntities/FurnaceEntity.cpp +++ b/source/BlockEntities/FurnaceEntity.cpp @@ -4,7 +4,6 @@ #include "FurnaceEntity.h" #include "../UI/Window.h" #include "../Player.h" -#include "../FurnaceRecipe.h" #include "../Root.h" #include @@ -23,54 +22,50 @@ enum -cFurnaceEntity::cFurnaceEntity(int a_X, int a_Y, int a_Z, cWorld * a_World) - : cBlockEntity( E_BLOCK_FURNACE, a_X, a_Y, a_Z, a_World ) - , m_Items( new cItem[3] ) - , m_CookingItem( 0 ) - , m_CookTime( 0 ) - , m_TimeCooked( 0 ) - , m_BurnTime( 0 ) - , m_TimeBurned( 0 ) +cFurnaceEntity::cFurnaceEntity(int a_BlockX, int a_BlockY, int a_BlockZ) : + super(E_BLOCK_FURNACE, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, NULL), + m_IsCooking(false), + m_NeedCookTime(0), + m_TimeCooked(0), + m_FuelBurnTime(0), + m_TimeBurned(0), + m_LastProgressFuel(0), + m_LastProgressCook(0) { SetBlockEntity(this); // cBlockEntityWindowOwner + m_Contents.AddListener(*this); } -cFurnaceEntity::~cFurnaceEntity() +cFurnaceEntity::cFurnaceEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : + super(E_BLOCK_FURNACE, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World), + m_IsCooking(false), + m_NeedCookTime(0), + m_TimeCooked(0), + m_FuelBurnTime(0), + m_TimeBurned(0), + m_LastProgressFuel(0), + m_LastProgressCook(0) { - // Tell window its owner is destroyed - if( GetWindow() ) - { - GetWindow()->OwnerDestroyed(); - } - - // Clean up items - if( m_Items ) - { - delete [] m_Items; - } + SetBlockEntity(this); // cBlockEntityWindowOwner + m_Contents.AddListener(*this); } -void cFurnaceEntity::Destroy() +cFurnaceEntity::~cFurnaceEntity() { - // Drop items - cItems Pickups; - for( int i = 0; i < 3; i++) + // Tell window its owner is destroyed + cWindow * Window = GetWindow(); + if (Window != NULL) { - if( !m_Items[i].IsEmpty() ) - { - Pickups.push_back(m_Items[i]); - m_Items[i].Empty(); - } + Window->OwnerDestroyed(); } - m_World->SpawnItemPickups(Pickups, m_PosX, m_PosY, m_PosZ); } @@ -83,11 +78,12 @@ void cFurnaceEntity::UsedBy(cPlayer * a_Player) { OpenWindow(new cFurnaceWindow(m_PosX, m_PosY, m_PosZ, this)); } - if (GetWindow() != NULL) + cWindow * Window = GetWindow(); + if (Window != NULL) { - if (a_Player->GetWindow() != GetWindow()) + if (a_Player->GetWindow() != Window) { - a_Player->OpenWindow(GetWindow()); + a_Player->OpenWindow(Window); } } } @@ -96,270 +92,380 @@ void cFurnaceEntity::UsedBy(cPlayer * a_Player) +/// Restarts cooking. Used after the furnace is loaded from storage to set up the internal variables so that cooking continues, if it was active. Returns true if cooking. +bool cFurnaceEntity::ContinueCooking(void) +{ + UpdateInput(); + UpdateFuel(); + return m_IsCooking; +} + + + + + bool cFurnaceEntity::Tick(float a_Dt, cChunk & a_Chunk) { - /* - // DEBUG: - Int16 BurnTime = (Int16)(GetTimeToBurn() / 50.0); - Int16 CookTime = (Int16)(GetTimeCooked() / 50.0); - LOGD("Furnace: BurnTime %d, CookTime %d", BurnTime, CookTime); - */ - - if (m_BurnTime <= 0) + if (m_FuelBurnTime <= 0) { - if (m_TimeCooked > 0) + // No fuel is burning, reset progressbars and bail out + if ((m_LastProgressCook > 0) || (m_LastProgressFuel > 0)) { - // We have just finished smelting, reset the progress bar: - BroadcastProgress(PROGRESSBAR_SMELTING, 0); - m_TimeCooked = 0; - m_World->FastSetBlock(m_PosX, m_PosY, m_PosZ, E_BLOCK_FURNACE, m_World->GetBlockMeta(m_PosX, m_PosY, m_PosZ)); + UpdateProgressBars(); } - // There is no fuel and no flame, no need to tick at all return false; } - - // DEBUG: LOGD("Furnace: Left: %0.1f Burned: %0.1f Burn time: %0.1f", m_CookTime - m_TimeCooked, m_TimeBurned, m_BurnTime ); - - short SmeltingProgress = 0; - if ((m_CookingItem != NULL) && ((m_TimeBurned < m_BurnTime) || (m_TimeCooked + a_Dt >= m_CookTime))) - { - if (m_CookingItem->IsEqual(m_Items[2]) || m_Items[2].IsEmpty()) - { - m_TimeCooked += a_Dt; - if ( m_TimeCooked >= m_CookTime ) - { - m_Items[0].m_ItemCount--; - if( m_Items[0].IsEmpty() ) m_Items[0].Empty(); - - m_Items[2].m_ItemDamage = m_CookingItem->m_ItemDamage; - m_Items[2].m_ItemType = m_CookingItem->m_ItemType; - m_Items[2].m_ItemCount += m_CookingItem->m_ItemCount; - delete m_CookingItem; - m_CookingItem = NULL; - - cWindow * Window = GetWindow(); - if (Window != NULL) - { - Window->BroadcastWholeWindow(); - } - - m_TimeCooked -= m_CookTime; - StartCooking(); - } - SmeltingProgress = (short)( m_TimeCooked * (180.f / m_CookTime)); - if (SmeltingProgress > 180) SmeltingProgress = 180; - if (SmeltingProgress < 0) SmeltingProgress = 0; - } - } - BroadcastProgress(PROGRESSBAR_SMELTING, SmeltingProgress); - m_TimeBurned += a_Dt; - - cWindow * Window = GetWindow(); - if (m_TimeBurned >= m_BurnTime) + if (m_IsCooking) { - m_TimeBurned -= m_BurnTime; - m_BurnTime = 0; - if (StartCooking() && (Window != NULL)) + m_TimeCooked++; + if (m_TimeCooked >= m_NeedCookTime) { - Window->BroadcastWholeWindow(); + // Finished smelting one item + FinishOne(a_Chunk); } } - short Value = 0; - if (m_BurnTime > 0.f) + + m_TimeBurned++; + if (m_TimeBurned >= m_FuelBurnTime) { - Value = 250 - (short)( m_TimeBurned * (250.f / m_BurnTime)); - if (Value > 250) Value = 250; - if (Value < 0) Value = 0; + // The current fuel has been exhausted, use another one, if possible + BurnNewFuel(); } - BroadcastProgress(PROGRESSBAR_FUEL, Value); - return ((m_CookingItem != NULL) || (m_TimeBurned < m_BurnTime)) && (m_BurnTime > 0.0); // Keep on ticking, if there's more to cook, or if it's cooking + UpdateProgressBars(); + + return true; } -bool cFurnaceEntity::StartCooking(void) +bool cFurnaceEntity::LoadFromJson(const Json::Value & a_Value) { - cFurnaceRecipe* FR = cRoot::Get()->GetFurnaceRecipe(); - float BurnTime = FR->GetBurnTime( m_Items[1] ); - if( (m_TimeBurned < m_BurnTime) || BurnTime > 0.f ) // burnable material + m_PosX = a_Value.get("x", 0).asInt(); + m_PosY = a_Value.get("y", 0).asInt(); + m_PosZ = a_Value.get("z", 0).asInt(); + + Json::Value AllSlots = a_Value.get("Slots", 0); + int SlotIdx = 0; + for (Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr) { - const cFurnaceRecipe::Recipe* R = FR->GetRecipeFrom( m_Items[0] ); - if (R != NULL) // cook able ingredient - { - if (m_Items[2].IsEqual(*R->Out) || m_Items[2].IsEmpty()) - { - // good to go - m_World->FastSetBlock(m_PosX, m_PosY, m_PosZ, E_BLOCK_LIT_FURNACE, m_World->GetBlockMeta(m_PosX, m_PosY, m_PosZ)); - - if( m_TimeBurned >= m_BurnTime ) // burn new material - { - m_Items[1].m_ItemCount--; - if( m_Items[1].m_ItemCount <= 0 ) m_Items[1].Empty(); - m_TimeBurned = 0; - m_BurnTime = BurnTime; - } - - if( !m_CookingItem ) // Only cook new item if not already cooking - { - m_CookingItem = new cItem( *R->Out ); // Resulting item - m_TimeCooked = 0.f; - m_CookTime = R->CookTime; - } - return true; - } - } + cItem Item; + Item.FromJson(*itr); + SetSlot(SlotIdx, Item); + SlotIdx++; } - return false; + + m_NeedCookTime = (int)(a_Value.get("CookTime", 0).asDouble() / 50); + m_TimeCooked = (int)(a_Value.get("TimeCooked", 0).asDouble() / 50); + m_FuelBurnTime = (int)(a_Value.get("BurnTime", 0).asDouble() / 50); + m_TimeBurned = (int)(a_Value.get("TimeBurned", 0).asDouble() / 50); + + return true; } -bool cFurnaceEntity::ContinueCooking(void) +void cFurnaceEntity::SaveToJson( Json::Value& a_Value ) { - cFurnaceRecipe * FR = cRoot::Get()->GetFurnaceRecipe(); - float BurnTime = FR->GetBurnTime( m_Items[1] ); - if( (m_TimeBurned < m_BurnTime) || BurnTime > 0.f ) // burnable material + a_Value["x"] = m_PosX; + a_Value["y"] = m_PosY; + a_Value["z"] = m_PosZ; + + Json::Value AllSlots; + int NumSlots = m_Contents.GetNumSlots(); + for (int i = 0; i < NumSlots; i++) { - const cFurnaceRecipe::Recipe * R = FR->GetRecipeFrom( m_Items[0] ); - if (R != NULL) // cook able ingredient - { - if (m_Items[2].IsEqual(*R->Out) || m_Items[2].IsEmpty()) - { - // good to go - if (m_CookingItem == NULL) // Only cook new item if not already cooking - { - m_CookingItem = new cItem( *R->Out ); // Resulting item - } - return true; - } - } + Json::Value Slot; + m_Contents.GetSlot(i).GetJson(Slot); + AllSlots.append(Slot); } - return false; + a_Value["Slots"] = AllSlots; + + a_Value["CookTime"] = m_NeedCookTime * 50; + a_Value["TimeCooked"] = m_TimeCooked * 50; + a_Value["BurnTime"] = m_FuelBurnTime * 50; + a_Value["TimeBurned"] = m_TimeBurned * 50; } -void cFurnaceEntity::ResetCookTimer() +void cFurnaceEntity::SendTo(cClientHandle & a_Client) { - delete m_CookingItem; - m_CookingItem = NULL; - m_TimeCooked = 0.f; - m_CookTime = 0.f; + // Nothing needs to be sent + UNUSED(a_Client); } -void cFurnaceEntity::SetSlot(int a_Slot, const cItem & a_Item) +void cFurnaceEntity::BroadcastProgress(int a_ProgressbarID, short a_Value) { - if ((a_Slot < 0) || (a_Slot >= 3)) + cWindow * Window = GetWindow(); + if (Window != NULL) { - ASSERT(!"Furnace: slot number out of range"); - return; + Window->BroadcastInventoryProgress(a_ProgressbarID, a_Value); } - m_Items[a_Slot] = a_Item; } -bool cFurnaceEntity::LoadFromJson(const Json::Value & a_Value) +/// One item finished cooking +void cFurnaceEntity::FinishOne(cChunk & a_Chunk) { - m_PosX = a_Value.get("x", 0).asInt(); - m_PosY = a_Value.get("y", 0).asInt(); - m_PosZ = a_Value.get("z", 0).asInt(); + m_TimeCooked = 0; - Json::Value AllSlots = a_Value.get("Slots", 0); - int SlotIdx = 0; - for( Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr ) + if (m_Contents.GetSlot(fsOutput).IsEmpty()) { - m_Items[ SlotIdx ].FromJson( *itr ); - SlotIdx++; + m_Contents.SetSlot(fsOutput, *m_CurrentRecipe->Out); + } + else + { + m_Contents.ChangeSlotCount(fsOutput, m_CurrentRecipe->Out->m_ItemCount); } + m_Contents.ChangeSlotCount(fsInput, -m_CurrentRecipe->In->m_ItemCount); + + UpdateIsCooking(); +} + + + - // Get currently cooking item - Json::Value JsonItem = a_Value.get("Cooking", Json::nullValue ); - if( !JsonItem.empty() ) + +void cFurnaceEntity::BurnNewFuel(void) +{ + cFurnaceRecipe * FR = cRoot::Get()->GetFurnaceRecipe(); + int NewTime = FR->GetBurnTime(m_Contents.GetSlot(fsFuel)); + if (NewTime == 0) { - cItem Item; - Item.FromJson( JsonItem ); - if( !Item.IsEmpty() ) + // The item in the fuel slot is not suitable + m_FuelBurnTime = 0; + m_TimeBurned = 0; + m_IsCooking = false; + return; + } + + // Is the input and output ready for cooking? + if (!CanCookInputToOutput()) + { + return; + } + + // Burn one new fuel: + m_FuelBurnTime = NewTime; + m_TimeBurned = 0; + m_IsCooking = true; + if (m_Contents.GetSlot(fsFuel).m_ItemType == E_ITEM_LAVA_BUCKET) + { + m_Contents.SetSlot(fsFuel, cItem(E_ITEM_BUCKET)); + } + else + { + m_Contents.ChangeSlotCount(fsFuel, -1); + } +} + + + + + +void cFurnaceEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) +{ + super::OnSlotChanged(a_ItemGrid, a_SlotNum); + + if (m_World == NULL) + { + // The furnace isn't initialized yet, do no processing + return; + } + + ASSERT(a_ItemGrid == &m_Contents); + switch (a_SlotNum) + { + case fsInput: + { + UpdateInput(); + break; + } + + case fsFuel: + { + UpdateFuel(); + break; + } + + case fsOutput: { - m_CookingItem = new cItem( Item ); + UpdateOutput(); + break; } } +} - m_CookTime = (float)a_Value.get("CookTime", 0).asDouble(); - m_TimeCooked = (float)a_Value.get("TimeCooked", 0).asDouble(); - m_BurnTime = (float)a_Value.get("BurnTime", 0).asDouble(); - m_TimeBurned = (float)a_Value.get("TimeBurned", 0).asDouble(); - return true; + + + + +/// Updates the current recipe, based on the current input +void cFurnaceEntity::UpdateInput(void) +{ + if (!m_Contents.GetSlot(fsInput).IsStackableWith(m_LastInput)) + { + // The input is different from what we had before, reset the cooking time + m_TimeCooked = 0; + } + m_LastInput = m_Contents.GetSlot(fsInput); + + cFurnaceRecipe * FR = cRoot::Get()->GetFurnaceRecipe(); + m_CurrentRecipe = FR->GetRecipeFrom(m_Contents.GetSlot(fsInput)); + if (!CanCookInputToOutput()) + { + // This input cannot be cooked + m_NeedCookTime = 0; + m_IsCooking = false; + } + else + { + m_NeedCookTime = m_CurrentRecipe->CookTime; + m_IsCooking = true; + + // Start burning new fuel if there's no flame now: + if (GetFuelBurnTimeLeft() <= 0) + { + BurnNewFuel(); + } + } } -void cFurnaceEntity::SaveToJson( Json::Value& a_Value ) +/// Called when the fuel slot changes or when the fuel is spent, burns another piece of fuel if appropriate +void cFurnaceEntity::UpdateFuel(void) { - a_Value["x"] = m_PosX; - a_Value["y"] = m_PosY; - a_Value["z"] = m_PosZ; - - Json::Value AllSlots; - for(unsigned int i = 0; i < 3; i++) + if (m_FuelBurnTime > m_TimeBurned) { - Json::Value Slot; - m_Items[ i ].GetJson( Slot ); - AllSlots.append( Slot ); + // The current fuel is still burning, don't modify anything: + return; } - a_Value["Slots"] = AllSlots; + + // The current fuel is spent, try to burn some more: + BurnNewFuel(); +} + + + + - // Currently cooking item - if( m_CookingItem ) +/// Called when the output slot changes; starts burning if space became available +void cFurnaceEntity::UpdateOutput(void) +{ + if (!CanCookInputToOutput()) { - Json::Value JsonItem; - m_CookingItem->GetJson( JsonItem ); - a_Value["Cooking"] = JsonItem; + // Cannot cook anymore: + m_TimeCooked = 0; + m_NeedCookTime = 0; + m_IsCooking = false; + return; } + + // No need to burn new fuel, the Tick() function will take care of that - a_Value["CookTime"] = m_CookTime; - a_Value["TimeCooked"] = m_TimeCooked; - a_Value["BurnTime"] = m_BurnTime; - a_Value["TimeBurned"] = m_TimeBurned; + // Can cook, start cooking if not already underway: + m_NeedCookTime = m_CurrentRecipe->CookTime; + m_IsCooking = true; } -void cFurnaceEntity::SendTo(cClientHandle & a_Client) +/// Updates the m_IsCooking, based on the input slot, output slot and m_FuelBurnTime / m_TimeBurned +void cFurnaceEntity::UpdateIsCooking(void) { - // Nothing needs to be sent - UNUSED(a_Client); + if ( + !CanCookInputToOutput() || // Cannot cook this + (m_FuelBurnTime <= 0) || // No fuel + (m_TimeBurned >= m_FuelBurnTime) // Fuel burnt out + ) + { + // Reset everything + m_IsCooking = false; + m_TimeCooked = 0; + m_NeedCookTime = 0; + return; + } + + m_IsCooking = true; } -void cFurnaceEntity::BroadcastProgress(int a_ProgressbarID, short a_Value) +/// Returns true if the input can be cooked into output and the item counts allow for another cooking operation +bool cFurnaceEntity::CanCookInputToOutput(void) const { - cWindow * Window = GetWindow(); - if (Window != NULL) + if (m_CurrentRecipe == NULL) { - Window->BroadcastInventoryProgress(a_ProgressbarID, a_Value); + // This input cannot be cooked + return false; + } + + if (m_Contents.GetSlot(fsOutput).IsEmpty()) + { + // The output is empty, can cook + return true; + } + + if (!m_Contents.GetSlot(fsOutput).IsStackableWith(*m_CurrentRecipe->Out)) + { + // The output slot is blocked with something that cannot be stacked with the recipe's output + return false; + } + + if (m_Contents.GetSlot(fsOutput).IsFullStack()) + { + // Cannot add any more items to the output slot + return false; + } + + return true; +} + + + + + +/// Broadcasts progressbar updates, if needed +void cFurnaceEntity::UpdateProgressBars(void) +{ + // In order to preserve bandwidth, an update is sent only every 10th tick + // That's why the comparisons use the division by eight + + int CurFuel = (m_FuelBurnTime > 0) ? (200 - 200 * m_TimeBurned / m_FuelBurnTime) : 0; + if ((CurFuel / 8) != (m_LastProgressFuel / 8)) + { + BroadcastProgress(PROGRESSBAR_FUEL, CurFuel); + m_LastProgressFuel = CurFuel; + } + + int CurCook = (m_NeedCookTime > 0) ? (200 * m_TimeCooked / m_NeedCookTime) : 0; + if ((CurCook / 8) != (m_LastProgressCook / 8)) + { + BroadcastProgress(PROGRESSBAR_SMELTING, CurCook); + m_LastProgressCook = CurCook; } } diff --git a/source/BlockEntities/FurnaceEntity.h b/source/BlockEntities/FurnaceEntity.h index 0606497b2..037ed75db 100644 --- a/source/BlockEntities/FurnaceEntity.h +++ b/source/BlockEntities/FurnaceEntity.h @@ -1,9 +1,9 @@ #pragma once -#include "BlockEntity.h" +#include "BlockEntityWithItems.h" #include "../UI/WindowOwner.h" -#include "../Item.h" +#include "../FurnaceRecipe.h" @@ -21,14 +21,33 @@ class cServer; -class cFurnaceEntity : - public cBlockEntity, - public cBlockEntityWindowOwner +class cFurnaceEntity : // tolua_export + public cBlockEntityWindowOwner, + // tolua_begin + public cBlockEntityWithItems { + typedef cBlockEntityWithItems super; + public: - cFurnaceEntity(int a_X, int a_Y, int a_Z, cWorld * a_World); + enum + { + fsInput = 0, // Input slot number + fsFuel = 1, // Fuel slot number + fsOutput = 2, // Output slot number + + ContentsWidth = 3, + ContentsHeight = 1, + }; + + /// Constructor used while generating a chunk; sets m_World to NULL + cFurnaceEntity(int a_BlockX, int a_BlockY, int a_BlockZ); + + // tolua_end + + /// Constructor used for normal operation + cFurnaceEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); + virtual ~cFurnaceEntity(); - virtual void Destroy(); static const char * GetClassStatic() { return "cFurnaceEntity"; } @@ -40,36 +59,97 @@ public: virtual bool Tick(float a_Dt, cChunk & a_Chunk) override; virtual void UsedBy(cPlayer * a_Player) override; - bool StartCooking(void); - /// Restarts cooking. Used after the furnace is loaded from storage to set up the internal variables so that cooking continues, if it was active. Returns true if cooking. bool ContinueCooking(void); void ResetCookTimer(); - const cItem * GetSlot(int i) const { return &(m_Items[i]); } + // tolua_begin + + /// Returns the item in the input slot + const cItem & GetInputSlot(void) const { return GetSlot(fsInput); } + + /// Returns the item in the fuel slot + const cItem & GetFuelSlot(void) const { return GetSlot(fsFuel); } + + /// Returns the item in the output slot + const cItem & GetOutputSlot(void) const { return GetSlot(fsOutput); } + + /// Sets the item in the input slot + void SetInputSlot(const cItem & a_Item) { SetSlot(fsInput, a_Item); } + + /// Sets the item in the fuel slot + void SetFuelSlot(const cItem & a_Item) { SetSlot(fsFuel, a_Item); } + + /// Sets the item in the output slot + void SetOutputSlot(const cItem & a_Item) { SetSlot(fsOutput, a_Item); } + + /// Returns the time that the current item has been cooking, in ticks + int GetTimeCooked(void) const {return m_TimeCooked; } + + /// Returns the time until the current item finishes cooking, in ticks + int GetCookTimeLeft(void) const { return m_NeedCookTime - m_TimeCooked; } - void SetSlot(int a_Slot, const cItem & a_Item); + /// Returns the time until the current fuel is depleted, in ticks + int GetFuelBurnTimeLeft(void) const {return m_FuelBurnTime - m_TimeBurned; } - float GetTimeCooked(void) const {return m_TimeCooked; } - float GetTimeToBurn(void) const {return m_BurnTime - m_TimeBurned; } + /// Returns true if there's time left before the current fuel is depleted + bool HasFuelTimeLeft(void) const { return (GetFuelBurnTimeLeft() > 0); } - void SetBurnTimes(float a_BurnTime, float a_TimeBurned) {m_BurnTime = a_BurnTime; m_TimeBurned = 0; } - void SetCookTimes(float a_CookTime, float a_TimeCooked) {m_CookTime = a_CookTime; m_TimeCooked = a_TimeCooked; } + // tolua_end -private: + void SetBurnTimes(int a_FuelBurnTime, int a_TimeBurned) {m_FuelBurnTime = a_FuelBurnTime; m_TimeBurned = 0; } + void SetCookTimes(int a_NeedCookTime, int a_TimeCooked) {m_NeedCookTime = a_NeedCookTime; m_TimeCooked = a_TimeCooked; } + +protected: - cItem * m_Items; - cItem * m_CookingItem; + /// The recipe for the current input slot + const cFurnaceRecipe::Recipe * m_CurrentRecipe; + + /// The item that is being smelted + cItem m_LastInput; + + bool m_IsCooking; ///< Set to true if the furnace is cooking an item + + // All timers are in ticks + int m_NeedCookTime; ///< Amount of time needed to fully cook current item + int m_TimeCooked; ///< Amount of time that the current item has been cooking + int m_FuelBurnTime; ///< Amount of time that the current fuel can burn (in total); zero if no fuel burning + int m_TimeBurned; ///< Amount of time that the current fuel has been burning - // All timers are in 1 ms - float m_CookTime; // Amount of time needed to fully cook current item - float m_TimeCooked; // Amount of time that the current item has been cooking - float m_BurnTime; // Amount of time that the current fuel can burn (in total); zero if no fuel burning - float m_TimeBurned; // Amount of time that the current fuel has been burning + int m_LastProgressFuel; ///< Last value sent as the progress for the fuel + int m_LastProgressCook; ///< Last value sent as the progress for the cooking void BroadcastProgress(int a_ProgressbarID, short a_Value); -}; + + /// One item finished cooking + void FinishOne(cChunk & a_Chunk); + + /// Starts burning a new fuel, if possible + void BurnNewFuel(void); + + /// Updates the recipe, based on the current input + void UpdateInput(void); + + /// Called when the fuel slot changes or when the fuel is spent, burns another piece of fuel if appropriate + void UpdateFuel(void); + + /// Called when the output slot changes + void UpdateOutput(void); + + /// Updates the m_IsCooking, based on the input slot, output slot and m_FuelBurnTime / m_TimeBurned + void UpdateIsCooking(void); + + /// Returns true if the input can be cooked into output and the item counts allow for another cooking operation + bool CanCookInputToOutput(void) const; + + /// Broadcasts progressbar updates, if needed + void UpdateProgressBars(void); + + // cItemGrid::cListener overrides: + virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override; + +} ; // tolua_export diff --git a/source/BlockEntities/HopperEntity.cpp b/source/BlockEntities/HopperEntity.cpp index fb2e36aa3..1ed0dbbb8 100644 --- a/source/BlockEntities/HopperEntity.cpp +++ b/source/BlockEntities/HopperEntity.cpp @@ -9,6 +9,7 @@ #include "../Player.h" #include "ChestEntity.h" #include "DropSpenserEntity.h" +#include "FurnaceEntity.h" @@ -229,7 +230,28 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk) /// Moves items from a furnace above the hopper into this hopper. Returns true if contents have changed. bool cHopperEntity::MoveItemsFromFurnace(cChunk & a_Chunk) { - // TODO + cFurnaceEntity * Furnace = (cFurnaceEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ); + ASSERT(Furnace != NULL); + + // Try move from the output slot: + if (MoveItemsFromSlot(Furnace->GetOutputSlot(), true)) + { + cItem NewOutput(Furnace->GetOutputSlot()); + Furnace->SetOutputSlot(NewOutput.AddCount(-1)); + return true; + } + + // No output moved, check if we can move an empty bucket out of the fuel slot: + if (Furnace->GetFuelSlot().m_ItemType == E_ITEM_BUCKET) + { + if (MoveItemsFromSlot(Furnace->GetFuelSlot(), true)) + { + Furnace->SetFuelSlot(cItem()); + return true; + } + } + + // Nothing can be moved return false; } diff --git a/source/FurnaceRecipe.cpp b/source/FurnaceRecipe.cpp index a012c8c51..8b1ee09a2 100644 --- a/source/FurnaceRecipe.cpp +++ b/source/FurnaceRecipe.cpp @@ -48,7 +48,7 @@ cFurnaceRecipe::~cFurnaceRecipe() -void cFurnaceRecipe::ReloadRecipes() +void cFurnaceRecipe::ReloadRecipes(void) { ClearRecipes(); LOG("-- Loading furnace recipes --"); @@ -58,15 +58,16 @@ void cFurnaceRecipe::ReloadRecipes() f.open(a_File, std::ios::in); std::string input; - if( !f.good() ) + if (!f.good()) { f.close(); - LOG("Could not open file for recipes: %s", a_File); + LOG("Could not open the furnace recipes file \"%s\"", a_File); return; } + // TODO: Replace this messy parse with a high-level-structured one (ReadLine / ProcessLine) bool bSyntaxError = false; - while( f.good() ) + while (f.good()) { char c; @@ -88,7 +89,10 @@ void cFurnaceRecipe::ReloadRecipes() // Line breaks f.get( c ); while( f.good() && ( c == '\n' || c == '\r' ) ) { f.get( c ); } - if( f.eof() ) break; + if (f.eof()) + { + break; + } f.unget(); ////////////////////////////////////////////////////////////////////////// @@ -112,7 +116,7 @@ void cFurnaceRecipe::ReloadRecipes() } // Burn time - float BurnTime; + int BurnTime; f >> c; if( c != '=' ) { bSyntaxError = true; break; } f >> BurnTime; @@ -141,7 +145,7 @@ void cFurnaceRecipe::ReloadRecipes() f >> IItemHealth; } - float CookTime; + int CookTime; f >> c; if( c != '@' ) { bSyntaxError = true; break; } f >> CookTime; @@ -167,22 +171,20 @@ void cFurnaceRecipe::ReloadRecipes() R.CookTime = CookTime; m_pState->Recipes.push_back( R ); } - if( bSyntaxError ) + if (bSyntaxError) { LOGERROR("ERROR: FurnaceRecipe, syntax error" ); } - LOG("Got %i furnace recipes, and %i fuels.", m_pState->Recipes.size(), m_pState->Fuel.size() ); - - LOG("-- Done loading furnace recipes --"); + LOG("Got %u furnace recipes, and %u fuels.", m_pState->Recipes.size(), m_pState->Fuel.size()); } -void cFurnaceRecipe::ClearRecipes() +void cFurnaceRecipe::ClearRecipes(void) { - for( RecipeList::iterator itr = m_pState->Recipes.begin(); itr != m_pState->Recipes.end(); ++itr ) + for (RecipeList::iterator itr = m_pState->Recipes.begin(); itr != m_pState->Recipes.end(); ++itr) { Recipe R = *itr; delete R.In; @@ -190,7 +192,7 @@ void cFurnaceRecipe::ClearRecipes() } m_pState->Recipes.clear(); - for( FuelList::iterator itr = m_pState->Fuel.begin(); itr != m_pState->Fuel.end(); ++itr ) + for (FuelList::iterator itr = m_pState->Fuel.begin(); itr != m_pState->Fuel.end(); ++itr) { Fuel F = *itr; delete F.In; @@ -198,15 +200,19 @@ void cFurnaceRecipe::ClearRecipes() m_pState->Fuel.clear(); } -const cFurnaceRecipe::Recipe* cFurnaceRecipe::GetRecipeFrom( const cItem & a_Ingredient ) const + + + + +const cFurnaceRecipe::Recipe * cFurnaceRecipe::GetRecipeFrom(const cItem & a_Ingredient) const { - const Recipe* BestRecipe = 0; - for( RecipeList::const_iterator itr = m_pState->Recipes.begin(); itr != m_pState->Recipes.end(); ++itr ) + const Recipe * BestRecipe = 0; + for (RecipeList::const_iterator itr = m_pState->Recipes.begin(); itr != m_pState->Recipes.end(); ++itr) { const Recipe & R = *itr; - if( (R.In->m_ItemType == a_Ingredient.m_ItemType) && (R.In->m_ItemCount <= a_Ingredient.m_ItemCount ) ) + if ((R.In->m_ItemType == a_Ingredient.m_ItemType) && (R.In->m_ItemCount <= a_Ingredient.m_ItemCount)) { - if( BestRecipe && (BestRecipe->In->m_ItemCount > R.In->m_ItemCount) ) + if (BestRecipe && (BestRecipe->In->m_ItemCount > R.In->m_ItemCount)) { continue; } @@ -219,15 +225,19 @@ const cFurnaceRecipe::Recipe* cFurnaceRecipe::GetRecipeFrom( const cItem & a_Ing return BestRecipe; } -float cFurnaceRecipe::GetBurnTime( const cItem & a_Fuel ) const + + + + +int cFurnaceRecipe::GetBurnTime(const cItem & a_Fuel) const { - float BestFuel = 0.f; - for( FuelList::const_iterator itr = m_pState->Fuel.begin(); itr != m_pState->Fuel.end(); ++itr ) + int BestFuel = 0; + for (FuelList::const_iterator itr = m_pState->Fuel.begin(); itr != m_pState->Fuel.end(); ++itr) { const Fuel & F = *itr; - if( (F.In->m_ItemType == a_Fuel.m_ItemType) && (F.In->m_ItemCount <= a_Fuel.m_ItemCount ) ) + if ((F.In->m_ItemType == a_Fuel.m_ItemType) && (F.In->m_ItemCount <= a_Fuel.m_ItemCount)) { - if( BestFuel > 0.f && (BestFuel > F.BurnTime ) ) + if (BestFuel > 0 && (BestFuel > F.BurnTime)) { continue; } @@ -238,4 +248,8 @@ float cFurnaceRecipe::GetBurnTime( const cItem & a_Fuel ) const } } return BestFuel; -} \ No newline at end of file +} + + + + diff --git a/source/FurnaceRecipe.h b/source/FurnaceRecipe.h index ccb008604..2f91e9bcb 100644 --- a/source/FurnaceRecipe.h +++ b/source/FurnaceRecipe.h @@ -14,31 +14,35 @@ class cItem; class cFurnaceRecipe { public: - cFurnaceRecipe(); + cFurnaceRecipe(void); ~cFurnaceRecipe(); - void ReloadRecipes(); + void ReloadRecipes(void); struct Fuel { - cItem* In; - float BurnTime; + cItem * In; + int BurnTime; ///< How long this fuel burns, in ticks }; struct Recipe { - cItem* In; - cItem* Out; - float CookTime; + cItem * In; + cItem * Out; + int CookTime; ///< How long this recipe takes to smelt, in ticks }; - const Recipe* GetRecipeFrom( const cItem & a_Ingredient ) const; - float GetBurnTime( const cItem & a_Fuel ) const; + + /// Returns a recipe for the specified input, NULL if no recipe found + const Recipe * GetRecipeFrom(const cItem & a_Ingredient) const; + + /// Returns the amount of time that the specified fuel burns, in ticks + int GetBurnTime(const cItem & a_Fuel) const; private: - void ClearRecipes(); + void ClearRecipes(void); struct sFurnaceRecipeState; - sFurnaceRecipeState* m_pState; + sFurnaceRecipeState * m_pState; }; diff --git a/source/UI/SlotArea.cpp b/source/UI/SlotArea.cpp index feeeb4add..fc3f248f5 100644 --- a/source/UI/SlotArea.cpp +++ b/source/UI/SlotArea.cpp @@ -475,43 +475,22 @@ cCraftingRecipe & cSlotAreaCrafting::GetRecipeForPlayer(cPlayer & a_Player) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cSlotAreaDropSpenser: - -cSlotAreaDropSpenser::cSlotAreaDropSpenser(cDropSpenserEntity * a_DropSpenser, cWindow & a_ParentWindow) : - cSlotArea(9, a_ParentWindow), - m_DropSpenser(a_DropSpenser) -{ -} - - - - - -const cItem * cSlotAreaDropSpenser::GetSlot(int a_SlotNum, cPlayer & a_Player) const -{ - return &(m_DropSpenser->GetSlot(a_SlotNum)); -} - - - - +// cSlotAreaFurnace: -void cSlotAreaDropSpenser::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) +cSlotAreaFurnace::cSlotAreaFurnace(cFurnaceEntity * a_Furnace, cWindow & a_ParentWindow) : + cSlotArea(3, a_ParentWindow), + m_Furnace(a_Furnace) { - m_DropSpenser->SetSlot(a_SlotNum, a_Item); + m_Furnace->GetContents().AddListener(*this); } -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cSlotAreaFurnace: - -cSlotAreaFurnace::cSlotAreaFurnace(cFurnaceEntity * a_Furnace, cWindow & a_ParentWindow) : - cSlotArea(3, a_ParentWindow), - m_Furnace(a_Furnace) +cSlotAreaFurnace::~cSlotAreaFurnace() { + m_Furnace->GetContents().RemoveListener(*this); } @@ -520,8 +499,6 @@ cSlotAreaFurnace::cSlotAreaFurnace(cFurnaceEntity * a_Furnace, cWindow & a_Paren void cSlotAreaFurnace::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { - cItem Fuel = *GetSlot(0, a_Player); - super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem); if (m_Furnace == NULL) @@ -530,16 +507,6 @@ void cSlotAreaFurnace::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a ASSERT(!"cSlotAreaFurnace::Clicked(): m_Furnace == NULL"); return; } - - if (Fuel.m_ItemType != GetSlot(0, a_Player)->m_ItemType) - { - m_Furnace->ResetCookTimer(); - } - - if (m_Furnace->StartCooking()) - { - m_ParentWindow.SendWholeWindow(*(a_Player.GetClientHandle())); - } } @@ -549,7 +516,7 @@ void cSlotAreaFurnace::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a const cItem * cSlotAreaFurnace::GetSlot(int a_SlotNum, cPlayer & a_Player) const { // a_SlotNum ranges from 0 to 2, query the items from the underlying furnace: - return m_Furnace->GetSlot(a_SlotNum); + return &(m_Furnace->GetSlot(a_SlotNum)); } @@ -565,6 +532,18 @@ void cSlotAreaFurnace::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & +void cSlotAreaFurnace::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) +{ + // Something has changed in the window, broadcast the entire window to all clients + ASSERT(a_ItemGrid == &(m_Furnace->GetContents())); + + m_ParentWindow.BroadcastWholeWindow(); +} + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cSlotAreaInventoryBase: diff --git a/source/UI/SlotArea.h b/source/UI/SlotArea.h index 2666f5209..516e6d644 100644 --- a/source/UI/SlotArea.h +++ b/source/UI/SlotArea.h @@ -276,39 +276,26 @@ protected: -class cSlotAreaDropSpenser : - public cSlotArea -{ - typedef cSlotArea super; - -public: - cSlotAreaDropSpenser(cDropSpenserEntity * a_DropSpenser, cWindow & a_ParentWindow); - - virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override; - virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; - -protected: - cDropSpenserEntity * m_DropSpenser; -} ; - - - - - class cSlotAreaFurnace : - public cSlotArea + public cSlotArea, + public cItemGrid::cListener { typedef cSlotArea super; public: cSlotAreaFurnace(cFurnaceEntity * a_Furnace, cWindow & a_ParentWindow); + virtual ~cSlotAreaFurnace(); + virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override; virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override; virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; protected: cFurnaceEntity * m_Furnace; + + // cItemGrid::cListener overrides: + virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override; } ; diff --git a/source/UI/Window.cpp b/source/UI/Window.cpp index 161145d50..d09c57337 100644 --- a/source/UI/Window.cpp +++ b/source/UI/Window.cpp @@ -11,6 +11,7 @@ #include "../Inventory.h" #include "../Items/ItemHandler.h" #include "../BlockEntities/ChestEntity.h" +#include "../BlockEntities/DropSpenserEntity.h" #include "../BlockEntities/HopperEntity.h" @@ -777,7 +778,7 @@ cDropSpenserWindow::cDropSpenserWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cWindow(cWindow::DropSpenser, "MCS-DropSpenser") { m_ShouldDistributeToHotbarFirst = false; - m_SlotAreas.push_back(new cSlotAreaDropSpenser(a_DropSpenser, *this)); + m_SlotAreas.push_back(new cSlotAreaItemGrid(a_DropSpenser->GetContents(), *this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); } diff --git a/source/WorldStorage/NBTChunkSerializer.cpp b/source/WorldStorage/NBTChunkSerializer.cpp index 9c4f8a2ae..d391325c9 100644 --- a/source/WorldStorage/NBTChunkSerializer.cpp +++ b/source/WorldStorage/NBTChunkSerializer.cpp @@ -161,14 +161,12 @@ void cNBTChunkSerializer::AddDropperEntity(cDropperEntity * a_Entity) void cNBTChunkSerializer::AddFurnaceEntity(cFurnaceEntity * a_Furnace) { m_Writer.BeginCompound(""); - AddBasicTileEntity(a_Furnace, "Furnace"); - m_Writer.BeginList("Items", TAG_Compound); - AddItem(*(a_Furnace->GetSlot(0)), 0); - AddItem(*(a_Furnace->GetSlot(1)), 1); - AddItem(*(a_Furnace->GetSlot(2)), 2); - m_Writer.EndList(); - m_Writer.AddShort("BurnTime", (Int16)(a_Furnace->GetTimeToBurn() / 50.0)); - m_Writer.AddShort("CookTime", (Int16)(a_Furnace->GetTimeCooked() / 50.0)); + AddBasicTileEntity(a_Furnace, "Furnace"); + m_Writer.BeginList("Items", TAG_Compound); + AddItemGrid(a_Furnace->GetContents()); + m_Writer.EndList(); + m_Writer.AddShort("BurnTime", a_Furnace->GetFuelBurnTimeLeft()); + m_Writer.AddShort("CookTime", a_Furnace->GetTimeCooked()); m_Writer.EndCompound(); } diff --git a/source/WorldStorage/NBTChunkSerializer.h b/source/WorldStorage/NBTChunkSerializer.h index 14c31be01..c71286797 100644 --- a/source/WorldStorage/NBTChunkSerializer.h +++ b/source/WorldStorage/NBTChunkSerializer.h @@ -75,7 +75,7 @@ protected: /// Writes an item into the writer, if slot >= 0, adds the Slot tag. The compound is named as requested. void AddItem(const cItem & a_Item, int a_Slot, const AString & a_CompoundName = ""); - /// Writes an item grid into the writer; begins the stored slot numbers with a_BeginSlotNum + /// Writes an item grid into the writer; begins the stored slot numbers with a_BeginSlotNum. Note that it doesn't begin nor end the list tag void AddItemGrid(const cItemGrid & a_Grid, int a_BeginSlotNum = 0); // Block entities: diff --git a/source/WorldStorage/WSSAnvil.cpp b/source/WorldStorage/WSSAnvil.cpp index 43e6dce05..f0b0113da 100644 --- a/source/WorldStorage/WSSAnvil.cpp +++ b/source/WorldStorage/WSSAnvil.cpp @@ -769,14 +769,14 @@ void cWSSAnvil::LoadFurnaceFromNBT(cBlockEntityList & a_BlockEntities, const cPa { Int16 bt = a_NBT.GetShort(BurnTime); // Anvil doesn't store the time that the fuel can burn. We simply "reset" the current value to be the 100% - Furnace->SetBurnTimes((float)(bt * 50.0), (float)(bt * 50.0)); + Furnace->SetBurnTimes(bt, 0); } int CookTime = a_NBT.FindChildByName(a_TagIdx, "CookTime"); if (CookTime >= 0) { Int16 ct = a_NBT.GetShort(CookTime); - // Anvil doesn't store the time that an item takes to cook. We simply use the default - 10 seconds - Furnace->SetCookTimes(10000.0, (float)(ct * 50.0)); + // Anvil doesn't store the time that an item takes to cook. We simply use the default - 10 seconds (200 ticks) + Furnace->SetCookTimes(200, ct); } Furnace->ContinueCooking(); a_BlockEntities.push_back(Furnace.release()); -- cgit v1.2.3