This commit is the equivalent of a atomic bomb

This commit is contained in:
2026-02-15 08:08:56 -03:00
commit e4ac56b038
6934 changed files with 916278 additions and 0 deletions

0
make/__init__.py Normal file
View File

129
make/__main__.py Normal file
View File

@@ -0,0 +1,129 @@
__version__ = "2.00"
import sys
from format import array_to_string, format_objects_to_markdown, read_last_lines
from terminal import print_error, print_green, print_yellow
if sys.version_info[0] == 2:
print("Python 3 is required.")
sys.exit(1)
import os
import os.path
import subprocess
from pathlib import Path
import requests
from obsfuschatedList import obfuschatedList
def Fract_Sec(s):
temp = float()
temp = float(s) / (60*60*24)
d = int(temp)
temp = (temp - d) * 24
h = int(temp)
temp = (temp - h) * 60
m = int(temp)
temp = (temp - m) * 60
sec = temp
return d,h,m,sec
#endef Fract_Sec
failedBuilds = []
def pack_directory(directory):
output_dir = os.getenv("OUTPUT_DIR")
if not output_dir:
print_error("OUTPUT_DIR not set")
sys.exit(1)
absolute_output_dir = os.path.abspath(output_dir)
if not os.path.exists(absolute_output_dir):
os.makedirs(absolute_output_dir)
try:
absolute_path = os.path.abspath("P:/braf/" + directory)
print("Packing Directory {}".format(absolute_path))
print("Target Directory {}".format(absolute_output_dir))
cmd = ["pboproject","-P", absolute_path, "+M={}".format(absolute_output_dir)]
if directory in obfuschatedList:
cmd.append("+O")
else:
cmd.append("-O")
returnOutput = subprocess.call(cmd)
print("Builded {}".format(directory))
if returnOutput == 0:
print_green("Addon {} successfully built/signed.".format(directory))
else:
print_error("Addon {} not successfully built/signed".format(directory))
temp_dir = r'P:/temp'
if os.path.exists(temp_dir):
errorLog = read_last_lines(os.path.join(temp_dir,directory+".packing.log"), 10)
if errorLog is not None:
print_yellow("The last 10 lines of the log are:\n {}".format(errorLog))
else:
print_error("The log could not be found.")
failedBuilds.append({"directory": directory, "errorLog": [errorLog]})
else:
print_error("The temp folder could not be found.")
failedBuilds.append({"directory": directory, "errorLog": ["The log could not be found."]})
print ("Resuming build...")
except subprocess.CalledProcessError as e:
print(f"Error running command in {directory}: {e}")
def main():
if len(sys.argv) < 2:
print_error("No directories provided!")
sys.exit(1)
if len(sys.argv) == 2 and " " in sys.argv[1]:
directories = sys.argv[1].split()
else:
directories = sys.argv[1:]
for directory in directories:
path = Path(directory)
if path.is_dir():
pack_directory(directory)
else:
print_error(f"{directory} is not a valid directory path")
sys.exit(1)
print_yellow("There were {} failed builds".format(len(failedBuilds)))
discord_webhook = os.getenv("DISCORD_WEBHOOK")
if len(failedBuilds) > 0:
print_error("There were {} failed builds:\n {}".format(len(failedBuilds), (failedBuilds)))
if discord_webhook != "":
requests.post(discord_webhook, json={
"content": "**There were {} failed builds:**\n {}\n".format(len(failedBuilds), format_objects_to_markdown(failedBuilds)),
"username": "Build Failed",
"avatar_url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQE6prA5NL5oqTqEDMAkU823YY4xGMq9c3ucg&s"
})
sys.exit(1)
else:
print_green("All builds were successful")
if discord_webhook != "":
if len(directories) > 0:
requests.post(discord_webhook, json={
"content": "**All builds were successful** \n builded addons: {}".format(array_to_string(directories)),
"username": "Build Success",
"avatar_url": "https://cdn1.iconfinder.com/data/icons/basic-ui-elements-color-round/3/15-512.png"
})
sys.exit(0)
if __name__ == "__main__":
main()

38
make/format.py Normal file
View File

@@ -0,0 +1,38 @@
import os
from typing import List
def succesfullBuilds_to_string(succesfullBuilds: List[str]):
return ", ".join(succesfullBuilds)
def array_to_string(arr):
if not arr:
return ''
arr = [str(item) for item in arr]
if len(arr) == 1:
return arr[0]
if len(arr) == 2:
return f"{arr[0]} and {arr[1]}"
return f"{', '.join(arr[:-1])}, and {arr[-1]}"
def read_last_lines(file_path, num_lines=10):
if os.path.exists(file_path):
with open(file_path, 'r') as file:
lines = file.readlines()[-num_lines:] # Get the last `num_lines` lines
return "\n".join([line.strip() + "\n" for line in lines])
else:
return None
def format_objects_to_markdown(objects):
markdown_output = ""
for obj in objects:
directory = obj.get("directory", "Unknown Object")
error_log = obj.get("errorLog", "No error log available")
markdown_output += f"\n# {directory}\n\n"
markdown_output += "Error Output:\n"
markdown_output += f"```\n{array_to_string(error_log).replace(',', '')}\n```\n\n"
return markdown_output

80
make/mikero.py Normal file
View File

@@ -0,0 +1,80 @@
import os
import shutil
import subprocess
import sys
from make.terminal import print_error, print_green, print_yellow
if sys.platform == "win32":
import winreg
def mikero_windows_registry(path, access=winreg.KEY_READ):
try:
return winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Mikero\{}".format(path), access=access)
except FileNotFoundError:
try:
return winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"Software\Mikero\{}".format(path), access=access)
except FileNotFoundError:
try:
return winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Wow6432Node\Mikero\{}".format(path), access=access)
except FileNotFoundError:
return winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"Software\Wow6432Node\Mikero\{}".format(path), access=access)
def find_depbo_tools():
"""Use registry entries to find DePBO-based tools."""
# try running pboProject once if it's not in registry
try:
pboProject = mikero_windows_registry("pboProject")
print(f"pboProject found normally via registry")
except:
print(f"pboProject not in registry")
pboProject = shutil.which('pboProject')
if (pboProject is None):
print("pboProject not in sys path")
else:
print(f"pboProject startup")
ret = subprocess.call([pboProject, "-P"])
requiredToolPaths = {"pboProject": None, "rapify": None, "MakePbo": None}
failed = False
for tool in requiredToolPaths:
try:
k = mikero_windows_registry(tool)
path = winreg.QueryValueEx(k, "exe")[0]
except FileNotFoundError:
print_error("Could not find {}".format(tool))
failed = True
else:
#Strip any quotations from the path due to a MikeRo tool bug which leaves a trailing space in some of its registry paths.
requiredToolPaths[tool] = path.strip('"')
print_green("Found {}.".format(tool))
finally:
winreg.CloseKey(k)
if failed:
raise Exception("BadDePBO", "DePBO tools not installed correctly")
return requiredToolPaths
def pboproject_settings():
"""Use registry entries to configure needed pboproject settings."""
value_exclude = "thumbs.db,*.txt,*.h,*.dep,*.cpp,*.bak,*.png,*.log,*.pew,source,*.tga"
try:
pbok = mikero_windows_registry(r"pboProject")
try:
k = winreg.OpenKey(pbok, "Settings", access=winreg.KEY_SET_VALUE)
except:
print_yellow("WARNING: creating pboProject/Settings reg manually")
print_yellow("This should have happened before running make.py")
k = winreg.CreateKeyEx(pbok, "Settings", access=winreg.KEY_SET_VALUE)
winreg.SetValueEx(k, "m_exclude", 0, winreg.REG_SZ, value_exclude)
winreg.SetValueEx(k, "m_exclude2", 0, winreg.REG_SZ, value_exclude)
winreg.SetValueEx(k, "wildcard_exclude_from_pbo_normal", 0, winreg.REG_SZ, value_exclude)
winreg.SetValueEx(k, "wildcard_exclude_from_pbo_unbinarised_missions", 0, winreg.REG_SZ, value_exclude)
except:
raise Exception("BadDePBO", "pboProject not installed correctly, make sure to run it at least once")
finally:
winreg.CloseKey(k)
winreg.CloseKey(pbok)

28
make/obsfuschatedList.py Normal file
View File

@@ -0,0 +1,28 @@
obfuschatedList = [
"braf_air",
"braf_air2",
"braf_armored",
"braf_boat",
"braf_characters_army",
"braf_characters_aviation",
"braf_characters_backpack",
"braf_characters_binfa",
"braf_characters_headgear",
"braf_characters_marine",
"braf_characters_vest",
"braf_soft",
"braf_static",
"braf_structures",
"braf_structures_ammoboxes",
"braf_structures_land",
"braf_weapons_assault_rifles",
"braf_weapons_attach_side",
"braf_weapons_launchers",
"braf_weapons_machine_guns",
"braf_weapons_muzzle",
"braf_weapons_pistols",
"braf_weapons_scopes",
"braf_weapons_shotguns",
"braf_weapons_smg",
"braf_weapons_sniper_rifles"
]

122
make/terminal.py Normal file
View File

@@ -0,0 +1,122 @@
# Copyright (c) André Burgaud
# http://www.burgaud.com/bring-colors-to-the-windows-console-with-python/
import sys
if sys.platform == "win32":
from ctypes import windll, Structure, c_short, c_ushort, byref
SHORT = c_short
WORD = c_ushort
class COORD(Structure):
"""struct in wincon.h."""
_fields_ = [
("X", SHORT),
("Y", SHORT)]
class SMALL_RECT(Structure):
"""struct in wincon.h."""
_fields_ = [
("Left", SHORT),
("Top", SHORT),
("Right", SHORT),
("Bottom", SHORT)]
class CONSOLE_SCREEN_BUFFER_INFO(Structure):
"""struct in wincon.h."""
_fields_ = [
("dwSize", COORD),
("dwCursorPosition", COORD),
("wAttributes", WORD),
("srWindow", SMALL_RECT),
("dwMaximumWindowSize", COORD)]
# winbase.h
STD_INPUT_HANDLE = -10
STD_OUTPUT_HANDLE = -11
STD_ERROR_HANDLE = -12
# wincon.h
FOREGROUND_BLACK = 0x0000
FOREGROUND_BLUE = 0x0001
FOREGROUND_GREEN = 0x0002
FOREGROUND_CYAN = 0x0003
FOREGROUND_RED = 0x0004
FOREGROUND_MAGENTA = 0x0005
FOREGROUND_YELLOW = 0x0006
FOREGROUND_GREY = 0x0007
FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified.
BACKGROUND_BLACK = 0x0000
BACKGROUND_BLUE = 0x0010
BACKGROUND_GREEN = 0x0020
BACKGROUND_CYAN = 0x0030
BACKGROUND_RED = 0x0040
BACKGROUND_MAGENTA = 0x0050
BACKGROUND_YELLOW = 0x0060
BACKGROUND_GREY = 0x0070
BACKGROUND_INTENSITY = 0x0080 # background color is intensified.
stdout_handle = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
def get_text_attr():
"""Returns the character attributes (colors) of the console screen
buffer."""
csbi = CONSOLE_SCREEN_BUFFER_INFO()
GetConsoleScreenBufferInfo(stdout_handle, byref(csbi))
return csbi.wAttributes
def set_text_attr(color):
"""Sets the character attributes (colors) of the console screen
buffer. Color is a combination of foreground and background color,
foreground and background intensity."""
SetConsoleTextAttribute(stdout_handle, color)
###############################################################################
def color(color):
"""Set the color. Works on Win32 and normal terminals."""
if sys.platform == "win32":
if color == "green":
set_text_attr(FOREGROUND_GREEN | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY)
elif color == "yellow":
set_text_attr(FOREGROUND_YELLOW | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY)
elif color == "red":
set_text_attr(FOREGROUND_RED | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY)
elif color == "blue":
set_text_attr(FOREGROUND_BLUE | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY)
elif color == "reset":
set_text_attr(FOREGROUND_GREY | get_text_attr() & 0x0070)
elif color == "grey":
set_text_attr(FOREGROUND_GREY | get_text_attr() & 0x0070)
else :
if color == "green":
sys.stdout.write('\033[92m')
elif color == "red":
sys.stdout.write('\033[91m')
elif color == "blue":
sys.stdout.write('\033[94m')
elif color == "reset":
sys.stdout.write('\033[0m')
def print_error(msg):
color("red")
print("ERROR: {}".format(msg))
color("reset")
def print_green(msg):
color("green")
print(msg)
color("reset")
def print_blue(msg):
color("blue")
print(msg)
color("reset")
def print_yellow(msg):
color("yellow")
print(msg)
color("reset")

45
make/util.py Normal file
View File

@@ -0,0 +1,45 @@
import os
from tempfile import mkstemp
import pathlib
import platform
import glob
import hashlib
import configparser
import json
import traceback
import time
import timeit
import re
def get_directory_hash(directory):
directory_hash = hashlib.sha1()
if not os.path.exists (directory):
return -1
try:
for root, dirs, files in os.walk(directory):
for names in files:
path = os.path.join(root, names)
try:
f = open(path, 'rb')
except:
# You can't open the file for some reason
f.close()
continue
while 1:
# Read file in as little chunks
buf = f.read(4096)
if not buf: break
new = hashlib.sha1(buf)
directory_hash.update(new.digest())
f.close()
except:
# Print the stack traceback
traceback.print_exc()
return -2
retVal = directory_hash.hexdigest()
#print_yellow("Hash Value for {} is {}".format(directory,retVal))
return directory_hash.hexdigest()