Skip to content

Instantly share code, notes, and snippets.

@lisa
Created May 14, 2022 23:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lisa/87d10801f8c0fb15de9323eda0fb7f04 to your computer and use it in GitHub Desktop.
Save lisa/87d10801f8c0fb15de9323eda0fb7f04 to your computer and use it in GitHub Desktop.

A pair of helper scripts for Factorio blueprint (string) parsing.

Factorio blueprint strings are base64-encoded and zlib compressed JSON. There is a leading 0 which prefixes the blueprint string. Consider:

0eNp9j80KwjAQhN9lzmmhbWI0ryIibV0kkD+SVCwl725TL548zjLzzeyGySwUonYZaoOevUtQ1w1JP91o6i2vgaCgM1kwuNFWlexoTEOG5hz13ARvCIVBuwe9obpyYyCXddb0xR1ivbvFThR3w18QQ/Bpz3pX+ytvkLIVDCtUM/ChFaUWHIvUzwMML4rpiPXnjstLL4XgXMhTKR9Exkxi

The preceeding is a base64 encoded blueprint string for a single Small electric pole with no connections or anything else going on.

Stripping the leading 0 we have the real base64 blob:

0eNp9j80KwjAQhN9lzmmhbWI0ryIibV0kkD+SVCwl725TL548zjLzzeyGySwUonYZaoOevUtQ1w1JP91o6i2vgaCgM1kwuNFWlexoTEOG5hz13ARvCIVBuwe9obpyYyCXddb0xR1ivbvFThR3w18QQ/Bpz3pX+ytvkLIVDCtUM/ChFaUWHIvUzwMML4rpiPXnjstLL4XgXMhTKR9Exkxi

Using bpstring-to-json.rb as: ./bpstring-to-json.rb sample.txt sample-decoded.json we get the JSON representation of the blueprint (here it has been "prettified:"

{
  "blueprint": {
    "icons": [
      {
        "signal": {
          "type": "item",
          "name": "small-electric-pole"
        },
        "index": 1
      }
    ],
    "entities": [
      {
        "entity_number": 1,
        "name": "small-electric-pole",
        "position": {
          "x": 1377.5,
          "y": -343.5
        }
      }
    ],
    "item": "blueprint",
    "version": 281479275544576
  }
}

This is very handy but complex blueprints can be extremely large which can make counting entities tricky. Enter component-counter.rb.

Counting entities can be done with component-counter.rb sample-decoded.json:

small-electric-pole: 1
Total entities: 1

For a more complex blueprint:

assembling-machine-1: 4
assembling-machine-2: 124
chemical-plant: 2
fast-inserter: 33
inserter: 237
long-handed-inserter: 75
medium-electric-pole: 7
pipe: 2
pipe-to-ground: 1
small-electric-pole: 146
splitter: 1
transport-belt: 936
underground-belt: 55
Total entities: 1623
#!/usr/bin/env ruby
require 'zlib'
require 'base64'
bpstring_in = ARGV[0]
outfile = ARGV[1]
puts "infile=#{bpstring_in}; outfile=#{outfile}"
bpstring = File.read(bpstring_in)
if bpstring[0] != "0"
puts "bp string needs to start with a 0"
exit 1
end
bpstring_decoded = Base64.decode64(bpstring[1..bpstring.size])
inflated = Zlib::Inflate.inflate(bpstring_decoded)
File.open(outfile,"w") do |f|
f.write inflated
end
#!/usr/bin/env ruby
require 'json'
JSONBP_FILE = ARGV[0]
JSONBP = File.read(JSONBP_FILE)
# Parses a blueprint and returns a histogram of all the entities in it
def parse_blueprint(bp)
h = Hash.new(0)
bp["blueprint"]["entities"].each do |entity|
h[entity["name"]] += 1
end
return h
end
def print_blueprint_histogram(hist)
sorted_keys = hist.keys.sort
count = 0
sorted_keys.each do |key|
puts "#{key}: #{hist[key]}"
count += hist[key]
end
puts "Total entities: #{count}"
end
def parse_blueprint_book(bpbook)
h = Hash.new(0)
i = 0
bpbook["blueprint_book"]["blueprints"].each do |blueprint|
i += 1
individual_bp = parse_blueprint(blueprint)
puts "Book blueprint #{i}"
print_blueprint_histogram(individual_bp)
puts
h.merge!(individual_bp)
end
puts "Total:"
print_blueprint_histogram(h)
end
js = JSON.parse(JSONBP)
if js.has_key?("blueprint_book")
parse_blueprint_book(js)
else
h = parse_blueprint(js)
print_blueprint_histogram(h)
end
{
"blueprint": {
"icons": [
{
"signal": {
"type": "item",
"name": "small-electric-pole"
},
"index": 1
}
],
"entities": [
{
"entity_number": 1,
"name": "small-electric-pole",
"position": {
"x": 1377.5,
"y": -343.5
}
}
],
"item": "blueprint",
"version": 281479275544576
}
}
0eNp9j80KwjAQhN9lzmmhbWI0ryIibV0kkD+SVCwl725TL548zjLzzeyGySwUonYZaoOevUtQ1w1JP91o6i2vgaCgM1kwuNFWlexoTEOG5hz13ARvCIVBuwe9obpyYyCXddb0xR1ivbvFThR3w18QQ/Bpz3pX+ytvkLIVDCtUM/ChFaUWHIvUzwMML4rpiPXnjstLL4XgXMhTKR9Exkxi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment