1
0
mirror of https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git synced 2024-12-12 10:13:58 +02:00

More moddifng functionality. Some reduced debug logs.

This commit is contained in:
Oarcinae 2024-12-05 21:01:09 -05:00
parent fb52af346f
commit 07295f6a17
6 changed files with 190 additions and 45 deletions

View File

@ -1,4 +1,5 @@
-- To edit this scenario, you must make a copy of it and place it in your own scenarios folder first! -- To edit this scenario, you must make a copy of it and place it in your own scenarios folder first!
-- Alternatively, you can make a dependent mod based on this as well.
-- I provide this empty scenario to avoid the freeplay scenario extra baggage and as a template for how to modify the -- I provide this empty scenario to avoid the freeplay scenario extra baggage and as a template for how to modify the
-- settings on init. You can use the freeplay scenario too just fine if you want. -- settings on init. You can use the freeplay scenario too just fine if you want.
@ -13,19 +14,14 @@
-- Alternatively, you can use the in-game "export" button to get a string of all settings that you can then format -- Alternatively, you can use the in-game "export" button to get a string of all settings that you can then format
-- and edit however you want to use here. -- and edit however you want to use here.
-- ANY CONFIG HERE WILL OVERWRITE MOD SETTINGS! This is the whole point. ----------------------------------------------------------------------------------------------------------------
-- In order to modify the settings of the OARC mod, you need to implement the following section.
-- Check if the OARC mod is loaded. Other than that, it's an empty scenario! -- I need to insert any settings overrides before I run my mod's other init functions so this is why I do it
script.on_init(function(event) -- this way! If I let you overwrite config at a later time, it may have no effect or might cause other issues.
if not script.active_mods["oarc-mod"] then -- You should only be modifying the section as described below. Don't modify the rest of this interface.
error("OARC mod not found! This scenario is intended to be run with the OARC mod!") --
end -- You can implement this in a scenario OR a mod (despite the name).
----------------------------------------------------------------------------------------------------------------
storage.ocfg_copy = remote.call("oarc_mod", "get_mod_settings")
log("server info test: ")
end)
local oarc_scenario_interface = local oarc_scenario_interface =
{ {
get_scenario_settings = function() get_scenario_settings = function()
@ -35,6 +31,7 @@ local oarc_scenario_interface =
-- Overwrite whatever settings you want here: -- Overwrite whatever settings you want here:
-- If you provide an invalid value for a mod setting, it will error and not load the scenario. -- If you provide an invalid value for a mod setting, it will error and not load the scenario.
-- ANY CONFIG HERE WILL OVERWRITE MOD SETTINGS! This is the whole point.
---------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------
modified_settings.server_info.welcome_msg_title = "THIS IS A TEMPLATE SCENARIO" modified_settings.server_info.welcome_msg_title = "THIS IS A TEMPLATE SCENARIO"
modified_settings.server_info.welcome_msg = "This is a template scenario. You can modify the settings in the control.lua file. If you are seeing this message, you did not modify the scenario correctly." modified_settings.server_info.welcome_msg = "This is a template scenario. You can modify the settings in the control.lua file. If you are seeing this message, you did not modify the scenario correctly."
@ -51,19 +48,34 @@ local oarc_scenario_interface =
} }
remote.add_interface("oarc_scenario", oarc_scenario_interface) remote.add_interface("oarc_scenario", oarc_scenario_interface)
----------------------------------------------------------------------------------------------------------------
-- End of settings override section.
----------------------------------------------------------------------------------------------------------------
-- Check if the OARC mod is loaded. Other than that, it's an empty scenario! You can modify it however you want.
script.on_init(function(event)
if not script.active_mods["oarc-mod"] then
error("OARC mod not found! This scenario is intended to be run with the OARC mod!")
end
-- Please note: a scenario can NOT call this during on_init because you can't set load order for a scenario!
-- You just get nil back. If you are making a mod, you can use this to get the config during on_init.
-- storage.ocfg_copy = remote.call("oarc_mod", "get_mod_settings")
-- See the oarc-mod-on-config-changed event for how to keep the config up to date.
end)
---------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------
-- Everything below here is an example of how to use the custom events provided by the OARC mod. -- This section shows an example of how to customize the spawn gui options presented to the player, and how to
-- use that to customize the spawn area generation process.
---------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------
local util = require("util") local util = require("util") -- Only needed for the distance function in this example.
-- You can require files to use them if you want like this. (Ignore the diagnostic warning.) -- You can require files to use them if you want like this. (Ignore the diagnostic warning.)
---@diagnostic disable-next-line: different-requires ---@diagnostic disable-next-line: different-requires
require("__oarc-mod__/lib/oarc_gui_utils") require("__oarc-mod__/lib/oarc_gui_utils") -- I have a helper function in here for creating GUI elements.
-- This will keep a local copy of the mod's config so you can use it in your custom events. -- This will keep a local copy of the mod's config so you can use it in your custom events.
script.on_event("oarc-mod-on-config-changed", function(event) script.on_event("oarc-mod-on-config-changed", function(event)
@ -133,6 +145,10 @@ script.on_event("oarc-mod-on-chunk-generated-near-spawn", function(event)
custom_event.surface.set_tiles(tiles) custom_event.surface.set_tiles(tiles)
end) end)
----------------------------------------------------------------------------------------------------------------
-- This section just supports the above events.
----------------------------------------------------------------------------------------------------------------
---A helper function to create a dropdown for selecting tiles ---A helper function to create a dropdown for selecting tiles
---@param parent_flow LuaGuiElement ---@param parent_flow LuaGuiElement
---@return nil ---@return nil
@ -214,4 +230,80 @@ script.on_event(defines.events.on_gui_selection_state_changed, function(event)
if not event.element.valid then return end if not event.element.valid then return end
CustomSpawnOptsSelectionChanged(event) CustomSpawnOptsSelectionChanged(event)
end)
----------------------------------------------------------------------------------------------------------------
-- This section shows how to add a custom tab to the Oarc Mod GUI (the top left button).
----------------------------------------------------------------------------------------------------------------
local CUSTOM_TAB_NAME = "Test Mod"
script.on_event("oarc-mod-on-mod-top-left-gui-created", function(event --[[@as OarcModOnModTopLeftGuiCreatedEvent]])
-- Create a custom empty tab:
remote.call("oarc_mod", "create_custom_gui_tab", game.players[event.player_index], CUSTOM_TAB_NAME)
-- Get the tab content element
local tab_content = remote.call("oarc_mod", "get_custom_gui_tab_content_element", game.players[event.player_index], CUSTOM_TAB_NAME)
-- Save a reference to that tab content for later use, if it becomes nil you can ask for it again.
-- Or you can just always ask for it when you need it, depends on how often you plan to use it.
if storage.custom_tabs_table == nil then
storage.custom_tabs_table = {}
end
storage.custom_tabs_table[event.player_index] = {content = tab_content, example_data = 0}
-- Use the element to add content directly to it.
CreateExampleCustomTabContent(tab_content, tostring(0))
end)
---Creates the test tab content, just adds a couple of text labels and a button as an example.
---@param tab_container LuaGuiElement
---@param example_data string
---@return nil
function CreateExampleCustomTabContent(tab_container, example_data)
tab_container.clear()
tab_container.add {
type = "label",
caption = "This is a test tab to demonstrate how to add tabs to the Oarc Mod GUI.",
style = "caption_label"
}
tab_container.add {
type = "label",
caption = "This tab has been clicked " .. example_data .. " times.",
style = "caption_label"
}
tab_container.add {
type = "button",
caption = "Click Me!",
style = "button",
name = "test_mod_button",
tags = { test_mod_button = true } -- Learn to use tags, this is great for identifying where GUI events came from.
}
end
-- This is the event that is triggered when a player selects a tab (on ANY tabbed pane)
script.on_event(defines.events.on_gui_selected_tab_changed, function (event)
if (event.element.name ~= "oarc_tabs") then return end -- This is what I have named my tabbed pane in my mod.
-- Check if your custom tab was selected
local tab_name = event.element.tabs[event.element.selected_tab_index].tab.name
if (tab_name ~= "Test Mod") then return end
log("Selected Test Mod tab")
-- Proof of concept that shows you can update/change the content of your custom tab when it is selected.
local entry = storage.custom_tabs_table[event.player_index]
entry.example_data = entry.example_data + 1
CreateExampleCustomTabContent(entry.content, tostring(entry.example_data))
end)
-- This is the event that is triggered when a player clicks a button in the GUI (on ANY GUI)
script.on_event(defines.events.on_gui_click, function (event)
-- Check if the button clicked was yours, how you can identify it is up to you, but tags are a good way.
if event.element.tags and event.element.tags.test_mod_button then
log("Test Mod button clicked!")
game.players[event.player_index].print("Test Mod button clicked!")
end
end) end)

View File

@ -3,6 +3,11 @@ Version: 2.1.17
Date: ???? Date: ????
Bugfixes: Bugfixes:
- Fix incorrect names printed for infinite technology research. - Fix incorrect names printed for infinite technology research.
Info:
- Add more info to the template scenario to help with understanding how to override settings.
- Disable some of the extra debug logging.
Modding:
- Add remote interfaces to add custom tabs to the top left GUI. Updated template scenario to show how to use the new features.
--------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------
Version: 2.1.16 Version: 2.1.16
Date: 2024-12-03 Date: 2024-12-03

View File

@ -116,10 +116,10 @@ end)
-- SeparateSpawnsPlayerChangedSurface(event) -- SeparateSpawnsPlayerChangedSurface(event)
-- end) -- end)
script.on_event(defines.events.on_rocket_launched, function(event) -- script.on_event(defines.events.on_rocket_launched, function(event)
log("Rocket launched!") -- log("Rocket launched!")
log(serpent.block(event)) -- log(serpent.block(event))
end) -- end)
script.on_event(defines.events.on_player_driving_changed_state, function (event) script.on_event(defines.events.on_player_driving_changed_state, function (event)
local entity = event.entity local entity = event.entity
@ -130,19 +130,11 @@ script.on_event(defines.events.on_player_driving_changed_state, function (event)
RegrowthMarkAreaSafeGivenTilePos(entity.surface.name, entity.position, 1, false) RegrowthMarkAreaSafeGivenTilePos(entity.surface.name, entity.position, 1, false)
end end
log("Player driving changed state")
log(serpent.block(event))
-- Track the surfaces whenever driving state changes for a cargo-pod ONLY. -- Track the surfaces whenever driving state changes for a cargo-pod ONLY.
-- This triggers events for surface changes when using the standard space travel method. -- This triggers events for surface changes when using the standard space travel method.
if (entity ~= nil) and (entity.name == "cargo-pod") then if (entity ~= nil) and (entity.name == "cargo-pod") then
local player = game.players[event.player_index] local player = game.players[event.player_index]
-- Check if driving flag is set
if (player.driving) then
log("Player is driving a cargo-pod")
end
SeparateSpawnsUpdatePlayerSurface(player, entity.surface.name) SeparateSpawnsUpdatePlayerSurface(player, entity.surface.name)
end end
end) end)
@ -184,10 +176,10 @@ end)
---@class OarcModOnSpawnChoicesGuiDisplayedEvent: OarcCustomEventBase ---@class OarcModOnSpawnChoicesGuiDisplayedEvent: OarcCustomEventBase
---@field player_index integer ---@field player_index integer
---@field gui_element LuaGuiElement ---@field gui_element LuaGuiElement
script.on_event("oarc-mod-on-spawn-choices-gui-displayed", function(event) -- script.on_event("oarc-mod-on-spawn-choices-gui-displayed", function(event)
log("EVENT - oarc-mod-on-spawn-choices-gui-displayed:" .. serpent.block(event --[[@as OarcModOnSpawnChoicesGuiDisplayedEvent]])) -- log("EVENT - oarc-mod-on-spawn-choices-gui-displayed:" .. serpent.block(event --[[@as OarcModOnSpawnChoicesGuiDisplayedEvent]]))
-- The 4 main sub sections are called: spawn_settings_frame, solo_spawn_frame, shared_spawn_frame, and buddy_spawn_frame -- -- The 4 main sub sections are called: spawn_settings_frame, solo_spawn_frame, shared_spawn_frame, and buddy_spawn_frame
end) -- end)
---@class OarcModOnSpawnCreatedEvent: OarcCustomEventBase ---@class OarcModOnSpawnCreatedEvent: OarcCustomEventBase
@ -221,8 +213,6 @@ end)
---@field old_surface_name string ---@field old_surface_name string
---@field new_surface_name string ---@field new_surface_name string
script.on_event("oarc-mod-character-surface-changed", function(event) script.on_event("oarc-mod-character-surface-changed", function(event)
log("EVENT - oarc-mod-character-surface-changed:" .. serpent.block(event --[[@as OarcModCharacterSurfaceChangedEvent]]))
--This is just here so I don't get lua warnings about unused variables. --This is just here so I don't get lua warnings about unused variables.
---@type OarcModCharacterSurfaceChangedEvent ---@type OarcModCharacterSurfaceChangedEvent
local custom_event = event --[[@as OarcModCharacterSurfaceChangedEvent]] local custom_event = event --[[@as OarcModCharacterSurfaceChangedEvent]]
@ -231,22 +221,28 @@ script.on_event("oarc-mod-character-surface-changed", function(event)
SeparateSpawnsPlayerChangedSurface(player, custom_event.old_surface_name, custom_event.new_surface_name) SeparateSpawnsPlayerChangedSurface(player, custom_event.old_surface_name, custom_event.new_surface_name)
end) end)
-- I wouldn't recommend any logging inside this event as it is called for every chunk generated near a spawn.
---@class OarcModOnChunkGeneratedNearSpawnEvent: OarcCustomEventBase ---@class OarcModOnChunkGeneratedNearSpawnEvent: OarcCustomEventBase
---@field surface LuaSurface ---@field surface LuaSurface
---@field chunk_area BoundingBox ---@field chunk_area BoundingBox
---@field spawn_data OarcUniqueSpawn ---@field spawn_data OarcUniqueSpawn
-- script.on_event("oarc-mod-on-chunk-generated-near-spawn", function(event) -- script.on_event("oarc-mod-on-chunk-generated-near-spawn", function(event)
-- I wouldn't recommend any logging inside this event as it is called for every chunk generated near a spawn.
-- log("EVENT - oarc-mod-on-chunk-generated-near-spawn:" .. serpent.block(event --[[@as OarcModOnChunkGeneratedNearSpawnEvent]])) -- log("EVENT - oarc-mod-on-chunk-generated-near-spawn:" .. serpent.block(event --[[@as OarcModOnChunkGeneratedNearSpawnEvent]]))
-- end) -- end)
-- This can get called quite a lot during init or importing of settings.
---@class OarcModOnConfigChangedEvent: OarcCustomEventBase ---@class OarcModOnConfigChangedEvent: OarcCustomEventBase
-- script.on_event("oarc-mod-on-config-changed", function(event) -- script.on_event("oarc-mod-on-config-changed", function(event)
-- This can get called quite a lot during init or importing of settings.
-- log("EVENT - oarc-mod-on-config-changed:" .. serpent.block(event --[[@as OarcModOnConfigChangedEvent]])) -- log("EVENT - oarc-mod-on-config-changed:" .. serpent.block(event --[[@as OarcModOnConfigChangedEvent]]))
-- end) -- end)
-- I raise this event whenever teleporting the player! ---@class OarcModOnModTopLeftGuiCreatedEvent: OarcCustomEventBase
---@field player_index integer
-- script.on_event("oarc-mod-on-mod-top-left-gui-created", function(event)
-- log("EVENT - oarc-mod-on-mod-top-left-gui-created:" .. serpent.block(event --[[@as OarcModOnModTopLeftGuiCreatedEvent]]))
-- end)
-- I raise this event whenever teleporting the player, and it is used to update the player's surface.
script.on_event(defines.events.script_raised_teleported, function(event) script.on_event(defines.events.script_raised_teleported, function(event)
local entity = event.entity local entity = event.entity
if entity.type == "character" and entity.player then if entity.type == "character" and entity.player then
@ -507,6 +503,14 @@ local oarc_mod_interface =
get_player_primary_spawn = function(player_name) get_player_primary_spawn = function(player_name)
return FindPrimaryUniqueSpawn(player_name) return FindPrimaryUniqueSpawn(player_name)
end, end,
create_custom_gui_tab = function(player, tab_name)
AddCustomOarcGuiTab(player, tab_name)
end,
get_custom_gui_tab_content_element = function(player, tab_name)
return OarcGuiGetTabContentElement(player, tab_name)
end,
} }
remote.add_interface("oarc_mod", oarc_mod_interface) remote.add_interface("oarc_mod", oarc_mod_interface)

View File

@ -74,6 +74,12 @@ data:extend({
type = "custom-event", type = "custom-event",
name = "oarc-mod-on-config-changed", name = "oarc-mod-on-config-changed",
}, },
-- A player's custom GUI panel (top right special button) was created
{
type = "custom-event",
name = "oarc-mod-on-mod-top-left-gui-created",
},
}) })

View File

@ -101,6 +101,9 @@ function InitOarcGuiTabs(player)
SetOarcGuiTabEnabled(player, OARC_SURFACE_CONFIG_TAB_NAME, true) SetOarcGuiTabEnabled(player, OARC_SURFACE_CONFIG_TAB_NAME, true)
end end
-- Let other mods know the top left GUI was created, this is a good time to add buttons to it.
script.raise_event("oarc-mod-on-mod-top-left-gui-created", {player_index = player.index})
HideOarcGui(player) HideOarcGui(player)
end end
@ -201,13 +204,31 @@ function OarcGuiCreateContentOfTab(player)
-- log("OarcGuiCreateContentOfTab: " .. tab_name) -- log("OarcGuiCreateContentOfTab: " .. tab_name)
for _,t in ipairs(otabs.tabs) do for _,t in ipairs(otabs.tabs) do
t.content.clear() if (OARC_GUI_TAB_CONTENT[t.tab.name] ~= nil) then -- Only clear my own tabs.
if (t.tab.name == tab_name) then t.content.clear()
OARC_GUI_TAB_CONTENT[tab_name].create_tab_function(t.content, player) if (t.tab.name == tab_name) then
OARC_GUI_TAB_CONTENT[tab_name].create_tab_function(t.content, player)
end
end end
end end
end end
---Gets the content element of the named tab.
---@param player LuaPlayer
---@param tab_name string
---@return LuaGuiElement?
function OarcGuiGetTabContentElement(player, tab_name)
local otabs = GetOarcGuiTabsPane(player)
if (otabs == nil) then return nil end
for _,t in ipairs(otabs.tabs) do
if (t.tab.name == tab_name) then
return t.content
end
end
return nil
end
---Just an alias for OarcGuiCreateContentOfTab ---Just an alias for OarcGuiCreateContentOfTab
---@param player LuaPlayer ---@param player LuaPlayer
---@return nil ---@return nil
@ -270,7 +291,8 @@ end
-- It adds whatever it wants to the provided scroll-pane. -- It adds whatever it wants to the provided scroll-pane.
---@param player LuaPlayer ---@param player LuaPlayer
---@param tab_name string ---@param tab_name string
function AddOarcGuiTab(player, tab_name) ---@param localized_name LocalisedString
function AddOarcGuiTabWrapper(player, tab_name, localized_name)
if (not DoesOarcGuiExist(player)) then if (not DoesOarcGuiExist(player)) then
CreateOarcGuiTabsPane(player) CreateOarcGuiTabsPane(player)
end end
@ -284,7 +306,7 @@ function AddOarcGuiTab(player, tab_name)
local new_tab = otabs.add{ local new_tab = otabs.add{
type="tab", type="tab",
name=tab_name, name=tab_name,
caption=OARC_GUI_TAB_CONTENT[tab_name].localized_name,} caption=localized_name}
-- Create inside frame for content -- Create inside frame for content
local tab_inside_frame = otabs.add{ local tab_inside_frame = otabs.add{
@ -314,6 +336,13 @@ function AddOarcGuiTab(player, tab_name)
end end
end end
-- Uses AddOarcGuiTabWrapper to add my own tabs using OARC_GUI_TAB_CONTENT for the localized name.
---@param player LuaPlayer
---@param tab_name string
function AddOarcGuiTab(player, tab_name)
AddOarcGuiTabWrapper(player, tab_name, OARC_GUI_TAB_CONTENT[tab_name].localized_name)
end
-- https://forums.factorio.com/viewtopic.php?f=7&t=115901 -- https://forums.factorio.com/viewtopic.php?f=7&t=115901
-- ---Removes a tab from the GUI. -- ---Removes a tab from the GUI.
-- ---@param player LuaPlayer -- ---@param player LuaPlayer
@ -428,6 +457,16 @@ function AddRemoveOarcGuiTabForAllPlayers(tab_name, add, enable)
end end
end end
-- Lets other mods add their own tabs to the OARC GUI.
---@param player LuaPlayer
---@param tab_name string
function AddCustomOarcGuiTab(player, tab_name)
AddOarcGuiTabWrapper(player, tab_name, tab_name)
SetOarcGuiTabEnabled(player, tab_name, true)
end
--[[ --[[
_____ _____ _ _ _____ _ _ _ _ _ ___ _ ___ ___ ___ _____ _____ _ _ _____ _ _ _ _ _ ___ _ ___ ___ ___
| __\ \ / / __| \| |_ _| | || | /_\ | \| | \| | | __| _ \/ __| | __\ \ / / __| \| |_ _| | || | /_\ | \| | \| | | __| _ \/ __|

View File

@ -28,10 +28,9 @@ function InitSpawnGlobalsAndForces()
end end
SeparateSpawnsInitPlanets() SeparateSpawnsInitPlanets()
-- This contains each player's respawn point. Literally where they will respawn on death -- This contains each player's respawn point for each surface. Literally where they will respawn on death
-- There is a way in game to change this under one of the little menu features I added. This allows players to -- There is a way in game to change this under one of the little menu features I added. This allows players to
-- change their respawn point to something other than their home base. -- change their respawn point to something other than their home base.
-- TODO: Space Age will potentially affect this, as I may need to allow for multiple respawn points on different surfaces.
--[[@type OarcPlayerRespawnsTable]] --[[@type OarcPlayerRespawnsTable]]
storage.player_respawns = {} storage.player_respawns = {}
@ -52,7 +51,7 @@ function InitSpawnGlobalsAndForces()
storage.delayed_spawns = {} storage.delayed_spawns = {}
-- This stores the spawn choices that a player makes from the GUI interactions. -- This stores the spawn choices that a player makes from the GUI interactions.
-- Intended to be re-used for secondary spawns! (TODO SPACE AGE) -- Intended to be re-used for secondary spawns!
--[[@type OarcSpawnChoicesTable]] --[[@type OarcSpawnChoicesTable]]
storage.spawn_choices = {} storage.spawn_choices = {}