Help Retrieving List of Vehicles/Trains

Place to get help with not working mods / modding interface.
Pikachar
Burner Inserter
Burner Inserter
Posts: 16
Joined: Wed Apr 19, 2023 9:16 pm
Contact:

Help Retrieving List of Vehicles/Trains

Post by Pikachar »

Currently working on updating one of the mods I've taken over: https://mods.factorio.com/mod/PersonalTransformer2
And I'm trying to update it so that it works when placed in vehicle/train grids.

The problem I'm running into is in finding a good (ideally the right) way to get a list of all of the vehicles/trains that doesn't absolutely destroy UPS.
Currently I've tried using Forces and Surface. And from what I could tell, LuaSurface drops UPS to near 0 when nothing is going on. And LuaForces seemed to not return anything usable (maybe I was using it incorrectly).

If anyone could direct me to a better solution, it would be greatly appreciated.

User avatar
Silari
Filter Inserter
Filter Inserter
Posts: 526
Joined: Sat Jan 27, 2018 10:04 pm
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Silari »

Why do you need to list all trains in the first place?

You only need to interact with ones that have your equipment in them, and you should be able to track those with the equipment events: on_equipment_inserted and on_player_placed_equipment.

You might need to search for all in a on_init/on_config_changed to update the list if something changes but those are one-time events so you can use the find_entities commands even if they take a little bit.

Pikachar
Burner Inserter
Burner Inserter
Posts: 16
Joined: Wed Apr 19, 2023 9:16 pm
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Pikachar »

So, if I'm understanding you correctly:
- I should use 'on_equipment_inserted' and 'on_player_placed_equipment' to get each individual train/vehicle that gets equipment inserted.
- Probably save that list to global, so that it persists through saves.
- 'on_init' (load game) load list into my variable FROM global
- Do what I need to do with my list.

Does that about track?

User avatar
Silari
Filter Inserter
Filter Inserter
Posts: 526
Joined: Sat Jan 27, 2018 10:04 pm
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Silari »

Pikachar wrote:
Thu Apr 20, 2023 4:21 pm
- 'on_init' (load game) load list into my variable FROM global
Not that part. You don't need to load things from global, as the point of global is that it is persistent between save/loads and is handled by the engine. Just save a list of trains to it and it'll be there forever for that save unless you delete it yourself.

A search on_init would only be needed if there was something you had to do to trains that existed before your mod was added - remember that mods can be added midgame and generally they should try and account for that. Since it seems the mod is solely based on having a piece of equipment from the mod, no trains should HAVE that equipment so you likely won't need anything for that.

Pikachar
Burner Inserter
Burner Inserter
Posts: 16
Joined: Wed Apr 19, 2023 9:16 pm
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Pikachar »

For the global part, right. That's what I was thinking, I just may have misstated.

I do have a question on how the events.... work. I'm a little confused on the syntax of how that works.

The API says that on_equipment_inserted has (grid, equipment, name, tick),
and the example for using the events in the wiki uses something similar to this:

Code: Select all

script.on_event(defines.events.on_equipment_inserted,
	function()
--stuff to do
	end)
How do I use the previously stated variables from the API? Are they parameters to on_event? are they return values? I'm a little unclear about that.

Another question that came up is how do I actually obtain the owner of the grid? (player, spidertron, other assorted trains/vehicles) Because I don't really see how I would do that.

User avatar
Silari
Filter Inserter
Filter Inserter
Posts: 526
Joined: Sat Jan 27, 2018 10:04 pm
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Silari »

The function that gets called should have a parameter, usually called event though that's not required, because the engine calls the function with one parameter - this is a table that has fields for whatever data the event has. If you haven't you should really go over the tutorials on the wiki: https://wiki.factorio.com/Tutorial:Modding_tutorial

For the second question, it looks like there isn't one. I was expecting an equipment grid to reference it's owner - many other things in the games do, like LuaInventory. That's a problem.

Pikachar
Burner Inserter
Burner Inserter
Posts: 16
Joined: Wed Apr 19, 2023 9:16 pm
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Pikachar »

Silari wrote:
Sat Apr 22, 2023 4:15 am
For the second question, it looks like there isn't one. I was expecting an equipment grid to reference it's owner - many other things in the games do, like LuaInventory. That's a problem.
Which I guess brings me back to the first question, of "What's the best way to get a list of vehicles/trains?"

Pi-C
Smart Inserter
Smart Inserter
Posts: 1720
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Pi-C »

Silari wrote:
Sat Apr 22, 2023 4:15 am
For the second question, it looks like there isn't one. I was expecting an equipment grid to reference it's owner - many other things in the games do, like LuaInventory. That's a problem.
Since Factorio 1.1.63, we have LuaEquipmentGrid::unique_id. I had a similar problem where I needed to map grids to the cars/spider-vehicles that owned them (see this thread). I added a migration file that would look for all existing vehicles of the prototypes I need, fetched the unique_id of their equipment grids, and stored them as

Code: Select all

global.grids[LuaEquipmentGrid.unique_id] = LuaEntity.unit_number
Also, I listen to on_built_entity, on_entity_cloned, script_raised_built, and script_raised_revive; whenever a new vehicle is created, I store its grid ID in the same manner. Whenever one of the equipment-grid events is triggered, I check whether the grid ID is in my table and get the unit_number of the entity it belongs to.
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

Pikachar
Burner Inserter
Burner Inserter
Posts: 16
Joined: Wed Apr 19, 2023 9:16 pm
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Pikachar »

Pi-C wrote:
Sat Apr 22, 2023 7:33 am
I added a migration file that would look for all existing vehicles of the prototypes I need, fetched the unique_id of their equipment grids, and stored them as

Code: Select all

global.grids[LuaEquipmentGrid.unique_id] = LuaEntity.unit_number
Right, but how exactly did you get the list of all existing vehicles? The only way I can think of to do it is incredibly slow. And just to make sure I'm understanding correctly, you're keeping track of them in a table of {gridID, entityUniqueIdentifier}.

Pi-C wrote:
Sat Apr 22, 2023 7:33 am
Also, I listen to on_built_entity, on_entity_cloned, script_raised_built, and script_raised_revive; whenever a new vehicle is created, I store its grid ID in the same manner. Whenever one of the equipment-grid events is triggered, I check whether the grid ID is in my table and get the unit_number of the entity it belongs to.
When do these particular events occur exactly?
on_built_entity - is this on entity placement? is it just by the player or also by say robots?
on_entity_cloned - When exactly does cloning occur? Is this when a copy/pasta is made, or a blueprint is made, or both? Or is it just blueprint placement?
script_raised_built, and script_raised_revive - not sure that I would personally need these for what I'm trying to so since I'm not telling anything to build/revive. But good to know about.

Pi-C
Smart Inserter
Smart Inserter
Posts: 1720
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Pi-C »

Pikachar wrote:
Sun Apr 23, 2023 3:47 am
Pi-C wrote:
Sat Apr 22, 2023 7:33 am
I added a migration file that would look for all existing vehicles of the prototypes I need, fetched the unique_id of their equipment grids, and stored them as

Code: Select all

global.grids[LuaEquipmentGrid.unique_id] = LuaEntity.unit_number
Right, but how exactly did you get the list of all existing vehicles? The only way I can think of to do it is incredibly slow.
If you add a migration file, it will be run only once in each game. Looking for all entities may take a while but that's OK if it's only done once. This is how I would do it:

Code: Select all

local my_types = {"car", "spider-vehicle"}
local grid
global.grids = global.grids or {}

for s, surface in pairs(game.surfaces) do
	for v, vehicle in pairs(surface.find_entities_filtered{type = my_types}) do
		grid = vehicle.grid
		if grid and grid.valid then
			global.grids[grid.unique_id] = vehicle.unit_number
		end
	end
end
And just to make sure I'm understanding correctly, you're keeping track of them in a table of {gridID, entityUniqueIdentifier}.
I thought I did, but I've actually used

Code: Select all

global.grids[grid.unique_id] = vehicle
This has the advantage that grids from vehicles that have been destroyed or mined will automatically be removed from global.grids. You actually need an entity, the unit_number is only useful if you can look up the entity from it. But I've another table for storing all vehicles currently handled by my mod:

Code: Select all

global.vehicles[vehicle.unit_number = {
	entity = vehicle,
	id = vehicle.unit_number,
	grid_id = vehicle.grid and vehicle.grid.valid and vehicle.grid.unique_id,
	…,
}
So, if defines.events.on_equipment_inserted was triggered, this is how I would get the entity associated with that grid via unit_number:

Code: Select all

script.on_event(defines.events.on_equipment_inserted, function(event)
	local grid_id = event.grid.unique_id
	local unit_number = global.grids[grid_id]
	local vehicle =  unit_number and global.vehicles[unit_number] and global.vehicles[unit_number].entity
	
	if vehicle and vehicle.valid then
		-- 
	end
end)
This would be useful because most of my functions deal with the data I've stored with the vehicle, not the vehicle itself, so storing grid.unique_id together with vehicle.unit_number would allow me faster access to the data stored in global.vehicles[vehicle.unit_number]. The disadvantage is that I must manually remove entries from global.grids when an entity is destroyed, mined, etc.
When do these particular events occur exactly?
on_built_entity - is this on entity placement? is it just by the player or also by say robots?
This is called when a player or a bot place an entity.
on_entity_cloned - When exactly does cloning occur? Is this when a copy/pasta is made, or a blueprint is made, or both? Or is it just blueprint placement?
This is raised by LuaSurface.clone_entities.
script_raised_built, and script_raised_revive - not sure that I would personally need these for what I'm trying to so since I'm not telling anything to build/revive. But good to know about.
These events are for interaction of mods. For example, my mod could silently create an entity:

Code: Select all

local pos = {player.position.x + 10, player.position.y}
player.surface.create_entity{name = "car", position = pos, force = player.force}
Your mod would never know about this, so you couldn't update your grid table. But I could raise an event when I create my car, so all other mods who listen to script_raised_built can do whatever they need with it:

Code: Select all

local pos = {player.position.x + 10, player.position.y}
player.surface.create_entity{name = "car", position = pos, force = player.force, raise_built = true}
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

Pikachar
Burner Inserter
Burner Inserter
Posts: 16
Joined: Wed Apr 19, 2023 9:16 pm
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Pikachar »

All of this has been incredibly helpful.

I am wondering though, if it's possible to update an entity after it's created?
For example, if I have this entity:

Code: Select all

{
	type = 'electric-energy-interface',
	name = 'personal-transformer-input-entity',
	icon = '__base__/graphics/icons/power-armor.png',
	energy_source =
	{
		type = 'electric',
		buffer_capacity = '20kJ',
		usage_priority = 'secondary-input',
		input_flow_limit = '200kW',
		output_flow_limit = '0kW'
	}
}
And I want to be able to change the input_flow_limit on creation via script, or update it slightly afterwards.
I'm hoping to be able to change the icon on the fly too. ie, change this entity to look like the car for instance

If not, then I guess I'm going to have to keep track of a list of these. I was hoping to be able to consolidate them all into one though.

Pi-C
Smart Inserter
Smart Inserter
Posts: 1720
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Pi-C »

Pikachar wrote:
Tue Apr 25, 2023 4:55 am
All of this has been incredibly helpful.

I am wondering though, if it's possible to update an entity after it's created?
You only can modify the prototypes in the data stages.
For example, if I have this entity:

Code: Select all

{
	type = 'electric-energy-interface',
	name = 'personal-transformer-input-entity',
	icon = '__base__/graphics/icons/power-armor.png',
	energy_source =
	{
		type = 'electric',
		buffer_capacity = '20kJ',
		usage_priority = 'secondary-input',
		input_flow_limit = '200kW',
		output_flow_limit = '0kW'
	}
}
And I want to be able to change the input_flow_limit on creation via script, or update it slightly afterwards.
I'm hoping to be able to change the icon on the fly too. ie, change this entity to look like the car for instance
One way would be to define varieties of this prototype with differing input_flow_limit during the data stages, then keeping track of the entities and swapping them in the control stage.

You can also create different entities on top of each other in control. For example, in Bio Industries we use that technique, to combine things like gun turret and lamp (IIRC) into one entity so we can script it to only shoot if it has electric power. This is quite simple for entities that don't move once they've been placed down (well, you have to take care that invisible entities are added/removed when the main entity is placed/destroyed). For things that can move (vehicles + characters) that is much harder because you've got to teleport the invisible parts to the current position of the main entity.
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

Pikachar
Burner Inserter
Burner Inserter
Posts: 16
Joined: Wed Apr 19, 2023 9:16 pm
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Pikachar »

Aight, I've gotten things mostly ironed out at this point for the base logic. What other events should I be paying attention to?
I'm thinking:
- on_player_mined_entity
- on_entity_destroyed
- on_entity_died
- on_robot_mined_entity

since I'm going to have to update some tables when the vehicle is picked up or destroyed or leaves the surface in some way.

Also, to whoever is reading this: I hope you're having a great day!

Pi-C
Smart Inserter
Smart Inserter
Posts: 1720
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Pi-C »

Pikachar wrote:
Wed Apr 26, 2023 4:17 am
Aight, I've gotten things mostly ironed out at this point for the base logic. What other events should I be paying attention to?
I'm thinking:
- on_player_mined_entity
- on_entity_destroyed
- on_entity_died
- on_robot_mined_entity
You should also listen to script_raised_destroy.
Also, to whoever is reading this: I hope you're having a great day!
Thanks, have a nice day, too!
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

Pikachar
Burner Inserter
Burner Inserter
Posts: 16
Joined: Wed Apr 19, 2023 9:16 pm
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Pikachar »

Awesome. So far so good.
Yet Another Question (YAQ?): Is it possible to add a toggle button either in the form of the checkbox in the picture or to add some sort of shortcut buttons/bar to vehicles/entities?

Image
Attachments
possible buttons.png
possible buttons.png (3.09 MiB) Viewed 2239 times

Pi-C
Smart Inserter
Smart Inserter
Posts: 1720
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Help Retrieving List of Vehicles/Trains

Post by Pi-C »

Pikachar wrote:
Wed Apr 26, 2023 11:21 pm
Is it possible to add a toggle button either in the form of the checkbox in the picture or to add some sort of shortcut buttons/bar to vehicles/entities?
You can't modify the native GUIs. However, you can use the LuaGUI.relative element to attach GUI elements to vanilla GUIs. This is used by, for example, the Custom Color mod. I've also found this guide to building GUIs quite helpful.
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

Post Reply

Return to “Modding help”