diff --git a/common.mk b/common.mk index ee90431..06a7e60 100644 --- a/common.mk +++ b/common.mk @@ -49,7 +49,7 @@ _OBJS += quadtree.o _OBJS += shotgunBlob.o shotgunDroid.o sound.o spreadGunBlob.o spreadGunDroid.o sprites.o structures.o _OBJS += tankCommander.o tankTrack.o teeka.o teleporter.o text.o textures.o title.o triggers.o _OBJS += unit.o util.o -_OBJS += weapons.o weaponPickup.o widgets.o world.o worldLoader.o +_OBJS += weapons.o weaponPickup.o widgets.o world.o worldLoader.o worldSaver.o OBJS = $(patsubst %,$(OUT)/%,$(_OBJS)) diff --git a/src/entities/misc/infoPoint.c b/src/entities/misc/infoPoint.c index 0e0ecca..98715e0 100644 --- a/src/entities/misc/infoPoint.c +++ b/src/entities/misc/infoPoint.c @@ -92,5 +92,5 @@ static void save(cJSON *root) s = (Structure*)self; cJSON_AddStringToObject(root, "type", "InfoPoint"); - cJSON_AddStringToObject(root, "message", s->name); + cJSON_AddStringToObject(root, "message", s->message); } diff --git a/src/entities/structures/door.c b/src/entities/structures/door.c index 1f8dd96..f74d835 100644 --- a/src/entities/structures/door.c +++ b/src/entities/structures/door.c @@ -311,7 +311,7 @@ static void save(cJSON *root) s = (Structure*)self; - cJSON_AddStringToObject(root, "type", "Door"); + cJSON_AddStringToObject(root, "type", s->sprite[0]->name); cJSON_AddNumberToObject(root, "isLocked", s->isLocked); cJSON_AddNumberToObject(root, "tx", s->tx); cJSON_AddNumberToObject(root, "ty", s->ty); diff --git a/src/entities/structures/horizontalDoor.c b/src/entities/structures/horizontalDoor.c index 796182e..d297b77 100644 --- a/src/entities/structures/horizontalDoor.c +++ b/src/entities/structures/horizontalDoor.c @@ -28,7 +28,7 @@ Entity *initHorizontalDoor(void) s->type = ET_DOOR; - s->sprite[0] = s->sprite[1] = s->sprite[2] = getSprite("HorizonalDoor"); + s->sprite[0] = s->sprite[1] = s->sprite[2] = getSprite("HorizontalDoor"); return (Entity*)s; } diff --git a/src/entities/structures/pushBlock.c b/src/entities/structures/pushBlock.c index 3180492..3f64043 100644 --- a/src/entities/structures/pushBlock.c +++ b/src/entities/structures/pushBlock.c @@ -100,7 +100,7 @@ static void save(cJSON *root) s = (Structure*)self; - cJSON_AddStringToObject(root, "type", "PressurePlate"); + cJSON_AddStringToObject(root, "type", "PushBlock"); cJSON_AddStringToObject(root, "spriteName", s->spriteName); cJSON_AddNumberToObject(root, "startX", s->startX); cJSON_AddNumberToObject(root, "startY", s->startY); diff --git a/src/test/atlasTest.c b/src/test/atlasTest.c index 4cfae11..a51b957 100644 --- a/src/test/atlasTest.c +++ b/src/test/atlasTest.c @@ -30,7 +30,7 @@ void initAtlasTest(void) initHub(); - loadWorld("data/maps/beachApproach.json"); + loadWorld("beachApproach"); initWorld(); diff --git a/src/test/atlasTest.h b/src/test/atlasTest.h index 102b583..9045be1 100644 --- a/src/test/atlasTest.h +++ b/src/test/atlasTest.h @@ -25,6 +25,6 @@ extern void initMap(void); extern void initHub(void); extern void initGame(void); extern void initEntities(void); -extern void loadWorld(char *filename); +extern void loadWorld(char *id); extern Dev dev; diff --git a/src/world/player.c b/src/world/player.c index ec3a6dc..39979e2 100644 --- a/src/world/player.c +++ b/src/world/player.c @@ -20,17 +20,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "player.h" -static void doCheatControls(void); +static void doDebugControls(void); void doPlayer(void) { if (dev.debug) { - doCheatControls(); + doDebugControls(); } } -static void doCheatControls(void) +static void doDebugControls(void) { if (app.keyboard[SDL_SCANCODE_1]) { @@ -56,4 +56,10 @@ static void doCheatControls(void) { world.bob->weaponType = WPN_GRENADES; } + + if (app.keyboard[SDL_SCANCODE_0]) + { + saveWorld(); + app.keyboard[SDL_SCANCODE_0] = 0; + } } diff --git a/src/world/player.h b/src/world/player.h index d85d283..d537011 100644 --- a/src/world/player.h +++ b/src/world/player.h @@ -20,6 +20,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../common.h" +extern void saveWorld(void); + extern App app; extern Dev dev; extern World world; diff --git a/src/world/worldLoader.c b/src/world/worldLoader.c index 816a801..e752f5d 100644 --- a/src/world/worldLoader.c +++ b/src/world/worldLoader.c @@ -26,10 +26,10 @@ static void loadBob(cJSON *root); static void loadEntities(cJSON *root); static void loadObjectives(cJSON *root); -void loadWorld(char *filename) +void loadWorld(char *id) { cJSON *root; - char *text; + char *text, filename[MAX_FILENAME_LENGTH]; memset(&world, 0, sizeof(World)); @@ -38,7 +38,18 @@ void loadWorld(char *filename) world.objectiveTail = &world.objectiveHead; world.particleTail = &world.particleHead; - text = readFile(filename); + sprintf(filename, "%s/%s.json", app.saveDir, id); + + if (fileExists(filename)) + { + text = readFile(filename); + } + else + { + sprintf(filename, "data/maps/%s.json", id); + + text = readFile(filename); + } root = cJSON_Parse(text); diff --git a/src/world/worldLoader.h b/src/world/worldLoader.h index 89a2ff7..e23a9bd 100644 --- a/src/world/worldLoader.h +++ b/src/world/worldLoader.h @@ -22,9 +22,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../json/cJSON.h" extern char *readFile(const char *filename); -extern void loadSprite(cJSON *root); extern Entity *createEntity(char *typeStr); +extern int fileExists(const char *filename); +extern App app; extern Dev dev; extern Entity *self; extern World world; diff --git a/src/world/worldSaver.c b/src/world/worldSaver.c new file mode 100644 index 0000000..6c1b60f --- /dev/null +++ b/src/world/worldSaver.c @@ -0,0 +1,173 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "worldSaver.h" + +static void saveEnemyTypes(cJSON *root); +static void saveTriggers(cJSON *root); +static void saveBob(cJSON *root); +static void saveEntities(cJSON *root); +static void saveObjectives(cJSON *root); + +void saveWorld(void) +{ + cJSON *root; + char filename[MAX_FILENAME_LENGTH], *out; + + sprintf(filename, "%s/%s.json", app.saveDir, world.id); + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Saving world to '%s' ...", filename); + + root = cJSON_CreateObject(); + cJSON_AddStringToObject(root, "id", world.id); + cJSON_AddStringToObject(root, "name", world.name); + cJSON_AddNumberToObject(root, "minEnemySpawnTime", world.minEnemySpawnTime); + cJSON_AddNumberToObject(root, "maxEnemySpawnTime", world.maxEnemySpawnTime); + cJSON_AddStringToObject(root, "music", world.music); + cJSON_AddStringToObject(root, "tileset", world.tileset); + cJSON_AddStringToObject(root, "background", world.background); + cJSON_AddNumberToObject(root, "entityCounter", world.entityCounter); + + saveEnemyTypes(root); + + saveTriggers(root); + + saveBob(root); + + saveEntities(root); + + saveObjectives(root); + + out = cJSON_Print(root); + + if (!writeFile(filename, out)) + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "Failed to save world"); + } + + cJSON_Delete(root); + free(out); +} + +static void saveEnemyTypes(cJSON *root) +{ + char enemyTypes[MAX_DESCRIPTION_LENGTH]; + int i; + + strcpy(enemyTypes, ""); + + for (i = 0 ; i < world.numEnemyTypes ; i++) + { + if (i > 0) + { + strcat(enemyTypes, "|"); + } + + strcat(enemyTypes, world.enemyTypes[i]); + } + + cJSON_AddStringToObject(root, "enemyTypes", enemyTypes); +} + +static void saveTriggers(cJSON *root) +{ + cJSON *triggersJSON, *triggerJSON; + Trigger *t; + + triggersJSON = cJSON_CreateArray(); + + for (t = world.triggerHead.next ; t != NULL ; t = t->next) + { + triggerJSON = cJSON_CreateObject(); + + cJSON_AddStringToObject(triggerJSON, "name", t->name); + cJSON_AddStringToObject(triggerJSON, "targetNames", t->targetNames); + cJSON_AddStringToObject(triggerJSON, "message", t->message); + cJSON_AddNumberToObject(triggerJSON, "x", t->x); + cJSON_AddNumberToObject(triggerJSON, "y", t->y); + cJSON_AddNumberToObject(triggerJSON, "w", t->w); + cJSON_AddNumberToObject(triggerJSON, "h", t->h); + + cJSON_AddItemToArray(triggersJSON, triggerJSON); + } + + cJSON_AddItemToObject(root, "triggers", triggersJSON); +} + +static void saveBob(cJSON *root) +{ + cJSON *bobJSON; + + bobJSON = cJSON_CreateObject(); + + world.bob->save(bobJSON); + + cJSON_AddItemToObject(root, "bob", bobJSON); +} + +static void saveEntities(cJSON *root) +{ + cJSON *entitiesJSON, *entityJSON; + + entitiesJSON = cJSON_CreateArray(); + + for (self = world.entityHead.next ; self != NULL ; self = self->next) + { + if (self->type != ET_NONE && self->type != ET_BOB && self->health > 0 && self->alive == ALIVE_ALIVE) + { + entityJSON = cJSON_CreateObject(); + + cJSON_AddStringToObject(entityJSON, "name", self->name); + cJSON_AddNumberToObject(entityJSON, "x", (int)self->x); + cJSON_AddNumberToObject(entityJSON, "y", (int)self->y); + + self->save(entityJSON); + + cJSON_AddItemToArray(entitiesJSON, entityJSON); + } + } + + cJSON_AddItemToObject(root, "entities", entitiesJSON); +} + +static void saveObjectives(cJSON *root) +{ + Objective *o; + cJSON *objectivesJSON, *objectiveJSON; + + objectivesJSON = cJSON_CreateArray(); + + for (o = world.objectiveHead.next ; o != NULL ; o = o->next) + { + objectiveJSON = cJSON_CreateObject(); + + cJSON_AddStringToObject(objectiveJSON, "id", o->id); + cJSON_AddStringToObject(objectiveJSON, "targetName", o->targetName); + cJSON_AddStringToObject(objectiveJSON, "description", o->description); + cJSON_AddNumberToObject(objectiveJSON, "totalValue", o->totalValue); + cJSON_AddNumberToObject(objectiveJSON, "targetValue", o->targetValue); + cJSON_AddNumberToObject(objectiveJSON, "currentValue", o->currentValue); + cJSON_AddNumberToObject(objectiveJSON, "required", o->required); + + cJSON_AddItemToArray(objectivesJSON, objectiveJSON); + } + + cJSON_AddItemToObject(root, "objectives", objectivesJSON); +} diff --git a/src/world/worldSaver.h b/src/world/worldSaver.h new file mode 100644 index 0000000..9c4203f --- /dev/null +++ b/src/world/worldSaver.h @@ -0,0 +1,28 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" +#include "../json/cJSON.h" + +extern int writeFile(const char *filename, const char *data); + +extern App app; +extern Entity *self; +extern World world;