#ifndef __DFAPI__ #define __DFAPI__ #include "Python.h" #include #include #include "DFTypes.h" #include "DFHackAPI.h" #include "UnionBase.cpp" using namespace std; using namespace DFHack; struct DF_API { PyObject_HEAD DFHack::API* api_Ptr; }; // API type Allocation, Deallocation, and Initialization static PyObject* DF_API_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { DF_API* self; self = (DF_API*)type->tp_alloc(type, 0); if(self != NULL) self->api_Ptr = NULL; return (PyObject*)self; } static int DF_API_init(DF_API* self, PyObject* args, PyObject* kwds) { const char* memFileString = NULL; if(self->api_Ptr == NULL) { if(!PyArg_ParseTuple(args, "s", &memFileString)) return -1; if(memFileString) self->api_Ptr = new DFHack::API(std::string(memFileString)); else return -1; } return 0; } static void DF_API_dealloc(DF_API* self) { if(self != NULL) { if(self->api_Ptr != NULL) { delete self->api_Ptr; self->api_Ptr = NULL; } self->ob_type->tp_free((PyObject*)self); } } // Accessors static PyObject* DF_API_getIsAttached(DF_API* self, void* closure) { try { if(self->api_Ptr != NULL) if(self->api_Ptr->isAttached()) Py_RETURN_TRUE; } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to read attached flag"); Py_RETURN_FALSE; } Py_RETURN_FALSE; } static PyObject* DF_API_getIsSuspended(DF_API* self, void* closure) { try { if(self->api_Ptr != NULL) if(self->api_Ptr->isSuspended()) Py_RETURN_TRUE; } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to read suspension flag"); Py_RETURN_FALSE; } Py_RETURN_FALSE; } static PyObject* DF_API_getIsPaused(DF_API* self, void* closure) { try { if(self->api_Ptr != NULL) if(self->api_Ptr->ReadPauseState()) Py_RETURN_TRUE; } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to read pause state"); Py_RETURN_FALSE; } Py_RETURN_FALSE; } static PyObject* DF_API_getMenuState(DF_API* self, void* closure) { uint32_t menuState = 0; try { if(self->api_Ptr != NULL) { menuState = self->api_Ptr->ReadMenuState(); return PyInt_FromLong(menuState); } } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to read menu state"); Py_RETURN_NONE; } Py_RETURN_NONE; } static PyObject* DF_API_getViewCoords(DF_API* self, void* closure) { int32_t x, y, z; bool success; try { if(self->api_Ptr != NULL) { success = self->api_Ptr->getViewCoords(x, y, z); if(success) { return Py_BuildValue("iii", x, y, z); } else Py_RETURN_NONE; } } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to get view coordinates"); Py_RETURN_NONE; } Py_RETURN_NONE; } static PyObject* DF_API_getSize(DF_API* self, void* closure) { uint32_t x, y, z; try { if(self->api_Ptr != NULL) { self->api_Ptr->getSize(x, y, z); return Py_BuildValue("III", x, y, z); } } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to get view coordinates"); Py_RETURN_NONE; } Py_RETURN_NONE; } static PyGetSetDef DF_API_getterSetters[] = { {"is_attached", (getter)DF_API_getIsAttached, NULL, "is_attached", NULL}, {"is_suspended", (getter)DF_API_getIsSuspended, NULL, "is_suspended", NULL}, {"is_paused", (getter)DF_API_getIsPaused, NULL, "is_paused", NULL}, {"menu_state", (getter)DF_API_getMenuState, NULL, "menu_state", NULL}, {"view_coords", (getter)DF_API_getViewCoords, NULL, "view_coords", NULL}, {"map_size", (getter)DF_API_getSize, NULL, "max_size", NULL}, {NULL} // Sentinel }; // API type methods static PyObject* DF_API_Attach(DF_API* self) { if(self->api_Ptr != NULL) if(self->api_Ptr->Attach()) Py_RETURN_TRUE; Py_RETURN_FALSE; } static PyObject* DF_API_Detach(DF_API* self) { if(self->api_Ptr != NULL) if(self->api_Ptr->Detach()) Py_RETURN_TRUE; Py_RETURN_FALSE; } static PyObject* DF_API_Suspend(DF_API* self) { try { if(self->api_Ptr != NULL) if(self->api_Ptr->Suspend()) Py_RETURN_TRUE; } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to suspend"); Py_RETURN_FALSE; } Py_RETURN_FALSE; } static PyObject* DF_API_Resume(DF_API* self) { try { if(self->api_Ptr != NULL) if(self->api_Ptr->Resume()) Py_RETURN_TRUE; } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to resume"); Py_RETURN_FALSE; } Py_RETURN_FALSE; } static PyObject* DF_API_AsyncSuspend(DF_API* self) { try { if(self->api_Ptr != NULL) if(self->api_Ptr->AsyncSuspend()) Py_RETURN_TRUE; } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to asynchronously suspend"); Py_RETURN_FALSE; } Py_RETURN_FALSE; } static PyObject* DF_API_ForceResume(DF_API* self) { try { if(self->api_Ptr != NULL) if(self->api_Ptr->ForceResume()) Py_RETURN_TRUE; } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to force resume"); Py_RETURN_FALSE; } Py_RETURN_FALSE; } static PyObject* DF_API_InitMap(DF_API* self) { try { if(self->api_Ptr != NULL) if(self->api_Ptr->InitMap()) Py_RETURN_TRUE; } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to initialize map"); Py_RETURN_FALSE; } Py_RETURN_FALSE; } static PyObject* DF_API_DestroyMap(DF_API* self) { try { if(self->api_Ptr != NULL) if(self->api_Ptr->DestroyMap()) Py_RETURN_TRUE; } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to destroy map"); Py_RETURN_FALSE; } Py_RETURN_FALSE; } static PyObject* DF_API_InitReadConstructions(DF_API* self) { uint32_t numConstructions = 0; try { if(self->api_Ptr != NULL) if(self->api_Ptr->InitReadConstructions(numConstructions)) return PyInt_FromLong(numConstructions); } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to read constructions"); } Py_RETURN_NONE; } static PyObject* DF_API_FinishReadConstructions(DF_API* self) { try { if(self->api_Ptr != NULL) { self->api_Ptr->FinishReadConstructions(); Py_RETURN_TRUE; } } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to finish reading constructions"); } Py_RETURN_FALSE; } static PyObject* DF_API_InitReadBuildings(DF_API* self) { uint32_t numBuildings = 0; try { if(self->api_Ptr != NULL) if(self->api_Ptr->InitReadBuildings(numBuildings)) return PyInt_FromLong(numBuildings); } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to read buildings"); } Py_RETURN_NONE; } static PyObject* DF_API_FinishReadBuildings(DF_API* self) { try { if(self->api_Ptr != NULL) { self->api_Ptr->FinishReadBuildings(); Py_RETURN_TRUE; } } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to finish reading buildings"); } Py_RETURN_FALSE; } static PyObject* DF_API_InitReadEffects(DF_API* self) { uint32_t numEffects = 0; try { if(self->api_Ptr != NULL) if(self->api_Ptr->InitReadEffects(numEffects)) return PyInt_FromLong(numEffects); } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to read effects"); } Py_RETURN_NONE; } static PyObject* DF_API_FinishReadEffects(DF_API* self) { try { if(self->api_Ptr != NULL) { self->api_Ptr->FinishReadEffects(); Py_RETURN_TRUE; } } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to finish reading effects"); } Py_RETURN_FALSE; } static PyObject* DF_API_InitReadVegetation(DF_API* self) { uint32_t numVegetation = 0; try { if(self->api_Ptr != NULL) if(self->api_Ptr->InitReadVegetation(numVegetation)) return PyInt_FromLong(numVegetation); } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to read vegetation"); } Py_RETURN_NONE; } static PyObject* DF_API_FinishReadVegetation(DF_API* self) { try { if(self->api_Ptr != NULL) { self->api_Ptr->FinishReadVegetation(); Py_RETURN_TRUE; } } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to finish reading vegetation"); } Py_RETURN_FALSE; } static PyObject* DF_API_InitReadCreatures(DF_API* self) { uint32_t numCreatures = 0; try { if(self->api_Ptr != NULL) if(self->api_Ptr->InitReadCreatures(numCreatures)) return PyInt_FromLong(numCreatures); } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to read creatures"); } Py_RETURN_NONE; } static PyObject* DF_API_FinishReadCreatures(DF_API* self) { try { if(self->api_Ptr != NULL) { self->api_Ptr->FinishReadCreatures(); Py_RETURN_TRUE; } } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to finish reading creatures"); } Py_RETURN_FALSE; } static PyObject* DF_API_InitReadNotes(DF_API* self) { uint32_t numNotes = 0; try { if(self->api_Ptr != NULL) if(self->api_Ptr->InitReadNotes(numNotes)) return PyInt_FromLong(numNotes); } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to read notes"); } Py_RETURN_NONE; } static PyObject* DF_API_FinishReadNotes(DF_API* self) { try { if(self->api_Ptr != NULL) { self->api_Ptr->FinishReadNotes(); Py_RETURN_TRUE; } } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to finish reading notes"); } Py_RETURN_FALSE; } static PyObject* DF_API_InitReadSettlements(DF_API* self) { uint32_t numSettlements = 0; try { if(self->api_Ptr != NULL) if(self->api_Ptr->InitReadSettlements(numSettlements)) return PyInt_FromLong(numSettlements); } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to read settlements"); } Py_RETURN_NONE; } static PyObject* DF_API_FinishReadSettlements(DF_API* self) { try { if(self->api_Ptr != NULL) { self->api_Ptr->FinishReadSettlements(); Py_RETURN_TRUE; } } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to finish reading settlements"); } Py_RETURN_FALSE; } static PyObject* DF_API_InitReadItems(DF_API* self) { uint32_t numItems = 0; try { if(self->api_Ptr != NULL) if(self->api_Ptr->InitReadItems(numItems)) return PyInt_FromLong(numItems); } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to read items"); } Py_RETURN_NONE; } static PyObject* DF_API_FinishReadItems(DF_API* self) { try { if(self->api_Ptr != NULL) { self->api_Ptr->FinishReadItems(); Py_RETURN_TRUE; } } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to finish reading items"); } Py_RETURN_FALSE; } static PyObject* DF_API_InitReadHotkeys(DF_API* self) { try { if(self->api_Ptr != NULL) if(self->api_Ptr->InitReadHotkeys()) Py_RETURN_TRUE; } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to initialize hotkey reader"); } Py_RETURN_FALSE; } static PyObject* DF_API_InitViewSize(DF_API* self) { try { if(self->api_Ptr != NULL) if(self->api_Ptr->InitViewSize()) Py_RETURN_TRUE; } catch(...) { PyErr_SetString(PyExc_ValueError, "Error trying to initialize view size"); } Py_RETURN_FALSE; } static PyObject* DF_API_IsValidBlock(DF_API* self, PyObject* args) { uint32_t blockx, blocky, blockz; bool valid; if(self->api_Ptr != NULL) { if(!PyArg_ParseTuple(args, "III", &blockx, &blocky, &blockz)) Py_RETURN_NONE; valid = self->api_Ptr->isValidBlock(blockx, blocky, blockz); if(valid) Py_RETURN_TRUE; else Py_RETURN_FALSE; } Py_RETURN_FALSE; } static PyObject* DF_API_ReadDesignations(DF_API* self, PyObject* args) { uint32_t blockx, blocky, blockz; DFHack::designations40d designations; PyObject* list = NULL; if(self->api_Ptr != NULL) { if(!PyArg_ParseTuple(args, "III", &blockx, &blocky, &blockz)) Py_RETURN_NONE; self->api_Ptr->ReadDesignations(blockx, blocky, blockz, &designations); list = PyList_New(16); for(int i = 0; i < 16; i++) { PyObject* innerList = PyList_New(16); for(int j = 0; j < 16; j++) { PyList_SetItem(innerList, j, PyInt_FromLong(designations[i][j].whole)); } PyList_SetItem(list, i, innerList); } } return list; } static PyObject* DF_API_WriteDesignations(DF_API* self, PyObject* args) { uint32_t blockx, blocky, blockz; DFHack::designations40d designations; PyObject* list; if(self->api_Ptr != NULL) { if(!PyArg_ParseTuple(args, "IIIO", &blockx, &blocky, &blockz, &list)) Py_RETURN_NONE; for(int i = 0; i < 16; i++) { PyObject* innerList = PyList_GetItem(list, i); for(int j = 0; j < 16; j++) { UnionBase* obj = (UnionBase*)PyList_GetItem(innerList, j); designations[i][j].whole = obj->whole; } } self->api_Ptr->WriteDesignations(blockx, blocky, blockz, &designations); Py_RETURN_TRUE; } Py_RETURN_FALSE; } static PyObject* DF_API_ReadOccupancy(DF_API* self, PyObject* args) { uint32_t blockx, blocky, blockz; DFHack::occupancies40d occupancies; PyObject* list = NULL; if(self->api_Ptr != NULL) { if(!PyArg_ParseTuple(args, "III", &blockx, &blocky, &blockz)) Py_RETURN_NONE; self->api_Ptr->ReadOccupancy(blockx, blocky, blockz, &occupancies); list = PyList_New(16); for(int i = 0; i < 16; i++) { PyObject* innerList = PyList_New(16); for(int j = 0; j < 16; j++) { PyList_SetItem(innerList, j, PyInt_FromLong(occupancies[i][j].whole)); } PyList_SetItem(list, i, innerList); } } return list; } static PyObject* DF_API_WriteOccupancy(DF_API* self, PyObject* args) { uint32_t blockx, blocky, blockz; DFHack::occupancies40d occupancies; PyObject* list; if(self->api_Ptr != NULL) { if(!PyArg_ParseTuple(args, "IIIO", &blockx, &blocky, &blockz, &list)) Py_RETURN_NONE; for(int i = 0; i < 16; i++) { PyObject* innerList = PyList_GetItem(list, i); for(int j = 0; j < 16; j++) { UnionBase* obj = (UnionBase*)PyList_GetItem(innerList, j); occupancies[i][j].whole = obj->whole; } } self->api_Ptr->WriteOccupancy(blockx, blocky, blockz, &occupancies); Py_RETURN_TRUE; } Py_RETURN_FALSE; } static PyObject* DF_API_ReadDirtyBit(DF_API* self, PyObject* args) { uint32_t blockx, blocky, blockz; bool dirty; if(self->api_Ptr == NULL) return NULL; else { if(!PyArg_ParseTuple(args, "III", &blockx, &blocky, &blockz)) return NULL; self->api_Ptr->ReadDirtyBit(blockx, blocky, blockz, dirty); if(dirty) Py_RETURN_TRUE; else Py_RETURN_FALSE; } } static PyObject* DF_API_WriteDirtyBit(DF_API* self, PyObject* args) { uint32_t blockx, blocky, blockz; int dirtyFlag; if(self->api_Ptr == NULL) return NULL; else { if(!PyArg_ParseTuple(args, "IIIi", &blockx, &blocky, &blockz, &dirtyFlag)) return NULL; self->api_Ptr->WriteDirtyBit(blockx, blocky, blockz, dirtyFlag); Py_RETURN_TRUE; } } static PyMethodDef DF_API_methods[] = { {"Attach", (PyCFunction)DF_API_Attach, METH_NOARGS, "Attach to the DF process"}, {"Detach", (PyCFunction)DF_API_Detach, METH_NOARGS, "Detach from the DF process"}, {"Suspend", (PyCFunction)DF_API_Suspend, METH_NOARGS, "Suspend the DF process"}, {"Resume", (PyCFunction)DF_API_Resume, METH_NOARGS, "Resume the DF process"}, {"Async_Suspend", (PyCFunction)DF_API_AsyncSuspend, METH_NOARGS, "Asynchronously suspend the DF process"}, {"Force_Resume", (PyCFunction)DF_API_ForceResume, METH_NOARGS, "Force the DF process to resume"}, {"Init_Map", (PyCFunction)DF_API_InitMap, METH_NOARGS, "Initialize the DFHack map reader"}, {"Destroy_Map", (PyCFunction)DF_API_DestroyMap, METH_NOARGS, "Shut down the DFHack map reader"}, {"Init_Read_Constructions", (PyCFunction)DF_API_InitReadConstructions, METH_NOARGS, "Initialize construction reader"}, {"Finish_Read_Constructions", (PyCFunction)DF_API_FinishReadConstructions, METH_NOARGS, "Shut down construction reader"}, {"Init_Read_Buildings", (PyCFunction)DF_API_InitReadBuildings, METH_NOARGS, "Initialize building reader"}, {"Finish_Read_Buildings", (PyCFunction)DF_API_FinishReadBuildings, METH_NOARGS, "Shut down building reader"}, {"Init_Read_Effects", (PyCFunction)DF_API_InitReadEffects, METH_NOARGS, "Initialize effect reader"}, {"Finish_Read_Effects", (PyCFunction)DF_API_FinishReadEffects, METH_NOARGS, "Shut down effect reader"}, {"Init_Read_Vegetation", (PyCFunction)DF_API_InitReadVegetation, METH_NOARGS, "Initialize vegetation reader"}, {"Finish_Read_Vegetation", (PyCFunction)DF_API_FinishReadVegetation, METH_NOARGS, "Shut down vegetation reader"}, {"Init_Read_Creatures", (PyCFunction)DF_API_InitReadCreatures, METH_NOARGS, "Initialize creature reader"}, {"Finish_Read_Creatures", (PyCFunction)DF_API_FinishReadCreatures, METH_NOARGS, "Shut down creature reader"}, {"Init_Read_Notes", (PyCFunction)DF_API_InitReadNotes, METH_NOARGS, "Initialize note reader"}, {"Finish_Read_Notes", (PyCFunction)DF_API_FinishReadNotes, METH_NOARGS, "Shut down note reader"}, {"Init_Read_Settlements", (PyCFunction)DF_API_InitReadSettlements, METH_NOARGS, "Initialize settlement reader"}, {"Finish_Read_Settlements", (PyCFunction)DF_API_FinishReadSettlements, METH_NOARGS, "Shut down settlement reader"}, {"Init_Read_Items", (PyCFunction)DF_API_InitReadItems, METH_NOARGS, "Initialize item reader"}, {"Finish_Read_Items", (PyCFunction)DF_API_FinishReadItems, METH_NOARGS, "Shut down item reader"}, {"Init_Read_Hotkeys", (PyCFunction)DF_API_InitReadHotkeys, METH_NOARGS, "Initialize hotkey reader"}, {"Init_View_Size", (PyCFunction)DF_API_InitViewSize, METH_NOARGS, "Initialize view size reader"}, {"Is_Valid_Block", (PyCFunction)DF_API_IsValidBlock, METH_VARARGS, ""}, {"Read_Designations", (PyCFunction)DF_API_ReadDesignations, METH_VARARGS, "Read a block's designations"}, {"Write_Designations", (PyCFunction)DF_API_WriteDesignations, METH_VARARGS, ""}, {"Read_Occupancy", (PyCFunction)DF_API_ReadOccupancy, METH_VARARGS, ""}, {"Write_Occupancy", (PyCFunction)DF_API_WriteOccupancy, METH_VARARGS, ""}, {"Read_Dirty_Bit", (PyCFunction)DF_API_ReadDirtyBit, METH_VARARGS, ""}, {"Write_Dirty_Bit", (PyCFunction)DF_API_WriteDirtyBit, METH_VARARGS, ""}, {NULL} // Sentinel }; static PyTypeObject DF_API_type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "pydfhack.API", /*tp_name*/ sizeof(DF_API), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)DF_API_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "pydfhack API objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ DF_API_methods, /* tp_methods */ 0, /* tp_members */ DF_API_getterSetters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)DF_API_init, /* tp_init */ 0, /* tp_alloc */ DF_API_new, /* tp_new */ }; #endif