Scriptable Drones
This mod adds drones which can be scripted in lua to do things that you need. Think computercraft turtles, but in Factorio.
Details
Type: Mod
Name: Scriptable Drones
Description: Adds drones scriptable in lua
License: MIT
Version: 0.4.0
Release: 2017-09-something
Tested-With-Factorio-Version: 0.15.21
Category: New Entity
Tags: Bots
Download-Url: https://mods.factorio.com/mods/tesserac ... ble-drones
Command Line Usage
The help command should give you all the info you need. The command line simulates a basic shell, with a few utility functions. Feel free to request new command line features.
API
Your gateway from Lua to the Factorio world is the bot object. Check out the mod portal page for the API documentation!
TODO
What should be done in the future:
Bot networking
Displays that bots can connect to
Power and charging system
Lower tier coal power bots
Suggestions welcome
Things to be wary about
Problems that need to be fixed:
Multiplayer has not been tested, don't expect it to work
Miscellaneous crashing
Version History
See mod portal
Re: [MOD 0.15] Scriptable Drones v0.1.0
Posted: Mon Sep 18, 2017 1:54 am
by abordoli
Can we see an example of a "script" that does something neat?
...and how would you edit the script, etc.?
Re: [MOD 0.15] Scriptable Drones v0.1.0
Posted: Mon Sep 18, 2017 2:42 am
by tesseractcat
Well, I haven't actually made anything substantial yet, but I did make this one script that makes the robot move in a small square: https://pastebin.com/tAuVPfpy. To edit scripts, just make a bot, click on it to open the shell, and then write "edit [scriptname]".
Re: [MOD 0.15] Scriptable Drones v0.1.0
Posted: Mon Sep 18, 2017 5:17 am
by abordoli
I feel it has great potential and you've given alot of great script commands. Can't wait to see what others create.
Re: [MOD 0.15] Scriptable Drones v0.1.0
Posted: Mon Sep 18, 2017 8:36 am
by Airat9000
A good mod! just allows many to learn programming through the game
Re: [MOD 0.15] Scriptable Drones v0.1.0
Posted: Mon Sep 18, 2017 5:34 pm
by Adil
Hi, it's nice to see such mod done.
However, I did a peek into the code and there are some things I don't quite understand and some that I want to object to:
--get pos
local e = get_unit_data(self.uuid, "data", "entity") --gets entity reference
local pos = shallowcopy(e.position) --an access to entity.position is a function call that creates a new table each time, then this table is copied by shallowcopy
local posout = {x=pos["x"],y=pos["y"]}--then the copy is made yet again
return posout
To me it seems that there are two copy operations too much done here. Are they really needed?
--detect entities
if next(e_arr) == nil then
return nil --return nil if no entities
end
for k, v in pairs(e_arr) do
--Don't add itself
if v.name ~= "computer" and v.name ~= "computer-inventory" then
out_arr[#out_arr + 1] = v.name
end
end
return out_arr --can return {} if no entities beside itself
Here, the returns of the function are potentially inconsistent, which bothers me. (even though the first return is unlikely to ever be performed)
-- place_item
if game.entity_prototypes[inv[self.index].name] ~= nil then --checks the existence of entity with the same name as the item
e.surface.create_entity{name=inv[self.index].name,position=e.position,force="player"}
inv[self.index].count = inv[self.index].count - 1
return true
else
An item is not guaranteed to share the name with the entity they place. There is `place_result` field in the item prototype, item prototype is accessible from the game.item_prototypes. Maybe that one should be used.
--destroy
v.destroy() --call destroy on arbitrary entity
This method has a great breaking potential. It just silently invalidates the entity without anyone knowing, other mods might not be prepared for sudden disappearance of the entities they track, or at the very least, some local quirks may arise in their mechanics.
I'd like to suggest for things that you didn't spawn yourself to either use `.die()` methodf, or to simulate a complete mining event:
function run_script(uuid, code)
local bot = {--creation of many functions
...
local ok, err = pcall(load_code(code, {bot=bot, defines=defines}))--many functions used once and discarded
Is it really needed to perform script compilation each tick for each entity? Although I didn't measure performance of your mod but that is generally not very fast way to do things.
script.on_event(defines.events.on_tick, function(event)
...
--each tick much work
for k, v in pairs(global) do
if k:starts("unitscript") then--each tick string operations
--each tick new string creation:
if global[k:gsub("script","data")]["entity"] ~= nil then
if global[k:gsub("script","data")]["entity"].valid then
local e = global[k:gsub("script","data")]["entity"]
local ce = global[k:gsub("script","data")]["chestentity"]
Same here, string operations are relatively slow, rseding says so. Can't you implement the same with the tables?
if TOKENS[command] then TOKENS[command](opened_uuid,params) end
7a
In case you are interested, here is how I did command line interpreter recently (in my case it was actually about the second argument in the line, but it should not matter):
--flags for command line calls
FLAGS=setmetatable({},{__newindex=function(me,k,v)
assert(me[k]==nil,string.format("Key %s is already taken",k))
rawset(me,k,v)
end})
local add_flag, flag_help
do
local text={[[<without flags> start interactive interpreter]],}
add_flag=function(flag,help,fun)
table.insert(text,flag .." "..help)
FLAGS[flag]=fun
end
flag_help=function()
print(table.concat(text,'\n'))
end
end
add_flag("--help",[[print this help]],flag_help)
--here's example, how you commands would fit, just outline, I'm missing some of the loacl variables you use:
add_flag("run",
[[run <file name> - Runs a script file]],
function(uuid)
if wdfilesystem[params] ~= nil then
if wdfilesystem[params].type == "file" then
return run_script(opened_uuid, wdfilesystem[params].content)
else
return "You can only run files!\n"
end
else
return "File not found...\n"
end
end)
Re: [MOD 0.15] Scriptable Drones v0.2.0
Posted: Mon Sep 18, 2017 9:58 pm
by tesseractcat
Thanks for the suggestions! With version 0.2.0 I believe I have fixed everything mentioned
Re: [MOD 0.15] Scriptable Drones v0.2.0
Posted: Tue Sep 19, 2017 10:44 am
by hreintke
Nice functionality.
First questions :
- Is there a possibility to update the speed of the bot ?
- Is thee a possibility to provide the bot a scripts without manually typing a run command ?
Re: [MOD 0.15] Scriptable Drones v0.2.0
Posted: Tue Sep 19, 2017 4:19 pm
by Relik
Good mod but you must add some functionality.
I was a fan of the computercraft mod of Minecraft, but in factorio there are already systems to automate almost everything. So we have to do more than is already possible
I might have some ideas:
- A flying robot for fast travel and transport
- A ground robot to defend (patrol), slow movement but has a grid with the possibility of using the weapon that is given to him (gun, flamethrower, etc.)
Add a feature to scan an area around the robot, and identify: resources, enemies and more (a array of type ?)
Of course, nothing magic but input signals and programming
Maybe it could also listen / send a wifi signal on a network (using the network identifier) ?
If this can give you ideas, I would be delighted
_________
Sorry if my English is not very good, I speak fluently 2 languages: French and some programming languages ^^
Re: [MOD 0.15] Scriptable Drones v0.2.0
Posted: Wed Sep 20, 2017 12:08 am
by tesseractcat
Although I was not able to implement everything suggested, here are some of the features suggested that I added for version 0.3.0:
- For wifi, I added the register_net_call and get_net_call functions, to allow intrabot communication
- For input signals, I added the input function, which allows registering an input callback, along with a new run menu
- For detecting ores and enemies, I added the detect_range function, which allows detecting entities in a range up to 20
For defense drones, it can already be implemented by simply placing down a turret and then loading it with ammo, using a script such as:
For speed, right now I am happy with the speed, however I may consider adding support for alternative fuel types in the future.
For running scripts without the run command, hopefully this should be possible in the near future, I am hoping to implement some sort of disk drive that can be used to transfer programs.
That's all for v0.3.0 !
Re: [MOD 0.15] Scriptable Drones v0.3.0
Posted: Wed Sep 20, 2017 7:31 pm
by Relik
Cool, and fast
But, I have a small bug on my side: When I place the drone, it seems to be changing in construction bot (graphic) and goes in the nearest roboport
(No other mod installed)
Re: [MOD 0.15] Scriptable Drones v0.4.0
Posted: Fri Sep 22, 2017 2:06 am
by tesseractcat
With v0.4.0, that bug should have been fixed, along with that, here is the changelog for 0.4.0:
Stability fixes, api fixes, changed from using construction bot entity to using simple entity, added bot rotation, added nfc_copy_file, mine, added computer-position-markers, added move_to_marker.
Nfc file copy should fullfill the need of running scripts without using the "run" command. One thing to note: this version is incompatible with older versions of the mods. This means that you need to destroy and replace bots from old mod versions.
Re: [MOD 0.15] Scriptable Drones v0.4.0
Posted: Wed Sep 27, 2017 6:42 pm
by Relik
Hello,
I tested a small mining program and at the end of an ore I have the following error, while there is still 1 ore and not 0.
I have tested different variants and I have not found how to bypass the error (the example given also causes the error)
The ideal would be to have a function to know the remaining quantity in the resource field under the bot. (bot: get_field_data (ore_name, range)? range would also be able to evaluate the richness of an entire field of resources and emit signals when it is impoverished)
It was also good to have a listing of the functions available from the bot's interface. man / help bot?
Re: [MOD 0.15] Scriptable Drones v0.4.0
Posted: Wed Oct 11, 2017 3:26 pm
by Relik
Hello,
Out of curiosity, I look at the mod code.
I propose some modifications:
if params == "bot" then
return [[Available bot functions:
bot:get_pos() = Gets drone position object
bot:get_marker_pos(marker_name) = Gets marker position object
bot:move(pos_object,[callback]) = Move to position object, [optional] run callback when done
bot:move_offset(offx,offy,[callback]) = Move to offset, [optional] run callback when done
bot:move_to_marker(marker_name,[callback]) = Moves to marker position, [optional] run callback when done
bot:wait(callback,timeout_secs) = Run callback after certain amount of time
bot:update(callback) = Run callback every tick
bot:print(text) = Runs print with text, will automatically convert tables to readable strings for debugging purposes :)
bot:input(prompt, callback) = Prints prompt, and then runs callback with the input parameter when input is entered
bot:select(index) = Selects index in drone inventory (1 - 5)
bot:get_stack() = Gets what is in a stack at the index in the SimpleItemStack format
bot:drop_item(count) = Drops count of what is at index in inventory to the ground
bot:place_item() = Places one of the items at index (if placeable)
bot:destroy(object_name) = Destroys the object if it is below the drone
bot:retrieve_item(object_name) = Picks up the object if it is below the drone
bot:detect_entities() = Detects what entities are below the bot, returns an array of names
bot:detect_range(range) = Detects entities in a range up to 20, returns a table with name as key, and a table with a pos attribute with the objects position as the value, ex. {player={pos={x=10,y=10}},otherentity={pos={...}}}
bot:container_insert(container_name, count, [inventory_type]) = Inserts count of item at index into the container of container-name if it is below the bot, [optional] specify container type, see defines container types
bot:container_retrieve(container_name, item_name, count, [inventory_type]) = Retrieves count of item_name from container_name if it is below the bot, [optional] specify container type, see defines container types
bot:get_item_prod_data() = Gets item production data, returns an array with the format {inputs=[name=value,name2=value2], outputs=[...]}
bot:get_fluid_prod_data() = Same as get_item_prod_data, but for fluid production
bot:get_electric_data() = Same as get_item_prod_data, but requires the bot to be above an electric pole, (I actually do not understand the format that electric poles return for production data, but I will update this when I do)
bot:register_net_call(name, callback) = Registers a callback on the drone network, can be called with the next function
bot:get_net_call(name) = Returns the callback named name, which you can then run
bot:mine(ore_name, callback) = Mines the ore. Runs callback when the ore is done being mined. Callback is REQUIRED or ore will not be mined.
bot:nfc_copy_file(source_file, [run_on_copy]) = Copies the source file to the closest drone (1 tile away range). [optional] If run_on_copy is true, it will automatically start the file on the bot that it is copied to.
]]
else
return [[Available commands:
ls - List files and directories
mkdir <dir name> - Create directory
edit <file name> - Edit file
remove <file/dir name> - Remove file or directory
cls - Clear the screen (not implemented yet)
lua <code> - Runs a line of lua code
run <file name> - Runs a script file
stop - Stops all running scripts
debug - Prints debug info (position, unit_number, etc.)
credits - Prints mod developer credits
help bot - Prints bot functions
]]
end
Re: [MOD 0.15] Scriptable Drones v0.4.0
Posted: Tue Nov 07, 2017 3:09 pm
by tomr-r
hi
can anyone help me I want to put a program on more bots is there a way to do this without having to copy and paste it.