Last active
December 30, 2015 13:39
-
-
Save MrDOS/7836657 to your computer and use it in GitHub Desktop.
Print out the Bukkit/Spigot “lastKnownName” tag if it exists.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* "Where my people at?" | |
* | |
* NBTologist: search through an un-gzipped player.dat NBT file for the player's | |
* X/Y/Z coordinates. | |
*/ | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#define BUF_SIZE 128 | |
/* | |
* Read the given `source` to EOF and place its contents into `dest`. | |
* | |
* Arguments: source, the source file | |
* dest, the destination block of memory; expected to be null | |
* Returns: the number of bytes read (i.e., the useful size of dest) | |
*/ | |
size_t consume_file(FILE *source, char **dest) | |
{ | |
size_t allocated = 0; | |
size_t size = 0; | |
int c; | |
while ((c = fgetc(source)) != EOF) | |
{ | |
if (size == allocated) | |
{ | |
if (allocated == 0) allocated = BUF_SIZE; | |
else allocated *= 2; | |
*dest = realloc(*dest, allocated); | |
} | |
(*dest)[size++] = (char) c; | |
} | |
return size; | |
} | |
/* | |
* Find the first occurrence of a binary string in another binary string. | |
* | |
* Arguments: haystack, the string within which to search | |
* haystack_size, the size of the haystack | |
* needle, the search string | |
* needle_size, the size of the search string | |
* Returns: the first index of `needle` within `haystack` or -1 if not found | |
*/ | |
int memfind(const char *haystack, size_t haystack_size, const char *needle, size_t needle_size) | |
{ | |
for (int i = 0; i < haystack_size - needle_size; i++) | |
if (memcmp(haystack + i, needle, needle_size) == 0) | |
return i; | |
return -1; | |
} | |
/* | |
* Retrieve the big endian short integer at `pos` in `ptr`. | |
*/ | |
uint16_t short_at(char *ptr, size_t pos) | |
{ | |
return __bswap_16(*(uint16_t *) &ptr[pos]); | |
} | |
/* | |
* Retrieve the big endian double at `pos` in `ptr`. | |
*/ | |
double double_at(char *ptr, size_t pos) | |
{ | |
double val; | |
*((uint64_t *) &val) = __bswap_64(*(uint64_t *) &ptr[pos]); | |
return val; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
/* Read the (uncompressed) NBT data from stdin. */ | |
char *player = NULL; | |
size_t size = consume_file(stdin, &player); | |
/* Figure out where the "Pos" list is. */ | |
int pos = memfind(player, size, "Pos\x06\x00\x00\x00\x03", 8); | |
if (pos < 0) | |
return EXIT_FAILURE; | |
/* Print out the values. */ | |
printf("%f %f %f", | |
double_at(player, pos + 8), | |
double_at(player, pos + 8 + sizeof(uint64_t)), | |
double_at(player, pos + 8 + sizeof(uint64_t) + sizeof(uint64_t))); | |
/* See if the Bukkit "lastKnownName" tag exists. */ | |
int name_pos = memfind(player, size, "lastKnownName", 13); | |
if (name_pos >= 0) | |
{ | |
int name_length = short_at(player, name_pos + 13); | |
printf(" %.*s", name_length, player + name_pos + 15); | |
} | |
putchar('\n'); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment