Ejemplo n.º 1
0
def main(argv):
    LOGGER.info('Srctools VRAD hook started!')

    game_info = find_gameinfo(argv)

    fsys = game_info.get_filesystem()
    fsys.open_ref()

    packlist = PackList(fsys)

    LOGGER.info('Gameinfo: {}\nSearch path: \n{}', game_info.path,
                '\n'.join([sys[0].path for sys in fsys.systems]))

    fgd = load_fgd()

    LOGGER.info('Loading soundscripts...')
    packlist.load_soundscript_manifest('srctools_sndscript_data.vdf')
    LOGGER.info('Done! ({} sounds)', len(packlist.soundscripts))

    # The path is the last argument to VRAD
    # Hammer adds wrong slashes sometimes, so fix that.
    path = os.path.normpath(argv[-1])

    LOGGER.info("Map path is " + path)
    if path == "":
        raise Exception("No map passed!")

    if not path.endswith(".bsp"):
        path += ".bsp"

    LOGGER.info('Reading BSP...')
    bsp_file = BSP(path)
    bsp_file.read_header()
    bsp_file.read_game_lumps()

    LOGGER.info('Reading entities...')
    vmf = bsp_file.read_ent_data()
    LOGGER.info('Done!')

    run_transformations(vmf, fsys, packlist)

    bsp_file.replace_lump(
        bsp_file.filename,
        BSP_LUMPS.ENTITIES,
        bsp_file.write_ent_data(vmf),
    )

    LOGGER.info('Finished writing entities.')

    packlist.pack_fgd(vmf, fgd)

    packlist.pack_from_bsp(bsp_file)
    packlist.eval_dependencies()

    with bsp_file.packfile() as pak_zip:
        packlist.pack_into_zip(pak_zip)

    LOGGER.info("srctools VRAD hook finished!")
Ejemplo n.º 2
0
def main(argv):
    LOGGER.info('Srctools VRAD hook started!')

    game_info = find_gameinfo(argv)

    fsys = game_info.get_filesystem()
    fsys.open_ref()

    packlist = PackList(fsys)

    LOGGER.info('Gameinfo: {}\nSearch path: \n{}', game_info.path, '\n'.join([sys[0].path for sys in fsys.systems]))

    fgd = load_fgd()

    LOGGER.info('Loading soundscripts...')
    packlist.load_soundscript_manifest('srctools_sndscript_data.vdf')
    LOGGER.info('Done! ({} sounds)', len(packlist.soundscripts))

    # The path is the last argument to VRAD
    # Hammer adds wrong slashes sometimes, so fix that.
    path = os.path.normpath(argv[-1])

    LOGGER.info("Map path is " + path)
    if path == "":
        raise Exception("No map passed!")

    if not path.endswith(".bsp"):
        path += ".bsp"

    LOGGER.info('Reading BSP...')
    bsp_file = BSP(path)
    bsp_file.read_header()
    bsp_file.read_game_lumps()

    LOGGER.info('Reading entities...')
    vmf = bsp_file.read_ent_data()
    LOGGER.info('Done!')

    run_transformations(vmf, fsys, packlist)

    bsp_file.replace_lump(
        bsp_file.filename,
        BSP_LUMPS.ENTITIES,
        bsp_file.write_ent_data(vmf),
    )

    LOGGER.info('Finished writing entities.')

    packlist.pack_fgd(vmf, fgd)

    packlist.pack_from_bsp(bsp_file)
    packlist.eval_dependencies()

    with bsp_file.packfile() as pak_zip:
        packlist.pack_into_zip(pak_zip)

    LOGGER.info("srctools VRAD hook finished!")
Ejemplo n.º 3
0
def main(argv):
    LOGGER.info('BEE2 VRAD hook started!')
    args = " ".join(argv)
    fast_args = argv[1:]
    full_args = argv[1:]

    # The path is the last argument to vrad
    # P2 adds wrong slashes sometimes, so fix that.
    fast_args[-1] = path = os.path.normpath(argv[-1])

    LOGGER.info("Map path is " + path)
    if path == "":
        raise Exception("No map passed!")

    load_config()

    for a in fast_args[:]:
        if a.casefold() in (
                "-both",
                "-final",
                "-staticproplighting",
                "-staticproppolys",
                "-textureshadows",
        ):
            # remove final parameters from the modified arguments
            fast_args.remove(a)
        elif a in ('-force_peti', '-force_hammer', '-no_pack'):
            # we need to strip these out, otherwise VBSP will get confused
            fast_args.remove(a)
            full_args.remove(a)

    fast_args = ['-bounce', '2', '-noextra'] + fast_args

    # Fast args: -bounce 2 -noextra -game $gamedir $path\$file
    # Final args: -both -final -staticproplighting -StaticPropPolys
    # -textureshadows  -game $gamedir $path\$file

    if not path.endswith(".bsp"):
        path += ".bsp"

    # If VBSP thinks it's hammer, trust it.
    if CONF.bool('is_hammer', False):
        is_peti = edit_args = False
    else:
        is_peti = True
        # Detect preview via knowing the bsp name. If we are in preview,
        # check the config file to see what was specified there.
        if os.path.basename(path) == "preview.bsp":
            edit_args = not CONF.bool('force_full', False)
        else:
            # publishing - always force full lighting.
            edit_args = False

    if '-force_peti' in args or '-force_hammer' in args:
        # we have override commands!
        if '-force_peti' in args:
            LOGGER.warning('OVERRIDE: Applying cheap lighting!')
            is_peti = edit_args = True
        else:
            LOGGER.warning('OVERRIDE: Preserving args!')
            is_peti = edit_args = False

    LOGGER.info('Final status: is_peti={}, edit_args={}', is_peti, edit_args)

    LOGGER.info('Reading BSP')
    bsp_file = BSP(path)
    bsp_file.read_header()
    LOGGER.info('Done!')

    if '-no_pack' not in args:
        pack_content(bsp_file, path, is_peti)
    else:
        LOGGER.warning("Packing files is disabled!")

    if is_peti:
        mod_screenshots()

    if edit_args:
        LOGGER.info("Forcing Cheap Lighting!")
        run_vrad(fast_args)
    else:
        if is_peti:
            LOGGER.info(
                "Publishing - Full lighting enabled! (or forced to do so)")
        else:
            LOGGER.info("Hammer map detected! Not forcing cheap lighting..")
        run_vrad(full_args)

    LOGGER.info("BEE2 VRAD hook finished!")
Ejemplo n.º 4
0
Archivo: vrad.py Proyecto: prrg/BEE2.4
def main(argv: List[str]) -> None:
    LOGGER.info('BEE2 VRAD hook started!')

    args = " ".join(argv)
    fast_args = argv[1:]
    full_args = argv[1:]

    if not fast_args:
        # No arguments!
        LOGGER.info(
            'No arguments!\n'
            "The BEE2 VRAD takes all the regular VRAD's "
            'arguments, with some extra arguments:\n'
            '-force_peti: Force enabling map conversion. \n'
            "-force_hammer: Don't convert the map at all.\n"
            "If not specified, the map name must be \"preview.bsp\" to be "
            "treated as PeTI.")
        sys.exit()

    # The path is the last argument to vrad
    # P2 adds wrong slashes sometimes, so fix that.
    fast_args[-1] = path = os.path.normpath(argv[-1])  # type: str

    LOGGER.info("Map path is " + path)

    load_config()

    for a in fast_args[:]:
        if a.casefold() in (
                "-both",
                "-final",
                "-staticproplighting",
                "-staticproppolys",
                "-textureshadows",
        ):
            # remove final parameters from the modified arguments
            fast_args.remove(a)
        elif a in ('-force_peti', '-force_hammer', '-no_pack'):
            # we need to strip these out, otherwise VRAD will get confused
            fast_args.remove(a)
            full_args.remove(a)

    fast_args = ['-bounce', '2', '-noextra'] + fast_args

    # Fast args: -bounce 2 -noextra -game $gamedir $path\$file
    # Final args: -both -final -staticproplighting -StaticPropPolys
    # -textureshadows  -game $gamedir $path\$file

    if not path.endswith(".bsp"):
        path += ".bsp"

    if not os.path.exists(path):
        raise ValueError('"{}" does not exist!'.format(path))
    if not os.path.isfile(path):
        raise ValueError('"{}" is not a file!'.format(path))

    # If VBSP thinks it's hammer, trust it.
    if CONF.bool('is_hammer', False):
        is_peti = edit_args = False
    else:
        is_peti = True
        # Detect preview via knowing the bsp name. If we are in preview,
        # check the config file to see what was specified there.
        if os.path.basename(path) == "preview.bsp":
            edit_args = not CONF.bool('force_full', False)
        else:
            # publishing - always force full lighting.
            edit_args = False

    if '-force_peti' in args or '-force_hammer' in args:
        # we have override commands!
        if '-force_peti' in args:
            LOGGER.warning('OVERRIDE: Applying cheap lighting!')
            is_peti = edit_args = True
        else:
            LOGGER.warning('OVERRIDE: Preserving args!')
            is_peti = edit_args = False

    LOGGER.info('Final status: is_peti={}, edit_args={}', is_peti, edit_args)

    # Grab the currently mounted filesystems in P2.
    game = find_gameinfo(argv)
    root_folder = game.path.parent
    fsys = game.get_filesystem()

    fsys_tag = fsys_mel = None
    if is_peti and 'mel_vpk' in CONF:
        fsys_mel = VPKFileSystem(CONF['mel_vpk'])
        fsys.add_sys(fsys_mel)
    if is_peti and 'tag_dir' in CONF:
        fsys_tag = RawFileSystem(CONF['tag_dir'])
        fsys.add_sys(fsys_tag)

    LOGGER.info('Reading BSP')
    bsp_file = BSP(path)
    bsp_file.read_header()

    bsp_ents = bsp_file.read_ent_data()

    zip_data = BytesIO()
    zip_data.write(bsp_file.get_lump(BSP_LUMPS.PAKFILE))
    zipfile = ZipFile(zip_data, mode='a')

    # Mount the existing packfile, so the cubemap files are recognised.
    fsys.systems.append((ZipFileSystem('', zipfile), ''))

    fsys.open_ref()

    LOGGER.info('Done!')

    LOGGER.info('Reading our FGD files...')
    fgd = load_fgd()

    packlist = PackList(fsys)
    packlist.load_soundscript_manifest(
        str(root_folder / 'bin/bee2/sndscript_cache.vdf'))

    # We nee to add all soundscripts in scripts/bee2_snd/
    # This way we can pack those, if required.
    for soundscript in fsys.walk_folder('scripts/bee2_snd/'):
        if soundscript.path.endswith('.txt'):
            packlist.load_soundscript(soundscript, always_include=False)

    if is_peti:
        LOGGER.info('Adding special packed files:')
        music_data = CONF.find_key('MusicScript', [])
        if music_data:
            packlist.pack_file('scripts/BEE2_generated_music.txt',
                               PackType.SOUNDSCRIPT,
                               data=generate_music_script(
                                   music_data, packlist))

        for filename, arcname in inject_files():
            LOGGER.info('Injecting "{}" into packfile.', arcname)
            with open(filename, 'rb') as f:
                packlist.pack_file(arcname, data=f.read())

    LOGGER.info('Run transformations...')
    run_transformations(bsp_ents, fsys, packlist)

    LOGGER.info('Scanning map for files to pack:')
    packlist.pack_from_bsp(bsp_file)
    packlist.pack_fgd(bsp_ents, fgd)
    packlist.eval_dependencies()
    LOGGER.info('Done!')

    if is_peti:
        packlist.write_manifest()
    else:
        # Write with the map name, so it loads directly.
        packlist.write_manifest(os.path.basename(path)[:-4])

    # We need to disallow Valve folders.
    pack_whitelist = set()
    pack_blacklist = set()
    if is_peti:
        pack_blacklist |= {
            RawFileSystem(root_folder / 'portal2_dlc2'),
            RawFileSystem(root_folder / 'portal2_dlc1'),
            RawFileSystem(root_folder / 'portal2'),
            RawFileSystem(root_folder / 'platform'),
            RawFileSystem(root_folder / 'update'),
        }
        pack_whitelist.add(fsys_mel)
        pack_whitelist.add(fsys_tag)
        # If those weren't present, we added a None.
        pack_whitelist.discard(None)

    if '-no_pack' not in args:
        # Cubemap files packed into the map already.
        existing = set(zipfile.infolist())

        LOGGER.info('Writing to BSP...')
        packlist.pack_into_zip(
            zipfile,
            ignore_vpk=True,
            whitelist=pack_whitelist,
            blacklist=pack_blacklist,
        )

        LOGGER.info(
            'Packed files:\n{}', '\n'.join([
                zipinfo.filename for zipinfo in zipfile.infolist()
                if zipinfo.filename not in existing
            ]))

    dump_files(zipfile)

    zipfile.close()  # Finalise the zip modification

    # Copy the zipfile into the BSP file, and adjust the headers
    bsp_file.replace_lump(
        path,
        BSP_LUMPS.PAKFILE,
        zip_data.getvalue(),  # Get the binary data we need
    )
    # Copy new entity data.
    bsp_file.replace_lump(
        path,
        BSP_LUMPS.ENTITIES,
        BSP.write_ent_data(bsp_ents),
    )
    LOGGER.info(' - BSP written!')

    if is_peti:
        mod_screenshots()

    if edit_args:
        LOGGER.info("Forcing Cheap Lighting!")
        run_vrad(fast_args)
    else:
        if is_peti:
            LOGGER.info(
                "Publishing - Full lighting enabled! (or forced to do so)")
        else:
            LOGGER.info("Hammer map detected! Not forcing cheap lighting..")
        run_vrad(full_args)

    LOGGER.info("BEE2 VRAD hook finished!")
def pack_content(path, is_peti):
    """Pack any custom content into the map.

    Filelist format: "[control char]filename[\t packname]"
    Filename is the name of the actual file. If given packname is the
    name to save it into the packfile as. If the first character of the
    filename is '#', the file will be added to the soundscript manifest too.
    """
    files = set()  # Files to pack.
    soundscripts = set()  # Soundscripts need to be added to the manifest too..
    rem_soundscripts = set(
    )  # Soundscripts to exclude, so we can override the sounds.
    particles = set()
    additional_files = set()  # .vvd files etc which also are needed.
    preload_files = set()  # Files we want to force preloading

    try:
        pack_list = open(path[:-4] + '.filelist.txt')
    except (IOError, FileNotFoundError):
        pass  # Assume no files if missing..
        # There might still be things to inject.
    else:
        with pack_list:
            for line in pack_list:
                line = line.strip().lower()
                if not line or line.startswith('//'):
                    continue  # Skip blanks or comments

                if line[:8] == 'precache':
                    preload_files.add(line)
                    continue

                if line[:2] == '-#':
                    rem_soundscripts.add(line[2:])
                    continue

                if line[:1] == '#':
                    line = line[1:]
                    soundscripts.add(line)

                # We need to add particle systems to a manifest.
                if line.startswith('particles/'):
                    particles.add(line)

                if line[-4:] == '.mdl':
                    additional_files.update(
                        {line[:-4] + ext
                         for ext in MDL_ADDITIONAL_EXT})

                files.add(line)

    # Remove guessed files not in the original list.
    additional_files -= files

    # Only generate a soundscript for PeTI maps..
    if is_peti:
        music_data = CONF.find_key('MusicScript', [])
        if music_data.value:
            generate_music_script(music_data, files)
            # Add the new script to the manifest file..
            soundscripts.add('scripts/BEE2_generated_music.txt')

    # We still generate these in hammer-mode - it's still useful there.
    # If no files are packed, no manifest will be added either.
    gen_sound_manifest(soundscripts, rem_soundscripts)
    gen_part_manifest(particles)
    gen_auto_script(preload_files, is_peti)

    inject_names = list(inject_files())

    # Abort packing if no packfiles exist, and no injected files exist either.
    if not files and not inject_names:
        LOGGER.info('No files to pack!')
        return

    LOGGER.info('Files to pack:')
    for file in sorted(files):
        # \t seperates the original and in-pack name if used.
        LOGGER.info(' # "' + file.replace('\t', '" as "') + '"')

    if additional_files and LOGGER.isEnabledFor(logging.DEBUG):
        LOGGER.info('Potential additional files:')
        for file in sorted(additional_files):
            LOGGER.debug(' # "' + file + '"')

    LOGGER.info('Injected files:')
    for _, file in inject_names:
        LOGGER.info(' # "' + file + '"')

    LOGGER.info("Packing Files!")
    bsp_file = BSP(path)
    LOGGER.debug(' - Header read')
    bsp_file.read_header()

    # Manipulate the zip entirely in memory
    zip_data = BytesIO()
    zip_data.write(bsp_file.get_lump(BSP_LUMPS.PAKFILE))
    zipfile = ZipFile(zip_data, mode='a')
    LOGGER.debug(' - Existing zip read')

    zip_write = get_zip_writer(zipfile)

    for file in files:
        pack_file(zip_write, file)

    for file in additional_files:
        pack_file(zip_write, file, suppress_error=True)

    for filename, arcname in inject_names:
        LOGGER.info('Injecting "{}" into packfile.', arcname)
        zip_write(filename, arcname)

    LOGGER.debug(' - Added files')

    zipfile.close()  # Finalise the zip modification

    # Copy the zipfile into the BSP file, and adjust the headers
    bsp_file.replace_lump(
        path,
        BSP_LUMPS.PAKFILE,
        zip_data.getvalue(),  # Get the binary data we need
    )
    LOGGER.debug(' - BSP written!')

    LOGGER.info("Packing complete!")