steam.gd 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. class_name _ModLoaderSteam
  2. extends Node
  3. const LOG_NAME := "ModLoader:ThirdParty:Steam"
  4. # Methods related to Steam and the Steam Workshop
  5. # Get mod zip paths from steam workshop folders.
  6. # folder structure of a workshop item
  7. # <workshop folder>/<steam app id>/<workshop item id>/<mod>.zip
  8. static func find_steam_workshop_zips() -> Array[String]:
  9. # TODO: use new diraccess methods + filter
  10. var zip_paths: Array[String] = []
  11. var workshop_folder_path := _get_path_to_workshop()
  12. ModLoaderLog.info("Checking workshop items, with path: \"%s\"" % workshop_folder_path, LOG_NAME)
  13. var workshop_dir := DirAccess.open(workshop_folder_path)
  14. if workshop_dir == null:
  15. ModLoaderLog.error("Can't open workshop folder %s (Error: %s)" % [workshop_folder_path, error_string(DirAccess.get_open_error())], LOG_NAME)
  16. return []
  17. var workshop_dir_listdir_error := workshop_dir.list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547
  18. if not workshop_dir_listdir_error == OK:
  19. ModLoaderLog.error("Can't read workshop folder %s (Error: %s)" % [workshop_folder_path, error_string(workshop_dir_listdir_error)], LOG_NAME)
  20. return []
  21. # Loop 1: Workshop folders
  22. while true:
  23. # Get the next workshop item folder
  24. var item_dir := workshop_dir.get_next()
  25. if item_dir == '':
  26. break
  27. var item_path := workshop_dir.get_current_dir() + "/" + item_dir
  28. ModLoaderLog.info("Checking workshop item path: \"%s\"" % item_path, LOG_NAME)
  29. # Only check directories
  30. if not workshop_dir.current_is_dir():
  31. continue
  32. # Loop 2: ZIPs inside the workshop folders
  33. zip_paths.append_array(_ModLoaderPath.get_zip_paths_in(ProjectSettings.globalize_path(item_path)))
  34. workshop_dir.list_dir_end()
  35. return zip_paths
  36. # Get the path to the Steam workshop folder. Only works for Steam games, as it
  37. # traverses directories relative to where a Steam game and its workshop content
  38. # would be installed. Based on code by Blobfish (developer of Brotato).
  39. # For reference, these are the paths of a Steam game and its workshop folder:
  40. # GAME = Steam/steamapps/common/GameName
  41. # WORKSHOP = Steam/steamapps/workshop/content/AppID
  42. # Eg. Brotato:
  43. # GAME = Steam/steamapps/common/Brotato
  44. # WORKSHOP = Steam/steamapps/workshop/content/1942280
  45. static func _get_path_to_workshop() -> String:
  46. if ModLoaderStore.ml_options.override_path_to_workshop:
  47. return ModLoaderStore.ml_options.override_path_to_workshop
  48. var game_install_directory := _ModLoaderPath.get_local_folder_dir()
  49. var path := ""
  50. # Traverse up to the steamapps directory (ie. `cd ..\..\` on Windows)
  51. var path_array := game_install_directory.split("/")
  52. path_array.resize(path_array.size() - 3)
  53. # Reconstruct the path, now that it has "common/GameName" removed
  54. path = "/".join(path_array)
  55. # Append the game's workshop path
  56. path = path.path_join("workshop/content/" + _get_steam_app_id())
  57. return path
  58. # Gets the steam app ID from ml_options or the steam_data.json, which should be in the root
  59. # directory (ie. res://steam_data.json). This file is used by Godot Workshop
  60. # Utility (GWU), which was developed by Brotato developer Blobfish:
  61. # https://github.com/thomasgvd/godot-workshop-utility
  62. static func _get_steam_app_id() -> String:
  63. # Check if the steam id is stored in the options
  64. if ModLoaderStore.ml_options.steam_id:
  65. return str(ModLoaderStore.ml_options.steam_id)
  66. ModLoaderLog.debug("No Steam ID specified in the Mod Loader options. Attempting to read the steam_data.json file next.", LOG_NAME)
  67. # If the steam_id is not stored in the options try to get it from the steam_data.json file.
  68. var game_install_directory := _ModLoaderPath.get_local_folder_dir()
  69. var steam_app_id := ""
  70. var file := FileAccess.open(game_install_directory.path_join("steam_data.json"), FileAccess.READ)
  71. if not file == null:
  72. var test_json_conv = JSON.new()
  73. test_json_conv.parse(file.get_as_text())
  74. var file_content: Dictionary = test_json_conv.get_data()
  75. file.close()
  76. if not file_content.has("app_id"):
  77. ModLoaderLog.error("The steam_data file does not contain an app ID. Mod uploading will not work.", LOG_NAME)
  78. return ""
  79. steam_app_id = str(file_content.app_id)
  80. else :
  81. ModLoaderLog.error("Can't open steam_data file, \"%s\". Please make sure the file exists and is valid." % game_install_directory.path_join("steam_data.json"), LOG_NAME)
  82. return steam_app_id