mcplayerstat.c 3.41 KB
#include <stdio.h>

#include "nbt.h"

void printInventory(TagList *inv) {
    for(int j = 0; j < inv->size; ++j) {
        TagCompound item = *(TagCompound*)inv->list[j].payload;
        uint8_t slot = 0;
        char* id;
        uint8_t count = 0;
        for(int k = 0; k < item.numTags; ++k) {
            Tag attr = item.list[k];
            if(!strncmp(attr.name,"Slot",attr.nameLength)) {
                slot = *((uint8_t*)attr.payload);
            } else if(!strncmp(attr.name,"id",attr.nameLength)) {
                id = calloc(attr.payloadLength+1,sizeof(char));
                memcpy(id,(char*)attr.payload,attr.payloadLength);
            } else if(!strncmp(attr.name,"Count",attr.nameLength)) {
                count = *((uint8_t*)attr.payload);
            }
        }
        printf("\t- [%u] %ux %s\n",slot,count,id);
        free(id);
    }
}

/*
 * int playerGameType
 * int XpLevel
 * list(compound) Inventory
 * list(compound) EnderItems
 * list(float) Pos
 */
int parseMCPlayerFile(const char* filename) {
    unsigned int pos = 0;
    void* data;

    ssize_t dblen = loadDB(filename, &data);
    if(dblen < 0) {
        switch(dblen) {
            case ACCESS_ERROR:
                fprintf(stderr,"Error calling access() on database %s\n",filename);
                break;
            case OPEN_ERROR:
                fprintf(stderr,"Error opening database %s\n",filename);
                break;
            case READ_ERROR:
                fprintf(stderr,"Error reading database %s\n",filename);
                break;
        }
        return dblen;
    }
    Tag t;
    pos = parseTag((data + pos),&t);
    if(pos < 0) {
        fprintf(stderr,"Error parsing root tag: code %d\n",pos);
        return pos;
    } else if(pos != dblen) {
        fprintf(stderr,"Didn't reach end of NBT file\n");
        return 2;
    }

    TagCompound root = *(TagCompound*) t.payload;
    for(int i = 0; i < root.numTags; ++i) {
        Tag node = root.list[i];
        if(node.type == TAG_INT) {
            if(!strncmp(node.name,"playerGameType",node.nameLength)) {
                int playerGameType = *((uint32_t*)node.payload);
                printf("playerGameType: %s\n",(playerGameType == 0 ? "Survival" : (playerGameType == 1 ? "Creative" : (playerGameType == 2 ? "Adventure" : (playerGameType == 3 ? "Spectator" : "UNKNOWN")))));
            } else if (!strncmp(node.name,"XpLevel",node.nameLength)) {
                int xpLevel = *((uint32_t*)node.payload);
                printf("XpLevel: %u\n",xpLevel);
            }
        } else if(node.type == TAG_LIST) {
            TagList* l = (TagList*)node.payload;
            if(!strncmp(node.name,"Inventory",node.nameLength)) {
                printf("Inventory:\n");
                printInventory(l);
            } else if (!strncmp(node.name,"EnderItems",node.nameLength)) {
                printf("Ender Inventory:\n");
                printInventory(l);
            } else if (!strncmp(node.name,"Pos",node.nameLength)) {
                double x = (*(double*)l->list[0].payload);
                double y = (*(double*)l->list[1].payload);
                double z = (*(double*)l->list[2].payload);
                printf("Pos: (x: %f,y: %f,z: %f)\n",x,y,z);
            }
        }
    }

    destroyTag(&t);
    free(data);
    return 0;
}

int main(int argc, char** argv) {
    if(argc != 2) {
        fprintf(stderr,"No file specified\n");
        return 2;
    }

    return parseMCPlayerFile(argv[1]);
}