Commit ab8cd4ec023b1eb75803ecd209d6039680cc1169

Authored by Imanol-Mikel Barba Sabariego
0 parents

Initial import. Incomplete version without getopt implementation

Showing 1 changed file with 253 additions and 0 deletions
mcpetbackup.c 0 → 100644
  1 +++ a/mcpetbackup.c
  1 +#include <stdio.h>
  2 +
  3 +#include "nbt.h"
  4 +#include "chunk.h"
  5 +
  6 +int savePetToFile(Tag* pet, const char* filename) {
  7 + void* petData;
  8 + size_t petDataLength = composeTag(*pet, &petData);
  9 +
  10 + int fd = open(filename,O_CREAT|O_WRONLY,0644);
  11 + if(fd == -1) {
  12 + fprintf(stderr,"Unable to open file to save pet: %s\n",strerror(errno));
  13 + free(petData);
  14 + return 1;
  15 + }
  16 + ssize_t nWritten = 0;
  17 + size_t totalWritten = 0;
  18 +
  19 + while((nWritten = write(fd,petData+totalWritten,petDataLength-totalWritten))) {
  20 + if(nWritten == -1) {
  21 + if(errno == EINTR) {
  22 + continue;
  23 + }
  24 + fprintf(stderr,"Unable to write pet data: %s\n",strerror(errno));
  25 + close(fd);
  26 + free(petData);
  27 + return 2;
  28 + }
  29 + totalWritten += nWritten;
  30 + }
  31 + close(fd);
  32 +
  33 + free(petData);
  34 + return 0;
  35 +}
  36 +
  37 +int loadPetFromFile(Tag* pet, const char* filename) {
  38 + int fd = open(filename,O_RDONLY);
  39 + if(fd == -1) {
  40 + fprintf(stderr,"Unable to open file to load pet: %s\n",strerror(errno));
  41 + return 1;
  42 + }
  43 +
  44 + struct stat sb;
  45 + if(stat(filename,&sb) == -1) {
  46 + fprintf(stderr,"Unable to stat() file to load pet: %s\n",strerror(errno));
  47 + close(fd);
  48 + return 2;
  49 + }
  50 + void* petData = calloc(sb.st_size,sizeof(uint8_t));
  51 +
  52 + ssize_t nRead = 0;
  53 + size_t totalRead = 0;
  54 +
  55 + while((nRead = read(fd,petData+totalRead,sb.st_size-totalRead))) {
  56 + if(nRead == -1) {
  57 + if(errno == EINTR) {
  58 + continue;
  59 + }
  60 + fprintf(stderr,"Unable to write pet data: %s\n",strerror(errno));
  61 + close(fd);
  62 + free(petData);
  63 + return 3;
  64 + }
  65 + totalRead += nRead;
  66 + }
  67 + close(fd);
  68 +
  69 + size_t pos = parseTag(petData,pet);
  70 + if(pos != sb.st_size) {
  71 + fprintf(stderr,"Error parsing pet data\n");
  72 + free(petData);
  73 + return 4;
  74 + }
  75 +
  76 + free(petData);
  77 + return 0;
  78 +}
  79 +
  80 +int getEntitiesTag(TagCompound* chunkRoot,Tag** entities) {
  81 + Tag* t;
  82 + int found = 0;
  83 + for(int i = 0; i < chunkRoot->numTags; ++i) {
  84 + t = &(chunkRoot->list[i]);
  85 + if(!strcmp(t->name,"Level")) {
  86 + found = 1;
  87 + break;
  88 + }
  89 + }
  90 + if(!found) {
  91 + fprintf(stderr,"Unable to locate Level tag\n");
  92 + return 1;
  93 + }
  94 + found = 0;
  95 +
  96 + TagCompound* level = t->payload;
  97 + for(int i = 0; i < level->numTags; ++i) {
  98 + t = &(level->list[i]);
  99 + if(!strcmp(t->name,"Entities")) {
  100 + found = 1;
  101 + *entities = t;
  102 + break;
  103 + }
  104 + }
  105 + if(!found) {
  106 + fprintf(stderr,"Unable to locate Entities tag\n");
  107 + return 2;
  108 + }
  109 + *entities = t;
  110 + return 0;
  111 +}
  112 +
  113 +int searchForPet(Tag entities, const char* petName, const char* ownerUUID, Tag** pet) {
  114 + if(petName == NULL && ownerUUID == NULL) {
  115 + fprintf(stderr,"At least petName or ownerUUID have to be non-NULL\n");
  116 + return -1;
  117 + }
  118 +
  119 + Tag* t;
  120 + TagList* entitiesList = entities.payload;
  121 + TagCompound* entity;
  122 + for(int i = 0; i < entitiesList->size; ++i) {
  123 + t = &(entitiesList->list[i]);
  124 + entity = t->payload;
  125 + for(int j = 0; j < entity->numTags; ++j) {
  126 + Tag* attr = &(entity->list[j]);
  127 + if(!strcmp(attr->name,"OwnerUUID") && ownerUUID != NULL) {
  128 + if(!strcmp(attr->payload,ownerUUID)) {
  129 + *pet = t;
  130 + return 0;
  131 + }
  132 + } else if(!strcmp(attr->name,"CustomName") && petName != NULL) {
  133 + if(!strcmp(attr->payload,petName)) {
  134 + *pet = t;
  135 + return 0;
  136 + }
  137 + }
  138 + }
  139 + }
  140 + return 1;
  141 +}
  142 +
  143 +ssize_t insertPetIntoChunk(void** chunkData, Tag chunkRoot, Tag* entities, Tag pet, double x, double y, double z) {
  144 + TagList* entitiesList = (TagList*)entities->payload;
  145 + if(entitiesList->type == TAG_END) {
  146 + // Entities was an empty list. Generating it
  147 + entitiesList->type = TAG_COMPOUND;
  148 + entitiesList->size = 0;
  149 + entitiesList->list = calloc(1,sizeof(uint8_t));
  150 + }
  151 + void* newptr = reallocarray(entitiesList->list,++entitiesList->size,sizeof(Tag));
  152 + if(newptr == NULL) {
  153 + fprintf(stderr,"Unable to realloc an additional entity on the entities list\n");
  154 + return -1;
  155 + }
  156 + entitiesList->list = newptr;
  157 + Tag* newPet = &entitiesList->list[(entitiesList->size) - 1];
  158 +
  159 + void* rawPetData;
  160 + size_t rawPetDataLength = composeTag(pet,&rawPetData);
  161 + size_t parsePos = parseTag(rawPetData,newPet);
  162 + if(parsePos != rawPetDataLength) {
  163 + fprintf(stderr,"Error while duplicating pet. New pet data does not match original\n");
  164 + free(rawPetData);
  165 + return -2;
  166 + }
  167 + free(rawPetData);
  168 +
  169 + void* newChunkData;
  170 + size_t chunkDataLength = composeTag(chunkRoot, &newChunkData);
  171 + newptr = realloc(*chunkData,chunkDataLength);
  172 + if(newptr == NULL) {
  173 + fprintf(stderr,"Unable to realloc chunkData to fit new data\n");
  174 + free(newChunkData);
  175 + return -4;
  176 + }
  177 + *chunkData = newptr;
  178 + memcpy(*chunkData,newChunkData,chunkDataLength);
  179 + free(newChunkData);
  180 +
  181 + return chunkDataLength;
  182 +}
  183 +
  184 +int main(int argc, char** argv) {
  185 + // TODO argv
  186 + // --regiondata ./industrial/world/region --save Iris.mcdata --name Iris
  187 + // --regiondata ./industrial/world/region --save Iris.mcdata --owner 32812f90-17ec-4f5a-8b7e-e500f17b1ba5
  188 + // --regiondata ./industrial/world/region --load Iris.mcdata
  189 +
  190 + const char* regionFolder = "./industrial/world/region";
  191 + const char* petName = "Iris";
  192 + int save = 0;
  193 + const char* outputFile = "Iris.mcdata";
  194 + const char* inputFile = "Iris.mcdata";
  195 +
  196 + void *chunkData;
  197 + ChunkID chunk = translateCoordsToChunk(800, 200, 3041);
  198 + ssize_t chunkLen = loadChunk(regionFolder, chunk, &chunkData);
  199 + if(chunkLen <= 0) {
  200 + return chunkLen;
  201 + }
  202 +
  203 + Tag t;
  204 + unsigned int pos = parseTag(chunkData,&t);
  205 + if(pos != chunkLen) {
  206 + fprintf(stderr, "Didn't reach end of NBT file\n");
  207 + free(chunkData);
  208 + return 1;
  209 + }
  210 +
  211 + Tag* entities;
  212 + if(getEntitiesTag((TagCompound*)t.payload,&entities)) {
  213 + fprintf(stderr, "Unable to find Entities tag\n");
  214 + free(chunkData);
  215 + return 2;
  216 + }
  217 + if(save) {
  218 + Tag* pet;
  219 + if(searchForPet(*entities,petName,NULL,&pet)) {
  220 + fprintf(stderr, "Unable to find pet named %s\n",petName);
  221 + free(chunkData);
  222 + return 3;
  223 + }
  224 + if(savePetToFile(pet,outputFile)) {
  225 + fprintf(stderr, "Unable to save pet to file: %s\n",outputFile);
  226 + free(chunkData);
  227 + return 4;
  228 + }
  229 + } else {
  230 + Tag pet;
  231 + if(loadPetFromFile(&pet,inputFile)) {
  232 + fprintf(stderr, "Unable to load pet from file: %s\n",inputFile);
  233 + free(chunkData);
  234 + return 5;
  235 + }
  236 + chunkLen = insertPetIntoChunk(&chunkData,t,entities,pet,801,200,3040);
  237 + if(chunkLen <= 0) {
  238 + fprintf(stderr, "Unable to insert pet into chunk\n");
  239 + free(chunkData);
  240 + return 6;
  241 + }
  242 + destroyTag(&pet);
  243 + if(overwriteChunk(regionFolder, chunk, chunkData, chunkLen)) {
  244 + fprintf(stderr, "Unable to write new chunk\n");
  245 + free(chunkData);
  246 + return 7;
  247 + }
  248 + }
  249 +
  250 + destroyTag(&t);
  251 + free(chunkData);
  252 + return 0;
  253 +}
0 254 \ No newline at end of file
... ...