Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package nml for openSUSE:Factory checked in at 2025-12-04 11:24:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nml (Old) and /work/SRC/openSUSE:Factory/.nml.new.1939 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nml" Thu Dec 4 11:24:56 2025 rev:30 rq:1320956 version:0.8.1 Changes: -------- --- /work/SRC/openSUSE:Factory/nml/nml.changes 2025-10-28 14:50:12.036109174 +0100 +++ /work/SRC/openSUSE:Factory/.nml.new.1939/nml.changes 2025-12-04 11:27:28.840042282 +0100 @@ -0,0 +1,16 @@ +Wed Dec 3 09:26:34 UTC 2025 - Jan Baier <[email protected]> + +- update to 0.8.1: + * Add: station properties to editor symbols script by @Pixel-Tony in #383 + * Change: move black options to pyproject.toml by @ahyangyi in #386 + * Add: Extend FEAT_TRAIN track_type for prop 34 by @glx22 in #390 + * Codefix 41d5cd4: standalone build references non existing files by @glx22 in #397 + * Add: Support for Action5 type 1B bridge deck overlays by @zephyris in #393 + * Add: FEAT_AIRCRAFT flight_state variable (varE2) by @glx22 in #391 + * Fix: Validation and handling of multiple settings in one parameter by @glx22 in #382 + * Upgrade: bump the actions group across 1 directory with 6 updates by @dependabot[bot] in #396 + * Codefix: Fix typos and grammar errors by @Rito13 in #389 + * Change: Validate action 2 loaded list does not overlap special types. by @PeterN in #400 + * Add: Station/RoadStop height and blocked pillar flag lists. by @PeterN in #388 + * Update: changelog for 0.8.1 by @glx22 in #399 + Old: ---- nml-0.8.0.tar.gz New: ---- nml-0.8.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nml.spec ++++++ --- /var/tmp/diff_new_pack.7oItR5/_old 2025-12-04 11:27:29.356064118 +0100 +++ /var/tmp/diff_new_pack.7oItR5/_new 2025-12-04 11:27:29.360064287 +0100 @@ -1,6 +1,7 @@ # # spec file for package nml # +# Copyright (c) 2025 SUSE LLC # Copyright (c) 2025 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties @@ -17,7 +18,7 @@ Name: nml -Version: 0.8.0 +Version: 0.8.1 Release: 0 Summary: NewGRF Meta Language License: GPL-2.0-or-later ++++++ nml-0.8.0.tar.gz -> nml-0.8.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/Makefile new/nml-0.8.1/Makefile --- old/nml-0.8.0/Makefile 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/Makefile 2025-12-02 20:17:25.000000000 +0100 @@ -1,6 +1,5 @@ MAKE?=make PYTHON?=/usr/bin/env python3 -BLACK_OPTIONS=-l 120 --exclude 'action2var_variables.py|action3_callbacks.py|ply' .PHONY: regression test install extensions clean flake black @@ -21,8 +20,8 @@ rm -f *.so flake: - $(PYTHON) -m black --check $(BLACK_OPTIONS) nml + $(PYTHON) -m black --check nml $(PYTHON) -m flake8 nml black: - $(PYTHON) -m black $(BLACK_OPTIONS) nml + $(PYTHON) -m black nml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/PKG-INFO new/nml-0.8.1/PKG-INFO --- old/nml-0.8.0/PKG-INFO 2025-06-21 21:12:41.286344500 +0200 +++ new/nml-0.8.1/PKG-INFO 2025-12-02 20:17:28.717712000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: nml -Version: 0.8.0 +Version: 0.8.1 Summary: An OpenTTD NewGRF compiler for the nml language Home-page: https://github.com/OpenTTD/nml Author: NML Development Team diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/README.md new/nml-0.8.1/README.md --- old/nml-0.8.0/README.md 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/README.md 2025-12-02 20:17:25.000000000 +0100 @@ -1,6 +1,6 @@ # NML NewGRF meta language -NML is a a python-based compiler, capable of compiling NML files (along +NML is a Python-based compiler, capable of compiling NML files (along with their associated language, sound and graphic files) into grf and / or nfo files. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/docs/changelog.txt new/nml-0.8.1/docs/changelog.txt --- old/nml-0.8.0/docs/changelog.txt 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/docs/changelog.txt 2025-12-02 20:17:25.000000000 +0100 @@ -1,3 +1,16 @@ +0.8.1 (2025-12-02) +------------------------------------------------------------------------ +Support for NewGRF additions of OpenTTD 15: + - Add: Station/RoadStop height and blocked pillar flag lists (#388) + - Add: Extend FEAT_TRAIN track_type for prop 34 (#390) + - Add: Support for Action5 type 1B bridge deck overlays (#393) + +Other changes and fixes: + - Fix: Validation and handling of multiple settings in one parameter (#382) + - Add: FEAT_AIRCRAFT flight_state variable (varE2) (#391) + - Change: Validate action 2 loaded list does not overlap special types (#400) + + 0.8.0 (2025-06-21) ------------------------------------------------------------------------ This release removes external dependency for "ply". diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/__version__.py new/nml-0.8.1/nml/__version__.py --- old/nml-0.8.0/nml/__version__.py 2025-06-21 21:12:41.000000000 +0200 +++ new/nml-0.8.1/nml/__version__.py 2025-12-02 20:17:28.000000000 +0100 @@ -1,2 +1,2 @@ # this file is autogenerated by setup.py -version = "0.8.0" +version = "0.8.1" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action0.py new/nml-0.8.1/nml/actions/action0.py --- old/nml-0.8.0/nml/actions/action0.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action0.py 2025-12-02 20:17:25.000000000 +0100 @@ -48,7 +48,7 @@ @ivar allocated: Mapping of allocated blocks. @type allocated: C{dict} of C{int} to allocation information. - @ivar filled: Mapping of block size to smallest address that may contain free space. + @ivar filled: Mapping of block size to the smallest address that may contain free space. Serves as a cache to speed up searches. @type filled: C{dict} of C{int} """ @@ -72,7 +72,7 @@ def get_max_allocated(self): """ - Return maximum number of allocateable ids. + Return maximum number of allocatable ids. """ if self.dynamic_allocation: return self.last - self.first + 1 @@ -90,7 +90,7 @@ @param length: Number of addresses in the block. @type length: C{int} - @return: Whether the block fits enitrely in the available address space. + @return: Whether the block fits entirely in the available address space. @rtype: C{bool} """ return addr >= 0 and addr + length - 1 <= self.last @@ -923,7 +923,7 @@ num_ids = 1 # Number of values that will be written in one go values = [] - # try to capture as much values as possible + # try to capture as many values as possible while True: cost = basecost.costs[i] if isinstance(cost.value, expression.ConstantNumeric): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action0properties.py new/nml-0.8.1/nml/actions/action0properties.py --- old/nml-0.8.0/nml/actions/action0properties.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action0properties.py 2025-12-02 20:17:25.000000000 +0100 @@ -108,7 +108,7 @@ # Summary: If 'string' or 'string_literal' is set, the value should be a # string or literal string, else the value is a number. 'unit_type' and # 'unit_conversion' are used to convert user-entered values to nfo values. -# If some more arithmetic is needed to convert the entered value into an nfo +# If some more arithmetic is needed to convert the entered value into a nfo # value, 'value_function' can be used. For even more complicated things, # 'custom_function' can be used to create a special mapping of the value to nfo # properties, else 'num' and 'size' are used to provide a 'normal' action0. @@ -214,7 +214,7 @@ def animation_info(value, loop_bit=8, max_frame=253): """ Convert animation info array of two elements to an animation info property. - The first is 0/1, and defines whether or not the animation loops. + The first is 0/1, and defines whether the animation loops. The second is the number of frames, at most 253 frames. @param value: Array of animation info. @@ -412,6 +412,16 @@ ] +def single_or_list(prop_name, single_num, multiple_num, value): + if isinstance(value, ConstantNumeric): + return [Action0Property(single_num, value, 1)] + if isinstance(value, Array): + if len(value.values) == 1: + return [Action0Property(single_num, value.values[0].reduce_constant(), 1)] + return [VariableByteListProp(multiple_num, [[type.reduce_constant().value for type in value.values]])] + raise generic.ScriptError("'{}' must be a constant or an array of constants".format(prop_name)) + + # # Feature 0x00 (Trains) # @@ -419,7 +429,9 @@ # fmt: off properties[0x00] = { **general_veh_props, - "track_type": {"size": 1, "num": 0x05}, + "track_type": { + "custom_function": lambda value: single_or_list("track_type", 0x05, 0x34, value) + }, "ai_special_flag": {"size": 1, "num": 0x08}, "speed": { "size": 2, @@ -428,12 +440,12 @@ "unit_conversion": (5000, 1397), "adjust_value": lambda val, unit: ottd_display_speed(val, 1, 1, unit) }, - # 09 doesn"t exist + # 09 doesn't exist "power": {"size": 2, "num": 0x0B, "unit_type": "power"}, - # 0A doesn"t exist + # 0A doesn't exist "running_cost_factor": {"size": 1, "num": 0x0D}, "running_cost_base": {"size": 4, "num": 0x0E}, - # 0F -11 don"t exist + # 0F -11 don't exist "sprite_id": {"size": 1, "num": 0x12}, "dual_headed": {"size": 1, "num": 0x13}, "cargo_capacity": {"size": 1, "num": 0x14}, @@ -717,7 +729,7 @@ def station_platforms_length(value): # Writing bitmask(2) to disable platform/length 3 is not very intuitive. - # Instead we expect the user will write bitmask(3) and we shift the result. + # Instead, we expect the user will write bitmask(3) and we shift the result. return nmlop.SHIFT_RIGHT(value, 1, value.pos).reduce() @@ -818,6 +830,12 @@ ] +def station_tile_list(value, prop_num, description): + if not isinstance(value, Array) or len(value.values) % 2 != 0: + raise generic.ScriptError(f"{description} list must be an array of even length", value.pos) + return [VariableByteListProp(prop_num, [[x.reduce_constant().value for x in value.values]], True)] + + # fmt: off properties[0x04] = { "class": {"size": 4, "num": 0x08, "first": None, "string_literal": 4}, @@ -843,6 +861,8 @@ "name": {"size": 2, "num": (256, -1, 0x1C), "string": (256, 0xC5, 0xDC), "required": True}, "classname": {"size": 2, "num": (256, -1, 0x1D), "string": (256, 0xC4, 0xDC)}, "tile_flags": {"custom_function": station_tile_flags}, # = prop 1E + "heights": {"custom_function": lambda x: station_tile_list(x, 0x20, "Station height")}, + "blocked_pillars": {"custom_function": lambda x: station_tile_list(x, 0x21, "Station blocked pillar")}, } # fmt: on @@ -1566,7 +1586,7 @@ properties[0x11] = { "substitute": {"size": 1, "num": 0x08, "first": None}, "override": {"size": 1, "num": 0x09}, - # 0A - 0D don"t exist (yet?) + # 0A - 0D don't exist (yet?) # 0E (callback flags) is not set by user "animation_info": {"size": 2, "num": 0x0F, "value_function": animation_info}, "animation_speed": {"size": 1, "num": 0x10}, @@ -1656,5 +1676,7 @@ "animation_triggers": {"size": 2, "num": 0x10}, # 11 (callback flags) is not set by user "general_flags": {"size": 4, "num": 0x12}, + "heights": {"custom_function": lambda x: station_tile_list(x, 0x13, "Station height")}, + "blocked_pillars": {"custom_function": lambda x: station_tile_list(x, 0x14, "Station blocked pillar")}, "cost_multipliers": {"custom_function": lambda x: byte_sequence_list(x, 0x15, "Cost multipliers", 2)}, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action1.py new/nml-0.8.1/nml/actions/action1.py --- old/nml-0.8.0/nml/actions/action1.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action1.py 2025-12-02 20:17:25.000000000 +0100 @@ -145,7 +145,7 @@ Create a list of actions needed to write this collection to the output. This will generate a single Action1 and as many realsprites as needed. - @return: A list of actions needed to represet this collection in a GRF. + @return: A list of actions needed to represent this collection in a GRF. @rtype: C{list} of L{BaseAction} """ actions = [Action1(self.feature, self.first_set, len(self.spritesets), self.num_sprites_per_spriteset)] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action14.py new/nml-0.8.1/nml/actions/action14.py --- old/nml-0.8.0/nml/actions/action14.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action14.py 2025-12-02 20:17:25.000000000 +0100 @@ -278,9 +278,9 @@ setting_node.subnodes.append(value_names_node) else: assert setting.type == "bool" + assert setting.bit_num is not None setting_node.subnodes.append(BinaryNode("TYPE", 1, 1)) - bit = setting.bit_num.value if setting.bit_num is not None else 0 - setting_node.subnodes.append(SettingMaskNode(param_num, bit, 1)) + setting_node.subnodes.append(SettingMaskNode(param_num, setting.bit_num.value, 1)) if setting.def_val is not None: setting_node.subnodes.append(BinaryNode("DFLT", 4, setting.def_val.value)) param_root.subnodes.append(setting_node) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action2.py new/nml-0.8.1/nml/actions/action2.py --- old/nml-0.8.0/nml/actions/action2.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action2.py 2025-12-02 20:17:25.000000000 +0100 @@ -139,7 +139,7 @@ def remove_tmp_location(self, location, force_recursive): """ Recursively remove a location from the list of available temporary - storage locations. It is not only removed from the the list of the + storage locations. It is not only removed from the list of the current Action2Var but also from all Action2Var it calls. If an Action2Var is referenced as a procedure call, the location is always removed recursively, otherwise only if force_recursive is True. @@ -230,7 +230,7 @@ Metaclass factory which makes base classes for all nodes 'Action 2 graph' This graph is made up of all blocks that are eventually compiled to Action2, which use the same name space. Spritesets do inherit from this class to make - referencing them possible, but they are not part of the refernce graph that + referencing them possible, but they are not part of the reference graph that is built. @param cls_is_spriteset: Whether this class represents a spriteset @@ -244,7 +244,7 @@ @type cls_has_explicit_feature: C{bool} @param cls_is_relocatable: Whether instances of this class can be freely moved around or whether they need - to to be converted to nfo code at the same location as they are in the nml code. + to be converted to nfo code at the same location as they are in the nml code. @type cls_is_relocatable: C{bool} @return: The constructed class @@ -262,7 +262,7 @@ Child classes should do the following: - Implement their own __init__ method - Call BaseStatement.__init__ - - Call initialize, pre_process and perpare_output (in that order) + - Call initialize, pre_process and prepare_output (in that order) - Implement collect_references - Call set_action2 after generating the corresponding action2 (if applicable) @@ -294,8 +294,8 @@ def __init__(self): """ Subclasses should implement their own __init__ method. - This method should not be called, because calling a method on a meta class can be troublesome. - Instead, call initialize(..). + This method should not be called, because calling a method on a metaclass can be troublesome. + Instead, call initialize(...). """ raise NotImplementedError( ( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action2layout.py new/nml-0.8.1/nml/actions/action2layout.py --- old/nml-0.8.0/nml/actions/action2layout.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action2layout.py 2025-12-02 20:17:25.000000000 +0100 @@ -117,7 +117,7 @@ flags |= 1 << 2 if self.palette_from_action1: flags |= 1 << 3 - # for building sprites: bit 4 => xoffset+yoffset, bit 5 => zoffset (x and y always set totgether) + # for building sprites: bit 4 => xoffset+yoffset, bit 5 => zoffset (x and y always set together) # for child sprites: bit 4 => xoffset, bit 5 => yoffset if self.type == Action2LayoutSpriteType.BUILDING: assert (self.get_register("xoffset") is not None) == (self.get_register("yoffset") is not None) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action2random.py new/nml-0.8.1/nml/actions/action2random.py --- old/nml-0.8.0/nml/actions/action2random.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action2random.py 2025-12-02 20:17:25.000000000 +0100 @@ -105,7 +105,7 @@ def parse_randomswitch_type(random_switch): """ - Parse the type of a random switch to determine the type and random bits to use. + Parse the type of random switch to determine the type and random bits to use. @param random_switch: Random switch to parse the type of @type random_switch: L{RandomSwitch} @@ -203,7 +203,7 @@ @return: A tuple of two values: - The first random bit to use - - The number of random choices to use. This may be higher the the original amount passed as paramter + - The number of random choices to use. This may be higher than the original amount passed as parameter @rtype: C{tuple} of (C{int}, C{int}) """ # Dependent random chains @@ -240,7 +240,7 @@ else: randbit = -1 - # INdependent random chains + # Independent random chains possible_mask = ((1 << bits_available) - 1) << start_bit for indep in random_switch.independent: act2 = lookup_random_action2(indep) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action2real.py new/nml-0.8.1/nml/actions/action2real.py --- old/nml-0.8.0/nml/actions/action2real.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action2real.py 2025-12-02 20:17:25.000000000 +0100 @@ -89,6 +89,11 @@ else: loaded_list.append(action1_index) + if len(loaded_list) >= 0x80: + raise generic.ScriptError("Too many 'loaded' sprite set(s).", spritegroup.pos) + if len(loading_list) >= 0xFF: + raise generic.ScriptError("Too many 'loading' sprite set(s).", spritegroup.pos) + actions.append( Action2Real( feature, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action2var_variables.py new/nml-0.8.1/nml/actions/action2var_variables.py --- old/nml-0.8.0/nml/actions/action2var_variables.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action2var_variables.py 2025-12-02 20:17:25.000000000 +0100 @@ -212,6 +212,7 @@ 'max_speed' : {'var': 0x98, 'start': 0, 'size': 16, 'value_function': value_mul_div(0x3939, 0x1000)}, 'current_speed' : {'var': 0xB4, 'start': 0, 'size': 16, 'value_function': value_mul_div(0x3939, 0x1000)}, 'current_max_speed' : {'var': 0x4C, 'start': 0, 'size': 16, 'value_function': value_mul_div(0x3939, 0x1000)}, + 'flight_state' : {'var': 0xE2, 'start': 0, 'size': 8}, 'vehicle_is_in_depot' : {'var': 0xE6, 'start': 0, 'size': 8, 'value_function': value_equals(0)}, } @@ -297,7 +298,7 @@ varact2vars_stations = { **varact2vars_base_stations, # Vars 40, 41, 46, 47, 49 are implemented as 60+x vars, - # except for the 'tile type' part which is always the same anyways + # except for the 'tile type' part which is always the same anyway 'tile_type' : {'var': 0x40, 'start': 24, 'size': 8}, 'terrain_type' : {'var': 0x42, 'start': 0, 'size': 8}, 'track_type' : {'var': 0x42, 'start': 8, 'size': 8}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action3.py new/nml-0.8.1/nml/actions/action3.py --- old/nml-0.8.0/nml/actions/action3.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action3.py 2025-12-02 20:17:25.000000000 +0100 @@ -474,7 +474,7 @@ # Special case for vehicle cb 36, maps var10 values to spritegroups cb36_mapping = {} cb36_buy_mapping = {} - # Sspecial case for industry production CB, maps var18 values to spritegroups + # Special case for industry production CB, maps var18 values to spritegroups prod_cb_mapping = {} for cb_info, gfx in callbacks: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action3_callbacks.py new/nml-0.8.1/nml/actions/action3_callbacks.py --- old/nml-0.8.0/nml/actions/action3_callbacks.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action3_callbacks.py 2025-12-02 20:17:25.000000000 +0100 @@ -29,7 +29,7 @@ general_vehicle_cbs = { 'default' : {'type': 'cargo', 'num': None}, 'purchase' : {'type': 'cargo', 'num': 0xFF}, - 'random_trigger' : {'type': 'cb', 'num': 0x01}, # Almost undocumented, but really neccesary! + 'random_trigger' : {'type': 'cb', 'num': 0x01}, # Almost undocumented, but really necessary! 'loading_speed' : {'type': 'cb', 'num': 0x36, 'var10': 0x07}, 'cargo_subtype_text' : {'type': 'cb', 'num': 0x19, 'flag_bit': 5}, 'additional_text' : {'type': 'cb', 'num': 0x23, 'purchase': 2}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action5.py new/nml-0.8.1/nml/actions/action5.py --- old/nml-0.8.0/nml/actions/action5.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action5.py 2025-12-02 20:17:25.000000000 +0100 @@ -85,6 +85,7 @@ "OTTD_RECOLOUR": (0x18, 1, Action5BlockType.OFFSET), "ROAD_WAYPOINTS": (0x19, 4, Action5BlockType.OFFSET), "OVERLAY_ROCKS": (0x1A, 95, Action5BlockType.OFFSET), + "BRIDGE_DECKS": (0x1B, 24, Action5BlockType.OFFSET), } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/action7.py new/nml-0.8.1/nml/actions/action7.py --- old/nml-0.8.0/nml/actions/action7.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/action7.py 2025-12-02 20:17:25.000000000 +0100 @@ -178,7 +178,7 @@ # We need to create a new block if skip_opts[0]: - # We can just choose to not skip the preceeding actions without harm + # We can just choose to not skip the preceding actions without harm actions.extend(action_list[start : start + length]) else: action_type = 7 if skip_opts[1] else 9 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/actionD.py new/nml-0.8.1/nml/actions/actionD.py --- old/nml-0.8.0/nml/actions/actionD.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/actionD.py 2025-12-02 20:17:25.000000000 +0100 @@ -27,13 +27,13 @@ @ivar target: Number of the target parameter @ivar target: L{ConstantNumeric} - @ivar param1: Paramter number of the first operand + @ivar param1: Parameter number of the first operand @type param1: L{ConstantNumeric} @ivar op: (Binary) operator to use. @type op: L{Operator} - @ivar param2: Paramter number of the second operand + @ivar param2: Parameter number of the second operand @type param2: L{ConstantNumeric} @ivar data: Numerical data that will be used instead of parameter value, @@ -324,7 +324,7 @@ elif op == nmlop.CMP_NEQ: extra_actions.extend(parse_actionD(ParameterAssignment(assignment.param, nmlop.SUB(expr1, expr2)))) op = nmlop.DIV - # We rely here on the (ondocumented) behavior of both OpenTTD and TTDPatch + # We rely here on the (undocumented) behavior of both OpenTTD and TTDPatch # that expr/0==expr. What we do is compute A/A, which will result in 1 if # A != 0 and in 0 if A == 0 expr1 = assignment.param diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/actionF.py new/nml-0.8.1/nml/actions/actionF.py --- old/nml-0.8.0/nml/actions/actionF.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/actionF.py 2025-12-02 20:17:25.000000000 +0100 @@ -29,7 +29,7 @@ # - unsafe numbered: Number is allocated by the user, and is not safe to refer to # (that is, it is below the point of 'prepare_output') # - invisible: Number is allocated by a final town_name, without attaching a name to it. -# It is not accessible any more. +# It is not accessible anymore. # Instances of the TownNames class have a 'name' attribute, which can be 'None' (for an invisible number), # a string (for a named number), or a (constant numeric) expression (for a safe/unsafe number). # diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/actions/real_sprite.py new/nml-0.8.1/nml/actions/real_sprite.py --- old/nml-0.8.0/nml/actions/real_sprite.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/actions/real_sprite.py 2025-12-02 20:17:25.000000000 +0100 @@ -201,10 +201,10 @@ return [parse_real_sprite(self, default_file, default_mask_file, poslist, id_dict)] def check_sprite_size(self): - generic.check_range(self.xpos.value, 0, 0x7FFFFFFF, "Real sprite paramater 'xpos'", self.xpos.pos) - generic.check_range(self.ypos.value, 0, 0x7FFFFFFF, "Real sprite paramater 'ypos'", self.ypos.pos) - generic.check_range(self.xsize.value, 1, 0xFFFF, "Real sprite paramater 'xsize'", self.xsize.pos) - generic.check_range(self.ysize.value, 1, 0xFFFF, "Real sprite paramater 'ysize'", self.ysize.pos) + generic.check_range(self.xpos.value, 0, 0x7FFFFFFF, "Real sprite parameter 'xpos'", self.xpos.pos) + generic.check_range(self.ypos.value, 0, 0x7FFFFFFF, "Real sprite parameter 'ypos'", self.ypos.pos) + generic.check_range(self.xsize.value, 1, 0xFFFF, "Real sprite parameter 'xsize'", self.xsize.pos) + generic.check_range(self.ysize.value, 1, 0xFFFF, "Real sprite parameter 'ysize'", self.ysize.pos) def validate_size(self): """ @@ -232,7 +232,7 @@ def get_cache_key(self, crop_sprites): """ - Assemble the sprite meta data into a key, able to identify the sprite. + Assemble the sprite metadata into a key, able to identify the sprite. @param crop_sprites: Whether to crop sprites, which allow it. @type crop_sprites: C{bool} @@ -492,14 +492,14 @@ new_sprite.xrel.value, -0x8000, 0x7FFF, - "Real sprite paramater {:d} 'xrel'".format(param_offset + 1), + "Real sprite parameter {:d} 'xrel'".format(param_offset + 1), new_sprite.xrel.pos, ) generic.check_range( new_sprite.yrel.value, -0x8000, 0x7FFF, - "Real sprite paramater {:d} 'yrel'".format(param_offset + 2), + "Real sprite parameter {:d} 'yrel'".format(param_offset + 2), new_sprite.yrel.pos, ) param_offset += 2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/ast/alt_sprites.py new/nml-0.8.1/nml/ast/alt_sprites.py --- old/nml-0.8.0/nml/ast/alt_sprites.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/ast/alt_sprites.py 2025-12-02 20:17:25.000000000 +0100 @@ -65,7 +65,7 @@ self.bit_depth = global_constants.bit_depths[param_list[2].value] else: raise generic.ScriptError( - "value for alternative_sprites parameter 3 'bit depth' is not a valid bit depthl", param_list[2].pos + "value for alternative_sprites parameter 3 'bit depth' is not a valid bit depth", param_list[2].pos ) if self.bit_depth == 32: global_constants.any_32bpp_sprites = global_constants.allow_32bpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/ast/base_statement.py new/nml-0.8.1/nml/ast/base_statement.py --- old/nml-0.8.0/nml/ast/base_statement.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/ast/base_statement.py 2025-12-02 20:17:25.000000000 +0100 @@ -84,7 +84,7 @@ def pre_process(self): """ Called to do any pre-processing before the actual action generation. - For example, to remove identifiesr + For example, to remove identifiers """ pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/ast/error.py new/nml-0.8.1/nml/ast/error.py --- old/nml-0.8.0/nml/ast/error.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/ast/error.py 2025-12-02 20:17:25.000000000 +0100 @@ -20,8 +20,8 @@ class Error(base_statement.BaseStatement): """ - An error has occured while parsing the GRF. This can be anything ranging from - an imcompatible GRF file that was found or a game setting that is set to the + An error has occurred while parsing the GRF. This can be anything ranging from + an incompatible GRF file that was found or a game setting that is set to the wrong value to a wrong combination of parameters. The action taken by the host depends on the severity level of the error. NML equivalent: error(level, message[, extra_text[, parameter1[, parameter2]]]). @@ -33,7 +33,7 @@ @type severity: L{Expression} @ivar msg: The string to be used for this error message. This can be either - one of the predifined error strings or a custom string from the + one of the predefined error strings or a custom string from the language file. @type msg: L{Expression} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/ast/grf.py new/nml-0.8.1/nml/ast/grf.py --- old/nml-0.8.0/nml/ast/grf.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/ast/grf.py 2025-12-02 20:17:25.000000000 +0100 @@ -305,6 +305,8 @@ class ParameterDescription: + free_bits = {} + def __init__(self, setting_list, num=None, pos=None): self.setting_list = setting_list self.num = num @@ -330,15 +332,31 @@ if self.num is None: self.num = num self.num = self.num.reduce_constant() + if self.num.value not in ParameterDescription.free_bits: + ParameterDescription.free_bits[self.num.value] = list(range(0, 32)) for setting in self.setting_list: setting.pre_process() for setting in self.setting_list: if setting.type == "int": - if len(self.setting_list) > 1: + if len(self.setting_list) > 1 or len(ParameterDescription.free_bits[self.num.value]) != 32: raise generic.ScriptError( - "When packing multiple settings in one parameter only bool settings are allowed", self.pos + "When packing multiple settings in one parameter only bool settings are allowed", + setting.name.pos, ) global_constants.settings[setting.name.value] = {"num": self.num.value, "size": 4} + ParameterDescription.free_bits[self.num.value].clear() else: - bit = 0 if setting.bit_num is None else setting.bit_num.value - global_constants.misc_grf_bits[setting.name.value] = {"param": self.num.value, "bit": bit} + if setting.bit_num is None: + if len(ParameterDescription.free_bits[self.num.value]) == 0: + raise generic.ScriptError("No bits available for this parameter", setting.name.pos) + setting.bit_num = expression.ConstantNumeric(ParameterDescription.free_bits[self.num.value].pop(0)) + else: + if setting.bit_num.value not in ParameterDescription.free_bits[self.num.value]: + raise generic.ScriptError( + "Bit {} is already used".format(setting.bit_num.value), setting.name.pos + ) + ParameterDescription.free_bits[self.num.value].remove(setting.bit_num.value) + global_constants.misc_grf_bits[setting.name.value] = { + "param": self.num.value, + "bit": setting.bit_num.value, + } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/ast/item.py new/nml-0.8.1/nml/ast/item.py --- old/nml-0.8.0/nml/ast/item.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/ast/item.py 2025-12-02 20:17:25.000000000 +0100 @@ -128,7 +128,7 @@ class Property: """ AST-node representing a single property. These are only valid - insde a PropertyBlock. + inside a PropertyBlock. @ivar name: The name (or number) of this property. @type name: L{Identifier} or L{ConstantNumeric}. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/ast/override.py new/nml-0.8.1/nml/ast/override.py --- old/nml-0.8.0/nml/ast/override.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/ast/override.py 2025-12-02 20:17:25.000000000 +0100 @@ -23,7 +23,7 @@ AST Node for an engine override. @ivar grfid: GRFid of the grf to override the engines from. - @type grfid: C{int{ + @type grfid: C{int} @ivar source_grfid: GRFid of the grf that overrides the engines. @type source_grfid: C{int} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/ast/switch.py new/nml-0.8.1/nml/ast/switch.py --- old/nml-0.8.0/nml/ast/switch.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/ast/switch.py 2025-12-02 20:17:25.000000000 +0100 @@ -117,7 +117,7 @@ ) return self.optimised is not self - self.optimised = self # Prevent multiple run on the same non optimisable Switch + self.optimised = self # Prevent multiple run on the same non-optimisable Switch return False def collect_references(self): @@ -390,7 +390,7 @@ if self.optimised: return self.optimised is not self - # Triggers have side-effects, and can't be skipped. + # Triggers have side effects, and can't be skipped. # Scope for expressions can be different in referencing location, so don't optimise them. if self.triggers.value == 0 and len(self.choices) == 1: optimised = self.choices[0].result.value @@ -407,7 +407,7 @@ self.optimised = optimised return True - self.optimised = self # Prevent multiple run on the same non optimisable RandomSwitch + self.optimised = self # Prevent multiple run on the same non-optimisable RandomSwitch return False def collect_references(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/ast/tilelayout.py new/nml-0.8.1/nml/ast/tilelayout.py --- old/nml-0.8.0/nml/ast/tilelayout.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/ast/tilelayout.py 2025-12-02 20:17:25.000000000 +0100 @@ -22,7 +22,7 @@ """ 'tile_layout' AST node. A TileLayout is a list of x,y-offset/tileID pairs. The x and y offsets are from the northernmost tile of the industry/airport. - Additionally some extra properties can be stored in the TileLayout, like + Additionally, some extra properties can be stored in the TileLayout, like the orientation of the airport. @ivar name: The name of this layout by which it can be referenced later. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/ast/townnames.py new/nml-0.8.1/nml/ast/townnames.py --- old/nml-0.8.0/nml/ast/townnames.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/ast/townnames.py 2025-12-02 20:17:25.000000000 +0100 @@ -208,7 +208,7 @@ finished_actions.extend(heap) - # To ensure the chances do not get messed up due to one part needing less bits for its + # To ensure the chances do not get messed up due to one part needing fewer bits for its # selection, all parts are forced to use the same number of bits. max_prob = max(sub[0] for sub in finished_actions) num_bits = 1 @@ -305,7 +305,7 @@ class TownNamesParam: """ Class containing a parameter of a town name. - Currently known key/values: + Currently, known key/values: - 'styles' / string expression """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/editors/extract_tables.py new/nml-0.8.1/nml/editors/extract_tables.py --- old/nml-0.8.0/nml/editors/extract_tables.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/editors/extract_tables.py 2025-12-02 20:17:25.000000000 +0100 @@ -80,6 +80,7 @@ action0properties.properties[0x01], action0properties.properties[0x02], action0properties.properties[0x03], + action0properties.properties[0x04], action0properties.properties[0x05], action0properties.properties[0x07], action0properties.properties[0x09], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/expression/binop.py new/nml-0.8.1/nml/expression/binop.py --- old/nml-0.8.0/nml/expression/binop.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/expression/binop.py 2025-12-02 20:17:25.000000000 +0100 @@ -173,7 +173,7 @@ expr1.add = ConstantNumeric(0) expr1.mod = expr2 return expr1 - # Since we have a lot of nml-variables that are in fact only the high bits of an nfo + # Since we have a lot of nml-variables that are in fact only the high bits of a nfo # variable it can happen that we want to shift back the variable to the left. # Don't use any extra opcodes but just reduce the shift-right in that case. if ( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/expression/functioncall.py new/nml-0.8.1/nml/expression/functioncall.py --- old/nml-0.8.0/nml/expression/functioncall.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/expression/functioncall.py 2025-12-02 20:17:25.000000000 +0100 @@ -92,7 +92,7 @@ @ivar varsize: Varsize for the action7/9 check @type varsize: C{int} - @ivar mask: Mask to to test only certain bits of the value + @ivar mask: Mask to test only certain bits of the value @type mask: C{int} @ivar pos: Position information @@ -183,7 +183,7 @@ """ max(...) builtin function. - @return Heighest value of the given arguments. + @return Highest value of the given arguments. """ if len(args) < 2: raise generic.ScriptError("max() requires at least 2 arguments", pos) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/expression/parameter.py new/nml-0.8.1/nml/expression/parameter.py --- old/nml-0.8.0/nml/expression/parameter.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/expression/parameter.py 2025-12-02 20:17:25.000000000 +0100 @@ -47,7 +47,7 @@ supported = isinstance(self.num, ConstantNumeric) if not supported and raise_error: raise generic.ScriptError( - "Parameter acessess with non-constant numbers are not supported in a switch-block.", self.pos + "Parameter accesses with non-constant numbers are not supported in a switch-block.", self.pos ) return supported @@ -100,12 +100,12 @@ def parse_string_to_dword(string): """ - Convert string literal expression of length 4 to it's equivalent 32 bit number. + Convert string literal expression of length 4 to its equivalent 32-bit number. @param string: Expression to convert. @type string: L{Expression} - @return: Value of the converted expression (a 32 bit integer number, little endian). + @return: Value of the converted expression (a 32-bit integer number, little endian). @rtype: C{int} """ if not isinstance(string, StringLiteral) or grfstrings.get_string_size(string.value, False, True) != 4: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/expression/special_parameter.py new/nml-0.8.1/nml/expression/special_parameter.py --- old/nml-0.8.0/nml/expression/special_parameter.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/expression/special_parameter.py 2025-12-02 20:17:25.000000000 +0100 @@ -36,7 +36,7 @@ Position information Return value is a 2-tuple: Left side of the assignment (must be a parameter) - Right side of the assignment (may be any expression) + Right side of the assignment (can be any expression) @type write_func: C{function} @ivar read_func: Function that will be called to read out the parameter value diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/expression/storage_op.py new/nml-0.8.1/nml/expression/storage_op.py --- old/nml-0.8.0/nml/expression/storage_op.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/expression/storage_op.py 2025-12-02 20:17:25.000000000 +0100 @@ -33,7 +33,7 @@ @ivar name: Name of the called storage function @type name: C{str} - @ivar info: Dictionary containting information about the operation to perform + @ivar info: Dictionary containing information about the operation to perform @type info: C{dict} @ivar value: Value to store, or C{None} for loading operations diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/free_number_list.py new/nml-0.8.1/nml/free_number_list.py --- old/nml-0.8.0/nml/free_number_list.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/free_number_list.py 2025-12-02 20:17:25.000000000 +0100 @@ -25,7 +25,7 @@ @type total_amount: C{int} @ivar stats: Statistics about id usage. - @type stats: Tuple of C{int} and L{Position} refering to the amount on location of most concurrently used ids. + @type stats: Tuple of C{int} and L{Position} referring to the amount on location of most concurrently used ids. @ivar free_numbers: The list with currently unused numbers. @type free_numbers: C{list} @@ -86,7 +86,7 @@ def pop_global(self, pos): """ Pop a free number from the list. The number may have been used before - and already been restored but it'll never be given out again. + and already been restored, but it'll never be given out again. @param pos: Positional context. @type pos: L{Position} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/generic.py new/nml-0.8.1/nml/generic.py --- old/nml-0.8.0/nml/generic.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/generic.py 2025-12-02 20:17:25.000000000 +0100 @@ -378,7 +378,7 @@ def print_progress(msg, incremental=False): """ - Output progess information to the user. + Output progress information to the user. @param msg: Progress message. @type msg: C{str} @@ -411,7 +411,7 @@ def print_info(msg): """ - Output a pure informational message to th euser. + Output a pure informational message to the user. """ if verbosity_level < VERBOSITY_INFO: return @@ -590,7 +590,7 @@ path = os.path.join(cache_root_dir, path) result = os.path.join(path, name) else: - # In case of multiple soure files, ignore the path component for all but the first + # In case of multiple source files, ignore the path component for all but the first result += "_" + name return result + extension diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/global_constants.py new/nml-0.8.1/nml/global_constants.py --- old/nml-0.8.0/nml/global_constants.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/global_constants.py 2025-12-02 20:17:25.000000000 +0100 @@ -385,6 +385,16 @@ # station tiles "STAT_ALL_TILES" : 0xFF, + # bridge pillar flags + "BRIDGE_PILLAR_CORNER_W" : 0, + "BRIDGE_PILLAR_CORNER_S" : 1, + "BRIDGE_PILLAR_CORNER_E" : 2, + "BRIDGE_PILLAR_CORNER_N" : 3, + "BRIDGE_PILLAR_EDGE_NE" : 4, + "BRIDGE_PILLAR_EDGE_SE" : 5, + "BRIDGE_PILLAR_EDGE_SW" : 6, + "BRIDGE_PILLAR_EDGE_NW" : 7, + # house flags "HOUSE_FLAG_NOT_SLOPED" : 1, "HOUSE_FLAG_ANIMATE" : 5, @@ -1294,7 +1304,7 @@ def map_exponentiate(expr, info): """ - Given a exponent, add an offset to it and compute the exponentiation with base 2. + Given an exponent, add an offset to it and compute the exponentiation with base 2. @param expr: The exponent. @type expr: L{Expression} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/grfstrings.py new/nml-0.8.1/nml/grfstrings.py --- old/nml-0.8.0/nml/grfstrings.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/grfstrings.py 2025-12-02 20:17:25.000000000 +0100 @@ -49,7 +49,7 @@ def is_ascii_string(string): """ Check whether a given string can be written using the ASCII codeset or - that we need unicode. + that we need Unicode. @param string: The string to check. @type string: C{str} @@ -81,7 +81,7 @@ @param string: The string to check. @type string: C{str} - @param final_zero: Whether or not to account for a zero-byte directly after the string. + @param final_zero: Whether to account for a zero-byte directly after the string. @type final_zero: C{bool} @param force_ascii: When true, make sure the string is written as ascii as opposed to unicode. @@ -421,14 +421,14 @@ """ Convert the string command to output text. - @param str_type: Exptected type of result text, C{"unicode"} or C{"ascii"}. + @param str_type: Expected type of result text, C{"unicode"} or C{"ascii"}. @type str_type: C{str} @param lang: Language of the string. @type lang: L{Language} @param wanted_lang_id: Language-id to use for interpreting the command - (this string may be from another language, eg with missing strings). + (this string may be from another language, e.g. with missing strings). @param prev_command: Argument of previous string command (parameter number, size). @type prev_command: C{tuple} or C{None} @@ -677,7 +677,6 @@ raise generic.ScriptError('Invalid case-name "{}"'.format(case), pos) command.case = lang.cases[case] if string[end] != "}": - command.argument_is_assigment = string[end] == "=" arg_start = end + 1 end = string.find("}", end + 1) if end == -1 or not command.set_arguments(string[arg_start:end]): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/main.py new/nml-0.8.1/nml/main.py --- old/nml-0.8.0/nml/main.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/main.py 2025-12-02 20:17:25.000000000 +0100 @@ -308,7 +308,7 @@ input = sys.stdin else: input = codecs.open(generic.find_file(input_filename), "r", "utf-8") - # Only append an output grf name, if no ouput is given, also not implicitly via -M + # Only append an output grf name, if no output is given, also not implicitly via -M if not opts.outputfile_given and not outputs: opts.grf_filename = filename_output_from_input(input_filename, ".grf") @@ -528,7 +528,7 @@ last_file = None for f_pair in sprite_files: - # Palette is defined by mask_file, if present. Otherwise by the main file. + # Palette is defined by mask_file, if present. Otherwise, by the main file. f = f_pair[1] if f is None: f = f_pair[0] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/output_base.py new/nml-0.8.1/nml/output_base.py --- old/nml-0.8.0/nml/output_base.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/output_base.py 2025-12-02 20:17:25.000000000 +0100 @@ -316,7 +316,7 @@ def print_data(self, data): """ - Print a chunck of data in one go + Print a chunk of data in one go @param data: Data to output @type data: C{array} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/output_grf.py new/nml-0.8.1/nml/output_grf.py --- old/nml-0.8.0/nml/output_grf.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/output_grf.py 2025-12-02 20:17:25.000000000 +0100 @@ -34,7 +34,7 @@ def open_file(self): # Remove / unlink the file, most useful for linux systems # See also issue #4165 - # If the file happens to be in use or non-existant, ignore + # If the file happens to be in use or non-existent, ignore try: os.unlink(self.filename) except OSError: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml/spriteencoder.py new/nml-0.8.1/nml/spriteencoder.py --- old/nml-0.8.0/nml/spriteencoder.py 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/nml/spriteencoder.py 2025-12-02 20:17:25.000000000 +0100 @@ -180,7 +180,7 @@ """ Get encoded sprite date, either from cache, or new. - @param sprite_info: Sprite meta data + @param sprite_info: Sprite metadata @type sprite_info: C{RealSprite} """ @@ -253,7 +253,7 @@ """ Crop and compress a real sprite. - @param sprite_info: Sprite meta data + @param sprite_info: Sprite metadata @type sprite_info: C{RealSprite} @return: size_x, size_y, xoffset, yoffset, compressed_data, info_byte, crop_rect, pixel_stats diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/nml.egg-info/PKG-INFO new/nml-0.8.1/nml.egg-info/PKG-INFO --- old/nml-0.8.0/nml.egg-info/PKG-INFO 2025-06-21 21:12:41.000000000 +0200 +++ new/nml-0.8.1/nml.egg-info/PKG-INFO 2025-12-02 20:17:28.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: nml -Version: 0.8.0 +Version: 0.8.1 Summary: An OpenTTD NewGRF compiler for the nml language Home-page: https://github.com/OpenTTD/nml Author: NML Development Team diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/pyproject.toml new/nml-0.8.1/pyproject.toml --- old/nml-0.8.0/pyproject.toml 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/pyproject.toml 2025-12-02 20:17:25.000000000 +0100 @@ -1,2 +1,6 @@ [build-system] requires = ["setuptools", "ply"] + +[tool.black] +line-length = 120 +exclude = 'action2var_variables.py|action3_callbacks.py|ply|setup.py' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/regression/013_train_callback.nml new/nml-0.8.1/regression/013_train_callback.nml --- old/nml-0.8.0/regression/013_train_callback.nml 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/regression/013_train_callback.nml 2025-12-02 20:17:25.000000000 +0100 @@ -136,6 +136,8 @@ speed: 0; refit_cost: 40; track_type: RAIL; + track_type: [RAIL]; + track_type: [RAIL, ELRL]; power: 0; running_cost_base: RUNNING_COST_STEAM; cargo_capacity: 30; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/regression/021_grf_parameter.nml new/nml-0.8.1/regression/021_grf_parameter.nml --- old/nml-0.8.0/regression/021_grf_parameter.nml 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/regression/021_grf_parameter.nml 2025-12-02 20:17:25.000000000 +0100 @@ -39,6 +39,22 @@ }; } } + param (2) { + param_NoGrid { + type: bool; + name: string(STR_PARAM_NOGRID); + desc: string(STR_PARAM_NOGRID_DESC); + def_value: 1; + } + } + param (2) { + transmitter2rock { + type: bool; + name: string(STR_PARAM_TRANSMITTER); + desc: string(STR_PARAM_TRANSMITTER_DESC); + def_value: 0; + } + } } param[10] = param_landscape; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/regression/040_station.nml new/nml-0.8.1/regression/040_station.nml --- old/nml-0.8.0/regression/040_station.nml 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/regression/040_station.nml 2025-12-02 20:17:25.000000000 +0100 @@ -135,6 +135,17 @@ [6, 7] ], ]; + heights: [1, 1, 2, 2, 3, 3, 4, 4]; + blocked_pillars: [ + bitmask(BRIDGE_PILLAR_CORNER_N, BRIDGE_PILLAR_CORNER_E), + bitmask(BRIDGE_PILLAR_CORNER_S, BRIDGE_PILLAR_CORNER_W), + bitmask(BRIDGE_PILLAR_CORNER_N, BRIDGE_PILLAR_CORNER_E), + bitmask(BRIDGE_PILLAR_CORNER_S, BRIDGE_PILLAR_CORNER_W), + bitmask(BRIDGE_PILLAR_CORNER_N, BRIDGE_PILLAR_CORNER_E, BRIDGE_PILLAR_EDGE_NE, BRIDGE_PILLAR_EDGE_NW), + bitmask(BRIDGE_PILLAR_CORNER_S, BRIDGE_PILLAR_CORNER_W, BRIDGE_PILLAR_EDGE_SE, BRIDGE_PILLAR_EDGE_SW), + bitmask(BRIDGE_PILLAR_CORNER_N, BRIDGE_PILLAR_CORNER_E, BRIDGE_PILLAR_EDGE_NE, BRIDGE_PILLAR_EDGE_NW), + bitmask(BRIDGE_PILLAR_CORNER_S, BRIDGE_PILLAR_CORNER_W, BRIDGE_PILLAR_EDGE_SE, BRIDGE_PILLAR_EDGE_SW), + ]; } graphics { foundations: 0; Binary files old/nml-0.8.0/regression/expected/013_train_callback.grf and new/nml-0.8.1/regression/expected/013_train_callback.grf differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/regression/expected/013_train_callback.nfo new/nml-0.8.1/regression/expected/013_train_callback.nfo --- old/nml-0.8.0/regression/expected/013_train_callback.nfo 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/regression/expected/013_train_callback.nfo 2025-12-02 20:17:25.000000000 +0100 @@ -223,11 +223,11 @@ 69 * 9 0D 7E \D<< 01 FF \dxFFFFFFF8 70 * 12 06 -7F 01 FF \wx004D -7E 01 FF \wx004F +7F 01 FF \wx0053 +7E 01 FF \wx0055 FF -71 * 82 00 00 \b26 01 FF \wx0074 +71 * 88 00 00 \b28 01 FF \wx0074 06 0F 28 \wx0010 1D \dx00000000 @@ -249,6 +249,9 @@ 09 \wx0000 1C 28 05 00 +05 00 +34 \b2 +00 01 0B \wx0000 0E \dx00004C30 14 1E Binary files old/nml-0.8.0/regression/expected/021_grf_parameter.grf and new/nml-0.8.1/regression/expected/021_grf_parameter.grf differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/regression/expected/021_grf_parameter.nfo new/nml-0.8.1/regression/expected/021_grf_parameter.nfo --- old/nml-0.8.0/regression/expected/021_grf_parameter.nfo 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/regression/expected/021_grf_parameter.nfo 2025-12-02 20:17:25.000000000 +0100 @@ -7,10 +7,10 @@ 0 * 4 \d3 -1 * 817 14 "C" "INFO" +1 * 1254 14 "C" "INFO" "B" "VRSN" \w4 \dx00000001 "B" "MINV" \w4 \dx00000000 -"B" "NPAR" \w1 03 +"B" "NPAR" \w1 05 "C" "PARA" "C" \d0 "T" "NAME" 7F "Disable gridlines" 00 @@ -41,6 +41,20 @@ 00 "B" "DFLT" \w4 \dx00000000 00 +"C" \d3 +"T" "NAME" 7F "Disable gridlines" 00 +"T" "DESC" 7F "This setting allows to replace all ground sprites such that the landscape is painted (mostly) without grid lines. Note that roads and train tracks don't yet follow this rule" 00 +"B" "TYPE" \w1 01 +"B" "MASK" \w3 \b2 \b0 \b1 +"B" "DFLT" \w4 \dx00000001 +00 +"C" \d4 +"T" "NAME" 7F "Replace the transmitter tower by a rock" 00 +"T" "DESC" 7F "Enable to replace the transmitter tower by a rock (useful for early scenarios without telecomunication towers)" 00 +"B" "TYPE" \w1 01 +"B" "MASK" \w3 \b2 \b1 \b1 +"B" "DFLT" \w4 \dx00000000 +00 00 "B" "PALS" \w1 "A" "B" "BLTR" \w1 "8" Binary files old/nml-0.8.0/regression/expected/040_station.grf and new/nml-0.8.1/regression/expected/040_station.grf differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.8.0/regression/expected/040_station.nfo new/nml-0.8.1/regression/expected/040_station.nfo --- old/nml-0.8.0/regression/expected/040_station.nfo 2025-06-21 21:12:37.000000000 +0200 +++ new/nml-0.8.1/regression/expected/040_station.nfo 2025-12-02 20:17:25.000000000 +0100 @@ -21,7 +21,7 @@ 4 * 16 00 08 \b1 02 FF \wx0000 09 "COAL" "LVST" -5 * 47 00 04 \b6 01 FF \wx00FF +5 * 71 00 04 \b8 01 FF \wx00FF 08 "TEST" 13 18 12 \dx00000002 @@ -35,6 +35,10 @@ 04 04 06 06 \b0 \b0 +20 FF \w8 +01 01 02 02 03 03 04 04 +21 FF \w8 +0C 03 0C 03 9C 63 9C 63 6 * 11 04 04 FF 01 \wxC4FF "Test" 00
