# # This script parses the CraftingManager.java file decompiled by mcp5 from # the Minecraft code. It generates ruby datastructures/constants etc. # craftingmanager_file = 'CraftingManager.java' lang_file = 'en_US.lang' block_file = 'Block.java' if ARGV.length >= 1 lang_file = ARGV[0] elsif ARGV.length >= 2 block_file ARGV[1] elsif ARGV.length >= 3 craftingmanager_file ARGV[2] end if not File.exists? lang_file or not File.exists? craftingmanager_file or not File.exists? block_file puts "Options: %s " % [$0] exit end # load language mappings: @@lang = {} IO.read(lang_file).scan(%r{^([^=]+)=(.*)$}).each do |pairs| @@lang[pairs[0].strip] = pairs[1].strip end # load block instance -> names @@blocks = {} block_java = IO.read(block_file) block_java.scan(%r{^([^=]+) = [^;]+setBlockName\("([^\"]+)"\)}).each do |m| @@blocks[m[0].strip] = m[1].strip end items = {} #unused block_java.scan(%r{^Item\.itemsList\[([^=]+)\.blockID\] = [^;]+setItemName\("([^\"]+)"\)}).each do |m| items[m[0]] = m[1] end # converts java constants to their real name in language file: def const_to_string(const) const.match /[^\.]+\.(.*)/ const = $1 if @@blocks.has_key? const lang_key = @@blocks[const] else lang_key = const end lang_name = nil @@lang.each_key do |key| if key.include? ".#{lang_key}." if not @@lang[key].empty? lang_name = @@lang[key] break end end end if lang_name and not lang_name.empty? name = lang_name elsif lang_name and lang_name.empty? puts puts "# WARNING!! empty lang name for #{const}" name = const else puts puts "# WARNING!! no lang found for #{const}" name = const end "'" + name.gsub("'", "") + "'" end # generate recipes puts "# Generated: #{Time.now}" puts puts "::MinecraftRecipes = {" IO.read(craftingmanager_file).scan(%r{addRecipe\(([^;]+)\);}m).each do |recipe| recipe = recipe.first # each recipe contains an ItemStack and an Object array, # first seperate them both: raise 'item stack parse error' if not recipe.match /new ItemStack\(([^,]+), (\d+)/ product, amount = const_to_string($1), $2.to_i puts "# product:#{product.inspect} amount:#{amount.inspect}" # Object array contains the recipe itself and all ingridients # we are only interested in each ingridient and the amount raise 'recipe array parse error' if not recipe.match /new Object\[\] {([^}]+)}/ recipe_array = $1 recipe_mapping = '' recipe_ingredients = {} tmp_amount = 0 recipe_array.split(',').each do |arg| arg.strip! # recipe mappings if arg.match /^"([^"]+)"$/ recipe_mapping += $1 # item representation in mapping elsif arg.match /Character\.valueOf\('(.)'\)/ tmp_amount = recipe_mapping.count($1) # the actual item or block within the recipe: elsif arg.match /^((Item|Block)\..*)$/ item = const_to_string($1) recipe_ingredients[item] = tmp_amount if tmp_amount <= 0 puts "# WARNING: ingredient with mapping?" end end end puts < { :amount => #{amount}, :ingredients => { EOF recipe_ingredients.each_pair do |item, amount| puts " #{item} => #{amount}," end puts <