diff --git a/.gitignore b/.gitignore index 9311ff7..ac3d235 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,9 @@ /user_config.cmd /VIDE /game_compiling +/game_hammer /compilepal /bin - /extras/hammerlua/lua/winapiffi +/game_hammer_ +/game_compiling_ diff --git a/metamap_devenv.cmd b/metamap_devenv.cmd new file mode 100644 index 0000000..b28a37e --- /dev/null +++ b/metamap_devenv.cmd @@ -0,0 +1,25 @@ +@prompt $G$S + +git --version +IF ERRORLEVEL 1 GOTO fail + +git clone https://github.com/Metastruct/map-compiling-toolkit.git +git clone git@gitlab.com:metastruct/mapdata.git mapdata +git clone https://github.com/Metastruct/meta-mapassets mapdata2 +git clone git@gitlab.com:metastruct/mapfiles.git mapfiles + +cd map-compiling-toolkit\setup +setup.exe + + +cd .. +"LAUNCH propperall.cmd" +notepad user_config.cmd + +echo DEVENV AUTOSETUP FINISHED. You're on your own. +goto end +:fail +echo FAILURE + +:end +pause \ No newline at end of file diff --git a/setup/GameConfig.txt b/setup/GameConfig.txt new file mode 100644 index 0000000..cc071e2 --- /dev/null +++ b/setup/GameConfig.txt @@ -0,0 +1,33 @@ +"Configs" +{ + "Games" + { + "GMODMAPDEV" + { + "GameDir" "x:\do\GMod\meta3-mapcompiler\game_hammer\garrysmod" + "Hammer" + { + "GameData0" "x:\g\steam\steamapps\common\Source SDK Base 2013 Multiplayer\bin\halflife2.fgd" + "GameData1" "x:\g\steam\steamapps\common\Source SDK Base 2013 Multiplayer\bin\propper.fgd" + "GameData2" "X:\do\gmod\metastruct\mapfiles\metastruct.fgd" + "TextureFormat" "5" + "MapFormat" "4" + "DefaultTextureScale" "0.250000" + "DefaultLightmapScale" "128" + "GameExe" "x:\g\steam\steamapps\common\GarrysMod\hl2.exe" + "DefaultSolidEntity" "func_detail" + "DefaultPointEntity" "light" + "BSP" "x:\g\steam\SteamApps\common\Source SDK Base 2013 Multiplayer\bin\vbsp.exe" + "Vis" "x:\g\steam\SteamApps\common\Source SDK Base 2013 Multiplayer\bin\vvis.exe" + "Light" "x:\g\steam\SteamApps\common\Source SDK Base 2013 Multiplayer\bin\vrad.exe" + "GameExeDir" "x:\g\steam\steamapps\common\GarrysMod" + "MapDir" "x:\g\steam\steamapps\common\GarrysMod\garrysmod\maps" + "BSPDir" "x:\g\steam\steamapps\common\GarrysMod\garrysmod\maps" + "CordonTexture" "tools\toolsskybox" + "MaterialExcludeCount" "0" + } + } + "SDKVersion" "5" + } + "SDKVersion" "5" +} diff --git a/setup/gameinfo.txt b/setup/gameinfo.txt new file mode 100644 index 0000000..f7ca1bd --- /dev/null +++ b/setup/gameinfo.txt @@ -0,0 +1,22 @@ +"GameInfo" +{ + game "GMod" + type multiplayer_only + nodegraph 0 + + + FileSystem + { + SteamAppId 4000 + ToolsAppId 211 + SearchPaths + { + "mod+mod_write+default_write_path" "|gameinfo_path|." + + + "game" "|all_source_engine_paths|hl2" + "platform" "|all_source_engine_paths|platform" + + } + } +} diff --git a/setup/generate_setup_exe.cmd b/setup/generate_setup_exe.cmd new file mode 100644 index 0000000..c99d8ba --- /dev/null +++ b/setup/generate_setup_exe.cmd @@ -0,0 +1,3 @@ +pip install -r requirements.txt +pyinstaller --distpath . -F setup.py --upx-exclude ucrtbase.dll --upx-exclude vcruntime140.dll +pause \ No newline at end of file diff --git a/setup/mount.cfg b/setup/mount.cfg new file mode 100644 index 0000000..08de54e --- /dev/null +++ b/setup/mount.cfg @@ -0,0 +1,7 @@ +"mountcfg" +{ + "cstrike" "X:\g\steam\steamapps\common\Counter-Strike Source\cstrike" + "tf" "X:\g\steam\steamapps\common\Team Fortress 2\tf" + "mapdata" "x:\do\GMod\mapdata" + "sourceengine" "X:/g/steam/steamapps/common/GarrysMod/sourceengine" +} \ No newline at end of file diff --git a/setup/requirements.txt b/setup/requirements.txt new file mode 100644 index 0000000..0e3dd6f --- /dev/null +++ b/setup/requirements.txt @@ -0,0 +1,3 @@ +vpk +vdf +pyinstaller \ No newline at end of file diff --git a/setup/setup.py b/setup/setup.py new file mode 100644 index 0000000..c662c61 --- /dev/null +++ b/setup/setup.py @@ -0,0 +1,198 @@ +from utils import * +from pathlib import Path +import shutil +from shutil import copyfileobj +import vpk +import traceback +import sys + +def my_except_hook(exctype, value, traceback): + if exctype == KeyboardInterrupt: + print("\n\n====== Something happened that we can't handle ======") + print(exctype) + print(value) + print(traceback) + input("\nThis may be a programming error.\n\nPress ENTER to close this window.") + sys.exit(1) + else: + sys.__excepthook__(exctype, value, traceback) +sys.excepthook = my_except_hook + +def pathcheck(fatal,printthing,path): + if path.exists(): + print("\t",printthing,path) + else: + print("\t",printthing,path," !!!! MISSING !!!!") + if fatal: + input("\nPress ENTER to abort.") + sys.exit(1) + +print("\nChecking paths:") +pathcheck(True,"GMod\t\t",GetGModPath()) +pathcheck(False,"Hammer\t\t",HammerRoot()) +pathcheck(False,"Compiler\t",CompilerRoot()) +pathcheck(False,"TF2\t\t",TF2Path("tf")) +pathcheck(False,"CSS\t\t",CSSPath("cstrike")) +pathcheck(True,"Maps\t\t",MapFiles()) +pathcheck(True,"Map assets\t",MapAssets()) +print("") + +def RebuildHammerRoot(): + if not (HammerRoot()/ 'garrysmod' / 'garrysmod_dir.vpk').exists(): + print("missing hammer copy, copying") + (HammerRoot()/ 'garrysmod' / 'cfg').mkdir(parents=True, exist_ok=True) + def mov(s,d): + if (GetGModPath()/s).is_dir(): + shutil.copytree(str(GetGModPath()/s), str(HammerRoot()/ d)) + else: + shutil.copy(str(GetGModPath()/s), str(HammerRoot()/ d)) + + def link(s): + os.link(str(GetGModPath()/s), str(HammerRoot()/ s)) + link("garrysmod/garrysmod_000.vpk") + link("garrysmod/garrysmod_001.vpk") + link("garrysmod/garrysmod_002.vpk") + link("garrysmod/garrysmod_dir.vpk") + mov("platform/platform_misc_000.vpk",'garrysmod/') + mov("platform/platform_misc_dir.vpk",'garrysmod/') + mov("garrysmod/steam.inf",'garrysmod/') + with (HammerRoot() / 'garrysmod/steam_appid.txt').open('wb') as f: + f.write(b"4000\n\0") + + mov("bin",'bin') + + # hammer needs shaders + with vpk.open(str(GetGModPath()/"sourceengine/hl2_misc_dir.vpk")) as hl2misc: + for fpath in hl2misc: + if fpath.startswith("shaders/"): + (HammerRoot() / 'garrysmod' / Path(fpath).parents[0]).mkdir(parents=True, exist_ok=True) + + with hl2misc.get_file(fpath) as input,(HammerRoot() / 'garrysmod' / Path(fpath)).open('wb') as output: + copyfileobj(input, output) + +def RebuildCompilerRoot(): + if not (CompilerRoot()/ 'garrysmod' / 'garrysmod_dir.vpk').exists(): + print("missing compiler root, copying") + (CompilerRoot()/ 'garrysmod' / 'cfg').mkdir(parents=True, exist_ok=True) + def mov(s,d): + if (GetGModPath()/s).is_dir(): + shutil.copytree(str(GetGModPath()/s), str(CompilerRoot()/ d)) + else: + shutil.copy(str(GetGModPath()/s), str(CompilerRoot()/ d)) + + def link(s): + os.link(str(GetGModPath()/s), str(CompilerRoot()/ s)) + link("garrysmod/garrysmod_000.vpk") + link("garrysmod/garrysmod_001.vpk") + link("garrysmod/garrysmod_002.vpk") + link("garrysmod/garrysmod_dir.vpk") + mov("platform/platform_misc_000.vpk",'garrysmod') + mov("platform/platform_misc_dir.vpk",'garrysmod') + mov("garrysmod/steam.inf",'garrysmod') + mov("garrysmod/scripts",'garrysmod/scripts') + + with (CompilerRoot() / 'garrysmod/steam_appid.txt').open('wb') as f: + f.write(b"4000\n\0") + mov("bin",'bin') + + +def BuildHammerGameConfig(): + with open(Path('.') / 'GameConfig.txt') as template: + GameConfig = vdf.parse(template) + + conf=GameConfig["Configs"]["Games"]["GMODMAPDEV"] + conf["GameDir"]=str(HammerRoot()/'garrysmod') + Hammer=conf["Hammer"] + Hammer["BSP"] = str(CompilerRoot()/'bin/win64/vbsp.exe') + Hammer["Vis"] = str(CompilerRoot()/'bin/win64/vvis.exe') + Hammer["Light"] = str(CompilerRoot()/'bin/win64/vrad.exe') + Hammer["GameData0"] = str(HammerRoot()/'bin/halflife2.fgd') + Hammer["GameData1"] = str(ToolkitRoot()/'extras/propper/bin/propper.fgd') + Hammer["GameData2"] = str(MapFiles()/'metastruct.fgd') + Hammer["GameExeDir"]= str(GetGModPath()) + Hammer["MapDir"]= str(GetGModPath()/'garrysmod/maps') + Hammer["GameExe"]= str(GetGModPath()/'hl2.exe') + Hammer["BSPDir"]=Hammer["MapDir"] + + target=HammerRoot() / 'bin/GameConfig.txt' + with target.open('w') as out: + vdf.dump(GameConfig, out, pretty=True) + print("Generated ",target,"!") + +def write_mountcfg(target): + with open(Path('.') / 'mount.cfg') as template: + mountcfg = vdf.parse(template) + + conf=mountcfg["mountcfg"] + conf["cstrike"]=CSSPath("cstrike") + conf["tf"]=TF2Path("tf") + conf["mapdata"]=MapAssets() + conf["sourceengine"]=GetGModPath()/'sourceengine' + + with target.open('w') as out: + vdf.dump(mountcfg, out, pretty=True) + print("Generated ",target,"!") + +def BuildGameInfo(target): + with open(Path('.') / 'gameinfo.txt') as template: + gameinfo = vdf.parse(template,mapper=vdf.VDFDict) + + conf=gameinfo["GameInfo"] + + conf["GameData"] = HammerRoot()/'bin/base.fgd' + conf["GameData0"] = HammerRoot()/'bin/halflife2.fgd' + conf["GameData1"] = MapFiles()/'metastruct.fgd' + + conf["InstancePath"]=MapAssets() + conf["sourceengine"]=GetGModPath()/'sourceengine' + + SearchPaths=conf["FileSystem"]["SearchPaths"] + SearchPaths["game"]=MapAssets() + SearchPaths["game"]=GetGModPath()/"garrysmod/garrysmod.vpk" + SearchPaths["game"]=GetGModPath()/"sourceengine/hl2_textures.vpk" + SearchPaths["game"]=GetGModPath()/"sourceengine/hl2_sound_misc.vpk" + SearchPaths["game"]=GetGModPath()/"sourceengine/hl2_misc.vpk" + SearchPaths["gamebin"]=GetGModPath()/"bin" + SearchPaths["game+game_write"]=GetGModPath()/'garrysmod' + SearchPaths["game+download"]=GetGModPath()/'garrysmod/download' + SearchPaths["platform"]=GetGModPath()/"platform/platform_misc.vpk" + + with target.open('w') as out: + vdf.dump(gameinfo, out, pretty=True) + print("Generated ",target,"!") + +def GenerateUserConfig(): + if (ToolkitRoot() / 'user_config.cmd').exists(): + return + + def GetAnyMap(): + for map in MapFiles().glob('*.vmf'): + return map.replace(".vmf","") + return "gm_mymap" + + with (Path('.') / 'user_config.cmd').open('r') as template, (ToolkitRoot() / 'user_config.cmd').open('w') as output: + mapfile = (MapFiles() / 'metastruct_3.vmf').exists() and 'metastruct_3' or GetAnyMap() + mapname = mapfile=="metastruct_3" and "gm_construct_m3" or "gm_mymap" + + output.write( template.read().format( SteamAppUser="ChangeMe", + SteamPath=GetSteamPath(), + SteamPathAlt=GetGamePath(4000).parents[0], + mapfolder=MapFiles(), + mapdata=MapAssets(), + mapfile=mapfile, + mapname=mapname + )) + print("Generated user_config.cmd, edit it!") +GenerateUserConfig() +RebuildHammerRoot() +write_mountcfg(HammerRoot() / 'garrysmod/cfg/mount.cfg') + +RebuildCompilerRoot() +write_mountcfg(CompilerRoot() / 'garrysmod/cfg/mount.cfg') + +BuildHammerGameConfig() + +BuildGameInfo(HammerRoot() / 'garrysmod/gameinfo.txt') +BuildGameInfo(CompilerRoot() / 'garrysmod/gameinfo.txt') + +input("\nPress ENTER to close.") diff --git a/setup/setup.spec b/setup/setup.spec new file mode 100644 index 0000000..da698ac --- /dev/null +++ b/setup/setup.spec @@ -0,0 +1,33 @@ +# -*- mode: python ; coding: utf-8 -*- + +block_cipher = None + + +a = Analysis(['setup.py'], + pathex=['x:\\do\\GMod\\meta3-mapcompiler\\setup'], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + noarchive=False) +pyz = PYZ(a.pure, a.zipped_data, + cipher=block_cipher) +exe = EXE(pyz, + a.scripts, + a.binaries, + a.zipfiles, + a.datas, + [], + name='setup', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=['ucrtbase.dll', 'vcruntime140.dll'], + runtime_tmpdir=None, + console=True ) diff --git a/setup/user_config.cmd b/setup/user_config.cmd new file mode 100644 index 0000000..40262ee --- /dev/null +++ b/setup/user_config.cmd @@ -0,0 +1,15 @@ +@rem see common.cmd for potential configuration options + +@set SteamAppUser={SteamAppUser} +@set SteamPath={SteamPath} + +@set SteamPathAlt={SteamPathAlt} + +@set mapfolder={mapfolder} +@set version_file=%mapfolder%\ver_meta3.txt +@set mapdata={mapdata} + +@set mapwsid=123456 +@set mapfile={mapfile} +@set mapname={mapname}_%BUILD_VERSION% + diff --git a/setup/utils.py b/setup/utils.py new file mode 100644 index 0000000..e9618fd --- /dev/null +++ b/setup/utils.py @@ -0,0 +1,68 @@ + +import os +import winreg +import vdf +from pathlib import Path +from pprint import pprint as PrintTable +# DETECT OS VERSION + +def Is64Windows(): + return 'PROGRAMFILES(X86)' in os.environ + +def GetProgramFiles32(): + if Is64Windows(): + return os.environ['PROGRAMFILES(X86)'] + else: + return os.environ['PROGRAMFILES'] + +def GetProgramFiles64(): + if Is64Windows(): + return os.environ['PROGRAMW6432'] + else: + return None + +if Is64Windows() is True: + key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432Node\\Valve\\Steam") +else: + key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam") + +steampath = winreg.QueryValueEx(key, "InstallPath")[0] +def GetSteamPath(): + return steampath + +vdffile = vdf.parse(open(steampath + "/SteamApps/LibraryFolders.vdf")) +vdflocations = [x for x in vdffile['LibraryFolders']]+[steampath] +def GetGamePath(appid): + for acfpath in vdflocations: + appmanifestpath = acfpath + "/SteamApps/appmanifest_%d.acf"%(appid) + if os.path.isfile(appmanifestpath): + appmanifest = vdf.parse(open(appmanifestpath)) + return Path(acfpath+"\\SteamApps\\common\\"+appmanifest['AppState']['installdir']+"\\") + +def GetGModPath(): + return GetGamePath(4000) + +def TF2Path(d="."): + return GetGamePath(440) / d + +def CSSPath(d="."): + return GetGamePath(240) / d + +def MapFiles(d="."): + return Path("../../mapfiles").resolve() / d +def MapAssets(d="."): + return Path("../../mapdata").resolve() / d + + +def HammerRoot(): + p = Path("../game_hammer").resolve() + #assert p.exists() + return p + +def CompilerRoot(): + p = Path("../game_compiling").resolve() + #assert p.exists() + return p + +def ToolkitRoot(d="."): + return Path("..").resolve() / d