Programming Utilities

Doesn't fit in the other categories, like libraries, small fixes or modpacks.
Post Reply
dalsio
Burner Inserter
Burner Inserter
Posts: 10
Joined: Sun Jun 21, 2015 9:56 pm
Contact:

Programming Utilities

Post by dalsio »

As I was making my first mod, I also made a lot of functions to help me out, and because of my programming style they were already mostly independent of my own mod. So, I decided to wrap them all in one file and post it here, with documentation as to how they work. Some might be similar to the factorio util library with different methods, but all are made from scratch. Hopefully others find it useful and if they do, I might update it with new stuff as I go. I'm thinking it will save a lot of modding time to spread some functionality around rather than have everyone build the same stuff individually and maybe make modding the game easier. To see it in action and/or for detailed examples of how to use it, check out my stackers mod: https://forums.factorio.com/forum/vie ... 87&t=13451

First, to use this, just put the "utilities.lua" file in with your mod files/folders. I put mine in a "library" folder but it can go anywhere near your control.lua. Then, just add

Code: Select all

require "library/utilities.lua"
to the beginning of control.lua substituting "library" for whatever folder path you put it in. Then, just use the functions as you would any others that you made in control.lua.
utilities.lua
(5.26 KiB) Downloaded 701 times
getTime() ------ Returns the number of ticks that have passed in-game since this instance of utilities.lua (and by extention control.lua) was started.
EXAMPLE:

Code: Select all

if getTime()>60 then -dostuff- end
notNil(class, property) ------ Takes class (the desired object), and checks if it has a property named property (of type string). With most objects in factorio (like entity.lua), trying to access a property that it does not have results in an error being thrown, and the game returning to the main menu. This will check if it has the specified property without throwing an error.
EXAMPLE:

Code: Select all

if game.real then -dostuff- end ------will throw an error and stop the game, since game.real does not exist
if notNil(game, "real") then -dostuff- end ------won't throw an error
message(text, dialog, asTable) ------ Takes message and prints it to the player, regardless of what type of argument is passed to it (strings, numbers, booleans, functions, tables, and specific handlers for factorio objects). For a detailed list of what can be given to this method and how it prints each item, check toGameString() below. If dialog is given and is set to true (defaults to false) will print the message as a dialog, interrupting and pausing the game. If asTable is given and is true (defaults to false), will print the item as a standard table, instead of the special format for factorio objects.
EXAMPLE:

Code: Select all

message("Try Again", true) ------ prints to a dialog (pauses game): "Try Again"
message(entity) ------ prints: "Entity: Name = biter, Type = unit, Position: 56, -190"
message({1, 5, 10, 43, 81}) ------ prints: "Table: {1, 5, 10, ... 81}"
toGameString(arg, asTable) ------ used by message(). Takes any argument (arg) and converts it into a single string. If it is a string, number, or boolean, it simply returns them. If it's a function, it returns that it's a function and then whatever it finds as the function's name. If it is an entity, it returns that it's an entity, it's name, it's type, and it's position. If it's a position, it returns as much and the co-ordinates. If it's a tile, it returns "Tile: " and the name of the tile. If it's any factorio object that can become invalid, it returns "Unknown Valid/Invalid Object" (depending on it's valid state), the name if it has one, the type if it has one, and the position if it has one. If it's any table that has a name, type, or position value, it returns "Unknown: " and any of those values that it has. Anything else by this point should be a table, so it returns "Table: " and proceeds to return the contents of the table. Whatever is stored in the table, it is given back to another call of toGameString(). So whether it's a factorio object, a function, or another table, it should print properly. If there are more than 4 items in the table, since factorio can't print too long of a string (and multi-dimensional tables can get rather long to display), it will show only the first 3 elements of the table, followed by a ... and then the last element of that table. asTable works as above, if true (defaults to false) then (if it's also a table) it ignores any checks for a factorio object and returns the item as a standard table. NOTE: printing as a standard table only works if that table is in sequence (IE all elements are right after each other, starting at 1). The keys must also be sequential numbers starting at 1.

waitToDo(ticks, function) ------ After ticks number of ticks in-game, will do function. The easiest way to do this is with a temporary, unnamed function. NOTE: to use this properly, you need to put stepTimers() in with the ontick event so that every game tick, it steps the timers. Without this step, what you put in function will not run!
EXAMPLE:

Code: Select all

waitToDo(900,      ------ will wait 15 seconds and then kill [entity]
function() 
    entity.die
end
--------------------------------
jerry = function()     ------ once called, will check every 60 seconds if [entity] is at position [target] and if so, kill it and stop checking.
    if entity.position = target then entity.die else waitToDo(60, jerry) end
end
stepTimers() ------ used by waitToDo() to move the timers forward each tick. A call to this should be placed in an "ontick" event. Should only be called outside of "ontick" if you want to manually speed-up a timer, but be very careful with this, as it can easily lead to complications.
EXAMPLE:

Code: Select all

if event.name == defines.events.ontick
then
    stepTimers()    ------ Steps timers every tick.
end
moveTowards(start, direction, distance) ------ takes a starting position start and returns a new position distance units away in the direction direction.
EXAMPLE:

Code: Select all

newpos = moveTowards(oldpos, defines.direction.east, 5)    ------ returns a position 5 tiles east of oldpos
newpos = moveTowards(moveTowards(oldpos, defines.direction.east, 3), defines.direction.north, 4)    ------ returns a new position 3 tiles east and 4 tiles north of oldpos
right(direction) ------ returns the direction 90 degrees to the right of direction

left(direction) ------ returns the direction 90 degrees to the left of direction

modPosition(position, modx, mody) ------ returns a new position starting at position, modx distance in the x axis and mody in the y axis.

areaAround(start, radius) ------ returns an area with the center at position start and of a radius of radius.
EXAMPLE:

Code: Select all

areaAround(entity.position, 10)   ------ returns a 20x20 area centered on "entity"
centerOfArea(area) ------ returns the position at the center of a given area

positionInChunk(position) ------ returns what chunk position is in. chunks have x and y like position, starting at 0,0 and are 32x32 tiles
EXAMPLE:

Code: Select all

positionInChunk({x = 5, y = 1})    ------ returns 0,0
chunkArea(chunk) ------ converts a chunk chunk into it's corresponding area
EXAMPLE:

Code: Select all

chunkArea({x=0,y=0})    ------ returns area = {{0,0},{32,32}}
mergeTables(table1, table2) ------ returns a new table with all the elements of table1 and table2 combined. Only works on sequential tables with numbers as the keys.
EXAMPLE:

Code: Select all

mergeTables({"time", 5, true}, {"warp", 0, false})    ------ returns a table: {"time", 5, true, "warp", 0, false}
findEntitiesInGeneratedChunks(nameList) ------ first, gets all chunks that have been generated, goes through all the names in the table nameList and finds all entities with those names in the generated chunks, adds them all to a single table, and then returns that table. Very useful for when you want to find your custom mod entitiy that you want to reference, but don't want to search a fixed area. This will find any of your desired entities in only the places that it could possibly exist (areas that have been generated) and expands automatically to any size map. Generally takes less processor resources and time than searching a fixed, and arbitrarily large area.
EXAMPLE:

Code: Select all

findEntitiesInGeneratedChunks({"assembling-machine-1", "assembling-machine-2", "assembling-machine-3"})
------ returns a table containing all the assembling machines of any tier in this world

User avatar
Afforess
Filter Inserter
Filter Inserter
Posts: 422
Joined: Tue May 05, 2015 6:07 pm
Contact:

Re: Programming Utilities

Post by Afforess »

Looks helpful. Any chance of moving the code to a place like Github? It might be nice to have version control, or be able to contribute to the library.

Tarrke
Burner Inserter
Burner Inserter
Posts: 5
Joined: Wed Nov 07, 2018 1:20 pm
Contact:

Re: Programming Utilities

Post by Tarrke »

Afforess wrote:
Fri Jul 31, 2015 2:55 pm
Looks helpful. Any chance of moving the code to a place like Github? It might be nice to have version control, or be able to contribute to the library.
+1, and we can add this repo as a submodule of new mods.

Post Reply

Return to “Mod Packs / Libs / Special Interest”