Raised This Month: $ Target: $400
 0% 

Getting the entity list directly from any BSP file


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Thrawn2
Veteran Member
Join Date: Apr 2009
Old 05-21-2011 , 20:03   Getting the entity list directly from any BSP file
Reply With Quote #1

I've needed a way to get the entity list straight from a bsp file at runtime.
This is not beautified or anything, but what i've came up with in a hurry:
PHP Code:
#define READSIZE        4096

#define GET_LITTLE_ENDIAN_INT(%1,%2,%3)\
    
%|= %3[%1+3] & 0xFF;\
    %
<<= 8;\
    %
|= %3[%1+2] & 0xFF;\
    %
<<= 8;\
    %
|= %3[%1+1] & 0xFF;\
    %
<<= 8;\
    %
|= %3[%1] & 0xFF;

stock bool:JumpToEntityByClassname(Handle:hKV, const String:sClassName[]) {
    while (
KvGotoNextKey(hKVtrue)) {
        new 
String:sValue[255];
        
KvGetString(hKV"classname"sValuesizeof(sValue), "");

        if(
StrEqual(sValuesClassName)) {
            return 
true;
        }
    }

    return 
false;
}

stock Handle:ExtractEntities(const String:sIn[]) {
    new 
String:sMap[PLATFORM_MAX_PATH];
    
Format(sMapsizeof(sMap), "%s%s"sInStrContains(sMap".bsp"false) == -".bsp" "");

    new 
String:sPath[PLATFORM_MAX_PATH];
    
Format(sPathsizeof(sPath), "maps/%s"sMap);

    if(!
FileExists(sPath)) {
        
LogError("Map \"%s\" does not exists"sMap);
        return 
INVALID_HANDLE;
    }

    new 
String:sOutput[PLATFORM_MAX_PATH];
    
Format(sOutputsizeof(sOutput), "%s.entities.txt"sPath);

    if(!
FileExists(sOutput)) {
        
LogMessage("Grabbing entity list from %s"sMap);
        new 
Handle:hFile OpenFile(sPath"rb");

        new 
String:sFormat[5];
        
ReadFileString(hFilesFormatsizeof(sFormat), 4);

        new 
String:sVersion[5];
        
ReadFileString(hFilesVersionsizeof(sVersion), 4);
        new 
iVersion 0;
        
GET_LITTLE_ENDIAN_INT(0,iVersion,sVersion)

        
LogMessage("BSP-Format: %s"sFormat);
        if(!
StrEqual(sFormat"VBSP")) {
            
LogError("Map %s is no Valve BSP File."sMap);
            
CloseHandle(hFile);
            return 
INVALID_HANDLE;
        }
        
LogMessage("Version: %i"iVersion);

        new 
iOffsetiLengthiVersionLumpiFourCC;

        new 
String:sLump[17];
        
ReadFileString(hFilesLumpsizeof(sLump), 16);
        
ReadLump(sLumpiOffsetiLengthiVersionLumpiFourCC);

        
LogMessage("Found Entity Lump: offset %i, length %i"iOffsetiLength);

        new 
Handle:hWFile OpenFile(sOutput"w");

        new 
iNum 0;
        for(new 
iPos 0iPos iLengthiPos += READSIZE) {
            
FileSeek(hFileiOffset iPosSEEK_SET);

            new 
String:sEntities[READSIZE++READSIZE];
            
ReadFileString(hFilesEntitiessizeof(sEntities), READSIZE);

            new 
iProcessed 0;
            new 
String:sReplacement[16];

            new 
iResult 0;
            while(
iResult != -1) {
                
Format(sReplacementsizeof(sReplacement), "\"%i\"\n{"iNum);

                
iResult ReplaceStringEx(sEntities[iProcessed], sizeof(sEntities), "{"sReplacement);
                
iProcessed += iResult;
                if(
iResult != -1)iNum++;
            }

            
WriteFileString(hWFilesEntitiesfalse);
        }

        
CloseHandle(hWFile);
        
CloseHandle(hFile);
    }

    new 
Handle:hKV CreateKeyValues("");
    
FileToKeyValues(hKVsOutput);

    return 
hKV;
}

stock ReadLump(const String:sLump[17], &iOffset, &iLength, &iVersion, &iFourCC) {
    
GET_LITTLE_ENDIAN_INT(0,iOffset,sLump)
    
GET_LITTLE_ENDIAN_INT(4,iLength,sLump)
    
GET_LITTLE_ENDIAN_INT(8,iVersion,sLump)
    
GET_LITTLE_ENDIAN_INT(12,iFourCC,sLump)

This allows you to do something like this (as an example):
PHP Code:
#pragma semicolon 1
#include <sourcemod>

public OnPluginStart() {
    
RegConsoleCmd("sm_getmapmode"Command_GetMapMode);
}

public 
Action:Command_GetMapMode(client,args) {
    if(
args != 1) {
        
ReplyToCommand(client"[Usage] sm_getmapmode <mapname>[.bsp]");
        return 
Plugin_Handled;
    } else {
        new 
String:sBuffer[255];
        
GetCmdArg(1sBuffersizeof(sBuffer));

        new 
Handle:hKVEntities ExtractEntities(sBuffer);
        if(
hKVEntities == INVALID_HANDLE) {
            
ReplyToCommand(client"Map not found or wrong format");
            return 
Plugin_Handled;
        }

        new 
bool:bHasRedCapturePoints false;
        while(
JumpToEntityByClassname(hKVEntities"team_control_point")) {
            new 
iTeam KvGetNum(hKVEntities"point_default_owner"0);
            if(
iTeam == 3)bHasRedCapturePoints true;
        }

        
CloseHandle(hKVEntities);

        
ReplyToCommand(client"%s is a %s mode map"sBufferbHasRedCapturePoints "Push" "Attack/Defense");
    }

    return 
Plugin_Handled;


resulting in:
PHP Code:
[SMPlugin tExtractEntitiesFromBSP reloaded successfully.
sm_textract cp_dustbowl
cp_dustbowl is a Attack
/Defense mode map
sm_textract cp_badlands
cp_badlands is a Push mode map
sm_textract qwerty
L 05
/22/2011 01:45:07: [tExtractEntitiesFromBSP.smxMap "qwerty.bsp" does not exists
Map not found 
or wrong format
sm_textract cp_granary
L 05
/22/2011 01:45:20: [tExtractEntitiesFromBSP.smxGrabbing entity list from cp_granary.bsp
L 05
/22/2011 01:45:20: [tExtractEntitiesFromBSP.smxBSP-FormatVBSP
L 05
/22/2011 01:45:20: [tExtractEntitiesFromBSP.smxVersion20
L 05
/22/2011 01:45:20: [tExtractEntitiesFromBSP.smxFound Entity Lumpoffset 31278296length 225412
cp_granary is a Push mode map 
btw, the entity list will only be grabbed if it has not been already. The ExtractEntities stock will create a <mapname>.bsp.entities.txt in your maps folder. This should be changed to a different and dedicated folder or sth.

more information about the bsp structure can be found here.
__________________
einmal mit profis arbeiten. einmal.

Last edited by Thrawn2; 05-21-2011 at 20:08.
Thrawn2 is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 21:53.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode