[Proposal] Implementing FSCRIPT: Deploy-time file modification #6

Closed
opened 2024-07-18 00:33:38 -04:00 by bonkmaykr · 2 comments
Owner

Some modders will want to have files be modified automatically by Firestar using a patch system rather than replace the entire file in order to avoid compatibility issues with other mods. As of 1.2, Firestar is not capable of doing this, it simply repacks files. 1.3 changes this.

After some internal discussion, I've come up with a format that Firestar will use to make these changes.

A file will be placed at the root of the FSTAR (along with data/ and pack.png) called changes.fscript, this file instructs Firestar in sequential order what alterations to make. This can be used as an alternative to file replacements.

I don't intend on removing the data/ folder requirement for Generate New Mod from Folder... so if your mod only uses this fscript and nothing else then an empty data/ folder will suffice.

My only concern with this approach is that it's somewhat complicated to implement as it would require making our own parser.

File paths start from FSTAR root (~/.firestar/temp/ during deploy-time).

List of commands and their usages:

locate [path]

Selects the current working file. If this fails, then for safety, all other commands are skipped until the next locate and a warning is printed.

delete [all|which] [text]

all deletes all matches, which is any integer starting from 0 that points to an instance of that text. For example, if it appears 3 times:

The quick brown fox jumps over the lazy dog.
The lazy dog sleeps under the quick brown fox.
The dog is lazy, and sleeps, as the quick brown fox frolics.

...And we use delete 1 "quick brown fox"

Then:

The quick brown fox jumps over the lazy dog.
The lazy dog sleeps under the .
The dog is lazy, and sleeps, as the quick brown fox frolics.

all is implied by default.

replace [all|which] [text1] [text2]

Replaces text1 with text2. Same rules apply as above.

replace all "AG-SYSTEMS" "GTech"

all is implied by default.

apply-diff [path]

Applies the patch file at the specified path location to the currently selected file.
Example:

locate data/plugins/music/Definition.xml
apply-diff customplaylist.fpatch

Dedicated XML editing options also included below, use those when possible.

xml select [css selector] <which>

Selects an XML object inside the current file, only if valid XML is present.
If which is not specified then the first match is selected.

xml select-child [css selector] <which>

Same syntax as previous. Selects the child of the current selected object.

xml select-parent

Self-explanatory.

xml add-child [tagname] [attributes]

Gives a child to the currently selected XML node.
Example: xml add-child Image src="data/SomeImage.gxt"

xml delete

Deletes the current node and it's children. Afterward, selection is automatically moved to the parent if it exists, otherwise nothing is selected.

xml append [path]

Copies the specified path XML into the selected XML node.

locate data/xml/SomeGUI.xml
xml select Image[src="*SomeImage.gxt"] 0
xml append ImageThing.xml

xml merge [path]

Combines the selected XML file and specified path XML.

locate data/plugins/languages/American/entries.xml
xml merge customplaylist.xml
Some modders will want to have files be modified automatically by Firestar using a patch system rather than replace the entire file in order to avoid compatibility issues with other mods. As of 1.2, Firestar is not capable of doing this, it simply repacks files. 1.3 changes this. After some internal discussion, I've come up with a format that Firestar will use to make these changes. A file will be placed at the root of the FSTAR (along with data/ and pack.png) called changes.fscript, this file instructs Firestar in sequential order what alterations to make. This can be used as an alternative to file replacements. I don't intend on removing the data/ folder requirement for `Generate New Mod from Folder...` so if your mod only uses this fscript and nothing else then an empty data/ folder will suffice. My only concern with this approach is that it's somewhat complicated to implement as it would require making our own parser. **File paths start from FSTAR root (~/.firestar/temp/ during deploy-time).** ## List of commands and their usages: ### `locate [path]` Selects the current working file. If this fails, then for safety, all other commands are skipped until the next `locate` and a warning is printed. ### `delete [all|which] [text]` `all` deletes all matches, `which` is any integer starting from 0 that points to an instance of that text. For example, if it appears 3 times: The quick brown fox jumps over the lazy dog. The lazy dog sleeps under the quick brown fox. The dog is lazy, and sleeps, as the quick brown fox frolics. ...And we use `delete 1 "quick brown fox"` Then: The quick brown fox jumps over the lazy dog. The lazy dog sleeps under the . The dog is lazy, and sleeps, as the quick brown fox frolics. `all` is implied by default. ### `replace [all|which] [text1] [text2]` Replaces text1 with text2. Same rules apply as above. `replace all "AG-SYSTEMS" "GTech"` `all` is implied by default. ### `apply-diff [path]` Applies the patch file at the specified `path` location to the currently selected file. Example: locate data/plugins/music/Definition.xml apply-diff customplaylist.fpatch Dedicated XML editing options also included below, use those when possible. ### `xml select [css selector] <which>` Selects an XML object inside the current file, only if valid XML is present. If which is not specified then the first match is selected. ### `xml select-child [css selector] <which>` Same syntax as previous. Selects the child of the current selected object. ### `xml select-parent` Self-explanatory. ### `xml add-child [tagname] [attributes]` Gives a child to the currently selected XML node. Example: `xml add-child Image src="data/SomeImage.gxt"` ### `xml delete` Deletes the current node and it's children. Afterward, selection is automatically moved to the parent if it exists, otherwise nothing is selected. ### `xml append [path]` Copies the specified `path` XML into the selected XML node. locate data/xml/SomeGUI.xml xml select Image[src="*SomeImage.gxt"] 0 xml append ImageThing.xml ### `xml merge [path]` Combines the selected XML file and specified `path` XML. locate data/plugins/languages/American/entries.xml xml merge customplaylist.xml
bonkmaykr added the
enhancement
help wanted
action plan
labels 2024-07-18 00:33:38 -04:00
Collaborator

An example of the proposal that is currently being implemented.

# WBs FScript Proposal
# This script proposal intends to make functions and commands clear, and allow
# advanced configuration within mod files that go beyond simple changes. It is
# intended to give the complete tools to dynamically change files without
# making breaking changes.
fscript 1

# FScript is simple, as in everything can be boiled down to a single line. This
# example line below replaces a string in a file.
file "data/plugins/languages/american/entries.xml" xstr replace "string=\"Feisar" "string=\"Pepsi"
# This works well, but if we want to make more changes to the same file, it is
# extremely inefficient. Let's change "Auricom" to "Coke", and "Qirex" to 
# "Sprite" too.
file "data/plugins/languages/american/entries.xml" {
	xstr replace "string=\"Auricom" "string=\"Coke"
	xstr replace "string=\"Qirex" "string=\"Sprite"
}
# What we're doing here in the brackets is defining the "context block". This 
# allows using the same definition without redefining it, like we did with our
# file. Many commands under Fscript define a context that can be used with
# blocks, making the script much cleaner and easier to read.

# FILE [context:path]
# Opens a file for modifications.
file "data/plugins/languages/american/entries.xml" {
	# XML [create|modify|delete] [context:selector]
	# Modifies elements in the working file as XML.
	xml modify StringTable.entry#MT_12 set attribute "string" "Darude\nSandstorm"
	
	# Passing selector as a context
	xml create StringTable.entry#MT_13 {
		# SET [attribute|value] <values...>
		set attribute "string" "Rick Astley\nNever Gonna Give You Up"
	}
	
	# [xstr|str] [append|delete|replace] [find] <replace> <offset> <limit>
	# Finds and replaces files. STR is case-sensitive while XSTR is not.
	xstr replace "string=\"Feisar" "string=\"Pepsi"
	# Quotes can be escaped with a backslash [\].
}

# DELETE
# Deletes a file.
file "data/audio/music/01/music_stereo.fft" delete
file "data/audio/music/02/music_stereo.fft" delete
file "data/audio/music/03/music_stereo.fft" delete
file "data/audio/music/04/music_stereo.fft" delete
file "data/audio/music/05/music_stereo.fft" delete
file "data/audio/music/06/music_stereo.fft" delete
file "data/audio/music/07/music_stereo.fft" delete
file "data/audio/music/08/music_stereo.fft" delete
file "data/audio/music/09/music_stereo.fft" delete
file "data/audio/music/10/music_stereo.fft" delete
file "data/audio/music/11/music_stereo.fft" delete

# I feel like screwing up a file for no reason.
# BINEDIT [offset] [byte]
# Changes binary data. This example changes the 100th byte to 0x01.
file "data/audio/sound/speech.bnk" binedit 100 01
# More than one byte can be changed at a time.
file "data/audio/sound/speech.bnk" binedit 0 FFFFFFFF

file "data/plugins/music/Definition.xml" {
	# PATCH [file]
	# Patches a file with a unified patch.
	#patch "mod/Definition.xml.patch"
	# XML MERGE [file]
	# Merges the defined XML document with the context.
	xml merge "mod/Definition.xml"
}
An example of the proposal that is currently being implemented. ``` # WBs FScript Proposal # This script proposal intends to make functions and commands clear, and allow # advanced configuration within mod files that go beyond simple changes. It is # intended to give the complete tools to dynamically change files without # making breaking changes. fscript 1 # FScript is simple, as in everything can be boiled down to a single line. This # example line below replaces a string in a file. file "data/plugins/languages/american/entries.xml" xstr replace "string=\"Feisar" "string=\"Pepsi" # This works well, but if we want to make more changes to the same file, it is # extremely inefficient. Let's change "Auricom" to "Coke", and "Qirex" to # "Sprite" too. file "data/plugins/languages/american/entries.xml" { xstr replace "string=\"Auricom" "string=\"Coke" xstr replace "string=\"Qirex" "string=\"Sprite" } # What we're doing here in the brackets is defining the "context block". This # allows using the same definition without redefining it, like we did with our # file. Many commands under Fscript define a context that can be used with # blocks, making the script much cleaner and easier to read. # FILE [context:path] # Opens a file for modifications. file "data/plugins/languages/american/entries.xml" { # XML [create|modify|delete] [context:selector] # Modifies elements in the working file as XML. xml modify StringTable.entry#MT_12 set attribute "string" "Darude\nSandstorm" # Passing selector as a context xml create StringTable.entry#MT_13 { # SET [attribute|value] <values...> set attribute "string" "Rick Astley\nNever Gonna Give You Up" } # [xstr|str] [append|delete|replace] [find] <replace> <offset> <limit> # Finds and replaces files. STR is case-sensitive while XSTR is not. xstr replace "string=\"Feisar" "string=\"Pepsi" # Quotes can be escaped with a backslash [\]. } # DELETE # Deletes a file. file "data/audio/music/01/music_stereo.fft" delete file "data/audio/music/02/music_stereo.fft" delete file "data/audio/music/03/music_stereo.fft" delete file "data/audio/music/04/music_stereo.fft" delete file "data/audio/music/05/music_stereo.fft" delete file "data/audio/music/06/music_stereo.fft" delete file "data/audio/music/07/music_stereo.fft" delete file "data/audio/music/08/music_stereo.fft" delete file "data/audio/music/09/music_stereo.fft" delete file "data/audio/music/10/music_stereo.fft" delete file "data/audio/music/11/music_stereo.fft" delete # I feel like screwing up a file for no reason. # BINEDIT [offset] [byte] # Changes binary data. This example changes the 100th byte to 0x01. file "data/audio/sound/speech.bnk" binedit 100 01 # More than one byte can be changed at a time. file "data/audio/sound/speech.bnk" binedit 0 FFFFFFFF file "data/plugins/music/Definition.xml" { # PATCH [file] # Patches a file with a unified patch. #patch "mod/Definition.xml.patch" # XML MERGE [file] # Merges the defined XML document with the context. xml merge "mod/Definition.xml" } ```
Author
Owner

Above demo from Wirlaburla was implemented -- closing

Above demo from Wirlaburla was implemented -- closing
Sign in to join this conversation.
No description provided.