Files
GTASource/game/VS_Project_NM/CheckForNmApiChanges.rb
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

111 lines
4.8 KiB
Ruby

# The Natural Motion API is defined by a set of strings in NmRsMessageDefinitions.h which
# are accessed via enums in game code. The enum <--> string mapping is in CNmDefines and
# needs to be kept up to date with the NmRsMessageDefinitions.h which is where this little
# script comes in.
#
# Strip out everything but the API strings from NmRsMessageDefinitions and compare with
# the strings in NmDefines.cpp.
#
# Started on : 18/2/10
# Author : Richard Archibald
# Some defines to allow this script to work from any location and under different projects
# more easily.
PROJECT_BASE = "x:/gta5/src/dev_nm"
RAGE_DIR = "#{PROJECT_BASE}/rage"
# EXECUTION START:
if __FILE__ == $0
# Open the files to compare.
puts "Opening \"#{RAGE_DIR}/naturalmotion/src/rockstar/NmRsMessageDefinitions.h\""
nmApiFile = File.open("#{RAGE_DIR}/naturalmotion/src/rockstar/NmRsMessageDefinitions.h", "r")
puts "Opening \"#{PROJECT_BASE}/game/task/Physics/NmDefines.cpp\""
gameDefinesFile = File.open("#{PROJECT_BASE}/game/task/Physics/NmDefines.cpp", "r")
# Create two temporary files to store the stripped down versions of the two files
# above. These are the files we will actually run a diff on.
puts "Creating temporary files..."
nmApiCmpFile = File.new("NmApiStrings.txt", "w")
puts "done 1 ok."
gameCmpFile = File.new("GameSideApiStrings.txt", "w")
puts "done 2 ok."
# Iterate over each line of NmRsMessageDefinitions.h and spit out the strings into a
# temporary file.
nmApiFile.each_line do |line|
line.chomp!().strip!() # Get rid of the trailing '\n' character and any leading or trailing whitespace.
if line.match('BEHAVIOUR\(.*\)') && !line.match('BEHAVIOUR\(stopAllBehaviours\)')
apiString = line
#apiString = apiString.sub("BEHAVIOUR\(", "") # Delete "BEHAVIOUR(".
#apiString.chomp!("\)") # Delete the trailing right parenthesis.
nmApiCmpFile.puts("============================== #{apiString} ==============================")
elsif line.match('PARAMETER\(.*\)')
apiString = line
apiString = apiString.sub("PARAMETER\(", "")
apiString = apiString.slice(0..apiString.index(',')-1) # Delete from the first comma onwards.
nmApiCmpFile.puts("\"#{apiString}\"")
end
end
# Iterate over each line of NmDefines.cpp and spit out the API strings into a temporary file to
# compare with the one we just made above. This file is complicated by the fact that there are other
# bits of code and definitions in there that have nothing to do with the API. Use a flag to keep track of
# whether we've reached the start of the static string definitions of the API.
bApiSentinelFound = false
bThisLineIsBlank = false
gameDefinesFile.each_line do |line|
line.chomp!().strip!() # Get rid of the trailing '\n' character and any leading or trailing whitespace.
# Only parse those lines which are in the API string block. When the final "}" is found, set the
# sentinel flag back to false to skip over any remaining code in the file.
if bApiSentinelFound && line != "{" && !line.match("\"stopAllBehaviours\"") && !line.match("\"start\"")
# Have we reached the end of the API string block?
if line == "};"
bApiSentinelFound = false
else
# ***** PARSE THE API STRING BLOCK *****
apiString = line
# If a line is blank, the next valid string should be a behaviour name. Flag this so that we
# can insert a marker in the txt file to aid comparison.
bLastLineWasBlank = bThisLineIsBlank
bThisLineIsBlank = false
if apiString == ""
bThisLineIsBlank = true
end
# Skip blank lines, feedback messages, any C++ comment lines which might be in there and the
# final "nmstring_end" string.
if apiString != "" && apiString.match(/^\".+\" *,/) && !apiString.match(/_FB,$/)
apiString = apiString.slice(0..apiString.index(',')-1) # Delete from the first comma onwards.
if bLastLineWasBlank
2.times do apiString.sub!("\"", "") end # Lose the quotes.
gameCmpFile.puts("============================== BEHAVIOUR(#{apiString}) ==============================")
else
gameCmpFile.puts("#{apiString}")
end
end
end
end
# Check for API string block. This goes at the end of the loop so that we don't parse the sentinel
# itself.
if line.match('CNmDefines::ms_aNMStrings')
bApiSentinelFound = true
end
end
# Close all files.
nmApiFile.close()
gameDefinesFile.close()
nmApiCmpFile.close()
gameCmpFile.close()
puts "All files closed, comparing files..."
# Visualise the differences using an external merge program with GUI.
system('"C:\Program Files\Perforce\p4merge.exe" NmApiStrings.txt GameSideApiStrings.txt')
puts "Finished."
end