Commit 860372b6 authored by dylan grafmyre's avatar dylan grafmyre
Browse files


parent 37639735
......@@ -19,3 +19,6 @@ lint
......@@ -29,43 +29,23 @@ GEN_BSPZIP_ADDLIST_FLAGS?=--pack-used-local
J2_BIN?=$(PYTHON_BIN) ./contrib/j2
# my take on compiling
# vbsp: writes bsp
# vvis: depends on .prt, r/w bsp
# vrad: reads lights.rad, r/w bsp
%.bsp: %.vmf
$(BSP_BIN) $(BSP_FLAGS) $(basename $^)
$(VIS_BIN) $(VIS_FLAGS) $(basename $^)
$(RAD_BIN) $(RAD_FLAGS) $(basename $^)
%.prt: %.bsp
@test -f $@ || rm -f $(basename $@).bsp
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) $(basename $@).bsp
%.log: %.bsp
@test -f $@ ||rm -f $(basename $@).bsp
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) $(basename $@).bsp
GMAD_TAR_BIN?=$(PYTHON_BIN) ./contrib/gmad-tar
%_p.bsp: %.bsp
$(BSPZIP_BIN) -addlist $^ $(^:.bsp=.bspzip-addlist) $@ $(BSPZIP_FLAGS)
cp $@ $(MOUNT_DIR)maps\\$(notdir $@)
all: ttt_terrorcon_v2.bsp ttt_terrorcon_v2.lint
%.bspzip-addlist: %.vmf
ifeq ($(GAME),0)
echo user disabled run game via GAME=0
echo "user disabled run game via GAME=0"
$(GAME_DIR)$(GAME) -allowdebug $(VBIN_FLAGS) +map $(notdir $(basename $^)) +gamemode terrortown +ttt_debug_preventwin 1 +ttt_preptime_seconds 10 +ttt_minimum_players 1
install: ttt_terrorcon_v2_hdr_final_p.bsp
cp -v $^ $(MOD_DIR)maps\\
%.lint: %.bspzip-addlist
$(PYTHON_BIN) ./contrib/bspzip-lint $^ 2>&1 | tee $@
maps/%.bsp: %.bsp
cp $^ $@
......@@ -122,14 +102,16 @@ maps/%.bsp: %.bsp
# addons-src/maps/*.res
# addons-src/materials/vgui/maps/*.vmt
# addons-src/materials/vgui/maps/*.vtf
# $(GMAD_BIN) $(GMAD_FLAGS) create -folder "addons-src" -out "$@"
addons/%.gma: %.bsp addons-src/addon.json Makefile
rm -rv \
addons-src/maps/*.bsp \
addons-src/maps/thumb/*.png \
|| true
cp $(word 1, $^) addons-src/maps/
cp addons-src/128x128.png addons-src/maps/thumb/$(basename $(word 1, $^)).png
$(GMAD_BIN) $(GMAD_FLAGS) create -folder "addons-src" -out "$@"
cp thumbnail_map_128.png addons-src/maps/thumb/$(basename $(word 1, $^)).png
$(GMAD_TAR_BIN) addons-src/ --output-tar $(@:.gma=.tar) --tar-prefix $(basename $(word 1, $^)) --gmad-bin $(GMAD_BIN) --output-gma $@ --output-index $(@:.gma=.tar-index) --output-digest $(@:.gma=.tar-sha1sums)
# garrysmod refuses to load gma files untill after thier published and live
# so no use trying to test them
......@@ -138,6 +120,23 @@ addons/%.gma: %.bsp addons-src/addon.json Makefile
# cp -var addons/*.gma $(MOD_DIR)/addons/
publish: addons/ttt_terrorcon_v2_hdr_final_p.gma
$(GMPUBLISH_BIN) $(GMPUBLISH_FLAGS) create -addon "$^" -icon "addons/512x512.jpg"
#publish: addons/ttt_terrorcon_v2_hdr_final_p.gma
# $(GMPUBLISH_BIN) $(GMPUBLISH_FLAGS) create -addon "$^" -icon "addons/512x512.jpg"
# custom rules
all: lint maps/ttt_terrorcon_v2_hdr_final_p.bsp addons/ttt_terrorcon_v2_hdr_final_p.gma
fast: lint maps/ttt_terrorcon_v2_fast.bsp
install-bsp: maps/ttt_terrorcon_v2_hdr_final_p.bsp maps/thumb/ttt_terrorcon_v2_hdr_final_p.png
cp -v $(word 1, $^) $(MOD_DIR)maps\\
cp -v $(word 2, $^) $(MOD_DIR)maps\\thumb\\
# gmod dosn't allow this
# so instead, i've got a parallel artifact being built that can be installed to garrysmod
#install-gma: addons/ttt_terrocon_v2_hdr_final_p.gma
# cp -v $^ $(MOD_DIR)addons\\
lint: ttt_terrorcon_v2.bspzip-addlist
$(PYTHON_BIN) ./contrib/bspzip-lint $^ 2>&1 | tee $@^.lint
$basetexture "vgui\maps\{{argv[1]}}"
$translucent 1
$ignorez 1
$vertexcolor 1
......@@ -5,10 +5,7 @@
"ignore" :
......@@ -5,12 +5,14 @@ import collections
import logging
import os
LOGGER = logging.getLogger(os.path.basename(__file__))
import pyvmf
except ImportError as err:
ARGP = argparse.ArgumentParser()
ARGP.add_argument('input', type=argparse.FileType())
......@@ -28,7 +30,7 @@ class BsppackAddlist(collections.UserDict):
while True:
local = file_.readline().rstrip('\n')
remote = file_.readline().rstrip('\n')
logging.debug('%r -> %r', local, remote)
LOGGER.debug('%r -> %r', local, remote)
if not local:
if not remote:
......@@ -38,27 +40,27 @@ class BsppackAddlist(collections.UserDict):
def lint_local(self):
for key in self:
if not os.path.isfile(key):
logging.error('local file is not file: %r', key)
LOGGER.error('local file is not file: %r', key)
def main_vmflint(argp, bspzip_addlist):
path = '{}.vmf'.format(os.path.splitext([0])'parsing vmf %r ...', path)'parsing vmf %r ...', path)
with open(path) as fh:
vmf = pyvmf.Vmf.load(fh)'parsing vmf %r ... done %r ', path, vmf)'parsing vmf %r ... done %r ', path, vmf)
models = set([i.attributes['model'] for i in vmf.iter_props()])
bspzip_addlist_values = bspzip_addlist.values()
bspzip_addlist_values_lower = [i.lower() for i in bspzip_addlist_values]
for model in models:
prop_is_zipped = model in bspzip_addlist_values
if not prop_is_zipped:
logging.error('using unpacked prop: %r', model)
LOGGER.error('using unpacked prop: %r', model)
for model in models:
prop_is_zipped = model in bspzip_addlist_values
prop_in_source = os.path.isfile(model)
if not prop_in_source:
logging.error('using prop outside of source: %r', model)
LOGGER.error('using prop outside of source: %r', model)
materials = collections.defaultdict(list)
......@@ -77,7 +79,7 @@ def main_vmflint(argp, bspzip_addlist):
for name in usage:
if len(usage[name]) > 3:
usage[name] = usage[name][:3] + ['...']
logging.error('using unpacked material: %r (%r)', material, list(usage.keys()))
LOGGER.error('using unpacked material: %r (%r)', material, list(usage.keys()))
for material in materials_set:
material_in_source = os.path.isfile(os.path.join('materials', '{}.vmt'.format(material)))
......@@ -88,7 +90,7 @@ def main_vmflint(argp, bspzip_addlist):
for name in usage:
if len(usage[name]) > 3:
usage[name] = usage[name][:3] + ['...']
logging.error('using material outside of source: %r (%r)', material, list(usage.keys()))
LOGGER.error('using material outside of source: %r (%r)', material, list(usage.keys()))
def main(argp=None, argv=None):
if argp is None:
#!/usr/bin/env python3
import argparse
import fnmatch
import os
import json
import logging
import tarfile
import hashlib
import collections
import sys
import subprocess
LOGGER = logging.getLogger(os.path.basename(__file__))
def file_type(*args, **kwargs):
def _(name):
fh = open(name, *args, **kwargs)
return fh
except Exception as err:
LOGGER.exception('%r', err)
return _
ARGP = argparse.ArgumentParser()
ARGP.add_argument('--output-digest', type=file_type('w', newline='\n'), default=sys.stdout)
ARGP.add_argument('--output-index', type=file_type('w', newline='\n'), default=sys.stdout)
ARGP.add_argument('--gmad-bin', default='gmad.exe')
def get_bin(name, environ_name, path):
orig_name = name
if os.path.isfile(name):
return name
name = os.environ.get(environ_name, None)
if name is not None and os.path.isfile(name):
return name
for prefix in path:
name = os.path.join(prefix, orig_name)
if os.path.isfile(name):
return name
raise NameError('bin nout found: {!r}'.format(orig_name))
class FnmatchAny(collections.UserList):
def __contains__(self, other):
for i in self:
if fnmatch.fnmatch(other, i):
return True
return False
def hashfile(file_, bufsize=None, hashfunc=None):
if hashfunc is None:
hashfunc = hashlib.sha1
if bufsize is None:
bufsize = 1<<16
obj = hashfunc()
while True:
data =
if not data:
return obj
def get_addon_json(prefix):
path = os.path.join(prefix, 'addon.json')
with open(path) as fh:
return json.load(fh)
def tarfile_logging_filter(tarinfo):'tarinfo: %r', tarinfo.get_info())
return tarinfo
def normpath(prefix, path):
if prefix is not None:
path = os.path.join(prefix, path)
return './{}'.format(path.replace('\\', '/'))
def main_gmad_tar(argp):
addon = get_addon_json(argp.prefix)
addon_ignore = FnmatchAny(addon['ignore'])
tar_f = None
if argp.output_tar:
tar_f =, mode='w', format=tarfile.PAX_FORMAT)
for root, dirs, files in os.walk(argp.prefix):
relroot = os.path.relpath(root, argp.prefix)
if relroot == '.':
relroot = ''
if tar_f:
tar_f.add(root, normpath(argp.tar_prefix, relroot), recursive=False)
for file_ in files:
wholepath = os.path.join(root, file_)
path = os.path.relpath(wholepath, argp.prefix)
path_in_ignore = path in addon_ignore
path_is_addon_json = path.endswith('addon.json')
if path_in_ignore or path_is_addon_json:'addons.json ignored file: %r', wholepath)
continue'member: %r (%r)', path, wholepath)
digest = None
with open(wholepath, 'rb') as fh:
digest = hashfile(fh, hashfunc=argp.hashfunc)
argp.output_digest.write('{} {}\n'.format(
if tar_f:
tar_f.add(wholepath, normpath(argp.tar_prefix, path), filter=tarfile_logging_filter)
if tar_f:
gma_ok = True
if argp.output_gma:
gmad_bin = get_bin(argp.gmad_bin, 'GMAD_BIN', os.environ.get('PATH', []))
execve = [gmad_bin, 'create', '-folder', argp.prefix, '-out', argp.output_gma]'execve: %s', execve), stdin=subprocess.DEVNULL)
gma_ok &= os.path.isfile(argp.output_gma)
return (0 if gma_ok else 1)
def main(argp=None, argv=None):
if argp is None:
argp = ARGP.parse_args(argv)
if argp.hashfunc:
argp.hashfunc = getattr(hashlib, argp.hashfunc)
return main_gmad_tar(argp)
if __name__ == '__main__':
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment