Skip to content

Commit b460bb4

Browse files
committed
Fix: reimplement logistic trash support
1 parent 0c60e19 commit b460bb4

11 files changed

Lines changed: 254 additions & 47 deletions

control.lua

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ local F = require("scripts.field-ref")
3838
local Filters = require("scripts.filters")
3939
local Graphics = require("scripts.graphics")
4040
local InventoryTransfers = require("scripts.inventory-transfers")
41+
local InventoryUtils = require("scripts.inventory-utils")
4142
local ItemDescriptions = require("scripts.item-descriptions")
4243
local KruiseKontrol = require("scripts.kruise-kontrol-wrapper")
4344
local Localising = require("scripts.localising")
@@ -67,7 +68,7 @@ require("scripts.ui.selectors.upgrade-selector")
6768
require("scripts.ui.selectors.blueprint-selector")
6869
require("scripts.ui.selectors.copy-paste-selector")
6970
require("scripts.ui.menus.gun-menu")
70-
require("scripts.ui.menus.main-menu")
71+
local MainMenu = require("scripts.ui.menus.main-menu")
7172
require("scripts.ui.menus.fast-travel-menu")
7273
require("scripts.ui.menus.debug-menu")
7374
require("scripts.ui.tabs.item-chooser")
@@ -2785,12 +2786,8 @@ local function kb_open_player_inventory(event)
27852786
sounds.play_open_inventory(p.index)
27862787
p.selected = nil
27872788

2788-
-- Use the router to open the main menu
2789-
local router = UiRouter.get_router(pindex)
2790-
router:open_ui(
2791-
UiRouter.UI_NAMES.MAIN,
2792-
{ player_inventory = { entity = p.character, inventory_index = defines.inventory.character_main } }
2793-
)
2789+
-- Open the main menu
2790+
MainMenu.open_main_menu(pindex)
27942791
end
27952792

27962793
EventManager.on_event(
@@ -4189,16 +4186,6 @@ EventManager.on_event("fa-cas-r", function(event, pindex)
41894186
game.reload_script()
41904187
end)
41914188

4192-
EventManager.on_event(
4193-
"fa-o",
4194-
---@param event EventData.CustomInputEvent
4195-
function(event, pindex)
4196-
local p = game.get_player(pindex)
4197-
if p.character == nil then return end
4198-
if p.driving == true then Driving.pda_read_cruise_control_toggled_info(event.player_index) end
4199-
end
4200-
)
4201-
42024189
EventManager.on_event("fa-c-o", function(event)
42034190
Speech.speak(
42044191
event.player_index,
@@ -4279,3 +4266,47 @@ EventManager.on_event(
42794266
KruiseKontrol.cancel_kk(pindex)
42804267
end
42814268
)
4269+
4270+
-- Send hand contents to trash: O key
4271+
EventManager.on_event("fa-o", function(event)
4272+
local pindex = event.player_index
4273+
local player = game.get_player(pindex)
4274+
if not player or not player.character then return end
4275+
4276+
local cursor_stack = player.cursor_stack
4277+
if not cursor_stack or not cursor_stack.valid_for_read then
4278+
Speech.speak(pindex, { "fa.trash-nothing-in-hand" })
4279+
return
4280+
end
4281+
4282+
-- Get character's trash inventory
4283+
local trash_inventory = InventoryUtils.find_trash_inventory(player.character)
4284+
if not trash_inventory then
4285+
Speech.speak(pindex, { "fa.trash-not-available" })
4286+
return
4287+
end
4288+
4289+
-- Try to insert into trash
4290+
local item_name = cursor_stack.name
4291+
local item_count = cursor_stack.count
4292+
local item_quality = cursor_stack.quality and cursor_stack.quality.name or nil
4293+
4294+
local inserted = trash_inventory.insert({ name = item_name, count = item_count, quality = item_quality })
4295+
4296+
if inserted > 0 then
4297+
-- Remove from hand
4298+
cursor_stack.count = cursor_stack.count - inserted
4299+
4300+
-- Announce success
4301+
local item_description = Localising.localise_item({
4302+
name = item_name,
4303+
count = inserted,
4304+
quality = item_quality,
4305+
})
4306+
Speech.speak(pindex, { "fa.trash-sent-to-trash", item_description })
4307+
4308+
if inserted < item_count then Speech.speak(pindex, { "fa.trash-full", tostring(item_count - inserted) }) end
4309+
else
4310+
Speech.speak(pindex, { "fa.trash-full-none-inserted" })
4311+
end
4312+
end, EventManager.EVENT_KIND.WORLD)

locale/en/inventory-titles.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ inventory-title-hub_trash=Platform Trash
3939
inventory-title-lab_trash=Lab Trash
4040
inventory-title-cargo_landing_pad_trash=Landing Pad Trash
4141
inventory-title-rocket_silo_trash=Silo Trash
42-
inventory-title-logistic_container_trash=Trash Filter
42+
inventory-title-logistic_container_trash=Trash
4343

4444
# Fuel inventories
4545
inventory-title-fuel=Fuel

locale/en/ui-inventory.cfg

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ ui-inventory-slot-locked-to=, locked to __1__
77
ui-inventory-main-title=Main Inventory
88
ui-inventory-player-title=Player Inventory
99
ui-inventory-player-fallback=Player Inventory
10+
ui-inventory-trash-title=Trash Inventory
1011
ui-inventory-no-action=No action
1112
half-stack=half
1213

@@ -21,3 +22,11 @@ ui-inventory-bar-not-supported=This inventory does not support a bar
2122
dangerous-delete-nothing-to-delete=Nothing to delete
2223
dangerous-delete-deleted=Deleted __1__
2324
dangerous-delete-not-planner=Can only delete blueprints or planners.
25+
26+
# Trash functionality
27+
trash-nothing-in-hand=Nothing in hand
28+
trash-nothing-in-slot=Nothing in slot
29+
trash-not-available=Trash not available
30+
trash-sent-to-trash=Sent __1__ to trash
31+
trash-full=Trash full, __1__ remaining
32+
trash-full-none-inserted=Trash full

scripts/inventory-utils.lua

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,28 @@ function mod.get_main_inventory(entity)
124124
return nil
125125
end
126126

127+
---Find the trash inventory for an entity
128+
---
129+
---Checks all possible trash inventory types and returns the first one that exists.
130+
---@param entity LuaEntity
131+
---@return LuaInventory? inventory The trash inventory if it exists, nil otherwise
132+
function mod.find_trash_inventory(entity)
133+
return mod.get_inventory_by_priority(
134+
entity,
135+
"character_trash",
136+
"car_trash",
137+
"spider_trash",
138+
"assembling_machine_trash",
139+
"cargo_landing_pad_trash",
140+
"crafter_trash",
141+
"furnace_trash",
142+
"hub_trash",
143+
"lab_trash",
144+
"logistic_container_trash",
145+
"rocket_silo_trash"
146+
)
147+
end
148+
127149
---Quick transfer a stack from source to destination inventory
128150
---@param pindex integer Player index performing the transfer (for sound playback)
129151
---@param msg_builder fa.MessageBuilder Message builder to append transfer results to

scripts/ui/generic-inventory.lua

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,24 @@ local function setup_shared_state(pindex, params)
4949
entity = p.character,
5050
inventory_index = defines.inventory.character_main,
5151
}
52+
53+
-- Add trash inventory for vehicles if vehicle logistics is enabled
54+
local trash_inv_index = nil
55+
local show_trash = false
56+
57+
if entity.type == "car" or entity.type == "spider-vehicle" then
58+
trash_inv_index = defines.inventory.car_trash
59+
-- For vehicles: only show if vehicle logistics is enabled
60+
show_trash = entity.force.vehicle_logistics
61+
end
62+
63+
if show_trash and trash_inv_index and entity.get_inventory(trash_inv_index) then
64+
ret["trash_inventory"] = {
65+
entity = entity,
66+
inventory_index = trash_inv_index,
67+
}
68+
end
69+
5270
return ret
5371
end
5472

@@ -67,6 +85,12 @@ PERSONAL_GRID.callbacks.enabled = function(pindex)
6785
return game.players[pindex] ~= nil and game.players[pindex].character ~= nil and game.players[pindex].character.valid
6886
end
6987

88+
local TRASH_GRID = InventoryGrid.create_inventory_grid({
89+
name = "trash_inventory",
90+
title = { "fa.ui-inventory-trash-title" },
91+
subkey = "trash_inventory",
92+
})
93+
7094
-- Create the TabList declaration for generic inventories.
7195
mod.generic_inventory = TabList.declare_tablist({
7296
ui_name = UiRouter.UI_NAMES.GENERIC_INVENTORY,
@@ -78,6 +102,7 @@ mod.generic_inventory = TabList.declare_tablist({
78102
tabs = {
79103
GENERIC_GRID,
80104
PERSONAL_GRID,
105+
TRASH_GRID,
81106
},
82107
},
83108
}),

scripts/ui/inventory-grid.lua

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,48 @@ local function render_inventory_grid(ctx)
469469
delete_ctx.message:fragment({ "fa.dangerous-delete-not-planner" })
470470
end
471471
end,
472+
on_trash = function(trash_ctx)
473+
-- Send item in slot to trash (slot_index captured from loop)
474+
local stack = inv[slot_index]
475+
476+
if not stack or not stack.valid_for_read then
477+
trash_ctx.message:fragment({ "fa.trash-nothing-in-slot" })
478+
return
479+
end
480+
481+
-- Get the entity's trash inventory
482+
local trash_inv = InventoryUtils.find_trash_inventory(entity)
483+
if not trash_inv then
484+
trash_ctx.message:fragment({ "fa.trash-not-available" })
485+
return
486+
end
487+
488+
-- Try to insert into trash
489+
local item_name = stack.name
490+
local item_count = stack.count
491+
local item_quality = stack.quality and stack.quality.name or nil
492+
493+
local inserted = trash_inv.insert({ name = item_name, count = item_count, quality = item_quality })
494+
495+
if inserted > 0 then
496+
-- Remove from slot
497+
stack.count = stack.count - inserted
498+
499+
-- Announce success
500+
local item_description = Localising.localise_item({
501+
name = item_name,
502+
count = inserted,
503+
quality = item_quality,
504+
})
505+
trash_ctx.message:fragment({ "fa.trash-sent-to-trash", item_description })
506+
507+
if inserted < item_count then
508+
trash_ctx.message:fragment({ "fa.trash-full", tostring(item_count - inserted) })
509+
end
510+
else
511+
trash_ctx.message:fragment({ "fa.trash-full-none-inserted" })
512+
end
513+
end,
472514
})
473515
end
474516

scripts/ui/key-graph.lua

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ local mod = {}
116116
---@field on_bar_down_small fa.ui.graph.SimpleCallback? Handler for bar down small (-)
117117
---@field on_bar_up_large fa.ui.graph.SimpleCallback? Handler for bar up large (shift++)
118118
---@field on_bar_down_large fa.ui.graph.SimpleCallback? Handler for bar down large (shift+-)
119+
---@field on_trash fa.ui.graph.SimpleCallback? Handler for trash (o key)
119120
---@field exclude_from_search boolean? If true, this node won't be included in search results. Default false.
120121

121122
---@class fa.ui.graph.TransitionVtable
@@ -487,13 +488,22 @@ end
487488
---@param ctx fa.ui.graph.InternalTabCtx
488489
---@param accelerator_name string
489490
function Graph:on_accelerator(ctx, accelerator_name)
490-
self:_with_render(ctx, function()
491-
local n = self.render.nodes[ctx.state.cur_key]
492-
if n and n.vtable.on_accelerator then
491+
-- Check if there's a graph-level on_accelerator handler
492+
if self.on_accelerator_callback then
493+
self:_with_render(ctx, function()
493494
local wrapped_ctx = self:_wrap_ctx(ctx, self.name, NO_MODIFIERS)
494-
n.vtable.on_accelerator(wrapped_ctx, accelerator_name)
495-
end
496-
end)
495+
self.on_accelerator_callback(wrapped_ctx, accelerator_name)
496+
end)
497+
else
498+
-- Fall back to node-level handler
499+
self:_with_render(ctx, function()
500+
local n = self.render.nodes[ctx.state.cur_key]
501+
if n and n.vtable.on_accelerator then
502+
local wrapped_ctx = self:_wrap_ctx(ctx, self.name, NO_MODIFIERS)
503+
n.vtable.on_accelerator(wrapped_ctx, accelerator_name)
504+
end
505+
end)
506+
end
497507
end
498508

499509
---@param ctx fa.ui.graph.InternalTabCtx
@@ -560,6 +570,14 @@ function Graph:on_bar_down_large(ctx)
560570
end)
561571
end
562572

573+
---@param ctx fa.ui.graph.InternalTabCtx
574+
function Graph:on_trash(ctx)
575+
self:_with_render(ctx, function()
576+
local n = self.render.nodes[ctx.state.cur_key]
577+
self:_maybe_call(n, ctx, "on_trash", NO_MODIFIERS)
578+
end)
579+
end
580+
563581
-- Search support
564582

565583
---Check if this UI supports search (always true for KeyGraph)
@@ -679,13 +697,15 @@ end
679697
---@field title LocalisedString
680698
---@field render_callback fa.ui.graph.RenderCallback
681699
---@field name string
700+
---@field on_accelerator fun(ctx: fa.ui.graph.Ctx, accelerator_name: string)?
682701

683702
---@param declaration fa.ui.graph.Declaration
684703
---@return fa.ui.TabDescriptor
685704
function mod.declare_graph(declaration)
686705
local graph = setmetatable({
687706
render_callback = declaration.render_callback,
688707
name = declaration.name,
708+
on_accelerator_callback = declaration.on_accelerator,
689709
-- For debugging, because otherwise it is very unclear that this is a metatable trick.
690710
_callbacks_are_from_metatable = "yes because this is KeyGraph",
691711
}, Graph_meta)

scripts/ui/menu.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ local mod = {}
2121
---@field on_bar_down_small? fa.ui.graph.SimpleCallback
2222
---@field on_bar_up_large? fa.ui.graph.SimpleCallback
2323
---@field on_bar_down_large? fa.ui.graph.SimpleCallback
24+
---@field on_trash? fa.ui.graph.SimpleCallback
2425

2526
---@class fa.ui.menu.Entry
2627
---@field vtable fa.ui.graph.NodeVtable
@@ -120,6 +121,7 @@ function MenuBuilder:add_clickable(key, label, click_handlers)
120121
if click_handlers.on_bar_down_small then vtable.on_bar_down_small = click_handlers.on_bar_down_small end
121122
if click_handlers.on_bar_up_large then vtable.on_bar_up_large = click_handlers.on_bar_up_large end
122123
if click_handlers.on_bar_down_large then vtable.on_bar_down_large = click_handlers.on_bar_down_large end
124+
if click_handlers.on_trash then vtable.on_trash = click_handlers.on_trash end
123125

124126
self:add_item(key, vtable)
125127
end

0 commit comments

Comments
 (0)