diff --git a/modules/fjei/functions.lua b/modules/fjei/functions.lua index bf18b2ed..cca03592 100644 --- a/modules/fjei/functions.lua +++ b/modules/fjei/functions.lua @@ -1,38 +1,37 @@ +local table_insert = table.insert +local string_find = string.find + local Public = {} local function is_recipe_valid(force_name, name) local force_recipes = game.forces[force_name].recipes if not force_recipes[name] then return end - if not force_recipes[name].enabled then return end - if force_recipes[name].hidden then return end return true end function Public.get_crafting_machines_for_recipe(force_name, recipe) - local crafting_machine_list = global.fjei[force_name].crafting_machines + local crafting_machines = global.fjei.crafting_machines local recipe_category = recipe.category - local machine_names = {} + local result = {} local i = 1 - for _, name in pairs(crafting_machine_list) do + for _, name in pairs(crafting_machines) do if is_recipe_valid(force_name, name) or name == "character" then local crafting_categories = game.entity_prototypes[name].crafting_categories for category, _ in pairs(crafting_categories) do if recipe_category == category then - machine_names[i] = name + result[i] = name i = i + 1 break end end end end - return machine_names + return result end -function Public.set_crafting_machines(force_name) - if not global.fjei[force_name] then global.fjei[force_name] = {} end - global.fjei[force_name].crafting_machines = {} - - local list = global.fjei[force_name].crafting_machines +local function set_crafting_machines() + global.fjei.crafting_machines = {} + local list = global.fjei.crafting_machines local i = 1 for _, prototype in pairs(game.entity_prototypes) do if prototype.crafting_categories then @@ -42,46 +41,121 @@ function Public.set_crafting_machines(force_name) end end -function Public.set_base_item_list(force_name) - if not global.fjei[force_name] then global.fjei[force_name] = {} end - global.fjei[force_name].item_list = {} - - local list = global.fjei[force_name].item_list +local function add_item_list_product(item_list, product_name, recipe_name) + if not item_list[product_name] then item_list[product_name] = {{}, {}} end + table_insert(item_list[product_name][1], recipe_name) +end + +local function add_item_list_ingredient(item_list, ingredient_name, recipe_name) + if not item_list[ingredient_name] then item_list[ingredient_name] = {{}, {}} end + table_insert(item_list[ingredient_name][2], recipe_name) +end + +local function set_item_list() + global.fjei.item_list = {} + local item_list = global.fjei.item_list + for recipe_name, recipe in pairs(game.recipe_prototypes) do + for key, product in pairs(recipe.products) do + add_item_list_product(item_list, product.name, recipe_name) + end + for key, ingredient in pairs(recipe.ingredients) do + add_item_list_ingredient(item_list, ingredient.name, recipe_name) + end + end +end + +local function set_sorted_item_list() + global.fjei.sorted_item_list = {} + local sorted_item_list = global.fjei.sorted_item_list + local item_list = global.fjei.item_list local i = 1 - for name, prototype in pairs(game.recipe_prototypes) do - if is_recipe_valid(force_name, name) then - --local machines = Public.get_crafting_machines_for_recipe(force_name, prototype) - --if #machines > 0 then - list[i] = name - i = i + 1 - --end + for key, value in pairs(item_list) do + sorted_item_list[i] = key + i = i + 1 + end + table.sort(sorted_item_list, function (a, b) return a < b end) +end + +local function add_recipe_to_whitelist(item_whitelist, recipe) + for key, product in pairs(recipe.products) do + item_whitelist[product.name] = true + end + for key, ingredient in pairs(recipe.ingredients) do + item_whitelist[ingredient.name] = true + end +end + +function Public.add_research_to_whitelist(force, effects) + if not effects then return end + local item_whitelist = global.fjei.item_whitelist[force.name] + local items_have_been_added = false + for _, effect in pairs(effects) do + if effect.recipe then + add_recipe_to_whitelist(item_whitelist, game.recipe_prototypes[effect.recipe]) + items_have_been_added = true + end + end + return items_have_been_added +end + +local function set_item_whitelist(force) + global.fjei.item_whitelist[force.name] = {} + local item_whitelist = global.fjei.item_whitelist[force.name] + + for key, recipe in pairs(game.recipe_prototypes) do + if recipe.enabled then + add_recipe_to_whitelist(item_whitelist, recipe) + end + end + + for key, technology in pairs(force.technologies) do + if technology.researched then + Public.add_research_to_whitelist(force, technology.effects) + end + end +end + +local function set_item_whitelists_for_all_forces() + global.fjei.item_whitelist = {} + for _, force in pairs(game.forces) do + if force.index ~= 2 and force.index ~= 3 then + set_item_whitelist(force) end end - table.sort(list, function (a, b) return a < b end) - global.fjei.size_of_item_list = #list end function Public.set_filtered_list(player) local player_data = global.fjei.player_data[player.index] - local active_filter = player_data.active_filter - local base_list = global.fjei[player.force.name].item_list - player_data.active_page = 1 player_data.filtered_list = {} + player_data.active_page = 1 local filtered_list = player_data.filtered_list + local active_filter = player_data.active_filter + local sorted_item_list = global.fjei.sorted_item_list + local item_whitelist = global.fjei.item_whitelist[player.force.name] + local i = 1 - for key, name in pairs(base_list) do - if active_filter then - local a, b = string.find(name, active_filter) - if a then + for key, name in pairs(sorted_item_list) do + if item_whitelist[name] then + if active_filter then + local a, b = string_find(name, active_filter) + if a then + filtered_list[i] = key + i = i + 1 + end + else filtered_list[i] = key i = i + 1 end - else - filtered_list[i] = key - i = i + 1 end end player_data.size_of_filtered_list = #player_data.filtered_list end +function Public.build_tables() + set_item_list() --creates list of all items as key and two tables for each key containing [1] product recipes and [2] ingredient recipes + set_sorted_item_list() --creates sorted list of all items in the game for faster searching + set_crafting_machines() --creates list of available crafting entities + set_item_whitelists_for_all_forces() --whitelist to only display researched items in the browser for the force +end + return Public \ No newline at end of file diff --git a/modules/fjei/gui.lua b/modules/fjei/gui.lua index 6fcc6e2c..c71a8b27 100644 --- a/modules/fjei/gui.lua +++ b/modules/fjei/gui.lua @@ -64,16 +64,14 @@ local function display_item_list(player) local active_page = global.fjei.player_data[player.index].active_page local starting_index = 1 + (active_page - 1) * items_per_page - local item_list = global.fjei[player.force.name].item_list + local sorted_item_list = global.fjei.sorted_item_list local filtered_list = global.fjei.player_data[player.index].filtered_list local item_list_table = player.gui.left.fjei_main_window.fjei_main_window_item_list_table item_list_table.clear() for i = starting_index, starting_index + items_per_page - 1, 1 do if not filtered_list[i] then return end - local item_key = filtered_list[i] - if not item_list[item_key] then return end - add_recipe_icon(item_list_table, item_list[item_key], true) + add_recipe_icon(item_list_table, sorted_item_list[filtered_list[i]], false) end end @@ -142,12 +140,21 @@ local function draw_main_window(player) Public.refresh_main_window(player) end -local function create_recipe_window(recipe_name, player, button) - local recipe = game.recipe_prototypes[recipe_name] - if not recipe then return end - +local function create_recipe_window(item_name, player, button) + local recipes + local category_string + if button == defines.mouse_button_type.left then + recipes = global.fjei.item_list[item_name][1] + category_string = "Product of" + else + recipes = global.fjei.item_list[item_name][2] + category_string = "Ingredient in" + end + if #recipes == 0 then return end + if player.gui.center["fjei_recipe_window"] then player.gui.center["fjei_recipe_window"].destroy() end + local recipe = game.recipe_prototypes[recipes[1]] local machines = Functions.get_crafting_machines_for_recipe(player.force.name, recipe) local products = recipe.products local ingredients = recipe.ingredients @@ -249,38 +256,40 @@ local function toggle_main_window(element, player, button) end local function main_window_next_page(element, player, button) + local player_data = global.fjei.player_data[player.index] if button == defines.mouse_button_type.right then for _ = 1, 5, 1 do - if global.fjei.player_data[player.index].active_page == get_total_page_count(player) then - global.fjei.player_data[player.index].active_page = 1 + if player_data.active_page == get_total_page_count(player) then + player_data.active_page = 1 else - global.fjei.player_data[player.index].active_page = global.fjei.player_data[player.index].active_page + 1 + player_data.active_page = player_data.active_page + 1 end end else - if global.fjei.player_data[player.index].active_page == get_total_page_count(player) then - global.fjei.player_data[player.index].active_page = 1 + if player_data.active_page == get_total_page_count(player) then + player_data.active_page = 1 else - global.fjei.player_data[player.index].active_page = global.fjei.player_data[player.index].active_page + 1 + player_data.active_page = player_data.active_page + 1 end end Public.refresh_main_window(player) end local function main_window_previous_page(element, player, button) + local player_data = global.fjei.player_data[player.index] if button == defines.mouse_button_type.right then for _ = 1, 5, 1 do - if global.fjei.player_data[player.index].active_page == 1 then - global.fjei.player_data[player.index].active_page = get_total_page_count(player) + if player_data.active_page == 1 then + player_data.active_page = get_total_page_count(player) else - global.fjei.player_data[player.index].active_page = global.fjei.player_data[player.index].active_page - 1 + player_data.active_page = player_data.active_page - 1 end end else - if global.fjei.player_data[player.index].active_page == 1 then - global.fjei.player_data[player.index].active_page = get_total_page_count(player) + if player_data.active_page == 1 then + player_data.active_page = get_total_page_count(player) else - global.fjei.player_data[player.index].active_page = global.fjei.player_data[player.index].active_page - 1 + player_data.active_page = player_data.active_page - 1 end end Public.refresh_main_window(player) @@ -320,29 +329,29 @@ function Public.draw_top_toggle_button(player) button.style.padding = -2 end -local function add_to_history(recipe_name, player) - if not game.recipe_prototypes[recipe_name] then return end +local function add_to_history(item_name, player) + --if not game.recipe_prototypes[recipe_name] then return end local player_data = global.fjei.player_data[player.index] if not player_data.history then - player_data.history = {recipe_name} + player_data.history = {item_name} player_data.size_of_history = 1 return end --avoid double elements for _, v in pairs(player_data.history) do - if v == recipe_name then return end + if v == item_name then return end end player_data.size_of_history = player_data.size_of_history + 1 - player_data.history[player_data.size_of_history] = recipe_name + player_data.history[player_data.size_of_history] = item_name if player_data.size_of_history > column_count then player_data.history[player_data.size_of_history - column_count] = nil end end -function Public.open_recipe(recipe_name, player, button) - add_to_history(recipe_name, player) - create_recipe_window(recipe_name, player, button) +function Public.open_recipe(item_name, player, button) + add_to_history(item_name, player) + create_recipe_window(item_name, player, button) display_history(player) end diff --git a/modules/fjei/main.lua b/modules/fjei/main.lua index 90f8ade7..ce3c5946 100644 --- a/modules/fjei/main.lua +++ b/modules/fjei/main.lua @@ -9,8 +9,6 @@ local Functions = require "modules.fjei.functions" local function on_player_joined_game(event) local player = game.players[event.player_index] if not global.fjei.player_data[player.index] then global.fjei.player_data[player.index] = {} end - Functions.set_crafting_machines(player.force.name) - Functions.set_base_item_list(player.force.name) Gui.draw_top_toggle_button(player) end @@ -22,11 +20,10 @@ local function on_player_left_game(event) end local function on_research_finished(event) - local force_name = event.research.force.name - Functions.set_crafting_machines(force_name) - Functions.set_base_item_list(force_name) - for _, player in pairs(game.connected_players) do - global.fjei.player_data[player.index].filtered_list = nil + if not Functions.add_research_to_whitelist(event.research.force, event.research.effects) then return end + local player_data = global.fjei.player_data + for _, player in pairs(event.research.force.connected_players) do + player_data[player.index].filtered_list = nil Gui.refresh_main_window(player) end end @@ -71,11 +68,14 @@ local function on_gui_text_changed(event) Gui.refresh_main_window(player) end -local function on_init() +local function on_init() global.fjei = {} global.fjei.player_data = {} + Functions.build_tables() end +--script.on_configuration_changed(Functions.build_tables()) + local event = require "utils.event" event.add(defines.events.on_player_joined_game, on_player_joined_game) event.add(defines.events.on_player_left_game, on_player_left_game)