diff --git a/.gitignore b/.gitignore index 702a6490c..a19302fe4 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ build/CMakeCache.txt build/cmake_install.cmake build/CMakeFiles build/doc +build/lua build/bin build/library build/tools diff --git a/COMPILE.rst b/COMPILE.rst index 68e6a2175..ab6debd78 100644 --- a/COMPILE.rst +++ b/COMPILE.rst @@ -19,6 +19,9 @@ a 64-bit distribution like Arch, you'll need the multilib development tools and Before you can build anything, you'll also need ``cmake``. It is advisable to also get ``ccmake`` on distributions that split the cmake package into multiple parts. +For the code generation parts, you need perl and the XML::LibXML perl package. +You should be able to find them in your distro repositories (on Arch linux 'perl-xml-libxml'). + Build ===== Building is fairly straightforward. Enter the ``build`` folder and start the build like this:: @@ -51,9 +54,14 @@ site: http://www.cmake.org/cmake/resources/software.html It has the usual installer wizard. Make sure you let it add its binary folder to your binary search PATH so the tool can be later run from anywhere. -You'll also need a copy of Microsoft Visual C++ 2010. The Express version is sufficient. +You'll need a copy of Microsoft Visual C++ 2010. The Express version is sufficient. Grab it from Microsoft's site. +For the code generation parts, you'll need perl and XML::LibXML. You can install them like this: +* download and install strawberry perl from http://strawberryperl.com/ +* reboot so that the system can pick up the new binary path +* open a cmd.exe window and run "cpan XML::LibXML" (obviously without the quotes). This can take a while to complete. + Build ===== Open the ``build`` folder and double click the batch script there. This will eventually open diff --git a/Compile.html b/Compile.html index ec01686eb..95847f4f4 100644 --- a/Compile.html +++ b/Compile.html @@ -351,6 +351,8 @@ ul.auto-toc { a 64-bit distribution like Arch, you'll need the multilib development tools and libraries.

Before you can build anything, you'll also need cmake. It is advisable to also get ccmake on distributions that split the cmake package into multiple parts.

+

For the code generation parts, you need perl and the XML::LibXML perl package. +You should be able to find them in your distro repositories (on Arch linux 'perl-xml-libxml').

Build

@@ -380,8 +382,12 @@ program.

site: http://www.cmake.org/cmake/resources/software.html

It has the usual installer wizard. Make sure you let it add its binary folder to your binary search PATH so the tool can be later run from anywhere.

-

You'll also need a copy of Microsoft Visual C++ 2010. The Express version is sufficient. +

You'll need a copy of Microsoft Visual C++ 2010. The Express version is sufficient. Grab it from Microsoft's site.

+

For the code generation parts, you'll need perl and XML::LibXML. You can install them like this: +* download and install strawberry perl from http://strawberryperl.com/ +* reboot so that the system can pick up the new binary path +* open a cmd.exe window and run "cpan XML::LibXML" (obviously without the quotes). This can take a while to complete.

Build

Open the build folder and double click the batch script there. This will eventually open diff --git a/Memory.xml b/Memory.xml index 366dc48ba..b4f7ce1f3 100644 --- a/Memory.xml +++ b/Memory.xml @@ -1078,6 +1078,13 @@

+ +
+
+
+
+
+ @@ -2309,6 +2316,13 @@
+ +
+
+
+
+
+ cmake item vector: @@ -3174,6 +3188,13 @@
+ +
+
+
+
+
+ diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 195ffa6e1..9a87db9af 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -15,6 +15,10 @@ include_directories (depends/tinyxml) include_directories (depends/tthread) include_directories (private) +execute_process(COMMAND perl xml/list.pl xml include/dfhack/df ";" + WORKING_DIRECTORY ${dfapi_SOURCE_DIR} + OUTPUT_VARIABLE GENERATED_HDRS) + SET(PROJECT_HDRS_INTERNAL private/ContextShared.h private/Internal.h @@ -25,6 +29,7 @@ SET(PROJECT_HDRS include/DFHack.h include/dfhack/Console.h include/dfhack/Core.h +include/dfhack/DataDefs.h include/dfhack/Error.h include/dfhack/Export.h include/dfhack/FakeSDL.h @@ -60,6 +65,8 @@ include/dfhack/modules/Graphic.h SET(PROJECT_SRCS Core.cpp +DataDefs.cpp +DataStatics.cpp PluginManager.cpp TileTypes.cpp VersionInfo.cpp @@ -123,6 +130,24 @@ SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE ) LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS}) +# Generation + +SET_SOURCE_FILES_PROPERTIES(${GENERATED_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE GENERATED TRUE) + +FILE(GLOB GENERATE_INPUT_XMLS ${dfapi_SOURCE_DIR}/xml/*.xml) + +ADD_CUSTOM_COMMAND( + OUTPUT ${dfapi_SOURCE_DIR}/include/dfhack/df/static.inc + COMMAND perl xml/codegen.pl xml include/dfhack/df + WORKING_DIRECTORY ${dfapi_SOURCE_DIR} + MAIN_DEPENDENCY ${dfapi_SOURCE_DIR}/xml/codegen.pl + DEPENDS ${GENERATE_INPUT_XMLS} +) + +ADD_CUSTOM_TARGET(generate_headers DEPENDS ${dfapi_SOURCE_DIR}/include/dfhack/df/static.inc) + +# Compilation + ADD_DEFINITIONS(-DBUILD_DFHACK_LIB) IF(UNIX) @@ -142,6 +167,7 @@ ELSE(WIN32) ENDIF() ADD_LIBRARY(dfhack SHARED ${PROJECT_SRCS}) +ADD_DEPENDENCIES(dfhack generate_headers) IF(WIN32) SET_TARGET_PROPERTIES(dfhack PROPERTIES OUTPUT_NAME "SDL" ) diff --git a/library/Core.cpp b/library/Core.cpp index f218f2756..5296a057e 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -37,6 +37,7 @@ using namespace std; #include "dfhack/Error.h" #include "dfhack/Process.h" #include "dfhack/Core.h" +#include "dfhack/DataDefs.h" #include "dfhack/Console.h" #include "dfhack/Module.h" #include "dfhack/VersionInfoFactory.h" @@ -494,6 +495,10 @@ bool Core::Init() dump << vinfo->PrintOffsets(); dump.close(); } + + // initialize data defs + virtual_identity::Init(); + InitDataDefGlobals(this); // create mutex for syncing with interactive tasks StackMutex = new mutex(); diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp new file mode 100644 index 000000000..2f1f9c238 --- /dev/null +++ b/library/DataDefs.cpp @@ -0,0 +1,137 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "Internal.h" + +#include +#include +#include + +#include "dfhack/Process.h" +#include "dfhack/Core.h" +#include "dfhack/VersionInfo.h" +#include "tinythread.h" +// must be last due to MS stupidity +#include "dfhack/DataDefs.h" + +using namespace DFHack; + +/* The order of global object constructor calls is + * undefined between compilation units. Therefore, + * this list has to be plain data, so that it gets + * initialized by the loader in the initial mmap. + */ +virtual_identity *virtual_identity::list = NULL; + +virtual_identity::virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent) + : dfhack_name(dfhack_name), original_name(original_name), parent(parent), + prev(NULL), vtable_ptr(NULL), has_children(true) +{ + // Link into the static list. Nothing else can be safely done at this point. + next = list; list = this; +} + +/* Vtable to identity lookup. */ +static tthread::mutex *known_mutex = NULL; +std::map virtual_identity::known; + +virtual_identity *virtual_identity::get(virtual_ptr instance_ptr) +{ + if (!instance_ptr) return NULL; + + // Actually, a reader/writer lock would be sufficient, + // since the table is only written once per class. + tthread::lock_guard lock(*known_mutex); + + void *vtable = get_vtable(instance_ptr); + std::map::iterator it = known.find(vtable); + + if (it != known.end()) + return it->second; + + // If using a reader/writer lock, re-grab as write here, and recheck + Core &core = Core::getInstance(); + std::string name = core.p->doReadClassName(vtable); + + virtual_identity *actual = NULL; + + for (virtual_identity *p = list; p; p = p->next) { + if (strcmp(name.c_str(), p->getOriginalName()) != 0) continue; + known[vtable] = p; + p->vtable_ptr = vtable; + return p; + } + + known[vtable] = NULL; + return NULL; +} + +bool virtual_identity::check_instance(virtual_ptr instance_ptr, bool allow_subclasses) +{ + virtual_identity *actual = get(instance_ptr); + + if (actual == this) return true; + if (!allow_subclasses || !actual) return false; + + do { + actual = actual->parent; + if (actual == this) return true; + } while (actual); + + return false; +} + +void virtual_identity::Init() +{ + if (!known_mutex) + known_mutex = new tthread::mutex(); + + // This cannot be done in the constructors, because + // they are called in an undefined order. + for (virtual_identity *p = list; p; p = p->next) { + p->has_children = false; + p->children.clear(); + } + for (virtual_identity *p = list; p; p = p->next) { + if (p->parent) { + p->parent->children.push_back(p); + p->parent->has_children = true; + } + } +} + +#define GLOBAL(name,tname) \ + df::tname *df::global::name = NULL; +DF_KNOWN_GLOBALS +#undef GLOBAL + +void DFHack::InitDataDefGlobals(Core *core) { + OffsetGroup *global_table = core->vinfo->getGroup("global"); + uint32_t tmp; + +#define GLOBAL(name,tname) \ + if (global_table->getSafeAddress(#name,tmp)) df::global::name = (df::tname*)tmp; +DF_KNOWN_GLOBALS +#undef GLOBAL +} diff --git a/library/DataStatics.cpp b/library/DataStatics.cpp new file mode 100644 index 000000000..e3a448eac --- /dev/null +++ b/library/DataStatics.cpp @@ -0,0 +1,17 @@ +#include "Internal.h" +#include "dfhack/DataDefs.h" +#include "dfhack/MiscUtils.h" + +#include "dfhack/df/world.h" +#include "dfhack/df/world_data.h" +#include "dfhack/df/ui.h" + +namespace { + template + inline T &_toref(T &r) { return r; } + template + inline T &_toref(T *&p) { return *p; } +} + +// Instantiate all the static objects +#include "dfhack/df/static.inc" diff --git a/library/include/dfhack/Core.h b/library/include/dfhack/Core.h index 2d7941af2..64eae5d3e 100644 --- a/library/include/dfhack/Core.h +++ b/library/include/dfhack/Core.h @@ -190,4 +190,11 @@ namespace DFHack tthread::mutex * misc_data_mutex; std::map misc_data_map; }; + + class CoreSuspender { + Core *core; + public: + CoreSuspender(Core *core) : core(core) { core->Suspend(); } + ~CoreSuspender() { core->Resume(); } + }; } diff --git a/library/include/dfhack/DataDefs.h b/library/include/dfhack/DataDefs.h new file mode 100644 index 000000000..4308ea3ed --- /dev/null +++ b/library/include/dfhack/DataDefs.h @@ -0,0 +1,162 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#pragma once + +#include +#include +#include + +#include "dfhack/Core.h" +#include "dfhack/BitArray.h" + +// Stop some MS stupidity +#ifdef interface + #undef interface +#endif + +namespace DFHack +{ + class virtual_class {}; + +#ifdef _MSC_VER + typedef void *virtual_ptr; +#else + typedef virtual_class *virtual_ptr; +#endif + + class DFHACK_EXPORT virtual_identity { + static virtual_identity *list; + static std::map known; + + virtual_identity *prev, *next; + const char *dfhack_name; + const char *original_name; + virtual_identity *parent; + std::vector children; + + void *vtable_ptr; + bool has_children; + + protected: + virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent); + + bool check_instance(virtual_ptr instance_ptr, bool allow_subclasses); + + static void *get_vtable(virtual_ptr instance_ptr) { return *(void**)instance_ptr; } + + public: + const char *getName() { return dfhack_name; } + const char *getOriginalName() { return original_name ? original_name : dfhack_name; } + + virtual_identity *getParent() { return parent; } + const std::vector &getChildren() { return children; } + + static virtual_identity *get(virtual_ptr instance_ptr); + + bool is_instance(virtual_ptr instance_ptr) { + if (!instance_ptr) return false; + if (vtable_ptr) { + void *vtable = get_vtable(instance_ptr); + if (vtable == vtable_ptr) return true; + if (!has_children) return false; + } + return check_instance(instance_ptr, true); + } + + bool is_direct_instance(virtual_ptr instance_ptr) { + if (!instance_ptr) return false; + return vtable_ptr ? (vtable_ptr == get_vtable(instance_ptr)) + : check_instance(instance_ptr, false); + } + + static void Init(); + }; + + template + inline T *virtual_cast(virtual_ptr ptr) { + return T::_identity.is_instance(ptr) ? static_cast(ptr) : NULL; + } + + template + inline T *strict_virtual_cast(virtual_ptr ptr) { + return T::_identity.is_direct_instance(ptr) ? static_cast(ptr) : NULL; + } + + void InitDataDefGlobals(Core *core); + + template + T *ifnull(T *a, T *b) { return a ? a : b; } +} + +namespace df +{ + using DFHack::virtual_class; + using DFHack::BitArray; + + template + class class_virtual_identity : public DFHack::virtual_identity { + public: + class_virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent) + : virtual_identity(dfhack_name, original_name, parent) {}; + }; + + template + struct enum_field { + IntType value; + + enum_field() {} + enum_field(EnumType ev) : value(IntType(ev)) {} + template + enum_field(enum_field ev) : value(IntType(ev.value)) {} + + operator EnumType () { return EnumType(value); } + enum_field &operator=(EnumType ev) { + value = IntType(ev); return *this; + } + }; + + namespace enums {} +} + +#define ENUM_ATTR(enum,attr,val) (df::enums::enum::get_##attr(val)) +#define ENUM_ATTR_STR(enum,attr,val) DFHack::ifnull(ENUM_ATTR(enum,attr,val),"?") +#define ENUM_KEY_STR(enum,val) ENUM_ATTR_STR(enum,key,val) +#define ENUM_FIRST_ITEM(enum) (df::enums::enum::_first_item_of_##enum) +#define ENUM_LAST_ITEM(enum) (df::enums::enum::_last_item_of_##enum) + +namespace df { +#define DF_KNOWN_GLOBALS \ + GLOBAL(world,world) \ + GLOBAL(ui,ui) \ + GLOBAL(gview,interface) \ + GLOBAL(init,init) \ + GLOBAL(d_init,d_init) + +#define GLOBAL(name,tname) \ + struct tname; \ + namespace global { extern DFHACK_EXPORT tname *name; } +DF_KNOWN_GLOBALS +#undef GLOBAL +} diff --git a/library/include/dfhack/MiscUtils.h b/library/include/dfhack/MiscUtils.h index 2bdab10c6..adae44377 100644 --- a/library/include/dfhack/MiscUtils.h +++ b/library/include/dfhack/MiscUtils.h @@ -187,6 +187,7 @@ void print_bits ( T val, DFHack::Console& out ) strs << endl; out.print(strs.str().c_str()); } + /* // this is probably completely bogus std::string PrintSplatterType (int16_t mat1, int32_t mat2, vector &creature_types) @@ -247,4 +248,22 @@ std::string PrintSplatterType (int16_t mat1, int32_t mat2, vector +CT *binsearch_in_vector(std::vector &vec, FT CT::*field, AT value) { + int min = -1, max = (int)vec.size(); + CT **p = vec.data(); + FT key = (FT)value; + for (;;) { + int mid = (min + max)>>1; + if (mid == min) + return NULL; + FT midv = p[mid]->*field; + if (midv == key) + return p[mid]; + else if (midv < key) + min = mid; + else + max = mid; + } +} diff --git a/library/include/dfhack/df/.gitignore b/library/include/dfhack/df/.gitignore new file mode 100644 index 000000000..11c5ffbb1 --- /dev/null +++ b/library/include/dfhack/df/.gitignore @@ -0,0 +1,2 @@ +*.h +*.inc diff --git a/library/xml/codegen.pl b/library/xml/codegen.pl new file mode 100755 index 000000000..05684732b --- /dev/null +++ b/library/xml/codegen.pl @@ -0,0 +1,944 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use XML::LibXML; + +my $input_dir = $ARGV[0] || '.'; +my $output_dir = $ARGV[1] || 'codegen'; +my $main_namespace = $ARGV[2] || 'df'; +my $export_prefix = 'DFHACK_EXPORT '; + +my %types; +my %type_files; + +# Misc XML analysis + +our $typename; +our $filename; + +sub parse_address($;$) { + my ($str,$in_bits) = @_; + return undef unless defined $str; + + # Parse the format used by offset attributes in xml + $str =~ /^0x([0-9a-f]+)(?:\.([0-7]))?$/ + or die "Invalid address syntax: $str\n"; + my ($full, $bv) = ($1, $2); + die "Bits not allowed: $str\n" unless $in_bits; + return $in_bits ? (hex($full)*8 + ($bv||0)) : hex($full); +} + +sub check_bad_attrs($;$$) { + my ($tag, $allow_size, $allow_align) = @_; + + die "Cannot use size, alignment or offset for ".$tag->nodeName."\n" + if ((!$allow_size && defined $tag->getAttribute('size')) || + defined $tag->getAttribute('offset') || + (!$allow_align && defined $tag->getAttribute('alignment'))); +} + +sub check_name($) { + my ($name) = @_; + $name =~ /^[_a-zA-Z][_a-zA-Z0-9]*$/ + or die "Invalid identifier: $name\n"; + return $name; +} + +sub is_attr_true($$) { + my ($tag, $name) = @_; + return ($tag->getAttribute($name)||'') eq 'true'; +} + +sub type_header_def($) { + my ($name) = @_; + return uc($main_namespace).'_'.uc($name).'_H'; +} + +sub translate_lookup($) { + my ($str) = @_; + return undef unless $str && $str =~ /^\$global((\.[_a-zA-Z0-9]+)+)$/; + my @fields = split /\./, substr($1,1); + my $expr = "df::global::".shift(@fields); + for my $fn (@fields) { + $expr = "_toref($expr).$fn"; + } + return $expr; +} + +# Text generation with indentation + +our @lines; +our $indentation = 0; + +sub with_emit(&;$) { + # Executes the code block, and returns emitted lines + my ($blk, $start_indent) = @_; + local @lines; + local $indentation = ($start_indent||0); + $blk->(); + return @lines; +} + +sub emit(@) { + # Emit an indented line to be returned from with_emit + my $line = join('',map { defined($_) ? $_ : '' } @_); + $line = (' 'x$indentation).$line unless length($line) == 0; + push @lines, $line; +} + +sub indent(&) { + # Indent lines emitted from the block by one step + my ($blk) = @_; + local $indentation = $indentation+2; + $blk->(); +} + +sub outdent(&) { + # Unindent lines emitted from the block by one step + my ($blk) = @_; + local $indentation = ($indentation >= 2 ? $indentation-2 : 0); + $blk->(); +} + +sub emit_block(&;$$) { + # Emit a full {...} block with indentation + my ($blk, $prefix, $suffix) = @_; + $prefix ||= ''; + $suffix ||= ''; + emit $prefix,'{'; + &indent($blk); + emit '}',$suffix; +} + +# Static file output + +my @static_lines; +my %static_includes; + +sub with_emit_static(&) { + my ($blk) = @_; + $static_includes{$typename}++; + push @static_lines, &with_emit($blk,2); +} + +# Anonymous variable names + +our $anon_id = 0; +our $anon_prefix; + +sub ensure_name($) { + # If the name is empty, assign an auto-generated one + my ($name) = @_; + unless ($name) { + $name = $anon_prefix.(($anon_id == 0) ? '' : '_'.$anon_id); + $anon_id++; + } + return check_name($name); +} + +sub with_anon(&;$) { + # Establish a new anonymous namespace + my ($blk,$stem) = @_; + local $anon_id = $stem ? 0 : 1; + local $anon_prefix = ($stem||'anon'); + $blk->(); +} + +# Primitive types + +my @primitive_type_list = + qw(int8_t uint8_t int16_t uint16_t + int32_t uint32_t int64_t uint64_t + s-float + bool ptr-string stl-string flag-bit + pointer); + +my %primitive_aliases = ( + 'stl-string' => 'std::string', + 'ptr-string' => 'char*', + 'flag-bit' => 'void', + 'pointer' => 'void*', + 's-float' => 'float', +); + +my %primitive_types; +$primitive_types{$_}++ for @primitive_type_list; + +sub primitive_type_name($) { + my ($tag_name) = @_; + $primitive_types{$tag_name} + or die "Not primitive: $tag_name\n"; + return $primitive_aliases{$tag_name} || $tag_name; +} + +# Type references + +our %weak_refs; +our %strong_refs; + +sub register_ref($;$) { + # Register a reference to another type. + # Strong ones require the type to be included. + my ($ref, $is_strong) = @_; + + if ($ref) { + my $type = $types{$ref} + or die "Unknown type $ref referenced.\n"; + + if ($is_strong) { + $strong_refs{$ref}++; + } else { + $weak_refs{$ref}++; + } + } +} + +# Determines if referenced other types should be included or forward-declared +our $is_strong_ref = 1; + +sub with_struct_block(&$;$%) { + my ($blk, $tag, $name, %flags) = @_; + + my $kwd = (is_attr_true($tag,'is-union') ? "union" : "struct"); + my $exp = $flags{-export} ? $export_prefix : ''; + my $prefix = $kwd.' '.$exp.($name ? $name.' ' : ''); + + emit_block { + local $_; + local $is_strong_ref = 1; # reset the state + if ($flags{-no_anon}) { + $blk->(); + } else { + &with_anon($blk); + } + } $prefix, ";"; +} + +sub decode_type_name_ref($;%) { + # Interpret the type-name field of a tag + my ($tag,%flags) = @_; + my $force_type = $flags{-force_type}; + my $force_strong = $flags{-force_strong}; + my $tname = $tag->getAttribute($flags{-attr_name} || 'type-name') + or return undef; + + if ($primitive_types{$tname}) { + die "Cannot use type $tname as type-name of ".$tag->nodeName."\n" + if ($force_type && $force_type ne 'primitive'); + return primitive_type_name($tname); + } else { + register_ref $tname, ($force_strong||$is_strong_ref); + die "Cannot use type $tname as type-name of ".$tag->nodeName."\n" + if ($force_type && $force_type ne $types{$tname}->nodeName); + return $main_namespace.'::'.$tname; + } +} + +# CONDITIONALS + +sub is_conditional($) { + my ($tag) = @_; + return $tag->nodeName =~ /^(cond-if|cond-elseif)$/; +} + +sub translate_if_cond($) { + my ($tag) = @_; + + my @rules; + if (my $defvar = $tag->getAttribute('defined')) { + push @rules, "defined($defvar)"; + } + if (my $cmpvar = $tag->getAttribute('var')) { + if (my $cmpval = $tag->getAttribute('lt')) { + push @rules, "($cmpvar < $cmpval)"; + } + if (my $cmpval = $tag->getAttribute('le')) { + push @rules, "($cmpvar <= $cmpval)"; + } + if (my $cmpval = $tag->getAttribute('eq')) { + push @rules, "($cmpvar == $cmpval)"; + } + if (my $cmpval = $tag->getAttribute('ge')) { + push @rules, "($cmpvar >= $cmpval)"; + } + if (my $cmpval = $tag->getAttribute('gt')) { + push @rules, "($cmpvar > $cmpval)"; + } + if (my $cmpval = $tag->getAttribute('ne')) { + push @rules, "($cmpvar != $cmpval)"; + } + } + return '('.(join(' && ',@rules) || '1').')'; +} + +our $in_cond = 0; + +sub render_cond_if($$$;@) { + my ($tag, $in_elseif, $render_cb, @tail) = @_; + + local $in_cond = 1; + + { + local $indentation = 0; + my $op = ($in_elseif && $in_elseif >= 2) ? '#elif' : '#if'; + emit $op, ' ', translate_if_cond($tag); + } + + for my $child ($tag->findnodes('child::*')) { + &render_cond($child, $render_cb, @tail); + } + + unless ($in_elseif) { + local $indentation = 0; + emit "#endif"; + } +} + +sub render_cond($$;@) { + my ($tag, $render_cb, @tail) = @_; + + my $tag_name = $tag->nodeName; + if ($tag_name eq 'cond-if') { + render_cond_if($tag, 0, $render_cb, @tail); + } elsif ($tag_name eq 'cond-elseif') { + my $idx = 1; + for my $child ($tag->findnodes('child::*')) { + ($child->nodeName eq 'cond-if') + or die "Only cond-if tags may be inside a cond-switch: ".$child->nodeName."\n"; + render_cond_if($child, $idx++, $render_cb, @tail); + } + { + local $indentation = 0; + emit "#endif"; + } + } else { + local $_ = $tag; + $render_cb->($tag, @tail); + } +} + +# ENUM + +sub render_enum_core($$) { + my ($name,$tag) = @_; + + my $base = 0; + + emit_block { + my @items = $tag->findnodes('child::*'); + my $idx = 0; + + for my $item (@items) { + render_cond $item, sub { + my $tag = $_->nodeName; + return if $tag eq 'enum-attr'; + ($tag eq 'enum-item') + or die "Invalid enum member: ".$item->nodeName."\n"; + + my $name = ensure_name $_->getAttribute('name'); + my $value = $_->getAttribute('value'); + + $base = ($idx == 0 && !$in_cond) ? $value : undef if defined $value; + $idx++; + + emit $name, (defined($value) ? ' = '.$value : ''), ','; + }; + } + + emit "_last_item_of_$name"; + } "enum $name ", ";"; + + return $base; +} + +sub render_enum_tables($$$) { + my ($name,$tag,$base) = @_; + + # Enumerate enum attributes + + my %aidx = ('key' => 0); + my @anames = ('key'); + my @avals = ('NULL'); + my @atypes = ('const char*'); + my @atnames = (undef); + + for my $attr ($tag->findnodes('child::enum-attr')) { + my $name = $attr->getAttribute('name') or die "Unnamed enum-attr.\n"; + my $type = $attr->getAttribute('type-name'); + my $def = $attr->getAttribute('default-value'); + + die "Duplicate attribute $name.\n" if exists $aidx{$name}; + + check_name $name; + $aidx{$name} = scalar @anames; + push @anames, $name; + push @atnames, $type; + + if ($type) { + push @atypes, $type; + push @avals, (defined $def ? $def : "($type)0"); + } else { + push @atypes, 'const char*'; + push @avals, (defined $def ? "\"$def\"" : 'NULL'); + } + } + + # Emit accessor function prototypes + + emit "const $name _first_item_of_$name = ($name)$base;"; + + emit_block { + emit "return (value >= _first_item_of_$name && value < _last_item_of_$name);"; + } "inline bool is_valid($name value) "; + + for (my $i = 0; $i < @anames; $i++) { + emit "${export_prefix}$atypes[$i] get_$anames[$i]($name value);"; + } + + # Emit implementation + + with_emit_static { + emit_block { + emit_block { + # Emit the entry type + emit_block { + for (my $i = 0; $i < @anames; $i++) { + emit "$atypes[$i] $anames[$i];"; + } + } "struct _info_entry ", ";"; + + # Emit the info table + emit_block { + for my $item ($tag->findnodes('child::*')) { + render_cond $item, sub { + my $tag = $_->nodeName; + return if $tag eq 'enum-attr'; + + # Assemble item-specific attr values + my @evals = @avals; + my $name = $_->getAttribute('name'); + $evals[0] = "\"$name\"" if $name; + + for my $attr ($_->findnodes('child::item-attr')) { + my $name = $attr->getAttribute('name') or die "Unnamed item-attr.\n"; + my $value = $attr->getAttribute('value') or die "No-value item-attr.\n"; + my $idx = $aidx{$name} or die "Unknown item-attr: $name\n"; + + if ($atnames[$idx]) { + $evals[$idx] = $value; + } else { + $evals[$idx] = "\"$value\""; + } + } + + emit "{ ",join(', ',@evals)," },"; + }; + } + + emit "{ ",join(', ',@avals)," }"; + } "static const _info_entry _info[] = ", ";"; + + for (my $i = 0; $i < @anames; $i++) { + emit_block { + emit "return is_valid(value) ? _info[value - $base].$anames[$i] : $avals[$i];"; + } "$atypes[$i] get_$anames[$i]($name value) "; + } + } "namespace $name "; + } "namespace enums "; + }; +} + +sub render_enum_type { + my ($tag) = @_; + + emit_block { + emit_block { + my $base = render_enum_core($typename,$tag); + + if (defined $base) { + render_enum_tables($typename,$tag,$base); + } else { + print STDERR "Warning: complex enum: $typename\n"; + } + } "namespace $typename "; + } "namespace enums "; + + emit "using enums::",$typename,"::",$typename,";"; +} + +# BITFIELD + +sub get_primitive_base($;$) { + my ($tag, $default) = @_; + + my $base = $tag->getAttribute('base-type') || $default || 'uint32_t'; + $primitive_types{$base} or die "Must be primitive: $base\n"; + + return $base; +} + +sub render_bitfield_core { + my ($name, $tag) = @_; + + emit_block { + emit get_primitive_base($tag), ' whole;'; + + emit_block { + for my $item ($tag->findnodes('child::*')) { + render_cond $item, sub { + my ($item) = @_; + ($item->nodeName eq 'flag-bit') + or die "Invalid bitfield member:".$item->nodeName."\n"; + + check_bad_attrs($item); + my $name = ensure_name $item->getAttribute('name'); + my $size = $item->getAttribute('count') || 1; + emit "unsigned ", $name, " : ", $size, ";"; + }; + } + } "struct ", " bits;"; + } "union $name ", ";"; +} + +sub render_bitfield_type { + my ($tag) = @_; + render_bitfield_core($typename,$tag); +} + +# STRUCT + +my %struct_field_handlers; + +sub get_struct_fields($) { + # Retrieve subtags that are actual struct fields + my ($struct_tag) = @_; + local $_; + return grep { + my $tag = $_->nodeName; + die "Unknown field tag: $tag\n" + unless exists $struct_field_handlers{$tag}; + $struct_field_handlers{$tag}; + } $struct_tag->findnodes('child::*'); +} + +sub get_struct_field_type($) { + # Dispatch on the tag name, and retrieve the type prefix & suffix + my ($tag) = @_; + my $handler = $struct_field_handlers{$tag->nodeName} + or die "Unexpected tag: ".$tag->nodeName; + return $handler->($tag); +} + +sub do_render_struct_field($) { + my ($tag) = @_; + my $tag_name = $tag->nodeName; + my $field_name = $tag->getAttribute('name'); + + # Special case: anonymous compounds. + if ($tag_name eq 'compound' && !defined $field_name && + !defined $tag->getAttribute('type-name')) + { + check_bad_attrs($tag); + with_struct_block { + render_struct_field($_) for get_struct_fields($tag); + } $tag, undef, -no_anon => 1; + return; + } + + # Otherwise, create the name if necessary, and render + my $name = ensure_name $field_name; + with_anon { + my ($prefix, $postfix) = get_struct_field_type($tag); + emit $prefix, ' ', $name, $postfix, ';'; + } "T_$name"; +} + +sub render_struct_field($) { + my ($tag) = @_; + render_cond $tag, \&do_render_struct_field; +} + +sub emit_typedef($$) { + # Convert a prefix/postfix pair into a single name + my ($pre, $post) = @_; + my $name = ensure_name undef; + emit 'typedef ', $pre, ' ', $name, $post, ';'; + return $name; +} + +sub get_container_item_type($$;$) { + # Interpret the type-name and nested fields for a generic container type + my ($tag,$strong_ref,$allow_void) = @_; + + check_bad_attrs($tag); + + my $prefix; + my $postfix = ''; + local $is_strong_ref = $strong_ref; + + unless ($prefix = decode_type_name_ref($tag)) { + my @fields = get_struct_fields($tag); + + if (scalar(@fields) == 1 && !is_conditional($fields[0])) { + ($prefix, $postfix) = get_struct_field_type($fields[0]); + } elsif (scalar(@fields) == 0) { + $allow_void or die "Empty container: ".$tag->nodeName."\n"; + $prefix = $allow_void; + } else { + $prefix = ensure_name undef; + with_struct_block { + render_struct_field($_) for @fields; + } $tag, $prefix; + } + } + + return ($prefix,$postfix) if wantarray; + return emit_typedef($prefix, $postfix) if $postfix; + return $prefix; +} + +sub get_primitive_field_type { + # Primitive type handler + my ($tag,$fname) = @_; + check_bad_attrs($tag); + my $name = $tag->nodeName; + return (primitive_type_name($name), ""); +} + +sub get_static_string_type { + # Static string handler + my ($tag, $fname) = @_; + check_bad_attrs($tag, 1); + my $count = $tag->getAttribute('size') || 0; + return ('char', "[$count]"); +} + +sub get_padding_type { + # Padding handler. Supports limited alignment. + my ($tag, $fname) = @_; + + check_bad_attrs($tag, 1, 1); + my $count = $tag->getAttribute('size') || 0; + my $align = $tag->getAttribute('alignment') || 1; + + if ($align == 1) { + return ('char', "[$count]"); + } elsif ($align == 2) { + ($count % 2 == 0) or die "Size not aligned in padding: $count at $align\n"; + return ('short', "[".($count/2)."]"); + } elsif ($align == 4) { + ($count % 4 == 0) or die "Size not aligned in padding: $count at $align\n"; + return ('int', "[".($count/4)."]"); + } else { + die "Bad padding alignment $align in $typename in $filename\n"; + } +} + +sub get_static_array_type { + # static-array handler + my ($tag, $fname) = @_; + my ($pre, $post) = get_container_item_type($tag, 1); + my $count = $tag->getAttribute('count') + or die "Count is mandatory for static-array in $typename in $filename\n"; + return ($pre, "[$count]".$post); +} + +sub get_pointer_type($) { + # pointer handler + my ($tag) = @_; + my $item = get_container_item_type($tag, 0, 'void'); + return ($item.'*', ''); +} + +sub get_compound_type($) { + # compound (nested struct) handler + my ($tag) = @_; + check_bad_attrs($tag); + + my $tname = decode_type_name_ref($tag); + unless ($tname) { + $tname = ensure_name undef; + with_struct_block { + render_struct_field($_) for get_struct_fields($tag); + } $tag, $tname; + } + return ($tname,''); +} + +sub get_bitfield_type($) { + # nested bitfield handler + my ($tag) = @_; + check_bad_attrs($tag); + + my $tname = decode_type_name_ref($tag, -force_type => 'bitfield-type'); + unless ($tname) { + $tname = ensure_name undef; + with_anon { + render_bitfield_core($tname, $tag); + }; + } + return ($tname,''); +} + +sub get_enum_type($) { + # nested enum handler + my ($tag) = @_; + check_bad_attrs($tag); + + my $tname = decode_type_name_ref($tag, -force_type => 'enum-type', -force_strong => 1); + my $base = get_primitive_base($tag, 'int32_t'); + unless ($tname) { + $tname = ensure_name undef; + with_anon { + render_enum_core($tname,$tag); + }; + } + return ("enum_field<$tname,$base>", ''); +} + +sub get_stl_vector_type($) { + # STL vector + my ($tag) = @_; + my $item = get_container_item_type($tag,1,'void*'); + $item = 'char' if $item eq 'bool'; + return ("std::vector<$item>", ''); +} + +sub get_stl_bit_vector_type($) { + # STL bit vector + my ($tag) = @_; + check_bad_attrs($tag); + return ("std::vector", ''); +} + +sub get_df_flagarray_type($) { + # DF flag array + my ($tag) = @_; + check_bad_attrs($tag); + my $type = decode_type_name_ref($tag, -attr_name => 'index-enum', -force_type => 'enum-type', -force_strong => 1) || 'int'; + return ("BitArray<$type>", ''); +} + +# Struct dispatch table and core + +%struct_field_handlers = ( + 'comment' => undef, # skip + 'code-helper' => undef, # skip + 'cond-if' => sub { die "cond handling error"; }, + 'cond-elseif' => sub { die "cond handling error"; }, + 'static-string' => \&get_static_string_type, + 'padding' => \&get_padding_type, + 'static-array' => \&get_static_array_type, + 'pointer' => \&get_pointer_type, + 'compound' => \&get_compound_type, + 'bitfield' => \&get_bitfield_type, + 'enum' => \&get_enum_type, + 'stl-vector' => \&get_stl_vector_type, + 'stl-bit-vector' => \&get_stl_bit_vector_type, + 'df-flagarray' => \&get_df_flagarray_type, +); +$struct_field_handlers{$_} ||= \&get_primitive_field_type for @primitive_type_list; + +sub emit_find_instance { + my ($tag) = @_; + + my $instance_vector = translate_lookup $tag->getAttribute('instance-vector'); + if ($instance_vector) { + emit "static std::vector<$typename*> &get_vector();"; + emit "static $typename *find(int id);"; + + with_emit_static { + emit_block { + emit "return ", $instance_vector, ";"; + } "std::vector<$typename*>& ${typename}::get_vector() "; + + emit_block { + emit "std::vector<$typename*> &vec_ = get_vector();"; + + if (my $id = $tag->getAttribute('key-field')) { + emit "return binsearch_in_vector(vec_, &${typename}::$id, id_);"; + } else { + emit "return (id_ >= 0 && id_ < vec_.size()) ? vec_[id_] : NULL;"; + } + } "$typename *${typename}::find(int id_) "; + } + } +} + +sub render_struct_type { + my ($tag) = @_; + + my $tag_name = $tag->nodeName; + my $is_class = ($tag_name eq 'class-type'); + my $has_methods = $is_class || is_attr_true($tag, 'has-methods'); + my $inherits = $tag->getAttribute('inherits-from'); + my $original_name = $tag->getAttribute('original-name'); + my $ispec = ''; + + if ($inherits) { + register_ref $inherits, 1; + $ispec = ' : '.$inherits; + } elsif ($is_class) { + $ispec = ' : virtual_class'; + } + + with_struct_block { + render_struct_field($_) for get_struct_fields($tag); + + emit_find_instance($tag); + + if ($has_methods) { + if ($is_class) { + emit "static class_virtual_identity<$typename> _identity;"; + with_emit_static { + emit "class_virtual_identity<$typename> ${typename}::_identity(", + "\"$typename\",", + ($original_name ? "\"$original_name\"" : 'NULL'), ',', + ($inherits ? "&${inherits}::_identity" : 'NULL'), + ");"; + } + } + + outdent { + emit "protected:"; + }; + + if ($is_class) { + emit "virtual ~",$typename,"() {}"; + } else { + emit "~",$typename,"() {}"; + } + } + } $tag, "$typename$ispec", -export => 1; +} + +# MAIN BODY + +# Collect all type definitions from XML files + +sub add_type_to_hash($) { + my ($type) = @_; + + my $name = $type->getAttribute('type-name') + or die "Type without a name in $filename\n"; + + die "Duplicate definition of $name in $filename\n" if $types{$name}; + + local $typename = $name; + check_bad_attrs $type; + $types{$name} = $type; + $type_files{$name} = $filename; +} + +for my $fn (glob "$input_dir/*.xml") { + local $filename = $fn; + my $parser = XML::LibXML->new(); + my $doc = $parser->parse_file($filename); + + add_type_to_hash $_ foreach $doc->findnodes('/data-definition/enum-type'); + add_type_to_hash $_ foreach $doc->findnodes('/data-definition/bitfield-type'); + add_type_to_hash $_ foreach $doc->findnodes('/data-definition/struct-type'); + add_type_to_hash $_ foreach $doc->findnodes('/data-definition/class-type'); +} + +# Generate text representations + +my %type_handlers = ( + 'enum-type' => \&render_enum_type, + 'bitfield-type' => \&render_bitfield_type, + 'class-type' => \&render_struct_type, + 'struct-type' => \&render_struct_type, +); + +my %type_data; + +for my $name (sort { $a cmp $b } keys %types) { + local $typename = $name; + local $filename = $type_files{$typename}; + local %weak_refs; + local %strong_refs; + + eval { + my $type = $types{$typename}; + + # Emit the actual type definition + my @code = with_emit { + with_anon { + $type_handlers{$type->nodeName}->($type); + }; + } 2; + + delete $weak_refs{$name}; + delete $strong_refs{$name}; + + # Add wrapping + my @all = with_emit { + my $def = type_header_def($typename); + emit "#ifndef $def"; + emit "#define $def"; + + for my $strong (sort { $a cmp $b } keys %strong_refs) { + my $sdef = type_header_def($strong); + emit "#ifndef $sdef"; + emit "#include \"$strong.h\""; + emit "#endif"; + } + + emit_block { + for my $weak (sort { $a cmp $b } keys %weak_refs) { + next if $strong_refs{$weak}; + my $ttype = $types{$weak}; + my $tstr = 'struct'; + $tstr = 'enum' if $ttype->nodeName eq 'enum-type'; + $tstr = 'union' if $ttype->nodeName eq 'bitfield-type'; + $tstr = 'union' if ($ttype->nodeName eq 'struct-type' && is_attr_true($ttype,'is-union')); + emit $tstr, ' ', $weak, ';'; + } + + push @lines, @code; + } "namespace $main_namespace "; + + emit "#endif"; + }; + + $type_data{$typename} = \@all; + }; + if ($@) { + print 'Error: '.$@."Type $typename in $filename ignored\n"; + } +} + +# Write output files + +mkdir $output_dir; + +{ + # Delete the old files + for my $name (glob "$output_dir/*.h") { + unlink $name; + } + + # Write out the headers + local $, = "\n"; + local $\ = "\n"; + + for my $name (keys %type_data) { + open FH, ">$output_dir/$name.h"; + print FH "/* THIS FILE WAS GENERATED. DO NOT EDIT. */"; + print FH @{$type_data{$name}}; + close FH; + } + + # Write out the static file + open FH, ">$output_dir/static.inc"; + print FH "/* THIS FILE WAS GENERATED. DO NOT EDIT. */"; + for my $name (sort { $a cmp $b } keys %static_includes) { + print FH "#include \"$name.h\""; + } + print FH "namespace $main_namespace {"; + print FH @static_lines; + print FH '}'; + close FH; +} diff --git a/library/xml/df.building-raws.xml b/library/xml/df.building-raws.xml new file mode 100644 index 000000000..bf522ae31 --- /dev/null +++ b/library/xml/df.building-raws.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.buildings.xml b/library/xml/df.buildings.xml new file mode 100644 index 000000000..74df09eb7 --- /dev/null +++ b/library/xml/df.buildings.xml @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 - not room; 1 in stockpile; 2 wall; 3 inner; 4 distance boundary. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- stockpile -- + + + + + + + + + + + + + + + + + + + + + + + + + -- zone -- + + + + + + -- actual -- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- workshops -- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- misc -- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.creature-raws.xml b/library/xml/df.creature-raws.xml new file mode 100644 index 000000000..61aa7ed7c --- /dev/null +++ b/library/xml/df.creature-raws.xml @@ -0,0 +1,592 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // 0 around of, 1 around by + + + + + + + + + + + + + + + + + + + $global.world.raws.creatures.all[$$].caste[$] + + + + + + + + + // temporary + + + + fingers[2], nose, ear, head, eyes, mouth, hair, knuckles, lips, cheek, nails, f eet, arms, hands, tongue, leg + + + + + + + + + + + + + + + + + + + + + + + + + + // NOT 32-bit! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $global.world.raws.creatures.all[$] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.d_init.xml b/library/xml/df.d_init.xml new file mode 100644 index 000000000..345fa812a --- /dev/null +++ b/library/xml/df.d_init.xml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 85266c0 + + + + diff --git a/library/xml/df.history.xml b/library/xml/df.history.xml new file mode 100644 index 000000000..700329ea8 --- /dev/null +++ b/library/xml/df.history.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + (describe-obj $.name) + (awhen (find-creature $.race) + (fmt "~:(~A ~A~)" $it.caste[$.caste].caste_id $it.creature_id)) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dtor 8532fa0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.init.xml b/library/xml/df.init.xml new file mode 100644 index 000000000..6680b788a --- /dev/null +++ b/library/xml/df.init.xml @@ -0,0 +1,138 @@ + + -- init.h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- texture_handler.h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.item-raws.xml b/library/xml/df.item-raws.xml new file mode 100644 index 000000000..81d9c7671 --- /dev/null +++ b/library/xml/df.item-raws.xml @@ -0,0 +1,303 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.items.xml b/library/xml/df.items.xml new file mode 100644 index 000000000..c1b989b23 --- /dev/null +++ b/library/xml/df.items.xml @@ -0,0 +1,577 @@ + + -- MISC TYPES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- CORE ITEM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- ACTUAL ITEM + + + -- Important + + + + + + -- Misc + + + + + + + + + + + + + + + + + + + + + + + + + + -- Wielders + + + + + + + + + + + + (if (> $.stack_size 1) (fmt "stack: ~A" $.stack_size)) + (if (> $.wear 0) (fmt "wear: ~A" $.wear)) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- CRAFTED ITEM + + + + + + + $.quality + (describe-obj (material-by-id $.matType $.matIndex)) + + + + + + + + + + -- CONSTRUCTED ITEM + + + + + + + + -- BODY COMPONENT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- CRITTER + + + + + + + + + -- LIQUID/POWER + + + + + + + + + + + + + + + + + + -- MISC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- CONSTRUCTED + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.job-enums.xml b/library/xml/df.job-enums.xml new file mode 100644 index 000000000..6a84ec8f5 --- /dev/null +++ b/library/xml/df.job-enums.xml @@ -0,0 +1,1785 @@ + + ----- PROFESSION ----- + + + + + + + -- 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 50 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 60 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 80 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 90 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 100 + + + + + + + + + + + + + + + + + + + + + + ----- LABOR ----- + + + + + -- 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 50 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 60 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 70 + + + + + + + + + + + + + ----- SKILL ----- + + + + + -- 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 50 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 60 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 80 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 90 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 100 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 110 + + + + + + + + + + + + + + + + + + + + + + ----- JOB TYPE ----- + + + -- Declare attributes: + + + + -- 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 50 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 60 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 80 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 90 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 100 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 130 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 150 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 160 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 170 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 180 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 190 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 200 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 210 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 220 + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.jobs.xml b/library/xml/df.jobs.xml new file mode 100644 index 000000000..8c6c6d849 --- /dev/null +++ b/library/xml/df.jobs.xml @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- Guess: + + + + + + + + + + + -- Either empty, or same as above: + + + + + + + + -- These are equal to the ones above: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.language.xml b/library/xml/df.language.xml new file mode 100644 index 000000000..961057f2d --- /dev/null +++ b/library/xml/df.language.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $.word + + + + + + + + + + + + + + $.name + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (when $.has_name + (let* ((nick $.nickname) + (language $global.world.raws.translations[$.language]) + (fname $.first_name) + (lwords $language.words)) + (fmt "~:(~@[~A ~]~@['~A' ~]~{~A~^ ~}~)" + (if (> (length fname) 0) fname) + (if (> (length nick) 0) nick) + (loop for i from 0 below 7 for word = $.words[i] + when (>= word 0) collect $lwords[word].value)))) + + + + + diff --git a/library/xml/df.legends.xml b/library/xml/df.legends.xml new file mode 100644 index 000000000..a9d2e4a65 --- /dev/null +++ b/library/xml/df.legends.xml @@ -0,0 +1,301 @@ + + + + + + + + + + + + + (describe-obj $.name) + (describe-obj (find-creature $.race)) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (describe-obj $.name) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (describe-obj $.figure) + + + + + + + + + + + + + + + + (describe-obj $.name) + + + + + + + + + + diff --git a/library/xml/df.machines.xml b/library/xml/df.machines.xml new file mode 100644 index 000000000..000e83255 --- /dev/null +++ b/library/xml/df.machines.xml @@ -0,0 +1,96 @@ + + -- MACHINE + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- MACHINE COMPONENT BUILDINGS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.map.xml b/library/xml/df.map.xml new file mode 100644 index 000000000..eac8bbeb9 --- /dev/null +++ b/library/xml/df.map.xml @@ -0,0 +1,247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.materials.xml b/library/xml/df.materials.xml new file mode 100644 index 000000000..ea464879a --- /dev/null +++ b/library/xml/df.materials.xml @@ -0,0 +1,341 @@ + + + + + + + + (describe-material $) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // color token index + + + + + + + + + + + + + (material-by-id $ $$) + (describe-material $) + + + + + + + + + + + + + + + (describe-material $) + + + + + + + + + $.id + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $.id + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.military.xml b/library/xml/df.military.xml new file mode 100644 index 000000000..d44af3d30 --- /dev/null +++ b/library/xml/df.military.xml @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- May be invalid: + + + + + + + + + + + + + + + + + + + (describe-obj $.name) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (describe-obj $.name) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.projectile.xml b/library/xml/df.projectile.xml new file mode 100644 index 000000000..5fc9b3e4a --- /dev/null +++ b/library/xml/df.projectile.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.raws.xml b/library/xml/df.raws.xml new file mode 100644 index 000000000..ed2745fb5 --- /dev/null +++ b/library/xml/df.raws.xml @@ -0,0 +1,237 @@ + + + -- Materials + + + + + + -- Inorganic + + + + + + + + + -- Plants + + + dtor 852cc20 + + + + + + + + + + + + + + + + + + + + + + + + + -- Creature RAWs + + + + dtor 89bab50 + + + dtor 8527e40 + + + + + + + + + + + + + dtor 89ba980 + + + -- Creatures + + + dtor 81448c0 + + + + + + + + + + + + + + + + -- Item RAWs + + + dtor 852e080 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- Sapient species + + + + + + -- Language RAWs + + dtor 852bc90 + + + + + + + + + + + + + + + + + + + + + + -- Words + + + + + + + + + + + + + + + + + + + + + + + + + + + -- Reaction RAWs + + + + + + -- Workshops + + + + + + + + + + + + + + + + -- Material index + + + + + + diff --git a/library/xml/df.refs.xml b/library/xml/df.refs.xml new file mode 100644 index 000000000..04671dc55 --- /dev/null +++ b/library/xml/df.refs.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.stockpile.xml b/library/xml/df.stockpile.xml new file mode 100644 index 000000000..cfd48e38d --- /dev/null +++ b/library/xml/df.stockpile.xml @@ -0,0 +1,254 @@ + + + + + + + + + + + also 26 + also 31 + also 32 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 16 + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + 5 + 5 + + + + + 659 + + + + + + + + 17 + + + + + + + + + + + + + + + + + + + + + + + + 11 + + + + + + + + + + + + + + + 11 + + + + + + + + + + + + + diff --git a/library/xml/df.ui.xml b/library/xml/df.ui.xml new file mode 100644 index 000000000..457617a00 --- /dev/null +++ b/library/xml/df.ui.xml @@ -0,0 +1,603 @@ + + + + + + + + + + + + + + + (describe-obj $.name) + + + + + + + + + + + + + + + + + + -- 2 + + + + + + + + + + + + + + + -- 14 + + + + + + -- 17 + + + + + + + + -- 22 + + + + + + -- 25 + + + + + + + + + + + -- 33 + + + + + -- 35 + + + + -- 36 + + + + + + + -- 40 + + + + + + + -- 44 + + + + + + + + + + + + + + + + + + + + + + + + + + ctor 86e33c0 x + dtor 8534190 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dtor: 0x85272c0 + + + + diff --git a/library/xml/df.units.xml b/library/xml/df.units.xml new file mode 100644 index 000000000..fdad8cd56 --- /dev/null +++ b/library/xml/df.units.xml @@ -0,0 +1,701 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scuttle creature: causes creature to be killed, leaving a behind + corpse and generating negative thoughts like a real kill. + + + + + + + + + + + + (describe-obj $.name) + (awhen (find-creature $.race) + (fmt "~:(~A ~A~)" $it.caste[$.caste].caste_id $it.creature_id)) + + + + + + + + + + + + + + + + E.g. for a dead miner, holds the place where he + was likely hanging around when he got the command + to mine in an aquifer. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- If shot by a ranged weapon: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // fight related + // fight related + + + // increments every tick + + + + + + + + + // 87*0 ? + + + + + // 238*0 + // 238*0 + // 238*0 + // 238*0 + // 238*0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // 490 + + + + + + + + + + + + + + + + + + + + + + + + // 53c decrements every job_counter reroll, set when changing jobs + // 540 current_job unit/walk done when reach -1, decremented every tick + // if set, decrements every job_counter reroll + + + // 54c decrements every tick, unstun at 0 + + + + + // coords ? (-30.000x3) + + + // coords again + + + + + + + + + + + + + + + + + + + + + + + + // counter, decrement to 0 + // same as 58c + + // fluctuate + + + + + + + + + + + + + + + + + + + + + + + + // 0x3e8 (1000) + // 0x3e8 (1000) + + + + + + + + + + + + + + + + // item ids? + + // 6f0: dined in a legendary dinning room, etc + + + + // 710 + + + + + // 738 + + + + // coords (-30000*3) + + + + + + + + + + + // 794 + // 796 + // 798 + // 79a + + + + + + + + + + + + + + + + + + + + + + // combat log? + + + + + + + + + + + + + // item related + + + + + + // age ? incremented every tick + + + + + + + + + + // items ids? + + // same size as 8e8, soldier related? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (fmt "value=~A" $.value) + + + + + + + + + + + + + + + (describe-obj $.name) + (awhen (find-creature $.race) + (fmt "~:(~A ~A~)" $it.caste[$.caste].caste_id $it.creature_id)) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.viewscreen.xml b/library/xml/df.viewscreen.xml new file mode 100644 index 000000000..3874c445a --- /dev/null +++ b/library/xml/df.viewscreen.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.world-data.xml b/library/xml/df.world-data.xml new file mode 100644 index 000000000..2f0faa3a2 --- /dev/null +++ b/library/xml/df.world-data.xml @@ -0,0 +1,374 @@ + + + + + + + + + + + + + + + + + + + + (describe-obj $.name) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.world.xml b/library/xml/df.world.xml new file mode 100644 index 000000000..3058b0a64 --- /dev/null +++ b/library/xml/df.world.xml @@ -0,0 +1,503 @@ + + + dtor 89fff80 + + + dtor 8532540 + + + + + + + + + + + + + + + + + -- + + + + + + + + + + -- Entities + + + + + + + + + + + + -- Unknown + + + + -- Units + + + + + + + + + + + + + + + + + + -- Unknown + + + + + + + + + -- Nemesis + + + + + + + + + + + + + + -- Items + + + dtor 852f4b0 + + + + + + + + + + + + + + + + + + + -- Artifacts + + + + + + + + + + + + -- Jobs and projectiles + + + + + + -- Buildings + + + dtor 85316f0 + + + + + + + + + + + + + + + + + + + + -- Machines (connected groups of gears and so on) + + + + + + + + + + + -- Unknown + + + + + + + + + + + + + + + + + + + + + + + + -- Plants + + + + + + + + + -- Unknown + + + + -- Unknown + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- Drills + + + + + + + + + + + -- Reports and announcements + + + dtor 85356e0 + + + + + + + + + + Written to by code at 0x80fd7b0 + + + + + + + + + + + + + + + + + + + + + + 52cdc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 547f8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- RAWs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ctor 87ae880 + + + + + + + + + + + dtor 83bed90 + + + + + + + + + + + + -- hist figures + + + + + + + + + + + + + + + + Looks like a temporary buffer for pathfinding or something. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 192be0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/list.pl b/library/xml/list.pl new file mode 100755 index 000000000..206565843 --- /dev/null +++ b/library/xml/list.pl @@ -0,0 +1,33 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use XML::LibXML; + +my $input_dir = $ARGV[0] || '.'; +my $output_dir = $ARGV[1] || 'codegen'; +my $separator = $ARGV[2] || "\n"; + +print "$output_dir/static.inc"; + +for my $filename (glob "$input_dir/*.xml") { + my $parser = XML::LibXML->new(); + my $doc = $parser->parse_file($filename); + + my @nodes = ( + $doc->findnodes('/data-definition/enum-type'), + $doc->findnodes('/data-definition/bitfield-type'), + $doc->findnodes('/data-definition/struct-type'), + $doc->findnodes('/data-definition/class-type') + ); + + for my $node (@nodes) { + my $name = $node->getAttribute('type-name') + or die "Unnamed type in $filename\n"; + print "$separator$output_dir/$name.h"; + } +} + +print $separator if $separator eq "\n"; + diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index c08bcd9e1..ab7e039a4 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -30,7 +30,7 @@ if(BUILD_SERVER) add_subdirectory (server) endif() -OPTION(BUILD_DF2MC "Build DF2MC (needs a checkout first)." ON) +OPTION(BUILD_DF2MC "Build DF2MC (needs a checkout first)." OFF) if(BUILD_DF2MC) add_subdirectory (df2mc) endif() @@ -57,7 +57,9 @@ DFHACK_PLUGIN(deramp deramp.cpp) DFHACK_PLUGIN(flows flows.cpp) DFHACK_PLUGIN(filltraffic filltraffic.cpp) DFHACK_PLUGIN(seedwatch seedwatch.cpp) -DFHACK_PLUGIN(versionosd versionosd.cpp) +DFHACK_PLUGIN(initflags initflags.cpp) +DFHACK_PLUGIN(stockpiles stockpiles.cpp) +#DFHACK_PLUGIN(versionosd versionosd.cpp) # this is the skeleton plugin. If you want to make your own, make a copy and then change it OPTION(BUILD_SKELETON "Build the skeleton plugin." OFF) diff --git a/plugins/initflags.cpp b/plugins/initflags.cpp new file mode 100644 index 000000000..f27a318ae --- /dev/null +++ b/plugins/initflags.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include + +#include +#include + +using std::vector; +using std::string; +using std::endl; +using namespace DFHack; +using namespace df::enums; + +using df::global::d_init; + +DFhackCExport command_result twaterlvl(Core * c, vector & parameters); +DFhackCExport command_result tidlers(Core * c, vector & parameters); + +DFhackCExport const char * plugin_name ( void ) +{ + return "initflags"; +} + +DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +{ + commands.clear(); + if (d_init) { + commands.push_back(PluginCommand("twaterlvl", "Toggle display of water/magma depth.", twaterlvl)); + commands.push_back(PluginCommand("tidlers", "Toggle display of idlers.", tidlers)); + } + std::cerr << "d_init: " << sizeof(df::d_init) << endl; + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} + +DFhackCExport command_result twaterlvl(Core * c, vector & parameters) +{ + c->Suspend(); + df::global::d_init->flags1.toggle(d_init_flags1::SHOW_FLOW_AMOUNTS); + c->con << "Toggled the display of water/magma depth." << endl; + c->Resume(); + return CR_OK; +} + +DFhackCExport command_result tidlers(Core * c, vector & parameters) +{ + c->Suspend(); + df::d_init_idlers iv = df::d_init_idlers(int(d_init->idlers) + 1); + if (!d_init_idlers::is_valid(iv)) + iv = ENUM_FIRST_ITEM(d_init_idlers); + d_init->idlers = iv; + c->con << "Toggled the display of idlers to " << ENUM_KEY_STR(d_init_idlers, iv) << endl; + c->Resume(); + return CR_OK; +} diff --git a/plugins/stockpiles.cpp b/plugins/stockpiles.cpp new file mode 100644 index 000000000..5cd153335 --- /dev/null +++ b/plugins/stockpiles.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +using std::vector; +using std::string; +using std::endl; +using namespace DFHack; +using namespace df::enums; + +using df::global::world; +using df::global::ui; + +using df::building_stockpilest; + +DFhackCExport command_result copystock(Core * c, vector & parameters); + +DFhackCExport const char * plugin_name ( void ) +{ + return "stockpiles"; +} + +DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +{ + commands.clear(); + if (world && ui) { + commands.push_back(PluginCommand("copystock", "Copy stockpile under cursor.", copystock)); + } + std::cerr << "world: " << sizeof(df::world) << " ui: " << sizeof(df::ui) + << " b_stock: " << sizeof(building_stockpilest) << endl; + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} + +bool inSelectMode() { + using namespace ui_sidebar_mode; + + switch (ui->main.mode) { + case BuildingItems: + case QueryBuilding: + return true; + default: + return false; + } +} + +DFhackCExport command_result copystock(Core * c, vector & parameters) +{ + CoreSuspender suspend(c); + + // For convenience: when used in the stockpiles mode, switch to 'q' + if (ui->main.mode == ui_sidebar_mode::Stockpiles) { + world->selected_building = NULL; // just in case it contains some kind of garbage + ui->main.mode = ui_sidebar_mode::QueryBuilding; + + c->con << "Switched back to query building." << endl; + return CR_OK; + } + + if (!inSelectMode()) { + c->con << "Cannot copy stockpile in mode " << ENUM_KEY_STR(ui_sidebar_mode, ui->main.mode) << endl; + return CR_OK; + } + + building_stockpilest *sp = virtual_cast(world->selected_building); + if (!sp) { + c->con << "Selected building isn't a stockpile." << endl; + return CR_OK; + } + + ui->stockpile.custom_settings = sp->settings; + ui->main.mode = ui_sidebar_mode::Stockpiles; + world->selected_stockpile_type = stockpile_category::Custom; + + c->con << "Stockpile options copied." << endl; + return CR_OK; +} diff --git a/plugins/versionosd.cpp b/plugins/versionosd.cpp index b4d354ce5..466c4a45b 100644 --- a/plugins/versionosd.cpp +++ b/plugins/versionosd.cpp @@ -36,16 +36,16 @@ DFhackCExport const char * plugin_name ( void ) DFTileSurface* createTile(int x, int y) { - DFTileSurface* tile = new DFTileSurface; - tile->paintOver = true; - tile->rect = new DFSDL_Rect; - tile->rect->x = x*16; - tile->rect->y = y*16; - tile->rect->w = 16; - tile->rect->h = 16; - tile->surface = surface; - tile->dstResize = NULL; - return tile; + DFTileSurface* tile = new DFTileSurface; + tile->paintOver = true; + tile->rect = new DFSDL_Rect; + tile->rect->x = x*16; + tile->rect->y = y*16; + tile->rect->w = 16; + tile->rect->h = 16; + tile->surface = surface; + tile->dstResize = NULL; + return tile; } DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) @@ -55,72 +55,72 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector "Toggles displaying version in DF window", df_versionosd)); - HMODULE SDLImageLib = LoadLibrary("SDL_image.dll"); - _IMG_LoadPNG_RW = (DFHack::DFSDL_Surface* (*)(void*))GetProcAddress(SDLImageLib, "IMG_LoadPNG_RW"); + HMODULE SDLImageLib = LoadLibrary("SDL_image.dll"); + _IMG_LoadPNG_RW = (DFHack::DFSDL_Surface* (*)(void*))GetProcAddress(SDLImageLib, "IMG_LoadPNG_RW"); - HMODULE realSDLlib = LoadLibrary("SDLreal.dll"); - _SDL_RWFromFile = (void*(*)(const char*, const char*))GetProcAddress(realSDLlib,"SDL_RWFromFile"); - _SDL_SetAlpha = (int (*)(void*, uint32_t, uint8_t))GetProcAddress(realSDLlib,"SDL_SetAlpha"); + HMODULE realSDLlib = LoadLibrary("SDLreal.dll"); + _SDL_RWFromFile = (void*(*)(const char*, const char*))GetProcAddress(realSDLlib,"SDL_RWFromFile"); + _SDL_SetAlpha = (int (*)(void*, uint32_t, uint8_t))GetProcAddress(realSDLlib,"SDL_SetAlpha"); _SDL_SetColorKey = (int (*)(void*, uint32_t, uint32_t))GetProcAddress(realSDLlib,"SDL_SetColorKey"); - _SDL_MapRGB = (uint32_t (*)(void*, uint8_t, uint8_t, uint8_t))GetProcAddress(realSDLlib,"SDL_MapRGB"); + _SDL_MapRGB = (uint32_t (*)(void*, uint8_t, uint8_t, uint8_t))GetProcAddress(realSDLlib,"SDL_MapRGB"); - void* RWop = _SDL_RWFromFile(file, "rb"); - surface = _IMG_LoadPNG_RW(RWop); + void* RWop = _SDL_RWFromFile(file, "rb"); + surface = _IMG_LoadPNG_RW(RWop); - if ( !surface ) - { - c->con.print("Couldnt load image from file %s", file); - return CR_FAILURE; - } + if ( !surface ) + { + c->con.print("Couldnt load image from file %s", file); + return CR_FAILURE; + } - UINT32 pink = _SDL_MapRGB(vPtr(surface->format), 0xff, 0x00, 0xff); + UINT32 pink = _SDL_MapRGB(vPtr(surface->format), 0xff, 0x00, 0xff); - _SDL_SetColorKey((vPtr)surface, 4096, pink); - _SDL_SetAlpha((vPtr)surface, 65536, 255); + _SDL_SetColorKey((vPtr)surface, 4096, pink); + _SDL_SetAlpha((vPtr)surface, 65536, 255); - // setup tiles - tiles[0] = createTile(4, 4); // D - tiles[1] = createTile(6, 4); // F - tiles[2] = createTile(8, 4); // H - tiles[3] = createTile(1, 6); // a - tiles[4] = createTile(3, 6); // c - tiles[5] = createTile(11, 6); // k - tiles[6] = createTile(0, 0); // " " - // FIXME: it should get REAL version not hardcoded one - tiles[7] = createTile(2, 7); // r - tiles[8] = createTile(8, 3); // 8 + // setup tiles + tiles[0] = createTile(4, 4); // D + tiles[1] = createTile(6, 4); // F + tiles[2] = createTile(8, 4); // H + tiles[3] = createTile(1, 6); // a + tiles[4] = createTile(3, 6); // c + tiles[5] = createTile(11, 6); // k + tiles[6] = createTile(0, 0); // " " + // FIXME: it should get REAL version not hardcoded one + tiles[7] = createTile(2, 7); // r + tiles[8] = createTile(8, 3); // 8 - tiles[9] = createTile(9, 0); // o + tiles[9] = createTile(9, 0); // o - gui = c->getGui(); + gui = c->getGui(); - Graphic* g = c->getGraphic(); - g->Register(gettile); + Graphic* g = c->getGraphic(); + g->Register(gettile); return CR_OK; } DFhackCExport command_result plugin_shutdown ( Core * c ) { - Graphic* g = c->getGraphic(); - g->Unregister(gettile); - delete surface; + Graphic* g = c->getGraphic(); + g->Unregister(gettile); + delete surface; - for (int i=0; i<10; i++) - { - delete tiles[i]; - } - delete [] tiles; + for (int i=0; i<10; i++) + { + delete tiles[i]; + } + delete [] tiles; return CR_OK; } DFhackCExport command_result df_versionosd (Core * c, vector & parameters) { - On = !On; - c->Suspend(); + On = !On; + c->Suspend(); c->con.print("Version OSD is %s\n", On ? "On" : "Off"); c->Resume(); return CR_OK; @@ -128,21 +128,21 @@ DFhackCExport command_result df_versionosd (Core * c, vector & paramete DFTileSurface* gettile (int x, int y) { - if ( !On ) return NULL; - - if ( x == 0 && y-4 >= 0 && y-4 < 9 ) - { - return tiles[y-4]; - } - - int32_t cx, cy, cz; - int32_t vx, vy, vz; - if ( !gui->getViewCoords(vx, vy, vz) ) return NULL; - if ( !gui->getCursorCoords(cx, cy, cz) ) return NULL; - if ( cx-vx+1 == x && cy-vy+1 == y ) - { - return tiles[9]; - } - - return NULL; + if ( !On ) return NULL; + + if ( x == 0 && y-4 >= 0 && y-4 < 9 ) + { + return tiles[y-4]; + } + + int32_t cx, cy, cz; + int32_t vx, vy, vz; + if ( !gui->getViewCoords(vx, vy, vz) ) return NULL; + if ( !gui->getCursorCoords(cx, cy, cz) ) return NULL; + if ( cx-vx+1 == x && cy-vy+1 == y ) + { + return tiles[9]; + } + + return NULL; } \ No newline at end of file