Very basic plugin system.

develop
Petr Mrázek 2011-06-20 04:29:38 +02:00
parent ffd2ca3281
commit c6dc4900d2
14 changed files with 683 additions and 141 deletions

@ -71,6 +71,10 @@ IF(BUILD_LIBRARY)
install(FILES LICENSE Readme.html DESTINATION ${DFHACK_USERDOC_DESTINATION})
endif()
IF(BUILD_PLUGINS)
add_subdirectory (plugins)
endif()
# Packaging with CPack!
IF(UNIX)
SET(CPACK_GENERATOR "TGZ")

@ -116,3 +116,27 @@ AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
------------------------------------------------------------------
* dirent.h - dirent API for Microsoft Visual Studio
*
* Copyright (C) 2006 Toni Ronkko
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* ``Software''), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.

@ -119,14 +119,18 @@ ENDIF()
ADD_LIBRARY(dfhack SHARED ${PROJECT_SRCS})
IF(WIN32)
SET_TARGET_PROPERTIES(dfhack PROPERTIES OUTPUT_NAME "SDL" )
ENDIF()
SET_TARGET_PROPERTIES(dfhack PROPERTIES DEBUG_POSTFIX "-debug" )
TARGET_LINK_LIBRARIES(dfhack ${PROJECT_LIBS})
ADD_CUSTOM_TARGET( memxmlcopy
DEPENDS ${dfhack_SOURCE_DIR}/Memory.xml
COMMAND ${CMAKE_COMMAND} -E make_directory ${dfhack_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/
COMMAND ${CMAKE_COMMAND} -E copy ${dfhack_SOURCE_DIR}/Memory.xml ${dfhack_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/)
COMMAND ${CMAKE_COMMAND} -E make_directory ${DFHACK_OUTPUT_DIR}
COMMAND ${CMAKE_COMMAND} -E copy ${dfhack_SOURCE_DIR}/Memory.xml ${DFHACK_OUTPUT_DIR})
ADD_DEPENDENCIES(dfhack memxmlcopy)
install(TARGETS dfhack

@ -43,6 +43,23 @@ distribution.
#include "dfhack/FakeSDL.h"
#include <iostream>
/*
* Plugin loading functions
*/
DFLibrary * OpenPlugin (const char * filename)
{
return (DFLibrary *) dlopen(filename, RTLD_NOW);
}
void * LookupPlugin (DFLibrary * plugin ,const char * function)
{
return (DFLibrary *) dlsym((void *)plugin, function);
}
void ClosePlugin (DFLibrary * plugin)
{
dlclose((void *) plugin);
}
/*******************************************************************************
* SDL part starts here *
*******************************************************************************/

@ -45,10 +45,8 @@ distribution.
#define MAX_CONSOLE_LINES 250;
HANDLE g_hConsoleOut; // Handle to debug console
void RedirectIOToConsole();
/*
* This function dynamically creates a "Console" window and points stdout and stderr to it.
* It also hooks stdin to the window
@ -114,6 +112,22 @@ void RedirectIOToConsole()
#include "dfhack/FakeSDL.h"
#include <stdio.h>
/*
* Plugin loading functions
*/
DFLibrary * OpenPlugin (const char * filename)
{
return (DFLibrary *) LoadLibrary(filename);
}
void * LookupPlugin (DFLibrary * plugin ,const char * function)
{
return (DFLibrary *) GetProcAddress((HMODULE)plugin, function);
}
void ClosePlugin (DFLibrary * plugin)
{
FreeLibrary((HMODULE) plugin);
}
/*************************************************************************/
// extremely boring wrappers beyond this point. Only fix when broken
@ -518,7 +532,7 @@ DFhackCExport void * SDL_LoadFunction(DFLibrary *handle, const char *name)
return _SDL_LoadFunction(handle, name);
}
static DFLibrary * (*_SDL_LoadObject)(const char *sofile) = 0;
extern "C" static DFLibrary * (*_SDL_LoadObject)(const char *sofile) = 0;
DFhackCExport DFLibrary * SDL_LoadObject(const char *sofile)
{
return _SDL_LoadObject(sofile);

@ -43,134 +43,67 @@ using namespace std;
#include "dfhack/modules/World.h"
#include "dfhack/extra/rlutil.h"
#include <stdio.h>
#ifdef LINUX_BUILD
#include <dirent.h>
#include <errno.h>
#else
#include "wdirent.h"
#endif
using namespace DFHack;
int kittenz (void)
static int getdir (string dir, vector<string> &files)
{
const char * kittenz1 []=
DIR *dp;
struct dirent *dirp;
if((dp = opendir(dir.c_str())) == NULL)
{
" ____",
" (. \\",
" \\ | ",
" \\ |___(\\--/)",
" __/ ( . . )",
" \"'._. '-.O.'",
" '-. \\ \"|\\",
" '.,,/'.,,mrf",
0
};
rlutil::hidecursor();
rlutil::cls();
int color = 1;
while(1)
{
rlutil::setColor(color);
int index = 0;
const char * kit = kittenz1[index];
rlutil::locate(1,1);
cout << "Your DF is now full of kittens!" << endl;
while (kit != 0)
{
rlutil::locate(5,5+index);
cout << kit;
index++;
kit = kittenz1[index];
}
fflush(stdout);
rlutil::msleep(60);
color ++;
if(color > 15)
color = 1;
rlutil::cls();
cout << "Error(" << errno << ") opening " << dir << endl;
return errno;
}
}
struct hideblock
{
uint32_t x;
uint32_t y;
uint32_t z;
uint8_t hiddens [16][16];
};
int reveal (void)
{
Core & c = DFHack::Core::getInstance();
c.Suspend();
DFHack::Maps *Maps =c.getMaps();
DFHack::World *World =c.getWorld();
// init the map
if(!Maps->Start())
{
cerr << "Can't init map." << endl;
c.Resume();
return 1;
while ((dirp = readdir(dp)) != NULL) {
files.push_back(string(dirp->d_name));
}
closedir(dp);
return 0;
}
cout << "Revealing, please wait..." << endl;
uint32_t x_max, y_max, z_max;
DFHack::designations40d designations;
Maps->getSize(x_max,y_max,z_max);
vector <hideblock> hidesaved;
for(uint32_t x = 0; x< x_max;x++)
int fIOthread(void * _core)
{
Core * core = (Core *) _core;
vector <string> filez;
map <string, int (*)(Core *)> plugins;
getdir(core->p->getPath(), filez);
const char * (*_PlugName)(void) = 0;
int (*_PlugRun)(Core *) = 0;
for(int i = 0; i < filez.size();i++)
{
for(uint32_t y = 0; y< y_max;y++)
if(strstr(filez[i].c_str(),".plug."))
{
for(uint32_t z = 0; z< z_max;z++)
DFLibrary * plug = OpenPlugin(filez[i].c_str());
if(!plug)
{
if(Maps->isValidBlock(x,y,z))
{
hideblock hb;
hb.x = x;
hb.y = y;
hb.z = z;
// read block designations
Maps->ReadDesignations(x,y,z, &designations);
// change the hidden flag to 0
for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
{
hb.hiddens[i][j] = designations[i][j].bits.hidden;
designations[i][j].bits.hidden = 0;
}
hidesaved.push_back(hb);
// write the designations back
Maps->WriteDesignations(x,y,z, &designations);
}
cerr << "Can't load plugin " << filez[i] << endl;
continue;
}
_PlugName = (const char * (*)()) LookupPlugin(plug, "plugin_name");
if(!_PlugName)
{
cerr << "Plugin " << filez[i] << " has no name." << endl;
ClosePlugin(plug);
continue;
}
_PlugRun = (int (*)(Core * c)) LookupPlugin(plug, "plugin_run");
if(!_PlugRun)
{
cerr << "Plugin " << filez[i] << " has no run function." << endl;
ClosePlugin(plug);
continue;
}
cout << filez[i] << endl;
plugins[string(_PlugName())] = _PlugRun;
}
}
World->SetPauseState(true);
c.Resume();
cout << "Map revealed. The game has been paused for you." << endl;
cout << "Unpausing can unleash the forces of hell!" << endl;
cout << "Saving will make this state permanent. Don't do it." << endl << endl;
cout << "Press any key to unreveal." << endl;
cin.ignore();
cout << "Unrevealing... please wait." << endl;
// FIXME: do some consistency checks here!
c.Suspend();
Maps = c.getMaps();
Maps->Start();
for(size_t i = 0; i < hidesaved.size();i++)
{
hideblock & hb = hidesaved[i];
Maps->ReadDesignations(hb.x,hb.y,hb.z, &designations);
for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
{
designations[i][j].bits.hidden = hb.hiddens[i][j];
}
Maps->WriteDesignations(hb.x,hb.y,hb.z, &designations);
}
c.Resume();
return 0;
}
int fIOthread(void * _core)
{
Core * core = (Core *) _core;
cout << "Hello from the IO thread. Have a nice day!" << endl;
while (true)
{
@ -185,22 +118,23 @@ int fIOthread(void * _core)
if(command=="help" || command == "?")
{
cout << "Available commands:" << endl;
// TODO: generic list of available commands!
cout << "reveal" << endl;
cout << "kittens" << endl;
for (map <string, int (*)(Core *)>::iterator iter = plugins.begin(); iter != plugins.end(); iter++)
{
cout << iter->first << endl;
}
}
// TODO: commands will be registered. We'll scan a map of command -> function pointer and call stuff.
else if(command == "reveal")
{
reveal();
}
else if(command == "kittens")
{
kittenz();
}
else
{
cout << "Do 'help' or '?' for the list of available commands." << endl;
map <string, int (*)(Core *)>::iterator iter = plugins.find(command);
if(iter != plugins.end())
{
iter->second(core);
}
else
{
cout << "Do 'help' or '?' for the list of available commands." << endl;
}
}
}
}
@ -236,8 +170,9 @@ Core::Core()
errorstate = false;
// lock mutex
SDL_mutexP(AccessMutex);
// look for all plugins,
// create IO thread
DFThread * IO = SDL_CreateThread(fIOthread, 0);
DFThread * IO = SDL_CreateThread(fIOthread, this);
// and let DF do its thing.
};

@ -119,8 +119,7 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
}
}
int getdir (string dir, vector<string> &files)
static int getdir (string dir, vector<string> &files)
{
DIR *dp;
struct dirent *dirp;

@ -27,6 +27,8 @@ distribution.
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#include "dfhack/FakeSDL.h"
#include <vector>
namespace DFHack
{
class Process;

@ -40,3 +40,10 @@ distribution.
#endif
#endif
#endif
// C export macros for faking SDL and plugin exports
#ifdef LINUX_BUILD
#define DFhackCExport extern "C" __attribute__ ((visibility("default")))
#else
#define DFhackCExport extern "C" __declspec(dllexport)
#endif

@ -30,12 +30,7 @@ distribution.
#include "dfhack/Pragma.h"
#include "dfhack/Export.h"
#ifdef LINUX_BUILD
#define DFhackCExport extern "C" __attribute__ ((visibility("default")))
#else
#define DFhackCExport extern "C" __declspec(dllexport)
#endif
#include <string>
// function and variable pointer... we don't try to understand what SDL does here
typedef void * fPtr;
@ -51,11 +46,15 @@ DFhackCExport int SDL_mutexV(DFMutex *);
DFhackCExport void SDL_DestroyMutex(DFMutex *);
DFhackCExport DFThread *SDL_CreateThread(int (*fn)(void *), void *data);
// Functions for loading libraries and looking up exported symbols
//FIXME: remove, these fail
DFhackCExport void * SDL_LoadFunction(DFLibrary *handle, const char *name);
DFhackCExport DFLibrary * SDL_LoadObject(const char *sofile);
DFhackCExport void SDL_UnloadObject(DFLibrary * handle);
DFLibrary * OpenPlugin (const char * filename);
void * LookupPlugin (DFLibrary * plugin ,const char * function);
void ClosePlugin (DFLibrary * plugin);
// these functions are here because they call into DFHack::Core and therefore need to
// be declared as friend functions/known
DFhackCExport int SDL_NumJoysticks(void);

@ -0,0 +1,372 @@
/*****************************************************************************
* dirent.h - dirent API for Microsoft Visual Studio
*
* Copyright (C) 2006 Toni Ronkko
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* ``Software''), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Mar 15, 2011, Toni Ronkko
* Defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0.
*
* Aug 11, 2010, Toni Ronkko
* Added d_type and d_namlen fields to dirent structure. The former is
* especially useful for determining whether directory entry represents a
* file or a directory. For more information, see
* http://www.delorie.com/gnu/docs/glibc/libc_270.html
*
* Aug 11, 2010, Toni Ronkko
* Improved conformance to the standards. For example, errno is now set
* properly on failure and assert() is never used. Thanks to Peter Brockam
* for suggestions.
*
* Aug 11, 2010, Toni Ronkko
* Fixed a bug in rewinddir(): when using relative directory names, change
* of working directory no longer causes rewinddir() to fail.
*
* Dec 15, 2009, John Cunningham
* Added rewinddir member function
*
* Jan 18, 2008, Toni Ronkko
* Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
* between multi-byte and unicode representations. This makes the
* code simpler and also allows the code to be compiled under MingW. Thanks
* to Azriel Fasten for the suggestion.
*
* Mar 4, 2007, Toni Ronkko
* Bug fix: due to the strncpy_s() function this file only compiled in
* Visual Studio 2005. Using the new string functions only when the
* compiler version allows.
*
* Nov 2, 2006, Toni Ronkko
* Major update: removed support for Watcom C, MS-DOS and Turbo C to
* simplify the file, updated the code to compile cleanly on Visual
* Studio 2005 with both unicode and multi-byte character strings,
* removed rewinddir() as it had a bug.
*
* Aug 20, 2006, Toni Ronkko
* Removed all remarks about MSVC 1.0, which is antiqued now. Simplified
* comments by removing SGML tags.
*
* May 14 2002, Toni Ronkko
* Embedded the function definitions directly to the header so that no
* source modules need to be included in the Visual Studio project. Removed
* all the dependencies to other projects so that this very header can be
* used independently.
*
* May 28 1998, Toni Ronkko
* First version.
*****************************************************************************/
#ifndef DIRENT_H
#define DIRENT_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
/* Entries missing from MSVC 6.0 */
#if !defined(FILE_ATTRIBUTE_DEVICE)
# define FILE_ATTRIBUTE_DEVICE 0x40
#endif
/* File type and permission flags for stat() */
#if defined(_MSC_VER) && !defined(S_IREAD)
# define S_IFMT _S_IFMT /* file type mask */
# define S_IFDIR _S_IFDIR /* directory */
# define S_IFCHR _S_IFCHR /* character device */
# define S_IFFIFO _S_IFFIFO /* pipe */
# define S_IFREG _S_IFREG /* regular file */
# define S_IREAD _S_IREAD /* read permission */
# define S_IWRITE _S_IWRITE /* write permission */
# define S_IEXEC _S_IEXEC /* execute permission */
#endif
#define S_IFBLK 0 /* block device */
#define S_IFLNK 0 /* link */
#define S_IFSOCK 0 /* socket */
#if defined(_MSC_VER)
# define S_IRUSR S_IREAD /* read, user */
# define S_IWUSR S_IWRITE /* write, user */
# define S_IXUSR 0 /* execute, user */
# define S_IRGRP 0 /* read, group */
# define S_IWGRP 0 /* write, group */
# define S_IXGRP 0 /* execute, group */
# define S_IROTH 0 /* read, others */
# define S_IWOTH 0 /* write, others */
# define S_IXOTH 0 /* execute, others */
#endif
/* Indicates that d_type field is available in dirent structure */
#define _DIRENT_HAVE_D_TYPE
/* File type flags for d_type */
#define DT_UNKNOWN 0
#define DT_REG S_IFREG
#define DT_DIR S_IFDIR
#define DT_FIFO S_IFFIFO
#define DT_SOCK S_IFSOCK
#define DT_CHR S_IFCHR
#define DT_BLK S_IFBLK
/* Macros for converting between st_mode and d_type */
#define IFTODT(mode) ((mode) & S_IFMT)
#define DTTOIF(type) (type)
/*
* File type macros. Note that block devices, sockets and links cannot be
* distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
* only defined for compatibility. These macros should always return false
* on Windows.
*/
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#ifdef __cplusplus
extern "C" {
#endif
typedef struct dirent
{
char d_name[MAX_PATH + 1]; /* File name */
size_t d_namlen; /* Length of name without \0 */
int d_type; /* File type */
} dirent;
typedef struct DIR
{
dirent curentry; /* Current directory entry */
WIN32_FIND_DATAA find_data; /* Private file data */
int cached; /* True if data is valid */
HANDLE search_handle; /* Win32 search handle */
char patt[MAX_PATH + 3]; /* Initial directory name */
} DIR;
/* Forward declarations */
static DIR *opendir(const char *dirname);
static struct dirent *readdir(DIR *dirp);
static int closedir(DIR *dirp);
static void rewinddir(DIR* dirp);
/* Use the new safe string functions introduced in Visual Studio 2005 */
#if defined(_MSC_VER) && _MSC_VER >= 1400
# define DIRENT_STRNCPY(dest,src,size) strncpy_s((dest),(size),(src),_TRUNCATE)
#else
# define DIRENT_STRNCPY(dest,src,size) strncpy((dest),(src),(size))
#endif
/* Set errno variable */
#if defined(_MSC_VER)
#define DIRENT_SET_ERRNO(x) _set_errno (x)
#else
#define DIRENT_SET_ERRNO(x) (errno = (x))
#endif
/*****************************************************************************
* Open directory stream DIRNAME for read and return a pointer to the
* internal working area that is used to retrieve individual directory
* entries.
*/
static DIR *opendir(const char *dirname)
{
DIR *dirp;
/* ensure that the resulting search pattern will be a valid file name */
if (dirname == NULL) {
DIRENT_SET_ERRNO (ENOENT);
return NULL;
}
if (strlen (dirname) + 3 >= MAX_PATH) {
DIRENT_SET_ERRNO (ENAMETOOLONG);
return NULL;
}
/* construct new DIR structure */
dirp = (DIR*) malloc (sizeof (struct DIR));
if (dirp != NULL) {
int error;
/*
* Convert relative directory name to an absolute one. This
* allows rewinddir() to function correctly when the current working
* directory is changed between opendir() and rewinddir().
*/
if (GetFullPathNameA (dirname, MAX_PATH, dirp->patt, NULL)) {
char *p;
/* append the search pattern "\\*\0" to the directory name */
p = strchr (dirp->patt, '\0');
if (dirp->patt < p && *(p-1) != '\\' && *(p-1) != ':') {
*p++ = '\\';
}
*p++ = '*';
*p = '\0';
/* open directory stream and retrieve the first entry */
dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data);
if (dirp->search_handle != INVALID_HANDLE_VALUE) {
/* a directory entry is now waiting in memory */
dirp->cached = 1;
error = 0;
} else {
/* search pattern is not a directory name? */
DIRENT_SET_ERRNO (ENOENT);
error = 1;
}
} else {
/* buffer too small */
DIRENT_SET_ERRNO (ENOMEM);
error = 1;
}
if (error) {
free (dirp);
dirp = NULL;
}
}
return dirp;
}
/*****************************************************************************
* Read a directory entry, and return a pointer to a dirent structure
* containing the name of the entry in d_name field. Individual directory
* entries returned by this very function include regular files,
* sub-directories, pseudo-directories "." and "..", but also volume labels,
* hidden files and system files may be returned.
*/
static struct dirent *readdir(DIR *dirp)
{
DWORD attr;
if (dirp == NULL) {
/* directory stream did not open */
DIRENT_SET_ERRNO (EBADF);
return NULL;
}
/* get next directory entry */
if (dirp->cached != 0) {
/* a valid directory entry already in memory */
dirp->cached = 0;
} else {
/* get the next directory entry from stream */
if (dirp->search_handle == INVALID_HANDLE_VALUE) {
return NULL;
}
if (FindNextFileA (dirp->search_handle, &dirp->find_data) == FALSE) {
/* the very last entry has been processed or an error occured */
FindClose (dirp->search_handle);
dirp->search_handle = INVALID_HANDLE_VALUE;
return NULL;
}
}
/* copy as a multibyte character string */
DIRENT_STRNCPY ( dirp->curentry.d_name,
dirp->find_data.cFileName,
sizeof(dirp->curentry.d_name) );
dirp->curentry.d_name[MAX_PATH] = '\0';
/* compute the length of name */
dirp->curentry.d_namlen = strlen (dirp->curentry.d_name);
/* determine file type */
attr = dirp->find_data.dwFileAttributes;
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
dirp->curentry.d_type = DT_CHR;
} else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
dirp->curentry.d_type = DT_DIR;
} else {
dirp->curentry.d_type = DT_REG;
}
return &dirp->curentry;
}
/*****************************************************************************
* Close directory stream opened by opendir() function. Close of the
* directory stream invalidates the DIR structure as well as any previously
* read directory entry.
*/
static int closedir(DIR *dirp)
{
if (dirp == NULL) {
/* invalid directory stream */
DIRENT_SET_ERRNO (EBADF);
return -1;
}
/* release search handle */
if (dirp->search_handle != INVALID_HANDLE_VALUE) {
FindClose (dirp->search_handle);
dirp->search_handle = INVALID_HANDLE_VALUE;
}
/* release directory structure */
free (dirp);
return 0;
}
/*****************************************************************************
* Resets the position of the directory stream to which dirp refers to the
* beginning of the directory. It also causes the directory stream to refer
* to the current state of the corresponding directory, as a call to opendir()
* would have done. If dirp does not refer to a directory stream, the effect
* is undefined.
*/
static void rewinddir(DIR* dirp)
{
if (dirp != NULL) {
/* release search handle */
if (dirp->search_handle != INVALID_HANDLE_VALUE) {
FindClose (dirp->search_handle);
}
/* open new search handle and retrieve the first entry */
dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data);
if (dirp->search_handle != INVALID_HANDLE_VALUE) {
/* a directory entry is now waiting in memory */
dirp->cached = 1;
} else {
/* failed to re-open directory: no directory entry in memory */
dirp->cached = 0;
}
}
}
#ifdef __cplusplus
}
#endif
#endif /*DIRENT_H*/

@ -0,0 +1,22 @@
#FIXME: inherit all macros and stuff from the dfhack SDK
IF(UNIX)
add_definitions(-DLINUX_BUILD)
SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall")
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32")
SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32")
ENDIF()
include_directories("${dfhack_SOURCE_DIR}/library/include")
MACRO(DFHACK_PLUGIN PLUGIN_NAME PLUGIN_SOURCES)
ADD_LIBRARY(${PLUGIN_NAME} MODULE ${PLUGIN_SOURCES})
TARGET_LINK_LIBRARIES(${PLUGIN_NAME} dfhack)
IF(UNIX)
SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES SUFFIX .plug.so PREFIX "")
ELSE()
SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES SUFFIX .plug.dll)
ENDIF()
ENDMACRO()
DFHACK_PLUGIN(reveal reveal.cpp)
DFHACK_PLUGIN(kittens kittens.cpp)

@ -0,0 +1,48 @@
#include <dfhack/Core.h>
#include <dfhack/Export.h>
#include <dfhack/extra/rlutil.h>
DFhackCExport const char * plugin_name ( void )
{
return "kittens";
}
DFhackCExport int plugin_run (DFHack::Core * c)
{
const char * kittenz1 []=
{
" ____",
" (. \\",
" \\ | ",
" \\ |___(\\--/)",
" __/ ( . . )",
" \"'._. '-.O.'",
" '-. \\ \"|\\",
" '.,,/'.,,mrf",
0
};
rlutil::hidecursor();
rlutil::cls();
int color = 1;
while(1)
{
rlutil::setColor(color);
int index = 0;
const char * kit = kittenz1[index];
rlutil::locate(1,1);
std::cout << "Your DF is now full of kittens!" << std::endl;
while (kit != 0)
{
rlutil::locate(5,5+index);
std::cout << kit;
index++;
kit = kittenz1[index];
}
std::fflush(stdout);
rlutil::msleep(60);
color ++;
if(color > 15)
color = 1;
}
return 0;
}

@ -0,0 +1,95 @@
#include <stdint.h>
#include <iostream>
#include <map>
#include <vector>
#include <dfhack/Core.h>
#include <dfhack/Export.h>
#include <dfhack/modules/Maps.h>
#include <dfhack/modules/World.h>
DFhackCExport const char * plugin_name ( void )
{
return "reveal";
}
struct hideblock
{
uint32_t x;
uint32_t y;
uint32_t z;
uint8_t hiddens [16][16];
};
DFhackCExport int plugin_run (DFHack::Core * c)
{
c->Suspend();
DFHack::Maps *Maps =c->getMaps();
DFHack::World *World =c->getWorld();
// init the map
if(!Maps->Start())
{
std::cerr << "Can't init map." << std::endl;
c->Resume();
return 1;
}
std::cout << "Revealing, please wait..." << std::endl;
uint32_t x_max, y_max, z_max;
DFHack::designations40d designations;
Maps->getSize(x_max,y_max,z_max);
std::vector <hideblock> hidesaved;
for(uint32_t x = 0; x< x_max;x++)
{
for(uint32_t y = 0; y< y_max;y++)
{
for(uint32_t z = 0; z< z_max;z++)
{
if(Maps->isValidBlock(x,y,z))
{
hideblock hb;
hb.x = x;
hb.y = y;
hb.z = z;
// read block designations
Maps->ReadDesignations(x,y,z, &designations);
// change the hidden flag to 0
for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
{
hb.hiddens[i][j] = designations[i][j].bits.hidden;
designations[i][j].bits.hidden = 0;
}
hidesaved.push_back(hb);
// write the designations back
Maps->WriteDesignations(x,y,z, &designations);
}
}
}
}
World->SetPauseState(true);
c->Resume();
std::cout << "Map revealed. The game has been paused for you." << std::endl;
std::cout << "Unpausing can unleash the forces of hell!" << std::endl;
std::cout << "Saving will make this state permanent. Don't do it." << std::endl << std::endl;
std::cout << "Press any key to unreveal." << std::endl;
std::cin.ignore();
std::cout << "Unrevealing... please wait." << std::endl;
// FIXME: do some consistency checks here!
c->Suspend();
Maps = c->getMaps();
Maps->Start();
for(size_t i = 0; i < hidesaved.size();i++)
{
hideblock & hb = hidesaved[i];
Maps->ReadDesignations(hb.x,hb.y,hb.z, &designations);
for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
{
designations[i][j].bits.hidden = hb.hiddens[i][j];
}
Maps->WriteDesignations(hb.x,hb.y,hb.z, &designations);
}
c->Resume();
return 0;
}