dfhack/shmserver/mod-maps.cpp

113 lines
3.7 KiB
C++

#include <string>
#include <vector>
#include <integers.h>
#include "shms.h"
#include "mod-core.h"
#include "mod-maps.h"
#include <DFTypes.h>
using namespace DFHack;
using namespace DFHack::Maps;
#include <string.h>
#include <malloc.h>
extern char *shm;
//TODO: circular buffer streaming primitives required
//TODO: commands can fail without the proper offsets. Hot to handle that?
#define SHMHDR ((shm_maps_hdr *)shm)
#define SHMCMD ((shm_cmd *)shm)->pingpong
#define SHMDATA ((char *)(shm + SHM_HEADER))
void NullCommand (void* data)
{
};
void InitOffsets (void* data)
{
maps_modulestate * state = (maps_modulestate *) data;
memcpy((void *) &(state->offsets), SHMDATA, sizeof(maps_offsets));
((maps_modulestate *) data)->inited = true;
}
void GetMapSize (void *data)
{
maps_modulestate * state = (maps_modulestate *) data;
if(state->inited)
{
SHMHDR->x = *(uint32_t *) (state->offsets.x_count_offset);
SHMHDR->y = *(uint32_t *) (state->offsets.y_count_offset);
SHMHDR->z = *(uint32_t *) (state->offsets.z_count_offset);
SHMHDR->error = false;
}
else
{
SHMHDR->error = true;
}
}
struct mblock
{
uint32_t * ptr_to_dirty;
};
#define SHMBLOCK ((mapblock40d *)(shm + SHM_HEADER))
void ReadBlockByCoords (void * data)
{
maps_modulestate * state = (maps_modulestate *) data;
maps_offsets & offsets = state->offsets;
/* map_offset is a pointer to
a pointer to
an X block of pointers to
an Y blocks of pointers to
a Z blocks of pointers to
map blocks
only Z blocks can have NULL pointers? TODO: verify
*/
mblock * *** mapArray = *(mblock * ****)offsets.map_offset;
mblock * block = mapArray[SHMHDR->x][SHMHDR->y][SHMHDR->z];
//fprintf(stderr, "Readblock: %d %d %d 0x%x\n", SHMHDR->x,SHMHDR->y,SHMHDR->z, block);
if(block)
{
memcpy(&(SHMBLOCK->tiletypes), block + offsets.tile_type_offset, sizeof(SHMBLOCK->tiletypes));
memcpy(&(SHMBLOCK->designaton), block + offsets.designation_offset, sizeof(SHMBLOCK->designaton));
memcpy(&(SHMBLOCK->occupancy), block + offsets.occupancy_offset, sizeof(SHMBLOCK->occupancy));
memcpy(&(SHMBLOCK->biome_indices), block + offsets.biome_stuffs, sizeof(SHMBLOCK->biome_indices));
SHMBLOCK->dirty_dword = *block->ptr_to_dirty;
SHMBLOCK->origin = reinterpret_cast<uint32_t>(block);
SHMHDR->error = false;
}
else
{
SHMHDR->error = true;
}
}
DFPP_module InitMaps( void )
{
DFPP_module maps;
maps.name = "Maps";
maps.version = MAPS_VERSION;
// freed by the core
maps.modulestate = malloc(sizeof(maps_modulestate)); // we store a flag
memset(maps.modulestate,0,sizeof(maps_modulestate));
maps.reserve(NUM_MAPS_CMDS);
// client sends a maps_offsets struct -> inited = true;
maps.set_command(MAP_INIT, FUNCTION, "Supply the module with offsets",InitOffsets,CORE_SUSPENDED);
maps.set_command(MAP_GET_SIZE, FUNCTION, "Get map size in 16x16x1 tile blocks", GetMapSize, CORE_SUSPENDED);
maps.set_command(MAP_READ_BLOCK_BY_COORDS, FUNCTION, "Read the whole block with specified coords", ReadBlockByCoords, CORE_SUSPENDED);
// will it fit into 1MB? We shouldn't assume this is the case
maps.set_command(MAP_READ_BLOCKTREE, FUNCTION,"Get the tree of block pointers as a single structure", NullCommand, CORE_SUSPENDED);
// really doesn't fit into 1MB, there should be a streaming variant to better utilize context switches
maps.set_command(MAP_READ_BLOCKS_3D, FUNCTION, "Read a range of blocks between two sets of coords", NullCommand, CORE_SUSPENDED);
return maps;
}