#grf-py 0.3.1 - a new way to make NewGRFs (with Python)

1 messages ยท Page 1 of 1 (latest)

prime haven
#

grf-py 0.2.0 - a new way to make NewGRFs

prime haven
#

Version 0.2.1 is available on pypi and github (https://github.com/citymania-org/grf-py).
Nothing too big, just a whole bunch of bugfixes and QoL improvements.

  • Fix: Add articulated callback to purchase chain as well.

  • Fix: Don't write data for same real sprite object multiple times.

  • Fix incorrect encoding of empty sprite.

  • Fix duplicating actions that were added to grf manually.

  • Fix Label value validation.

  • Fix error in action generator for vehicle name.

  • Fix compilation for railtype_table, lang_genders and lang_cases global vars.

  • Fix vox house example.

  • Allow specifying fallbacks in the railtype table.

  • Add a crop parameter to sprites (True by default).

  • Support new variant_group and extra_flag Action 0 vehicle properties.

  • Add encoder for advanced_layout action 0 station property.

  • Return railtype ids in NewGRF.set_railtype_table.

  • Add functions to manage railtype tables to NewGRF class (set_railtype_table and get_railtype_id).

  • Add get_cargo_id method to NewGRF class.

  • Allow to use nml-like comparison operators in the Switch code.

  • Allow to pass code to Switch as a list of lines.

  • Add DEFAULT_CARGO_FIRST_REFITTABLE constant.

  • Allow passing bytes value to actions 7, 9 and D.

  • Check that articulated part id doesn't exceed the max value (0x4000).

  • Allow to omit sprite width and height when they can be auto-detected.

  • Add support for Action B (ErrorMessage).

  • Add id property to the Define class.

  • Rename Action0 properties for OBJECT feature to match NML names.

  • Export StringRef, open_image, find_best_color, SpriteRef, SpriteLayout, SpriteLayoutList, GroundSprite, ParentSprite, ChildSprite classes.

  • Check that first parameter of Map action is DefineMultiple.

  • Cache palette remap when fixing sprite palette.

  • When fixing palette check for exact color first.

  • Add some handling for sprites without any image.

  • Update numpy version to one that has Python 10 builds.

#
  • lib: Fix CallbackManager not writing some callbacks.
  • lib: Fix CallbackManager not setting purchase graphics without purchase callbacks.
  • lib: Add skip_props_check argument to Train.add_articulated_part to skip validation of properties.
  • lib: Make Train articulated parts liveries optional.
  • lib: Allow specifying callbacks for Train articulated parts.
  • lib: Make liveries argument optional for Train and RoadVehicle.
  • lib: Add callbacks property to Train and RoadVehicle.
  • lib: Add optional callback argument to CallbackManager constructor.
  • lib: Add CallbackManager.make_map_action to make Map (Action3) for Define (Action0).
  • lib: Make graphics and purchase graphics properties of CallbackManager instead of make_switches arguments.
  • lib: Allow using StringRef as a name for Train or RoadVehicle.
  • lib: Allow using StringRef as a vehicle additional text.

grftopy: Fix value decompilation in action 7/9.
grftopy: Fix sprite sheet filename generation.
grftopy: Fix RandomSwitch decompilation for vehicles.
grftopy: Fix python generation for properties of custom type.
grftopy: Assign variables to referenceable actions and use them for references.
grftopy: Write climate bits as constants.
grftopy: Don't write ref_id=None in generated python.
grftopy: Decomplile introduction_date property into a datetime object.
grftopy: Print value as a label in comment for actions 7, 9 and D.
grftopy: Convert grftopy script into decompile sub-module.

#

grf-py 0.2.1 - a new way to make NewGRFs

prime haven
#

Version 0.2.2 is available on pypi and github (https://github.com/citymania-org/grf-py).
A bunch of minor additions, changes and bugfixes before (hopefully) heading into 0.3.0

  • Change license to GPL v2+ (same as nml) instead of v3 to allow reusing v2 code/resources.

  • Fix graphics sprite composition.

  • Fix Train weight Action 0 properties (low and high bytes).

  • Fix compilation of generic var parameter in Action 2.

  • Fix var(...) call in Switch code not accepting param value without parentheses.

  • Fix default purchase sprite for auto-articulated trains.

  • Rename speed Action 0 property for ships to max_speed for consinstency with other vehile types.

  • Rename Action 0 ship properties to match nml:

    • cargo_type to default_cargo_type
    • sound to sound_effect
    • ocean_speed to ocean_speed_fraction
    • canal_speed to canal_speed_fraction
    • flags to misc_flags
    • refit_classes to refittable_cargo_classes
    • non_refit_classes to non_refittable_cargo_classes
  • Add id_map_file parameter to BaseNewGRF constructor and reserve_ids and resolve_id methods to manage auto-assigned (string) IDs.

  • Use AlternativeSprites instead of sprite tuples.

  • Add Action0 properties for road types.

  • Add NewGRF.add_railtype to add railtypes one-by-one.

  • Add VEHICLE_NEVER_EXPIRES constant.

  • Add AIFlags and TrainRunningCost enums.

  • Add Flags, AIFlags, RuningCost enums for Trains.

  • Add Palette enum.

  • Add Train.hp and Train.ton methods for converting metric units.

  • Add visual effect constants and methods.

  • Make NewGRF.bind to make a subclass of the type instead of function and expose bound_newgrf property.

  • Change Switch parameter order from to code, ranges, default.

  • Rename is_dual_headed Action 0 Train property to dual_headed to match nml.

  • Add NewGRF.grfid_value property.

  • Pass grf as an argument to Vehicle._set_callbacks.

#
  • Allow visual_effect_and_powered for Train articulated parts.

  • Don't check for sprite type when adding it for now (messes up decompiling).

  • Use setuptools-git-versioning to manage versions.

  • Update documentation.

  • Allow to use objects with id as a variant_group value in Aciton0.

  • Use IDProperty for sort_purchase_list in Action 0 for vehicles.

  • lib: Add Ship sprite generator.

  • lib: Rename kmhishph method to kmhish in Train and RoadVehicle.

  • lib: Make _set_callbacks return list of sprites to allow adding graphics.

  • lib: Make auto-articulated parts use auto-assigned(string) IDs.

  • lib: Support road vehicle property callbacks in CallbackMananger.

  • lib: Fix RoadVehicle name.

  • lib: Fix CallbackManager exceptions.

  • lib: Fix incorect livery for Train wagons.

  • lib: Add VehicleGroup class to define vehicle groups in SetPurchaseOrder.

  • lib: Add length property to a Train constructor, auto-articulate if > 8 (up to 24).

  • lib: Add length property to RoadVehicle constructor (1..8).

  • lib: Add purchase_sprite property to Train and RoadVehicle.

  • lib: Allow to use length > 8 (but <= 24) for articulated parts.

  • lib: Allow specifying property callbacks individually in CallbackManager.

  • lib: Add SetPurchaseOrder sprite generator.

  • lib: Rename POWERED_WAGONS callback to VISUAL_EFFECT_AND_POWERED.

  • lib: Allow to use StringRef as a livery name.

  • lib: Add _set_articulated_part_callbacks method to Train.

  • lib: Use assigned id for the first part when auto-articulating.

  • lib: Add SetGlobalTrainDepotYOffset sprite generator.

  • lib: Add GlobalTrainMiscFlag enum and SetGlobalTrainMiscFlag sprite generator.

  • vox: Fix vox house example.

  • vox: Experimental .vox renderer for trains.

#

grf-py 0.2.2 - a new way to make NewGRFs (with Python)

cerulean cargo
#

What does NewGRF.add_railtype do?

prime haven
#

may need a better name I guess

#

same as set_railtype_table but for a single entry

hazy blade
prime haven
thick nacelle
#

Hey @prime haven ! I just cloned this repo to try it out. I'm hoping to use this to automate getting traditional 3d models from blender into OpenTTD. I have a couple of friends that make assets for Cities Skylines and other games that'd love to see their stuff in OpenTTD.

I gave the vehicle example a try, worked great! However I'm running into difficulty running the vox_house.py example. It seems like some unexpected sprites are getting packed? Any ideas of stuff I'm doing wrong?

prime haven
# thick nacelle Hey <@141594449695211520> ! I just cloned this repo to try it out. I'm hoping to...

Hello! Yeah, vox house example got pretty outdated. I'm not sure how you even got it to compile. Are you using 0.2.2 version? If you do switch to the latest from the github https://github.com/citymania-org/grf-py it's getting close to 0.3.0 already and lots of stuff changed. Anyway I fixed the vox house example, should work now.

Though the closest for your usecase is probably not the voxel stuff as that just uses custom renderer that grf-py has but this part in BonkyGFX: https://github.com/lukaskrepel/BonkyGFX/blob/567174b97620e606dba0698dfcf545a1f63e0512/lib.py#L798-L848 As it runs an external program "aseprite" to generate the image files with all the requested options (layers and frames in this case). BonkyGFX in general is a great example of the latest trends in grf-py develepment. It may be a bit overwhelming due to the size of the project but most of the code is pretty modular and I will be moving some stuff from it into grf-py pretty soon.

Anyway, let me know if you need any help with the code, I don't mind writing some of it and, in fact, would like to have a wrapper for blender rendering in the grf-py itself eventually.

thick nacelle
prime haven
olive storm
#

What a coincidence!
I started looking into making NewGRFs the day before yesterday, got irritated by NFO after 2 hours, got surprised at there not being a higher level language (than NML) or even GUI interface and I find this on discord with an announcment for a version 0.3.0? What a rollercoaster of emotions ๐Ÿ˜†

I haven't been able to look into the code as I'm quite busy with work still, but I was planning on modelling and creating some Swiss stations, so I might be back soon to ask some questions @prime haven ^^

cerulean cargo
#

Stations do happen to be the most complicated feature to code in any language so maybe you should try and start with something else first

olive storm
#

A friend of mine said the same thing, having asked a similar question in another channel before ๐Ÿ˜†

#

I already had a surge of motivation when I got GIMP to work with the color palette, or when my first (modified) NML created GRF worked.
I'll go about the task slowly and see where it takes me ๐Ÿ™‚

prime haven
#

well, the most complicated part in case of grf-py is that noone used it for stations yet so there are no high-level classes and no examples but probably plenty of bugs

#

though I did have an extremely simple station example somewhere

#

I'll look for it tomorrow

prime haven
olive storm
#

I have checked out the train example and your freshly uploaded one. Makes sense so far to me. I will probably not have time to delve deeper until Sunday, but I'll test it further and try and see where I could contribute ๐Ÿ™‚

#

Thanks @prime haven, appreciated

marsh wagon
#

Following

languid spade
prime haven
lyric scarab
#

can this be used to make industry chains

prime haven
#

somewhat tricky one actually as one of the industries has a randomized cargo acceptance

lyric scarab
prime haven
#

Version 0.3.0 is available on pypi and github (https://github.com/citymania-org/grf-py).

This release has been long overdue and a lot of changes got accumulated. Main feature this time is the addition of sprite caching with support for custom sprite classes and procedural sprites. But there are also a lot of bugfixes, new additions and some API changes in an attempt to stabilize it a bit.

Full changelog:

  • Reorganize base sprite/action hierarchy so it better reflects newgrf structure. Also rename classes to use common terms rather than grf-specific ones (real/pseudo sprite).
    • Rename BaseSprite to Action.
    • Rename IntermediateSprite to FakeAction.
    • Rename RealSprite to ResourceAction.
    • Add new base class Resource that resources now inherit instead of RealSprite.
    • Make ResourceAction and AlternativeSprites containers for the Resource objects.
    • Rename SoundSprite to Sound.
    • Rename GraphicsSprite to Sprite.
    • Rename EmptyGraphicsSprite to EmptySprite.
    • Remove LazyAciton and Action.get_data_size as no longer necessary.
  • Fix auto-assigned IDs overlapping when adding vehicles.
  • Fix encoding of label lists in Action0 properties.
  • Fix encoding and decoding of Action 5.
  • Fix min_life Action0 property size for houses (spec error).
  • Fix Switch code using wrong feature for related scope.
  • Fix Switch code grammar issues.
  • Fix alpha generation when using colourkey.
  • Fix encoding of min_bridge_height Action 0 station property (#33).
  • Fix imageSprite conversion for non-P and non-RGBA images (#43).
  • Add sprite cache.
  • Optimize memory usage when writing NewGRF.
  • Optimize grf file size by removing duplicate sprites (by data).
  • Allow defining named temporary variables in Switch code.
#
  • Allow defining named temporary variables in Switch code.
  • Rename zoom constants to use natural/nml order: ZOOM_4X -> ZOOM_2X -> ZOOM_NORMAL -> ZOOM_OUT_2X -> ZOOM_OUT_4X -> ZOOM_OUT_8X.
  • Rename PALETTE to PIL_PALETTE, add PALETTE as a list of (r, g, b) tuples.
  • Add OKLAB_PALETTE, NP_PALETTE, PALETTE_IDX constants.
  • Add srgb_to_linear, linear_to_srgb, srgb_to_oklab, oklab_to_srgb colour conversion functions.
  • Add mode argument to Mask with option to overdraw sprite.
  • Add ShipFlags enum.
  • Support extended format in Action 1.
  • Support ids > 255 in Action 3 (#42).
  • Add main function to handle command line arguments.
  • Add support for road stop feature (#44).
  • Add some VarAction2 variables for houses.
  • Add station_name and station_class_name Action 0 properties for stations.
  • Add TTDString and TTDIndustry constants.
  • Add TownGrowthEffect constants.
  • Add Eval as a version of Switch without ranges.
  • Add subroutines argument to Switch and allow name() call syntax.
  • Add debug_zoom_levels argument to BaseNewGRF.write to recolour sprites according to their zoom level: 4x - red, 2x - blue, 1x - green, out-2x - cyan, out-4x - yellow, out-8x - magenta.
  • Add --debug-zoom-levels command line argument to build command of main function.
  • Add WithMask sprite class to add mask layer to images.
  • Add SpriteWrapper class to simplify writing sprite modifiers.
  • Add MoveSprite modifier to change sprite offsets.
  • Support using StringRef in Action 0x14 (SetProperties).
  • Support using StringRef as NewGRF name and description.
  • Support encoding of bridge layouts.
  • Support encoding of industry layouts.
  • Support encoding of tile acceptance lists for houses and industry tiles.
  • Support expressions for register value in PERM and TEMP access.
  • Support parameter expressions for vars60+ in Switch code (via var7b).
  • Support cropping 24bpp sprites.
#
  • Add preferred_blitter argument to NewGRF constructor, possible values NewGRF.BLITTER_BPP_8 and NewGRF.BLITTER_BPP_32.

  • Add StringManager.get_persistent_id function to register strings in "persistent" range (0xDCxx).

  • Add Sprite.save_gif method to generate palette animated images.

  • Add Sprite.make_rgba_image method to generate static PIL Image.

  • Add init_id_map command line command to initialize id_map.json.

  • Add Date type to represent dates that don't fit into datetime.date.

  • Add example of a simple eyecandy station.

  • Start auto-assiged IDs from 0 for INDUSTRY_TILE feature.

  • Rename AlternativeSprites.get_zoom to get_sprite and add bpp argument.

  • Rename some of the Action0 properties for CARGO to match nml.

  • Don't write redundant actions for railtypes without fallbacks in railtype table.

  • Return cargo type ids in NewGRF.set_cargo_table.

  • Remove all uses of spectra in favour of own colour submodule using OKLAB colour space.

  • Only replace .grf file when build succeeded.

  • lib: Fix CallbackManager.make_switches for non-vehicle features.

  • lib: Fix incorrect 2cc colors for auto-articulated parts.

  • lib: Fix unicode vehicle names.

  • lib: Don't change callbacks passed to CallbackMananger.

  • lib: Set correct flags and track_type on auto-articulated parts.

  • lib: Fix auto-articulation for vehicles without liveries.

  • lib: Fix: Make station availability a purchase callback.

  • lib: Add high-level Industry class.

  • lib: CallbackManager rewrite:

    • Support all features (non-vehicles may still be incomplete).
    • Make CallbackManager abstract class, use make_callback_manager function instead.
    • Support splitting callbacks for default and purchase branch with DualCallback.
    • Use graphics.purchase instead of purchase_graphics attribute.
  • lib: Add Ship.Flags and RoadVehicle.Flags for unified access to flags.

  • lib: Add EngineOverride sprite generator.

#
  • lib: Add reverse_build_probability vehicle callback.

  • lib: Allow omitting ids in DisableDefault to disable all items.

  • lib: Support HOUSE, INDUSTRY and CARGO features in DisableDefault.

  • lib: Add chunk_size parameter to combine_ranges.

  • grftopy: Fix missing sprite zoom

  • grftopy: Improve decoding of industry layouts.

  • grftopy: Fix decompilation of ActionB.

  • grftopy: Fix decompilation of action 7/9 with value > 4 bytes.

  • grftopy: Add -p/--palette cli option to set output palette for 8bpp images.

  • grftopy: Decompile cargo_(dis)allow_refit properties as a tuple of cargo indexes.

  • dev: Add new dev submodule for extending newgrf spec support.

  • dev: Add dev.add_feature function.

#

grf-py 0.3.0 - a new way to make NewGRFs (with Python)

prime haven
#

Version 0.3.1 is available on pypi and github (https://github.com/citymania-org/grf-py).

This is just a small release with accumulated fixes before heading into 0.4.0 development that will eventually drop support for Python < 3.12 and OpenTTD < 15.0.

Changelog:

  • Fix duplicate sprite counter in build report not counting individual alternative sprites like total does.
  • Fix unsigned parent sprite offsets in advanced layout (#45).
  • Fix exception when handling property encoding errors.
  • Fix error in Sprite.make_rgba_image for sprites with rgb and mask.
  • Fix Comment and Label actions (#49).
  • Fix length calculation for auto-articulated parts on articulated parts.
  • Add QuantizeSprite wrapper and quantize function to convert 32/24bpp sprites into 8bpp with openttd palette.
  • Add some code comments and documentation.
  • Update srgb_color_distance to use colour tuples.
  • grftopy: Fix decompilation error.
#

It's a Python framework that aims to cover the whole cycle of NewGRF development, from resource generation and low-level GRF actions to convenient templating and compilation. Having it all in the one place, powered by one of the best programming languages helps to keep it simple but flexible, minimize repeating code and achieve great readability and maintainability of the code.

As grf-py covers pretty much the whole range of GRF format capabilities its primary application are the most complex projects that benefit the most from the ease of development and maintenance while keeping full control over GRF performance. But in the future, as grf-py gains more high-level classes it should make it pretty approachable for beginners as well, better than nml at least.

Also, grf-py includes grftopy`decompiler that can produce low-level grf-py code for a .grf file.

Some examples of GRFs with grf-py:
Simple examples: https://github.com/citymania-org/grf-py/tree/main/examples
Road vehicles: https://github.com/citymania-org/uk-dk-busses
Trains: https://github.com/citymania-org/robs-trains
Trees and procedural sprites: https://github.com/citymania-org/debug-trees-grf
Objects and low-level API: https://github.com/citymania-org/cmclient/tree/master/grf/alpine

You can find grf-py on the github: https://github.com/citymania-org/grf-py
or pypi: pip install grf

#

I find it quite boring and even somewhat counter-productive to develop the API without a specific application for it and at this point, I've run out of my own grfs to make. So I'm looking for people who are willing to support further development of grf-py and try to make their own projects with it. Though I fully understand that it's not easy to learn grf-py as it is since documentation is lacking and API is not very stable so I'm ready to provide all the support you need and even code some things for you. In fact, if you can make good sprites, I'm ready to do all the heavy-lifting so you don't even need to code anything complex at all, just learn some git and python basics to copy-paste and fine-tune simple code like this: https://github.com/citymania-org/uk-dk-busses/blob/main/generate.py#L46 So if you have some good idea just hit me up and we'll make it work. It can be pretty much anything: porting old projects from nfo/nml, tweaks, and addons for other grfs, making a bridge or station sets, voxel stuff, anything goes. Though I'm mostly interested in things I haven't done yet, i.e. not trains and road vehicles, it's fine to have some variety of those as well.

cerulean cargo
#

Is it possible to use vehicle variable 61 in grf-py?

prime haven
#

well, var(num, shift, and, param) since it's 60+

#

and you'll need to assign TEMP[0x10f] and TEMP[0x10e] beforehand

cerulean cargo
#

Nice