Skip to content

Instantly share code, notes, and snippets.

@MrDOS
Last active December 30, 2015 13:39
Show Gist options
  • Save MrDOS/7836657 to your computer and use it in GitHub Desktop.
Save MrDOS/7836657 to your computer and use it in GitHub Desktop.
Print out the Bukkit/Spigot “lastKnownName” tag if it exists.
/* "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