Commit 1e868e43415a97f5d24ed6997028260b52adde17

Authored by Imanol-Mikel Barba Sabariego
1 parent 6a6d7496

Fully implemented all options. Fixed several memory errors

Showing 1 changed file with 161 additions and 56 deletions
mcpetbackup.c
1 1 #include <stdio.h>
2 2 #include <getopt.h>
  3 +#include <dirent.h>
3 4  
4 5 #include "nbt.h"
5 6 #include "chunk.h"
... ... @@ -7,19 +8,29 @@
7 8 enum paramIndex
8 9 {
9 10 UNKNOWN = 0,
  11 + HELP,
10 12 REGION,
11 13 SAVE,
12 14 LOAD,
13 15 NAME,
14   - OWNER
  16 + OWNER,
  17 + COORDS
15 18 };
16 19  
  20 +typedef struct Coords {
  21 + int x;
  22 + int y;
  23 + int z;
  24 +} Coords;
  25 +
17 26 static struct option longopts[] = {
  27 + { "help", no_argument, NULL, HELP },
18 28 { "regiondata", required_argument, NULL, REGION },
19 29 { "save", required_argument, NULL, SAVE },
20 30 { "load", required_argument, NULL, LOAD },
21 31 { "name", required_argument, NULL, NAME },
22 32 { "owner", required_argument, NULL, OWNER },
  33 + { "coords", required_argument, NULL, COORDS },
23 34 { NULL, 0, NULL, UNKNOWN }
24 35 };
25 36  
... ... @@ -102,7 +113,7 @@ int getEntitiesTag(TagCompound* chunkRoot,Tag** entities) {
102 113 int found = 0;
103 114 for(int i = 0; i < chunkRoot->numTags; ++i) {
104 115 t = &(chunkRoot->list[i]);
105   - if(!strcmp(t->name,"Level")) {
  116 + if(!strncmp(t->name,"Level",t->nameLength)) {
106 117 found = 1;
107 118 break;
108 119 }
... ... @@ -116,7 +127,7 @@ int getEntitiesTag(TagCompound* chunkRoot,Tag** entities) {
116 127 TagCompound* level = t->payload;
117 128 for(int i = 0; i < level->numTags; ++i) {
118 129 t = &(level->list[i]);
119   - if(!strcmp(t->name,"Entities")) {
  130 + if(!strncmp(t->name,"Entities",t->nameLength)) {
120 131 found = 1;
121 132 *entities = t;
122 133 break;
... ... @@ -144,13 +155,13 @@ int searchForPet(Tag entities, const char* petName, const char* ownerUUID, Tag**
144 155 entity = t->payload;
145 156 for(int j = 0; j < entity->numTags; ++j) {
146 157 Tag* attr = &(entity->list[j]);
147   - if(!strcmp(attr->name,"OwnerUUID") && ownerUUID != NULL) {
148   - if(!strcmp(attr->payload,ownerUUID)) {
  158 + if(!strncmp(attr->name,"OwnerUUID",attr->nameLength) && ownerUUID != NULL) {
  159 + if(!strncmp(attr->payload,ownerUUID,attr->payloadLength)) {
149 160 *pet = t;
150 161 return 0;
151 162 }
152   - } else if(!strcmp(attr->name,"CustomName") && petName != NULL) {
153   - if(!strcmp(attr->payload,petName)) {
  163 + } else if(!strncmp(attr->name,"CustomName",attr->nameLength) && petName != NULL) {
  164 + if(!strncmp(attr->payload,petName,attr->payloadLength)) {
154 165 *pet = t;
155 166 return 0;
156 167 }
... ... @@ -201,10 +212,26 @@ ssize_t insertPetIntoChunk(void** chunkData, Tag chunkRoot, Tag* entities, Tag p
201 212 return chunkDataLength;
202 213 }
203 214  
  215 +Coords getPetCoords(TagCompound* pet) {
  216 + Coords petCoords;
  217 + for(int i = 0; i < pet->numTags; ++i) {
  218 + Tag* attr = &pet->list[i];
  219 + if(!strncmp(attr->name,"Pos",attr->nameLength)) {
  220 + TagList* pos = attr->payload;
  221 + petCoords.x = (int)*((double*)pos->list[0].payload);
  222 + petCoords.y = (int)*((double*)pos->list[1].payload);
  223 + petCoords.z = (int)*((double*)pos->list[2].payload);
  224 + }
  225 + }
  226 + return petCoords;
  227 +}
  228 +
204 229 void printHelp() {
  230 + fprintf(stderr,"--regiondata ./industrial/world/region --name Iris\n");
  231 + fprintf(stderr,"--regiondata ./industrial/world/region --owner 32812f90-17ec-4f5a-8b7e-e500f17b1ba5\n");
205 232 fprintf(stderr,"--regiondata ./industrial/world/region --save Iris.mcdata --name Iris\n");
206 233 fprintf(stderr,"--regiondata ./industrial/world/region --save Iris.mcdata --owner 32812f90-17ec-4f5a-8b7e-e500f17b1ba5\n");
207   - fprintf(stderr,"--regiondata ./industrial/world/region --load Iris.mcdata\n");
  234 + fprintf(stderr,"--regiondata ./industrial/world/region --load Iris.mcdata --coords 801,200,3040\n");
208 235 }
209 236  
210 237 int main(int argc, char** argv) {
... ... @@ -212,7 +239,9 @@ int main(int argc, char** argv) {
212 239 const char* file = NULL;
213 240 const char* petName = NULL;
214 241 const char* ownerUUID = NULL;
  242 + const char* coords = NULL;
215 243 int save = 0;
  244 + int load = 0;
216 245  
217 246 int longIndex = UNKNOWN;
218 247 int c;
... ... @@ -224,17 +253,15 @@ int main(int argc, char** argv) {
224 253 return 0;
225 254 }
226 255  
227   - while ((c = getopt_long(argc, argv, "r:s:l:n:o:h", longopts, &longIndex)) != -1)
  256 + while ((c = getopt_long(argc, argv, "r:s:l:n:o:c:h", longopts, &longIndex)) != -1)
228 257 {
229   - if(c == 'h') {
230   - printHelp();
231   - return 0;
232   - }
233   - else if(c == REGION) {regionFolder = optarg;}
234   - else if(c == SAVE) {save = 1;file = optarg;}
235   - else if(c == LOAD) {file = optarg;}
236   - else if(c == NAME) {petName = optarg;}
237   - else if(c == OWNER) {ownerUUID = optarg;}
  258 + if(c == HELP || c == 'h') {printHelp();return 0;}
  259 + else if(c == REGION || c == 'r') {regionFolder = optarg;}
  260 + else if(c == SAVE || c == 's') {save = 1; file = optarg;}
  261 + else if(c == LOAD || c == 'l') {load = 1; file = optarg;}
  262 + else if(c == NAME || c == 'n') {petName = optarg;}
  263 + else if(c == OWNER || c == 'o') {ownerUUID = optarg;}
  264 + else if(c == COORDS || c == 'c') {coords = optarg;}
238 265 else {
239 266 fprintf(stderr,"Unrecognised argument: %s\n",optarg);
240 267 printHelp();
... ... @@ -251,75 +278,153 @@ int main(int argc, char** argv) {
251 278 fprintf(stderr,"Region path not specified (--regionpath PATH_TO_REGION_FOLDER)\n");
252 279 printHelp();
253 280 return 2;
254   - } else if(save && petName == NULL && ownerUUID == NULL) {
  281 + } else if(!load && (petName == NULL && ownerUUID == NULL)) {
255 282 fprintf(stderr,"OwnerUUID and petName were unspecified (--owner UUID, --name PET_NAME)\n");
256 283 printHelp();
257 284 return 3;
258   - } else if(!save && (petName != NULL || ownerUUID != NULL)) {
259   - fprintf(stderr,"OwnerUUID and petName were unspecified (--owner UUID, --name PET_NAME)\n");
  285 + } else if(load && (petName != NULL || ownerUUID != NULL)) {
  286 + fprintf(stderr,"OwnerUUID and petName options don't apply when loading a pet\n");
260 287 printHelp();
261 288 return 3;
262   - } else if(file == NULL) {
263   - fprintf(stderr,"Neither saving or loading a pet was requested (--save PATH_TO_FILE, --load PATH_TO_FILE)\n");
  289 + } else if(save && coords == NULL) {
  290 + fprintf(stderr,"Coordinates were not specified\n");
264 291 printHelp();
265 292 return 4;
266   - }
  293 + }
267 294  
268   - void *chunkData;
269   - ChunkID chunk = translateCoordsToChunk(800, 200, 3041);
270   - ssize_t chunkLen = loadChunk(regionFolder, chunk, &chunkData);
271   - if(chunkLen <= 0) {
272   - return chunkLen;
273   - }
  295 + if(!load) {
  296 + DIR *dirp;
  297 + struct dirent *dp;
274 298  
275   - Tag t;
276   - unsigned int pos = parseTag(chunkData,&t);
277   - if(pos != chunkLen) {
278   - fprintf(stderr, "Didn't reach end of NBT file\n");
279   - free(chunkData);
280   - return 5;
281   - }
  299 + if((dirp = opendir(regionFolder)) == NULL) {
  300 + fprintf(stderr,"Unable to open region folder '%s'\n",regionFolder);
  301 + return 1;
  302 + }
282 303  
283   - Tag* entities;
284   - if(getEntitiesTag((TagCompound*)t.payload,&entities)) {
285   - fprintf(stderr, "Unable to find Entities tag\n");
286   - free(chunkData);
287   - return 6;
288   - }
289   - if(save) {
290   - Tag* pet;
291   - if(searchForPet(*entities,petName,ownerUUID,&pet)) {
292   - fprintf(stderr, "Unable to find pet named %s\n",petName);
  304 + do {
  305 + if((dp = readdir(dirp)) != NULL) {
  306 + const char* regionFile = dp->d_name;
  307 + RegionID region;
  308 +
  309 + if(sscanf(regionFile,"r.%d.%d.mca",&region.x,&region.z) != 2) {
  310 + // WTF? Ignore this file
  311 + continue;
  312 + }
  313 + for(int i = 0; i < CHUNKS_PER_REGION; ++i) {
  314 + for(int j = 0; j < CHUNKS_PER_REGION; ++j) {
  315 + ChunkID chunk;
  316 + chunk.x = i + region.x * CHUNKS_PER_REGION;
  317 + chunk.z = j + region.z * CHUNKS_PER_REGION;
  318 +
  319 + void* chunkData;
  320 + printf("Looking in chunk (%d,%d): X (%d -> %d), Z (%d -> %d)\n",
  321 + chunk.x,
  322 + chunk.z,
  323 + chunk.x * BLOCKS_PER_CHUNK,
  324 + (chunk.x + 1) * BLOCKS_PER_CHUNK,
  325 + chunk.z * BLOCKS_PER_CHUNK,
  326 + (chunk.z + 1) * BLOCKS_PER_CHUNK
  327 + );
  328 + ssize_t chunkLen = loadChunk(regionFolder, chunk, &chunkData);
  329 + if(chunkLen < 0) {
  330 + fprintf(stderr, "Unable to load chunk\n");
  331 + return 5;
  332 + } else if(chunkLen != 0) {
  333 + Tag t;
  334 + unsigned int pos = parseTag(chunkData,&t);
  335 + if(pos != chunkLen) {
  336 + fprintf(stderr, "Didn't reach end of NBT file\n");
  337 + free(chunkData);
  338 + return 5;
  339 + }
  340 +
  341 + Tag* entities;
  342 + if(getEntitiesTag((TagCompound*)t.payload,&entities)) {
  343 + fprintf(stderr, "Unable to find Entities tag\n");
  344 + free(chunkData);
  345 + destroyTag(&t);
  346 + return 6;
  347 + }
  348 + Tag* pet;
  349 + if(searchForPet(*entities,petName,ownerUUID,&pet) == 0) {
  350 + Coords petPosition = getPetCoords(pet->payload);
  351 + printf("Found pet! @ (%d,%d,%d)\n",petPosition.x,petPosition.y,petPosition.z);
  352 + if(save) {
  353 + if(savePetToFile(pet,file)) {
  354 + fprintf(stderr, "Unable to save pet to file: %s\n",file);
  355 + free(chunkData);
  356 + closedir(dirp);
  357 + return 8;
  358 + }
  359 + }
  360 + destroyTag(&t);
  361 + closedir(dirp);
  362 + free(chunkData);
  363 + return 0;
  364 + }
  365 + destroyTag(&t);
  366 + free(chunkData);
  367 + }
  368 + }
  369 + }
  370 + }
  371 + } while (dp != NULL);
  372 + printf("Unable to find pet in this world :(\n");
  373 + closedir(dirp);
  374 + return 1;
  375 + } else {
  376 + Coords location;
  377 + if(sscanf(coords,"%d,%d,%d",&location.x,&location.y,&location.z) != 3) {
  378 + fprintf(stderr, "Unable to parse coordinates, please specify coordinates correctly (--coords X,Y,Z)\n");
  379 + return 5;
  380 + }
  381 +
  382 + void *chunkData;
  383 + ChunkID chunk = translateCoordsToChunk(location.x, location.y, location.z);
  384 + ssize_t chunkLen = loadChunk(regionFolder, chunk, &chunkData);
  385 + if(chunkLen <= 0) {
  386 + fprintf(stderr, "Unable to load chunk\n");
  387 + return 5;
  388 + }
  389 +
  390 + Tag t;
  391 + unsigned int pos = parseTag(chunkData,&t);
  392 + if(pos != chunkLen) {
  393 + fprintf(stderr, "Didn't reach end of NBT file\n");
293 394 free(chunkData);
294   - return 7;
  395 + return 5;
295 396 }
296   - if(savePetToFile(pet,file)) {
297   - fprintf(stderr, "Unable to save pet to file: %s\n",file);
  397 +
  398 + Tag* entities;
  399 + if(getEntitiesTag((TagCompound*)t.payload,&entities)) {
  400 + fprintf(stderr, "Unable to find Entities tag\n");
298 401 free(chunkData);
299   - return 8;
  402 + destroyTag(&t);
  403 + return 6;
300 404 }
301   - } else {
302 405 Tag pet;
303 406 if(loadPetFromFile(&pet,file)) {
304 407 fprintf(stderr, "Unable to load pet from file: %s\n",file);
305 408 free(chunkData);
  409 + destroyTag(&t);
306 410 return 9;
307 411 }
308   - chunkLen = insertPetIntoChunk(&chunkData,t,entities,pet,801,200,3040);
  412 + chunkLen = insertPetIntoChunk(&chunkData,t,entities,pet,location.x,location.y,location.z);
309 413 if(chunkLen <= 0) {
310 414 fprintf(stderr, "Unable to insert pet into chunk\n");
311 415 free(chunkData);
  416 + destroyTag(&t);
312 417 return 10;
313 418 }
314 419 destroyTag(&pet);
315 420 if(overwriteChunk(regionFolder, chunk, chunkData, chunkLen)) {
316 421 fprintf(stderr, "Unable to write new chunk\n");
317 422 free(chunkData);
  423 + destroyTag(&t);
318 424 return 11;
319 425 }
  426 + destroyTag(&t);
  427 + free(chunkData);
320 428 }
321   -
322   - destroyTag(&t);
323   - free(chunkData);
324 429 return 0;
325 430 }
326 431 \ No newline at end of file
... ...