Skip to content

Commit 09abce9

Browse files
Added py.transfer_stack, py.transfer_stack_to_cursor, py.transfer_cursor_to_stack, and py.transfer_inventory_items (#172)
* Added py.transfer_stack, py.transfer_stack_to_cursor, py.transfer_cursor_to_stack, and py.transfer_inventory_items also a few luals things that came up
1 parent e7ac19f commit 09abce9

5 files changed

Lines changed: 120 additions & 2 deletions

File tree

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Date: ???
1515
- Fixed incompatibility with Extended Vanilla. Resolves https://github.com/pyanodon/pybugreports/issues/1265
1616
- Added py.find_latest_undo_action to find the latest undo action referencing a supplied entity
1717
- Fixed that reproductive complex had extremely small alt-mode icons. Resolves https://github.com/pyanodon/pybugreports/issues/1377
18+
- Added py.transfer_stack, py.transfer_stack_to_cursor, py.transfer_cursor_to_stack, and py.transfer_inventory_items
1819
---------------------------------------------------------------------------------------------------
1920
Version: 3.0.41
2021
Date: 2025-12-28

lib/control-stage.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require "events"
66
require "vector"
77
require "smuggler"
88
require "compound-entities"
9+
require "inventory"
910

1011
---Draws a red error icon at the entity's position.
1112
---@param entity LuaEntity

lib/data-stage.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,4 +520,6 @@ py.flip_4way_animation = function(animation4way)
520520
end
521521

522522
---@diagnostic disable-next-line: duplicate-set-field
523-
py.on_event = function() end
523+
---@param event defines.events|defines.events[]|string
524+
---@param f function
525+
py.on_event = function(event, f) end

lib/events.lua

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ _G.gui_events = {
156156
[defines.events.on_gui_text_changed] = {},
157157
[defines.events.on_gui_checked_state_changed] = {},
158158
[defines.events.on_gui_selection_state_changed] = {},
159-
[defines.events.on_gui_checked_state_changed] = {},
160159
[defines.events.on_gui_elem_changed] = {},
161160
[defines.events.on_gui_value_changed] = {},
162161
[defines.events.on_gui_location_changed] = {},

lib/inventory.lua

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
-- all things relating to inventory management and transfers
2+
3+
---@param stack LuaItemStack
4+
---@return boolean simple whether or not the stack is simple, in that is has no special data to be managed
5+
local function is_simple_stack(stack)
6+
return not stack.is_item_with_label and
7+
not stack.is_item_with_entity_data and
8+
not stack.is_tool and
9+
not stack.grid
10+
end
11+
12+
---@param stack LuaItemStack
13+
---@param inventory LuaInventory
14+
---@param amount_to_transfer? uint|double maximum amount to transfer, attempts to transfer full stack if omitted. can be specified as number of items or ratio of current stack size
15+
---@return uint amount_transferred
16+
py.transfer_stack = function(stack, inventory, amount_to_transfer)
17+
if not stack or not stack.valid_for_read or not inventory then return 0 end
18+
if not inventory.can_insert(stack) then return 0 end
19+
local destination = inventory.find_empty_stack(stack)
20+
if stack.grid and not destination then return 0 end -- special case for grid items, can only use transfer_stack
21+
if amount_to_transfer and amount_to_transfer < 1 then
22+
amount_to_transfer = math.floor(stack.count * amount_to_transfer + 0.5)
23+
end
24+
---@cast amount_to_transfer uint
25+
if not destination or is_simple_stack(stack) then
26+
local pre_transfer_amount = stack.count
27+
stack.count = amount_to_transfer and amount_to_transfer < stack.count and amount_to_transfer or stack.count
28+
-- full, or almost full
29+
local amount_transferred = inventory.insert(stack)
30+
if amount_transferred == pre_transfer_amount then
31+
stack.clear()
32+
else
33+
stack.count = pre_transfer_amount - amount_transferred
34+
end
35+
return amount_transferred
36+
end
37+
destination.transfer_stack(stack, amount_to_transfer)
38+
return amount_to_transfer or destination.count
39+
end
40+
41+
---@param player LuaPlayer
42+
---@param stack LuaItemStack
43+
---@param amount_to_transfer? uint|double maximum amount to transfer, attempts to transfer full stack if omitted. can be specified as number of items or ratio of current stack size
44+
py.transfer_stack_to_cursor = function(player, stack, amount_to_transfer)
45+
if not stack or not stack.valid_for_read or player.controller_type == defines.controllers.spectator then return end
46+
local cursor_stack = player.cursor_stack
47+
if amount_to_transfer and amount_to_transfer < 1 then
48+
amount_to_transfer = math.floor(stack.count * amount_to_transfer + 0.5)
49+
end
50+
---@cast amount_to_transfer uint
51+
if is_simple_stack(stack) then
52+
cursor_stack.set_stack{
53+
name = stack.name,
54+
quality = stack.quality,
55+
count = amount_to_transfer or stack.count,
56+
spoil_percent = stack.spoil_percent,
57+
health = stack.health
58+
}
59+
if amount_to_transfer then
60+
stack.count = stack.count - amount_to_transfer
61+
else
62+
stack.clear()
63+
end
64+
else
65+
cursor_stack.transfer_stack(stack, amount_to_transfer)
66+
end
67+
end
68+
69+
---@param player LuaPlayer
70+
---@param stack LuaItemStack
71+
---@param amount_to_transfer? uint|double maximum amount to transfer, attempts to transfer full stack if omitted. can be specified as number of items or ratio of current stack size
72+
py.transfer_cursor_to_stack = function(player, stack, amount_to_transfer)
73+
local cursor_stack = player.cursor_stack
74+
if not cursor_stack or not cursor_stack.valid_for_read then return end
75+
if amount_to_transfer and amount_to_transfer < 1 then
76+
amount_to_transfer = math.floor(cursor_stack.count * amount_to_transfer + 0.5)
77+
end
78+
---@cast amount_to_transfer uint
79+
if is_simple_stack(cursor_stack) then
80+
stack.set_stack{
81+
name = cursor_stack.name,
82+
quality = cursor_stack.quality,
83+
count = amount_to_transfer or cursor_stack.count,
84+
spoil_percent = cursor_stack.spoil_percent,
85+
health = cursor_stack.health
86+
}
87+
if amount_to_transfer then
88+
cursor_stack.count = cursor_stack.count - amount_to_transfer
89+
else
90+
cursor_stack.clear()
91+
end
92+
else
93+
stack.transfer_stack(cursor_stack, amount_to_transfer)
94+
end
95+
end
96+
97+
---@param inventory LuaInventory
98+
---@param target_inventory LuaInventory
99+
---@param stack_to_match? LuaItemStack item stack to match. attempts to match quality and name, transfers all items if omitted or no items in the stack
100+
---@param amount_to_transfer? uint|double maximum amount to transfer, attempts to transfer full stack if omitted. can be specified as number of items or ratio of current stack size
101+
---@param is_supported? function whether the target inventory is supported
102+
py.transfer_inventory_items = function(inventory, target_inventory, stack_to_match, amount_to_transfer, is_supported)
103+
local total_transferred = 0
104+
105+
local item = stack_to_match and stack_to_match.valid_for_read and {name = stack_to_match.name, quality = stack_to_match.quality}
106+
for i = 1, #inventory do
107+
if not inventory[i].valid_for_read or is_supported and not is_supported(inventory[i]) then goto continue end
108+
if item and (inventory[i].name ~= item.name or inventory[i].quality ~= item.quality) then goto continue end
109+
110+
total_transferred = total_transferred + py.transfer_stack(inventory[i], target_inventory, amount_to_transfer)
111+
112+
::continue::
113+
end
114+
return total_transferred
115+
end

0 commit comments

Comments
 (0)