How to get current surface and all entities with some name?
How to get current surface and all entities with some name?
I try to create a little power production mod, based on rocket launch.
I already create items and entities, but has problem with script.
In another topic (viewtopic.php?t=87835) DaveMcW told me what I needed. But I can't figure out which event to call it in.
I already create items and entities, but has problem with script.
In another topic (viewtopic.php?t=87835) DaveMcW told me what I needed. But I can't figure out which event to call it in.
Re: How to get current surface and all entities with some name?
It depends, on when you want to call that function.
Here is the list of all available events: https://lua-api.factorio.com/latest/events.html
For further help, please provide, what you want to achive and when you want to run that code.
Here is the list of all available events: https://lua-api.factorio.com/latest/events.html
For further help, please provide, what you want to achive and when you want to run that code.
Re: How to get current surface and all entities with some name?
Then I think the event you want is this: https://lua-api.factorio.com/latest/eve ... t_launchedSLywnow wrote: βTue Aug 18, 2020 8:42 pmI try to create a little power production mod, based on rocket launch.
I already create items and entities, but has problem with script.
In another topic (viewtopic.php?t=87835) DaveMcW told me what I needed. But I can't figure out which event to call it in.
When a rocket is launched you then inspect what the rocket is carrying:
Code: Select all
function on_rocket_launched (event)
local rocket = event.rocket
if rocket then
local inventory = rocket.get_inventory(defines.inventory.rocket)
if inventory then
local count = inventory.get_item_count("name-of-some-item")
local surface = rocket.surface
# Do something here with count of launched item and surface
end
end
end
script.on_event(defines.events.on_rocket_launched, on_rocket_launched)
Re: How to get current surface and all entities with some name?
No, i already done it. Just this code:
Code: Select all
script.on_event(defines.events.on_tick,function(event)
for _, player in pairs(game.players) do change_output(player.surface,"player","ds-energy-loader") end
end)
function change_output(surface, force, entity_name)
local entities = surface.find_entities_filtered{force=force, name=entity_name}
for _, entity in pairs(entities) do
if global.dysonsphere == nil then
global.dysonsphere = 0
end
entity.power_production = global.dysonsphere / #entities * 100000 / 60
end
end
(I launched 3 object to space)
And:
Re: How to get current surface and all entities with some name?
Do keep in mind that the on_tick event runs 60 times per second and you are executing the change_output on every tick. This has the potential to make the game very slow if there are many ds-energy-loader entities in the map.SLywnow wrote: βTue Aug 18, 2020 11:25 pmNo, i already done it. Just this code:Then I think the event you want is thisCode: Select all
script.on_event(defines.events.on_tick,function(event) for _, player in pairs(game.players) do change_output(player.surface,"player","ds-energy-loader") end end) function change_output(surface, force, entity_name) local entities = surface.find_entities_filtered{force=force, name=entity_name} for _, entity in pairs(entities) do if global.dysonsphere == nil then global.dysonsphere = 0 end entity.power_production = global.dysonsphere / #entities * 100000 / 60 end end
I don't see where your code tracks the number of objects launched into space. Can you post that part?
Re: How to get current surface and all entities with some name?
Given that entity is decreasing its energy production, if there is another such entity on the surface, this is unlikely.
However, if there is a way to optimize this, i want to know how
That's simple part
Code: Select all
script.on_event(defines.events.on_rocket_launched,function(event)
rocketLaunched(event)
end)
function rocketLaunched(event)
local rocket_inventory = event.rocket.get_inventory(1)
if rocket_inventory.get_item_count("dyson-sphere-satellite") == 0 then
return
end
if global.dysonsphere == nil then
global.dysonsphere = 0
end
global.dysonsphere = global.dysonsphere+1
game.players[1].print("launched, count "..global.dysonsphere)
end
Code: Select all
{
type = "electric-energy-interface",
name = "ds-energy-loader",
icon = "__base__/graphics/icons/accumulator.png",
icon_size = 64,
flags = {"placeable-neutral", "placeable-player", "player-creation"},
minable = {hardness = 0.2, mining_time = 0.5, result = "ds-energy-loader"},
max_health = 250,
energy_source = {
type = "electric",
usage_priority = "tertiary",
--input_flow_limit = "0MW",
--output_flow_limit = "1000GW",
},
allow_copy_paste = true,
collision_box = {{-0.9, -0.9}, {0.9, 0.9}},
selection_box = {{-1, -1}, {1, 1}},
collision_mask = {},
picture = accumulator_picture( {r=0.6, g=1, b=1, a=1} ),
energy_production = "1ZW",
energy_usage = "0kW",
}
Re: How to get current surface and all entities with some name?
Okay, i found problem
I should have added a buffer. Now all works!
It's time to move to cinema4d to do sprites...
And a little change in control.lua:
I should have added a buffer. Now all works!
It's time to move to cinema4d to do sprites...
Code: Select all
{
type = "electric-energy-interface",
name = "ds-energy-loader",
icon = "__base__/graphics/icons/accumulator.png",
icon_size = 64,
flags = {"placeable-neutral", "placeable-player", "player-creation"},
minable = {hardness = 0.2, mining_time = 0.5, result = "ds-energy-loader"},
max_health = 250,
energy_source = {
type = "electric",
usage_priority = "tertiary",
buffer_capacity = "10GJ",
render_no_power_icon=true,
--input_flow_limit = "0MW",
--output_flow_limit = "1000GW",
},
allow_copy_paste = true,
collision_box = {{-0.9, -0.9}, {0.9, 0.9}},
selection_box = {{-1, -1}, {1, 1}},
collision_mask = {},
picture = accumulator_picture( {r=0.6, g=1, b=1, a=1} ),
energy_production = "0kW",
energy_usage = "0kW",
--corpse = "medium-remnants",
--subgroup = "other",
}
Code: Select all
local ticktime=0
script.on_event(defines.events.on_tick,function(event)
if ticktime < 60 then
ticktime = ticktime+1
else
for _, player in pairs(game.players) do change_output(player.surface,"player","ds-energy-loader") end
ticktime=0
end
end)
function change_output(surface, force, entity_name)
local entities = surface.find_entities_filtered{force=force, name=entity_name}
for _, entity in pairs(entities) do
if global.dysonsphere == nil then
global.dysonsphere = 0
end
--game.players[1].print("worked! "..global.dysonsphere)
entity.power_production = global.dysonsphere / #entities * 100000 / 60
entity.electric_buffer_size = global.dysonsphere / #entities * 100000 / 60
end
end
Re: How to get current surface and all entities with some name?
There are two situations where your ds-energy-loader need to be updated:
- A rocket is launched with dyson-sphere-satellite
- A new ds-energy-loader is placed
The second case can be handled with the events on_robot_built_entity and on_built_entity. On those events you can call the change_output for the ds-energy-loader that was just placed.
Re: How to get current surface and all entities with some name?
In that case i need check destroying events too, but yes, i think i use that, thanks
Re: How to get current surface and all entities with some name?
Shouldn't there also be a check for script_raised_built and script_raised_destroy?
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!
Re: How to get current surface and all entities with some name?
Don't use at all. The only valid use is for initialisation if the entities are placed before your mod is placed. But your entities are part of the mod so avoid it completely.
You are using the events, and they will tell you about what was placed or removed. Save those in the global table.
surface.find_entities() is really slow and only becomes slower the more you explore the map. And if you run it every time an entity is placed or removed then that's comparativly as bad as doing it on every tick.
If I run then I drop from 60 UPS to 7 UPS, with no factory at all!
Code: Select all
local entities = surface.find_entities_filtered{force=force, name=entity_name}
You are using the events, and they will tell you about what was placed or removed. Save those in the global table.
surface.find_entities() is really slow and only becomes slower the more you explore the map. And if you run it every time an entity is placed or removed then that's comparativly as bad as doing it on every tick.
If I run
Code: Select all
/c script.on_event(defines.events.on_tick, function() local a = game.players[1].surface.find_entities_filtered{name = 'burner-inserter'} end)
My mods: Capsule Ammo | HandyHands - Automatic handcrafting | ChunkyChunks - Configurable Gridlines
Some other creations: Combinassembly Language GitHub w instructions and link to run it in your browser | 0~drain Laser
Some other creations: Combinassembly Language GitHub w instructions and link to run it in your browser | 0~drain Laser
Re: How to get current surface and all entities with some name?
Okaaay, and what i must use to find all my entities and change values?Qon wrote: βWed Aug 19, 2020 8:34 amDon't useat all.Code: Select all
local entities = surface.find_entities_filtered{force=force, name=entity_name}
Re: How to get current surface and all entities with some name?
You don't have to "find all the entities" at once. Each event will tell you what is added and what is removed. Maintain a data structure in global with references to entities or entity indices of relevant entities (or just the number of them if that's enough) and use that data structure instead.
Most trivially written like something like this:
Code: Select all
script.on_init(function(event)
global.things_I_care_about = {}
global.things_I_care_about_count = 0
end)
function add_entity(event)
global.things_I_care_about[event.entity] = true
global.things_I_care_about_count = global.things_I_care_about_count + 1
end
function remove_entity(event)
if global.things_I_care_about[event.entity] ~= nil then
global.things_I_care_about[event.entity] = nil
global.things_I_care_about_count = global.things_I_care_about_count - 1
end
end
script.on_event(defines.events.on_something_added, add_entity)
script.on_event(defines.events.on_another_event_where_something_added, add_entity)
script.on_event(defines.events.on_something_removed, remove_entity)
script.on_event(defines.events.on_event_where_I_go_through_my_items, function(event)
-- If you just need count then
-- global.things_I_care_about_count
-- is the same as
-- table_size(global.things_I_care_about)
-- but is faster since it's already calculated
for entity, _ in pairs(global.things_I_care_about) do
if entity.valid then
do_stuff(entity)
else
global.things_I_care_about[entity] = nil
global.things_I_care_about_count = global.things_I_care_about_count - 1
end
end
end)
That way you don't have to rebuild the entire list from scratch tens of times per second where you go through the entire surface and every entity on it and filtering out the handful of things you actually care about. That's orders of magnitude slower.
The event names are ficticious and it's somewhat pseudocodey here, but the principle is to increment and decrement the data structure that keeps track of what things you want to keep track of and use that instead of doing all the things.
Edit: I read DaveMcW's response and your previous thread. Added code for keeping track of count.
My mods: Capsule Ammo | HandyHands - Automatic handcrafting | ChunkyChunks - Configurable Gridlines
Some other creations: Combinassembly Language GitHub w instructions and link to run it in your browser | 0~drain Laser
Some other creations: Combinassembly Language GitHub w instructions and link to run it in your browser | 0~drain Laser
Re: How to get current surface and all entities with some name?
I try to make this, and... it's work, partially...
If i copy-paste your code, the game says that the boolean type doesn't have a valid (well, it was to be expected), so I store it like this:
Code: Select all
global.generators[entity] = entity
How to make this?
Re: How to get current surface and all entities with some name?
Say, this looks suspicious!
Code: Select all
for entity, _ in pairs(global.things_I_care_about) do
if entity.valid then
do_stuff(entity)
β¦
end
Code: Select all
global = {
things_I_care_about = {
entity1 = true,
entity2 = true,
β¦
}
}
Code: Select all
global = {
things_I_care_about = {
[1] = {entity, true}
[2] = {entity, true}
β¦
}
}
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!
Re: How to get current surface and all entities with some name?
Thank you for your clarification
Now i can find my fail
I tried to use this
Code: Select all
for _, entity in pairs(global.things_I_care_about) do
Code: Select all
for entity, _ in pairs(global.things_I_care_about) do
It will be necessary to remember that relying on your many years of experience in coding in a very unfamiliar language like lua is a bad idea. Although I should have understood that when I was studying Python
Re: How to get current surface and all entities with some name?
SLywnow wrote: βThu Aug 20, 2020 2:21 amI try to make this, and... it's work, partially...
If i copy-paste your code, the game says that the boolean type doesn't have a valid (well, it was to be expected), so I store it like this:Code: Select all
global.generators[entity] = entity
So when you copy and pasted you also modified it to read the "true", and tried to use it as an entity?SLywnow wrote: βThu Aug 20, 2020 7:39 amNow i can find my fail
I tried to use thisInstead of thisCode: Select all
for _, entity in pairs(global.things_I_care_about) do
Before that, I thought that the first code was just a template for calling "for", but now I understand what it means and how.Code: Select all
for entity, _ in pairs(global.things_I_care_about) do
I think you get it now but just to show
Code: Select all
local xpression = 5
local my_table = {
blubb = 3,
['key with space'] = 9,
[xpression] = 11
}
my_table[1026] = 34
my_table[1025] = 33
my_table[1] = 99
for k, v in pairs(my_table) do
game.print(game.table_to_json({key = k, value = v}))
end
will print out
Code: Select all
{"key":1,"value":99}
{"key":5,"value":11}
{"key":"blubb","value":3}
{"key":"key with space","value":9}
{"key":1026,"value":34}
{"key":1025,"value":33}
My mods: Capsule Ammo | HandyHands - Automatic handcrafting | ChunkyChunks - Configurable Gridlines
Some other creations: Combinassembly Language GitHub w instructions and link to run it in your browser | 0~drain Laser
Some other creations: Combinassembly Language GitHub w instructions and link to run it in your browser | 0~drain Laser
Re: How to get current surface and all entities with some name?
What you expected gives you a list-like table.Pi-C wrote: βThu Aug 20, 2020 7:28 amDo you really use the complete entity as table index?
[/code]
What I'd have expected isTake that with a grain of salt, though -- I'm still decaffeinated.Code: Select all
global = { things_I_care_about = { [1] = {entity, true} [2] = {entity, true} β¦ } }
What I used was a map-like table.
"entire entity", not really, it's a reference, or just a typed number.
Edit: I would have used entity.index as key if there was something like that. I thought there was, but apparently not. It would not be a list since they keys are non-contiguous. But it would be values that can be printed to console.
Lookups in maps are O(1) which means instant while lookups in lists are O(n) if you don't know which index they are at (which you don't), which is slow.
If you are doing deletions somewhat often you want a map, since those have O(1) time deletions and lists have O(n) deletion time. If you are looping through it then both work but a list is better.But not in Lua. In Lua, lists are tables, which are key-value maps anyways. So they are basically maps with integer keys and not continous memory with pointer arithmetic access. So it doesn't matter here and you can use them as maps always basically.
My mods: Capsule Ammo | HandyHands - Automatic handcrafting | ChunkyChunks - Configurable Gridlines
Some other creations: Combinassembly Language GitHub w instructions and link to run it in your browser | 0~drain Laser
Some other creations: Combinassembly Language GitHub w instructions and link to run it in your browser | 0~drain Laser