stewbeet 2.2.7__tar.gz → 2.2.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of stewbeet might be problematic. Click here for more details.

Files changed (254) hide show
  1. {stewbeet-2.2.7 → stewbeet-2.2.8}/PKG-INFO +1 -1
  2. {stewbeet-2.2.7 → stewbeet-2.2.8}/pyproject.toml +1 -1
  3. stewbeet-2.2.8/stewbeet/continuous_delivery/modrinth.py +572 -0
  4. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/cables.py +6 -10
  5. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/gui.py +5 -10
  6. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/utils/io.py +18 -2
  7. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/custom_paintings/__init__.py +4 -5
  8. stewbeet-2.2.8/stewbeet/plugins/ingame_manual/assets/furnace.png +0 -0
  9. stewbeet-2.2.8/stewbeet/plugins/ingame_manual/assets/mining.png +0 -0
  10. stewbeet-2.2.8/stewbeet/plugins/ingame_manual/assets/pulverizing.png +0 -0
  11. stewbeet-2.2.8/stewbeet/plugins/ingame_manual/assets/shaped_2x2.png +0 -0
  12. stewbeet-2.2.8/stewbeet/plugins/ingame_manual/assets/shaped_3x3.png +0 -0
  13. stewbeet-2.2.8/stewbeet/plugins/ingame_manual/assets/stonecutting.png +0 -0
  14. stewbeet-2.2.8/stewbeet/plugins/ingame_manual/templates/furnace.png +0 -0
  15. stewbeet-2.2.8/stewbeet/plugins/ingame_manual/templates/mining.png +0 -0
  16. stewbeet-2.2.8/stewbeet/plugins/ingame_manual/templates/pulverizing.png +0 -0
  17. stewbeet-2.2.8/stewbeet/plugins/ingame_manual/templates/shaped_2x2.png +0 -0
  18. stewbeet-2.2.8/stewbeet/plugins/ingame_manual/templates/shaped_3x3.png +0 -0
  19. stewbeet-2.2.8/stewbeet/plugins/ingame_manual/templates/stonecutting.png +0 -0
  20. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/resource_pack/item_models/object.py +6 -15
  21. stewbeet-2.2.7/stewbeet/continuous_delivery/modrinth.py +0 -260
  22. stewbeet-2.2.7/stewbeet/plugins/ingame_manual/assets/furnace.png +0 -0
  23. stewbeet-2.2.7/stewbeet/plugins/ingame_manual/assets/mining.png +0 -0
  24. stewbeet-2.2.7/stewbeet/plugins/ingame_manual/assets/pulverizing.png +0 -0
  25. stewbeet-2.2.7/stewbeet/plugins/ingame_manual/assets/shaped_2x2.png +0 -0
  26. stewbeet-2.2.7/stewbeet/plugins/ingame_manual/assets/shaped_3x3.png +0 -0
  27. stewbeet-2.2.7/stewbeet/plugins/ingame_manual/assets/stonecutting.png +0 -0
  28. stewbeet-2.2.7/stewbeet/plugins/ingame_manual/templates/furnace.png +0 -0
  29. stewbeet-2.2.7/stewbeet/plugins/ingame_manual/templates/mining.png +0 -0
  30. stewbeet-2.2.7/stewbeet/plugins/ingame_manual/templates/pulverizing.png +0 -0
  31. stewbeet-2.2.7/stewbeet/plugins/ingame_manual/templates/shaped_2x2.png +0 -0
  32. stewbeet-2.2.7/stewbeet/plugins/ingame_manual/templates/shaped_3x3.png +0 -0
  33. stewbeet-2.2.7/stewbeet/plugins/ingame_manual/templates/stonecutting.png +0 -0
  34. {stewbeet-2.2.7 → stewbeet-2.2.8}/.gitignore +0 -0
  35. {stewbeet-2.2.7 → stewbeet-2.2.8}/LICENSE +0 -0
  36. {stewbeet-2.2.7 → stewbeet-2.2.8}/README.md +0 -0
  37. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/__init__.py +0 -0
  38. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/__main__.py +0 -0
  39. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/all.py +0 -0
  40. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/cli.py +0 -0
  41. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/continuous_delivery/__init__.py +0 -0
  42. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/continuous_delivery/cd_utils.py +0 -0
  43. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/continuous_delivery/github.py +0 -0
  44. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/continuous_delivery/pmc.py +0 -0
  45. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/continuous_delivery/smithed.py +0 -0
  46. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/__init__.py +0 -0
  47. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/balancing.py +0 -0
  48. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/batteries.py +0 -0
  49. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant.json +0 -0
  50. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_d.json +0 -0
  51. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_de.json +0 -0
  52. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dew.json +0 -0
  53. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dn.json +0 -0
  54. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dne.json +0 -0
  55. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dnew.json +0 -0
  56. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dns.json +0 -0
  57. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dnse.json +0 -0
  58. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dnsew.json +0 -0
  59. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dnsw.json +0 -0
  60. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dnw.json +0 -0
  61. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_ds.json +0 -0
  62. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dse.json +0 -0
  63. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dsew.json +0 -0
  64. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dsw.json +0 -0
  65. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_dw.json +0 -0
  66. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_e.json +0 -0
  67. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_ew.json +0 -0
  68. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_n.json +0 -0
  69. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_ne.json +0 -0
  70. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_new.json +0 -0
  71. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_ns.json +0 -0
  72. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_nse.json +0 -0
  73. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_nsew.json +0 -0
  74. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_nsw.json +0 -0
  75. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_nw.json +0 -0
  76. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_s.json +0 -0
  77. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_se.json +0 -0
  78. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_sew.json +0 -0
  79. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_sw.json +0 -0
  80. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_u.json +0 -0
  81. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_ud.json +0 -0
  82. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_ude.json +0 -0
  83. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udew.json +0 -0
  84. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udn.json +0 -0
  85. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udne.json +0 -0
  86. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udnew.json +0 -0
  87. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udns.json +0 -0
  88. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udnse.json +0 -0
  89. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udnsew.json +0 -0
  90. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udnsw.json +0 -0
  91. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udnw.json +0 -0
  92. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_uds.json +0 -0
  93. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udse.json +0 -0
  94. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udsew.json +0 -0
  95. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udsw.json +0 -0
  96. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_udw.json +0 -0
  97. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_ue.json +0 -0
  98. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_uew.json +0 -0
  99. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_un.json +0 -0
  100. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_une.json +0 -0
  101. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_unew.json +0 -0
  102. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_uns.json +0 -0
  103. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_unse.json +0 -0
  104. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_unsew.json +0 -0
  105. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_unsw.json +0 -0
  106. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_unw.json +0 -0
  107. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_us.json +0 -0
  108. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_use.json +0 -0
  109. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_usew.json +0 -0
  110. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_usw.json +0 -0
  111. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_uw.json +0 -0
  112. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_cable_models/variant_w.json +0 -0
  113. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/energy_lib_calls.py +0 -0
  114. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/item_cable_models/cable.bbmodel +0 -0
  115. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/item_cable_models/cable_base.json +0 -0
  116. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/py.typed +0 -0
  117. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/servo_mechanism_models/base_block.json +0 -0
  118. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/servo_mechanism_models/base_item.json +0 -0
  119. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/servo_mechanism_models/extract_block.json +0 -0
  120. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/servo_mechanism_models/extract_connected.json +0 -0
  121. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/servo_mechanism_models/extract_item.json +0 -0
  122. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/servo_mechanism_models/insert_block.json +0 -0
  123. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/servo_mechanism_models/insert_connected.json +0 -0
  124. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/servo_mechanism_models/insert_item.json +0 -0
  125. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/contrib/simplenergy/wrench.py +0 -0
  126. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/__init__.py +0 -0
  127. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/__memory__.py +0 -0
  128. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/constants.py +0 -0
  129. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/definitions_helper/__init__.py +0 -0
  130. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/definitions_helper/completion.py +0 -0
  131. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/definitions_helper/equipments.py +0 -0
  132. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/definitions_helper/materials.py +0 -0
  133. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/definitions_helper/records.py +0 -0
  134. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/definitions_helper/simplenergy.py +0 -0
  135. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/definitions_helper/smart_ore_generation.py +0 -0
  136. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/definitions_helper/text.py +0 -0
  137. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/ingredients.py +0 -0
  138. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/core/utils/sounds.py +0 -0
  139. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/__init__.py +0 -0
  140. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/bookshelf.py +0 -0
  141. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/bookshelf_config.json +0 -0
  142. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Bitwise.zip +0 -0
  143. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Block.zip +0 -0
  144. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Color.zip +0 -0
  145. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Dump.zip +0 -0
  146. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Environment.zip +0 -0
  147. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Generation.zip +0 -0
  148. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Health.zip +0 -0
  149. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Hitbox.zip +0 -0
  150. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Id.zip +0 -0
  151. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Interaction.zip +0 -0
  152. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Link.zip +0 -0
  153. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Log.zip +0 -0
  154. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Math.zip +0 -0
  155. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Move.zip +0 -0
  156. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Position.zip +0 -0
  157. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Random.zip +0 -0
  158. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Raycast.zip +0 -0
  159. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Schedule.zip +0 -0
  160. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Sidebar.zip +0 -0
  161. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Spline.zip +0 -0
  162. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf String.zip +0 -0
  163. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Time.zip +0 -0
  164. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Tree.zip +0 -0
  165. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Vector.zip +0 -0
  166. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf View.zip +0 -0
  167. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Bookshelf Xp.zip +0 -0
  168. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Common Signals.zip +0 -0
  169. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Furnace NBT Recipes.zip +0 -0
  170. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/ItemIO.zip +0 -0
  171. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/SmartOreGeneration.zip +0 -0
  172. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Smithed Crafter.zip +0 -0
  173. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/datapack/Smithed Custom Block.zip +0 -0
  174. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/dependencies/resource_pack/Smithed Crafter.zip +0 -0
  175. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/archive/__init__.py +0 -0
  176. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/auto/headers/__init__.py +0 -0
  177. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/auto/headers/context_analyzer.py +0 -0
  178. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/auto/headers/execution_parser.py +0 -0
  179. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/auto/headers/function_analyzer.py +0 -0
  180. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/auto/headers/object.py +0 -0
  181. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/auto/lang_file/__init__.py +0 -0
  182. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/auto/lang_file/utils.py +0 -0
  183. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/compatibilities/neo_enchant/__init__.py +0 -0
  184. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/compatibilities/simpledrawer/__init__.py +0 -0
  185. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/compute_sha1/__init__.py +0 -0
  186. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/copy_to_destination/__init__.py +0 -0
  187. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/custom_recipes/__init__.py +0 -0
  188. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/custom_recipes/furnace.py +0 -0
  189. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/custom_recipes/pulverizer.py +0 -0
  190. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/custom_recipes/smithed.py +0 -0
  191. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/custom_recipes/vanilla.py +0 -0
  192. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/datapack/custom_blocks/__init__.py +0 -0
  193. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/datapack/loading/__init__.py +0 -0
  194. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/datapack/loot_tables/__init__.py +0 -0
  195. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/datapack/sorters/__init__.py +0 -0
  196. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/datapack/sorters/constants.py +0 -0
  197. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/datapack/sorters/extend_datapack.py +0 -0
  198. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/datapack/sorters/match.py +0 -0
  199. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/datapack/sorters/mod.mcdoc +0 -0
  200. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/datapack/sorters/quick_sort.py +0 -0
  201. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/datapack/sorters/selection_sort.py +0 -0
  202. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/finalyze/basic_datapack_structure/__init__.py +0 -0
  203. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/finalyze/check_unused_textures/__init__.py +0 -0
  204. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/finalyze/custom_blocks_ticking/__init__.py +0 -0
  205. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/finalyze/dependencies/__init__.py +0 -0
  206. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/finalyze/last_final/__init__.py +0 -0
  207. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/__init__.py +0 -0
  208. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/assets/heavy_workbench.png +0 -0
  209. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/assets/invisible_item.png +0 -0
  210. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/assets/invisible_item_release.png +0 -0
  211. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/assets/minecraft_font.ttf +0 -0
  212. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/assets/none.png +0 -0
  213. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/assets/none_release.png +0 -0
  214. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/assets/simple_case_no_border.png +0 -0
  215. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/assets/wiki_information.png +0 -0
  216. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/assets/wiki_ingredient_of_craft.png +0 -0
  217. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/assets/wiki_ingredient_of_craft_template.png +0 -0
  218. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/assets/wiki_mining_template.png +0 -0
  219. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/assets/wiki_result_of_craft.png +0 -0
  220. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/book_components.py +0 -0
  221. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/book_optimizer.py +0 -0
  222. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/craft_content.py +0 -0
  223. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/image_utils.py +0 -0
  224. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/iso_renders.py +0 -0
  225. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/main.py +0 -0
  226. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/other_utils.py +0 -0
  227. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/page_font.py +0 -0
  228. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/shared_import.py +0 -0
  229. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/showcase_image.py +0 -0
  230. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/.gitignore +0 -0
  231. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/_README.md +0 -0
  232. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/heavy_workbench.png +0 -0
  233. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/invisible_item.png +0 -0
  234. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/invisible_item_release.png +0 -0
  235. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/minecraft_font.ttf +0 -0
  236. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/none.png +0 -0
  237. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/none_release.png +0 -0
  238. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/simple_case_no_border.png +0 -0
  239. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/wiki_information.png +0 -0
  240. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/wiki_ingredient_of_craft.png +0 -0
  241. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/wiki_ingredient_of_craft_template.png +0 -0
  242. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/wiki_mining_template.png +0 -0
  243. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/templates/wiki_result_of_craft.png +0 -0
  244. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/ingame_manual/text_components.py +0 -0
  245. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/initialize/__init__.py +0 -0
  246. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/initialize/source_lore_font.py +0 -0
  247. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/merge_smithed_weld/__init__.py +0 -0
  248. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/merge_smithed_weld/weld.py +0 -0
  249. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/resource_pack/check_power_of_2/__init__.py +0 -0
  250. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/resource_pack/item_models/__init__.py +0 -0
  251. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/resource_pack/sounds/__init__.py +0 -0
  252. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/plugins/verify_definitions/__init__.py +0 -0
  253. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/py.typed +0 -0
  254. {stewbeet-2.2.7 → stewbeet-2.2.8}/stewbeet/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stewbeet
3
- Version: 2.2.7
3
+ Version: 2.2.8
4
4
  Summary: Beet Framework made to help generating advanced Minecraft datapack contents
5
5
  Project-URL: Homepage, https://github.com/Stoupy51/stewbeet
6
6
  Project-URL: Issues, https://github.com/Stoupy51/stewbeet/issues
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
5
5
 
6
6
  [project]
7
7
  name = "stewbeet"
8
- version = "2.2.7"
8
+ version = "2.2.8"
9
9
  description = "Beet Framework made to help generating advanced Minecraft datapack contents"
10
10
  readme = "README.md"
11
11
  license = "MIT"
@@ -0,0 +1,572 @@
1
+
2
+ # Imports
3
+ import json
4
+ import os
5
+ import zipfile
6
+
7
+ import requests
8
+ import stouputils as stp
9
+ from beet.core.utils import JsonDict
10
+
11
+ from .cd_utils import get_supported_versions
12
+
13
+ # Constants
14
+ MODRINTH_API_URL: str = "https://api.modrinth.com/v2"
15
+ PROJECT_ENDPOINT: str = f"{MODRINTH_API_URL}/project"
16
+ VERSION_ENDPOINT: str = f"{MODRINTH_API_URL}/version"
17
+
18
+ def validate_credentials(credentials: dict[str, str]) -> str:
19
+ """ Get and validate Modrinth credentials
20
+
21
+ Args:
22
+ credentials (dict[str, str]): Credentials for the Modrinth API
23
+ Returns:
24
+ str: API key for Modrinth
25
+ """
26
+ if "modrinth_api_key" not in credentials:
27
+ raise ValueError("The credentials file must contain a 'modrinth_api_key' key, which is a PAT (Personal Access Token) for the Modrinth API: https://modrinth.com/settings/pats")
28
+ return credentials["modrinth_api_key"]
29
+
30
+ def validate_config(modrinth_config: JsonDict) -> tuple[str, str, str, str, str, str, str]:
31
+ """ Validate Modrinth configuration
32
+
33
+ Args:
34
+ modrinth_config (JsonDict): Configuration for the Modrinth project
35
+ Returns:
36
+ str: Project name on Modrinth
37
+ str: Version of the project
38
+ str: Slug (namespace) of the project
39
+ str: Summary of the project
40
+ str: Description in Markdown format
41
+ str: Version type (release, beta, alpha)
42
+ str: Build folder path
43
+ """
44
+ required_keys = [
45
+ "project_name", "version", "slug", "summary",
46
+ "description_markdown", "version_type", "build_folder"
47
+ ]
48
+ error_messages = {
49
+ "project_name": "name of the project on Modrinth",
50
+ "version": "version of the project",
51
+ "slug": "namespace of the project",
52
+ "summary": "summary of the project",
53
+ "description_markdown": "description of the project in Markdown format",
54
+ "version_type": "version type of the project (release, beta, alpha)",
55
+ "build_folder": "folder containing the build of the project (datapack and resourcepack zip files)"
56
+ }
57
+
58
+ for key in required_keys:
59
+ if key not in modrinth_config:
60
+ raise ValueError(f"The modrinth_config dictionary must contain a '{key}' key, which is the {error_messages[key]}")
61
+ if isinstance(modrinth_config.get("authors"), str):
62
+ modrinth_config["authors"] = [x.strip() for x in modrinth_config["authors"].split(",")]
63
+
64
+ return (
65
+ modrinth_config["project_name"],
66
+ modrinth_config["version"],
67
+ modrinth_config["slug"],
68
+ modrinth_config["summary"],
69
+ modrinth_config["description_markdown"],
70
+ modrinth_config["version_type"],
71
+ modrinth_config["build_folder"]
72
+ )
73
+
74
+ def get_project(slug: str, headers: dict[str, str]) -> dict[str, str]:
75
+ """ Get project from Modrinth
76
+
77
+ Args:
78
+ slug (str): Project slug/namespace
79
+ headers (dict[str, str]): Headers for Modrinth API requests
80
+ Returns:
81
+ dict: Project data
82
+ """
83
+ stp.progress(f"Getting project {slug} from Modrinth")
84
+ search_response = requests.get(f"{PROJECT_ENDPOINT}/{slug}", headers=headers)
85
+ stp.handle_response(search_response, f"Project not found on Modrinth, with namespace {slug}, please create it manually on https://modrinth.com/")
86
+ return search_response.json()
87
+
88
+ def update_project_description(slug: str, description: str, summary: str, headers: dict[str, str]) -> None:
89
+ """ Update project description and summary
90
+
91
+ Args:
92
+ slug (str): Project slug/namespace
93
+ description (str): Project description in Markdown
94
+ summary (str): Project summary
95
+ headers (dict[str, str]): Headers for Modrinth API requests
96
+ """
97
+ stp.progress("Updating project description")
98
+ update_response = requests.patch(
99
+ f"{PROJECT_ENDPOINT}/{slug}",
100
+ headers=headers,
101
+ json={"body": description.strip(), "description": summary.strip()}
102
+ )
103
+ stp.handle_response(update_response, "Failed to update project description")
104
+
105
+ def handle_existing_version(slug: str, version: str, headers: dict[str, str]) -> bool:
106
+ """ Check and handle existing version
107
+
108
+ Args:
109
+ slug (str): Project slug/namespace
110
+ version (str): Version to check
111
+ headers (dict[str, str]): Headers for Modrinth API requests
112
+ Returns:
113
+ bool: True if we should continue, False otherwise
114
+ """
115
+ version_response = requests.get(f"{PROJECT_ENDPOINT}/{slug}/version/{version}", headers=headers)
116
+ if version_response.status_code == 200:
117
+ stp.warning(f"Version {version} already exists on Modrinth, do you want to delete it? (y/N)")
118
+ if input().lower() != "y":
119
+ return False
120
+ version_id: str = version_response.json()["id"]
121
+ delete_response = requests.delete(f"{VERSION_ENDPOINT}/{version_id}", headers=headers)
122
+ stp.handle_response(delete_response, "Failed to delete the version")
123
+ elif version_response.status_code == 404:
124
+ stp.info(f"Version {version} not found on Modrinth, uploading...")
125
+ else:
126
+ stp.handle_response(version_response, "Failed to check if the version already exists")
127
+ return True
128
+
129
+ def generate_fabric_metadata(mod_id: str, metadata: JsonDict) -> str:
130
+ """ Generate Fabric mod metadata JSON
131
+
132
+ Args:
133
+ mod_id (str): Mod ID
134
+ metadata (dict): Mod metadata
135
+ Returns:
136
+ str: Fabric mod.json content
137
+ """
138
+ fabric_mod_json: JsonDict = {
139
+ "schemaVersion": 1,
140
+ "id": f"stewbeet_{mod_id}",
141
+ "version": metadata["version"],
142
+ "name": metadata["name"],
143
+ "description": metadata.get("description", ""),
144
+ "authors": metadata.get("authors", []),
145
+ "contact": {"homepage": f"https://modrinth.com/datapack/{mod_id}"},
146
+ "license": metadata.get("license", "All Rights Reserved"),
147
+ "icon": f"{mod_id}_pack.png",
148
+ "environment": "*",
149
+ "depends": {"fabric-resource-loader-v0": "*"}
150
+ }
151
+
152
+ # Add optional contact fields
153
+ if metadata.get("sources"):
154
+ fabric_mod_json["contact"]["sources"] = metadata["sources"]
155
+ if metadata.get("issues"):
156
+ fabric_mod_json["contact"]["issues"] = metadata["issues"]
157
+ return stp.super_json_dump(fabric_mod_json, max_level=-1)
158
+
159
+ def generate_forge_metadata(mod_id: str, metadata: JsonDict, is_neoforge: bool = False) -> str:
160
+ """ Generate Forge/NeoForge mod metadata TOML
161
+
162
+ Args:
163
+ mod_id (str): Mod ID
164
+ metadata (dict): Mod metadata
165
+ is_neoforge (bool): Whether this is for NeoForge (uses javafml) or Forge (uses lowcodefml)
166
+ Returns:
167
+ str: mods.toml content
168
+ """
169
+ description: str = metadata.get("description", "").replace(chr(10), "\\n").replace('"', '\\"')
170
+ authors: str = ", ".join(metadata.get("authors", []))
171
+ homepage: str = f"https://modrinth.com/datapack/{mod_id}"
172
+ mod_loader: str = "'javafml'" if is_neoforge else "'lowcodefml'"
173
+ loader_version: str = "'[1,)'" if is_neoforge else "'[40,)'"
174
+
175
+ toml_content: str = f"""
176
+ modLoader = {mod_loader}
177
+ loaderVersion = {loader_version}
178
+ license = '{metadata.get("license", "All Rights Reserved")}'
179
+ showAsResourcePack = false
180
+ mods = [
181
+ {{ modId = 'stewbeet_{mod_id}', version = '{metadata["version"]}', displayName = '{metadata["name"]}', description = "{description}", logoFile = '{mod_id}_pack.png'"""
182
+
183
+ # Add optional fields
184
+ if homepage:
185
+ update_url = f"https://api.modrinth.com/updates/{mod_id}/forge_updates.json"
186
+ if is_neoforge:
187
+ update_url += "?neoforge=only"
188
+ toml_content += f""", updateJSONURL = '{update_url}'"""
189
+ toml_content += f""", credits = 'Generated by StewBeet', authors = '{authors}', displayURL = '{homepage}' }},
190
+ ]
191
+ """
192
+ # Add issue tracker if available
193
+ if metadata.get("issues"):
194
+ toml_content += f"issueTrackerURL = '{metadata['issues']}'\n"
195
+ return toml_content
196
+
197
+ def generate_quilt_metadata(mod_id: str, metadata: JsonDict) -> str:
198
+ """ Generate Quilt mod metadata JSON
199
+
200
+ Args:
201
+ mod_id (str): Mod ID
202
+ metadata (dict): Mod metadata
203
+ Returns:
204
+ str: quilt.mod.json content
205
+ """
206
+ # Build contributors dictionary
207
+ contributors: JsonDict = {}
208
+ for author in metadata.get("authors", []):
209
+ contributors[author] = "Member"
210
+
211
+ # Build contact dictionary
212
+ contact: JsonDict = {"homepage": f"https://modrinth.com/datapack/{mod_id}"}
213
+ if metadata.get("sources"):
214
+ contact["sources"] = metadata["sources"]
215
+ if metadata.get("issues"):
216
+ contact["issues"] = metadata["issues"]
217
+
218
+ quilt_mod_json: JsonDict = {
219
+ "schema_version": 1,
220
+ "quilt_loader": {
221
+ "group": "com.stewbeet",
222
+ "id": f"stewbeet_{mod_id}",
223
+ "version": metadata["version"],
224
+ "metadata": {
225
+ "name": metadata["name"],
226
+ "description": metadata.get("description", ""),
227
+ "contributors": contributors,
228
+ "contact": contact,
229
+ "icon": f"{mod_id}_pack.png"
230
+ },
231
+ "intermediate_mappings": "net.fabricmc:intermediary",
232
+ "depends": [
233
+ {
234
+ "id": "quilt_resource_loader",
235
+ "versions": "*",
236
+ "unless": "fabric-resource-loader-v0"
237
+ }
238
+ ]
239
+ }
240
+ }
241
+ return stp.super_json_dump(quilt_mod_json, max_level=-1)
242
+
243
+ def convert_datapack_to_mod(
244
+ datapack_path: str,
245
+ output_path: str,
246
+ metadata: JsonDict,
247
+ platforms: list[str],
248
+ resource_pack_path: str | None = None
249
+ ) -> None:
250
+ """ Convert a datapack ZIP to a mod JAR with proper metadata files
251
+
252
+ Args:
253
+ datapack_path (str): Path to the datapack ZIP file
254
+ output_path (str): Path where to save the mod JAR file
255
+ metadata (dict): Mod metadata (id, name, version, description, authors, etc.)
256
+ platforms (list[str]): List of platforms (fabric, forge, neoforge, quilt)
257
+ resource_pack_path (str): Optional path to the resource pack ZIP file
258
+ """
259
+ # Create a new ZIP/JAR file with datapack + resource pack content + mod metadata
260
+ with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as mod_zip:
261
+
262
+ # Determine mod ID
263
+ mod_id = metadata.get("id", metadata.get("slug", metadata["name"])).lower().replace(" ", "_").replace("-", "_")
264
+
265
+ # Copy all files from datapack
266
+ with zipfile.ZipFile(datapack_path, 'r') as datapack_zip:
267
+ for item in datapack_zip.infolist():
268
+ data = datapack_zip.read(item.filename)
269
+ mod_zip.writestr(item, data)
270
+ if item.filename == "pack.png":
271
+ mod_zip.writestr(f"{mod_id}_pack.png", data)
272
+
273
+ # Copy assets folder from resource pack if provided
274
+ if resource_pack_path and os.path.exists(resource_pack_path):
275
+ with zipfile.ZipFile(resource_pack_path, 'r') as resource_pack_zip:
276
+ for item in resource_pack_zip.infolist():
277
+ # Only copy files from the assets folder (exclude pack.png and pack.mcmeta)
278
+ if item.filename.startswith("assets/") and not item.is_dir():
279
+ data = resource_pack_zip.read(item.filename)
280
+ mod_zip.writestr(item, data)
281
+
282
+ # Generate platform-specific metadata files
283
+ if "fabric" in platforms:
284
+ mod_zip.writestr("fabric.mod.json", generate_fabric_metadata(mod_id, metadata))
285
+
286
+ if "forge" in platforms:
287
+ mod_zip.writestr("META-INF/mods.toml", generate_forge_metadata(mod_id, metadata, is_neoforge=False))
288
+
289
+ if "neoforge" in platforms:
290
+ mod_zip.writestr("META-INF/neoforge.mods.toml", generate_forge_metadata(mod_id, metadata, is_neoforge=True))
291
+
292
+ if "quilt" in platforms:
293
+ mod_zip.writestr("quilt.mod.json", generate_quilt_metadata(mod_id, metadata))
294
+
295
+ def get_file_parts(project_name: str, build_folder: str, modrinth_config: JsonDict, project_data: JsonDict | None = None) -> list[str]:
296
+ """ Get file parts to upload
297
+
298
+ Args:
299
+ project_name (str): Name of the project
300
+ build_folder (str): Path to build folder
301
+ modrinth_config (dict): Modrinth configuration
302
+ project_data (dict): Optional project data from Modrinth API
303
+ Returns:
304
+ list[str]: List of file paths to upload
305
+ """
306
+ file_parts: list[str] = [
307
+ f"{build_folder}/{project_name}_datapack_with_libs.zip",
308
+ f"{build_folder}/{project_name}_resource_pack_with_libs.zip"
309
+ ]
310
+ file_parts = [file_part for file_part in file_parts if os.path.exists(file_part)]
311
+ if len(file_parts) == 0:
312
+ file_parts = [
313
+ f"{build_folder}/{project_name}_datapack.zip",
314
+ f"{build_folder}/{project_name}_resource_pack.zip"
315
+ ]
316
+ file_parts = [file_part for file_part in file_parts if os.path.exists(file_part)]
317
+ if len(file_parts) == 0:
318
+ raise ValueError(f"No file parts (datapack and resourcepack zip files) found in {build_folder}, please check the build_folder path in the modrinth_config file")
319
+
320
+ # Convert datapack to mod if requested
321
+ package_as_mod: str | None = modrinth_config.get("package_as_mod", None)
322
+ if package_as_mod in ["all", "separate"]:
323
+
324
+ # Find the datapack file and resourcepack file
325
+ datapack_file: str = ""
326
+ resource_pack_file: str = ""
327
+ for file_part in file_parts:
328
+ if "datapack" in file_part.lower():
329
+ datapack_file = file_part
330
+ elif "resource_pack" in file_part.lower():
331
+ resource_pack_file = file_part
332
+
333
+ if datapack_file:
334
+
335
+ # Get mod platforms (default to all platforms)
336
+ platforms = modrinth_config.get("mod_platforms", ["fabric", "forge", "neoforge", "quilt"])
337
+ if isinstance(platforms, str):
338
+ platforms = [platforms]
339
+
340
+ # Prepare base metadata
341
+ base_metadata: JsonDict = {
342
+ "id": modrinth_config.get("slug", project_name).lower().replace("-", "_").replace(" ", "_"),
343
+ "name": project_name,
344
+ "version": modrinth_config.get("version", "1.0.0"),
345
+ "description": modrinth_config.get("summary", ""),
346
+ "authors": modrinth_config.get("authors", []),
347
+ "license": modrinth_config.get("license", "All Rights Reserved"),
348
+ "homepage": modrinth_config.get("homepage"),
349
+ "sources": modrinth_config.get("sources"),
350
+ "issues": modrinth_config.get("issues"),
351
+ "icon": modrinth_config.get("icon")
352
+ }
353
+
354
+ # Complete metadata from Modrinth project if available
355
+ if project_data:
356
+ # Use existing project data to fill missing metadata
357
+ if not base_metadata.get("description") and project_data.get("description"):
358
+ base_metadata["description"] = project_data["description"]
359
+ if not base_metadata.get("license") or base_metadata["license"] == "All Rights Reserved":
360
+ if project_data.get("license") and project_data["license"].get("id"):
361
+ base_metadata["license"] = project_data["license"]["id"]
362
+ if not base_metadata.get("homepage") and project_data.get("project_url"):
363
+ base_metadata["homepage"] = project_data["project_url"]
364
+ if not base_metadata.get("sources") and project_data.get("source_url"):
365
+ base_metadata["sources"] = project_data["source_url"]
366
+ if not base_metadata.get("issues") and project_data.get("issues_url"):
367
+ base_metadata["issues"] = project_data["issues_url"]
368
+ if project_data.get("title"):
369
+ base_metadata["name"] = project_data["title"]
370
+
371
+ # Create one mod with all platforms
372
+ if package_as_mod == "all":
373
+ mod_output_path: str = f"{build_folder}/{project_name}_mod.jar"
374
+ with stp.MeasureTime(stp.progress, message=f"Converted datapack to mod for platforms: {', '.join(platforms)}"):
375
+ convert_datapack_to_mod(datapack_file, mod_output_path, base_metadata, platforms, resource_pack_file)
376
+
377
+ # Add mod file to file_parts (keep datapack too)
378
+ file_parts.append(mod_output_path)
379
+
380
+ # Create separate mod for each platform
381
+ elif package_as_mod == "separate":
382
+ for platform in platforms:
383
+ platform_metadata = base_metadata.copy()
384
+ platform_metadata["name"] = project_name
385
+ mod_output_path = f"{build_folder}/{project_name}_{platform}_mod.jar"
386
+ with stp.MeasureTime(stp.progress, message=f"Converted datapack to mod for platform: {platform}"):
387
+ convert_datapack_to_mod(datapack_file, mod_output_path, platform_metadata, [platform], resource_pack_file)
388
+
389
+ # Add platform-specific mod to file_parts
390
+ file_parts.append(mod_output_path)
391
+
392
+ return file_parts
393
+
394
+ def upload_version(
395
+ project_id: str,
396
+ project_name: str,
397
+ version: str,
398
+ version_type: str,
399
+ changelog: str,
400
+ file_parts: list[str],
401
+ headers: dict[str, str],
402
+ dependencies: list[str] | None = None,
403
+ loaders: list[str] | None = None
404
+ ) -> JsonDict:
405
+ """ Upload new version
406
+
407
+ Args:
408
+ project_id (str): Modrinth project ID
409
+ project_name (str): Name of the project
410
+ version (str): Version number
411
+ version_type (str): Type of version (release, beta, alpha)
412
+ changelog (str): Changelog text
413
+ file_parts (list[str]): List of files to upload
414
+ headers (dict[str, str]): Headers for Modrinth API requests
415
+ dependencies (list[str]): List of dependencies
416
+ loaders (list[str]): List of loaders (datapack, fabric, forge, etc.)
417
+ Returns:
418
+ dict: Upload response data
419
+ """
420
+ if dependencies is None:
421
+ dependencies = []
422
+ if loaders is None:
423
+ loaders = ["datapack"]
424
+ stp.progress(f"Creating version {version}")
425
+ files: dict[str, bytes] = {}
426
+ for file_part in file_parts:
427
+ stp.progress(f"Reading file {os.path.basename(file_part)}")
428
+ with open(file_part, "rb") as file:
429
+ files[os.path.basename(file_part)] = file.read()
430
+
431
+ request_data: JsonDict = {
432
+ "name": f"{project_name} [v{version}]",
433
+ "version_number": version,
434
+ "changelog": changelog,
435
+ "dependencies": dependencies,
436
+ "game_versions": get_supported_versions(),
437
+ "version_type": version_type,
438
+ "loaders": loaders,
439
+ "featured": False,
440
+ "status": "listed",
441
+ "project_id": project_id,
442
+ "file_parts": [os.path.basename(file_part) for file_part in file_parts],
443
+ "primary_file": os.path.basename(file_parts[0])
444
+ }
445
+
446
+ upload_response = requests.post(
447
+ VERSION_ENDPOINT,
448
+ headers=headers,
449
+ data={"data": json.dumps(request_data)},
450
+ files=files,
451
+ timeout=10,
452
+ stream=False
453
+ )
454
+ json_response: JsonDict = upload_response.json()
455
+ stp.handle_response(upload_response, "Failed to upload the version")
456
+ return json_response
457
+
458
+ def set_resource_pack_required(version_id: str, resource_pack_hash: str, headers: dict[str, str]) -> None:
459
+ """ Set resource pack as required
460
+
461
+ Args:
462
+ version_id (str): ID of the version
463
+ resource_pack_hash (str): SHA1 hash of resource pack
464
+ headers (dict[str, str]): Headers for Modrinth API requests
465
+ """
466
+ stp.progress("Setting resource pack as required")
467
+ version_response = requests.patch(
468
+ f"{VERSION_ENDPOINT}/{version_id}",
469
+ headers=headers,
470
+ json={"file_types": [{"algorithm": "sha1", "hash": resource_pack_hash, "file_type": "required-resource-pack"}]}
471
+ )
472
+ stp.handle_response(version_response, "Failed to put the resource pack as required")
473
+
474
+ @stp.measure_time(stp.progress, "Uploading to modrinth took")
475
+ @stp.handle_error()
476
+ def upload_to_modrinth(credentials: dict[str, str], modrinth_config: JsonDict, changelog: str = "") -> None:
477
+ """ Upload the project to Modrinth using the credentials and the configuration
478
+
479
+ Args:
480
+ credentials (dict[str, str]): Credentials for the Modrinth API
481
+ modrinth_config (dict): Configuration for the Modrinth project
482
+ changelog (str): Changelog text for the release
483
+ """
484
+ api_key: str = validate_credentials(credentials)
485
+ headers: dict[str, str] = {"Authorization": api_key}
486
+
487
+ project_name, version, slug, summary, description_markdown, version_type, build_folder = validate_config(modrinth_config)
488
+
489
+ project = get_project(slug, headers)
490
+ update_project_description(slug, description_markdown, summary, headers)
491
+ can_continue: bool = handle_existing_version(slug, version, headers)
492
+ if not can_continue:
493
+ return
494
+
495
+ file_parts = get_file_parts(project_name, build_folder, modrinth_config, project)
496
+
497
+ package_as_mod = modrinth_config.get("package_as_mod", None)
498
+ mod_platforms = modrinth_config.get("mod_platforms", ["fabric", "forge", "neoforge", "quilt"])
499
+ if isinstance(mod_platforms, str):
500
+ mod_platforms = [mod_platforms]
501
+
502
+ # Handle different packaging modes
503
+ if package_as_mod == "all":
504
+ # Upload datapack version first
505
+ datapack_files = [f for f in file_parts if "_datapack" in f or "_resource_pack" in f]
506
+ if datapack_files:
507
+ stp.info("Uploading datapack version...")
508
+ json_response = upload_version(
509
+ project["id"], project_name, version, version_type,
510
+ changelog, datapack_files, headers, modrinth_config.get("dependencies", []),
511
+ ["datapack"]
512
+ )
513
+ if len(datapack_files) > 1:
514
+ resource_pack_hash: str = json_response["files"][1]["hashes"]["sha1"]
515
+ set_resource_pack_required(json_response["id"], resource_pack_hash, headers)
516
+
517
+ # Upload mod version (with all platforms)
518
+ mod_files = [f for f in file_parts if "_mod" in f and "_datapack" not in f]
519
+ if mod_files:
520
+ # Check if mod version already exists
521
+ mod_version_name = f"{version}+mod"
522
+ can_continue_mod = handle_existing_version(slug, mod_version_name, headers)
523
+ if can_continue_mod:
524
+ stp.info(f"Uploading mod version (all platforms: {', '.join(mod_platforms)})...")
525
+ upload_version(
526
+ project["id"], project_name, mod_version_name, version_type,
527
+ changelog, mod_files, headers, modrinth_config.get("dependencies", []),
528
+ mod_platforms
529
+ )
530
+
531
+ elif package_as_mod == "separate":
532
+ # Upload datapack version first
533
+ datapack_files = [f for f in file_parts if "_datapack" in f or "_resource_pack" in f]
534
+ if datapack_files:
535
+ stp.info("Uploading datapack version...")
536
+ json_response = upload_version(
537
+ project["id"], project_name, version, version_type,
538
+ changelog, datapack_files, headers, modrinth_config.get("dependencies", []),
539
+ ["datapack"]
540
+ )
541
+ if len(datapack_files) > 1:
542
+ resource_pack_hash: str = json_response["files"][1]["hashes"]["sha1"]
543
+ set_resource_pack_required(json_response["id"], resource_pack_hash, headers)
544
+
545
+ # Upload separate version for each platform
546
+ for platform in mod_platforms:
547
+ platform_files = [f for f in file_parts if f"_{platform}" in f]
548
+ if platform_files:
549
+ platform_version_name = f"{version}+{platform}"
550
+ can_continue_platform = handle_existing_version(slug, platform_version_name, headers)
551
+ if can_continue_platform:
552
+ stp.info(f"Uploading {platform} version...")
553
+ upload_version(
554
+ project["id"], project_name, platform_version_name, version_type,
555
+ changelog, platform_files, headers, modrinth_config.get("dependencies", []),
556
+ [platform]
557
+ )
558
+
559
+ else:
560
+ # Default: upload as datapack only
561
+ json_response = upload_version(
562
+ project["id"], project_name, version, version_type,
563
+ changelog, file_parts, headers, modrinth_config.get("dependencies", []),
564
+ ["datapack"]
565
+ )
566
+ if len(file_parts) > 1:
567
+ resource_pack_hash: str = json_response["files"][1]["hashes"]["sha1"]
568
+ set_resource_pack_required(json_response["id"], resource_pack_hash, headers)
569
+
570
+ stp.info(f"Project {project_name} updated on Modrinth!")
571
+
572
+
@@ -3,10 +3,10 @@
3
3
  # Imports
4
4
  import os
5
5
 
6
- from beet import ItemModel, Model, Texture
6
+ from beet import ItemModel, Model
7
7
  from stouputils.io import get_root_path, super_json_load
8
8
 
9
- from ...core import CUSTOM_ITEM_VANILLA, JsonDict, Mem, set_json_encoder, write_function
9
+ from ...core import CUSTOM_ITEM_VANILLA, JsonDict, Mem, set_json_encoder, texture_mcmeta, write_function
10
10
 
11
11
  # Constants
12
12
  ENERGY_CABLE_MODELS_FOLDER: str = get_root_path(__file__) + "/energy_cable_models"
@@ -69,10 +69,8 @@ def energy_cables_models(cables: list[str]) -> None:
69
69
  # Write the vanilla model for this cable
70
70
  Mem.ctx.assets[ns].item_models[cable] = set_json_encoder(ItemModel(content), max_level=3)
71
71
 
72
- # Copy texture
73
- src: str = f"{textures_folder}/{cable}.png"
74
- mcmeta: JsonDict | None = None if not os.path.exists(src + ".mcmeta") else super_json_load(f"{src}.mcmeta")
75
- Mem.ctx.assets[ns].textures[f"block/{cable}"] = Texture(source_path=src, mcmeta=mcmeta)
72
+ # Copy texture to resource pack
73
+ Mem.ctx.assets[ns].textures[f"block/{cable}"] = texture_mcmeta(f"{textures_folder}/{cable}.png")
76
74
 
77
75
  # On placement, rotate
78
76
  write_function(f"{ns}:custom_blocks/{cable}/place_secondary", f"""
@@ -186,8 +184,7 @@ def item_cables_models(cables: dict[str, dict[str, str] | None]) -> None:
186
184
 
187
185
  # Check if the source file exists and if the texture is not already registered
188
186
  if os.path.exists(src) and (not Mem.ctx.assets[ns].textures.get(dst)):
189
- mcmeta: JsonDict | None = None if not os.path.exists(src + ".mcmeta") else super_json_load(f"{src}.mcmeta")
190
- Mem.ctx.assets[ns].textures[dst] = Texture(source_path=src, mcmeta=mcmeta)
187
+ Mem.ctx.assets[ns].textures[dst] = texture_mcmeta(src)
191
188
 
192
189
  # On placement, add itemio.cable tag and call init function
193
190
  write_function(f"{ns}:custom_blocks/{cable}/place_secondary", f"""
@@ -289,8 +286,7 @@ def servo_mechanisms_models(servos: dict[str, dict[str, str] | None]) -> None:
289
286
 
290
287
  # Check if the source file exists and if the texture is not already registered
291
288
  if os.path.exists(src) and (not Mem.ctx.assets[ns].textures.get(dst)):
292
- mcmeta: JsonDict | None = None if not os.path.exists(src + ".mcmeta") else super_json_load(f"{src}.mcmeta")
293
- Mem.ctx.assets[ns].textures[dst] = Texture(source_path=src, mcmeta=mcmeta)
289
+ Mem.ctx.assets[ns].textures[dst] = texture_mcmeta(src)
294
290
 
295
291
  ## Working functions
296
292
  # On placement, add necessary tag and call init function
@@ -6,11 +6,11 @@ import json
6
6
  import os
7
7
  from enum import Enum
8
8
 
9
- from beet import ItemModel, Model, Texture
9
+ from beet import ItemModel, Model
10
10
  from beet.core.utils import JsonDict
11
- from stouputils.io import super_json_dump, super_json_load
11
+ from stouputils.io import super_json_dump
12
12
 
13
- from ...core import Mem
13
+ from ...core import Mem, texture_mcmeta
14
14
 
15
15
 
16
16
  # GUI Translation for
@@ -25,7 +25,7 @@ class GuiTranslation(Enum):
25
25
  """ Assume you are placing GUI item model in the __27th__ slot of a barrel. """
26
26
 
27
27
  # Setup GUI in resource packs
28
- def setup_gui_in_resource_packs(gui_translations: dict[str, list[int]]) -> dict[str, str]:
28
+ def setup_gui_in_resource_packs(gui_translations: dict[str, GuiTranslation]) -> dict[str, str]:
29
29
  """ Setup GUI item models in resource packs by creating item models and textures for each GUI.
30
30
 
31
31
  Args:
@@ -85,12 +85,7 @@ def setup_gui_in_resource_packs(gui_translations: dict[str, list[int]]) -> dict[
85
85
  )
86
86
 
87
87
  # Copy the textures
88
- src = f"{textures_folder}/{gui}"
89
- mcmeta = None if not os.path.exists(src + ".mcmeta") else super_json_load(src + ".mcmeta")
90
- Mem.ctx.assets[namespace].textures[f"item/{model_name}"] = Texture(
91
- source_path=src,
92
- mcmeta=mcmeta
93
- )
88
+ Mem.ctx.assets[namespace].textures[f"item/{model_name}"] = texture_mcmeta(f"{textures_folder}/{gui}")
94
89
 
95
90
  # Write the file in items/
96
91
  Mem.ctx.assets[namespace].item_models[model_name] = ItemModel(