redruin1 / factorio-draftsman

A complete, well-tested, and up-to-date module to manipulate Factorio blueprint strings. Compatible with mods.
MIT License
94 stars 17 forks source link

`TypeError: Element of blueprint book is not blueprint` when importing large book #40

Closed rpdelaney closed 2 years ago

rpdelaney commented 2 years ago
$ python --version
Python 3.10.5
$ pip3 freeze | grep draftsman
factorio-draftsman==1.0.1

When importing Bocian's Book of Rails using this code:

#!/usr/bin/env python3
#
import sys

from draftsman.blueprintable import Blueprint, BlueprintBook, get_blueprintable_from_string

def main() -> None:
    with open(sys.argv[1]) as f:
        bpstring = f.read()

    b = get_blueprintable_from_string(bpstring)

if __name__ == "__main__":
    main()

# EOF
Stack trace ```python Traceback (most recent call last): File "/home/ryan/src/me/factorio-rails-cleaner/foo.py", line 18, in main() └ File "/home/ryan/src/me/factorio-rails-cleaner/foo.py", line 12, in main b = get_blueprintable_from_string(bpstring) │ └ '0eNrsvctuXUmSrvkqgibVjRajll38lkBNCmfSPTg1yATOII9QYEjMCKIYpEBRmRVIxDv1M/ST9aa01xaD8kX+35Z2VZxTAdQFIdk2mZuZm/ly/83s7y+/v/pw8e728v... └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/blueprintable.py", line 42, in get_blueprintable_from_string return BlueprintBook(blueprint_string) │ └ '0eNrsvctuXUmSrvkqgibVjRajll38lkBNCmfSPTg1yATOII9QYEjMCKIYpEBRmRVIxDv1M/ST9aa01xaD8kX+35Z2VZxTAdQFIdk2mZuZm/ly/83s7y+/v/pw8e728v... └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/utils.py", line 858, in inner result = func(*args, **kwargs) │ │ └ {} │ └ (, '0eNrsvctuXUmSrvkqgibVjRajll38lkBNCmfSPTg1yATOII9QYEj... └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/classes/blueprintbook.py", line 108, in __init__ self.load_from_string(blueprint_book) │ └ '0eNrsvctuXUmSrvkqgibVjRajll38lkBNCmfSPTg1yATOII9QYEjMCKIYpEBRmRVIxDv1M/ST9aa01xaD8kX+35Z2VZxTAdQFIdk2mZuZm/ly/83s7y+/v/pw8e728v... └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/utils.py", line 858, in inner result = func(*args, **kwargs) │ │ └ {} │ └ (, '0eNrsvctuXUmSrvkqgibVjRajll38lkBNCmfSPTg1yATOII9QYEj... └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/classes/blueprintbook.py", line 137, in load_from_string self.setup(**root["blueprint_book"]) │ └ {'blueprint_book': {'blueprints': [{'blueprint_book': {'blueprints': [{'blueprint_book': {'blueprints': [{'blueprint': {'snap-to... └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/utils.py", line 858, in inner result = func(*args, **kwargs) │ │ └ {'blueprints': [{'blueprint_book': {'blueprints': [{'blueprint_book': {'blueprints': [{'blueprint': {'snap-to-grid': {'x': 42, '... │ └ (,) └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/classes/blueprintbook.py", line 182, in setup self.root["blueprints"] = BlueprintableList(kwargs.pop("blueprints")) │ │ └ {'description': 'RHD[virtual-signal=signal-dot][item=solar-panel] & [item=accumulator] & [item=small-lamp] & [item=red-wire] & ... │ └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/classes/blueprintbook.py", line 48, in __init__ self.append(BlueprintBook(elem["blueprint_book"])) │ │ └ {'blueprint_book': {'blueprints': [{'blueprint_book': {'blueprints': [{'blueprint': {'snap-to-grid': {'x': 42, 'y': 42}, 'absolu... │ └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/utils.py", line 858, in inner result = func(*args, **kwargs) │ │ └ {} │ └ (, {'blueprints': [{'blueprint_book': {'blueprints': [{'... └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/classes/blueprintbook.py", line 110, in __init__ self.setup(**blueprint_book) │ └ {'blueprints': [{'blueprint_book': {'blueprints': [{'blueprint': {'snap-to-grid': {'x': 42, 'y': 42}, 'absolute-snapping': True,... └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/utils.py", line 858, in inner result = func(*args, **kwargs) │ │ └ {'blueprints': [{'blueprint_book': {'blueprints': [{'blueprint': {'snap-to-grid': {'x': 42, 'y': 42}, 'absolute-snapping': True,... │ └ (,) └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/classes/blueprintbook.py", line 182, in setup self.root["blueprints"] = BlueprintableList(kwargs.pop("blueprints")) │ │ └ {'description': 'Pollution :)'} │ └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/classes/blueprintbook.py", line 48, in __init__ self.append(BlueprintBook(elem["blueprint_book"])) │ │ └ {'blueprint_book': {'blueprints': [{'blueprint': {'snap-to-grid': {'x': 2, 'y': 42}, 'absolute-snapping': True, 'icons': [{'sign... │ └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/utils.py", line 858, in inner result = func(*args, **kwargs) │ │ └ {} │ └ (, {'blueprints': [{'blueprint': {'snap-to-grid': {'x': ... └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/classes/blueprintbook.py", line 110, in __init__ self.setup(**blueprint_book) │ └ {'blueprints': [{'blueprint': {'snap-to-grid': {'x': 2, 'y': 42}, 'absolute-snapping': True, 'icons': [{'signal': {'type': 'virt... └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/utils.py", line 858, in inner result = func(*args, **kwargs) │ │ └ {'blueprints': [{'blueprint': {'snap-to-grid': {'x': 2, 'y': 42}, 'absolute-snapping': True, 'icons': [{'signal': {'type': 'virt... │ └ (,) └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/classes/blueprintbook.py", line 182, in setup self.root["blueprints"] = BlueprintableList(kwargs.pop("blueprints")) │ │ └ {'description': 'Entry/Exit In relation to the station[virtual-signal=signal-dot][color=185,95,0]L[/color]- left[virtual-signal=... │ └ File "/home/ryan/src/me/factorio-rails-cleaner/.venv/lib/python3.10/site-packages/draftsman/classes/blueprintbook.py", line 50, in __init__ raise TypeError( TypeError: Element of blueprint book is not blueprint or blueprint book object nor is it blueprint dictionary ```
redruin1 commented 2 years ago

Bocian's Book of Rails 1.5 MB

holy

The issue is that I've forgotten that you can put upgrade planners and deconstruction planners in blueprint books, which causes problems. I forgot about these, so I'll add two new classes for them DeconstructionPlanner and UpgradePlanner, but the quickest patch until 1.0.2 would be to simply remove these items from the blueprint book and reimport it, providing that you don't actually need those constructs in the blueprint book. I assume you're autogenerating a rail grid?

rpdelaney commented 2 years ago

I assume you're autogenerating a rail grid?

He got everything aligned manually already because he's some kind of lunatic hero. I want to use his rails but purge the lamps (I hate lamps) and big poles (I have my own tiling blueprint for power, and it lines up with his rails but not the poles already there). Obviously with a book this big, nobody (least of all me) is gonna do that post-production manually. :)

redruin1 commented 2 years ago

Alright, UpgradePlanner and DeconstructionPlanner are now implemented. After trying to load that blueprint design again however, some of the signal id's on some of the rail signals appear malformed:

{
  "entity_number": 18,
  "name": "rail-signal",
  "position": {
    "x": 336.5,
    "y": 26.5
  },
  "direction": 6,
  "control_behavior": {
    "circuit_close_signal": false,
    "circuit_read_signal": true,
    "red_output_signal": {
      "type": "virtual",
      "name": "signal-1"
    },
    "orange_output_signal": {
      "type": "virtual",
      "name": "signal-1"
    },
    "green_output_signal": {
      "type": "item" # <-------- what
    }
  },
  ...
}

Of course, this imports into Factorio no problem! It lives as an empty signal, and persists if you place the blueprint down and create a new blueprint from the placed entities, implying this intentional. Just documenting another very strange edge case here before I forget about it, though it is confusing how this ended up like this in the first place.

Unfortunately, the blueprint book does contain modded entities, so even after 1.0.2 goes live importing it will still be difficult unless you install the associated mods. I'll add this issue to the 2.0 milestone to track it there as well.

rpdelaney commented 2 years ago

the blueprint book does contain modded entities

Wait, what? Can you tell me which ones? (I recognize this is a fucking tome of a blueprint, so please don't spend much time on that.) It may be a bug that the author will want to fix.

redruin1 commented 2 years ago
    ...
    raise InvalidTileError("'{}'".format(value))
draftsman.error.InvalidTileError: 'dect-concrete-grid'

Which I assume is a decorative grid tile, and if I ignore unknown tiles:

    ...
    raise InvalidEntityError("'{}'".format(name))
draftsman.error.InvalidEntityError: 'logistic-train-stop-output'

LTN train stops. Of course, these are just the first tiles/entities that appear before Draftsman errors out; there may be a few more tiles/entities from the same mods or different ones elsewhere in the blueprint.

rpdelaney commented 2 years ago

Oh yeah. I forgot about LTN. That's for sure not a bug in the book. I think that closes this, and the issue with LTN stops is better captured in #42 -- of course, you should feel completely feel free to re-open if you disagree.