// Copyright (c) 2023 Alex Diener. All rights reserved. #include "PROJECT_NAME/FileUtilities.h" #include "PROJECT_NAME/GameData.h" #include "PROJECT_NAME/Globals.h" #include "MetadataKeys.h" #include #include #include #define TILE_ID_ROOM_ENTRANCE 3 GameData * GameData_create(void) { extern const char EMBEDDATA_tilemaps_tilemap_bundle[]; extern unsigned int EMBEDSIZE_tilemaps_tilemap_bundle; FileBundle * tileMapBundle = FileBundle_loadData(EMBEDDATA_tilemaps_tilemap_bundle, EMBEDSIZE_tilemaps_tilemap_bundle); unsigned int tileMapCount = tileMapBundle->entryCount; TileMapEditData * tileMaps[tileMapCount]; for (unsigned int entryIndex = 0; entryIndex < tileMapCount; entryIndex++) { uint32_t entrySize; const void * entry = FileBundle_getFileAtIndex(tileMapBundle, entryIndex, &entrySize); tileMaps[entryIndex] = readTileMapEditData(entry, entrySize); } extern const char EMBEDDATA_world_zonemap[]; extern unsigned int EMBEDSIZE_world_zonemap; TileZoneMap * zoneMap = readTileZoneMap(EMBEDDATA_world_zonemap, EMBEDSIZE_world_zonemap); GameData * zone = malloc(sizeof(*zone)); zone->roomCount = zoneMap->roomCount; zone->rooms = malloc(zone->roomCount * sizeof(*zone->rooms)); for (unsigned int roomIndex = 0; roomIndex < zoneMap->roomCount; roomIndex++) { zone->rooms[roomIndex].layers = NULL; for (unsigned int tileMapIndex = 0; tileMapIndex < tileMapCount; tileMapIndex++) { if (tileMaps[tileMapIndex]->identifier == zoneMap->rooms[roomIndex].tileMapID) { RoomData room; room.zoneLayer = zoneMap->rooms[roomIndex].zoneLayer; room.zonePosition = zoneMap->rooms[roomIndex].offset; room.identifier = tileMaps[tileMapIndex]->identifier; room.size = tileMaps[tileMapIndex]->size; room.layerCount = tileMaps[tileMapIndex]->layerCount; room.layers = malloc(room.layerCount * sizeof(*room.layers)); for (unsigned int layerIndex = 0; layerIndex < room.layerCount; layerIndex++) { room.layers[layerIndex].type = valueGetInt32(hashGet(tileMaps[tileMapIndex]->layers[layerIndex].metadata, METADATA_KEY_type)); room.layers[layerIndex].offset = Vector2i_subtract(tileMaps[tileMapIndex]->layers[layerIndex].offset, tileMaps[tileMapIndex]->origin); room.layers[layerIndex].tileGrid = TileInstanceGrid_copy(&tileMaps[tileMapIndex]->layers[layerIndex].grid); } room.musicID = valueGetInt32(hashGet(tileMaps[tileMapIndex]->metadata, METADATA_KEY_music)); zone->rooms[roomIndex] = room; break; } } assert(zone->rooms[roomIndex].layers != NULL); } zone->startingRoomIdentifier = valueGetUInt32(hashGet(zoneMap->metadata, METADATA_KEY_start_room)); zone->startingRoomEntranceName = strdup(valueGetString(hashGet(zoneMap->metadata, METADATA_KEY_start_entrance))); TileZoneMap_dispose(zoneMap); return zone; } void GameData_dispose(GameData * zone) { for (unsigned int roomIndex = 0; roomIndex < zone->roomCount; roomIndex++) { for (unsigned int layerIndex = 0; layerIndex < zone->rooms[roomIndex].layerCount; layerIndex++) { TileInstanceGrid_dispose(&zone->rooms[roomIndex].layers[layerIndex].tileGrid); } free(zone->rooms[roomIndex].layers); } free(zone->rooms); free(zone->startingRoomEntranceName); free(zone); } RoomData * GameData_getRoomDataByIdentifier(GameData * zone, TileMapID roomIdentifier, unsigned int * outRoomIndex) { for (unsigned int roomIndex = 0; roomIndex < zone->roomCount; roomIndex++) { if (zone->rooms[roomIndex].identifier == roomIdentifier) { if (outRoomIndex != NULL) { *outRoomIndex = roomIndex; } return &zone->rooms[roomIndex]; } } return NULL; } unsigned int GameData_getRoomIndexAtZonePosition(GameData * zone, int zoneLayer, Vector2i zonePosition) { for (unsigned int roomIndex = 0; roomIndex < zone->roomCount; roomIndex++) { if (zone->rooms[roomIndex].zoneLayer == zoneLayer && zone->rooms[roomIndex].zonePosition.x <= zonePosition.x && zone->rooms[roomIndex].zonePosition.y <= zonePosition.y && zone->rooms[roomIndex].zonePosition.x + (int) zone->rooms[roomIndex].size.x > zonePosition.x && zone->rooms[roomIndex].zonePosition.y + (int) zone->rooms[roomIndex].size.y > zonePosition.y) { return roomIndex; } } return UINT_MAX; } DataHashTable * RoomData_getRoomEntranceByName(RoomData * room, const char * entranceName, Vector2i * outPosition) { for (unsigned int layerIndex = 0; layerIndex < room->layerCount; layerIndex++) { if (room->layers[layerIndex].type == ROOM_LAYER_TYPE_ENTITY) { TileInstance * tileInstances = room->layers[layerIndex].tileGrid.tileInstances; Vector2u layerSize = room->layers[layerIndex].tileGrid.size; for (unsigned int rowIndex = 0; rowIndex < layerSize.y; rowIndex++) { for (unsigned int columnIndex = 0; columnIndex < layerSize.x; columnIndex++) { if (tileInstances[rowIndex * layerSize.x + columnIndex].tileID == TILE_ID_ROOM_ENTRANCE && !strcmp(valueGetString(hashGet(tileInstances[rowIndex * layerSize.x + columnIndex].metadata, METADATA_KEY_identifier)), entranceName)) { if (outPosition != NULL) { outPosition->x = room->layers[layerIndex].offset.x + columnIndex; outPosition->y = room->layers[layerIndex].offset.y + rowIndex; } return tileInstances[rowIndex * layerSize.x + columnIndex].metadata; } } } } } return NULL; } Rect4i RoomData_getLocalBounds(RoomData * room) { return RECT4i(0, room->size.x, 0, room->size.y); } TilePropertyBits getTileProperties(TileID tileID) { TilePropertyBits * tileProperties = HashTable_get(g_tileProperties, HashTable_uint32Key(tileID)); if (tileProperties != NULL) { return *tileProperties; } return 0; }