cleaning up in needs_porting
Removed obsolete plugins. Started hotkeys port. Mostly-finished position port. Corrected dwarfmonitor date display. Documented putontable.lua in readme.develop
parent
8e6fcac92e
commit
f3826abc0c
@ -1,543 +0,0 @@
|
|||||||
#ifndef SEGMENTED_FINDER_H
|
|
||||||
#define SEGMENTED_FINDER_H
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <iosfwd>
|
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
class SegmentedFinder;
|
|
||||||
class SegmentFinder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SegmentFinder(DFHack::t_memrange & mr, DFHack::Context * DF, SegmentedFinder * SF)
|
|
||||||
{
|
|
||||||
_DF = DF;
|
|
||||||
mr_ = mr;
|
|
||||||
valid=false;
|
|
||||||
if(mr.valid)
|
|
||||||
{
|
|
||||||
mr_.buffer = (uint8_t *)malloc (mr_.end - mr_.start);
|
|
||||||
_SF = SF;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DF->ReadRaw(mr_.start,(mr_.end - mr_.start),mr_.buffer);
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
catch (DFHack::Error::MemoryAccessDenied &)
|
|
||||||
{
|
|
||||||
free(mr_.buffer);
|
|
||||||
valid = false;
|
|
||||||
mr.valid = false; // mark the range passed in as bad
|
|
||||||
cout << "Range 0x" << hex << mr_.start << " - 0x" << mr_.end;
|
|
||||||
|
|
||||||
if (strlen(mr_.name) != 0)
|
|
||||||
cout << " (" << mr_.name << ")";
|
|
||||||
|
|
||||||
cout << dec << " not readable." << endl;
|
|
||||||
cout << "Skipping this range on future scans." << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~SegmentFinder()
|
|
||||||
{
|
|
||||||
if(valid)
|
|
||||||
free(mr_.buffer);
|
|
||||||
}
|
|
||||||
bool isValid()
|
|
||||||
{
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
template <class needleType, class hayType, typename comparator >
|
|
||||||
bool Find (needleType needle, const uint8_t increment , vector <uint64_t> &newfound, comparator oper)
|
|
||||||
{
|
|
||||||
if(!valid) return !newfound.empty();
|
|
||||||
//loop
|
|
||||||
for(uint64_t offset = 0; offset < (mr_.end - mr_.start) - sizeof(hayType); offset += increment)
|
|
||||||
{
|
|
||||||
if( oper(_SF,(hayType *)(mr_.buffer + offset), needle) )
|
|
||||||
newfound.push_back(mr_.start + offset);
|
|
||||||
}
|
|
||||||
return !newfound.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
template < class needleType, class hayType, typename comparator >
|
|
||||||
uint64_t FindInRange (needleType needle, comparator oper, uint64_t start, uint64_t length)
|
|
||||||
{
|
|
||||||
if(!valid) return 0;
|
|
||||||
uint64_t stopper = min((mr_.end - mr_.start) - sizeof(hayType), (start - mr_.start) - sizeof(hayType) + length);
|
|
||||||
//loop
|
|
||||||
for(uint64_t offset = start - mr_.start; offset < stopper; offset +=1)
|
|
||||||
{
|
|
||||||
if( oper(_SF,(hayType *)(mr_.buffer + offset), needle) )
|
|
||||||
return mr_.start + offset;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class needleType, class hayType, typename comparator >
|
|
||||||
bool Filter (needleType needle, vector <uint64_t> &found, vector <uint64_t> &newfound, comparator oper)
|
|
||||||
{
|
|
||||||
if(!valid) return !newfound.empty();
|
|
||||||
for( uint64_t i = 0; i < found.size(); i++)
|
|
||||||
{
|
|
||||||
if(mr_.isInRange(found[i]))
|
|
||||||
{
|
|
||||||
uint64_t corrected = found[i] - mr_.start;
|
|
||||||
if( oper(_SF,(hayType *)(mr_.buffer + corrected), needle) )
|
|
||||||
newfound.push_back(found[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return !newfound.empty();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
friend class SegmentedFinder;
|
|
||||||
SegmentedFinder * _SF;
|
|
||||||
DFHack::Context * _DF;
|
|
||||||
DFHack::t_memrange mr_;
|
|
||||||
bool valid;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SegmentedFinder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SegmentedFinder(vector <DFHack::t_memrange>& ranges, DFHack::Context * DF)
|
|
||||||
{
|
|
||||||
_DF = DF;
|
|
||||||
for(size_t i = 0; i < ranges.size(); i++)
|
|
||||||
{
|
|
||||||
segments.push_back(new SegmentFinder(ranges[i], DF, this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~SegmentedFinder()
|
|
||||||
{
|
|
||||||
for(size_t i = 0; i < segments.size(); i++)
|
|
||||||
{
|
|
||||||
delete segments[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SegmentFinder * getSegmentForAddress (uint64_t addr)
|
|
||||||
{
|
|
||||||
for(size_t i = 0; i < segments.size(); i++)
|
|
||||||
{
|
|
||||||
if(segments[i]->mr_.isInRange(addr))
|
|
||||||
{
|
|
||||||
return segments[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
template <class needleType, class hayType, typename comparator >
|
|
||||||
bool Find (const needleType needle, const uint8_t increment, vector <uint64_t> &found, comparator oper)
|
|
||||||
{
|
|
||||||
found.clear();
|
|
||||||
for(size_t i = 0; i < segments.size(); i++)
|
|
||||||
{
|
|
||||||
segments[i]->Find<needleType,hayType,comparator>(needle, increment, found, oper);
|
|
||||||
}
|
|
||||||
return !(found.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
template < class needleType, class hayType, typename comparator >
|
|
||||||
uint64_t FindInRange (needleType needle, comparator oper, uint64_t start, uint64_t length)
|
|
||||||
{
|
|
||||||
SegmentFinder * sf = getSegmentForAddress(start);
|
|
||||||
if(sf)
|
|
||||||
{
|
|
||||||
return sf->FindInRange<needleType,hayType,comparator>(needle, oper, start, length);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class needleType, class hayType, typename comparator >
|
|
||||||
bool Filter (const needleType needle, vector <uint64_t> &found, comparator oper)
|
|
||||||
{
|
|
||||||
vector <uint64_t> newfound;
|
|
||||||
for(size_t i = 0; i < segments.size(); i++)
|
|
||||||
{
|
|
||||||
segments[i]->Filter<needleType,hayType,comparator>(needle, found, newfound, oper);
|
|
||||||
}
|
|
||||||
found.clear();
|
|
||||||
found = newfound;
|
|
||||||
return !(found.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class needleType, class hayType, typename comparator >
|
|
||||||
bool Incremental (needleType needle, const uint8_t increment ,vector <uint64_t> &found, comparator oper)
|
|
||||||
{
|
|
||||||
if(found.empty())
|
|
||||||
{
|
|
||||||
return Find <needleType, hayType, comparator>(needle,increment,found,oper);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Filter <needleType, hayType, comparator>(needle,found,oper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T * Translate(uint64_t address)
|
|
||||||
{
|
|
||||||
for(size_t i = 0; i < segments.size(); i++)
|
|
||||||
{
|
|
||||||
if(segments[i]->mr_.isInRange(address))
|
|
||||||
{
|
|
||||||
return (T *) (segments[i]->mr_.buffer + address - segments[i]->mr_.start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T Read(uint64_t address)
|
|
||||||
{
|
|
||||||
return *Translate<T>(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool Read(uint64_t address, T& target)
|
|
||||||
{
|
|
||||||
T * test = Translate<T>(address);
|
|
||||||
if(test)
|
|
||||||
{
|
|
||||||
target = *test;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
DFHack::Context * _DF;
|
|
||||||
vector <SegmentFinder *> segments;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool equalityP (SegmentedFinder* s, T *x, T y)
|
|
||||||
{
|
|
||||||
return (*x) == y;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct vecTriplet
|
|
||||||
{
|
|
||||||
uint32_t start;
|
|
||||||
uint32_t finish;
|
|
||||||
uint32_t alloc_finish;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Needle>
|
|
||||||
bool vectorLength (SegmentedFinder* s, vecTriplet *x, Needle &y)
|
|
||||||
{
|
|
||||||
if(x->start <= x->finish && x->finish <= x->alloc_finish)
|
|
||||||
if((x->finish - x->start) == y)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find a vector of 32bit pointers, where an object pointed to has a string 'y' as the first member
|
|
||||||
bool vectorString (SegmentedFinder* s, vecTriplet *x, const char *y)
|
|
||||||
{
|
|
||||||
uint32_t object_ptr;
|
|
||||||
// iterate over vector of pointers
|
|
||||||
for(uint32_t idx = x->start; idx < x->finish; idx += sizeof(uint32_t))
|
|
||||||
{
|
|
||||||
// deref ptr idx, get ptr to object
|
|
||||||
if(!s->Read(idx,object_ptr))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// deref ptr to first object, get ptr to string
|
|
||||||
uint32_t string_ptr;
|
|
||||||
if(!s->Read(object_ptr,string_ptr))
|
|
||||||
return false;
|
|
||||||
// get string location in our local cache
|
|
||||||
char * str = s->Translate<char>(string_ptr);
|
|
||||||
if(!str)
|
|
||||||
return false;
|
|
||||||
if(strcmp(y, str) == 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find a vector of 32bit pointers, where the first object pointed to has a string 'y' as the first member
|
|
||||||
bool vectorStringFirst (SegmentedFinder* s, vecTriplet *x, const char *y)
|
|
||||||
{
|
|
||||||
uint32_t object_ptr;
|
|
||||||
uint32_t idx = x->start;
|
|
||||||
// deref ptr idx, get ptr to object
|
|
||||||
if(!s->Read(idx,object_ptr))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// deref ptr to first object, get ptr to string
|
|
||||||
uint32_t string_ptr;
|
|
||||||
if(!s->Read(object_ptr,string_ptr))
|
|
||||||
return false;
|
|
||||||
// get string location in our local cache
|
|
||||||
char * str = s->Translate<char>(string_ptr);
|
|
||||||
if(!str)
|
|
||||||
return false;
|
|
||||||
if(strcmp(y, str) == 0)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// test if the address is between vector.start and vector.finish
|
|
||||||
// not very useful alone, but could be a good step to filter some things
|
|
||||||
bool vectorAddrWithin (SegmentedFinder* s, vecTriplet *x, uint32_t address)
|
|
||||||
{
|
|
||||||
if(address < x->finish && address >= x->start)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// test if an object address is within the vector of pointers
|
|
||||||
//
|
|
||||||
bool vectorOfPtrWithin (SegmentedFinder* s, vecTriplet *x, uint32_t address)
|
|
||||||
{
|
|
||||||
uint32_t object_ptr;
|
|
||||||
for(uint32_t idx = x->start; idx < x->finish; idx += sizeof(uint32_t))
|
|
||||||
{
|
|
||||||
if(!s->Read(idx,object_ptr))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(object_ptr == address)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool vectorAll (SegmentedFinder* s, vecTriplet *x, int )
|
|
||||||
{
|
|
||||||
if(x->start <= x->finish && x->finish <= x->alloc_finish)
|
|
||||||
{
|
|
||||||
if(s->getSegmentForAddress(x->start) == s->getSegmentForAddress(x->finish)
|
|
||||||
&& s->getSegmentForAddress(x->finish) == s->getSegmentForAddress(x->alloc_finish))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Bytestreamdata
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void * object;
|
|
||||||
uint32_t length;
|
|
||||||
uint32_t allocated;
|
|
||||||
uint32_t n_used;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Bytestream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Bytestream(void * obj, uint32_t len, bool alloc = false)
|
|
||||||
{
|
|
||||||
d = new Bytestreamdata();
|
|
||||||
d->allocated = alloc;
|
|
||||||
d->object = obj;
|
|
||||||
d->length = len;
|
|
||||||
d->n_used = 1;
|
|
||||||
constant = false;
|
|
||||||
}
|
|
||||||
Bytestream()
|
|
||||||
{
|
|
||||||
d = new Bytestreamdata();
|
|
||||||
d->allocated = false;
|
|
||||||
d->object = 0;
|
|
||||||
d->length = 0;
|
|
||||||
d->n_used = 1;
|
|
||||||
constant = false;
|
|
||||||
}
|
|
||||||
Bytestream( Bytestream & bs)
|
|
||||||
{
|
|
||||||
d =bs.d;
|
|
||||||
d->n_used++;
|
|
||||||
constant = false;
|
|
||||||
}
|
|
||||||
Bytestream( const Bytestream & bs)
|
|
||||||
{
|
|
||||||
d =bs.d;
|
|
||||||
d->n_used++;
|
|
||||||
constant = true;
|
|
||||||
}
|
|
||||||
~Bytestream()
|
|
||||||
{
|
|
||||||
d->n_used --;
|
|
||||||
if(d->allocated && d->object && d->n_used == 0)
|
|
||||||
{
|
|
||||||
free (d->object);
|
|
||||||
free (d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool Allocate(size_t bytes)
|
|
||||||
{
|
|
||||||
if(constant)
|
|
||||||
return false;
|
|
||||||
if(d->allocated)
|
|
||||||
{
|
|
||||||
d->object = realloc(d->object, bytes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->object = malloc( bytes );
|
|
||||||
}
|
|
||||||
|
|
||||||
if(d->object)
|
|
||||||
{
|
|
||||||
d->allocated = bytes;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->allocated = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template < class T >
|
|
||||||
bool insert( T what )
|
|
||||||
{
|
|
||||||
if(constant)
|
|
||||||
return false;
|
|
||||||
if(d->length+sizeof(T) >= d->allocated)
|
|
||||||
Allocate((d->length+sizeof(T)) * 2);
|
|
||||||
(*(T *)( (uint64_t)d->object + d->length)) = what;
|
|
||||||
d->length += sizeof(T);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Bytestreamdata * d;
|
|
||||||
bool constant;
|
|
||||||
};
|
|
||||||
std::ostream& operator<< ( std::ostream& out, Bytestream& bs )
|
|
||||||
{
|
|
||||||
if(bs.d->object)
|
|
||||||
{
|
|
||||||
out << "bytestream " << dec << bs.d->length << "/" << bs.d->allocated << " bytes" << endl;
|
|
||||||
for(size_t i = 0; i < bs.d->length; i++)
|
|
||||||
{
|
|
||||||
out << hex << (int) ((uint8_t *) bs.d->object)[i] << " ";
|
|
||||||
}
|
|
||||||
out << endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
out << "empty bytestresm" << endl;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::istream& operator>> ( std::istream& out, Bytestream& bs )
|
|
||||||
{
|
|
||||||
string read;
|
|
||||||
while(!out.eof())
|
|
||||||
{
|
|
||||||
string tmp;
|
|
||||||
out >> tmp;
|
|
||||||
read.append(tmp);
|
|
||||||
}
|
|
||||||
cout << read << endl;
|
|
||||||
bs.d->length = 0;
|
|
||||||
size_t first = read.find_first_of("\"");
|
|
||||||
size_t last = read.find_last_of("\"");
|
|
||||||
size_t start = first + 1;
|
|
||||||
if(first == read.npos)
|
|
||||||
{
|
|
||||||
std::transform(read.begin(), read.end(), read.begin(), (int(*)(int)) tolower);
|
|
||||||
bs.Allocate(read.size()); // overkill. size / 2 should be good, but this is safe
|
|
||||||
int state = 0;
|
|
||||||
char big = 0;
|
|
||||||
char small = 0;
|
|
||||||
string::iterator it = read.begin();
|
|
||||||
// iterate through string, construct a bytestream out of 00-FF bytes
|
|
||||||
while(it != read.end())
|
|
||||||
{
|
|
||||||
char reads = *it;
|
|
||||||
if((reads >='0' && reads <= '9'))
|
|
||||||
{
|
|
||||||
if(state == 0)
|
|
||||||
{
|
|
||||||
big = reads - '0';
|
|
||||||
state = 1;
|
|
||||||
}
|
|
||||||
else if(state == 1)
|
|
||||||
{
|
|
||||||
small = reads - '0';
|
|
||||||
state = 0;
|
|
||||||
bs.insert<char>(big*16 + small);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if((reads >= 'a' && reads <= 'f'))
|
|
||||||
{
|
|
||||||
if(state == 0)
|
|
||||||
{
|
|
||||||
big = reads - 'a' + 10;
|
|
||||||
state = 1;
|
|
||||||
}
|
|
||||||
else if(state == 1)
|
|
||||||
{
|
|
||||||
small = reads - 'a' + 10;
|
|
||||||
state = 0;
|
|
||||||
bs.insert<char>(big*16 + small);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
// we end in state= 1. should we add or should we trim... or throw errors?
|
|
||||||
// I decided on adding
|
|
||||||
if (state == 1)
|
|
||||||
{
|
|
||||||
small = 0;
|
|
||||||
bs.insert<char>(big*16 + small);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(last == first)
|
|
||||||
{
|
|
||||||
// only one "
|
|
||||||
last = read.size();
|
|
||||||
}
|
|
||||||
size_t length = last - start;
|
|
||||||
// construct bytestream out of stuff between ""
|
|
||||||
bs.d->length = length;
|
|
||||||
if(length)
|
|
||||||
{
|
|
||||||
// todo: Bytestream should be able to handle this without external code
|
|
||||||
bs.Allocate(length);
|
|
||||||
bs.d->length = length;
|
|
||||||
const char* strstart = read.c_str();
|
|
||||||
memcpy(bs.d->object, strstart + start, length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bs.d->object = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cout << bs;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool findBytestream (SegmentedFinder* s, void *addr, Bytestream compare )
|
|
||||||
{
|
|
||||||
if(memcmp(addr, compare.d->object, compare.d->length) == 0)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool findString (SegmentedFinder* s, uint32_t *addr, const char * compare )
|
|
||||||
{
|
|
||||||
// read string pointer, translate to local scheme
|
|
||||||
char *str = s->Translate<char>(*addr);
|
|
||||||
// verify
|
|
||||||
if(!str)
|
|
||||||
return false;
|
|
||||||
if(strcmp(str, compare) == 0)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool findStrBuffer (SegmentedFinder* s, uint32_t *addr, const char * compare )
|
|
||||||
{
|
|
||||||
if(memcmp((const char *)addr, compare, strlen(compare)) == 0)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SEGMENTED_FINDER_H
|
|
@ -1,30 +1,13 @@
|
|||||||
Notes by PeridexisErrant, on the needs_porting scripts and plugins:
|
TODO:
|
||||||
|
copypaste.cpp
|
||||||
I deleted:
|
high value target - a proof of concept plugin to allow copy-pasting in DF; does both terrain and buildings/constructions
|
||||||
attachtest.py obsolete
|
creaturemanager.cpp
|
||||||
digger.cpp less useful than digger2, replaced by autochop
|
modify skills and labors of creatures, kill creatures, etc; impressive but I suspect most functions implemented elsewhere
|
||||||
digger2.cpp replaced by digfort
|
dfbauxtite.cpp
|
||||||
dfstatus.cpp replaced by dfstatus.lua
|
changes material of mechanisms to bauxtite (ie magma-safe)
|
||||||
drawtile.cpp replaced by tiletypes
|
hellhole.cpp
|
||||||
fix-3708.cpp obsolete, bug fixed in vanilla
|
instantly creates a hole to the HFS
|
||||||
lair.cpp replaced by lair
|
|
||||||
reveal.py replaced by reveal
|
In progress:
|
||||||
treedump.py replaced by prospect & autochop
|
hotkey-notes.lua
|
||||||
veinlook.cpp replaced by prospect
|
prints list of hotkeys with name and jump position
|
||||||
veinswap.cpp replaced by changevein
|
|
||||||
|
|
||||||
|
|
||||||
To investigate further:
|
|
||||||
creaturemanager.cpp modify skills and labors of creatures, kill creatures, etc; impressive but I suspect most functions implemented elsewhere
|
|
||||||
digpattern.cpp allows multi-Z designations. Obsolete, or is there more here?
|
|
||||||
incrementalsearch.cpp linux-only memory stuff; unqualified to judge
|
|
||||||
SegementedFinder.h more memory stuff
|
|
||||||
|
|
||||||
|
|
||||||
To port:
|
|
||||||
copypaste.cpp high value target - a proof of concept plugin to allow copy-pasting in DF; does both terrain and buildings/constructions
|
|
||||||
dfbauxtite.cpp changes material of mechanisms to bauxtite (ie magma-safe)
|
|
||||||
hellhole.cpp instantly creates a hole to the HFS
|
|
||||||
hotkeynotedump.py outputs a list of hotkeys and names; most useful before keybindings were possible. Trival to port but low value.
|
|
||||||
itemdesignator.cpp mostly replaced by Falconne's enhanced stocks, but could port the interesting 'set fire to things' function
|
|
||||||
position.py outputs very detailed time& place info
|
|
||||||
|
@ -1,259 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <string.h> // for memset
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <stack>
|
|
||||||
#include <map>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <cstdlib>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include <DFHack.h>
|
|
||||||
#include <extra/MapExtras.h>
|
|
||||||
using namespace MapExtras;
|
|
||||||
//#include <argstream.h>
|
|
||||||
|
|
||||||
void usage(int argc, const char * argv[])
|
|
||||||
{
|
|
||||||
cout
|
|
||||||
<< "Usage:" << endl
|
|
||||||
<< argv[0] << " [option 1] [option 2] [...]" << endl
|
|
||||||
<< "-q : Suppress \"Press any key to continue\" at program termination" << endl
|
|
||||||
<< "-u <n> : Dig upwards <n> times (default 5)" << endl
|
|
||||||
<< "-d <n> : Dig downwards <n> times (default 5)" << endl
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void digat(MapCache * MCache, DFHack::DFCoord xy)
|
|
||||||
{
|
|
||||||
int16_t tt;
|
|
||||||
tt = MCache->tiletypeAt(xy);
|
|
||||||
if(!DFHack::isWallTerrain(tt))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// found a good tile, dig+unset material
|
|
||||||
DFHack::t_designation des = MCache->designationAt(xy);
|
|
||||||
|
|
||||||
if(MCache->testCoord(xy))
|
|
||||||
{
|
|
||||||
MCache->clearMaterialAt(xy);
|
|
||||||
|
|
||||||
if(des.bits.dig == DFHack::designation_no)
|
|
||||||
des.bits.dig = DFHack::designation_default;
|
|
||||||
MCache->setDesignationAt(xy,des);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int strtoint(const string &str)
|
|
||||||
{
|
|
||||||
stringstream ss(str);
|
|
||||||
int result;
|
|
||||||
return ss >> result ? result : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int16_t x;
|
|
||||||
int16_t y;
|
|
||||||
} pos;
|
|
||||||
|
|
||||||
int main (int argc, const char* argv[])
|
|
||||||
{
|
|
||||||
// Command line options
|
|
||||||
bool updown = false;
|
|
||||||
bool quiet = true;
|
|
||||||
// let's be more useful when double-clicked on windows
|
|
||||||
#ifndef LINUX_BUILD
|
|
||||||
quiet = false;
|
|
||||||
#endif
|
|
||||||
int dig_up_n = 5;
|
|
||||||
int dig_down_n = 5;
|
|
||||||
|
|
||||||
for(int i = 1; i < argc; i++)
|
|
||||||
{
|
|
||||||
string arg_cur = argv[i];
|
|
||||||
string arg_next = "";
|
|
||||||
int arg_next_int = -99999;
|
|
||||||
/* Check if argv[i+1] is a number >= 0 */
|
|
||||||
if (i < argc-1) {
|
|
||||||
arg_next = argv[i+1];
|
|
||||||
arg_next_int = strtoint(arg_next);
|
|
||||||
if (arg_next != "0" && arg_next_int == 0) {
|
|
||||||
arg_next_int = -99999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (arg_cur == "-x")
|
|
||||||
{
|
|
||||||
updown = true;
|
|
||||||
}
|
|
||||||
else if (arg_cur == "-q")
|
|
||||||
{
|
|
||||||
quiet = true;
|
|
||||||
}
|
|
||||||
else if(arg_cur == "-u" && i < argc-1)
|
|
||||||
{
|
|
||||||
if (arg_next_int < 0 || arg_next_int >= 99999) {
|
|
||||||
usage(argc, argv);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
dig_up_n = arg_next_int;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else if(arg_cur == "-d" && i < argc-1)
|
|
||||||
{
|
|
||||||
if (arg_next_int < 0 || arg_next_int >= 99999) {
|
|
||||||
usage(argc, argv);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
dig_down_n = arg_next_int;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
usage(argc, argv);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DFHack::ContextManager DFMgr("Memory.xml");
|
|
||||||
DFHack::Context * DF;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DF = DFMgr.getSingleContext();
|
|
||||||
DF->Attach();
|
|
||||||
}
|
|
||||||
catch (exception& e)
|
|
||||||
{
|
|
||||||
cerr << "Error getting context: " << e.what() << endl;
|
|
||||||
if (!quiet)
|
|
||||||
cin.ignore();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t x_max,y_max,z_max;
|
|
||||||
DFHack::Maps * Maps = DF->getMaps();
|
|
||||||
DFHack::Gui * Gui = DF->getGui();
|
|
||||||
|
|
||||||
// init the map
|
|
||||||
if(!Maps->Start())
|
|
||||||
{
|
|
||||||
cerr << "Can't init map. Make sure you have a map loaded in DF." << endl;
|
|
||||||
DF->Detach();
|
|
||||||
if (!quiet)
|
|
||||||
cin.ignore();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t cx, cy, cz;
|
|
||||||
Maps->getSize(x_max,y_max,z_max);
|
|
||||||
uint32_t tx_max = x_max * 16;
|
|
||||||
uint32_t ty_max = y_max * 16;
|
|
||||||
|
|
||||||
Gui->getCursorCoords(cx,cy,cz);
|
|
||||||
if (cx == -30000)
|
|
||||||
{
|
|
||||||
cerr << "Cursor is not active. Point the cursor at the position to dig at." << endl;
|
|
||||||
DF->Detach();
|
|
||||||
if (!quiet)
|
|
||||||
{
|
|
||||||
cin.ignore();
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
|
|
||||||
if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1)
|
|
||||||
{
|
|
||||||
cerr << "I won't dig the borders. That would be cheating!" << endl;
|
|
||||||
DF->Detach();
|
|
||||||
if (!quiet)
|
|
||||||
{
|
|
||||||
cin.ignore();
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
MapCache * MCache = new MapCache(Maps);
|
|
||||||
|
|
||||||
DFHack::t_designation des = MCache->designationAt(xy);
|
|
||||||
int16_t tt = MCache->tiletypeAt(xy);
|
|
||||||
int16_t veinmat = MCache->veinMaterialAt(xy);
|
|
||||||
|
|
||||||
/*
|
|
||||||
if( veinmat == -1 )
|
|
||||||
{
|
|
||||||
cerr << "This tile is non-vein. Bye :)" << endl;
|
|
||||||
delete MCache;
|
|
||||||
DF->Detach();
|
|
||||||
if (!quiet) {
|
|
||||||
cin.ignore();
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
printf("Digging at (%d/%d/%d), tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole);
|
|
||||||
|
|
||||||
// 1 < xy.x < tx_max - 1
|
|
||||||
// 1 < xy.y < ty_max - 1
|
|
||||||
// xy.z
|
|
||||||
|
|
||||||
// X____
|
|
||||||
// X_XXX
|
|
||||||
// XXXXX
|
|
||||||
// __XXX
|
|
||||||
// __XXX
|
|
||||||
// _____
|
|
||||||
pos map[] =
|
|
||||||
{
|
|
||||||
{ 0,0 }
|
|
||||||
, { 0,1 }
|
|
||||||
, { 0,2 } , { 2,2 }, { 3,2 }, { 4,2 }
|
|
||||||
, { 0,3 }, { 1,3 }, { 2,3 }, { 3,3 }, { 4,3 }
|
|
||||||
, { 2,4 }, { 3,4 }, { 4,4 }
|
|
||||||
// this is mirrored, goes left instead of right
|
|
||||||
, {-2,2 }, {-3,2 }, {-4,2 }
|
|
||||||
, {-1,3 }, {-2,3 }, {-3,3 }, {-4,3 }
|
|
||||||
, {-2,4 }, {-3,4 }, {-4,4 }
|
|
||||||
};
|
|
||||||
|
|
||||||
DFHack::DFCoord npos = xy;
|
|
||||||
|
|
||||||
if (dig_up_n > 0)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < dig_up_n; j++)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < sizeof(map)/sizeof(map[0]); i++)
|
|
||||||
{
|
|
||||||
npos=xy;
|
|
||||||
npos.x += map[i].x;
|
|
||||||
npos.y -= 4*j + map[i].y;
|
|
||||||
printf("Digging at (%d/%d/%d)\n", npos.x, npos.y, npos.z);
|
|
||||||
digat(MCache, npos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dig_down_n > 0)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < dig_down_n; j++)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < sizeof(map)/sizeof(map[0]); i++)
|
|
||||||
{
|
|
||||||
npos=xy;
|
|
||||||
npos.x += map[i].x;
|
|
||||||
npos.y += 4*j + map[i].y;
|
|
||||||
printf("Digging at (%d/%d/%d)\n", npos.x, npos.y, npos.z);
|
|
||||||
digat(MCache, npos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MCache->WriteAll();
|
|
||||||
delete MCache;
|
|
||||||
DF->Detach();
|
|
||||||
if (!quiet) {
|
|
||||||
cout << "Done. Press any key to continue" << endl;
|
|
||||||
cin.ignore();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -0,0 +1,40 @@
|
|||||||
|
-- prints info on assigned hotkeys to the console
|
||||||
|
|
||||||
|
local hotkeys = {'F1 ', 'F2 ', 'F3 ', 'F4 ', 'F5 ', 'F6 ',
|
||||||
|
'F7 ', 'F8 ', 'F9 ', 'F10', 'F11', 'F12'}
|
||||||
|
|
||||||
|
for i=1, #hotkeys do
|
||||||
|
local hk = hotkeys[i]
|
||||||
|
hk = {id=hk}
|
||||||
|
-- PLACEHOLDER PROPERTIES ONLY!
|
||||||
|
hk.name = '_name'
|
||||||
|
hk.x = df.global.window_x
|
||||||
|
hk.y = df.global.window_y
|
||||||
|
hk.z = df.global.window_z
|
||||||
|
|
||||||
|
print(hk.id..' '..hk.name..' X= '..hk.x..', Y= '..hk.y..', Z= '..hk.z)
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
# the (very) old Python version...
|
||||||
|
from context import Context, ContextManager
|
||||||
|
|
||||||
|
cm = ContextManager("Memory.xml")
|
||||||
|
df = cm.get_single_context()
|
||||||
|
|
||||||
|
df.attach()
|
||||||
|
|
||||||
|
gui = df.gui
|
||||||
|
|
||||||
|
print "Hotkeys"
|
||||||
|
|
||||||
|
hotkeys = gui.read_hotkeys()
|
||||||
|
|
||||||
|
for key in hotkeys:
|
||||||
|
print "x: %d\ny: %d\tz: %d\ttext: %s" % (key.x, key.y, key.z, key.name)
|
||||||
|
|
||||||
|
df.detach()
|
||||||
|
|
||||||
|
print "Done. Press any key to continue"
|
||||||
|
raw_input()
|
||||||
|
]]--
|
@ -1,20 +0,0 @@
|
|||||||
from context import Context, ContextManager
|
|
||||||
|
|
||||||
cm = ContextManager("Memory.xml")
|
|
||||||
df = cm.get_single_context()
|
|
||||||
|
|
||||||
df.attach()
|
|
||||||
|
|
||||||
gui = df.gui
|
|
||||||
|
|
||||||
print "Hotkeys"
|
|
||||||
|
|
||||||
hotkeys = gui.read_hotkeys()
|
|
||||||
|
|
||||||
for key in hotkeys:
|
|
||||||
print "x: %d\ny: %d\tz: %d\ttext: %s" % (key.x, key.y, key.z, key.name)
|
|
||||||
|
|
||||||
df.detach()
|
|
||||||
|
|
||||||
print "Done. Press any key to continue"
|
|
||||||
raw_input()
|
|
File diff suppressed because it is too large
Load Diff
@ -1,71 +0,0 @@
|
|||||||
import sys
|
|
||||||
from pydfhack import ContextManager
|
|
||||||
|
|
||||||
df_cm = ContextManager("Memory.xml")
|
|
||||||
df = df_cm.get_single_context()
|
|
||||||
|
|
||||||
if not df.attach():
|
|
||||||
print "Unable to attach!"
|
|
||||||
print "Press any key to continue"
|
|
||||||
|
|
||||||
raw_input()
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
gui = df.gui
|
|
||||||
|
|
||||||
if gui is not None:
|
|
||||||
maps = df.maps
|
|
||||||
world = df.world
|
|
||||||
|
|
||||||
have_maps = maps.start()
|
|
||||||
world.start()
|
|
||||||
|
|
||||||
gm = world.read_game_mode()
|
|
||||||
|
|
||||||
if gm is not None:
|
|
||||||
print gm
|
|
||||||
|
|
||||||
date_tuple = (world.read_current_year(), world.read_current_month(), world.read_current_day(), world.read_current_tick())
|
|
||||||
|
|
||||||
print "Year: %d Month: %d Day: %d Tick: %d" % date_tuple
|
|
||||||
|
|
||||||
v_coords = gui.get_view_coords()
|
|
||||||
c_coords = gui.get_cursor_coords()
|
|
||||||
w_coords = (-1, -1, -1)
|
|
||||||
world_pos_string = ""
|
|
||||||
|
|
||||||
if have_maps is True:
|
|
||||||
w_coords = maps.getPosition()
|
|
||||||
|
|
||||||
x = (v_coords[0] + w_coords[0]) * 48
|
|
||||||
y = (v_coords[1] + w_coords[1]) * 48
|
|
||||||
z = (v_coords[2] + w_coords[2])
|
|
||||||
|
|
||||||
world_pos_string = " world: %d/%d/%d" % (x, y, z)
|
|
||||||
|
|
||||||
print "Map world offset: %d/%d/%d embark squares" % w_coords
|
|
||||||
|
|
||||||
if v_coords != (-1, -1, -1):
|
|
||||||
print "view coords: %d/%d/%d" % v_coords
|
|
||||||
|
|
||||||
if have_maps is True:
|
|
||||||
print world_pos_string
|
|
||||||
|
|
||||||
if c_coords != (-1, -1, -1):
|
|
||||||
print "cursor coords: %d/%d/%d" % c_coords
|
|
||||||
|
|
||||||
if have_maps is True:
|
|
||||||
print world_pos_string
|
|
||||||
|
|
||||||
window_size = gui.get_window_size()
|
|
||||||
|
|
||||||
if window_size != (-1, -1):
|
|
||||||
print "window size : %d %d" % window_size
|
|
||||||
else:
|
|
||||||
print "cursor and window parameters are unsupported on your version of DF"
|
|
||||||
|
|
||||||
if not df.detach():
|
|
||||||
print "Unable to detach!"
|
|
||||||
|
|
||||||
print "Done. Press any key to continue"
|
|
||||||
raw_input()
|
|
@ -0,0 +1,40 @@
|
|||||||
|
--prints current time and position
|
||||||
|
|
||||||
|
local months = {
|
||||||
|
'Granite, in early Spring.',
|
||||||
|
'Slate, in mid Spring.',
|
||||||
|
'Felsite, in late Spring.',
|
||||||
|
'Hematite, in early Summer.',
|
||||||
|
'Malachite, in mid Summer.',
|
||||||
|
'Galena, in late Summer.',
|
||||||
|
'Limestone, in early Autumn.',
|
||||||
|
'Sandstone, in mid Autumn.',
|
||||||
|
'Timber, in late Autumn.',
|
||||||
|
'Moonstone, in early Winter.',
|
||||||
|
'Opal, in mid Winter.',
|
||||||
|
'Obsidian, in late Winter.',
|
||||||
|
}
|
||||||
|
|
||||||
|
--Fortress mode counts 1200 ticks per day and 403200 per year
|
||||||
|
--Adventurer mode counts 86400 ticks to a day and 29030400 ticks per year
|
||||||
|
--Twelve months per year, 28 days to every month, 336 days per year
|
||||||
|
|
||||||
|
local julian_day = math.floor(df.global.cur_year_tick / 1200) + 1
|
||||||
|
local month = math.floor(julian_day / 28) + 1 --days and months are 1-indexed
|
||||||
|
local day = julian_day % 28
|
||||||
|
|
||||||
|
local time_of_day = math.floor(df.global.cur_year_tick_advmode / 336)
|
||||||
|
local second = time_of_day % 60
|
||||||
|
local minute = (time_of_day / 60) % 60
|
||||||
|
local hour = math.floor(time_of_day / 3600) % 24
|
||||||
|
|
||||||
|
print('Time:')
|
||||||
|
print(' The time is '..string.format('%02d:%02d:%02d', hour, minute, second))
|
||||||
|
print(' The date is '..string.format('%05d-%02d-%02d', df.global.cur_year, month, day))
|
||||||
|
print(' It is the month of '..months[month])
|
||||||
|
|
||||||
|
print('Place:')
|
||||||
|
print(' Local window is at x='..df.global.window_x
|
||||||
|
..' y='..df.global.window_y..' z='..df.global.window_z)
|
||||||
|
|
||||||
|
--TODO: add cursor, regional/embark square co-ords, window size?
|
Loading…
Reference in New Issue