1
0

[Handy] updated for new API, fixed bugs, added warnings. Now v2.

This commit is contained in:
Tau 2014-01-02 19:25:26 +02:00
parent d3dc12815b
commit 0c095faac8
2 changed files with 145 additions and 284 deletions

View File

@ -1,7 +1,7 @@
-- Global variables -- Global variables
PLUGIN = {} -- Reference to own plugin object PLUGIN = {} -- Reference to own plugin object
CHEST_WIDTH = 9 CHEST_WIDTH = 9
HANDY_VERSION = 1 HANDY_VERSION = 2
--[[ --[[
Handy is a plugin for other plugins. It contain no commands, no hooks, but functions to ease plugins developers' life. Handy is a plugin for other plugins. It contain no commands, no hooks, but functions to ease plugins developers' life.

View File

@ -6,350 +6,211 @@ function GetHandyVersion()
return HANDY_VERSION return HANDY_VERSION
end end
-- Checks if handy is in proper version -- Checks if handy is in proper version
function CheckForRequiedVersion(IN_version) function CheckForRequiedVersion( inVersion )
if (IN_version > HANDY_VERSION) then return false end if( inVersion > HANDY_VERSION ) then return false end
return true return true
end end
--[[ --[[
MCS-specific _functions and nasty hacks :D MCS-specific _functions and nasty hacks :D
]] ]]
-- There's a "GetChestHeight" function inside source code, but it's not lua-exported function GetChestHeightCheat( inChest )
function GetChestHeightCheat(IN_chest) local chestGrid = inChest:GetContents()
if (IN_chest:GetSlot(28) == nil) then -- this means we're trying to get double chest slot and FAIL LOGINFO( "This function serves no purpose now! You should consider chest:GetContents():GetHeight() now!" )
LOGWARN("HANDY: single chest checked") LOGINFO( "Also, you might find Handy's new 'IsChestDouble()' useful for your case" )
return 3 return chestGrid:GetHeight()
end
LOGWARN("HANDY: double chest checked")
return 6
end end
-- Those two checks how many items of given IN_itemID chest and player have, and how much they could fit inside them function IsChestDouble( inChest )
function ReadChestForItem(IN_chest, IN_itemID) local chestHeight = inChest:GetContents():GetHeight()
local _items_found = 0 if( chestHeight == 3 ) then
local _free_space = 0 return false
-- stalk through chest slots...
local _slot_counter = 0
local _slot_item
local _item_max_stack = GetItemMaxStack(IN_itemID)
while true do
_slot_item = IN_chest:GetSlot(_slot_counter)
if (_slot_item ~= nil) then
if (_slot_item.m_ItemID == IN_itemID) then
_items_found = _items_found + _slot_item.m_ItemCount
_free_space = _free_space + (_item_max_stack - _slot_item.m_ItemCount)
end
if (_slot_item:IsEmpty() == true) then
_free_space = _free_space + _item_max_stack
end
end
_slot_counter = _slot_counter + 1
if (_slot_counter == CHEST_WIDTH*GetChestHeightCheat(IN_chest)) then
break
end
end end
return _items_found, _free_space return true
end end
function ReadPlayerForItem(IN_player, IN_itemID) -- Those two checks how many items of given inItemID chest and player have, and how much they could fit inside them
local _items_found = 0 function ReadChestForItem( inChest, inItemID )
local _free_space = 0 return ReadGridForItems( inChest:GetContents(), inItemID )
-- stalk through IN_player inventory slots...
local _slot_counter = 9
if (ItemIsArmor(IN_itemID) == true) then _slot_counter = 5 end
local _slot_item
local _item_max_stack = GetItemMaxStack(IN_itemID)
while true do
_slot_item = IN_player:GetInventory():GetSlot(_slot_counter)
if (_slot_item ~= nil) then
if (_slot_item.m_ItemID == IN_itemID) then
_items_found = _items_found + _slot_item.m_ItemCount
_free_space = _free_space + (_item_max_stack - _slot_item.m_ItemCount)
end
if (_slot_item:IsEmpty() == true) then
_free_space = _free_space + _item_max_stack
end
end
_slot_counter = _slot_counter + 1
if (_slot_counter == 45) then
break
end
end
return _items_found, _free_space
end end
-- Following functions are for chest-related operations (since noone was bothered writing them in MCS code) function ReadPlayerForItem( inPlayer, inItemID )
local inventoryFound, inventoryFree = ReadGridForItems( inPlayer:GetInventory():GetInventoryGrid(), inItemID )
local hotbarFound, hotbarFree = ReadGridForItems( inPlayer:GetInventory():GetHotbarGrid(), inItemID )
local itemsFound = inventoryFound + hotbarFound
local freeSpace = inventoryFree + hotbarFree
return itemsFound, freeSpace
end
-- Following functions are for chest-related operations
-- BEWARE! Those assume you did checked if chest has items/space in it! -- BEWARE! Those assume you did checked if chest has items/space in it!
function TakeItemsFromChest(IN_chest, IN_itemID, IN_ammount) -- UNSAFE! CHECK FOR ITEMS FIRST!! function ReadGridForItems( inGrid, inItemID )
-- stalk through chest slots... local itemsFound = 0
local _slot_counter = 0 local freeSpace = 0
local _slot_item local slotsCount = inGrid:GetNumSlots()
local _take_count = IN_ammount local testerItem = cItem( inItemID )
while true do local maxStackSize = testerItem:GetMaxStackSize()
_slot_item = IN_chest:GetSlot(_slot_counter) for index = 0, (slotsCount - 1) do
if (_slot_item ~= nil) then slotItem = inGrid:GetSlot( index )
if (_slot_item.m_ItemID == IN_itemID) then if( slotItem:IsEmpty() ) then
-- assuming player have enought money freeSpace = freeSpace + maxStackSize
if (_take_count > 0) then else
if (_take_count > _slot_item.m_ItemCount) then if( slotItem:IsStackableWith( testerItem ) ) then
_take_count = _take_count - _slot_item.m_ItemCount itemsFound = itemsFound + slotItem.m_ItemCount
IN_chest:SetSlot(_slot_counter, cItem()) -- a bit hacky, can't make cItem:Clear() work( freeSpace = maxStackSize - slotItem.m_ItemCount
else
local _left_count = _slot_item.m_ItemCount - _take_count
IN_chest:SetSlot(_slot_counter, cItem(_slot_item.m_ItemID, _left_count)) -- a bit hacky
_take_count = 0
end
end
if (_take_count == 0) then
break
end
end end
end end
_slot_counter = _slot_counter + 1
if (_slot_counter == CHEST_WIDTH*GetChestHeightCheat(IN_chest)) then
break
end
end end
return itemsFound, freeSpace
end end
function PutItemsToChest(IN_chest, IN_itemID, IN_ammount) -- UNSAFE! CHECK FOR SPACE FIRST!!
-- stalk through chest slots... function TakeItemsFromGrid( inGrid, inItem )
local _slot_counter = 0 local slotsCount = inGrid:GetNumSlots()
local _slot_item local removedItem = cItem( inItem )
local _put_count = IN_ammount for index = 0, (slotsCount - 1) do
local _max_stack = GetItemMaxStack(IN_itemID) slotItem = inGrid:GetSlot( index )
while true do if( slotItem:IsSameType( removedItem ) ) then
_slot_item = IN_chest:GetSlot(_slot_counter) if( slotItem.m_ItemCount <= removedItem.m_ItemCount ) then
local _portion = 0 removedItem.m_ItemCount = removedItem.m_ItemCount - slotItem.m_ItemCount
local _ammount_to_set = 0 inGrid:EmptySlot( index )
if (_slot_item ~= nil) then
if (_slot_item:IsEmpty() == true) then
_portion = math.min(_max_stack, _put_count)
_ammount_to_set = _portion
else else
if (_slot_item.m_ItemID == IN_itemID) then removedItem.m_ItemCount = slotItem.m_ItemCount - removedItem.m_ItemCount
-- choose between how much we need to put and how much free space left inGrid:SetSlot( index, removedItem )
_portion = math.min(_put_count, _max_stack - _slot_item.m_ItemCount) removedItem.m_ItemCount = 0
_ammount_to_set = _slot_item.m_ItemCount + _portion
end
end end
end if( removedItem.m_ItemCount <= 0 ) then break end
IN_chest:SetSlot(_slot_counter, cItem(IN_itemID, _ammount_to_set)) -- we add max stack to chest
_put_count = _put_count - _portion
if (_put_count == 0) then break end
_slot_counter = _slot_counter + 1
if (_slot_counter == CHEST_WIDTH*GetChestHeightCheat(IN_chest)) then
break
end end
end end
return removedItem.m_ItemCount
end
--------------
function TakeItemsFromChest( inChest, inItemID, inAmount ) -- MIGHT BE UNSAFE! CHECK FOR ITEMS FIRST!!
local chestGrid = inChest:GetContents()
local removedItem = cItem( inItemID, inAmount )
TakeItemsFromGrid( chestGrid, removedItem )
end
function PutItemsToChest( inChest, inItemID, inAmount )
local chestGrid = inChest:GetContents()
local addedItem = cItem( inItemID, inAmount )
chestGrid:AddItem( addedItem )
end end
-- Similar to chest-related. -- Similar to chest-related.
function TakeItemsFromPlayer(IN_player, IN_itemID, IN_ammount) -- UNSAFE! CHECK FIRST! function TakeItemsFromPlayer( inPlayer, inItemID, inAmount ) -- MIGHT BE UNSAFE! CHECK FIRST!
local _put_count = IN_ammount local removedItem = cItem( inItemID, inAmount )
local _max_stack = GetItemMaxStack(IN_itemID) local inventoryGrid = inPlayer:GetInventory():GetInventoryGrid()
while true do local hotbarGrid = inPlayer:GetInventory():GetHotbarGrid()
local _portion = math.min(_max_stack, _put_count) local itemsLeft = TakeItemsFromGrid( inventoryGrid, removedItem )
IN_player:GetInventory():RemoveItem(cItem(IN_itemID, _portion)) if( itemsLeft > 0 ) then
_put_count = _put_count - _portion removedItem = cItem( inItemID, itemsLeft )
if (_put_count == 0) then break end TakeItemsFromGrid( hotbarGrid, removedItem )
end end
end end
function GiveItemsToPlayer(IN_player, IN_itemID, IN_ammount) -- UNSAFE! CHECK FIRST! function GiveItemsToPlayer( inPlayer, inItemID, inAmount )
local _put_count = IN_ammount local addedItem = cItem( inItemID, inAmount )
local _max_stack = GetItemMaxStack(IN_itemID) local inventoryGrid = inPlayer:GetInventory():GetInventoryGrid()
while true do local hotbarGrid = inPlayer:GetInventory():GetHotbarGrid()
local _portion = math.min(_max_stack, _put_count) local itemsAdded = inventoryGrid:AddItem( addedItem )
IN_player:GetInventory():AddItem(cItem(IN_itemID, _portion)) if( itemsAdded < inAmount ) then
_put_count = _put_count - _portion addedItem.m_ItemCount = addedItem.m_ItemCount - itemsAdded
if (_put_count == 0) then break end hotbarGrid:AddItem( addedItem )
end end
end end
-- This function returns item max stack for a given itemID. It uses vanilla max stack size, and uses several non-common items notations; -- This function returns item max stack for a given itemID. It uses vanilla max stack size, and uses several non-common items notations;
-- Those are: -- Those are:
-- oneonerecord (because aparently 11record wasn't the best idea in lua scripting application) -- oneonerecord( because aparently 11record wasn't the best idea in lua scripting application )
-- carrotonastick (because it wasn't added to items.txt yet) -- carrotonastick( because it wasn't added to items.txt yet )
-- waitrecord (for same reason) -- waitrecord( for same reason )
-- Feel free to ignore the difference, or to add those to items.txt -- Feel free to ignore the difference, or to add those to items.txt
function GetItemMaxStack(IN_itemID) function GetItemMaxStack( inItemID )
local _result = 64 local testerItem = cItem( inItemID )
-- Tools and swords LOGINFO( "This function serves no real purpose now, maybe consider using cItem:GetMaxStackSize()?" )
if (IN_itemID == woodensword) then _result = 1 end return testerItem:GetMaxStackSize()
if (IN_itemID == woodenshovel) then _result = 1 end
if (IN_itemID == woodenpickaxe) then _result = 1 end
if (IN_itemID == woodenaxe) then _result = 1 end
if (IN_itemID == woodenhoe) then _result = 1 end
if (IN_itemID == stonesword) then _result = 1 end
if (IN_itemID == stoneshovel) then _result = 1 end
if (IN_itemID == stonepickaxe) then _result = 1 end
if (IN_itemID == stoneaxe) then _result = 1 end
if (IN_itemID == stonehoe) then _result = 1 end
if (IN_itemID == ironsword) then _result = 1 end
if (IN_itemID == ironshovel) then _result = 1 end
if (IN_itemID == ironpickaxe) then _result = 1 end
if (IN_itemID == ironaxe) then _result = 1 end
if (IN_itemID == ironhoe) then _result = 1 end
if (IN_itemID == diamondsword) then _result = 1 end
if (IN_itemID == diamondshovel) then _result = 1 end
if (IN_itemID == diamondpickaxe) then _result = 1 end
if (IN_itemID == diamondaxe) then _result = 1 end
if (IN_itemID == diamondhoe) then _result = 1 end
if (IN_itemID == goldensword) then _result = 1 end
if (IN_itemID == goldenshovel) then _result = 1 end
if (IN_itemID == goldenpickaxe) then _result = 1 end
if (IN_itemID == goldenaxe) then _result = 1 end
if (IN_itemID == goldenhoe) then _result = 1 end
if (IN_itemID == flintandsteel) then _result = 1 end
if (IN_itemID == bow) then _result = 1 end
if (IN_itemID == sign) then _result = 16 end
if (IN_itemID == woodendoor) then _result = 1 end
if (IN_itemID == irondoor) then _result = 1 end
if (IN_itemID == cake) then _result = 1 end
if (IN_itemID == cauldron) then _result = 1 end
if (IN_itemID == mushroomstew) then _result = 1 end
if (IN_itemID == painting) then _result = 1 end
if (IN_itemID == bucket) then _result = 16 end
if (IN_itemID == waterbucket) then _result = 1 end
if (IN_itemID == lavabucket) then _result = 1 end
if (IN_itemID == minecart) then _result = 1 end
if (IN_itemID == saddle) then _result = 1 end
if (IN_itemID == snowball) then _result = 16 end
if (IN_itemID == boat) then _result = 1 end
if (IN_itemID == milkbucket) then _result = 1 end
if (IN_itemID == storageminecart) then _result = 1 end
if (IN_itemID == poweredminecart) then _result = 1 end
if (IN_itemID == egg) then _result = 16 end
if (IN_itemID == fishingrod) then _result = 1 end
if (IN_itemID == bed) then _result = 1 end
if (IN_itemID == map) then _result = 1 end
if (IN_itemID == shears) then _result = 1 end
if (IN_itemID == enderpearl) then _result = 16 end
if (IN_itemID == potion) then _result = 1 end
if (IN_itemID == spawnegg) then _result = 1 end
if (IN_itemID == bookandquill) then _result = 1 end
if (IN_itemID == writtenbook) then _result = 1 end
if (IN_itemID == carrotonastick) then _result = 1 end
if (IN_itemID == goldrecord) then _result = 1 end
if (IN_itemID == greenrecord) then _result = 1 end
if (IN_itemID == blocksrecord) then _result = 1 end
if (IN_itemID == chirprecord) then _result = 1 end
if (IN_itemID == farrecord) then _result = 1 end
if (IN_itemID == mallrecord) then _result = 1 end
if (IN_itemID == mellohirecord) then _result = 1 end
if (IN_itemID == stalrecord) then _result = 1 end
if (IN_itemID == stradrecord) then _result = 1 end
if (IN_itemID == wardrecord) then _result = 1 end
if (IN_itemID == oneonerecord) then _result = 1 end
if (IN_itemID == waitrecord) then _result = 1 end
--if (IN_itemID == xxxxxxxxx) then _result = 1 end
if (IN_itemID == leatherhelmet) then _result = 1 end
if (IN_itemID == leatherchestplate) then _result = 1 end
if (IN_itemID == leatherpants) then _result = 1 end
if (IN_itemID == leatherboots) then _result = 1 end
if (IN_itemID == chainmailhelmet) then _result = 1 end
if (IN_itemID == chainmailchestplate) then _result = 1 end
if (IN_itemID == chainmailpants) then _result = 1 end
if (IN_itemID == chainmailboots) then _result = 1 end
if (IN_itemID == ironhelmet) then _result = 1 end
if (IN_itemID == ironchestplate) then _result = 1 end
if (IN_itemID == ironpants) then _result = 1 end
if (IN_itemID == ironboots) then _result = 1 end
if (IN_itemID == diamondhelmet) then _result = 1 end
if (IN_itemID == diamondchestplate) then _result = 1 end
if (IN_itemID == diamondpants) then _result = 1 end
if (IN_itemID == diamondboots) then _result = 1 end
if (IN_itemID == goldenhelmet) then _result = 1 end
if (IN_itemID == goldenchestplate) then _result = 1 end
if (IN_itemID == goldenpants) then _result = 1 end
if (IN_itemID == goldenboots) then _result = 1 end
return _result
end end
function ItemIsArmor(IN_itemID) function ItemIsArmor( inItemID, inCheckForHorseArmor )
local _result = false inCheckForHorseArmor = inCheckForHorseArmor or false
if (IN_itemID == leatherhelmet) then _result = true end if( inItemID == E_ITEM_LEATHER_CAP ) then return true end
if (IN_itemID == leatherchestplate) then _result = true end if( inItemID == E_ITEM_LEATHER_TUNIC ) then return true end
if (IN_itemID == leatherpants) then _result = true end if( inItemID == E_ITEM_LEATHER_PANTS ) then return true end
if (IN_itemID == leatherboots) then _result = true end if( inItemID == E_ITEM_LEATHER_BOOTS ) then return true end
if (IN_itemID == chainmailhelmet) then _result = true end if( inItemID == E_ITEM_CHAIN_HELMET ) then return true end
if (IN_itemID == chainmailchestplate) then _result = true end if( inItemID == E_ITEM_CHAIN_CHESTPLATE ) then return true end
if (IN_itemID == chainmailpants) then _result = true end if( inItemID == E_ITEM_CHAIN_LEGGINGS ) then return true end
if (IN_itemID == chainmailboots) then _result = true end if( inItemID == E_ITEM_CHAIN_BOOTS ) then return true end
if (IN_itemID == ironhelmet) then _result = true end if( inItemID == E_ITEM_IRON_HELMET ) then return true end
if (IN_itemID == ironchestplate) then _result = true end if( inItemID == E_ITEM_IRON_CHESTPLATE ) then return true end
if (IN_itemID == ironpants) then _result = true end if( inItemID == E_ITEM_IRON_LEGGINGS ) then return true end
if (IN_itemID == ironboots) then _result = true end if( inItemID == E_ITEM_IRON_BOOTS ) then return true end
if (IN_itemID == diamondhelmet) then _result = true end if( inItemID == E_ITEM_DIAMOND_HELMET ) then return true end
if (IN_itemID == diamondchestplate) then _result = true end if( inItemID == E_ITEM_DIAMOND_CHESTPLATE ) then return true end
if (IN_itemID == diamondpants) then _result = true end if( inItemID == E_ITEM_DIAMOND_LEGGINGS ) then return true end
if (IN_itemID == diamondboots) then _result = true end if( inItemID == E_ITEM_DIAMOND_BOOTS ) then return true end
if (IN_itemID == goldenhelmet) then _result = true end if( inItemID == E_ITEM_GOLD_HELMET ) then return true end
if (IN_itemID == goldenchestplate) then _result = true end if( inItemID == E_ITEM_GOLD_CHESTPLATE ) then return true end
if (IN_itemID == goldenpants) then _result = true end if( inItemID == E_ITEM_GOLD_LEGGINGS ) then return true end
if (IN_itemID == goldenboots) then _result = true end if( inItemID == E_ITEM_GOLD_BOOTS ) then return true end
return _result
end if( inCheckForHorseArmor ) then
-- Returns full-length playername for a short name (usefull for parsing commands) if( inItemID == E_ITEM_IRON_HORSE_ARMOR ) then return true end
function GetExactPlayername(IN_playername) if( inItemID == E_ITEM_GOLD_HORSE_ARMOR ) then return true end
local _result = IN_playername if( inItemID == E_ITEM_DIAMOND_HORSE_ARMOR ) then return true end
local function SetProcessingPlayername(IN_player)
_result = IN_player:GetName()
end end
cRoot:Get():FindAndDoWithPlayer(IN_playername, SetProcessingPlayername) return false
end
-- Returns full-length playername for a short name( usefull for parsing commands )
function GetExactPlayername( inPlayerName )
local _result = inPlayerName
local function SetProcessingPlayername( inPlayer )
_result = inPlayer:GetName()
end
cRoot:Get():FindAndDoWithPlayer( inPlayerName, SetProcessingPlayername )
return _result return _result
end end
function GetPlayerByName(IN_playername) function GetPlayerByName( inPlayerName )
local _player local _player
local PlayerSetter = function (Player) local PlayerSetter = function( Player )
_player = Player _player = Player
end end
cRoot:Get():FindAndDoWithPlayer(IN_playername, PlayerSetter) cRoot:Get():FindAndDoWithPlayer( inPlayerName, PlayerSetter )
return _player return _player
end end
--[[ --[[
Not-so-usual math _functions Not-so-usual math _functions
]] ]]
-- Rounds floating point number. Because lua guys think this function doesn't deserve to be presented in lua's math -- Rounds floating point number. Because lua guys think this function doesn't deserve to be presented in lua's math
function round(IN_x) function round( inX )
if (IN_x%2 ~= 0.5) then if( inX%2 ~= 0.5 ) then
return math.floor(IN_x+0.5) return math.floor( inX + 0.5 )
end end
return IN_x-0.5 return inX - 0.5
end end
--[[ --[[
Functions I use for filework and stringswork Functions I use for filework and stringswork
]] ]]
function PluralString(IN_value, IN_singular_string, IN_plural_string) function PluralString( inValue, inSingularString, inPluralString )
local _value_string = tostring(IN_value) local _value_string = tostring( inValue )
if (_value_string[#_value_string] == "1") then if( _value_string[#_value_string] == "1" ) then
return IN_singular_string return inSingularString
end end
return IN_plural_string return inPluralString
end end
function PluralItemName(IN_itemID, IN_ammount) -- BEWARE! TEMPORAL SOLUTION THERE! :D function PluralItemName( inItemID, inAmount ) -- BEWARE! TEMPORAL SOLUTION THERE! :D
local _value_string = tostring(IN_value) local _value_string = tostring( inValue )
local _name = "" local _name = ""
if (_value_string[#_value_string] == "1") then if( _value_string[#_value_string] == "1" ) then
-- singular names -- singular names
_name = ItemTypeToString(IN_itemID) _name = ItemTypeToString( inItemID )
else else
-- plural names -- plural names
_name = ItemTypeToString(IN_itemID).."s" _name = ItemTypeToString( inItemID ).."s"
end end
return _name return _name
end end
-- for filewriting purposes. 0 = false, 1 = true -- for filewriting purposes. 0 = false, 1 = true
function StringToBool(value) function StringToBool( inValue )
if value=="1" then return true end if( inValue == "1" ) then return true end
return false return false
end end
-- same, but reversal -- same, but reversal
function BoolToString(value) function BoolToString( inValue )
if value==true then return 1 end if( inValue == true ) then return 1 end
return 0 return 0
end end