Merge branch 'develop' into zone-unassign
						commit
						52728babd4
					
				| @ -0,0 +1,6 @@ | |||||||
|  | IF EXIST DF_PATH.txt SET /P _DF_PATH=<DF_PATH.txt | ||||||
|  | IF NOT EXIST DF_PATH.txt SET _DF_PATH=%CD%\DF | ||||||
|  | mkdir VC2010 | ||||||
|  | cd VC2010 | ||||||
|  | echo generating a build folder | ||||||
|  | cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX="%_DF_PATH%" -DBUILD_DEVEL=0 -DBUILD_DEV_PLUGINS=0 -DBUILD_DF2MC=1 -DBUILD_DFUSION=1 -DBUILD_STONESENSE=1 -DBUILD_SERVER=1 | ||||||
| @ -0,0 +1,4 @@ | |||||||
|  | # Add additional script search paths here | ||||||
|  | # Blank lines and lines that start with "#" will be ignored | ||||||
|  | # Paths preceded by "+" will be searched first | ||||||
|  | # Paths preceded by "-" will be searched after the default paths | ||||||
| @ -0,0 +1,605 @@ | |||||||
|  | :orphan: | ||||||
|  | 
 | ||||||
|  | .. _HISTORY: | ||||||
|  | 
 | ||||||
|  | ######################## | ||||||
|  | HISTORY - old changelogs | ||||||
|  | ######################## | ||||||
|  | 
 | ||||||
|  | This file is where old changelogs live, so the current `changelog` | ||||||
|  | in ``NEWS.rst`` doesn't get too long. | ||||||
|  | 
 | ||||||
|  | .. contents:: | ||||||
|  |    :depth: 2 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DFHack 0.40.23-r1 | ||||||
|  | ================= | ||||||
|  | 
 | ||||||
|  | Internals | ||||||
|  | - plugins will not be loaded if globals they specify as required are not located (should prevent some crashes) | ||||||
|  | 
 | ||||||
|  | Fixes | ||||||
|  | ----- | ||||||
|  | - Fixed numerous (mostly Lua-related) crashes on OS X by including a more up-to-date libstdc++ | ||||||
|  | - :kbd:`Alt` should no longer get stuck on Windows (and perhaps other platforms as well) | ||||||
|  | - `gui/advfort` works again | ||||||
|  | - `autobutcher`: takes sexualities into account | ||||||
|  | - devel/export-dt-ini: Updated for 0.40.20+ | ||||||
|  | - `digfort`: now checks file type and existence | ||||||
|  | - `exportlegends`: Fixed map export | ||||||
|  | - `full-heal`: Fixed a problem with selecting units in the GUI | ||||||
|  | - `gui/hack-wish`: Fixed restrictive material filters | ||||||
|  | - `mousequery`: Changed box-select key to Alt+M | ||||||
|  | - `dwarfmonitor`: correct date display (month index, separator) | ||||||
|  | - `putontable`: added to the readme | ||||||
|  | - `siren` should work again | ||||||
|  | - stderr.log: removed excessive debug output on OS X | ||||||
|  | - `trackstop`: No longer prevents cancelling the removal of a track stop or roller. | ||||||
|  | - Fixed a display issue with ``PRINT_MODE:TEXT`` | ||||||
|  | - Fixed a symbol error (MapExtras::BiomeInfo::MAX_LAYERS) when compiling DFHack in Debug mode | ||||||
|  | 
 | ||||||
|  | New Plugins | ||||||
|  | ----------- | ||||||
|  | - `fortplan`: designate construction of (limited) buildings from .csv file, quickfort-style | ||||||
|  | 
 | ||||||
|  | New Scripts | ||||||
|  | ----------- | ||||||
|  | - `gui/stockpiles`: an in-game interface for saving and loading stockpile settings files. | ||||||
|  | - `position`: Reports the current date, time, month, and season, plus some location info.  Port/update of position.py | ||||||
|  | - `hfs-pit`: Digs a hole to hell under the cursor.  Replaces needs_porting/hellhole.cpp | ||||||
|  | 
 | ||||||
|  | Removed | ||||||
|  | ------- | ||||||
|  | - embark.lua: Obsolete, use `embark-tools` | ||||||
|  | 
 | ||||||
|  | New tweaks | ||||||
|  | ---------- | ||||||
|  | - `eggs-fertile <tweak>`: Displays an egg fertility indicator on nestboxes | ||||||
|  | - `max-wheelbarrow <tweak>`: Allows assigning more than 3 wheelbarrows to a stockpile | ||||||
|  | 
 | ||||||
|  | Misc Improvements | ||||||
|  | ----------------- | ||||||
|  | - `embark-tools`: Added basic mouse support on the local map | ||||||
|  | - Made some adventure mode keybindings in :file:`dfhack.init-example` only work in adventure mode | ||||||
|  | - `gui/companion-order`: added a default keybinding | ||||||
|  | - further work on needs_porting | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DFHack 0.40.19-r1 | ||||||
|  | ================= | ||||||
|  | 
 | ||||||
|  | Fixes | ||||||
|  | ----- | ||||||
|  | - `modtools/reaction-trigger`: fixed typo | ||||||
|  | - `modtools/item-trigger`: should now work with item types | ||||||
|  | 
 | ||||||
|  | New plugins | ||||||
|  | ----------- | ||||||
|  | - `savestock, loadstock <stocksettings>`: save and load stockpile settings across worlds and saves | ||||||
|  | 
 | ||||||
|  | New scripts | ||||||
|  | ----------- | ||||||
|  | - `remove-stress`: set selected or all units unit to -1,000,000 stress (this script replaces removebadthoughts) | ||||||
|  | 
 | ||||||
|  | Misc improvements | ||||||
|  | ----------------- | ||||||
|  | - `command-prompt`: can now access selected items, units, and buildings | ||||||
|  | - `autolabor`: add an optional talent pool parameter | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DFHack 0.40.16-r1 | ||||||
|  | ================= | ||||||
|  | 
 | ||||||
|  | Internals | ||||||
|  | --------- | ||||||
|  | - `EventManager` should handle INTERACTION triggers a little better. It still can get confused about who did what but only rarely. | ||||||
|  | - `EventManager` should no longer trigger REPORT events for old reports after loading a save. | ||||||
|  | - lua/persist-table: a convenient way of using persistent tables of arbitrary structure and dimension in Lua | ||||||
|  | 
 | ||||||
|  | Fixes | ||||||
|  | ----- | ||||||
|  | - `mousequery`: Disabled when linking levers | ||||||
|  | - `stocks`: Melting should work now | ||||||
|  | - `full-heal`: Updated with proper argument handling | ||||||
|  | - `modtools/reaction-trigger-transition`: should produce the correct syntax now | ||||||
|  | - `superdwarf`: should work better now | ||||||
|  | - `forum-dwarves`: update for new df-structures changes | ||||||
|  | 
 | ||||||
|  | New Scripts | ||||||
|  | ----------- | ||||||
|  | - `adaptation`: view or set the cavern adaptation level of your citizens | ||||||
|  | - `add-thought`: allows the user to add thoughts to creatures. | ||||||
|  | - `gaydar`: detect the sexual orientation of units on the map | ||||||
|  | - `markdown`: Save a copy of a text screen in markdown (for reddit among others). | ||||||
|  | - devel/all-bob: renames everyone Bob to help test interaction-trigger | ||||||
|  | 
 | ||||||
|  | Misc Improvements | ||||||
|  | ----------------- | ||||||
|  | - `autodump`: Can now mark a stockpile for auto-dumping (similar to `automelt` and `autotrade`) | ||||||
|  | - `buildingplan`: Can now auto-allocate rooms to dwarves with specific positions (e.g. expedition leader, mayor) | ||||||
|  | - `dwarfmonitor`: now displays a weather indicator and date | ||||||
|  | - lua/syndrome-util, `modtools/add-syndrome`: now you can remove syndromes by SYN_CLASS | ||||||
|  | - No longer write empty :file:`.history` files | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DFHack 0.40.15-r1 | ||||||
|  | ================= | ||||||
|  | 
 | ||||||
|  | Fixes | ||||||
|  | ----- | ||||||
|  | - mousequery: Fixed behavior when selecting a tile on the lowest z-level | ||||||
|  | 
 | ||||||
|  | Misc Improvements | ||||||
|  | ----------------- | ||||||
|  | - `EventManager`: deals with frame_counter getting reset properly now. | ||||||
|  | - `modtools/item-trigger`: fixed equip/unequip bug and corrected minor documentation error | ||||||
|  | - `teleport`: Updated with proper argument handling and proper unit-at-destination handling. | ||||||
|  | - `autotrade`: Removed the newly obsolete :guilabel:`Mark all` functionality. | ||||||
|  | - `search-plugin`: Adapts to the new trade screen column width | ||||||
|  | - `tweak fast-trade <tweak>`: Switching the fast-trade keybinding to Shift-Up/Shift-Down, due to Select All conflict | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DFHack 0.40.14-r1 | ||||||
|  | ================= | ||||||
|  | 
 | ||||||
|  | Internals | ||||||
|  | --------- | ||||||
|  | - The DFHack console can now be disabled by setting the DFHACK_DISABLE_CONSOLE environment variable: ``DFHACK_DISABLE_CONSOLE=1 ./dfhack`` | ||||||
|  | 
 | ||||||
|  | Fixes | ||||||
|  | ----- | ||||||
|  | - Stopped duplicate load/unload events when unloading a world | ||||||
|  | - Stopped ``-e`` from being echoed when DFHack quits on Linux | ||||||
|  | - `automelt`: now uses a faster method to locate items | ||||||
|  | - `autotrade`: "Mark all" no longer double-marks bin contents | ||||||
|  | - `drain-aquifer`: new script replaces the buggy plugin | ||||||
|  | - `embark-tools`: no longer conflicts with keys on the notes screen | ||||||
|  | - `fastdwarf`: Fixed problems with combat/attacks | ||||||
|  | - `forum-dwarves`: should work now | ||||||
|  | - `manipulator`: now uses a stable sort, allowing sorting by multiple categories | ||||||
|  | - `rendermax`: updated to work with 0.40 | ||||||
|  | 
 | ||||||
|  | New Plugins | ||||||
|  | ----------- | ||||||
|  | - `trackstop`: Shows track stop friction and dump direction in its :kbd:`q` menu | ||||||
|  | 
 | ||||||
|  | New Tweaks | ||||||
|  | ---------- | ||||||
|  | - farm-plot-select: Adds "Select all" and "Deselect all" options to farm plot menus | ||||||
|  | - import-priority-category: Allows changing the priority of all goods in a category when discussing an import agreement with the liaison | ||||||
|  | - manager-quantity: Removes the limit of 30 jobs per manager order | ||||||
|  | - civ-view-agreement: Fixes overlapping text on the "view agreement" screen | ||||||
|  | - nestbox-color: Fixes the color of built nestboxes | ||||||
|  | 
 | ||||||
|  | Misc Improvements | ||||||
|  | ----------------- | ||||||
|  | - `exportlegends`: can now handle site maps | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DFHack 0.40.13-r1 | ||||||
|  | ================= | ||||||
|  | 
 | ||||||
|  | Internals | ||||||
|  | --------- | ||||||
|  | - unified spatter structs | ||||||
|  | - added ruby df.print_color(color, string) method for dfhack console | ||||||
|  | 
 | ||||||
|  | Fixes | ||||||
|  | ----- | ||||||
|  | - no more ``-e`` after terminating | ||||||
|  | - fixed `superdwarf` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DFHack 0.40.12-r1 | ||||||
|  | ================= | ||||||
|  | 
 | ||||||
|  | Internals | ||||||
|  | --------- | ||||||
|  | - support for global `onLoad.init` and `onUnload.init` files, called when loading and unloading a world | ||||||
|  | - Close file after loading a `binary patch <binpatches>`. | ||||||
|  | 
 | ||||||
|  | New Plugins | ||||||
|  | ----------- | ||||||
|  | - `hotkeys`: Shows ingame viewscreen with all dfhack keybindings active in current mode. | ||||||
|  | - `automelt`: allows marking stockpiles so any items placed in them will be designated for melting | ||||||
|  | 
 | ||||||
|  | Fixes | ||||||
|  | ----- | ||||||
|  | - possible crash fixed for `gui/hack-wish` | ||||||
|  | - `search-plugin`: updated to not conflict with BUILDJOB_SUSPEND | ||||||
|  | - `workflow`: job_material_category -> dfhack_material_category | ||||||
|  | 
 | ||||||
|  | Misc Improvements | ||||||
|  | ----------------- | ||||||
|  | - now you can use ``@`` to print things in interactive Lua with subtley different semantics | ||||||
|  | - optimizations for stockpiles for `autotrade` and `stockflow` | ||||||
|  | - updated `exportlegends` to work with new maps, dfhack 40.11 r1+ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DFHack 0.40.11-r1 | ||||||
|  | ================= | ||||||
|  | 
 | ||||||
|  | Internals | ||||||
|  | - Plugins on OS X now use ``.plug.dylib` as an extension instead of ``.plug.so`` | ||||||
|  | 
 | ||||||
|  | Fixes | ||||||
|  | ----- | ||||||
|  | - `3dveins`: should no longer hang/crash on specific maps | ||||||
|  | - `autotrade`, `search-plugin`: fixed some layout issues | ||||||
|  | - `deathcause`: updated | ||||||
|  | - `gui/hack-wish`: should work now | ||||||
|  | - `reveal`: no longer allocates data for nonexistent map blocks | ||||||
|  | - Various documentation fixes and updates | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DFHack v0.40.10-r1 | ||||||
|  | ================== | ||||||
|  | 
 | ||||||
|  | A few bugfixes. | ||||||
|  | 
 | ||||||
|  | DFHack v0.40.08-r2 | ||||||
|  | ================== | ||||||
|  | 
 | ||||||
|  | Internals | ||||||
|  | --------- | ||||||
|  | - supported per save script folders | ||||||
|  | - Items module: added createItem function | ||||||
|  | - Sorted CMakeList for plugins and plugins/devel | ||||||
|  | - `diggingInvaders` no longer builds if plugin building is disabled | ||||||
|  | - `EventManager`: EQUIPMENT_CHANGE now triggers for new units.  New events:: | ||||||
|  | 
 | ||||||
|  |             ON_REPORT | ||||||
|  |             UNIT_ATTACK | ||||||
|  |             UNLOAD | ||||||
|  |             INTERACTION | ||||||
|  | 
 | ||||||
|  | New Scripts | ||||||
|  | ----------- | ||||||
|  | - lua/repeat-util: makes it easier to make things repeat indefinitely | ||||||
|  | - lua/syndrome-util: makes it easier to deal with unit syndromes | ||||||
|  | - `forum-dwarves`: helps copy df viewscreens to a file | ||||||
|  | - `full-heal`: fully heal a unit | ||||||
|  | - `remove-wear`: removes wear from all items in the fort | ||||||
|  | - `repeat`: repeatedly calls a script or a plugin | ||||||
|  | - ShowUnitSyndromes: shows syndromes affecting units and other relevant info | ||||||
|  | - `teleport`: teleports units | ||||||
|  | - `devel/print-args` | ||||||
|  | - `fix/blood-del`: makes it so civs don't bring barrels full of blood ichor or goo | ||||||
|  | - `fix/feeding-timers`: reset the feeding timers of all units | ||||||
|  | - `gui/hack-wish`: creates items out of any material | ||||||
|  | - `gui/unit-info-viewer`: displays information about units | ||||||
|  | - `modtools/add-syndrome`: add a syndrome to a unit or remove one | ||||||
|  | - `modtools/anonymous-script`: execute an lua script defined by a string. Useful for the ``*-trigger`` scripts. | ||||||
|  | - `modtools/force`: forces events: caravan, migrants, diplomat, megabeast, curiousbeast, mischievousbeast, flier, siege, nightcreature | ||||||
|  | - `modtools/item-trigger`: triggers commands based on equipping, unequipping, and wounding units with items | ||||||
|  | - `modtools/interaction-trigger`: triggers commands when interactions happen | ||||||
|  | - `modtools/invader-item-destroyer`: destroys invaders' items when they die | ||||||
|  | - `modtools/moddable-gods`: standardized version of Putnam's moddable gods script | ||||||
|  | - `modtools/projectile-trigger`: standardized version of projectileExpansion | ||||||
|  | - `modtools/reaction-trigger`: trigger commands when custom reactions complete; replaces autoSyndrome | ||||||
|  | - `modtools/reaction-trigger-transition`: a tool for converting mods from autoSyndrome to reaction-trigger | ||||||
|  | - `modtools/random-trigger`: triggers random scripts that you register | ||||||
|  | - `modtools/skill-change`: for incrementing and setting skills | ||||||
|  | - `modtools/spawn-flow`: creates flows, like mist or dragonfire | ||||||
|  | - `modtools/syndrome-trigger`: trigger commands when syndromes happen | ||||||
|  | - `modtools/transform-unit`: shapeshifts a unit, possibly permanently | ||||||
|  | 
 | ||||||
|  | Misc improvements | ||||||
|  | ----------------- | ||||||
|  | - new function in utils.lua for standardized argument processing | ||||||
|  | 
 | ||||||
|  | Removed | ||||||
|  | ------- | ||||||
|  | - digmat.rb: digFlood does the same functionality with less FPS impact | ||||||
|  | - invasionNow: `modtools/force` does it better | ||||||
|  | - autoSyndrome replaced with `modtools/reaction-trigger` | ||||||
|  | - syndromeTrigger replaced with `modtools/syndrome-trigger` | ||||||
|  | - devel/printArgs plugin converted to `devel/print-args` | ||||||
|  | - outsideOnly plugin replaced by `modtools/outside-only` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DFHack v0.40.08-r1 | ||||||
|  | ================== | ||||||
|  | 
 | ||||||
|  | Was a mistake. Don't use it. | ||||||
|  | 
 | ||||||
|  | DFHack v0.34.11-r5 | ||||||
|  | ================== | ||||||
|  | 
 | ||||||
|  | Internals | ||||||
|  | --------- | ||||||
|  | - support for calling a lua function via a protobuf request (demonstrated by dfhack-run --lua). | ||||||
|  | - support for basic filesystem operations (e.g. chdir, mkdir, rmdir, stat) in C++ and Lua | ||||||
|  | - Lua API for listing files in directory. Needed for `gui/mod-manager` | ||||||
|  | - Lua API for creating unit combat reports and writing to gamelog. | ||||||
|  | - Lua API for running arbitrary DFHack commands | ||||||
|  | - support for multiple ``raw/init.d/*.lua`` init scripts in one save. | ||||||
|  | - eventful now has a more friendly way of making custom sidebars | ||||||
|  | - on Linux and OS X the console now supports moving the cursor back and forward by a whole word. | ||||||
|  | 
 | ||||||
|  | New scripts | ||||||
|  | ----------- | ||||||
|  | - `gui/mod-manager`: allows installing/uninstalling mods into df from ``df/mods`` directory. | ||||||
|  | - `gui/clone-uniform`: duplicates the currently selected uniform in the military screen. | ||||||
|  | - `fix/build-location`: partial work-around for :bug:`5991` (trying to build wall while standing on it) | ||||||
|  | - `undump-buildings`: removes dump designation from materials used in buildings. | ||||||
|  | - `exportlegends`: exports data from legends mode, allowing a set-and-forget export of large worlds. | ||||||
|  | - log-region: each time a fort is loaded identifying information will be written to the gamelog. | ||||||
|  | - `dfstatus <gui/dfstatus>`: show an overview of critical stock quantities, including food, drinks, wood, and bars. | ||||||
|  | - `command-prompt`: a dfhack command prompt in df. | ||||||
|  | 
 | ||||||
|  | New plugins | ||||||
|  | ----------- | ||||||
|  | - `rendermax`: replace the renderer with something else, eg ``rendermax light``- a lighting engine | ||||||
|  | - `automelt`: allows marking stockpiles for automelt (i.e. any items placed in stocpile will be designated for melting) | ||||||
|  | - `embark-tools`: implementations of Embark Anywhere, Nano Embark, and a few other embark-related utilities | ||||||
|  | - `building-hacks`: Allows to add custom functionality and/or animations to buildings. | ||||||
|  | - `petcapRemover`: triggers pregnancies in creatures so that you can effectively raise the default pet population cap | ||||||
|  | - `plant create <plant>`: spawn a new shrub under the cursor | ||||||
|  | 
 | ||||||
|  | New tweaks | ||||||
|  | ---------- | ||||||
|  | - craft-age-wear: make crafted items wear out with time like in old versions (:bug:`6003`) | ||||||
|  | - adamantine-cloth-wear: stop adamantine clothing from wearing out (:bug:`6481`) | ||||||
|  | - confirm-embark: adds a prompt before embarking (on the "prepare carefully" screen) | ||||||
|  | 
 | ||||||
|  | Misc improvements | ||||||
|  | ----------------- | ||||||
|  | - `plant`: move the 'grow', 'extirpate' and 'immolate' commands as 'plant' subcommands | ||||||
|  | - `digfort`: improved csv parsing, add start() comment handling | ||||||
|  | - `exterminate`: allow specifying a caste (exterminate gob:male) | ||||||
|  | - `createitem`: in adventure mode it now defaults to the controlled unit as maker. | ||||||
|  | - `autotrade`: adds "(Un)mark All" options to both panes of trade screen. | ||||||
|  | - `mousequery`: several usability improvements; show live overlay (in menu area) of what's on the tile under the mouse cursor. | ||||||
|  | - `search`: workshop profile search added. | ||||||
|  | - `dwarfmonitor`: add screen to summarise preferences of fortress dwarfs. | ||||||
|  | - `getplants`: add autochop function to automate woodcutting. | ||||||
|  | - `stocks`: added more filtering and display options. | ||||||
|  | 
 | ||||||
|  | - `siege-engine`: | ||||||
|  | 
 | ||||||
|  |     - engine quality and distance to target now affect accuracy | ||||||
|  |     - firing the siege engine at a target produces a combat report | ||||||
|  |     - improved movement speed computation for meandering units | ||||||
|  |     - operators in Prepare To Fire mode are released from duty once hungry/thirsty if there is a free replacement | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DFHack v0.34.11-r4 | ||||||
|  | ================== | ||||||
|  | 
 | ||||||
|  | New commands | ||||||
|  | ------------ | ||||||
|  | - `diggingInvaders` - allows invaders to dig and/or deconstruct walls and buildings in order to get at your dwarves. | ||||||
|  | - `digFlood` - automatically dig out specified veins as they are revealed | ||||||
|  | - `enable, disable <enable>` - Built-in commands that can be used to enable/disable many plugins. | ||||||
|  | - `restrictice` - Restrict traffic on squares above visible ice. | ||||||
|  | - `restrictliquids` - Restrict traffic on every visible square with liquid. | ||||||
|  | - treefarm - automatically chop trees and dig obsidian | ||||||
|  | 
 | ||||||
|  | New Scripts | ||||||
|  | ----------- | ||||||
|  | - `autobutcher`: A GUI front-end for the autobutcher plugin. | ||||||
|  | - invasionNow: trigger an invasion, or many | ||||||
|  | - `locate-ore`: scan the map for unmined ore veins | ||||||
|  | - `masspit`: designate caged creatures in a zone for pitting | ||||||
|  | - `multicmd`: run a sequence of dfhack commands, separated by ';' | ||||||
|  | - `startdwarf`: change the number of dwarves for a new embark | ||||||
|  | - digmat: dig veins/layers tile by tile, as discovered | ||||||
|  | 
 | ||||||
|  | Misc improvements | ||||||
|  | ----------------- | ||||||
|  | - autoSyndrome: | ||||||
|  | 
 | ||||||
|  |     - disable by default | ||||||
|  |     - reorganized special tags | ||||||
|  |     - minimized error spam | ||||||
|  |     - reset policies: if the target already has an instance of the syndrome you can skip, | ||||||
|  |       add another instance, reset the timer, or add the full duration to the time remaining | ||||||
|  | 
 | ||||||
|  | - core: fix SC_WORLD_(UN)LOADED event for arena mode | ||||||
|  | - `exterminate`: renamed from slayrace, add help message, add butcher mode | ||||||
|  | - `fastdwarf`: fixed bug involving fastdwarf and teledwarf being on at the same time | ||||||
|  | - magmasource: rename to `source`, allow water/magma sources/drains | ||||||
|  | - Add df.dfhack_run "somecommand" to Ruby | ||||||
|  | - syndromeTrigger: replaces and extends trueTransformation. Can trigger things when syndromes are added for any reason. | ||||||
|  | - `tiletypes`: support changing tile material to arbitrary stone. | ||||||
|  | - `workNow`: can optionally look for jobs when jobs are completed | ||||||
|  | 
 | ||||||
|  | New tweaks | ||||||
|  | ---------- | ||||||
|  | - hive-crash: Prevent crash if bees die in a hive with ungathered products (:bug:`6368`). | ||||||
|  | 
 | ||||||
|  | New plugins | ||||||
|  | ----------- | ||||||
|  | - `3dveins`: Reshapes all veins on the map in a way that flows between Z levels. May be unstable. Backup before using. | ||||||
|  | - `autotrade`: Automatically send items in marked stockpiles to trade depot, when trading is possible. | ||||||
|  | - `buildingplan`: Place furniture before it's built | ||||||
|  | - `dwarfmonitor`: Records dwarf activity to measure fort efficiency | ||||||
|  | - `mousequery`: Look and poke at the map elements with the mouse. | ||||||
|  | - outsideOnly: make raw-specified buildings impossible to build inside | ||||||
|  | - `resume`: A plugin to help display and resume suspended constructions conveniently | ||||||
|  | - `stocks`: An improved stocks display screen. | ||||||
|  | 
 | ||||||
|  | Internals | ||||||
|  | --------- | ||||||
|  | - Core: there is now a per-save dfhack.init file for when the save is loaded, and another for when it is unloaded | ||||||
|  | - EventManager: fixed job completion detection, fixed removal of TICK events, added EQUIPMENT_CHANGE event | ||||||
|  | - Lua API for a better `random number generator <lua_api_random>` and perlin noise functions. | ||||||
|  | - Once: easy way to make sure something happens once per run of DF, such as an error message | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | DFHack v0.34.11-r3 | ||||||
|  | ================== | ||||||
|  | 
 | ||||||
|  | Internals | ||||||
|  | --------- | ||||||
|  | - support for displaying active keybindings properly. | ||||||
|  | - support for reusable widgets in lua screen library. | ||||||
|  | - Maps::canStepBetween: returns whether you can walk between two tiles in one step. | ||||||
|  | - EventManager: monitors various in game events centrally so that individual plugins | ||||||
|  |   don't have to monitor the same things redundantly. | ||||||
|  | - Now works with OS X 10.6.8 | ||||||
|  | 
 | ||||||
|  | Notable bugfixes | ||||||
|  | ---------------- | ||||||
|  | - `autobutcher` can be re-enabled again after being stopped. | ||||||
|  | - stopped `Dwarf Manipulator <manipulator>` from unmasking vampires. | ||||||
|  | - `stonesense` is now fixed on OS X | ||||||
|  | 
 | ||||||
|  | Misc improvements | ||||||
|  | ----------------- | ||||||
|  | - `fastdwarf`: new mode using debug flags, and some internal consistency fixes. | ||||||
|  | - added a small stand-alone utility for applying and removing `binary patches <binpatches>`. | ||||||
|  | - removebadthoughts: add --dry-run option | ||||||
|  | - `superdwarf`: work in adventure mode too | ||||||
|  | - `tweak` stable-cursor: carries cursor location from/to Build menu. | ||||||
|  | - `deathcause`: allow selection from the unitlist screen | ||||||
|  | - slayrace: allow targetting undeads | ||||||
|  | - `workflow` plugin: | ||||||
|  | 
 | ||||||
|  |     - properly considers minecarts assigned to routes busy. | ||||||
|  |     - code for deducing job outputs rewritten in lua for flexibility. | ||||||
|  |     - logic fix: collecting webs produces silk, and ungathered webs are not thread. | ||||||
|  |     - items assigned to squads are considered busy, even if not in inventory. | ||||||
|  |     - shearing and milking jobs are supported, but only with generic MILK or YARN outputs. | ||||||
|  |     - workflow announces when the stock level gets very low once a season. | ||||||
|  | 
 | ||||||
|  | - Auto syndrome plugin: A way of automatically applying boiling rock syndromes and calling dfhack commands controlled by raws. | ||||||
|  | - `infiniteSky` plugin: Create new z-levels automatically or on request. | ||||||
|  | - True transformation plugin: A better way of doing permanent transformations that allows later transformations. | ||||||
|  | - `workNow` plugin: Makes the game assign jobs every time you pause. | ||||||
|  | 
 | ||||||
|  | New tweaks | ||||||
|  | ---------- | ||||||
|  | - tweak military-training: speed up melee squad training up to 10x (normally 3-5x). | ||||||
|  | 
 | ||||||
|  | New scripts | ||||||
|  | ----------- | ||||||
|  | - `binpatch`: the same as the stand-alone binpatch.exe, but works at runtime. | ||||||
|  | - region-pops: displays animal populations of the region and allows tweaking them. | ||||||
|  | - `lua`: lua interpreter front-end converted to a script from a native command. | ||||||
|  | - dfusion: misc scripts with a text based menu. | ||||||
|  | - embark: lets you embark anywhere. | ||||||
|  | - `lever`: list and pull fort levers from the dfhack console. | ||||||
|  | - `stripcaged`: mark items inside cages for dumping, eg caged goblin weapons. | ||||||
|  | - soundsense-season: writes the correct season to gamelog.txt on world load. | ||||||
|  | - create-items: spawn items | ||||||
|  | - fix/cloth-stockpile: fixes :bug:`5739`; needs to be run after savegame load every time. | ||||||
|  | 
 | ||||||
|  | New GUI scripts | ||||||
|  | --------------- | ||||||
|  | - `gui/guide-path`: displays the cached path for minecart Guide orders. | ||||||
|  | - `gui/workshop-job`: displays inputs of a workshop job and allows tweaking them. | ||||||
|  | - `gui/workflow`: a front-end for the workflow plugin (part inspired by falconne). | ||||||
|  | - `gui/assign-rack`: works together with a binary patch to fix weapon racks. | ||||||
|  | - `gui/gm-editor`: an universal editor for lots of dfhack things. | ||||||
|  | - `gui/companion-order`: a adventure mode command interface for your companions. | ||||||
|  | - `gui/advfort`: a way to do jobs with your adventurer (e.g. build fort). | ||||||
|  | 
 | ||||||
|  | New binary patches | ||||||
|  | ------------------ | ||||||
|  | (for use with `binpatch`) | ||||||
|  | 
 | ||||||
|  | - armorstand-capacity: doubles the capacity of armor stands. | ||||||
|  | - custom-reagent-size: lets custom reactions use small amounts of inputs. | ||||||
|  | - deconstruct-heapfall: stops some items still falling on head when deconstructing. | ||||||
|  | - deconstruct-teleport: stops items from 16x16 block teleporting when deconstructing. | ||||||
|  | - hospital-overstocking: stops hospital overstocking with supplies. | ||||||
|  | - training-ammo: lets dwarves with quiver full of combat-only ammo train. | ||||||
|  | - weaponrack-unassign: fixes bug that negates work done by gui/assign-rack. | ||||||
|  | 
 | ||||||
|  | New Plugins | ||||||
|  | ----------- | ||||||
|  | - `fix-armory`: Together with a couple of binary patches and the `gui/assign-rack` script, this plugin makes weapon racks, armor stands, chests and cabinets in properly designated barracks be used again for storage of squad equipment. | ||||||
|  | - `search`: Adds an incremental search function to the Stocks, Trading, Stockpile and Unit List screens. | ||||||
|  | - `automaterial`: Makes building constructions (walls, floors, fortifications, etc) a little bit easier by saving you from having to trawl through long lists of materials each time you place one. | ||||||
|  | - Dfusion: Reworked to make use of lua modules, now all the scripts can be used from other scripts. | ||||||
|  | - Eventful: A collection of lua events, that will allow new ways to interact with df world. | ||||||
|  | 
 | ||||||
|  | DFHack v0.34.11-r2 | ||||||
|  | ================== | ||||||
|  | 
 | ||||||
|  | Internals | ||||||
|  | --------- | ||||||
|  | - full support for Mac OS X. | ||||||
|  | - a plugin that adds scripting in `ruby <rb>`. | ||||||
|  | - support for interposing virtual methods in DF from C++ plugins. | ||||||
|  | - support for creating new interface screens from C++ and lua. | ||||||
|  | - added various other API functions. | ||||||
|  | 
 | ||||||
|  | Notable bugfixes | ||||||
|  | ---------------- | ||||||
|  | - better terminal reset after exit on linux. | ||||||
|  | - `seedwatch` now works on reclaim. | ||||||
|  | - the sort plugin won't crash on cages anymore. | ||||||
|  | 
 | ||||||
|  | Misc improvements | ||||||
|  | ----------------- | ||||||
|  | - `autodump`: can move items to any walkable tile, not just floors. | ||||||
|  | - `stripcaged`: by default keep armor, new dumparmor option. | ||||||
|  | - `zone`: allow non-domesticated birds in nestboxes. | ||||||
|  | - `workflow`: quality range in constraints. | ||||||
|  | - cleanplants: new command to remove rain water from plants. | ||||||
|  | - `liquids`: can paint permaflow, i.e. what makes rivers power water wheels. | ||||||
|  | - `prospect`: pre-embark prospector accounts for caves & magma sea in its estimate. | ||||||
|  | - `rename`: supports renaming stockpiles, workshops, traps, siege engines. | ||||||
|  | - `fastdwarf`: now has an additional option to make dwarves teleport to their destination. | ||||||
|  | - `autolabor`: | ||||||
|  | 
 | ||||||
|  |     - can set nonidle hauler percentage. | ||||||
|  |     - broker excluded from all labors when needed at depot. | ||||||
|  |     - likewise, anybody with a scheduled diplomat meeting. | ||||||
|  | 
 | ||||||
|  | New commands | ||||||
|  | ------------ | ||||||
|  | - misery: multiplies every negative thought gained (2x by default). | ||||||
|  | - `digtype`: designates every tile of the same type of vein on the map for 'digging' (any dig designation). | ||||||
|  | 
 | ||||||
|  | New tweaks | ||||||
|  | ---------- | ||||||
|  | - tweak stable-cursor: keeps exact cursor position between d/k/t/q/v etc menus. | ||||||
|  | - tweak patrol-duty: makes Train orders reduce patrol timer, like the binary patch does. | ||||||
|  | - tweak readable-build-plate: fix unreadable truncation in unit pressure plate build ui. | ||||||
|  | - tweak stable-temp: fixes bug 6012; may improve FPS by 50-100% on a slow item-heavy fort. | ||||||
|  | - tweak fast-heat: speeds up item heating & cooling, thus making stable-temp act faster. | ||||||
|  | - tweak fix-dimensions: fixes subtracting small amounts from stacked liquids etc. | ||||||
|  | - tweak advmode-contained: fixes UI bug in custom reactions with container inputs in advmode. | ||||||
|  | - tweak fast-trade: Shift-Enter for selecting items quckly in Trade and Move to Depot screens. | ||||||
|  | - tweak military-stable-assign: Stop rightmost list of military->Positions from jumping to top. | ||||||
|  | - tweak military-color-assigned: In same list, color already assigned units in brown & green. | ||||||
|  | 
 | ||||||
|  | New scripts | ||||||
|  | ----------- | ||||||
|  | - `fixnaked`: removes thoughts about nakedness. | ||||||
|  | - `setfps`: set FPS cap at runtime, in case you want slow motion or speed-up. | ||||||
|  | - `siren`: wakes up units, stops breaks and parties - but causes bad thoughts. | ||||||
|  | - `fix/population-cap`: run after every migrant wave to prevent exceeding the cap. | ||||||
|  | - `fix/stable-temp`: counts items with temperature updates; does instant one-shot stable-temp. | ||||||
|  | - `fix/loyaltycascade`: fix units allegiance, eg after ordering a dwarf merchant kill. | ||||||
|  | - `deathcause`: shows the circumstances of death for a given body. | ||||||
|  | - `digfort`: designate areas to dig from a csv file. | ||||||
|  | - `drain-aquifer`: remove aquifers from the map. | ||||||
|  | - `growcrops`: cheat to make farm crops instantly grow. | ||||||
|  | - magmasource: continuously spawn magma from any map tile. | ||||||
|  | - removebadthoughts: delete all negative thoughts from your dwarves. | ||||||
|  | - slayrace: instakill all units of a given race, optionally with magma. | ||||||
|  | - `superdwarf`: per-creature `fastdwarf`. | ||||||
|  | - `gui/mechanisms`: browse mechanism links of the current building. | ||||||
|  | - `gui/room-list`: browse other rooms owned by the unit when assigning one. | ||||||
|  | - `gui/liquids`: a GUI front-end for the liquids plugin. | ||||||
|  | - `gui/rename`: renaming stockpiles, workshops and units via an in-game dialog. | ||||||
|  | - `gui/power-meter`: front-end for the Power Meter plugin. | ||||||
|  | - `gui/siege-engine`: front-end for the Siege Engine plugin. | ||||||
|  | - `gui/choose-weapons`: auto-choose matching weapons in the military equip screen. | ||||||
|  | 
 | ||||||
|  | New Plugins | ||||||
|  | ----------- | ||||||
|  | - `manipulator`: a Dwarf Therapist like UI in the game (:kbd:`u`:kbd:`l`) | ||||||
|  | - `steam-engine`: an alternative to Water Reactors which make more sense. | ||||||
|  |   See ``hack/raw/*_steam_engine.txt`` for the necessary raw definitions. | ||||||
|  | - `power-meter`: a pressure plate modification to detect powered gear | ||||||
|  |   boxes on adjacent tiles. `gui/power-meter` implements | ||||||
|  |   the build configuration UI. | ||||||
|  | - `siege-engine`:  massive overhaul for siege engines, configured via `gui/siege-engine` | ||||||
|  | - `add-spatter`: allows poison coatings via raw reactions, among other things. | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | <!DOCTYPE HTML> | ||||||
|  | <!-- | ||||||
|  |     DO NOT CHANGE THIS FILE - it redirects to the actual documentation. | ||||||
|  |     If the page is not found, you can read the raw docs in the docs folder. | ||||||
|  | 
 | ||||||
|  |     This file is an additional redirect for users in the DFHack code repo | ||||||
|  |     who are visiting from ../README.html | ||||||
|  | 
 | ||||||
|  |     For end-users, the real index.html will be in this relative location. | ||||||
|  |     --> | ||||||
|  | <html lang="en-US"> | ||||||
|  |     <head> | ||||||
|  |         <meta charset="UTF-8"> | ||||||
|  |         <meta http-equiv="refresh" content="0;url=./html/index.html"> | ||||||
|  |         <script type="text/javascript"> | ||||||
|  |             window.location.href = "./html/index.html" | ||||||
|  |         </script> | ||||||
|  |         <title>Page Redirection</title> | ||||||
|  |     </head> | ||||||
|  |     <body> | ||||||
|  |         Follow this <a href='./html/index.html'>link to the documentation.</a> | ||||||
|  |     </body> | ||||||
|  | </html> | ||||||
| @ -0,0 +1,2 @@ | |||||||
|  | *.cpp | ||||||
|  | *.tmp | ||||||
| @ -0,0 +1 @@ | |||||||
|  | friend struct df::world; | ||||||
| @ -0,0 +1 @@ | |||||||
|  | friend struct df::world; | ||||||
| @ -1 +1 @@ | |||||||
| Subproject commit 49eff8dca662bff83ff2191ac5b611504c72ae1c | Subproject commit 58806dc7e4bfcc1bb5f33b15395bdc9fd5a1ea28 | ||||||
| @ -1,11 +0,0 @@ | |||||||
| include_directories(include) |  | ||||||
| 
 |  | ||||||
| FILE(GLOB DFUSION_CPPS src/*.c*) |  | ||||||
| set( |  | ||||||
|     DFUSION_CPPS_ALL |  | ||||||
|     dfusion.cpp |  | ||||||
|     ${DFUSION_CPPS} |  | ||||||
| ) |  | ||||||
| FILE(GLOB DFUSION_HS include/*) |  | ||||||
| SET_SOURCE_FILES_PROPERTIES( ${DFUSION_HS} PROPERTIES HEADER_FILE_ONLY TRUE ) |  | ||||||
| DFHACK_PLUGIN(dfusion  ${DFUSION_CPPS_ALL} ${DFUSION_HS} LINK_LIBRARIES lua dfhack-tinythread) |  | ||||||
| @ -1,88 +0,0 @@ | |||||||
| #include "Core.h" |  | ||||||
| #include "Export.h" |  | ||||||
| #include "PluginManager.h" |  | ||||||
| #include "MemAccess.h" |  | ||||||
| #include "MiscUtils.h" |  | ||||||
| #include <vector> |  | ||||||
| #include <string> |  | ||||||
| 
 |  | ||||||
| #include "luamain.h" |  | ||||||
| #include "lua_Process.h" |  | ||||||
| #include "lua_Hexsearch.h" |  | ||||||
| #include "lua_Misc.h" |  | ||||||
| 
 |  | ||||||
| #include "DataDefs.h" |  | ||||||
| #include "LuaTools.h" |  | ||||||
| 
 |  | ||||||
| using std::vector; |  | ||||||
| using std::string; |  | ||||||
| using namespace DFHack; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| DFHACK_PLUGIN("dfusion") |  | ||||||
| 
 |  | ||||||
| static int loadObjectFile(lua_State* L) |  | ||||||
| { |  | ||||||
|     std::string path; |  | ||||||
| 
 |  | ||||||
|     path=luaL_checkstring(L,1); |  | ||||||
| 
 |  | ||||||
|     OutFile::File f(path); |  | ||||||
|     lua_newtable(L); |  | ||||||
|     int table_pos=lua_gettop(L); |  | ||||||
|     size_t size=f.GetTextSize(); |  | ||||||
|     Lua::Push(L,size); |  | ||||||
|     lua_setfield(L,table_pos,"data_size"); |  | ||||||
|     char* buf=new char[size]; |  | ||||||
|     f.GetText(buf); |  | ||||||
| 
 |  | ||||||
|     //Lua::PushDFObject(L,DFHack::,buf);
 |  | ||||||
|     //Lua::Push(L,buf);
 |  | ||||||
|     lua_pushlightuserdata(L,buf); |  | ||||||
|     lua_setfield(L,table_pos,"data"); |  | ||||||
|     const OutFile::vSymbol &symbols=f.GetSymbols(); |  | ||||||
|     lua_newtable(L); |  | ||||||
|     for(size_t i=0;i<symbols.size();i++) |  | ||||||
|     { |  | ||||||
|         Lua::Push(L,i); |  | ||||||
|         lua_newtable(L); |  | ||||||
|         Lua::Push(L,symbols[i].name); |  | ||||||
|         lua_setfield(L,-2,"name"); |  | ||||||
|         Lua::Push(L,symbols[i].pos); |  | ||||||
|         lua_setfield(L,-2,"pos"); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         lua_settable(L,-3); |  | ||||||
|     } |  | ||||||
|     lua_setfield(L,table_pos,"symbols"); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| static int markAsExecutable(lua_State* L) |  | ||||||
| { |  | ||||||
|     unsigned addr=luaL_checkunsigned(L,1); |  | ||||||
|     std::vector<DFHack::t_memrange> ranges; |  | ||||||
|     DFHack::Core::getInstance().p->getMemRanges(ranges); |  | ||||||
|     for(size_t i=0;i<ranges.size();i++) |  | ||||||
|     { |  | ||||||
|         if(ranges[i].isInRange((void*)addr)) |  | ||||||
|         { |  | ||||||
|             DFHack::t_memrange newperm=ranges[i]; |  | ||||||
|             newperm.execute=true; |  | ||||||
|             DFHack::Core::getInstance().p->setPermisions(ranges[i],newperm); |  | ||||||
|             return 0; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     lua_pushlstring(L,"Memory range not found",23); |  | ||||||
|     lua_error(L); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| DFHACK_PLUGIN_LUA_COMMANDS { |  | ||||||
|     DFHACK_LUA_COMMAND(loadObjectFile), |  | ||||||
|     DFHACK_LUA_COMMAND(markAsExecutable), |  | ||||||
|     DFHACK_LUA_END |  | ||||||
| }; |  | ||||||
| DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) |  | ||||||
| { |  | ||||||
|     return CR_OK; |  | ||||||
| } |  | ||||||
| @ -1,126 +0,0 @@ | |||||||
| #ifndef OUTFILE_H |  | ||||||
| #define OUTFILE_H |  | ||||||
| #include <string> |  | ||||||
| #include <fstream> |  | ||||||
| #include <iostream> |  | ||||||
| #include <map> |  | ||||||
| #include <vector> |  | ||||||
| namespace OutFile |  | ||||||
| { |  | ||||||
| struct Header |  | ||||||
| { |  | ||||||
|         unsigned short machinetype; |  | ||||||
|         unsigned short sectioncount; |  | ||||||
|         unsigned long time; |  | ||||||
|         unsigned long symbolptr; |  | ||||||
|         unsigned long symbolcount; |  | ||||||
|         unsigned short opthead; |  | ||||||
|         unsigned short flags; |  | ||||||
|      void PrintData() |  | ||||||
|     { |  | ||||||
|         std::cout<<"Symbol start:"<<symbolptr<<"\n"; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| struct Section |  | ||||||
| { |  | ||||||
|     char name[8]; |  | ||||||
|     unsigned long Vsize; |  | ||||||
|     unsigned long Vstart; |  | ||||||
|     unsigned long size; |  | ||||||
|     unsigned long start; |  | ||||||
|     unsigned long ptrRel; |  | ||||||
|     unsigned long ptrLine; |  | ||||||
|     unsigned short numRel; |  | ||||||
|     unsigned short numLine; |  | ||||||
|     unsigned long flags; |  | ||||||
|     void PrintData() |  | ||||||
|     { |  | ||||||
|         std::cout<<name<<" size:"<<size<<" start:"<<start<<"\n"; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| struct Symbol |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
|     std::string name; |  | ||||||
|     unsigned long pos; |  | ||||||
|     unsigned short sectnumb; |  | ||||||
|     unsigned short type; |  | ||||||
|     unsigned char storageclass; |  | ||||||
|     unsigned char auxsymbs; |  | ||||||
|     //char unk2[6];
 |  | ||||||
|     void Read(std::iostream &s,unsigned long strptr) |  | ||||||
|     { |  | ||||||
|         union |  | ||||||
|         { |  | ||||||
|             char buf[8]; |  | ||||||
|             struct |  | ||||||
|             { |  | ||||||
|             unsigned long zeros; |  | ||||||
|             unsigned long strptr; |  | ||||||
|             }; |  | ||||||
| 
 |  | ||||||
|         }data; |  | ||||||
| 
 |  | ||||||
|         s.read((char*)&data,8); |  | ||||||
|         s.read((char*)&pos,4); |  | ||||||
|         s.read((char*)§numb,2); |  | ||||||
|         s.read((char*)&type,2); |  | ||||||
|         s.read((char*)&storageclass,1); |  | ||||||
|         s.read((char*)&auxsymbs,1); |  | ||||||
|         if(data.zeros!=0) |  | ||||||
|         { |  | ||||||
|             name=data.buf; |  | ||||||
|             name=name.substr(0,8); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             //name="";
 |  | ||||||
|             //std::cout<<"Name in symbol table\n";
 |  | ||||||
|             char buf[256]; |  | ||||||
|             s.seekg(strptr+data.strptr); |  | ||||||
|             s.get(buf,256,'\0'); |  | ||||||
|             name=buf; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         //s.seekp(6,std::ios::cur);
 |  | ||||||
|     } |  | ||||||
|     void PrintData() |  | ||||||
|     { |  | ||||||
|         std::cout<<name<<" section:"<<sectnumb<<" pos:"<<pos<<"\n"; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| struct Relocation |  | ||||||
| { |  | ||||||
|     unsigned long  ptr; |  | ||||||
|     unsigned long  tblIndex; |  | ||||||
|     unsigned short type; |  | ||||||
| }; |  | ||||||
| typedef std::vector<Symbol> vSymbol; |  | ||||||
| class File |  | ||||||
| { |  | ||||||
| public: |  | ||||||
|     File(std::string path); |  | ||||||
|     virtual ~File(); |  | ||||||
| 
 |  | ||||||
|     void GetText(char *ptr); |  | ||||||
|     size_t GetTextSize(); |  | ||||||
|     void LoadSymbols(); |  | ||||||
|     const vSymbol& GetSymbols(){LoadSymbols();return symbols;}; |  | ||||||
|     void PrintSymbols(); |  | ||||||
|     void PrintRelocations(); |  | ||||||
| protected: |  | ||||||
| private: |  | ||||||
|     typedef std::map<std::string,Section> secMap; |  | ||||||
| 
 |  | ||||||
|     secMap sections; |  | ||||||
|     vSymbol symbols; |  | ||||||
|     Section &GetSection(std::string name); |  | ||||||
| 
 |  | ||||||
|     std::fstream mystream; |  | ||||||
|     Header myhead; |  | ||||||
|    // Section Text;
 |  | ||||||
|     //Section Data;
 |  | ||||||
|    // Section Bss;
 |  | ||||||
| }; |  | ||||||
| } |  | ||||||
| #endif // OUTFILE_H
 |  | ||||||
| @ -1,37 +0,0 @@ | |||||||
| #ifndef HEXSEARCH_H |  | ||||||
| #define HEXSEARCH_H |  | ||||||
| #include <vector> |  | ||||||
| #include "Core.h" //for some reason process.h needs core |  | ||||||
| #include "MemAccess.h" |  | ||||||
| 
 |  | ||||||
| //(not yet)implemented using Boyer-Moore algorithm
 |  | ||||||
| 
 |  | ||||||
| class Hexsearch |  | ||||||
| { |  | ||||||
| public: |  | ||||||
|     typedef std::vector<int> SearchArgType; |  | ||||||
|     enum SearchConst  //TODO add more
 |  | ||||||
|     { |  | ||||||
|         ANYBYTE=0x101,DWORD_,ANYDWORD,ADDRESS |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     Hexsearch(const SearchArgType &args,char * startpos,char * endpos); |  | ||||||
|     ~Hexsearch(); |  | ||||||
| 
 |  | ||||||
|     void Reset(){pos_=startpos_;}; |  | ||||||
|     void SetStart(char * pos){pos_=pos;}; |  | ||||||
| 
 |  | ||||||
|     void * FindNext(); |  | ||||||
|     std::vector<void *> FindAll(); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     bool Compare(int a,int b); |  | ||||||
|     void ReparseArgs(); |  | ||||||
|     SearchArgType args_; |  | ||||||
|     char * pos_,* startpos_,* endpos_; |  | ||||||
|     std::vector<int> BadCharShifts,GoodSuffixShift; |  | ||||||
|     void PrepareGoodSuffixTable(); |  | ||||||
|     void PrepareBadCharShift(); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| @ -1,33 +0,0 @@ | |||||||
| #ifndef LUA_HEXSEARCH_H |  | ||||||
| #define LUA_HEXSEARCH_H |  | ||||||
| #include "hexsearch.h" |  | ||||||
| 
 |  | ||||||
| #include "luamain.h" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| namespace lua |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| class Hexsearch |  | ||||||
| { |  | ||||||
|     int tblid; |  | ||||||
|     ::Hexsearch *p; |  | ||||||
| public: |  | ||||||
|     Hexsearch(lua_State *L,int id); |  | ||||||
|     ~Hexsearch(); |  | ||||||
| 
 |  | ||||||
|     int GetTableId(){return tblid;}; |  | ||||||
| 
 |  | ||||||
|     int find(lua_State *L); |  | ||||||
|     int findall(lua_State *L); |  | ||||||
|     int reset(lua_State *L); |  | ||||||
| 
 |  | ||||||
|     DEF_LUNE(Hexsearch); |  | ||||||
| }; |  | ||||||
| void RegisterHexsearch(lua::state &st); |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| @ -1,46 +0,0 @@ | |||||||
| #ifndef LUA_MISC_H |  | ||||||
| #define LUA_MISC_H |  | ||||||
| 
 |  | ||||||
| #include <map> |  | ||||||
| 
 |  | ||||||
| #include "Core.h" |  | ||||||
| #include <MemAccess.h> |  | ||||||
| #include "luamain.h" |  | ||||||
| #include "OutFile.h" |  | ||||||
| #include "LuaTools.h" |  | ||||||
| 
 |  | ||||||
| namespace lua |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| typedef std::map<std::string,void *> mapPlugs; |  | ||||||
| 
 |  | ||||||
| class PlugManager |  | ||||||
| { |  | ||||||
|     public: |  | ||||||
| 
 |  | ||||||
|         mapPlugs GetList(){return plugs;}; |  | ||||||
|         uint32_t AddNewPlug(std::string name,uint32_t size,uint32_t loc=0); |  | ||||||
|         uint32_t FindPlugin(std::string name); |  | ||||||
| 
 |  | ||||||
|         static PlugManager &GetInst() |  | ||||||
|         { |  | ||||||
|             void *p; |  | ||||||
|             p=DFHack::Core::getInstance().GetData("dfusion_manager"); |  | ||||||
|             if(p==0) |  | ||||||
|             { |  | ||||||
|                 p=new PlugManager; |  | ||||||
|                 DFHack::Core::getInstance().RegisterData(p,"dfusion_manager"); |  | ||||||
|             } |  | ||||||
|             return *static_cast<PlugManager*>(p); |  | ||||||
|         }; |  | ||||||
|     protected: |  | ||||||
|     private: |  | ||||||
|         PlugManager(){}; |  | ||||||
|         mapPlugs plugs; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void RegisterMisc(lua::state &st); |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| @ -1,13 +0,0 @@ | |||||||
| #ifndef LUA_PROCESS_H |  | ||||||
| #define LUA_PROCESS_H |  | ||||||
| 
 |  | ||||||
| #include "Core.h" |  | ||||||
| #include <MemAccess.h> |  | ||||||
| 
 |  | ||||||
| #include "luamain.h" |  | ||||||
| 
 |  | ||||||
| namespace lua |  | ||||||
| { |  | ||||||
| void RegisterProcess(lua::state &st); |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| @ -1,40 +0,0 @@ | |||||||
| #ifndef LUAMAIN_H |  | ||||||
| #define LUAMAIN_H |  | ||||||
| #include <string> |  | ||||||
| using std::string; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #include "lua.h" |  | ||||||
| #include "lauxlib.h" |  | ||||||
| #include "lualib.h" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #include "lune.h" |  | ||||||
| #include "luaxx.hpp" |  | ||||||
| 
 |  | ||||||
| namespace lua |  | ||||||
| { |  | ||||||
|     //global lua state singleton
 |  | ||||||
|     class glua |  | ||||||
|     { |  | ||||||
|     public: |  | ||||||
|         static state &Get(); |  | ||||||
|     private: |  | ||||||
|         glua(); |  | ||||||
|         static glua *ptr; |  | ||||||
|         state mystate; |  | ||||||
|     }; |  | ||||||
|     //registers basic lua commands
 |  | ||||||
|     void RegBasics(lua::state &L); |  | ||||||
|     //dumps lua function trace, useless unless called from lua.
 |  | ||||||
|     string DebugDump(lua::state &L); |  | ||||||
|     //register functions, first registers into global scope, second into current table
 |  | ||||||
|     void RegFunctions(lua::state &L,luaL_Reg const *arr); |  | ||||||
|     void RegFunctionsLocal(lua::state &L,luaL_Reg const *arr); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #endif // LUAMAIN_H
 |  | ||||||
| @ -1,530 +0,0 @@ | |||||||
| /* vim: set et sw=3 tw=0 fo=croqlaw cino=t0:
 |  | ||||||
|  * |  | ||||||
|  * Luaxx, the C++ Lua wrapper library. |  | ||||||
|  * Copyright (c) 2006-2008 Matthew Nicholson |  | ||||||
|  * |  | ||||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy |  | ||||||
|  * of this software and associated documentation files (the "Software"), to |  | ||||||
|  * deal in the Software without restriction, including without limitation the |  | ||||||
|  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |  | ||||||
|  * sell copies of the Software, and to permit persons to whom the Software is |  | ||||||
|  * furnished to do so, subject to the following conditions: |  | ||||||
|  * |  | ||||||
|  * The above copyright notice and this permission notice shall be included in |  | ||||||
|  * all copies or substantial portions of the Software. |  | ||||||
|  * |  | ||||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |  | ||||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |  | ||||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |  | ||||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |  | ||||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |  | ||||||
|  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |  | ||||||
|  * IN THE SOFTWARE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #ifndef LUAXX_H |  | ||||||
| #define LUAXX_H |  | ||||||
| 
 |  | ||||||
| #define lua_Integer_long 1 |  | ||||||
| #define lua_Integer_int 1 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #include "lua.h" |  | ||||||
| #include "lauxlib.h" |  | ||||||
| #include "lualib.h" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #include <string> |  | ||||||
| #include <vector> |  | ||||||
| #include <new> |  | ||||||
| #include <exception> |  | ||||||
| 
 |  | ||||||
| /** @file
 |  | ||||||
|  * Luaxx header file. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| /** @mainpage Luaxx
 |  | ||||||
|  * |  | ||||||
|  * Luaxx is a thin wrapper around the Lua C API.  The wrapper adds some |  | ||||||
|  * convenience functions and integrates well with modern C++. |  | ||||||
|  * |  | ||||||
|  * Luaxx is not designed like toLua, instead Luaxx is more of a 1 to 1 |  | ||||||
|  * logical mapping of the lua API in C++.  For example: in C you would write |  | ||||||
|  * 'lua_pushnumber(L, 3)', in C++ with Luaxx you would write |  | ||||||
|  * 'L.push(3)'. |  | ||||||
|  * |  | ||||||
|  * Every thing is contained in the 'lua' namespace and exceptions are thrown |  | ||||||
|  * when a lua API function returns an error.  Most of the functionality is |  | ||||||
|  * contained in the lua::state class, which can be passed directly to lua C API |  | ||||||
|  * functions (the compiler will automatically use the internal lua_State |  | ||||||
|  * pointer).  See the documentation for that class for more information. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| namespace lua |  | ||||||
| { |  | ||||||
|     void StackDump(lua_State *L); |  | ||||||
|    /** A generic lua exception.
 |  | ||||||
|     */ |  | ||||||
|    class exception : public std::exception { |  | ||||||
|       public: |  | ||||||
|          /// Constructor.
 |  | ||||||
|          exception() : std::exception() { } |  | ||||||
|          /// Constructor.
 |  | ||||||
|          explicit exception(const char* desc) : std::exception(), description(desc) { } |  | ||||||
|          virtual ~exception() throw() { } |  | ||||||
|          /** Get a description of the error.
 |  | ||||||
|           * @returns a C-string describing the error |  | ||||||
|           */ |  | ||||||
|          virtual const char* what() const throw() { |  | ||||||
|             return description.c_str(); |  | ||||||
|          } |  | ||||||
|       private: |  | ||||||
|          std::string description; |  | ||||||
|    }; |  | ||||||
| 
 |  | ||||||
|    /** A lua runtime error.
 |  | ||||||
|     * This is thrown when there was an error executing some lua code. |  | ||||||
|     * @note This is not an std::runtime error. |  | ||||||
|     */ |  | ||||||
|    class runtime_error : public exception { |  | ||||||
|       public: |  | ||||||
|          /// Constructor.
 |  | ||||||
|          runtime_error() : exception() { } |  | ||||||
|          /// Constructor.
 |  | ||||||
|          explicit runtime_error(const char* desc) : exception(desc) { } |  | ||||||
|          virtual ~runtime_error() throw() { } |  | ||||||
|    }; |  | ||||||
| 
 |  | ||||||
|    /** A syntax error.
 |  | ||||||
|     */ |  | ||||||
|    class syntax_error : public exception { |  | ||||||
|       public: |  | ||||||
|          /// Constructor.
 |  | ||||||
|          syntax_error() : exception() { } |  | ||||||
|          /// Constructor.
 |  | ||||||
|          explicit syntax_error(const char* desc) : exception(desc) { } |  | ||||||
|          virtual ~syntax_error() throw() { } |  | ||||||
|    }; |  | ||||||
| 
 |  | ||||||
|    /** An error loading a lua file.
 |  | ||||||
|     * This is thrown when a call to lua::loadfile failed because the file could |  | ||||||
|     * not be opened or read. |  | ||||||
|     */ |  | ||||||
|    class file_error : public exception { |  | ||||||
|       public: |  | ||||||
|          /// Constructor.
 |  | ||||||
|          file_error() : exception() { } |  | ||||||
|          /// Constructor.
 |  | ||||||
|          explicit file_error(const char* desc) : exception(desc) { } |  | ||||||
|          virtual ~file_error() throw() { } |  | ||||||
|    }; |  | ||||||
| 
 |  | ||||||
|    /** A memory allocation error.
 |  | ||||||
|     */ |  | ||||||
|    class bad_alloc : public exception, std::bad_alloc { |  | ||||||
|       public: |  | ||||||
|          /// Constructor.
 |  | ||||||
|          bad_alloc() : lua::exception(), std::bad_alloc() { } |  | ||||||
|          /// Constructor.
 |  | ||||||
|          explicit bad_alloc(const char* desc) : lua::exception(desc), std::bad_alloc() { } |  | ||||||
|          virtual ~bad_alloc() throw() { } |  | ||||||
|    }; |  | ||||||
| 
 |  | ||||||
|    /** An error converting a lua type.
 |  | ||||||
|     */ |  | ||||||
|    class bad_conversion : public exception { |  | ||||||
|       public: |  | ||||||
|          /// Constructor.
 |  | ||||||
|          bad_conversion() : exception() { } |  | ||||||
|          /// Constructor.
 |  | ||||||
|          explicit bad_conversion(const char* desc) : exception(desc) { } |  | ||||||
|          virtual ~bad_conversion() throw() { } |  | ||||||
|    }; |  | ||||||
| 
 |  | ||||||
|    /// A Lua table (this class does not have any data).
 |  | ||||||
|    class table { }; |  | ||||||
|    /// A Lua nil (this class does not have any data).
 |  | ||||||
|    class nil { }; |  | ||||||
|    /// A lua function (not a cfunction).
 |  | ||||||
|    class function { }; |  | ||||||
|    /// A lua userdatum
 |  | ||||||
|    class userdata { }; |  | ||||||
|    /// A lua light userdatum
 |  | ||||||
|    class lightuserdata { }; |  | ||||||
| 
 |  | ||||||
|    typedef lua_CFunction cfunction;  ///< A cfunction on the lua statck
 |  | ||||||
|    typedef lua_Integer integer;      ///< The default lua integer type
 |  | ||||||
|    typedef lua_Number number;        ///< The default lua number type
 |  | ||||||
|    typedef lua_Reader reader;        ///< The type of function used by lua_load
 |  | ||||||
|    const int multiret = LUA_MULTRET; ///< LUA_MULTIRET
 |  | ||||||
| 
 |  | ||||||
|    /** This is the Luaxx equivalent of lua_State.
 |  | ||||||
|     * The functions provided by this class, closely resemble those of the Lua C |  | ||||||
|     * API. |  | ||||||
|     */ |  | ||||||
|     void StackDump(lua_State *L); |  | ||||||
|    class state { |  | ||||||
|       public: |  | ||||||
|          state(); |  | ||||||
|          state(lua_State* L); |  | ||||||
|          state(const state& t) |  | ||||||
|          { |  | ||||||
|              managed=false; |  | ||||||
|              L=t.L; |  | ||||||
|          } |  | ||||||
|          state& operator = (const state& t); |  | ||||||
|          ~state(); |  | ||||||
| 
 |  | ||||||
|          operator lua_State*(); |  | ||||||
| 
 |  | ||||||
|          state& push(); |  | ||||||
|          state& push(nil); |  | ||||||
|          state& push(bool boolean); |  | ||||||
|          template<typename T> state& push(T number); |  | ||||||
|          state& push(const char* s, size_t length); |  | ||||||
|          state& push(const char* s); |  | ||||||
|          state& push(const std::string& s); |  | ||||||
|          state& push(cfunction f); |  | ||||||
|          state& push(table); |  | ||||||
|          state& push(void* p); |  | ||||||
|          template<typename T> state& pushlightuserdata(T p); |  | ||||||
| 
 |  | ||||||
|          template<typename T> state& to(T& number, int index = -1); |  | ||||||
|          template<typename T> state& touserdata(T& p, int index = -1); |  | ||||||
| 
 |  | ||||||
|          template<typename T> T as(T default_value, int index = -1); |  | ||||||
|          template<typename T> T as(int index = -1); |  | ||||||
|          template<typename T> T vpop() |  | ||||||
|          { |  | ||||||
|              T ret; |  | ||||||
|              ret=as<T>(); |  | ||||||
|              pop(); |  | ||||||
|              return ret; |  | ||||||
|          } |  | ||||||
|          template<typename T> bool is(int index = -1); |  | ||||||
| 
 |  | ||||||
|          state& check(int narg); |  | ||||||
| #ifndef lua_Integer_int |  | ||||||
|          state& check(int& i, int narg); |  | ||||||
| #endif |  | ||||||
|          state& check(integer& i, int narg); |  | ||||||
| #ifndef lua_Integer_long |  | ||||||
|          state& check(long& l, int narg); |  | ||||||
| #endif |  | ||||||
|          state& check(std::string& s, int narg); |  | ||||||
|          state& check(number& n, int narg); |  | ||||||
| 
 |  | ||||||
|          template<typename msg_t> void error(msg_t message); |  | ||||||
| #if 0 |  | ||||||
|          template<> void error(const std::string& message); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|          state& pcall(int nargs = 0, int nresults = 0, int on_error = 0); |  | ||||||
|          state& call(int nargs = 0, int nresults = 0); |  | ||||||
| 
 |  | ||||||
|          state& checkstack(int size); |  | ||||||
|          state& settop(int index); |  | ||||||
|          int gettop(); |  | ||||||
|          int size(); |  | ||||||
|          bool empty(); |  | ||||||
| 
 |  | ||||||
|          state& insert(int index); |  | ||||||
|          state& replace(int index); |  | ||||||
|          state& remove(int index); |  | ||||||
|          state& pop(int elements = 1); |  | ||||||
| 
 |  | ||||||
|          state& pushvalue(int index); |  | ||||||
| 
 |  | ||||||
|          state& newtable(); |  | ||||||
|          bool newmetatable(const std::string& tname); |  | ||||||
|          template<typename userdata_t> userdata_t* newuserdata(); |  | ||||||
|          void* newuserdata(size_t nbytes); |  | ||||||
| 
 |  | ||||||
|          state& gettable(int index = -2); |  | ||||||
|          state& getfield(const std::string& k, int index = -1); |  | ||||||
|          state& settable(int index = -3); |  | ||||||
|          state& setfield(const std::string& k, int index = -2); |  | ||||||
|          state& getmetatable(const std::string& tname); |  | ||||||
|          bool getmetatable(int index); |  | ||||||
| 
 |  | ||||||
|          bool next(int index = -2); |  | ||||||
| 
 |  | ||||||
|          state& getglobal(const std::string& name); |  | ||||||
|          state& setglobal(const std::string& name); |  | ||||||
| 
 |  | ||||||
|          state& loadfile(const std::string& filename); |  | ||||||
|          state& loadstring(const std::string& s); |  | ||||||
| 
 |  | ||||||
|          template<typename iterator_t> state& load(iterator_t begin, iterator_t end); |  | ||||||
| 
 |  | ||||||
|          size_t objlen(int index = -1); |  | ||||||
| 
 |  | ||||||
|       private: |  | ||||||
|          lua_State* L; |  | ||||||
|          bool managed; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|          int throw_error(int code); |  | ||||||
|    }; |  | ||||||
| 
 |  | ||||||
|    // template functions
 |  | ||||||
| 
 |  | ||||||
|    /** Push a number onto the stack.
 |  | ||||||
|     * @tparam T the numeric type to push (should be automatically determined, |  | ||||||
|     * if there is no specialization for the desired type, lua_pushnumber() will |  | ||||||
|     * be used, and may fail) |  | ||||||
|     * @param number the number to push |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    template<typename T> |  | ||||||
|    state& state::push(T number) { |  | ||||||
|       lua_pushnumber(L, number); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Push a light userdatum on to the stack.
 |  | ||||||
|     * @tparam T the type of data to push (should be automatically determined) |  | ||||||
|     * @param p the pointer to push |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    template<typename T> |  | ||||||
|    state& state::pushlightuserdata(T p) { |  | ||||||
|       lua_pushlightuserdata(L, p); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Check if the given index is of the given type (defaults to using
 |  | ||||||
|     * lua_isnumber()). |  | ||||||
|     * @tparam T the type to check for (the default, if no specializations |  | ||||||
|     * match, does lua_isnumber()) |  | ||||||
|     * @param index the index to check |  | ||||||
|     * @note the default version (used if no specialization is matched) will |  | ||||||
|     * check if the given value is a number |  | ||||||
|     * @returns whether the value at the given index is a nil |  | ||||||
|     */ |  | ||||||
|    template<typename T> |  | ||||||
|    bool state::is(int index) { |  | ||||||
|       return lua_isnumber(L, index); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the value at index as the given numeric type.
 |  | ||||||
|     * @tparam T they numeric type to static_cast<T>() the numeric value on the |  | ||||||
|     * stack to |  | ||||||
|     * @param number where to store the value |  | ||||||
|     * @param index the index to get |  | ||||||
|     * @note This function does \em not pop the value from the stack. |  | ||||||
|     * @todo Instead of throwing an exception here, we may just return an |  | ||||||
|     * error code. |  | ||||||
|     * @throws lua::bad_conversion if the value on the stack could not be |  | ||||||
|     * converted to the indicated type |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    template<typename T> |  | ||||||
|    state& state::to(T& number, int index) { |  | ||||||
|       if (lua_isnumber(L, index)) |  | ||||||
|          number = static_cast<T>(lua_tonumber(L, index)); |  | ||||||
|       else |  | ||||||
|          throw bad_conversion("Cannot convert non 'number' value to number"); |  | ||||||
| 
 |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the value at index as (light) userdata.
 |  | ||||||
|     * @tparam T the type of data pointed to (pointer is returned as |  | ||||||
|     * reinterpret_cast<T>()) |  | ||||||
|     * @param p the pointer to store the value in |  | ||||||
|     * @param index the index to get |  | ||||||
|     * @note This function does \em not pop the value from the stack. |  | ||||||
|     * @todo Instead of throwing an exception here, we may just return an |  | ||||||
|     * error code. |  | ||||||
|     * @throws lua::bad_conversion if the value on the stack could not be |  | ||||||
|     * converted to the indicated type |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    template<typename T> |  | ||||||
|    state& state::touserdata(T& p, int index) { |  | ||||||
|       if (lua_isuserdata(L, index)) |  | ||||||
|          p = reinterpret_cast<T>(lua_touserdata(L, index)); |  | ||||||
|       else |  | ||||||
|          throw bad_conversion("Cannot convert non 'userdata' or 'lightuserdata' value to userdata"); |  | ||||||
| 
 |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the value at index as the given type.
 |  | ||||||
|     * @tparam T the type to retrieve the value on the stack as (the default |  | ||||||
|     * template function uses lua_tonumber(), specializations may cause |  | ||||||
|     * different behavior) |  | ||||||
|     * @param default_value this value is returned if the conversion fails |  | ||||||
|     * @param index the index to get |  | ||||||
|     * @note This function does \em not pop the value from the stack. |  | ||||||
|     * @returns the indicated value from the stack or the default value if |  | ||||||
|     * the conversion fails |  | ||||||
|     */ |  | ||||||
|    template<typename T> |  | ||||||
|    T state::as(T default_value, int index) { |  | ||||||
|       if (lua_isnumber(L, index)) |  | ||||||
|          return static_cast<T>(lua_tonumber(L, index)); |  | ||||||
|       else |  | ||||||
|          return default_value; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the value at index as the given type.
 |  | ||||||
|     * @tparam T the expected type of the value |  | ||||||
|     * @param index the index to get |  | ||||||
|     * |  | ||||||
|     * @note This function does \em not pop the value from the stack. |  | ||||||
|     * @note The default version of this function uses lua_tonumber() but |  | ||||||
|     * specializations may cause different behavior. |  | ||||||
|     * |  | ||||||
|     * @todo Instead of throwing an exception here, we may just return an |  | ||||||
|     * error code. |  | ||||||
|     * |  | ||||||
|     * @throws lua::bad_conversion if the value on the stack could not be |  | ||||||
|     * converted to the indicated type |  | ||||||
|     * |  | ||||||
|     * This function will return the value on the stack as the given type.  If |  | ||||||
|     * the value is not of the given type <em>no conversion will be |  | ||||||
|     * performed</em> and lua::bad_conversion will be thrown.  There are some |  | ||||||
|     * exceptions to this rule, for example, numbers will be converted to |  | ||||||
|     * strings and vice-versa (conversion is only performed if the matching |  | ||||||
|     * lua_is*() function returns true).  The state::to() function should be |  | ||||||
|     * used to perform automatic conversion. |  | ||||||
|     * |  | ||||||
|     * @returns the indicated value as the given type if possible |  | ||||||
|     */ |  | ||||||
|    template<typename T> |  | ||||||
|    T state::as(int index) { |  | ||||||
|       if (lua_isnumber(L, index)) |  | ||||||
|          return static_cast<T>(lua_tonumber(L, index)); |  | ||||||
|       else |  | ||||||
|          throw bad_conversion("Cannot convert non 'number' value to number"); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Create a new userdatum on the stack.
 |  | ||||||
|     * @tparam userdata_t the type of the userdata (will be passed to sizeof()) |  | ||||||
|     * |  | ||||||
|     * This function creates a new userdatum on the stack the size of |  | ||||||
|     * userdata_t and return a pointer to it. |  | ||||||
|     * @returns a pointer to the new userdatum |  | ||||||
|     */ |  | ||||||
|    template<typename userdata_t> |  | ||||||
|    userdata_t* state::newuserdata() { |  | ||||||
|       return reinterpret_cast<userdata_t*>(lua_newuserdata(L, sizeof(userdata_t))); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Generate a Lua error.
 |  | ||||||
|     * @tparam msg_t the type of error message data (should be automatically |  | ||||||
|     * determined) |  | ||||||
|     * @param message the error message/value |  | ||||||
|     * @note This function is used to raise errors from lua::cfunctions. |  | ||||||
|     * @note This function never returns, instead it throws an exception |  | ||||||
|     * caught by the intepreter. |  | ||||||
|     */ |  | ||||||
|    template<typename msg_t> |  | ||||||
|    void state::error(msg_t message) { |  | ||||||
|       push(message); |  | ||||||
|       lua_error(L); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Load a sequence of data as a Lua chunk.
 |  | ||||||
|     * @tparam iterator_t the type of iterator to use (should be automatically |  | ||||||
|     * determined) |  | ||||||
|     * @param begin an iterator to the start of the sequence |  | ||||||
|     * @param end an iterator to the end of the sequence (one past the |  | ||||||
|     * end) |  | ||||||
|     * |  | ||||||
|     * This function takes a sequence of data and attempts to convert it |  | ||||||
|     * into a Lua chunk.  The type of data passed must be able to be |  | ||||||
|     * converted into an 8-bit char. |  | ||||||
|     * |  | ||||||
|     * @note This function should automatically detect if the data is text |  | ||||||
|     * or binary. |  | ||||||
|     * |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    template<typename iterator_t> |  | ||||||
|    state& state::load(iterator_t begin, iterator_t end) { |  | ||||||
|       // convert the data to characters
 |  | ||||||
|       std::vector<char> chunk(begin, end); |  | ||||||
| 
 |  | ||||||
|       // Here we use the address of the first element of our vector.
 |  | ||||||
|       // This works because the data in std::vectors is contiguous.
 |  | ||||||
|       throw_error(luaL_loadbuffer(L, &(*chunk.begin()), chunk.size(), NULL)); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|    // template specializations
 |  | ||||||
|    template<> state& state::to(bool& boolean, int index); |  | ||||||
|    template<> state& state::to(std::string& string, int index); |  | ||||||
| 
 |  | ||||||
|    template<> bool state::as(bool default_value, int index); |  | ||||||
|    template<> std::string state::as(std::string default_value, int index); |  | ||||||
|    template<> bool state::as(int index); |  | ||||||
|    template<> std::string state::as(int index); |  | ||||||
| 
 |  | ||||||
|    template<> bool state::is<nil>(int index); |  | ||||||
|    template<> bool state::is<bool>(int index); |  | ||||||
|    template<> bool state::is<std::string>(int index); |  | ||||||
|    template<> bool state::is<table>(int index); |  | ||||||
|    template<> bool state::is<cfunction>(int index); |  | ||||||
|    template<> bool state::is<function>(int index); |  | ||||||
|    template<> bool state::is<userdata>(int index); |  | ||||||
|    template<> bool state::is<lightuserdata>(int index); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|    // inline functions
 |  | ||||||
| 
 |  | ||||||
|    /** Convert a lua::state to a lua_State*.
 |  | ||||||
|     * This operator allows lua::state to behave like a lua_State |  | ||||||
|     * pointer. |  | ||||||
|     * |  | ||||||
|     * @note This should be used as a last result to interoperate with C |  | ||||||
|     * code.  This may be removed in future versions of Luaxx. |  | ||||||
|     */ |  | ||||||
|    inline state::operator lua_State*() { |  | ||||||
|       return L; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Throws exceptions for error return codes.
 |  | ||||||
|     * @param code the return code |  | ||||||
|     * |  | ||||||
|     * This function throws an exception based on the error it was passed. |  | ||||||
|     * If it is passed a 0 it will not throw anything. |  | ||||||
|     * |  | ||||||
|     * @todo In the future this function may check an exception mask |  | ||||||
|     * before throwing an error. |  | ||||||
|     * |  | ||||||
|     * @returns the code it was passed |  | ||||||
|     */ |  | ||||||
|    inline int state::throw_error(int code) { |  | ||||||
|       std::string error; |  | ||||||
| 
 |  | ||||||
|       // below, we package lua errors into exceptions
 |  | ||||||
|       switch (code) { |  | ||||||
|          case 0: |  | ||||||
|             break; |  | ||||||
|          case LUA_ERRSYNTAX: |  | ||||||
|             to(error).pop(); |  | ||||||
|             throw syntax_error(error.c_str()); |  | ||||||
|          case LUA_ERRMEM: |  | ||||||
|             to(error).pop(); |  | ||||||
|             throw bad_alloc(error.c_str()); |  | ||||||
|          case LUA_ERRRUN: |  | ||||||
|             to(error).pop(); |  | ||||||
|             throw runtime_error(error.c_str()); |  | ||||||
|          case LUA_ERRFILE: |  | ||||||
|             to(error).pop(); |  | ||||||
|             throw file_error(error.c_str()); |  | ||||||
|          default: |  | ||||||
|             to(error).pop(); |  | ||||||
|             throw exception(error.c_str()); |  | ||||||
|       } |  | ||||||
|       return code; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| @ -1,360 +0,0 @@ | |||||||
| #ifndef LUNE_H |  | ||||||
| #define LUNE_H |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #include "lua.h" |  | ||||||
| #include "lauxlib.h" |  | ||||||
| #include "lualib.h" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #include "luaxx.hpp" |  | ||||||
| #include <string> |  | ||||||
| 
 |  | ||||||
| namespace lua |  | ||||||
| { |  | ||||||
|     class object |  | ||||||
|     { |  | ||||||
|         state &myst; |  | ||||||
|         int myref; |  | ||||||
|     public: |  | ||||||
|         object(state &myst):myst(myst) |  | ||||||
|         { |  | ||||||
|             myref=luaL_ref(myst,LUA_REGISTRYINDEX); |  | ||||||
|         } |  | ||||||
|         ~object() |  | ||||||
|         { |  | ||||||
|             luaL_unref(myst,LUA_REGISTRYINDEX,myref); |  | ||||||
|         } |  | ||||||
|         void Get() |  | ||||||
|         { |  | ||||||
|             lua_rawgeti(myst,LUA_REGISTRYINDEX,myref); |  | ||||||
|         } |  | ||||||
|         state &GetState(){return myst;}; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     class local_object |  | ||||||
|     { |  | ||||||
|         state myst; |  | ||||||
|         int myref; |  | ||||||
|         static object *mytbl; |  | ||||||
|     public: |  | ||||||
|         local_object(lua_State *L) |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|             myst=state(L); |  | ||||||
|             //LOG<<"Creating local object...\n";
 |  | ||||||
|             //StackDump(L);
 |  | ||||||
|             if(!mytbl) |  | ||||||
|             { |  | ||||||
|                 //LOG<<" Metable...\n";
 |  | ||||||
|                 myst.newtable(); //2
 |  | ||||||
|                 if(myst.newmetatable("WEAKTABLE"))//3
 |  | ||||||
|                 { |  | ||||||
|                     //StackDump(L);
 |  | ||||||
|                     myst.push("kv"); //4
 |  | ||||||
|                     myst.setfield("__mode");//3
 |  | ||||||
|                     //LOG<<" Setting Metable...\n";
 |  | ||||||
|                     //StackDump(L);
 |  | ||||||
|                 } |  | ||||||
|                 //LOG<<" Attaching to holder...\n";
 |  | ||||||
| 
 |  | ||||||
|                 //myst.setfield("__metatable");//2
 |  | ||||||
|                 lua_setmetatable(myst,-1); |  | ||||||
|                 mytbl=new object(myst); |  | ||||||
|                 //StackDump(L);
 |  | ||||||
|                 //LOG<<" Done Metatable...\n";
 |  | ||||||
|             } |  | ||||||
|             //StackDump(L);
 |  | ||||||
|             mytbl->Get(); |  | ||||||
|             //LOG<<" Got my table...\n";
 |  | ||||||
|             //StackDump(L);
 |  | ||||||
|             myst.insert(-2); |  | ||||||
|             myref=luaL_ref(myst,-2); |  | ||||||
|             //LOG<<"Before pop:";
 |  | ||||||
|             //StackDump(L);
 |  | ||||||
|             myst.pop(1); |  | ||||||
|             GetTable(); |  | ||||||
|             //LOG<<"========Done...\n"<<"Ref="<<myref<<"\n";
 |  | ||||||
|             //mytbl->Get();
 |  | ||||||
|             //StackDump(L);
 |  | ||||||
|             //LOG<<"===========================\n";
 |  | ||||||
|         } |  | ||||||
|         ~local_object() |  | ||||||
|         { |  | ||||||
|             //LOG<<"Deleting local object...\n";
 |  | ||||||
|             ReleaseTable(); |  | ||||||
|         } |  | ||||||
|         void ReleaseTable() |  | ||||||
|         { |  | ||||||
|             mytbl->Get(); |  | ||||||
|             int pos=myst.gettop(); |  | ||||||
|             luaL_unref(myst,pos,myref); |  | ||||||
|             myst.remove(pos); |  | ||||||
|         } |  | ||||||
|         state GetState(){return myst;} |  | ||||||
|         void GetTable() |  | ||||||
|         { |  | ||||||
|             //LOG<<"Getting ref="<<myref<<"\n";
 |  | ||||||
|             //StackDump(myst);
 |  | ||||||
|             //LOG<<"Tbl preget\n";
 |  | ||||||
|             mytbl->Get(); |  | ||||||
|             int pos=myst.gettop(); |  | ||||||
|             //StackDump(myst);
 |  | ||||||
|             //LOG<<"Tbl get\n";
 |  | ||||||
|             //int pos=myst.gettop();
 |  | ||||||
|             lua_rawgeti(myst,pos,myref); |  | ||||||
|             //StackDump(myst);
 |  | ||||||
|             //LOG<<"Done\n";
 |  | ||||||
|             myst.remove(pos); |  | ||||||
|         } |  | ||||||
|     protected: |  | ||||||
| 
 |  | ||||||
|     }; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| template <typename T,bool GC=true> |  | ||||||
| class Lune |  | ||||||
| { |  | ||||||
| public: |  | ||||||
|     typedef struct |  | ||||||
|     { |  | ||||||
|         T *pT; |  | ||||||
|         int tableref; |  | ||||||
|     } userdataType; |  | ||||||
| 
 |  | ||||||
|     typedef int (T::*mfp)(lua_State *L); |  | ||||||
|     typedef struct |  | ||||||
|     { |  | ||||||
|         const char *name; |  | ||||||
|         mfp mfunc; |  | ||||||
|     } RegType; |  | ||||||
| 
 |  | ||||||
|     static void Register(lua_State *L) |  | ||||||
|     { |  | ||||||
|         lua_newtable(L); |  | ||||||
|         int methods = lua_gettop(L); |  | ||||||
| 
 |  | ||||||
|         luaL_newmetatable(L, T::className); |  | ||||||
|         int metatable = lua_gettop(L); |  | ||||||
| 
 |  | ||||||
|         // store method table in globals so that
 |  | ||||||
|         // scripts can add functions written in Lua.
 |  | ||||||
|         lua_pushvalue(L, methods); |  | ||||||
|         lua_setglobal(L, T::className); |  | ||||||
| 
 |  | ||||||
|         lua_pushliteral(L, "__metatable"); |  | ||||||
|         lua_pushvalue(L, methods); |  | ||||||
|         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
 |  | ||||||
| 
 |  | ||||||
|         lua_pushliteral(L, "__index"); |  | ||||||
|         lua_pushcfunction(L, index_T); |  | ||||||
|         lua_settable(L, metatable); |  | ||||||
| 
 |  | ||||||
|         //lua_pushliteral(L, "__name");
 |  | ||||||
|         //lua_pushstring(L, T::className);
 |  | ||||||
|         //lua_settable(L, metatable);
 |  | ||||||
| 
 |  | ||||||
|         lua_pushliteral(L, "__newindex"); |  | ||||||
|         lua_pushcfunction(L, newindex_T); |  | ||||||
|         lua_settable(L, metatable); |  | ||||||
| 
 |  | ||||||
|         lua_pushliteral(L, "__instances"); |  | ||||||
|         lua_newtable(L); |  | ||||||
|         lua_settable(L, metatable); |  | ||||||
|         if(GC) |  | ||||||
|         { |  | ||||||
|             lua_pushliteral(L, "__gc"); |  | ||||||
|             lua_pushcfunction(L, gc_T); |  | ||||||
|             lua_settable(L, metatable); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         lua_newtable(L);                // metatable for method table
 |  | ||||||
|         int mt = lua_gettop(L); |  | ||||||
|         lua_pushliteral(L, "__call"); |  | ||||||
|         lua_pushcfunction(L, new_T); |  | ||||||
|         lua_pushliteral(L, "new"); |  | ||||||
|         lua_pushvalue(L, -2);           // dup new_T function
 |  | ||||||
|         lua_settable(L, methods);       // add new_T to method table
 |  | ||||||
|         lua_settable(L, mt);            // mt.__call = new_T
 |  | ||||||
|         lua_setmetatable(L, methods); |  | ||||||
|         //LOG<<"lune: registered class \""<<T::className<<"\"\n";
 |  | ||||||
|         // fill method table with methods from class T
 |  | ||||||
|         for (RegType *l = T::methods; l->name; l++) |  | ||||||
|         { |  | ||||||
|             /* edited by Snaily: shouldn't it be const RegType *l ... ? */ |  | ||||||
|             lua_pushstring(L, l->name); |  | ||||||
|             lua_pushlightuserdata(L, (void*)l); |  | ||||||
|             lua_pushcclosure(L, thunk, 1); |  | ||||||
|             lua_settable(L, methods); |  | ||||||
|             //LOG<<"lune:    method \""<<l->name<<"\"\n";
 |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         lua_pop(L, 2);  // drop metatable and method table
 |  | ||||||
|     }; |  | ||||||
|     static void GetTable(lua_State *L,T *p) |  | ||||||
|     { |  | ||||||
|         GetTableEx(L,p->GetTableId()); |  | ||||||
|     } |  | ||||||
|     static void GetTableEx(lua_State *L,int id) |  | ||||||
|     { |  | ||||||
|         lua::state s(L); |  | ||||||
|         s.getmetatable(T::className); |  | ||||||
|         s.getfield("__instances"); |  | ||||||
|         int ins=s.gettop(); |  | ||||||
|         lua_rawgeti(L, ins, id); |  | ||||||
|         s.insert(-3); |  | ||||||
|         s.pop(2); |  | ||||||
|     } |  | ||||||
|     static T *check(lua_State *L, int narg) |  | ||||||
|     { |  | ||||||
|         userdataType *ud = |  | ||||||
|             static_cast<userdataType*>(luaL_checkudata(L, narg, T::className)); //TODO FIX THIs..
 |  | ||||||
|         //(lua_touserdata(L, narg));//
 |  | ||||||
|         if(!ud) luaL_error(L, "Bad argument %d: expected type %s", narg, T::className); |  | ||||||
|         return ud->pT;  // pointer to T object
 |  | ||||||
|     } |  | ||||||
| protected: |  | ||||||
| private: |  | ||||||
| 
 |  | ||||||
|     static int RegTable(lua_State *L) |  | ||||||
|     { |  | ||||||
|        // LOG<<"Regging....\n";
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
| 
 |  | ||||||
|         lua::state s(L); |  | ||||||
|         int ssize=s.gettop(); |  | ||||||
|         //s.getglobal(T::className);
 |  | ||||||
|         s.getmetatable(T::className); |  | ||||||
|         s.getfield("__instances"); |  | ||||||
|         int ins=s.gettop(); |  | ||||||
|         s.newtable(); |  | ||||||
|         int id=luaL_ref(L,ins); |  | ||||||
|         //LOG<<"After reg:\n";
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         s.settop(ssize); |  | ||||||
|         return id; |  | ||||||
|     } |  | ||||||
|     static void UnregTable(lua_State *L,int id) |  | ||||||
|     { |  | ||||||
|         lua::state s(L); |  | ||||||
|         s.getmetatable(T::className); |  | ||||||
|         s.getfield("__instances"); |  | ||||||
|         int ins=s.gettop(); |  | ||||||
|         //LOG<<"Unreg table id:"<<id<<"stack dump:\n";
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         luaL_unref(L,ins,id); |  | ||||||
|     } |  | ||||||
|     static int index_T(lua_State *L)  // calls with (table, key), return value
 |  | ||||||
|     { |  | ||||||
|         lua::state st(L); |  | ||||||
|         std::string key=st.as<std::string>(-1); |  | ||||||
|         T *p=check(L,1); |  | ||||||
|         GetTable(L,p); |  | ||||||
|         st.insert(-2); |  | ||||||
|         //LOG<<"Index:\n";
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         lua_rawget(L,-2); //try getting from normal table
 |  | ||||||
|         if(st.is<lua::nil>()) //failed
 |  | ||||||
|         { |  | ||||||
|             st.pop(2); |  | ||||||
|             st.getglobal(T::className); //try class tables then
 |  | ||||||
|             st.push(key); |  | ||||||
|             st.gettable(); |  | ||||||
|         } |  | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
|     static int newindex_T(lua_State *L) |  | ||||||
|     { |  | ||||||
|         //LOG<<"New index....\n";
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
| 
 |  | ||||||
|         lua::state st(L); |  | ||||||
|         T *p=check(L,1); |  | ||||||
|         GetTable(L,p); |  | ||||||
|         //st.insert(-3);
 |  | ||||||
|         //LOG<<"Before set:\n";
 |  | ||||||
|         st.insert(-3); |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         lua_rawset(L,-3); |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
|     static int thunk(lua_State *L) |  | ||||||
|     { |  | ||||||
|         //LOG<<"Size of stack:"<<lua_gettop(L)<<"\n";
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         if(lua_gettop(L)<1) |  | ||||||
|             luaL_error(L,"Member function called without 'self'"); |  | ||||||
|         //LOG<<"Size of stack after:"<<lua_gettop(L)<<"\n";
 |  | ||||||
|         // stack has userdata, followed by method args
 |  | ||||||
|         T *obj = check(L, 1);  // get 'self', or if you prefer, 'this'
 |  | ||||||
|         //T *obj=static_cast<userdataType*>(lua_touserdata(L,1))->pT;
 |  | ||||||
|         lua_remove(L, 1);  // remove self so member function args start at index 1
 |  | ||||||
|         // get member function from upvalue
 |  | ||||||
|         RegType *l = static_cast<RegType*>(lua_touserdata(L, lua_upvalueindex(1))); |  | ||||||
|         return (obj->*(l->mfunc))(L);  // call member function
 |  | ||||||
|     } |  | ||||||
|     static int gc_T(lua_State *L) |  | ||||||
|     { |  | ||||||
|         //lua_getfield(L,,"__ud");
 |  | ||||||
|         //LOG<<"Garbage collecting.\n";
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, 1)); |  | ||||||
|         T *obj = ud->pT; |  | ||||||
| 
 |  | ||||||
|         delete obj;  // call destructor for T objects
 |  | ||||||
|         UnregTable(L,ud->tableref); |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
|     static int new_T(lua_State *L) |  | ||||||
|     { |  | ||||||
|         //LOG<<"Pre build:"<<lua_gettop(L)<<"\n";
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         lua_remove(L, 1);   // use classname:new(), instead of classname.new()
 |  | ||||||
|         //lua_newtable(L);
 |  | ||||||
|         int id=RegTable(L); |  | ||||||
|         //LOG<<"Registred as:"<<id<<"\n";
 |  | ||||||
|         //int ssize=lua_gettop(L);
 |  | ||||||
|         T *obj = new T(L,id);  // call constructor for T objects
 |  | ||||||
|         lua_settop(L,0); //no need for parameters later.
 |  | ||||||
|         //LOG<<"Post build:"<<lua_gettop(L)<<"\t";
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         //LOG<<"TSOP\n";
 |  | ||||||
| 
 |  | ||||||
|         userdataType *ud = |  | ||||||
|             static_cast<userdataType*>(lua_newuserdata(L, sizeof(userdataType))); |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         luaL_getmetatable(L, T::className);  // lookup metatable in Lua registry
 |  | ||||||
|         lua_setmetatable(L,-2); |  | ||||||
|         //LOG<<"metatable set\n";
 |  | ||||||
| 
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         GetTable(L,obj); |  | ||||||
|         lua_pushliteral(L,"__obj"); |  | ||||||
|         lua_pushvalue(L,-3); |  | ||||||
|         lua_settable(L,-3); |  | ||||||
|         lua_pop(L,1); |  | ||||||
|         //LOG<<"Object referenced\n";
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         //T *p = new(ud) T(L);  // call constructor for T objects
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         ud->pT = obj;  // store pointer to object in userdata
 |  | ||||||
|         ud->tableref=id; |  | ||||||
|         //luaL_getmetatable(L, T::className);  // lookup metatable in Lua registry
 |  | ||||||
|         //lua_setmetatable(L, tableindex);
 |  | ||||||
|         //lua::StackDump(L);
 |  | ||||||
|         //LOG<<"Push done\n";
 |  | ||||||
|         return 1;  // userdata containing pointer to T object
 |  | ||||||
|     } |  | ||||||
|     Lune() {}; //non constructable...
 |  | ||||||
| }; |  | ||||||
| #define method(class, name) {#name, &class::name} |  | ||||||
| #define DEF_LUNE(class) static const char className[];\ |  | ||||||
|                          static Lune<class>::RegType methods[]; |  | ||||||
| #define DEF_LUNE_NOGC(class) static const char className[];\ |  | ||||||
|                          static Lune<class,false>::RegType methods[]; |  | ||||||
| #define IMP_LUNE(class,lua_name) const char class::className[]=#lua_name; |  | ||||||
| #define LUNE_METHODS_START(class) Lune<class>::RegType class::methods[] = { |  | ||||||
| #define LUNE_METHODS_START_NOGC(class) Lune<class,false>::RegType class::methods[] = { |  | ||||||
| #define LUNE_METHODS_END() {0,0}} |  | ||||||
| #endif // LUNE_H
 |  | ||||||
| @ -1,12 +0,0 @@ | |||||||
| Dfusion plugin offers four DFhack commands: 'dfusion', 'dfuse' and 'lua', 'runlua'. |  | ||||||
| lua: |  | ||||||
| Runs an interactive lua console. For more on lua commands see [http://www.lua.org/manual/5.1/manual.html Lua reference manual] or google "lua". Also this command could be ran with filepath as an argument. Then it runs that file as a lua script file. E.g. ''lua dfusion/temp.lua'' runs a file  <your df path>/dfusion/temp.lua. |  | ||||||
| runlua: |  | ||||||
| Similar to ''lua <filename>'' but not interactive, to be used with hotkeys |  | ||||||
| dfusion: |  | ||||||
| First this command runs all plugins' init.lua part then show a menu. Type number to run specified plugin. |  | ||||||
| dfuse: |  | ||||||
| Similar to dfusion but not interactive. To be used with hotkeys (later will have command support). |  | ||||||
| 
 |  | ||||||
| Also dfuse/dfusion runs an init script located at 'save directory/dfusion/init.lua'. And 'initcustom.lua' if it exists |  | ||||||
| More info http://dwarffortresswiki.org/index.php/Utility:DFusion |  | ||||||
| @ -1,102 +0,0 @@ | |||||||
| #include "OutFile.h" |  | ||||||
| #include <stdexcept> |  | ||||||
| using namespace OutFile; |  | ||||||
| File::File(std::string path) |  | ||||||
| { |  | ||||||
|     //mystream.exceptions ( std::fstream::eofbit | std::fstream::failbit | std::fstream::badbit );
 |  | ||||||
|     mystream.open(path.c_str(),std::fstream::binary|std::ios::in|std::ios::out); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     if(mystream) |  | ||||||
|     { |  | ||||||
|         mystream.read((char*)&myhead,sizeof(myhead)); |  | ||||||
|         for(unsigned i=0;i<myhead.sectioncount;i++) |  | ||||||
|         { |  | ||||||
|             Section x; |  | ||||||
|             mystream.read((char*)&x,sizeof(Section)); |  | ||||||
|             sections[x.name]=x; |  | ||||||
|         } |  | ||||||
|         //std::cout<<"Sizeof:"<<sizeof(Section)<<"\n";
 |  | ||||||
|       /*myhead.PrintData();
 |  | ||||||
|       for(auto it=sections.begin();it!=sections.end();it++) |  | ||||||
|       { |  | ||||||
|           it->second.PrintData(); |  | ||||||
|       }*/ |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         throw std::runtime_error("Error opening file!"); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| Section &File::GetSection(std::string name) |  | ||||||
| { |  | ||||||
|     return sections[name]; |  | ||||||
| } |  | ||||||
| void File::GetText(char *ptr) |  | ||||||
| { |  | ||||||
|     Section &s=GetSection(".text"); |  | ||||||
|     mystream.seekg(s.start); |  | ||||||
| 
 |  | ||||||
|     mystream.read(ptr,s.size); |  | ||||||
| } |  | ||||||
| size_t File::GetTextSize() |  | ||||||
| { |  | ||||||
|     Section &s=GetSection(".text"); |  | ||||||
|     return s.size; |  | ||||||
| } |  | ||||||
| void File::PrintRelocations() |  | ||||||
| { |  | ||||||
|     for(auto it=sections.begin();it!=sections.end();it++) |  | ||||||
|       { |  | ||||||
|           std::cout<<it->first<<":\n"; |  | ||||||
|           for(unsigned i=0;i<it->second.numRel;i++) |  | ||||||
|           { |  | ||||||
|               Relocation r; |  | ||||||
|               mystream.seekg(it->second.ptrRel+10*i); |  | ||||||
|               mystream.read((char*)&r,10); |  | ||||||
|               std::cout<<r.ptr<<" -- "<<r.tblIndex<<":"<</*symbols[r.tblIndex].name<<*/" type:"<<r.type<<"\n"; |  | ||||||
|           } |  | ||||||
|       } |  | ||||||
| } |  | ||||||
| void File::PrintSymbols() |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
|     std::cout<<"Sizeof symbol:"<<sizeof(Symbol)<<std::endl; |  | ||||||
|     std::cout<<"Symbol count:"<<myhead.symbolcount<<std::endl; |  | ||||||
|     for(unsigned i=0;i<myhead.symbolcount;i++) |  | ||||||
|     { |  | ||||||
|         mystream.seekg(myhead.symbolptr+i*18); |  | ||||||
|         Symbol s; |  | ||||||
|         std::cout<<i<<"\t"; |  | ||||||
|         s.Read(mystream,myhead.symbolptr+18*myhead.symbolcount); |  | ||||||
| 
 |  | ||||||
|         //mystream.read((char*)&s,sizeof(Symbol));
 |  | ||||||
|         s.PrintData(); |  | ||||||
|         symbols.push_back(s); |  | ||||||
|         if(s.auxsymbs>0) |  | ||||||
|         { |  | ||||||
|             i+=s.auxsymbs; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| void File::LoadSymbols() |  | ||||||
| { |  | ||||||
|     symbols.clear(); |  | ||||||
|     for(unsigned i=0;i<myhead.symbolcount;i++) |  | ||||||
|     { |  | ||||||
|         mystream.seekg(myhead.symbolptr+i*18); |  | ||||||
|         Symbol s; |  | ||||||
|         s.Read(mystream,myhead.symbolptr+18*myhead.symbolcount); |  | ||||||
|         symbols.push_back(s); |  | ||||||
|         if(s.auxsymbs>0) |  | ||||||
|         { |  | ||||||
|             i+=s.auxsymbs; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| File::~File() |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,116 +0,0 @@ | |||||||
| #include "hexsearch.h" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Hexsearch::Hexsearch(const SearchArgType &args,char * startpos,char * endpos):args_(args),pos_(startpos),startpos_(startpos),endpos_(endpos) |  | ||||||
| { |  | ||||||
|     ReparseArgs(); |  | ||||||
| } |  | ||||||
| Hexsearch::~Hexsearch() |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| inline bool Hexsearch::Compare(int a,int b) |  | ||||||
| { |  | ||||||
|     if(b==Hexsearch::ANYBYTE) |  | ||||||
|         return true; |  | ||||||
|     if(a==b) |  | ||||||
|         return true; |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
| void Hexsearch::ReparseArgs() |  | ||||||
| { |  | ||||||
|     union |  | ||||||
|     { |  | ||||||
|         uint32_t val; |  | ||||||
|         uint8_t bytes[4]; |  | ||||||
|     }B; |  | ||||||
|     SearchArgType targ; |  | ||||||
|     targ=args_; |  | ||||||
|     args_.clear(); |  | ||||||
|     for(size_t i=0;i<targ.size();) |  | ||||||
|     { |  | ||||||
|         if(targ[i]==DWORD_) |  | ||||||
|         { |  | ||||||
|             i++; |  | ||||||
|             B.val=targ[i]; |  | ||||||
|             for(int j=0;j<4;j++) |  | ||||||
|             { |  | ||||||
|                 args_.push_back(B.bytes[j]); |  | ||||||
|             } |  | ||||||
|             i++; |  | ||||||
|         } |  | ||||||
|         else if (targ[i]==ANYDWORD) |  | ||||||
|         { |  | ||||||
|             i++; |  | ||||||
|             for(int j=0;j<4;j++) |  | ||||||
|                 args_.push_back(ANYBYTE); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             args_.push_back(targ[i]); |  | ||||||
|             i++; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| void * Hexsearch::FindNext() //TODO rewrite using Boyer-Moore algorithm
 |  | ||||||
| { |  | ||||||
|     DFHack::Core &inst=DFHack::Core::getInstance(); |  | ||||||
|     DFHack::Process *p=inst.p; |  | ||||||
|     uint8_t *buf; |  | ||||||
|     buf=new uint8_t[args_.size()]; |  | ||||||
|     while(pos_<endpos_) |  | ||||||
|     { |  | ||||||
|         bool found=true; |  | ||||||
|         p->readByte(pos_,buf[0]); |  | ||||||
|         if(Compare(buf[0],args_[0])) |  | ||||||
|         { |  | ||||||
|             p->read(pos_,args_.size(),buf); |  | ||||||
|             for(size_t i=0;i<args_.size();i++) |  | ||||||
|             { |  | ||||||
|                 if(!Compare(buf[i],args_[i])) |  | ||||||
|                 { |  | ||||||
|                     pos_+=i; |  | ||||||
|                     found=false; |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             if(found) |  | ||||||
|             { |  | ||||||
|                 pos_+=args_.size(); |  | ||||||
|                 delete [] buf; |  | ||||||
|                 return pos_-args_.size(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         pos_ = pos_ + 1; |  | ||||||
|     } |  | ||||||
|     delete [] buf; |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::vector<void *> Hexsearch::FindAll() |  | ||||||
| { |  | ||||||
|     std::vector<void *> ret; |  | ||||||
|     void * cpos=pos_; |  | ||||||
|     while(cpos!=0) |  | ||||||
|     { |  | ||||||
|         cpos=FindNext(); |  | ||||||
|         if(cpos!=0) |  | ||||||
|             ret.push_back(cpos); |  | ||||||
|     } |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| void Hexsearch::PrepareBadCharShift() |  | ||||||
| { |  | ||||||
|     BadCharShifts.resize(256,-1); |  | ||||||
|     int i=0; |  | ||||||
|     for(SearchArgType::reverse_iterator it=args_.rbegin();it!=args_.rend();it++) |  | ||||||
|     { |  | ||||||
|         BadCharShifts[*it]=i; |  | ||||||
|         i++; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| void Hexsearch::PrepareGoodSuffixTable() |  | ||||||
| { |  | ||||||
|     GoodSuffixShift.resize(args_.size()+1,0); |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,61 +0,0 @@ | |||||||
| #include "lua_Hexsearch.h" |  | ||||||
| int lua::Hexsearch::find(lua_State *L) |  | ||||||
| { |  | ||||||
|     lua::state st(L); |  | ||||||
|     void * pos=p->FindNext(); |  | ||||||
|     st.push(reinterpret_cast<size_t>(pos)); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| int lua::Hexsearch::findall(lua_State *L) |  | ||||||
| { |  | ||||||
|     lua::state st(L); |  | ||||||
|     std::vector<void *> pos=p->FindAll(); |  | ||||||
|     st.newtable(); |  | ||||||
|     for(unsigned i=0;i<pos.size();i++) |  | ||||||
|     { |  | ||||||
|         st.push(i+1); |  | ||||||
|         st.push(reinterpret_cast<size_t>(pos[i])); |  | ||||||
|         st.settable(); |  | ||||||
|     } |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| lua::Hexsearch::Hexsearch(lua_State *L,int id):tblid(id) |  | ||||||
| { |  | ||||||
|     lua::state st(L); |  | ||||||
|     char * start,* end; |  | ||||||
|     ::Hexsearch::SearchArgType args; |  | ||||||
|     start= (char *)st.as<uint32_t>(1); |  | ||||||
|     end=(char *)st.as<uint32_t>(2); |  | ||||||
|     for(int i=3;i<=st.gettop();i++) |  | ||||||
|     { |  | ||||||
|         args.push_back(st.as<int>(i)); |  | ||||||
|     } |  | ||||||
|     p=new ::Hexsearch(args,start,end); |  | ||||||
| } |  | ||||||
| lua::Hexsearch::~Hexsearch() |  | ||||||
| { |  | ||||||
|     delete p; |  | ||||||
| } |  | ||||||
| int lua::Hexsearch::reset(lua_State *L) |  | ||||||
| { |  | ||||||
|     lua::state st(L); |  | ||||||
|     p->Reset(); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| IMP_LUNE(lua::Hexsearch,hexsearch); |  | ||||||
| LUNE_METHODS_START(lua::Hexsearch) |  | ||||||
|     method(lua::Hexsearch,find), |  | ||||||
|     method(lua::Hexsearch,findall), |  | ||||||
|     method(lua::Hexsearch,reset), |  | ||||||
| LUNE_METHODS_END(); |  | ||||||
| #define __ADDCONST(name) st.push(::Hexsearch::  name); st.setglobal(#name) |  | ||||||
| void lua::RegisterHexsearch(lua::state &st) |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
|     Lune<lua::Hexsearch>::Register(st); |  | ||||||
|     __ADDCONST(ANYBYTE); |  | ||||||
|     __ADDCONST(ANYDWORD); |  | ||||||
|     __ADDCONST(DWORD_); |  | ||||||
| } |  | ||||||
| #undef __ADDCONST |  | ||||||
| @ -1,154 +0,0 @@ | |||||||
| #include "lua_Misc.h" |  | ||||||
| uint32_t lua::PlugManager::AddNewPlug(std::string name,uint32_t size,uint32_t loc) |  | ||||||
| { |  | ||||||
|     void *p; |  | ||||||
|     if(size!=0) |  | ||||||
|         p=new unsigned char[size]; |  | ||||||
|     else |  | ||||||
|         p=(void*)loc; |  | ||||||
|     plugs[name]=p; |  | ||||||
|     return (uint32_t)p; |  | ||||||
| } |  | ||||||
| uint32_t lua::PlugManager::FindPlugin(std::string name) |  | ||||||
| { |  | ||||||
|     mapPlugs::iterator it=plugs.find(name); |  | ||||||
|     if(it!=plugs.end()) |  | ||||||
|         return (uint32_t)it->second; |  | ||||||
|     else |  | ||||||
|         return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static int LoadMod(lua_State *L) |  | ||||||
| { |  | ||||||
|     lua::state st(L); |  | ||||||
|     std::string modfile=st.as<std::string>(1); |  | ||||||
|     std::string modname=st.as<std::string>(2); |  | ||||||
|     uint32_t size_add=st.as<uint32_t>(0,3); |  | ||||||
|     OutFile::File f(modfile); |  | ||||||
|     uint32_t size=f.GetTextSize(); |  | ||||||
|     uint32_t pos=lua::PlugManager::GetInst().AddNewPlug(modname,size+size_add); |  | ||||||
|     char *buf; |  | ||||||
|     buf=new char[size]; |  | ||||||
|     f.GetText(buf); |  | ||||||
|     //std::cout<<"poking @:"<<std::hex<<pos<<"size :"<<size<<std::endl;
 |  | ||||||
|     DFHack::Core::getInstance().p->write((void *) pos,size,(uint8_t*)buf); |  | ||||||
|     delete [] buf; |  | ||||||
|     st.push(pos); |  | ||||||
|     st.push(size); |  | ||||||
|     return 2; |  | ||||||
| } |  | ||||||
| static int LoadObj(lua_State *L) |  | ||||||
| { |  | ||||||
|     lua::state st(L); |  | ||||||
|     std::string modfile=st.as<std::string>(1); |  | ||||||
|     OutFile::File f(modfile); |  | ||||||
|     size_t s=f.GetTextSize(); |  | ||||||
|     void *p=st.newuserdata(s); //TODO does it leak memory??
 |  | ||||||
|     f.GetText((char*)p); |  | ||||||
|     st.push(s); |  | ||||||
|     return 2; |  | ||||||
| } |  | ||||||
| static int FindMarker(lua_State *L) // marker, void ptr, size, start
 |  | ||||||
| { |  | ||||||
|     lua::state st(L); |  | ||||||
|     union |  | ||||||
|     { |  | ||||||
|         unsigned char bytes[4]; |  | ||||||
|         size_t mark; |  | ||||||
|     }M; |  | ||||||
|     M.mark=st.as<size_t>(1); |  | ||||||
|     unsigned char *p=(unsigned char *)lua_touserdata(L, 2);//st.as<lua::userdata>(2);
 |  | ||||||
|     size_t size=st.as<size_t>(3); |  | ||||||
|     size_t start=st.as<size_t>(4); |  | ||||||
|     for(size_t i=start;i<size;i++) |  | ||||||
|     { |  | ||||||
|         bool ok; |  | ||||||
|         ok=true; |  | ||||||
|         if(p[i]==M.bytes[0]) |  | ||||||
|         { |  | ||||||
|             for(size_t j=0;j<4;j++) |  | ||||||
|             { |  | ||||||
|                 if(p[i+j]!=M.bytes[j]) |  | ||||||
|                 { |  | ||||||
|                     ok=false; |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             if(ok) |  | ||||||
|             { |  | ||||||
|                 st.push(i); |  | ||||||
|                 return 1; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| static int LoadObjSymbols(lua_State *L) |  | ||||||
| { |  | ||||||
|     lua::state st(L); |  | ||||||
|     std::string modfile=st.as<std::string>(1); |  | ||||||
|     OutFile::File f(modfile); |  | ||||||
|     OutFile::vSymbol vec=f.GetSymbols(); |  | ||||||
|     OutFile::Symbol S; |  | ||||||
| 
 |  | ||||||
|     st.newtable(); |  | ||||||
|     for(size_t i=0;i<vec.size();i++) |  | ||||||
|     { |  | ||||||
|         st.push(i); |  | ||||||
|         S=vec[i]; |  | ||||||
|         st.newtable(); |  | ||||||
|         st.push(S.name); |  | ||||||
|         st.setfield("name"); |  | ||||||
|         st.push(S.pos); |  | ||||||
|         st.setfield("pos"); |  | ||||||
|         st.settable(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| static int NewMod(lua_State *L) |  | ||||||
| { |  | ||||||
|     lua::state st(L); |  | ||||||
|     std::string modname=st.as<std::string>(1); |  | ||||||
|     size_t size=st.as<size_t>(2); |  | ||||||
|     size_t loc=st.as<size_t>(3,0); |  | ||||||
|     uint32_t pos=lua::PlugManager::GetInst().AddNewPlug(modname,size,loc); |  | ||||||
|     st.push(pos); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| static int GetMod(lua_State *L) |  | ||||||
| { |  | ||||||
|     lua::state st(L); |  | ||||||
|     std::string modname=st.as<std::string>(1); |  | ||||||
|     uint32_t pos=lua::PlugManager::GetInst().FindPlugin(modname); |  | ||||||
|     if(pos==0) |  | ||||||
|         st.push(); |  | ||||||
|     else |  | ||||||
|         st.push(pos); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| const luaL_Reg lua_misc_func[]= |  | ||||||
| { |  | ||||||
|     {"loadmod",LoadMod}, |  | ||||||
|     {"getmod",GetMod}, |  | ||||||
|     {"loadobj",LoadObj}, |  | ||||||
|     {"loadobjsymbols",LoadObjSymbols}, |  | ||||||
|     {"findmarker",FindMarker}, |  | ||||||
|     {"newmod",NewMod}, |  | ||||||
|     {NULL,NULL} |  | ||||||
| }; |  | ||||||
| void lua::RegisterMisc(lua::state &st) |  | ||||||
| { |  | ||||||
|     st.getglobal("engine"); |  | ||||||
|     if(st.is<lua::nil>()) |  | ||||||
|     { |  | ||||||
|         st.pop(); |  | ||||||
|         st.newtable(); |  | ||||||
|     } |  | ||||||
|     lua::RegFunctionsLocal(st, lua_misc_func); |  | ||||||
|     st.setglobal("engine"); |  | ||||||
| } |  | ||||||
| @ -1,269 +0,0 @@ | |||||||
| #include "lua_Process.h" |  | ||||||
| 
 |  | ||||||
| static DFHack::Process* GetProcessPtr(lua::state &st) |  | ||||||
| { |  | ||||||
|     return DFHack::Core::getInstance().p; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int lua_Process_readDWord(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     uint32_t ret=c->readDWord( (void *) st.as<uint32_t>(1)); |  | ||||||
|     st.push(ret); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| static int lua_Process_writeDWord(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     c->writeDWord((void *) st.as<uint32_t>(1),st.as<uint32_t>(2)); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| static int lua_Process_readFloat(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     float ret=c->readFloat((void *) st.as<uint32_t>(1)); |  | ||||||
|     st.push(ret); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int lua_Process_readWord(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     uint16_t ret=c->readWord((void *) st.as<uint32_t>(1)); |  | ||||||
|     st.push(ret); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int lua_Process_writeWord(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     c->writeWord((void *) st.as<uint32_t>(1),st.as<uint16_t>(2)); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| static int lua_Process_readByte(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     uint8_t ret=c->readByte((void *) st.as<uint32_t>(1)); |  | ||||||
|     st.push(ret); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int lua_Process_writeByte(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     c->writeByte((void *) st.as<uint32_t>(1),st.as<uint8_t>(2)); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| static int lua_Process_read(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     size_t len=st.as<uint32_t>(2); |  | ||||||
|     uint8_t* buf; |  | ||||||
| 
 |  | ||||||
|     if(!st.is<lua::nil>(3)) |  | ||||||
|         buf=(uint8_t*)lua_touserdata(st,3); |  | ||||||
|     else |  | ||||||
|         buf=new uint8_t[len]; |  | ||||||
|     c->read((void *) st.as<uint32_t>(1),len,buf); |  | ||||||
|     st.pushlightuserdata(buf); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| static int lua_Process_write(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     c-> write((void *) st.as<uint32_t>(1),st.as<uint32_t>(2),static_cast<uint8_t*>(lua_touserdata(st,3))); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| static int lua_Process_readSTLString (lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     std::string r=c->readSTLString((void *) st.as<uint32_t>(1)); |  | ||||||
|     st.push(r); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int lua_Process_writeSTLString(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     c->writeSTLString((void *) st.as<uint32_t>(1),st.as<std::string>(2)); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| static int lua_Process_copySTLString(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     c->copySTLString((void *) st.as<uint32_t>(1),st.as<uint32_t>(2)); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| static int lua_Process_doReadClassName(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     std::string r=c->doReadClassName((void*)st.as<size_t>(1)); |  | ||||||
|     st.push(r); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| static int lua_Process_readClassName(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     std::string r=c->readClassName((void*)st.as<size_t>(1)); |  | ||||||
|     st.push(r); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| static int lua_Process_readCString (lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     std::string r=c->readCString((void *) st.as<uint32_t>(1)); |  | ||||||
|     st.push(r); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| static int lua_Process_isSuspended(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     st.push(c->isSuspended()); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| static int lua_Process_isIdentified(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     st.push(c->isIdentified()); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| static int lua_Process_getMemRanges(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     std::vector<DFHack::t_memrange> ranges; |  | ||||||
|     c->getMemRanges(ranges); |  | ||||||
|     st.newtable(); |  | ||||||
|     for(size_t i=0;i<ranges.size();i++) |  | ||||||
|     { |  | ||||||
|         st.push(i); |  | ||||||
|         st.newtable(); |  | ||||||
|         st.push((uint32_t)ranges[i].start); // WARNING!! lua has only 32bit numbers, possible loss of data!!
 |  | ||||||
|         st.setfield("start"); |  | ||||||
|         st.push((uint32_t)ranges[i].end); |  | ||||||
|         st.setfield("end"); |  | ||||||
|         st.push(std::string(ranges[i].name)); |  | ||||||
|         st.setfield("name"); |  | ||||||
|         st.push(ranges[i].read); |  | ||||||
|         st.setfield("read"); |  | ||||||
|         st.push(ranges[i].write); |  | ||||||
|         st.setfield("write"); |  | ||||||
|         st.push(ranges[i].execute); |  | ||||||
|         st.setfield("execute"); |  | ||||||
|         st.push(ranges[i].shared); |  | ||||||
|         st.setfield("shared"); |  | ||||||
|         st.push(ranges[i].valid); |  | ||||||
|         st.setfield("valid"); |  | ||||||
|         st.settable(); |  | ||||||
|     } |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| static int lua_Process_getBase(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     uint32_t base=c->getBase(); |  | ||||||
|     st.push(base); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| /*static int lua_Process_getPID(lua_State *S)
 |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     int ret=c->getPID(); |  | ||||||
|     st.push(ret); |  | ||||||
|     return 1; |  | ||||||
| }*/ |  | ||||||
| static int lua_Process_getPath(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     std::string ret=c->getPath(); |  | ||||||
|     st.push(ret); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| static int lua_Process_setPermisions(lua_State *S) |  | ||||||
| { |  | ||||||
|     lua::state st(S); |  | ||||||
|     DFHack::Process* c=GetProcessPtr(st); |  | ||||||
|     DFHack::t_memrange range,trange; |  | ||||||
| 
 |  | ||||||
|     st.getfield("start",1); |  | ||||||
|     range.start= (void *)st.as<uint64_t>(); |  | ||||||
|     st.pop(); |  | ||||||
|     st.getfield("end",1); |  | ||||||
|     range.end= (void *)st.as<uint64_t>(); |  | ||||||
|     st.pop(); |  | ||||||
| 
 |  | ||||||
|     st.getfield("read",2); |  | ||||||
|     trange.read=st.as<bool>(); |  | ||||||
|     st.pop(); |  | ||||||
|     st.getfield("write",2); |  | ||||||
|     trange.write=st.as<bool>(); |  | ||||||
|     st.pop(); |  | ||||||
|     st.getfield("execute",2); |  | ||||||
|     trange.execute=st.as<bool>(); |  | ||||||
|     st.pop(); |  | ||||||
| 
 |  | ||||||
|     c->setPermisions(range,trange); |  | ||||||
| 
 |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| #define PROC_FUNC(name) {#name,lua_Process_ ## name} |  | ||||||
| const luaL_Reg lua_process_func[]= |  | ||||||
| { |  | ||||||
|     PROC_FUNC(readDWord), |  | ||||||
|     PROC_FUNC(writeDWord), |  | ||||||
|     PROC_FUNC(readFloat), |  | ||||||
|     PROC_FUNC(readWord), |  | ||||||
|     PROC_FUNC(writeWord), |  | ||||||
|     PROC_FUNC(readByte), |  | ||||||
|     PROC_FUNC(writeByte), |  | ||||||
|     PROC_FUNC(read), |  | ||||||
|     PROC_FUNC(write), |  | ||||||
|     PROC_FUNC(readSTLString), |  | ||||||
|     PROC_FUNC(writeSTLString), |  | ||||||
|     PROC_FUNC(copySTLString), |  | ||||||
|     PROC_FUNC(doReadClassName), |  | ||||||
|     PROC_FUNC(readClassName), |  | ||||||
|     PROC_FUNC(readCString ), |  | ||||||
|     PROC_FUNC(isSuspended), |  | ||||||
|     PROC_FUNC(isIdentified), |  | ||||||
|     PROC_FUNC(getMemRanges), |  | ||||||
|     PROC_FUNC(getBase), |  | ||||||
|     //PROC_FUNC(getPID), //not implemented
 |  | ||||||
|     PROC_FUNC(getPath), |  | ||||||
|     PROC_FUNC(setPermisions), |  | ||||||
|     {NULL,NULL} |  | ||||||
| }; |  | ||||||
| #undef PROC_FUNC |  | ||||||
| void lua::RegisterProcess(lua::state &st) |  | ||||||
| { |  | ||||||
|     st.getglobal("Process"); |  | ||||||
|     if(st.is<lua::nil>()) |  | ||||||
|     { |  | ||||||
|         st.pop(); |  | ||||||
|         st.newtable(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     lua::RegFunctionsLocal(st, lua_process_func); |  | ||||||
| 
 |  | ||||||
|     st.setglobal("Process"); |  | ||||||
| } |  | ||||||
| @ -1,69 +0,0 @@ | |||||||
| #include "luamain.h" |  | ||||||
| #include <vector> |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| lua::glua* lua::glua::ptr=0; |  | ||||||
| lua::glua::glua() |  | ||||||
| { |  | ||||||
|     RegBasics(mystate); |  | ||||||
| } |  | ||||||
| lua::state &lua::glua::Get() |  | ||||||
| { |  | ||||||
|     if(!glua::ptr) |  | ||||||
|         glua::ptr=new glua(); |  | ||||||
|     return glua::ptr->mystate; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| int lua_Ver_Lua(lua_State *L) |  | ||||||
| { |  | ||||||
|     lua::state st(L); |  | ||||||
|     st.push(LUA_RELEASE); |  | ||||||
|     return 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static const struct luaL_Reg lua_basic_lib [] = |  | ||||||
| { |  | ||||||
|     {"getluaver", lua_Ver_Lua}, |  | ||||||
|     {NULL, NULL}  /* sentinel */ |  | ||||||
| }; |  | ||||||
| void lua::RegBasics(lua::state &L) |  | ||||||
| { |  | ||||||
|     luaL_openlibs(L); |  | ||||||
|     RegFunctions(L,lua_basic_lib); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void lua::RegFunctions(lua::state &L,luaL_Reg const*arr) |  | ||||||
| { |  | ||||||
|     luaL_Reg const *cur=arr; |  | ||||||
|     while(cur->name!=NULL) |  | ||||||
|     { |  | ||||||
|         lua_pushcfunction(L, cur->func); |  | ||||||
|         lua_setglobal(L, cur->name); |  | ||||||
| 
 |  | ||||||
|         cur++; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| void lua::RegFunctionsLocal(lua::state &L,luaL_Reg const*arr) |  | ||||||
| { |  | ||||||
|     luaL_Reg const *cur=arr; |  | ||||||
|     while(cur->name!=NULL) |  | ||||||
|     { |  | ||||||
|         lua_pushcfunction(L, cur->func); |  | ||||||
|         //lua_setglobal(L, cur->name);
 |  | ||||||
|         L.setfield(cur->name); |  | ||||||
| 
 |  | ||||||
|         cur++; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| string lua::DebugDump(lua::state &L) |  | ||||||
| { |  | ||||||
|     L.getglobal("debug"); |  | ||||||
|     L.getfield("traceback"); |  | ||||||
|     L.call(0,1); |  | ||||||
|     string ret=L.as<string>(); |  | ||||||
|     //cout<<"StackTrace:"<<ret<<endl;
 |  | ||||||
|     L.settop(0); |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| @ -1,836 +0,0 @@ | |||||||
| /* vim: set et sw=3 tw=0 fo=croqlaw cino=t0:
 |  | ||||||
|  * |  | ||||||
|  * Luaxx, the C++ Lua wrapper library. |  | ||||||
|  * Copyright (c) 2006-2008 Matthew Nicholson |  | ||||||
|  * |  | ||||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy |  | ||||||
|  * of this software and associated documentation files (the "Software"), to |  | ||||||
|  * deal in the Software without restriction, including without limitation the |  | ||||||
|  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |  | ||||||
|  * sell copies of the Software, and to permit persons to whom the Software is |  | ||||||
|  * furnished to do so, subject to the following conditions: |  | ||||||
|  * |  | ||||||
|  * The above copyright notice and this permission notice shall be included in |  | ||||||
|  * all copies or substantial portions of the Software. |  | ||||||
|  * |  | ||||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |  | ||||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |  | ||||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |  | ||||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |  | ||||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |  | ||||||
|  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |  | ||||||
|  * IN THE SOFTWARE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include <luaxx.hpp> |  | ||||||
| #include <iostream> |  | ||||||
| #define LOG std::cout |  | ||||||
| /** @file
 |  | ||||||
|  * Luaxx implementation file. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| namespace lua |  | ||||||
| { |  | ||||||
|     void StackDump(lua_State *L) |  | ||||||
|     { |  | ||||||
|         int i; |  | ||||||
|         int top = lua_gettop(L); |  | ||||||
|         for (i = 1; i <= top; i++)    /* repeat for each level */ |  | ||||||
|         { |  | ||||||
|             int t = lua_type(L, i); |  | ||||||
|             LOG<<i<<":"; |  | ||||||
|             switch (t) |  | ||||||
|             { |  | ||||||
| 
 |  | ||||||
|             case LUA_TSTRING:  /* strings */ |  | ||||||
|                 LOG<<"str ="<<lua_tostring(L, i)<<"\n"; |  | ||||||
|                 break; |  | ||||||
| 
 |  | ||||||
|             case LUA_TBOOLEAN:  /* booleans */ |  | ||||||
|                 LOG<<"bool="<<(lua_toboolean(L, i) ? "true" : "false")<<"\n"; |  | ||||||
|                 break; |  | ||||||
| 
 |  | ||||||
|             case LUA_TNUMBER:  /* numbers */ |  | ||||||
|                 LOG<<"num ="<<lua_tonumber(L, i)<<"\n"; |  | ||||||
|                 break; |  | ||||||
|             case LUA_TTABLE: |  | ||||||
| 
 |  | ||||||
|                 LOG<<lua_typename(L, t); |  | ||||||
|                 { |  | ||||||
|                     //LOG<<"PRE TOP:"<< lua_gettop(L)<<"\n";
 |  | ||||||
|                     lua_getglobal(L,"PrintTable"); |  | ||||||
|                     //lua_insert(L,-2);
 |  | ||||||
|                     lua_pushvalue(L,i); |  | ||||||
|                     lua_pcall(L,1,0,0); |  | ||||||
|                     //LOG<<"POST TOP:"<< lua_gettop(L)<<"\n";
 |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 break; |  | ||||||
|             default:  /* other values */ |  | ||||||
|                 LOG<<lua_typename(L, t); |  | ||||||
|                 { |  | ||||||
|                     //LOG<<"PRE TOP:"<< lua_gettop(L)<<"\n";
 |  | ||||||
|                     lua_getglobal(L,"tostring"); |  | ||||||
|                     //lua_insert(L,-2);
 |  | ||||||
|                     lua_pushvalue(L,i); |  | ||||||
|                     lua_pcall(L,1,1,0); |  | ||||||
|                     LOG<<"="; |  | ||||||
|                     LOG<<lua_tostring(L,-1)<<"\n"; |  | ||||||
|                     lua_pop(L,1); |  | ||||||
|                     //LOG<<"POST TOP:"<< lua_gettop(L)<<"\n";
 |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 break; |  | ||||||
| 
 |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
|         LOG<<"\n";  /* end the listing */ |  | ||||||
|         LOG<<"==============================\n"; |  | ||||||
|     } |  | ||||||
| #undef LOG |  | ||||||
|    /// Construct our lua environment.
 |  | ||||||
|    state::state() : L(luaL_newstate()), managed(true) { |  | ||||||
|       if (L == NULL) |  | ||||||
|          throw bad_alloc("Error creating lua state"); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Construct our lua environment from an existing lua_State.
 |  | ||||||
|     * @param L the existing state to use. |  | ||||||
|     * |  | ||||||
|     * This function differs from the normal constructor as it sets a flag |  | ||||||
|     * that prevents lua_close() from being called when this class is |  | ||||||
|     * destroyed. |  | ||||||
|     */ |  | ||||||
|    state::state(lua_State* L) : |  | ||||||
|       L(L), managed(false) { |  | ||||||
|    } |  | ||||||
|    state& state::operator = (const state& t) |  | ||||||
|     { |  | ||||||
|              if(managed) |  | ||||||
|                 lua_close(L); |  | ||||||
|              managed=false; |  | ||||||
|              L=t.L; |  | ||||||
| 			 return *this; |  | ||||||
|         } |  | ||||||
|    /// Destroy our lua environment.
 |  | ||||||
|    state::~state() { |  | ||||||
|       if (managed) |  | ||||||
|          lua_close(L); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Push a nil onto the stack.
 |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::push() { |  | ||||||
|       lua_pushnil(L); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Push a nil onto the stack.
 |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::push(nil) { |  | ||||||
|       lua_pushnil(L); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Push a boolean onto the stack.
 |  | ||||||
|     * @param boolean the value to push |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::push(bool boolean) { |  | ||||||
|       lua_pushboolean(L, boolean); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Push a C-style string onto the stack.
 |  | ||||||
|     * @param s the string to push |  | ||||||
|     * @param length the length of the string |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::push(const char* s, size_t length) { |  | ||||||
|       lua_pushlstring(L, s, length); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Push a C-style string onto the stack.
 |  | ||||||
|     * @param s the string to push |  | ||||||
|     * @note This must be a '0' terminated string. |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::push(const char* s) { |  | ||||||
|       lua_pushstring(L, s); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Push an std::string onto the stack.
 |  | ||||||
|     * @param s the string to push |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::push(const std::string& s) { |  | ||||||
|       lua_pushlstring(L, s.c_str(), s.size()); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Push an C function onto the stack.
 |  | ||||||
|     * @param f the function to push |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::push(cfunction f) { |  | ||||||
|       lua_pushcfunction(L, f); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Create a new table on to the stack.
 |  | ||||||
|     * @see state::newtable() |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::push(table) { |  | ||||||
|       lua_newtable(L); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Push a light userdatum on to the stack.
 |  | ||||||
|     * @param p the pointer to push |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::push(void* p) { |  | ||||||
|       lua_pushlightuserdata(L, p); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the value at index as a string.
 |  | ||||||
|     * @param default_value this value is returned if the conversion fails |  | ||||||
|     * @param index the index to get |  | ||||||
|     * @note This function does \em not pop the value from the stack. |  | ||||||
|     * |  | ||||||
|     * @note lua::state::as(std::string()) will convert the value at the |  | ||||||
|     * indicated index to a string <em>on the stack</em>.  This can |  | ||||||
|     * confuse lua::state::next(); |  | ||||||
|     * |  | ||||||
|     * @returns the indicated value from the stack or the default value if the |  | ||||||
|     * conversion fails |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    std::string state::as(std::string default_value, int index) { |  | ||||||
|       if (lua_isstring(L, index)) |  | ||||||
|       { |  | ||||||
|          size_t len; |  | ||||||
|          const char *str = lua_tolstring(L, index, &len); |  | ||||||
|          return std::string(str, len); |  | ||||||
|       } |  | ||||||
|       else |  | ||||||
|          return default_value; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Check an argument of the current function.
 |  | ||||||
|     * @param narg the argument number to check |  | ||||||
|     * |  | ||||||
|     * This function will throw a lua error if there is no argument at the |  | ||||||
|     * given position. |  | ||||||
|     * |  | ||||||
|     * @note This function is meant to be called from with in a lua::cfunction. |  | ||||||
|     * The error throw is internal to the lua interpreter.  When compiled as |  | ||||||
|     * C++, a C++ exception is thrown, so the stack is properly unwound.  This |  | ||||||
|     * exception is not meant to be caught. |  | ||||||
|     */ |  | ||||||
|    state& state::check(int narg) { |  | ||||||
|       luaL_checkany(L, narg); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
| #ifndef lua_Integer_int |  | ||||||
|    /** Check an argument of the current function.
 |  | ||||||
|     * @param i the int to hold the returned value |  | ||||||
|     * @param narg the argument number to check |  | ||||||
|     * |  | ||||||
|     * This function checks if the given argument number is an int. |  | ||||||
|     * |  | ||||||
|     * @note This function is meant to be called from with in a |  | ||||||
|     * lua::cfunction.  The error throw is internal to the lua intrepeter. |  | ||||||
|     * When compiled as C++, a C++ exception is thrown, so the stack is |  | ||||||
|     * properly unwound.  This exception is not meant to be caught. |  | ||||||
|     */ |  | ||||||
|    state& state::check(int& i, int narg) { |  | ||||||
|       i = luaL_checkint(L, narg); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|    /** Check an argument of the current function.
 |  | ||||||
|     * @param i the lua::integer (lua_Integer) to hold the returned value |  | ||||||
|     * @param narg the argument number to check |  | ||||||
|     * |  | ||||||
|     * This function checks if the given argument number is an integer. |  | ||||||
|     * |  | ||||||
|     * @note This is different from lua::check(int(), ...).  It returns a |  | ||||||
|     * lua::integer (lua_Integer), which may not be an int. |  | ||||||
|     * |  | ||||||
|     * @note This function is meant to be called from with in a |  | ||||||
|     * lua::cfunction.  The error throw is internal to the lua intrepeter. |  | ||||||
|     * When compiled as C++, a C++ exception is thrown, so the stack is |  | ||||||
|     * properly unwound.  This exception is not meant to be caught. |  | ||||||
|     */ |  | ||||||
|    state& state::check(integer& i, int narg) { |  | ||||||
|       i = luaL_checkinteger(L, narg); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
| #ifndef lua_Integer_long |  | ||||||
|    /** Check an argument of the current function.
 |  | ||||||
|     * @param l the long to hold the returned value |  | ||||||
|     * @param narg the argument number to check |  | ||||||
|     * |  | ||||||
|     * This function checks if the given argument number is a long. |  | ||||||
|     * |  | ||||||
|     * @note This function is meant to be called from with in a |  | ||||||
|     * lua::cfunction.  The error throw is internal to the lua intrepeter. |  | ||||||
|     * When compiled as C++, a C++ exception is thrown, so the stack is |  | ||||||
|     * properly unwound.  This exception is not meant to be caught. |  | ||||||
|     */ |  | ||||||
|    state& state::check(long& l, int narg) { |  | ||||||
|       l = luaL_checklong(L, narg); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|    /** Check an argument of the current function.
 |  | ||||||
|     * @param s the string to hold the returned value |  | ||||||
|     * @param narg the argument number to check |  | ||||||
|     * |  | ||||||
|     * This function checks if the given argument number is a string. |  | ||||||
|     * |  | ||||||
|     * @note This function is meant to be called from with in a |  | ||||||
|     * lua::cfunction.  The error throw is internal to the lua intrepeter. |  | ||||||
|     * When compiled as C++, a C++ exception is thrown, so the stack is |  | ||||||
|     * properly unwound.  This exception is not meant to be caught. |  | ||||||
|     */ |  | ||||||
|    state& state::check(std::string& s, int narg) { |  | ||||||
|       const char* c; |  | ||||||
|       size_t l; |  | ||||||
|       c = luaL_checklstring(L, narg, &l); |  | ||||||
| 
 |  | ||||||
|       s.assign(c, l); |  | ||||||
| 
 |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Check an argument of the current function.
 |  | ||||||
|     * @param n the lua::number (lua_Number) to hold the returned value |  | ||||||
|     * @param narg the argument number to check |  | ||||||
|     * |  | ||||||
|     * This function checks if the given argument number is a lua::number |  | ||||||
|     * (lua_Number, a double by default). |  | ||||||
|     * |  | ||||||
|     * @note This function is meant to be called from with in a lua::cfunction. |  | ||||||
|     * The error throw is internal to the lua interpreter.  When compiled as |  | ||||||
|     * C++, a C++ exception is thrown, so the stack is properly unwound.  This |  | ||||||
|     * exception is not meant to be caught. |  | ||||||
|     */ |  | ||||||
|    state& state::check(number& n, int narg) { |  | ||||||
|       n = luaL_checknumber(L, narg); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
| #if 0 |  | ||||||
|    /** [specialization] Generate a Lua error (T = std::string).
 |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    void state::error(const std::string& message) { |  | ||||||
|       push(message); |  | ||||||
|       lua_error(L); |  | ||||||
|    } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|    /** Call a lua function.
 |  | ||||||
|     * @param nargs the number of args to pass to the function |  | ||||||
|     * @param nresults the number of values to return from the function |  | ||||||
|     * @param on_error A stack index where the error handling function is |  | ||||||
|     * stored. |  | ||||||
|     * @note The error handling function must be pushed in the stack |  | ||||||
|     * before the function to be called and its arguments. |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::pcall(int nargs, int nresults, int on_error) { |  | ||||||
|       throw_error(lua_pcall(L, nargs, nresults, on_error)); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Call a lua function in unprotected mode.
 |  | ||||||
|     * @param nargs the number of args to pass to the function |  | ||||||
|     * @param nresults the number of values to return from the function |  | ||||||
|     * stored. |  | ||||||
|     * @note If there is an error in the call the program will terminate. |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::call(int nargs, int nresults) { |  | ||||||
|       lua_call(L, nargs, nresults); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Ensure the stack is at least the given size.
 |  | ||||||
|     * @param size the size to use |  | ||||||
|     * |  | ||||||
|     * If the stack is smaller than the given size, it will grow to the |  | ||||||
|     * specified size. |  | ||||||
|     * |  | ||||||
|     * @exception lua::exception Thrown if the operation fails. |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::checkstack(int size) { |  | ||||||
|       if (!lua_checkstack(L, size)) |  | ||||||
|          throw lua::exception("Error growing the stack"); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Set a new index as the top of the stack.
 |  | ||||||
|     * @param index the index to use as the new top |  | ||||||
|     * @note If the previous top was higher than the new one, top values |  | ||||||
|     * are discarded.  Otherwise this function pushs nils on to the stack |  | ||||||
|     * to get the proper size. |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::settop(int index) { |  | ||||||
|       lua_settop(L, index); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the number of elements in the stack.
 |  | ||||||
|     * @note This value is also the index of the top element. |  | ||||||
|     * @returns the number of elements in the stack |  | ||||||
|     */ |  | ||||||
|    int state::gettop() { |  | ||||||
|       return lua_gettop(L); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the number of elements in the stack.
 |  | ||||||
|     * @note This value is also the index of the top element. |  | ||||||
|     * @returns the number of elements in the stack |  | ||||||
|     */ |  | ||||||
|    int state::size() { |  | ||||||
|       return lua_gettop(L); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Check if the stack is empty.
 |  | ||||||
|     * @returns true if the stack is empty, false otherwise |  | ||||||
|     */ |  | ||||||
|    bool state::empty() { |  | ||||||
|       return !lua_gettop(L); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Move the top element to the given index.
 |  | ||||||
|     * @param index the index to insert at |  | ||||||
|     * @note All elements on top of the given index are shifted up to open |  | ||||||
|     * space for this element. |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::insert(int index) { |  | ||||||
|       lua_insert(L, index); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Replace the given index with the top element.
 |  | ||||||
|     * @param index the index to replae |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::replace(int index) { |  | ||||||
|       lua_replace(L, index); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Remove the given index from the stack.
 |  | ||||||
|     * @param index the index to remove |  | ||||||
|     * @note Elements are shifted down to fill in the empty spot. |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::remove(int index) { |  | ||||||
|       lua_remove(L, index); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Remove the given number of elemens from the stack.
 |  | ||||||
|     * @param elements the number of elements to remove |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::pop(int elements) { |  | ||||||
|       lua_pop(L, elements); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Push a copy of the element at the given index to the top of the
 |  | ||||||
|     * stack. |  | ||||||
|     * @param index the index of the element to copy |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::pushvalue(int index) { |  | ||||||
|       lua_pushvalue(L, index); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Create a new table on the stack.
 |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::newtable() { |  | ||||||
|       lua_newtable(L); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Create a new metatable and add it to the registry.
 |  | ||||||
|     * @param tname the name to use for the new metatable in the registry |  | ||||||
|     * |  | ||||||
|     * This function creates a new metatable and adds it to the registry |  | ||||||
|     * with the given key.  This function also pushes the new metatable |  | ||||||
|     * onto the stack. |  | ||||||
|     * |  | ||||||
|     * @note Regardless of the return value, the new metatable is always pushed |  | ||||||
|     * on to the stack. |  | ||||||
|     * |  | ||||||
|     * @return true if a new metatable was created, false if the registry |  | ||||||
|     * alread has a key with the given name. |  | ||||||
|     */ |  | ||||||
|    bool state::newmetatable(const std::string& tname) { |  | ||||||
|       return luaL_newmetatable(L, tname.c_str()); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Create a new userdatum on the stack.
 |  | ||||||
|     * @param nbytes the size of the new userdatum |  | ||||||
|     * @return a pointer to the new userdatum |  | ||||||
|     */ |  | ||||||
|    void* state::newuserdata(size_t nbytes) { |  | ||||||
|       return lua_newuserdata(L, nbytes); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get a value from a table on the stack.
 |  | ||||||
|     * @param index the index the table is stored at |  | ||||||
|     * |  | ||||||
|     * This function gets a value from the table at the given index and |  | ||||||
|     * pushes it onto the stack. |  | ||||||
|     * |  | ||||||
|     * @note You should have already pushed the key used to reference this |  | ||||||
|     * value onto the stack before calling this function. |  | ||||||
|     * |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::gettable(int index) { |  | ||||||
|       lua_gettable(L, index); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get a value from a table on the stack.
 |  | ||||||
|     * @param k the key |  | ||||||
|     * @param index the index the table is stored at |  | ||||||
|     * |  | ||||||
|     * This function gets a value from the table at the given index and |  | ||||||
|     * pushes it onto the stack. |  | ||||||
|     * |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::getfield(const std::string& k, int index) { |  | ||||||
|       lua_getfield(L, index, k.c_str()); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Set a value in a table.
 |  | ||||||
|     * @param index the index the table is stored at |  | ||||||
|     * |  | ||||||
|     * This function sets a value in a table stored at the given index. |  | ||||||
|     * |  | ||||||
|     * @note The key and value to be used should have already been pushed |  | ||||||
|     * on the stack in that order. |  | ||||||
|     * |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::settable(int index) { |  | ||||||
|       lua_settable(L, index); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Set a field in a table.
 |  | ||||||
|     * @param k the key |  | ||||||
|     * @param index the index the table is stored at |  | ||||||
|     * |  | ||||||
|     * This function sets a value in a table stored at the given index. |  | ||||||
|     * |  | ||||||
|     * @note The value to be used should be on the top of the stack. |  | ||||||
|     * |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::setfield(const std::string& k, int index) { |  | ||||||
|       lua_setfield(L, index, k.c_str()); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the metatable associated with the given registry entry.
 |  | ||||||
|     * @param tname the name in the registry |  | ||||||
|     * |  | ||||||
|     * This function gets the metatable associated with the given key in |  | ||||||
|     * the registry.  The resulting metatable is pushed onto the stack. |  | ||||||
|     * |  | ||||||
|     * @note This function uses luaL_getmetatable() internally. |  | ||||||
|     * |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::getmetatable(const std::string& tname) { |  | ||||||
|       luaL_getmetatable(L, tname.c_str()); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the metatable of the value at the given index.
 |  | ||||||
|     * @param index the index the value is stored at |  | ||||||
|     * |  | ||||||
|     * This function pushes on to the stack the metatabe of the value at |  | ||||||
|     * the given index. |  | ||||||
|     * |  | ||||||
|     * @note This function uses lua_getmetatable() internally. |  | ||||||
|     * |  | ||||||
|     * @returns false if the value at the given index does not have a |  | ||||||
|     * metatable or if the index is not valid |  | ||||||
|     */ |  | ||||||
|    bool state::getmetatable(int index) { |  | ||||||
|       return lua_getmetatable(L, index); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the next key value pair from a table on the stack.
 |  | ||||||
|     * @param index the stack index the table is at |  | ||||||
|     * |  | ||||||
|     * This function pops a key from the stack and pushes the next key |  | ||||||
|     * value pair to the stack.  The key will be stored at index -2 and |  | ||||||
|     * the value will be at index -1.  The key is expected to be on the |  | ||||||
|     * top of the stack. |  | ||||||
|     * |  | ||||||
|     * @note While traversing a table, do not call |  | ||||||
|     * lua::state::to(std::string()) directly on a key, unless you know |  | ||||||
|     * that the key is actually a string.  lua::state::to(std::string()) |  | ||||||
|     * changes the value at the given index; this confuses the next call |  | ||||||
|     * to lua::state::next(). |  | ||||||
|     * |  | ||||||
|     * <strong>While Loop Example:</strong> |  | ||||||
|     * @code |  | ||||||
|     * while(L.next() != 0) { |  | ||||||
|     *    // do stuff
 |  | ||||||
|     *    L.pop(); |  | ||||||
|     * } |  | ||||||
|     * @endcode |  | ||||||
|     * |  | ||||||
|     * <strong>For Loop Example:</strong> |  | ||||||
|     * @code |  | ||||||
|     * for(L.push(lua::nil()); L.next(); L.pop()) { |  | ||||||
|     *    // do stuff
 |  | ||||||
|     * } |  | ||||||
|     * @endcode |  | ||||||
|     * |  | ||||||
|     * @returns true as long as there are remaining items in the table |  | ||||||
|     */ |  | ||||||
|    bool state::next(int index) { |  | ||||||
|       return lua_next(L, index); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Load a global symbol onto the stack.
 |  | ||||||
|     * @param name the name of the global to load |  | ||||||
|     * |  | ||||||
|     * This function loads a global symbol onto the stack from the lua |  | ||||||
|     * state. |  | ||||||
|     * |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::getglobal(const std::string& name) { |  | ||||||
|       lua_getglobal(L, name.c_str()); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Set a global symbol.
 |  | ||||||
|     * @param name the name of the global to set |  | ||||||
|     * |  | ||||||
|     * This function sets/creates a global symbol from the value above it |  | ||||||
|     * on the stack. |  | ||||||
|     * |  | ||||||
|     * @note You should have pushed the value of the symbol onto the stack |  | ||||||
|     * before calling this function. |  | ||||||
|     * |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::setglobal(const std::string& name) { |  | ||||||
|       lua_setglobal(L, name.c_str()); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Load a file as a Lua chunk.
 |  | ||||||
|     * @param filename the name of the file to load |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::loadfile(const std::string& filename) { |  | ||||||
|       throw_error(luaL_loadfile(L, filename.c_str())); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Load a string as a Lua chunk.
 |  | ||||||
|     * @param s the string to load |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    state& state::loadstring(const std::string& s) { |  | ||||||
|       throw_error(luaL_loadstring(L, s.c_str())); |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the length of a value on the stack.
 |  | ||||||
|     * @param index the index the value is stored at |  | ||||||
|     * @returns the length of the indicated value |  | ||||||
|     */ |  | ||||||
|    size_t state::objlen(int index) { |  | ||||||
|       return lua_rawlen(L, index); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the value at index as a bool.
 |  | ||||||
|     * @param boolean where to store the value |  | ||||||
|     * @param index the index to get |  | ||||||
|     * @note This function does \em not pop the value from the stack. |  | ||||||
|     * @todo Instead of throwing an exception here, we may just return an |  | ||||||
|     * error code. |  | ||||||
|     * @throws lua::bad_conversion if the value on the stack could not be |  | ||||||
|     * converted to the indicated type |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    state& state::to(bool& boolean, int index) { |  | ||||||
|       if (lua_isboolean(L, index)) |  | ||||||
|          boolean = lua_toboolean(L, index); |  | ||||||
|       else |  | ||||||
|          throw bad_conversion("Cannot convert non 'boolean' value to bool"); |  | ||||||
| 
 |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the value at index as a string.
 |  | ||||||
|     * @param string where to store the value |  | ||||||
|     * @param index the index to get |  | ||||||
|     * @note This function does \em not pop the value from the stack. |  | ||||||
|     * @todo Instead of throwing an exception here, we may just return an |  | ||||||
|     * error code. |  | ||||||
|     * |  | ||||||
|     * @note lua::state::to(std::string()) will convert the value at the |  | ||||||
|     * indicated index to a string <em>on the stack</em>.  This can |  | ||||||
|     * confuse lua::state::next(); |  | ||||||
|     * |  | ||||||
|     * @throws lua::bad_conversion if the value on the stack could not be |  | ||||||
|     * converted to the indicated type |  | ||||||
|     * @returns a reference to this lua::state |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    state& state::to(std::string& string, int index) { |  | ||||||
|       if (lua_isstring(L, index)) |  | ||||||
|       { |  | ||||||
|           size_t len; |  | ||||||
|           const char *str = lua_tolstring(L, index, &len); |  | ||||||
|           string.replace(0, std::string::npos, str, len); |  | ||||||
|       } |  | ||||||
|       else |  | ||||||
|          throw bad_conversion("Cannot convert value to string"); |  | ||||||
| 
 |  | ||||||
|       return *this; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** Get the value at index as a bool.
 |  | ||||||
|     * @param default_value this value is returned if the conversion fails |  | ||||||
|     * @param index the index to get |  | ||||||
|     * @note This function does \em not pop the value from the stack. |  | ||||||
|     * @returns the indicated value from the stack or the default value if the |  | ||||||
|     * conversion fails |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    bool state::as(bool default_value, int index) { |  | ||||||
|       if (lua_isboolean(L, index)) |  | ||||||
|          return lua_toboolean(L, index); |  | ||||||
|       else |  | ||||||
|          return default_value; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** [specialization] Get the value at index as a bool (T = bool).
 |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    bool state::as(int index) { |  | ||||||
|       if (lua_isboolean(L, index)) |  | ||||||
|          return lua_toboolean(L, index); |  | ||||||
|       else |  | ||||||
|          throw bad_conversion("Cannot convert non 'boolean' value to bool"); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** [specialization] Get the value at index as a string (T = std::string).
 |  | ||||||
|     * @note lua::state::as(std::string()) will convert the value at the |  | ||||||
|     * indicated index to a string <em>on the stack</em>.  This can confuse |  | ||||||
|     * lua::state::next(); |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    std::string state::as(int index) { |  | ||||||
|       if (lua_isstring(L, index)) |  | ||||||
|       { |  | ||||||
|           size_t len; |  | ||||||
|           const char *str = lua_tolstring(L, index, &len); |  | ||||||
|           return std::string(str, len); |  | ||||||
|       } |  | ||||||
|       else |  | ||||||
|          throw bad_conversion("Cannot convert value to string"); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** [specialization] Check if the given index is a nil (T = lua::nil).
 |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    bool state::is<nil>(int index) { |  | ||||||
|       return lua_isnil(L, index); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** [specialization] Check if the given index is a boolean (T = bool).
 |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    bool state::is<bool>(int index) { |  | ||||||
|       return lua_isboolean(L, index); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** [specialization] Check if the given index is a string (T = std::string).
 |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    bool state::is<std::string>(int index) { |  | ||||||
|       return lua_isstring(L, index); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** [specialization] Check if the given index is a table (T = lua::table).
 |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    bool state::is<table>(int index) { |  | ||||||
|       return lua_istable(L, index); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** [specialization] Check if the given index is a C function (T =
 |  | ||||||
|     * lua::cfunction). |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    bool state::is<cfunction>(int index) { |  | ||||||
|       return lua_iscfunction(L, index); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** [specialization] Check if the given index is a function (T =
 |  | ||||||
|     * lua::function). |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    bool state::is<function>(int index) { |  | ||||||
|       return lua_isfunction(L, index); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** [specialization] Check if the given index is userdata (T =
 |  | ||||||
|     * lua::userdata). |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    bool state::is<userdata>(int index) { |  | ||||||
|       return lua_isuserdata(L, index); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    /** [specialization] Check if the given index is light userdata (T =
 |  | ||||||
|     * lua::lightuserdata). |  | ||||||
|     */ |  | ||||||
|    template<> |  | ||||||
|    bool state::is<lightuserdata>(int index) { |  | ||||||
|       return lua_islightuserdata(L, index); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| @ -1,2 +0,0 @@ | |||||||
| #include "lune.h" |  | ||||||
| lua::object *lua::local_object::mytbl=0; |  | ||||||
| @ -1,153 +0,0 @@ | |||||||
| #include "Core.h" |  | ||||||
| #include "Console.h" |  | ||||||
| #include "Export.h" |  | ||||||
| #include "PluginManager.h" |  | ||||||
| #include <vector> |  | ||||||
| #include <string> |  | ||||||
| #include "modules/Vermin.h" |  | ||||||
| #include "modules/Materials.h" |  | ||||||
| 
 |  | ||||||
| using std::vector; |  | ||||||
| using std::string; |  | ||||||
| using namespace DFHack; |  | ||||||
| 
 |  | ||||||
| command_result colonies (color_ostream &out, vector <string> & parameters); |  | ||||||
| 
 |  | ||||||
| DFHACK_PLUGIN("colonies"); |  | ||||||
| REQUIRE_GLOBAL(world);  // used by Materials
 |  | ||||||
| 
 |  | ||||||
| DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) |  | ||||||
| { |  | ||||||
|     commands.push_back(PluginCommand( |  | ||||||
|         "colonies", "List or change wild colonies (ants hills and such)", |  | ||||||
|         colonies, false, |  | ||||||
|         "  Without any options, this command lists all the vermin colonies present.\n" |  | ||||||
|         "Options:\n" |  | ||||||
|         //"  kill   - destroy colonies\n" // unlisted because it's likely broken anyway
 |  | ||||||
|         "  bees   - turn colonies into honey bee hives\n" |  | ||||||
|     )); |  | ||||||
|     return CR_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| DFhackCExport command_result plugin_shutdown ( color_ostream &out ) |  | ||||||
| { |  | ||||||
|     return CR_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void destroyColonies(); |  | ||||||
| void convertColonies(Materials *Materials); |  | ||||||
| void showColonies(color_ostream &out, Materials *Materials); |  | ||||||
| 
 |  | ||||||
| command_result colonies (color_ostream &out, vector <string> & parameters) |  | ||||||
| { |  | ||||||
|     bool destroy = false; |  | ||||||
|     bool convert = false; |  | ||||||
| 
 |  | ||||||
|     for(size_t i = 0; i < parameters.size();i++) |  | ||||||
|     { |  | ||||||
|         if(parameters[i] == "kill") |  | ||||||
|             destroy = true; |  | ||||||
|         else if(parameters[i] == "bees") |  | ||||||
|             convert = true; |  | ||||||
|         else |  | ||||||
|             return CR_WRONG_USAGE; |  | ||||||
|     } |  | ||||||
|     if (destroy && convert) |  | ||||||
|     { |  | ||||||
|         out.printerr("Kill or make bees? DECIDE!\n"); |  | ||||||
|         return CR_FAILURE; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     CoreSuspender suspend; |  | ||||||
| 
 |  | ||||||
|     Materials * materials = Core::getInstance().getMaterials(); |  | ||||||
| 
 |  | ||||||
|     materials->ReadCreatureTypesEx(); |  | ||||||
| 
 |  | ||||||
|     if (destroy) |  | ||||||
|         destroyColonies(); |  | ||||||
|     else if (convert) |  | ||||||
|         convertColonies(materials); |  | ||||||
|     else |  | ||||||
|         showColonies(out, materials); |  | ||||||
| 
 |  | ||||||
|     materials->Finish(); |  | ||||||
| 
 |  | ||||||
|     return CR_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| //FIXME: this is probably bullshit
 |  | ||||||
| void destroyColonies() |  | ||||||
| { |  | ||||||
|     uint32_t numSpawnPoints = Vermin::getNumVermin(); |  | ||||||
|     for (uint32_t i = 0; i < numSpawnPoints; i++) |  | ||||||
|     { |  | ||||||
|         Vermin::t_vermin sp; |  | ||||||
|         Vermin::Read(i, sp); |  | ||||||
| 
 |  | ||||||
|         if (sp.visible && sp.is_colony) |  | ||||||
|         { |  | ||||||
|             sp.visible = false; |  | ||||||
|             Vermin::Write(i, sp); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Convert all colonies to honey bees.
 |  | ||||||
| void convertColonies(Materials *Materials) |  | ||||||
| { |  | ||||||
|     int bee_idx = -1; |  | ||||||
|     for (size_t i = 0; i < Materials->raceEx.size(); i++) |  | ||||||
|     { |  | ||||||
|         if (Materials->raceEx[i].id == "HONEY_BEE") |  | ||||||
|         { |  | ||||||
|             bee_idx = i; |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (bee_idx == -1) |  | ||||||
|     { |  | ||||||
|         std::cerr << "Honey bees not present in game." << std::endl; |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     uint32_t numSpawnPoints = Vermin::getNumVermin(); |  | ||||||
|     for (uint32_t i = 0; i < numSpawnPoints; i++) |  | ||||||
|     { |  | ||||||
|         Vermin::t_vermin sp; |  | ||||||
|         Vermin::Read(i, sp); |  | ||||||
| 
 |  | ||||||
|         if (sp.visible && sp.is_colony) |  | ||||||
|         { |  | ||||||
|             sp.race = bee_idx; |  | ||||||
|             Vermin::Write(i, sp); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void showColonies(color_ostream &out, Materials *Materials) |  | ||||||
| { |  | ||||||
|     uint32_t numSpawnPoints = Vermin::getNumVermin(); |  | ||||||
|     int      numColonies    = 0; |  | ||||||
|     for (uint32_t i = 0; i < numSpawnPoints; i++) |  | ||||||
|     { |  | ||||||
|         Vermin::t_vermin sp; |  | ||||||
| 
 |  | ||||||
|         Vermin::Read(i, sp); |  | ||||||
| 
 |  | ||||||
|         if (sp.visible && sp.is_colony) |  | ||||||
|         { |  | ||||||
|             numColonies++; |  | ||||||
|             string race="(no race)"; |  | ||||||
|             if(sp.race != -1) |  | ||||||
|                 race = Materials->raceEx[sp.race].id; |  | ||||||
| 
 |  | ||||||
|             out.print("Colony %u: %s at %d:%d:%d\n", i, |  | ||||||
|                       race.c_str(), sp.x, sp.y, sp.z); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (numColonies == 0) |  | ||||||
|         out << "No colonies present." << std::endl; |  | ||||||
| } |  | ||||||
| @ -1 +0,0 @@ | |||||||
| Subproject commit 5b167d2ba89b877d80e0609feae8771aeaef356d |  | ||||||
| @ -1,31 +0,0 @@ | |||||||
| PROJECT (export) |  | ||||||
| # A list of source files |  | ||||||
| SET(PROJECT_SRCS |  | ||||||
|     dwarfexport.cpp |  | ||||||
| ) |  | ||||||
| # A list of headers |  | ||||||
| SET(PROJECT_HDRS |  | ||||||
|     dwarfexport.h |  | ||||||
| ) |  | ||||||
| SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE) |  | ||||||
| 
 |  | ||||||
| # mash them together (headers are marked as headers and nothing will try to compile them) |  | ||||||
| LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS}) |  | ||||||
| 
 |  | ||||||
| #linux |  | ||||||
| IF(UNIX) |  | ||||||
|     add_definitions(-DLINUX_BUILD) |  | ||||||
|     SET(PROJECT_LIBS |  | ||||||
|         # add any extra linux libs here |  | ||||||
|         ${PROJECT_LIBS} |  | ||||||
|     ) |  | ||||||
| # windows |  | ||||||
| ELSE(UNIX) |  | ||||||
|     SET(PROJECT_LIBS |  | ||||||
|         # add any extra linux libs here |  | ||||||
|         ${PROJECT_LIBS} |  | ||||||
|         $(NOINHERIT) |  | ||||||
|     ) |  | ||||||
| ENDIF(UNIX) |  | ||||||
| # this makes sure all the stuff is put in proper places and linked to dfhack |  | ||||||
| DFHACK_PLUGIN(dwarfexport ${PROJECT_SRCS} LINK_LIBRARIES ${PROJECT_LIBS}) |  | ||||||
| @ -1,244 +0,0 @@ | |||||||
| // some headers required for a plugin. Nothing special, just the basics.
 |  | ||||||
| #include <vector> |  | ||||||
| #include <string> |  | ||||||
| #include <fstream> |  | ||||||
| #include <iostream> |  | ||||||
| using namespace std; |  | ||||||
| 
 |  | ||||||
| #define DFHACK_WANT_MISCUTILS |  | ||||||
| #include <Core.h> |  | ||||||
| #include <VersionInfo.h> |  | ||||||
| #include <Console.h> |  | ||||||
| #include <Export.h> |  | ||||||
| #include <PluginManager.h> |  | ||||||
| #include <modules/Units.h> |  | ||||||
| #include <modules/Translation.h> |  | ||||||
| 
 |  | ||||||
| #include <df/ui.h> |  | ||||||
| #include <df/world.h> |  | ||||||
| #include <df/unit.h> |  | ||||||
| #include <df/unit_soul.h> |  | ||||||
| #include <df/unit_labor.h> |  | ||||||
| #include <df/unit_skill.h> |  | ||||||
| /*
 |  | ||||||
| dwarfexport |  | ||||||
| =========== |  | ||||||
| Export dwarves to RuneSmith-compatible XML; also unused by modern tools. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| using namespace DFHack; |  | ||||||
| using df::global::ui; |  | ||||||
| using df::global::world; |  | ||||||
| 
 |  | ||||||
| // our own, empty header.
 |  | ||||||
| #include "dwarfexport.h" |  | ||||||
| #include <df/personality_facet_type.h> |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| // Here go all the command declarations...
 |  | ||||||
| // mostly to allow having the mandatory stuff on top of the file and commands on the bottom
 |  | ||||||
| command_result export_dwarves (color_ostream &con, std::vector <std::string> & parameters); |  | ||||||
| 
 |  | ||||||
| DFHACK_PLUGIN("dwarfexport"); |  | ||||||
| 
 |  | ||||||
| // Mandatory init function. If you have some global state, create it here.
 |  | ||||||
| DFhackCExport command_result plugin_init (color_ostream &con, std::vector <PluginCommand> &commands) |  | ||||||
| { |  | ||||||
|     // Fill the command list with your commands.
 |  | ||||||
|     commands.push_back(PluginCommand("dwarfexport", |  | ||||||
|                                      "Export dwarves to RuneSmith-compatible XML.", |  | ||||||
|                                      export_dwarves /*,
 |  | ||||||
|                                      true or false - true means that the command can't be used from non-interactive user interface'*/)); |  | ||||||
|     return CR_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // This is called right before the plugin library is removed from memory.
 |  | ||||||
| DFhackCExport command_result plugin_shutdown (color_ostream &con) |  | ||||||
| { |  | ||||||
|     return CR_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static const char* physicals[] = { |  | ||||||
|     "Strength", |  | ||||||
|     "Agility", |  | ||||||
|     "Toughness", |  | ||||||
|     "Endurance", |  | ||||||
|     "Recuperation", |  | ||||||
|     "DiseaseResistance", |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const char* mentals[] = { |  | ||||||
|     "AnalyticalAbility", |  | ||||||
|     "Focus", |  | ||||||
|     "Willpower", |  | ||||||
|     "Creatvity", //Speeling deliberate
 |  | ||||||
|     "Intuition", |  | ||||||
|     "Patience", |  | ||||||
|     "Memory", |  | ||||||
|     "LinguisticAbility", |  | ||||||
|     "SpatialSense", |  | ||||||
|     "Musicality", |  | ||||||
|     "KinaestheticSense", |  | ||||||
|     "Empathy", |  | ||||||
|     "SocialAwareness", |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static void element(const char* name, const char* content, ostream& out, const char* extra_indent="") { |  | ||||||
|     out << extra_indent << "    <" << name << ">" << content << "</" << name << ">" << endl; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void element(const char* name, const uint32_t content, ostream& out, const char* extra_indent="") { |  | ||||||
|     out << extra_indent << "    <" << name << ">" << content << "</" << name << ">" << endl; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void printAttributes(color_ostream &con, df::unit* cre, ostream& out) { |  | ||||||
|     out << "    <Attributes>" << endl; |  | ||||||
|     for (int i = 0; i < NUM_CREATURE_PHYSICAL_ATTRIBUTES; i++) { |  | ||||||
|         element(physicals[i], cre->body.physical_attrs[i].value, out, "  "); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     df::unit_soul * s = cre->status.current_soul; |  | ||||||
|     if (s) { |  | ||||||
|         for (int i = 0; i < NUM_CREATURE_MENTAL_ATTRIBUTES; i++) { |  | ||||||
|             element(mentals[i], s->mental_attrs[i].value, out, "  "); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     out << "    </Attributes>" << endl; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void printTraits(color_ostream &con, df::unit* cre, ostream& out) |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
|     out << "    <Traits>" << endl; |  | ||||||
|     df::unit_soul * s = cre->status.current_soul; |  | ||||||
|     if (s) |  | ||||||
|     { |  | ||||||
|         FOR_ENUM_ITEMS(personality_facet_type,index) |  | ||||||
|         { |  | ||||||
|             out << "      <Trait name='" << ENUM_KEY_STR(personality_facet_type, index) << |  | ||||||
|                 "' value='" << s->traits[index] << "'>"; |  | ||||||
|             //FIXME: needs reimplementing trait string generation
 |  | ||||||
|             /*
 |  | ||||||
|             string trait = con->vinfo->getTrait(i, s->traits[i]); |  | ||||||
|             if (!trait.empty()) { |  | ||||||
|                 out << trait.c_str(); |  | ||||||
|             } |  | ||||||
|             */ |  | ||||||
|             out << "</Trait>" << endl; |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     out << "    </Traits>" << endl; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int32_t getCreatureAge(df::unit* cre) |  | ||||||
| { |  | ||||||
|     int32_t yearDifference = *df::global::cur_year - cre->relations.birth_year; |  | ||||||
| 
 |  | ||||||
|     // If the birthday this year has not yet passed, subtract one year.
 |  | ||||||
|     // ASSUMPTION: birth_time is on the same scale as cur_year_tick
 |  | ||||||
|     if (cre->relations.birth_time >= *df::global::cur_year_tick) { |  | ||||||
|         yearDifference--; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return yearDifference; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void printLabors(color_ostream &con, df::unit* cre, ostream& out) |  | ||||||
| { |  | ||||||
|     // Using British spelling here, consistent with Runesmith
 |  | ||||||
|     out << "  <Labours>" << endl; |  | ||||||
|     FOR_ENUM_ITEMS(unit_labor, iCount) |  | ||||||
|     { |  | ||||||
|         if (cre->status.labors[iCount]) { |  | ||||||
|             // Get the caption for the labor index.
 |  | ||||||
|             element("Labour", ENUM_ATTR_STR(unit_labor, caption, iCount), out); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     out << "  </Labours>" << endl; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void printSkill(color_ostream &con, df::unit_skill* skill, ostream& out) |  | ||||||
| { |  | ||||||
|     out << "    <Skill>" << endl; |  | ||||||
| 
 |  | ||||||
|     element("Name", ENUM_ATTR_STR(job_skill, caption, skill->id), out); |  | ||||||
|     element("Level", skill->rating, out); |  | ||||||
| 
 |  | ||||||
|     out << "    </Skill>" << endl; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void printSkills(color_ostream &con, df::unit* cre, ostream& out) |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
|     std::vector<df::unit_skill* > vSkills = cre->status.current_soul->skills; |  | ||||||
| 
 |  | ||||||
|     out << "  <Skills>" << endl; |  | ||||||
|     for (int iCount = 0; iCount < vSkills.size(); iCount++) |  | ||||||
|     { |  | ||||||
|         printSkill(con, vSkills.at(iCount), out); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     out << "  </Skills>" << endl; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GDC needs:
 |  | ||||||
| // Name
 |  | ||||||
| // Nickname
 |  | ||||||
| // Sex
 |  | ||||||
| // Attributes
 |  | ||||||
| // Traits
 |  | ||||||
| static void export_dwarf(color_ostream &con, df::unit* cre, ostream& out) { |  | ||||||
|     string info = cre->name.first_name; |  | ||||||
|     info += " "; |  | ||||||
|     info += Translation::TranslateName(&cre->name, false); |  | ||||||
|     info[0] = toupper(info[0]); |  | ||||||
|     con.print("Exporting %s\n", info.c_str()); |  | ||||||
| 
 |  | ||||||
|     out << "  <Creature>" << endl; |  | ||||||
|     element("Name", info.c_str(), out); |  | ||||||
|     element("Nickname", cre->name.nickname.c_str(), out); |  | ||||||
|     element("Sex", cre->sex == 0 ? "Female" : "Male", out); |  | ||||||
|     element("Age", getCreatureAge(cre), out);       // Added age, active labors, and skills March 9, 2012
 |  | ||||||
|     printAttributes(con, cre, out); |  | ||||||
|     printTraits(con, cre, out); |  | ||||||
|     printLabors(con, cre, out); |  | ||||||
|     printSkills(con, cre, out); |  | ||||||
| 
 |  | ||||||
|     out << "  </Creature>" << endl; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| command_result export_dwarves (color_ostream &con, std::vector <std::string> & parameters) |  | ||||||
| { |  | ||||||
|     string filename; |  | ||||||
|     if (parameters.size() == 1) { |  | ||||||
|         filename = parameters[0]; |  | ||||||
|     } else { |  | ||||||
|         con.print("export <filename>\n"); |  | ||||||
|         return CR_OK; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     ofstream outf(filename.c_str()); |  | ||||||
|     if (!outf) { |  | ||||||
|         con.printerr("Failed to open file %s\n", filename.c_str()); |  | ||||||
|         return CR_FAILURE; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     CoreSuspender suspend; |  | ||||||
| 
 |  | ||||||
|     uint32_t race = ui->race_id; |  | ||||||
|     uint32_t civ = ui->civ_id; |  | ||||||
| 
 |  | ||||||
|     outf << "<?xml version='1.0' encoding='ibm850'?>" << endl << "<Creatures>" << endl; |  | ||||||
| 
 |  | ||||||
|     for (int i = 0; i < world->units.all.size(); ++i) |  | ||||||
|     { |  | ||||||
|         df::unit* cre = world->units.all[i]; |  | ||||||
|         if (cre->race == race && cre->civ_id == civ) { |  | ||||||
|             export_dwarf(con, cre, outf); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     outf << "</Creatures>" << endl; |  | ||||||
| 
 |  | ||||||
|     return CR_OK; |  | ||||||
| } |  | ||||||
| @ -1 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| @ -1,241 +0,0 @@ | |||||||
| -- Stuff used by dfusion |  | ||||||
| local _ENV = mkmodule('plugins.dfusion') |  | ||||||
| 
 |  | ||||||
| local ms=require("memscan") |  | ||||||
| 
 |  | ||||||
| local marker={0xDE,0xAD,0xBE,0xEF} |  | ||||||
| --utility functions |  | ||||||
| function dwordToTable(dword) |  | ||||||
|     local b={bit32.extract(dword,0,8),bit32.extract(dword,8,8),bit32.extract(dword,16,8),bit32.extract(dword,24,8)} |  | ||||||
|     return b |  | ||||||
| end |  | ||||||
| function concatTables(t1,t2) |  | ||||||
|     for k,v in pairs(t2) do |  | ||||||
|         table.insert(t1,v) |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| function makeCall(from,to) |  | ||||||
|     local ret={0xe8} |  | ||||||
|     concatTables(ret,dwordToTable(to-from-5)) |  | ||||||
|     return ret |  | ||||||
| end |  | ||||||
| -- A reversable binary patch |  | ||||||
| patches={} |  | ||||||
| BinaryPatch=defclass(BinaryPatch) |  | ||||||
| BinaryPatch.ATTRS {pre_data=DEFAULT_NIL,data=DEFAULT_NIL,address=DEFAULT_NIL,name=DEFAULT_NIL} |  | ||||||
| function BinaryPatch:init(args) |  | ||||||
|     self.is_applied=false |  | ||||||
|     if args.pre_data==nil or args.data==nil or args.address==nil or args.name==nil then |  | ||||||
|         error("Invalid parameters to binary patch") |  | ||||||
|     end |  | ||||||
|     if patches[self.name]~=nil then |  | ||||||
|         error("Patch already exist") |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     for k,v in ipairs(args.data) do |  | ||||||
|         if args.pre_data[k]==nil then |  | ||||||
|             error("can't edit without revert data") |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| function BinaryPatch:postinit(args) |  | ||||||
|     patches[args.name]=self |  | ||||||
| end |  | ||||||
| function BinaryPatch:test() |  | ||||||
|     local arr=ms.CheckedArray.new('uint8_t',self.address,self.address+#self.pre_data) |  | ||||||
|     for k,v in ipairs(self.pre_data) do |  | ||||||
|         if arr[k-1]~=v then |  | ||||||
|             return false |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     return true |  | ||||||
| end |  | ||||||
| function BinaryPatch:apply() |  | ||||||
|     if not self:test() then |  | ||||||
|         error(string.format("pre-data for binary patch does not match expected")) |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     local post_buf=df.new('uint8_t',#self.pre_data) |  | ||||||
|     for k,v in ipairs(self.pre_data) do |  | ||||||
|         if self.data[k]==nil then |  | ||||||
|             post_buf[k-1]=v |  | ||||||
|         else |  | ||||||
|             post_buf[k-1]=self.data[k] |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     local ret=dfhack.with_finalize(function() post_buf:delete() end,dfhack.internal.patchMemory,self.address,post_buf,#self.pre_data) |  | ||||||
|     if not ret then |  | ||||||
|         error("Patch application failed!") |  | ||||||
|     end |  | ||||||
|     self.is_applied=true |  | ||||||
| end |  | ||||||
| function BinaryPatch:repatch(newdata) |  | ||||||
|     if newdata==nil then newdata=self.data end |  | ||||||
|     self:remove() |  | ||||||
|     self.data=newdata |  | ||||||
|     self:apply() |  | ||||||
| end |  | ||||||
| function BinaryPatch:remove(delete) |  | ||||||
|     if delete==nil then |  | ||||||
|         delete=true |  | ||||||
|     end |  | ||||||
|     if not self.is_applied then |  | ||||||
|         error("can't remove BinaryPatch, not applied.") |  | ||||||
|     end |  | ||||||
|     local arr=ms.CheckedArray.new('uint8_t',self.address,self.address+#self.pre_data) |  | ||||||
| 
 |  | ||||||
|     local post_buf=df.new('uint8_t',#self.pre_data) |  | ||||||
|     for k,v in pairs(self.pre_data) do |  | ||||||
|             post_buf[k-1]=v |  | ||||||
|     end |  | ||||||
|     local ret=dfhack.with_finalize(function() post_buf:delete() end,dfhack.internal.patchMemory,self.address,post_buf,#self.pre_data) |  | ||||||
|     if not ret then |  | ||||||
|         error("Patch remove failed!") |  | ||||||
|     end |  | ||||||
|     self.is_applied=false |  | ||||||
|     if delete then |  | ||||||
|         patches[self.name]=nil |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function BinaryPatch:__gc() |  | ||||||
|     if self.is_applied then |  | ||||||
|         self:remove() |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| -- A binary hack (obj file) loader/manager |  | ||||||
| -- has to have: a way to get offsets for marked areas (for post load modification) or some way to do that pre-load |  | ||||||
| -- page managing (including excecute/write flags for DEP and the like) |  | ||||||
| -- TODO plugin state enum, a way to modify post install (could include repatching code...) |  | ||||||
| plugins=plugins or {} |  | ||||||
| BinaryPlugin=defclass(BinaryPlugin) |  | ||||||
| BinaryPlugin.ATTRS {filename=DEFAULT_NIL,reloc_table={},name=DEFAULT_NIL} |  | ||||||
| function BinaryPlugin:init(args) |  | ||||||
| 
 |  | ||||||
| end |  | ||||||
| function BinaryPlugin:postinit(args) |  | ||||||
|     if self.name==nil then error("Not a valid plugin name!") end |  | ||||||
|     if plugins[args.name]==nil then |  | ||||||
|         plugins[self.name]=self |  | ||||||
|     else |  | ||||||
|         error("Trying to create a same plugin") |  | ||||||
|     end |  | ||||||
|     self.allocated_object={} |  | ||||||
|     self:load() |  | ||||||
| end |  | ||||||
| function BinaryPlugin:get_or_alloc(name,typename,arrsize) |  | ||||||
|     if self.allocated_object[name]~=nil then |  | ||||||
|         return self.allocated_object[name] |  | ||||||
|     else |  | ||||||
|         return self:allocate(name,typename,arrsize) |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| function BinaryPlugin:allocate(name,typename,arrsize) |  | ||||||
|     local trg |  | ||||||
|     if df[typename]==nil then |  | ||||||
|         trg=df.new(typename,arrsize) |  | ||||||
|         self.allocated_object[name]=trg |  | ||||||
|     else |  | ||||||
|         trg=df[typename]:new(arrsize) |  | ||||||
|         self.allocated_object[name]=trg |  | ||||||
|     end |  | ||||||
|     return trg |  | ||||||
| end |  | ||||||
| function BinaryPlugin:load() |  | ||||||
|     local obj=loadObjectFile(self.filename) |  | ||||||
|     self.data=df.reinterpret_cast("uint8_t",obj.data) |  | ||||||
|     self.size=obj.data_size |  | ||||||
|     for _,v in pairs(obj.symbols) do |  | ||||||
|         if string.sub(v.name,1,5)=="mark_" then |  | ||||||
|             local new_pos=self:find_marker(v.pos) |  | ||||||
|             self.reloc_table[string.sub(v.name,6)]=new_pos |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| function BinaryPlugin:find_marker(start_pos) |  | ||||||
|     local matched=0 |  | ||||||
|     for i=start_pos,self.size do |  | ||||||
|         if self.data[i]==marker[4-matched] then |  | ||||||
|             matched=matched+1 |  | ||||||
|             if matched == 4 then |  | ||||||
|                 return i-4 |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| function BinaryPlugin:set_marker_dword(marker,dword) -- i hope Toady does not make a 64bit version... |  | ||||||
|     if self.reloc_table[marker]==nil then |  | ||||||
|         error("marker ".. marker.. " not found") |  | ||||||
|     end |  | ||||||
|     local b=dwordToTable(dword) |  | ||||||
|     local off=self.reloc_table[marker] |  | ||||||
|     for k,v in ipairs(b) do |  | ||||||
|         self.data[off+k]=b[k] |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| function BinaryPlugin:move_to_df() |  | ||||||
|     local _,addr=df.sizeof(self.data) |  | ||||||
|     markAsExecutable(addr) |  | ||||||
|     return addr |  | ||||||
| end |  | ||||||
| function BinaryPlugin:print_data() |  | ||||||
|     local out="" |  | ||||||
|     for i=0,self.size do |  | ||||||
|         out=out..string.format(" %02x",self.data[i]) |  | ||||||
|         if math.modf(i,16)==15 then |  | ||||||
|             print(out) |  | ||||||
|             out="" |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     print(out) |  | ||||||
| end |  | ||||||
| function BinaryPlugin:status() |  | ||||||
|     return "invalid, base class only!" |  | ||||||
| end |  | ||||||
| function BinaryPlugin:__gc() |  | ||||||
|     for k,v in pairs(self.allocated_object) do |  | ||||||
|         df.delete(v) |  | ||||||
|     end |  | ||||||
|     if self.unload then |  | ||||||
|         self:unload() |  | ||||||
|     end |  | ||||||
|     self.data:delete() |  | ||||||
| end |  | ||||||
| -- a Menu for some stuff. Maybe add a posibility of it working as a gui, or a gui adaptor? |  | ||||||
| -- Todo add hints, and parse them to make a "smart" choice of parameters to pass |  | ||||||
| SimpleMenu=defclass(SimpleMenu) |  | ||||||
| SimpleMenu.ATTRS{title=DEFAULT_NIL} |  | ||||||
| function SimpleMenu:init(args) |  | ||||||
|     self.items={} |  | ||||||
| end |  | ||||||
| function SimpleMenu:add(name,entry,hints) |  | ||||||
|     table.insert(self.items,{entry,name,hints}) |  | ||||||
| end |  | ||||||
| function SimpleMenu:display() |  | ||||||
|     print("Select choice (q exits):") |  | ||||||
|     for p,c in pairs(self.items) do |  | ||||||
|         print(string.format("%3d).%s",p,c[2])) |  | ||||||
|     end |  | ||||||
|     local ans |  | ||||||
|     repeat |  | ||||||
|         local r |  | ||||||
|         r=dfhack.lineedit() |  | ||||||
|         if r==nil then return end |  | ||||||
|         if r=='q' then return end |  | ||||||
|         ans=tonumber(r) |  | ||||||
| 
 |  | ||||||
|         if ans==nil or not(ans<=#self.items and ans>0) then |  | ||||||
|             print("Invalid choice.") |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|     until ans~=nil and (ans<=#self.items and ans>0) |  | ||||||
|     if type(self.items[ans][1])=="function" then |  | ||||||
|         self.items[ans][1]() |  | ||||||
|     else |  | ||||||
|         self.items[ans][1]:display() |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| 
 |  | ||||||
| return _ENV |  | ||||||
| @ -1,172 +0,0 @@ | |||||||
| local _ENV = mkmodule('plugins.dfusion.adv_tools') |  | ||||||
| local dfu=require("plugins.dfusion") |  | ||||||
| local tools=require("plugins.dfusion.tools") |  | ||||||
| menu=dfu.SimpleMenu() |  | ||||||
| function Reincarnate(trg_unit,swap_soul) --only for adventurer i guess |  | ||||||
|     if swap_soul==nil then |  | ||||||
|         swap_soul=true |  | ||||||
|     end |  | ||||||
|     local adv=trg_unit or df.global.world.units.active[0] |  | ||||||
|     if adv.flags1.dead==false then |  | ||||||
|         qerror("You are not dead (yet)!") |  | ||||||
|     end |  | ||||||
|     local hist_fig=dfhack.units.getNemesis(adv).figure |  | ||||||
|     if hist_fig==nil then |  | ||||||
|         qerror("No historical figure for adventurer...") |  | ||||||
|     end |  | ||||||
|     local events=df.global.world.history.events |  | ||||||
|     local trg_hist_fig |  | ||||||
|     for i=#events-1,0,-1 do -- reverse search because almost always it will be last entry |  | ||||||
|         if df.history_event_hist_figure_diedst:is_instance(events[i]) then |  | ||||||
|             --print("is instance:"..i) |  | ||||||
|             if events[i].victim_hf==hist_fig.id then |  | ||||||
|                 --print("Is same id:"..i) |  | ||||||
|                 trg_hist_fig=events[i].slayer_hf |  | ||||||
|                 if trg_hist_fig then |  | ||||||
|                     trg_hist_fig=df.historical_figure.find(trg_hist_fig) |  | ||||||
|                 end |  | ||||||
|                 break |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     if trg_hist_fig ==nil then |  | ||||||
|         qerror("Slayer not found") |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     local trg_unit=trg_hist_fig.unit_id |  | ||||||
|     if trg_unit==nil then |  | ||||||
|         qerror("Unit id not found!") |  | ||||||
|     end |  | ||||||
|     local trg_unit_final=df.unit.find(trg_unit) |  | ||||||
| 
 |  | ||||||
|     change_adv(trg_unit_final) |  | ||||||
|     if swap_soul then --actually add a soul... |  | ||||||
|         t_soul=adv.status.current_soul |  | ||||||
|         adv.status.current_soul=df.NULL |  | ||||||
|         adv.status.souls:resize(0) |  | ||||||
|         trg_unit_final.status.current_soul=t_soul |  | ||||||
|         trg_unit_final.status.souls:insert(#trg_unit_final.status.souls,t_soul) |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| menu:add("Reincarnate",Reincarnate,{{df.unit,"optional"}})-- bool, optional |  | ||||||
| function change_adv(unit,nemesis) |  | ||||||
|     if nemesis==nil then |  | ||||||
|         nemesis=true --default value is nemesis switch too. |  | ||||||
|     end |  | ||||||
|     if unit==nil then |  | ||||||
|         unit=dfhack.gui.getSelectedUnit()--getCreatureAtPointer() |  | ||||||
|     end |  | ||||||
|     if unit==nil then |  | ||||||
|         error("Invalid unit!") |  | ||||||
|     end |  | ||||||
|     local other=df.global.world.units.active |  | ||||||
|     local unit_indx |  | ||||||
|     for k,v in pairs(other) do |  | ||||||
|         if v==unit then |  | ||||||
|             unit_indx=k |  | ||||||
|             break |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     if unit_indx==nil then |  | ||||||
|         error("Unit not found in array?!") --should not happen |  | ||||||
|     end |  | ||||||
|     other[unit_indx]=other[0] |  | ||||||
|     other[0]=unit |  | ||||||
|     if nemesis then --basicly copied from advtools plugin... |  | ||||||
|         local nem=dfhack.units.getNemesis(unit) |  | ||||||
|         local other_nem=dfhack.units.getNemesis(other[unit_indx]) |  | ||||||
|         if other_nem then |  | ||||||
|             other_nem.flags[0]=false |  | ||||||
|             other_nem.flags[1]=true |  | ||||||
|         end |  | ||||||
|         if nem then |  | ||||||
|             nem.flags[0]=true |  | ||||||
|             nem.flags[2]=true |  | ||||||
|             for k,v in pairs(df.global.world.nemesis.all) do |  | ||||||
|                 if v.id==nem.id then |  | ||||||
|                     df.global.ui_advmode.player_id=k |  | ||||||
|                 end |  | ||||||
|             end |  | ||||||
|         else |  | ||||||
|             qerror("Current unit does not have nemesis record, further working not guaranteed") |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| menu:add("Change adventurer",change_adv) |  | ||||||
| function log_pos() |  | ||||||
|     local adv=df.global.world.units.active[0] |  | ||||||
| 
 |  | ||||||
|     local wmap=df.global.world.map |  | ||||||
|     local sub_pos={x=adv.pos.x,y=adv.pos.y,z=adv.pos.z} |  | ||||||
|     local region_pos={x=wmap.region_x,y=wmap.region_y,z=wmap.region_z} |  | ||||||
|     local pos={x=sub_pos.x+region_pos.x*48,y=sub_pos.y+region_pos.y*48,z=sub_pos.z+region_pos.z} |  | ||||||
|     local state |  | ||||||
|     if adv.flags1.dead then |  | ||||||
|         state="dead" |  | ||||||
|     else |  | ||||||
|         state="live n kicking" |  | ||||||
|     end |  | ||||||
|     local message=string.format("%s %s at pos={%d,%d,%d} region={%d,%d,%d}",dfhack.TranslateName(adv.name),state,pos.x,pos.y,pos.z,region_pos.x,region_pos.y,region_pos.z) |  | ||||||
|     print(message) |  | ||||||
|     local path="deaths_"..df.global.world.cur_savegame.save_dir..".txt" |  | ||||||
|     local f=io.open(path,"a") |  | ||||||
|     f:write(message) |  | ||||||
|     f:close() |  | ||||||
| end |  | ||||||
| menu:add("Log adventurers position",log_pos) |  | ||||||
| function addSite(x,y,rgn_max_x,rgn_min_x,rgn_max_y,rgn_min_y,civ_id,name,sitetype) |  | ||||||
|     if x==nil or y==nil then |  | ||||||
|         x=(df.global.world.map.region_x+1)/16 |  | ||||||
|         y=(df.global.world.map.region_y+1)/16 |  | ||||||
|     end |  | ||||||
|     if name==nil then |  | ||||||
|         name=dfhack.lineedit("Site name:")or "Hacked site" |  | ||||||
|     end |  | ||||||
|     if sitetype==nil then |  | ||||||
|         sitetype=tonumber(dfhack.lineedit("Site type (numeric):")) or 7 |  | ||||||
|     end |  | ||||||
|     rgn_max_x=rgn_max_x or (df.global.world.map.region_x+1)%16 |  | ||||||
|     rgn_max_y=rgn_max_y or (df.global.world.map.region_y+1)%16 |  | ||||||
|     rgn_min_y=rgn_min_y or rgn_max_y |  | ||||||
|     rgn_min_x=rgn_min_x or rgn_max_x |  | ||||||
|     print("Region:",rgn_max_x,rgn_min_x,rgn_max_y,rgn_min_y) |  | ||||||
| --[=[ |  | ||||||
| <angavrilov> global = pos*16 + rgn |  | ||||||
| <angavrilov> BUT |  | ||||||
| <angavrilov> for cities global is usually 17x17, i.e. max size |  | ||||||
| <angavrilov> while rgn designates a small bit in the middle |  | ||||||
| <angavrilov> for stuff like forts that formula holds exactly |  | ||||||
| ]=]-- |  | ||||||
|     local wd=df.global.world.world_data |  | ||||||
|     local nsite=df.world_site:new() |  | ||||||
|     nsite.name.first_name=name |  | ||||||
|     nsite.name.has_name=true |  | ||||||
|     nsite.pos:assign{x=x,y=y} |  | ||||||
|     nsite.rgn_max_x=rgn_max_x |  | ||||||
|     nsite.rgn_min_x=rgn_min_x |  | ||||||
|     nsite.rgn_min_y=rgn_min_y |  | ||||||
|     nsite.rgn_max_y=rgn_max_y |  | ||||||
|     nsite.global_max_x=nsite.pos.x*16+nsite.rgn_max_x |  | ||||||
|     nsite.global_min_x=nsite.pos.x*16+nsite.rgn_min_x |  | ||||||
|     nsite.global_max_y=nsite.pos.y*16+nsite.rgn_max_y |  | ||||||
|     nsite.global_min_y=nsite.pos.y*16+nsite.rgn_min_y |  | ||||||
|     nsite.id=wd.next_site_id |  | ||||||
|     nsite.civ_id=civ_id or -1 |  | ||||||
|     nsite.cur_owner_id=civ_id or -1 |  | ||||||
|     nsite.type=sitetype --lair = 7 |  | ||||||
|     nsite.flags:resize(23) |  | ||||||
|     --nsite.flags[4]=true |  | ||||||
|     --nsite.flags[5]=true |  | ||||||
|     --nsite.flags[6]=true |  | ||||||
|     nsite.index=#wd.sites+1 |  | ||||||
|     wd.sites:insert("#",nsite) |  | ||||||
|     wd.next_site_id=wd.next_site_id+1 |  | ||||||
|     --might not be needed... |  | ||||||
|     --[[local unk130=df.world_site_unk130:new() |  | ||||||
|     unk130.index=#wd.site_unk130+1 |  | ||||||
|     wd.site_unk130:insert("#",unk130) |  | ||||||
|     --wd.next_site_unk136_id=wd.next_site_unk136_id+1--]] |  | ||||||
|     return nsite |  | ||||||
| end |  | ||||||
| menu:add("Create site at current location",addSite) |  | ||||||
| return _ENV |  | ||||||
| @ -1,124 +0,0 @@ | |||||||
| local _ENV = mkmodule('plugins.dfusion.embark') |  | ||||||
| local dfu=require("plugins.dfusion") |  | ||||||
| local ms=require("memscan") |  | ||||||
| local MAX_RACES=100 |  | ||||||
| CustomEmbark=defclass(CustomEmbark,dfu.BinaryPlugin) |  | ||||||
| local myos=dfhack.getOSType() |  | ||||||
| if myos=="windows" then |  | ||||||
|     CustomEmbark.ATTRS{filename="hack/lua/plugins/dfusion/embark.o",name="CustomEmbark",race_caste_data=DEFAULT_NIL} |  | ||||||
|     function CustomEmbark:parseRaces(races) |  | ||||||
|         if #races<7 then |  | ||||||
|             error("caste and race count must be bigger than 6") |  | ||||||
|         end |  | ||||||
|         if #races>MAX_RACES then |  | ||||||
|             error("caste and race count must be less then "..MAX_RACES) |  | ||||||
|         end |  | ||||||
|         local n_to_id=require("plugins.dfusion.tools").build_race_names() |  | ||||||
| 
 |  | ||||||
|         local ids={} |  | ||||||
|         for k,v in pairs(races) do |  | ||||||
|             local race=v[1] or v |  | ||||||
|             ids[k]={} |  | ||||||
|             ids[k][1]=n_to_id[race] |  | ||||||
|             if ids[k][1]==nil then qerror(race.." not found!") end |  | ||||||
|             ids[k][2]=v[2] or -1 |  | ||||||
|         end |  | ||||||
|         self.race_caste_data=ids |  | ||||||
|     end |  | ||||||
|     function CustomEmbark:install(race_caste_data) |  | ||||||
|         local stoff=dfhack.internal.getAddress('start_dwarf_count') |  | ||||||
|         if race_caste_data~=nil then |  | ||||||
|             self:parseRaces(race_caste_data) |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         if stoff==nil then |  | ||||||
|             error("address for start_dwarf_count not found!") |  | ||||||
|         end |  | ||||||
|         local _,race_id_offset=df.sizeof(df.global.ui:_field("race_id")) |  | ||||||
|         print(string.format("start=%08x",stoff)) |  | ||||||
|         local needle={0x0f,0xb7,0x0d} --movzx eax,dword ptr [race_id] |  | ||||||
|         local tmp_table=dfu.dwordToTable(race_id_offset) |  | ||||||
|         for k,v in ipairs(tmp_table) do |  | ||||||
|             table.insert(needle,v) |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         local mem=ms.get_code_segment() |  | ||||||
|         print(mem.uint8_t:addr2idx(stoff)) |  | ||||||
|         print(mem.uint8_t:find(needle,mem.uint8_t:addr2idx(stoff))) |  | ||||||
|         local _,trg_offset=mem.uint8_t:find(needle,mem.uint8_t:addr2idx(stoff),nil)--maybe endoff=stoff+bignumber |  | ||||||
|         if trg_offset==nil then |  | ||||||
|             error("address for race_load not found") |  | ||||||
|         end |  | ||||||
|         local call_data={0x90,0x90} |  | ||||||
|         local _,data_offset=df.sizeof(self.data) |  | ||||||
|         dfu.concatTables(call_data,dfu.makeCall(trg_offset+2,data_offset)) |  | ||||||
|         self.call_patch=self.call_patch or dfu.BinaryPatch{pre_data=needle,data=call_data,address=trg_offset,name="custom_embark_call_patch"} |  | ||||||
|         needle={0x83,0xc8,0xff} -- or eax, 0xFF |  | ||||||
|         local _,caste_offset=mem.uint8_t:find(needle,mem.uint8_t:addr2idx(trg_offset),nil) |  | ||||||
|         if caste_offset==nil or caste_offset-stoff>1000 then |  | ||||||
|             error("Caste change code not found or found too far!") |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         self.disable_castes=self.disable_castes or dfu.BinaryPatch{pre_data={0x83,0xc8,0xff},data={0x90,0x90,0x90},address=caste_offset,name="custom_embark_caste_disable"} |  | ||||||
|         self.disable_castes:apply() |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         self:setEmbarkParty(self.race_caste_data) |  | ||||||
|         local caste_array=self:get_or_alloc("caste_array","uint16_t",MAX_RACES) |  | ||||||
|         local race_array=self:get_or_alloc("race_array","uint16_t",MAX_RACES) |  | ||||||
| 
 |  | ||||||
|         local race_array_off,caste_array_off |  | ||||||
|         local _ |  | ||||||
|         _,race_array_off=df.sizeof(race_array) |  | ||||||
|         _,caste_array_off=df.sizeof(caste_array) |  | ||||||
|         self:set_marker_dword("race",caste_array_off) --hehe... mixed them up i guess... |  | ||||||
|         self:set_marker_dword("caste",race_array_off) |  | ||||||
| 
 |  | ||||||
|         self:move_to_df() |  | ||||||
|         self.call_patch:apply() |  | ||||||
|         self.installed=true |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     function CustomEmbark:setEmbarkParty(racesAndCastes) |  | ||||||
|         local stoff=dfhack.internal.getAddress('start_dwarf_count') |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         if self.dwarfcount== nil then |  | ||||||
|             self.dwarfcount=dfu.BinaryPatch{pre_data=dfu.dwordToTable(7),data=dfu.dwordToTable(#self.race_caste_data),address=stoff,name="custom_embark_embarkcount"} |  | ||||||
|             self.dwarfcount:apply() |  | ||||||
|         else |  | ||||||
|             self.dwarfcount:repatch(dfu.dwordToTable(#self.race_caste_data)) |  | ||||||
|         end |  | ||||||
|         local caste_array=self:get_or_alloc("caste_array","uint16_t",MAX_RACES) |  | ||||||
|         local race_array=self:get_or_alloc("race_array","uint16_t",MAX_RACES) |  | ||||||
| 
 |  | ||||||
|         for k,v in ipairs(self.race_caste_data) do |  | ||||||
|             caste_array[k-1]=v[2] or -1 |  | ||||||
|             race_array[k-1]=v[1] |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     function CustomEmbark:status() |  | ||||||
|         if self.installed then |  | ||||||
|             return "valid, installed" |  | ||||||
|         else |  | ||||||
|             return "valid, not installed" |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     function CustomEmbark:uninstall() |  | ||||||
|         if self.installed then |  | ||||||
|             self.call_patch:remove() |  | ||||||
|             self.disable_castes:remove() |  | ||||||
|             self.dwarfcount:remove() |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     function CustomEmbark:unload() |  | ||||||
|         self:uninstall() |  | ||||||
|         if Embark~=nil then |  | ||||||
|             Embark=nil |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     Embark=Embark or CustomEmbark() |  | ||||||
| else |  | ||||||
|     CustomEmbark.status=function() return"invalid, os not supported" end |  | ||||||
| end |  | ||||||
| return _ENV |  | ||||||
											
												Binary file not shown.
											
										
									
								| @ -1,121 +0,0 @@ | |||||||
| local _ENV = mkmodule('plugins.dfusion.friendship') |  | ||||||
| local dfu=require("plugins.dfusion") |  | ||||||
| local ms=require("memscan") |  | ||||||
| 
 |  | ||||||
| local MAX_RACES=100 |  | ||||||
| local MAX_CODE_DIST=250 |  | ||||||
| FriendshipRainbow=defclass(FriendshipRainbow,dfu.BinaryPlugin) |  | ||||||
| FriendshipRainbow.name="FriendshipRainbow" |  | ||||||
| -- os independant... I think... |  | ||||||
| FriendshipRainbow.ATTRS{filename="hack/lua/plugins/dfusion/friendship.o",name="FriendshipRainbow",race_data=DEFAULT_NIL} |  | ||||||
| FriendshipRainbow.class_status="valid, not installed" |  | ||||||
| function FriendshipRainbow:findall_needles(codesg,needle) -- todo move to memscan.lua |  | ||||||
|     local cidx,caddr=codesg.uint8_t:find(needle) |  | ||||||
|     local ret={} |  | ||||||
|     while cidx~=nil do |  | ||||||
|        table.insert(ret,{cidx,caddr}) |  | ||||||
|        cidx,caddr=codesg.uint8_t:find(needle,cidx+1) |  | ||||||
|     end |  | ||||||
|     return ret |  | ||||||
| end |  | ||||||
| function FriendshipRainbow:find_one(codesg,needle,crace) |  | ||||||
|     dfu.concatTables(needle,dfu.dwordToTable(crace)) |  | ||||||
|     return self:findall_needles(codesg,needle) |  | ||||||
| end |  | ||||||
| function FriendshipRainbow:find_all() |  | ||||||
|     local code=ms.get_code_segment() |  | ||||||
|     local locations={} |  | ||||||
|     local _,crace=df.sizeof(df.global.ui:_field("race_id")) |  | ||||||
| 
 |  | ||||||
|     dfu.concatTables(locations,self:find_one(code,{0x66,0xa1},crace)) --mov ax,[ptr] |  | ||||||
|     dfu.concatTables(locations,self:find_one(code,{0xa1},crace)) --mov ax,[ptr] |  | ||||||
|     local registers= |  | ||||||
|     {0x05, -- (e)ax |  | ||||||
|     0x1d, --ebx |  | ||||||
|     0x0d, --ecx |  | ||||||
|     0x15, --edx |  | ||||||
|     0x35, --esi |  | ||||||
|     0x3d, --edi |  | ||||||
|     --0x25, --esp not used? |  | ||||||
|     --0x2d, --ebp not used? |  | ||||||
|     } |  | ||||||
|     for k,reg in ipairs(registers) do |  | ||||||
| 
 |  | ||||||
|         dfu.concatTables(locations,self:find_one(code,{0x0f,0xbf,reg},crace)) --movsx reg,[ptr] |  | ||||||
|         dfu.concatTables(locations,self:find_one(code,{0x66,0x8b,reg},crace)) --mov reg,[ptr] |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     return self:filter_locations(code,locations) |  | ||||||
| end |  | ||||||
| function FriendshipRainbow:filter_locations(codesg,locations) |  | ||||||
|     local ret={} |  | ||||||
|     local registers={0x80,0x83,0x81,0x82,0x86,0x87, |  | ||||||
|                      0x98,0x9b,0x99,0x9a,0x9e,0x9f, |  | ||||||
|                      0x88,0x8b,0x89,0x8a,0x8e,0x8f, |  | ||||||
|                      0x90,0x93,0x91,0x92,0x96,0x97, |  | ||||||
|                      0xb0,0xb3,0xb1,0xb2,0xb6,0xb7, |  | ||||||
|                      0xb8,0xbb,0xb9,0xba,0xbe,0xbf} |  | ||||||
|     for _,entry in ipairs(locations) do |  | ||||||
|         for _,r in ipairs(registers) do |  | ||||||
| 
 |  | ||||||
|             local idx,addr=codesg.uint8_t:find({0x39,r,0x8c,0x00,0x00,0x00}, |  | ||||||
|                 codesg.uint8_t:addr2idx(entry[2]),codesg.uint8_t:addr2idx(entry[2])+MAX_CODE_DIST) |  | ||||||
|             if addr then |  | ||||||
|                 table.insert(ret,{addr,r}) |  | ||||||
|                 break |  | ||||||
|             end |  | ||||||
|             idx,addr=codesg.uint8_t:find({0x3b,r,0x8c,0x00,0x00,0x00}, |  | ||||||
|                 codesg.uint8_t:addr2idx(entry[2]),codesg.uint8_t:addr2idx(entry[2])+MAX_CODE_DIST) |  | ||||||
|             if addr then |  | ||||||
|                 table.insert(ret,{addr,r}) |  | ||||||
|                 break |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     return ret |  | ||||||
| end |  | ||||||
| function FriendshipRainbow:patchCalls(target) |  | ||||||
|     local addrs=self:find_all() |  | ||||||
|     local swaps={} |  | ||||||
|     for k,adr in ipairs(addrs) do |  | ||||||
|         local newval=dfu.makeCall(adr[1],target) |  | ||||||
|         table.insert(newval,adr[2]) |  | ||||||
|         for t,val in ipairs(newval) do |  | ||||||
|             swaps[adr[1]+t-1]=val |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     dfhack.internal.patchBytes(swaps) |  | ||||||
| end |  | ||||||
| function FriendshipRainbow:set_races(arr) |  | ||||||
|     local n_to_id=require("plugins.dfusion.tools").build_race_names() |  | ||||||
|     local ids={} |  | ||||||
|     for k,v in ipairs(self.race_data) do -- to check if all races are valid. |  | ||||||
|         ids[k]=n_to_id[v] |  | ||||||
|     end |  | ||||||
|     for k,v in ipairs(ids) do |  | ||||||
|         arr[k-1]=ids[k] |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| function FriendshipRainbow:install(races) |  | ||||||
|         self.race_data=races or self.race_data |  | ||||||
|         if #self.race_data<1 then |  | ||||||
|             error("race count must be bigger than 0") |  | ||||||
|         end |  | ||||||
|         if #self.race_data>MAX_RACES then |  | ||||||
|             error("race count must be less then "..MAX_RACES) |  | ||||||
|         end |  | ||||||
|         local rarr=self:allocate("race_array",'uint16_t',MAX_RACES) |  | ||||||
|         local _,rarr_offset=df.sizeof(rarr) |  | ||||||
|         self:set_marker_dword("racepointer",rarr_offset) |  | ||||||
|         self:set_races(rarr) |  | ||||||
|         self:set_marker_dword("racecount",#self.race_data) |  | ||||||
|         local safe_loc=self:allocate("safe_loc",'uint32_t',1) |  | ||||||
|         local _1,safe_loc_offset=df.sizeof(safe_loc) |  | ||||||
|         self:set_marker_dword("safeloc1",safe_loc_offset) |  | ||||||
|         self:set_marker_dword("safeloc2",safe_loc_offset) |  | ||||||
|         local addr=self:move_to_df() |  | ||||||
|         self:patchCalls(addr) |  | ||||||
|         self.installed=true |  | ||||||
| end |  | ||||||
| Friendship=Friendship or FriendshipRainbow() |  | ||||||
| return _ENV |  | ||||||
											
												Binary file not shown.
											
										
									
								| @ -1 +0,0 @@ | |||||||
| as  -anl --32 -o friendship.o friendship.asm |  | ||||||
| @ -1,7 +0,0 @@ | |||||||
| .intel_syntax |  | ||||||
| mov eax , [esp+0x1C] # loop counter |  | ||||||
| mark_caste: |  | ||||||
| movsx ecx, word ptr[eax*2+0xdeadbeef] |  | ||||||
| mark_race: |  | ||||||
| movzx eax,word ptr [eax*2+0xDEADBEEF] |  | ||||||
| ret |  | ||||||
| @ -1,106 +0,0 @@ | |||||||
| .intel_syntax |  | ||||||
| push eax |  | ||||||
| mov eax,[esp+0x04] |  | ||||||
| push ebx |  | ||||||
| pushfd |  | ||||||
| mov eax,[eax] # get a byte after the call this procedure to analyze what register holds cr ptr |  | ||||||
| jmptbl: |  | ||||||
| cmp al,0x81 |  | ||||||
| jz regC |  | ||||||
| cmp al,0x82 |  | ||||||
| jz regD |  | ||||||
| cmp al,0x83 |  | ||||||
| jz regB |  | ||||||
| cmp al,0x85 |  | ||||||
| jz regBP |  | ||||||
| cmp al,0x86 |  | ||||||
| jz regESI |  | ||||||
| cmp al,0x87 |  | ||||||
| jz regEDI |  | ||||||
| cmp al,0x88 |  | ||||||
| jz regA |  | ||||||
| cmp al,0x8A |  | ||||||
| jz regD |  | ||||||
| cmp al,0x8B |  | ||||||
| jz regB |  | ||||||
| cmp al,0x8D |  | ||||||
| jz regBP |  | ||||||
| cmp al,0x8E |  | ||||||
| jz regESI |  | ||||||
| cmp al,0x8F |  | ||||||
| jz regEDI |  | ||||||
| cmp al,0x90 |  | ||||||
| jz regA |  | ||||||
| cmp al,0x91 |  | ||||||
| jz regC |  | ||||||
| cmp al,0x93 |  | ||||||
| jz regB |  | ||||||
| cmp al,0x95 |  | ||||||
| jz regBP |  | ||||||
| cmp al,0x96 |  | ||||||
| jz regESI |  | ||||||
| cmp al,0x97 |  | ||||||
| jz regEDI |  | ||||||
| jmp fail |  | ||||||
| regA: |  | ||||||
| mov eax, [esp+0x8] |  | ||||||
| mov eax, [eax+0x8c] |  | ||||||
| jmp compare |  | ||||||
| regC: |  | ||||||
| mov eax, [ecx+0x8c] |  | ||||||
| jmp compare |  | ||||||
| regB: |  | ||||||
| mov eax, [ebx+0x8c] |  | ||||||
| jmp compare |  | ||||||
| regD: |  | ||||||
| mov eax, [edx+0x8c] |  | ||||||
| jmp compare |  | ||||||
| regBP: |  | ||||||
| mov eax, [ebp+0x8c] |  | ||||||
| jmp compare |  | ||||||
| regESI: |  | ||||||
| mov eax, [esi+0x8c] |  | ||||||
| jmp compare |  | ||||||
| regEDI: |  | ||||||
| mov eax, [edi+0x8c] |  | ||||||
| #jmp compare |  | ||||||
| compare: |  | ||||||
| push ecx |  | ||||||
| mark_racepointer: |  | ||||||
| mov ebx,0xDEADBEEF #write a pointer to the list of allowed races |  | ||||||
| mark_racecount: |  | ||||||
| mov ecx,0xDEADBEEF #write a number of allowed races |  | ||||||
| loop1: |  | ||||||
| cmp word[ebx+ecx*2],ax |  | ||||||
| jz endok |  | ||||||
| dec ecx |  | ||||||
| cmp ecx ,-1 |  | ||||||
| jnz loop1 |  | ||||||
| pop ecx |  | ||||||
| popfd |  | ||||||
| jmp fail |  | ||||||
| endok: |  | ||||||
| pop ecx |  | ||||||
| popfd |  | ||||||
| cmp eax,eax |  | ||||||
| jmp endfinal |  | ||||||
| fail: |  | ||||||
| 
 |  | ||||||
| xor ebx,ebx |  | ||||||
| xor eax,eax |  | ||||||
| inc eax |  | ||||||
| cmp eax,ebx |  | ||||||
| endfinal: |  | ||||||
| 
 |  | ||||||
| pop ebx |  | ||||||
| pop eax |  | ||||||
| mark_safeloc1: |  | ||||||
| mov [0xDEADBEEF],eax #write a pointer to safe location (usually after this) |  | ||||||
| pop eax |  | ||||||
| pushfd |  | ||||||
| inc eax #skip one instruction |  | ||||||
| popfd |  | ||||||
| push eax |  | ||||||
| mark_safeloc2: |  | ||||||
| mov eax,[0xDEADBEEF] #write a pointer to safe location (same as above) |  | ||||||
| ret |  | ||||||
| @ -1,243 +0,0 @@ | |||||||
| local _ENV = mkmodule('plugins.dfusion.tools') |  | ||||||
| local dfu=require("plugins.dfusion") |  | ||||||
| local ms=require "memscan" |  | ||||||
| menu=dfu.SimpleMenu() |  | ||||||
| RaceNames={} |  | ||||||
| function build_race_names() |  | ||||||
|     if #RaceNames~=0 then |  | ||||||
|         return RaceNames |  | ||||||
|     else |  | ||||||
|         for k,v in pairs(df.global.world.raws.creatures.all) do |  | ||||||
|             RaceNames[v.creature_id]=k |  | ||||||
|         end |  | ||||||
|         dfhack.onStateChange.invalidate_races=function(change_id) --todo does this work? |  | ||||||
|             if change_id==SC_WORLD_UNLOADED then |  | ||||||
|                 dfhack.onStateChange.invalidate_races=nil |  | ||||||
|                 RaceNames={} |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|         return RaceNames |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| function setrace(name) |  | ||||||
|     local RaceTable=build_race_names() |  | ||||||
|     print("Your current race is:"..df.global.world.raws.creatures.all[df.global.ui.race_id].creature_id) |  | ||||||
|     local id |  | ||||||
|     if name == nil then |  | ||||||
|         print("Type new race's token name in full caps (q to quit):") |  | ||||||
|         repeat |  | ||||||
|             local entry=dfhack.lineedit() |  | ||||||
|             if entry=="q" then |  | ||||||
|                 return |  | ||||||
|             end |  | ||||||
|             id=RaceTable[entry] |  | ||||||
|         until id~=nil |  | ||||||
|     else |  | ||||||
|         id=RaceTable[name] |  | ||||||
|         if id==nil then |  | ||||||
|             error("Name not found!") |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     df.global.ui.race_id=id |  | ||||||
| end |  | ||||||
| menu:add("Set current race",setrace) |  | ||||||
| function GiveSentience(names) |  | ||||||
|     local RaceTable=build_race_names() --slow.If loaded don't load again |  | ||||||
|     local id,ids |  | ||||||
|     if names ==nil then |  | ||||||
|         ids={} |  | ||||||
|         print("Type race's  token name in full caps to give sentience to:") |  | ||||||
|         repeat |  | ||||||
|             id=dfhack.lineedit() |  | ||||||
|             id=RaceTable[entry] |  | ||||||
|             if id~=nil then |  | ||||||
|                 table.insert(ids,id) |  | ||||||
|             end |  | ||||||
|         until id==nil |  | ||||||
| 
 |  | ||||||
|     else |  | ||||||
|         ids={} |  | ||||||
|         for _,name in pairs(names) do |  | ||||||
|             id=RaceTable[name] |  | ||||||
|             table.insert(ids,id) |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     for _,id in pairs(ids) do |  | ||||||
|         local races=df.global.world.raws.creatures.all |  | ||||||
| 
 |  | ||||||
|         local castes=races[id].caste |  | ||||||
|         print(string.format("Caste count:%i",#castes)) |  | ||||||
|         for i =0,#castes-1 do |  | ||||||
| 
 |  | ||||||
|             print("Caste name:"..castes[i].caste_id.."...") |  | ||||||
| 
 |  | ||||||
|             local flags=castes[i].flags |  | ||||||
|             --print(string.format("%x",flagoffset)) |  | ||||||
|             if flags.CAN_SPEAK then |  | ||||||
|                 print("\tis sentient.") |  | ||||||
|             else |  | ||||||
|                 print("\tnon sentient. Allocating IQ...") |  | ||||||
|                 flags.CAN_SPEAK=true |  | ||||||
|             end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| menu:add("Give Sentience",GiveSentience) |  | ||||||
| function MakeFollow(unit,trgunit) |  | ||||||
|     if unit == nil then |  | ||||||
|         unit=dfhack.gui.getSelectedUnit() |  | ||||||
|     end |  | ||||||
|     if unit== nil then |  | ||||||
|         error("Invalid creature") |  | ||||||
|     end |  | ||||||
|     if trgunit==nil then |  | ||||||
|         trgunit=df.global.world.units.active[0] |  | ||||||
|     end |  | ||||||
|     unit.relations.group_leader_id=trgunit.id |  | ||||||
|     local u_nem=dfhack.units.getNemesis(unit) |  | ||||||
|     local t_nem=dfhack.units.getNemesis(trgunit) |  | ||||||
|     if u_nem then |  | ||||||
|         u_nem.group_leader_id=t_nem.id |  | ||||||
|     end |  | ||||||
|     if t_nem and u_nem then |  | ||||||
|         t_nem.companions:insert(#t_nem.companions,u_nem.id) |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| menu:add("Make creature follow",MakeFollow) |  | ||||||
| function project(unit,trg) --TODO add to menu? |  | ||||||
|     if unit==nil then |  | ||||||
|         unit=getCreatureAtPointer() |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     if unit==nil then |  | ||||||
|         error("Failed to project unit. Unit not selected/valid") |  | ||||||
|     end |  | ||||||
|     -- todo: add projectile to world, point to unit, add flag to unit, add gen-ref to projectile. |  | ||||||
|     local p=df.proj_unitst:new() |  | ||||||
|     local startpos={x=unit.pos.x,y=unit.pos.y,z=unit.pos.z} |  | ||||||
|     p.origin_pos=startpos |  | ||||||
|     p.target_pos=trg |  | ||||||
|     p.cur_pos=startpos |  | ||||||
|     p.prev_pos=startpos |  | ||||||
|     p.unit=unit |  | ||||||
|     --- wtf stuff |  | ||||||
|     p.unk14=100 |  | ||||||
|     p.unk16=-1 |  | ||||||
|     p.unk23=-1 |  | ||||||
|     p.fall_delay=5 |  | ||||||
|     p.fall_counter=5 |  | ||||||
|     p.collided=true |  | ||||||
|     -- end wtf |  | ||||||
|     local citem=df.global.world.proj_list |  | ||||||
|     local maxid=1 |  | ||||||
|     local newlink=df.proj_list_link:new() |  | ||||||
|     newlink.item=p |  | ||||||
|     while citem.item~= nil do |  | ||||||
|         if citem.item.id>maxid then maxid=citem.item.id end |  | ||||||
|         if citem.next ~= nil then |  | ||||||
|             citem=citem.next |  | ||||||
|         else |  | ||||||
|             break |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
|     p.id=maxid+1 |  | ||||||
|     newlink.prev=citem |  | ||||||
|     citem.next=newlink |  | ||||||
|     local proj_ref=df.general_ref_projectile:new() |  | ||||||
|     proj_ref.projectile_id=p.id |  | ||||||
|     unit.general_refs:insert(#unit.general_refs,proj_ref) |  | ||||||
|     unit.flags1.projectile=true |  | ||||||
| end |  | ||||||
| function empregnate(unit) |  | ||||||
|     if unit==nil then |  | ||||||
|         unit=dfhack.gui.getSelectedUnit() |  | ||||||
|     end |  | ||||||
|     if unit==nil then |  | ||||||
|         error("Failed to empregnate. Unit not selected/valid") |  | ||||||
|     end |  | ||||||
|     if unit.curse then |  | ||||||
|         unit.curse.add_tags2.STERILE=false |  | ||||||
|     end |  | ||||||
|     local genes = unit.appearance.genes |  | ||||||
|     if unit.relations.pregnancy_genes == nil then |  | ||||||
|         print("creating preg ptr.") |  | ||||||
|         if false then |  | ||||||
|             print(string.format("%x %x",df.sizeof(unit.relations:_field("pregnancy_genes")))) |  | ||||||
|             return |  | ||||||
|         end |  | ||||||
|         unit.relations.pregnancy_genes = { new = true, assign = genes } |  | ||||||
|     end |  | ||||||
|     local ngenes = unit.relations.pregnancy_genes |  | ||||||
|     if #ngenes.appearance ~= #genes.appearance or #ngenes.colors ~= #genes.colors then |  | ||||||
|         print("Array sizes incorrect, fixing.") |  | ||||||
|         ngenes:assign(genes); |  | ||||||
|     end |  | ||||||
|     print("Setting preg timer.") |  | ||||||
|     unit.relations.pregnancy_timer=10 |  | ||||||
|     unit.relations.pregnancy_caste=1 |  | ||||||
| end |  | ||||||
| menu:add("Empregnate",empregnate) |  | ||||||
| function healunit(unit) |  | ||||||
|     if unit==nil then |  | ||||||
|         unit=dfhack.gui.getSelectedUnit() |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     if unit==nil then |  | ||||||
|         error("Failed to Heal unit. Unit not selected/valid") |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     unit.body.wounds:resize(0) -- memory leak here :/ |  | ||||||
|     unit.body.blood_count=unit.body.blood_max |  | ||||||
|     --set flags for standing and grasping... |  | ||||||
|     unit.status2.limbs_stand_max=4 |  | ||||||
|     unit.status2.limbs_stand_count=4 |  | ||||||
|     unit.status2.limbs_grasp_max=4 |  | ||||||
|     unit.status2.limbs_grasp_count=4 |  | ||||||
|     --should also set temperatures, and flags for breath etc... |  | ||||||
|     unit.flags1.dead=false |  | ||||||
|     unit.flags2.calculated_bodyparts=false |  | ||||||
|     unit.flags2.calculated_nerves=false |  | ||||||
|     unit.flags2.circulatory_spray=false |  | ||||||
|     unit.flags2.vision_good=true |  | ||||||
|     unit.flags2.vision_damaged=false |  | ||||||
|     unit.flags2.vision_missing=false |  | ||||||
|     unit.counters.winded=0 |  | ||||||
|     unit.counters.unconscious=0 |  | ||||||
|     for k,v in pairs(unit.body.components) do |  | ||||||
|         for kk,vv in pairs(v) do |  | ||||||
|             if k == 'body_part_status' then v[kk].whole = 0  else v[kk] = 0 end |  | ||||||
|         end |  | ||||||
|     end |  | ||||||
| end |  | ||||||
| menu:add("Heal unit",healunit) |  | ||||||
| function powerup(unit,labor_rating,military_rating,skills) |  | ||||||
|     if unit==nil then |  | ||||||
|         unit=dfhack.gui.getSelectedUnit() |  | ||||||
|     end |  | ||||||
|     if unit==nil then |  | ||||||
|         error("Failed to power up unit. Unit not selected/valid") |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     if unit.status.current_soul== nil then |  | ||||||
|         error("Failed to power up unit. Unit has no soul") |  | ||||||
|     end |  | ||||||
|     local utils = require 'utils' |  | ||||||
|     labor_rating = labor_rating or 15 |  | ||||||
|     military_rating = military_rating or 70 |  | ||||||
| 
 |  | ||||||
|     skill =skill or { 0,2,3,4,5,6,7,8,9,10,11,12,13,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,41,42,43,44,45,46,47,48,49,54,55,57,58,59,60,61,62,63,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,95,96,97,98,99,100,101,102,103,104,105,109,110,111,112,113,114,115 } |  | ||||||
|     local military = { 38,39,41,42,43,44,45,46,54,99,100,101,102,103,104,105 } |  | ||||||
| 
 |  | ||||||
|     for sk,sv in ipairs(skill) do |  | ||||||
|     local new_rating = labor_rating |  | ||||||
|     for _,v in ipairs(military) do |  | ||||||
|       if v == sv then |  | ||||||
|         local new_rating = military_rating |  | ||||||
|       end |  | ||||||
|     end |  | ||||||
|     utils.insert_or_update(unit.status.current_soul.skills, { new = true, id = sv, rating = new_rating, experience = (new_rating * 500) + (new_rating * (new_rating - 1)) * 50}, 'id') |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
| end |  | ||||||
| menu:add("Power up",powerup) |  | ||||||
| return _ENV |  | ||||||
| @ -1 +0,0 @@ | |||||||
| proto/*.pb.* |  | ||||||
| @ -1,43 +0,0 @@ | |||||||
| PROJECT(mapexport) |  | ||||||
| 
 |  | ||||||
| # add *our* headers here. |  | ||||||
| SET(PROJECT_HDRS |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| SET(PROJECT_SRCS |  | ||||||
| mapexport.cpp |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| SET(PROJECT_PROTOS |  | ||||||
| ${CMAKE_CURRENT_SOURCE_DIR}/proto/Tile.proto |  | ||||||
| ${CMAKE_CURRENT_SOURCE_DIR}/proto/Plant.proto |  | ||||||
| ${CMAKE_CURRENT_SOURCE_DIR}/proto/Block.proto |  | ||||||
| ${CMAKE_CURRENT_SOURCE_DIR}/proto/Material.proto |  | ||||||
| ${CMAKE_CURRENT_SOURCE_DIR}/proto/Map.proto |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| #Create new lists of what sources and headers protoc will output after we invoke it |  | ||||||
| STRING(REPLACE ".proto" ".pb.cc;" PROJECT_PROTO_SRCS ${PROJECT_PROTOS}) |  | ||||||
| STRING(REPLACE ".proto" ".pb.h;" PROJECT_PROTO_HDRS ${PROJECT_PROTOS}) |  | ||||||
| 
 |  | ||||||
| SET_SOURCE_FILES_PROPERTIES( ${PROJECT_PROTO_HDRS} PROPERTIES GENERATED TRUE) |  | ||||||
| SET_SOURCE_FILES_PROPERTIES( ${PROJECT_PROTO_SRCS} PROPERTIES GENERATED TRUE) |  | ||||||
| 
 |  | ||||||
| LIST(APPEND PROJECT_HDRS ${PROJECT_PROTO_HDRS}) |  | ||||||
| LIST(APPEND PROJECT_SRCS ${PROJECT_PROTO_SRCS}) |  | ||||||
| 
 |  | ||||||
| SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE) |  | ||||||
| LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS}) |  | ||||||
| 
 |  | ||||||
| #Generate sources from our proto files and store them in the source tree |  | ||||||
| ADD_CUSTOM_COMMAND( |  | ||||||
| OUTPUT ${PROJECT_PROTO_SRCS} ${PROJECT_PROTO_HDRS} |  | ||||||
| COMMAND protoc-bin -I=${CMAKE_CURRENT_SOURCE_DIR}/proto/ --cpp_out=${CMAKE_CURRENT_SOURCE_DIR}/proto/ ${PROJECT_PROTOS} |  | ||||||
| DEPENDS protoc-bin ${PROJECT_PROTOS} |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| IF(WIN32) |  | ||||||
|     DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf-lite) |  | ||||||
| ELSE() |  | ||||||
|     DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf-lite) |  | ||||||
| ENDIF() |  | ||||||
| @ -1,325 +0,0 @@ | |||||||
| #include "Core.h" |  | ||||||
| #include "Console.h" |  | ||||||
| #include "Export.h" |  | ||||||
| #include "PluginManager.h" |  | ||||||
| #include "modules/MapCache.h" |  | ||||||
| using namespace DFHack; |  | ||||||
| 
 |  | ||||||
| #include <fstream> |  | ||||||
| #include <google/protobuf/io/coded_stream.h> |  | ||||||
| #include <google/protobuf/io/zero_copy_stream_impl.h> |  | ||||||
| #include <google/protobuf/io/gzip_stream.h> |  | ||||||
| using namespace google::protobuf::io; |  | ||||||
| 
 |  | ||||||
| #include "DataDefs.h" |  | ||||||
| #include "df/world.h" |  | ||||||
| #include "df/plant.h" |  | ||||||
| #include "modules/Constructions.h" |  | ||||||
| 
 |  | ||||||
| #include "proto/Map.pb.h" |  | ||||||
| #include "proto/Block.pb.h" |  | ||||||
| 
 |  | ||||||
| using namespace DFHack; |  | ||||||
| using df::global::world; |  | ||||||
| /*
 |  | ||||||
| mapexport |  | ||||||
| ========= |  | ||||||
| Export the current loaded map as a file. This was used by visualizers for |  | ||||||
| DF 0.34.11, but is now basically obsolete. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| typedef std::vector<df::plant *> PlantList; |  | ||||||
| 
 |  | ||||||
| command_result mapexport (color_ostream &out, std::vector <std::string> & parameters); |  | ||||||
| 
 |  | ||||||
| DFHACK_PLUGIN("mapexport"); |  | ||||||
| 
 |  | ||||||
| DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) |  | ||||||
| { |  | ||||||
|     GOOGLE_PROTOBUF_VERIFY_VERSION; |  | ||||||
|     commands.push_back(PluginCommand("mapexport", "Exports the current map to a file.", mapexport, true)); |  | ||||||
|     return CR_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| DFhackCExport command_result plugin_shutdown ( color_ostream &out ) |  | ||||||
| { |  | ||||||
|     return CR_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static dfproto::Tile::TileMaterialType toProto(df::tiletype_material mat) |  | ||||||
| { |  | ||||||
|     /*
 |  | ||||||
|      * This is surely ugly, but casting enums without officially |  | ||||||
|      * defined numerical values to protobuf enums is against the |  | ||||||
|      * way protobufs are supposed to be used, because it defeats |  | ||||||
|      * the backward compatible nature of the protocols. |  | ||||||
|      */ |  | ||||||
|     switch (mat) |  | ||||||
|     { |  | ||||||
| #define CONVERT(name) case tiletype_material::name: return dfproto::Tile::name; |  | ||||||
|         case tiletype_material::NONE: |  | ||||||
|         CONVERT(AIR) |  | ||||||
|         case tiletype_material::PLANT: |  | ||||||
|         CONVERT(SOIL) |  | ||||||
|         CONVERT(STONE) |  | ||||||
|         CONVERT(FEATURE) |  | ||||||
|         CONVERT(LAVA_STONE) |  | ||||||
|         CONVERT(MINERAL) |  | ||||||
|         CONVERT(FROZEN_LIQUID) |  | ||||||
|         CONVERT(CONSTRUCTION) |  | ||||||
|         CONVERT(GRASS_LIGHT) |  | ||||||
|         CONVERT(GRASS_DARK) |  | ||||||
|         CONVERT(GRASS_DRY) |  | ||||||
|         CONVERT(GRASS_DEAD) |  | ||||||
|         CONVERT(HFS) |  | ||||||
|         CONVERT(CAMPFIRE) |  | ||||||
|         CONVERT(FIRE) |  | ||||||
|         CONVERT(ASHES) |  | ||||||
|         case tiletype_material::MAGMA: |  | ||||||
|             return dfproto::Tile::MAGMA_TYPE; |  | ||||||
|         CONVERT(DRIFTWOOD) |  | ||||||
|         CONVERT(POOL) |  | ||||||
|         CONVERT(BROOK) |  | ||||||
|         CONVERT(RIVER) |  | ||||||
| #undef CONVERT |  | ||||||
|     } |  | ||||||
|     return dfproto::Tile::AIR; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| command_result mapexport (color_ostream &out, std::vector <std::string> & parameters) |  | ||||||
| { |  | ||||||
|     bool showHidden = false; |  | ||||||
| 
 |  | ||||||
|     int filenameParameter = 1; |  | ||||||
| 
 |  | ||||||
|     for(size_t i = 0; i < parameters.size();i++) |  | ||||||
|     { |  | ||||||
|         if(parameters[i] == "help" || parameters[i] == "?") |  | ||||||
|         { |  | ||||||
|             out.print("Exports the currently visible map to a file.\n" |  | ||||||
|                          "Usage: mapexport [options] <filename>\n" |  | ||||||
|                          "Example: mapexport all embark.dfmap\n" |  | ||||||
|                          "Options:\n" |  | ||||||
|                          "   all   - Export the entire map, not just what's revealed.\n" |  | ||||||
|             ); |  | ||||||
|             return CR_OK; |  | ||||||
|         } |  | ||||||
|         if (parameters[i] == "all") |  | ||||||
|         { |  | ||||||
|             showHidden = true; |  | ||||||
|             filenameParameter++; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     CoreSuspender suspend; |  | ||||||
| 
 |  | ||||||
|     uint32_t x_max=0, y_max=0, z_max=0; |  | ||||||
| 
 |  | ||||||
|     if (!Maps::IsValid()) |  | ||||||
|     { |  | ||||||
|         out.printerr("Map is not available!\n"); |  | ||||||
|         return CR_FAILURE; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (parameters.size() < filenameParameter) |  | ||||||
|     { |  | ||||||
|         out.printerr("Please supply a filename.\n"); |  | ||||||
|         return CR_FAILURE; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     std::string filename = parameters[filenameParameter-1]; |  | ||||||
|     if (filename.rfind(".dfmap") == std::string::npos) filename += ".dfmap"; |  | ||||||
|     out << "Writing to " << filename << "..." << std::endl; |  | ||||||
| 
 |  | ||||||
|     std::ofstream output_file(filename.c_str(), std::ios::out | std::ios::trunc | std::ios::binary); |  | ||||||
|     if (!output_file.is_open()) |  | ||||||
|     { |  | ||||||
|         out.printerr("Couldn't open the output file.\n"); |  | ||||||
|         return CR_FAILURE; |  | ||||||
|     } |  | ||||||
|     ZeroCopyOutputStream *raw_output = new OstreamOutputStream(&output_file); |  | ||||||
|     GzipOutputStream *zip_output = new GzipOutputStream(raw_output); |  | ||||||
|     CodedOutputStream *coded_output = new CodedOutputStream(zip_output); |  | ||||||
| 
 |  | ||||||
|     coded_output->WriteLittleEndian32(0x50414DDF); //Write our file header
 |  | ||||||
| 
 |  | ||||||
|     Maps::getSize(x_max, y_max, z_max); |  | ||||||
|     MapExtras::MapCache map; |  | ||||||
|     DFHack::Materials *mats = Core::getInstance().getMaterials(); |  | ||||||
| 
 |  | ||||||
|     out << "Writing  map info..." << std::endl; |  | ||||||
| 
 |  | ||||||
|     dfproto::Map protomap; |  | ||||||
|     protomap.set_x_size(x_max); |  | ||||||
|     protomap.set_y_size(y_max); |  | ||||||
|     protomap.set_z_size(z_max); |  | ||||||
| 
 |  | ||||||
|     out << "Writing material dictionary..." << std::endl; |  | ||||||
| 
 |  | ||||||
|     for (size_t i = 0; i < world->raws.inorganics.size(); i++) |  | ||||||
|     { |  | ||||||
|         dfproto::Material *protomaterial = protomap.add_inorganic_material(); |  | ||||||
|         protomaterial->set_index(i); |  | ||||||
|         protomaterial->set_name(world->raws.inorganics[i]->id); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     for (size_t i = 0; i < world->raws.plants.all.size(); i++) |  | ||||||
|     { |  | ||||||
|         dfproto::Material *protomaterial = protomap.add_organic_material(); |  | ||||||
|         protomaterial->set_index(i); |  | ||||||
|         protomaterial->set_name(world->raws.plants.all[i]->id); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     std::map<df::coord,std::pair<uint32_t,uint16_t> > constructionMaterials; |  | ||||||
|     if (Constructions::isValid()) |  | ||||||
|     { |  | ||||||
|         for (uint32_t i = 0; i < Constructions::getCount(); i++) |  | ||||||
|         { |  | ||||||
|             df::construction *construction = Constructions::getConstruction(i); |  | ||||||
|             constructionMaterials[construction->pos] = std::make_pair(construction->mat_index, construction->mat_type); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     coded_output->WriteVarint32(protomap.ByteSize()); |  | ||||||
|     protomap.SerializeToCodedStream(coded_output); |  | ||||||
| 
 |  | ||||||
|     DFHack::t_feature blockFeatureGlobal; |  | ||||||
|     DFHack::t_feature blockFeatureLocal; |  | ||||||
| 
 |  | ||||||
|     out.print("Writing map block information"); |  | ||||||
| 
 |  | ||||||
|     for(uint32_t z = 0; z < z_max; z++) |  | ||||||
|     { |  | ||||||
|         for(uint32_t b_y = 0; b_y < y_max; b_y++) |  | ||||||
|         { |  | ||||||
|             for(uint32_t b_x = 0; b_x < x_max; b_x++) |  | ||||||
|             { |  | ||||||
|                 if (b_x == 0 && b_y == 0 && z % 10 == 0) out.print("."); |  | ||||||
|                 // Get the map block
 |  | ||||||
|                 df::coord2d blockCoord(b_x, b_y); |  | ||||||
|                 MapExtras::Block *b = map.BlockAt(DFHack::DFCoord(b_x, b_y, z)); |  | ||||||
|                 if (!b || !b->is_valid()) |  | ||||||
|                 { |  | ||||||
|                     continue; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 dfproto::Block protoblock; |  | ||||||
|                 protoblock.set_x(b_x); |  | ||||||
|                 protoblock.set_y(b_y); |  | ||||||
|                 protoblock.set_z(z); |  | ||||||
| 
 |  | ||||||
|                 // Find features
 |  | ||||||
|                 b->GetGlobalFeature(&blockFeatureGlobal); |  | ||||||
|                 b->GetLocalFeature(&blockFeatureLocal); |  | ||||||
| 
 |  | ||||||
|                 int global_z = df::global::world->map.region_z + z; |  | ||||||
| 
 |  | ||||||
|                 // Iterate over all the tiles in the block
 |  | ||||||
|                 for(uint32_t y = 0; y < 16; y++) |  | ||||||
|                 { |  | ||||||
|                     for(uint32_t x = 0; x < 16; x++) |  | ||||||
|                     { |  | ||||||
|                         df::coord2d coord(x, y); |  | ||||||
|                         df::tile_designation des = b->DesignationAt(coord); |  | ||||||
|                         df::tile_occupancy occ = b->OccupancyAt(coord); |  | ||||||
| 
 |  | ||||||
|                         // Skip hidden tiles
 |  | ||||||
|                         if (!showHidden && des.bits.hidden) |  | ||||||
|                         { |  | ||||||
|                             continue; |  | ||||||
|                         } |  | ||||||
| 
 |  | ||||||
|                         dfproto::Tile *prototile = protoblock.add_tile(); |  | ||||||
|                         prototile->set_x(x); |  | ||||||
|                         prototile->set_y(y); |  | ||||||
| 
 |  | ||||||
|                         // Check for liquid
 |  | ||||||
|                         if (des.bits.flow_size) |  | ||||||
|                         { |  | ||||||
|                             prototile->set_liquid_type((dfproto::Tile::LiquidType)des.bits.liquid_type); |  | ||||||
|                             prototile->set_flow_size(des.bits.flow_size); |  | ||||||
|                         } |  | ||||||
| 
 |  | ||||||
|                         df::tiletype type = b->tiletypeAt(coord); |  | ||||||
|                         prototile->set_type((dfproto::Tile::TileType)tileShape(type)); |  | ||||||
|                         prototile->set_tile_material(toProto(tileMaterial(type))); |  | ||||||
| 
 |  | ||||||
|                         df::coord map_pos = df::coord(b_x*16+x,b_y*16+y,z); |  | ||||||
| 
 |  | ||||||
|                         switch (tileMaterial(type)) |  | ||||||
|                         { |  | ||||||
|                         case tiletype_material::SOIL: |  | ||||||
|                         case tiletype_material::STONE: |  | ||||||
|                             prototile->set_material_type(0); |  | ||||||
|                             prototile->set_material_index(b->layerMaterialAt(coord)); |  | ||||||
|                             break; |  | ||||||
|                         case tiletype_material::MINERAL: |  | ||||||
|                             prototile->set_material_type(0); |  | ||||||
|                             prototile->set_material_index(b->veinMaterialAt(coord)); |  | ||||||
|                             break; |  | ||||||
|                         case tiletype_material::FEATURE: |  | ||||||
|                             if (blockFeatureLocal.type != -1 && des.bits.feature_local) |  | ||||||
|                             { |  | ||||||
|                                 if (blockFeatureLocal.type == feature_type::deep_special_tube |  | ||||||
|                                         && blockFeatureLocal.main_material == 0) // stone
 |  | ||||||
|                                 { |  | ||||||
|                                     prototile->set_material_type(0); |  | ||||||
|                                     prototile->set_material_index(blockFeatureLocal.sub_material); |  | ||||||
|                                 } |  | ||||||
|                                 if (blockFeatureGlobal.type != -1 && des.bits.feature_global |  | ||||||
|                                         && blockFeatureGlobal.type == feature_type::feature_underworld_from_layer |  | ||||||
|                                         && blockFeatureGlobal.main_material == 0) // stone
 |  | ||||||
|                                 { |  | ||||||
|                                     prototile->set_material_type(0); |  | ||||||
|                                     prototile->set_material_index(blockFeatureGlobal.sub_material); |  | ||||||
|                                 } |  | ||||||
|                             } |  | ||||||
|                             break; |  | ||||||
|                         case tiletype_material::CONSTRUCTION: |  | ||||||
|                             if (constructionMaterials.find(map_pos) != constructionMaterials.end()) |  | ||||||
|                             { |  | ||||||
|                                 prototile->set_material_index(constructionMaterials[map_pos].first); |  | ||||||
|                                 prototile->set_material_type(constructionMaterials[map_pos].second); |  | ||||||
|                             } |  | ||||||
|                             break; |  | ||||||
|                         default: |  | ||||||
|                             break; |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 if (b->getRaw()) |  | ||||||
|                 { |  | ||||||
|                     PlantList *plants = &b->getRaw()->plants; |  | ||||||
|                     for (PlantList::const_iterator it = plants->begin(); it != plants->end(); it++) |  | ||||||
|                     { |  | ||||||
|                         const df::plant & plant = *(*it); |  | ||||||
|                         df::coord2d loc(plant.pos.x, plant.pos.y); |  | ||||||
|                         loc = loc % 16; |  | ||||||
|                         if (showHidden || !b->DesignationAt(loc).bits.hidden) |  | ||||||
|                         { |  | ||||||
|                             dfproto::Plant *protoplant = protoblock.add_plant(); |  | ||||||
|                             protoplant->set_x(loc.x); |  | ||||||
|                             protoplant->set_y(loc.y); |  | ||||||
|                             protoplant->set_is_shrub(plant.flags.bits.is_shrub); |  | ||||||
|                             protoplant->set_material(plant.material); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 coded_output->WriteVarint32(protoblock.ByteSize()); |  | ||||||
|                 protoblock.SerializeToCodedStream(coded_output); |  | ||||||
|             } // block x
 |  | ||||||
|             // Clean uneeded memory
 |  | ||||||
|             map.trash(); |  | ||||||
|         } // block y
 |  | ||||||
|     } // z
 |  | ||||||
| 
 |  | ||||||
|     delete coded_output; |  | ||||||
|     delete zip_output; |  | ||||||
|     delete raw_output; |  | ||||||
| 
 |  | ||||||
|     mats->Finish(); |  | ||||||
|     out.print("\nMap succesfully exported!\n"); |  | ||||||
|     return CR_OK; |  | ||||||
| } |  | ||||||
| @ -1,14 +0,0 @@ | |||||||
| package dfproto; |  | ||||||
| option optimize_for = LITE_RUNTIME; |  | ||||||
| 
 |  | ||||||
| import "Tile.proto"; |  | ||||||
| import "Plant.proto"; |  | ||||||
| 
 |  | ||||||
| message Block |  | ||||||
| { |  | ||||||
|     required uint32 x = 1; |  | ||||||
|     required uint32 y = 2; |  | ||||||
|     required uint32 z = 3; |  | ||||||
|     repeated Tile tile = 4; |  | ||||||
|     repeated Plant plant = 5; |  | ||||||
| } |  | ||||||
| @ -1,13 +0,0 @@ | |||||||
| package dfproto; |  | ||||||
| option optimize_for = LITE_RUNTIME; |  | ||||||
| 
 |  | ||||||
| import "Material.proto"; |  | ||||||
| 
 |  | ||||||
| message Map |  | ||||||
| { |  | ||||||
|     required uint32 x_size = 1; |  | ||||||
|     required uint32 y_size = 2; |  | ||||||
|     required uint32 z_size = 3; |  | ||||||
|     repeated Material inorganic_material = 4; |  | ||||||
|     repeated Material organic_material = 5; |  | ||||||
| } |  | ||||||
| @ -1,8 +0,0 @@ | |||||||
| package dfproto; |  | ||||||
| option optimize_for = LITE_RUNTIME; |  | ||||||
| 
 |  | ||||||
| message Material |  | ||||||
| { |  | ||||||
|     required uint32 index= 1; |  | ||||||
|     required string name = 2; |  | ||||||
| } |  | ||||||
| @ -1,10 +0,0 @@ | |||||||
| package dfproto; |  | ||||||
| option optimize_for = LITE_RUNTIME; |  | ||||||
| 
 |  | ||||||
| message Plant |  | ||||||
| { |  | ||||||
|     required uint32 x = 1; |  | ||||||
|     required uint32 y = 2; |  | ||||||
|     required bool is_shrub = 3; |  | ||||||
|     optional uint32 material = 4; |  | ||||||
| } |  | ||||||
| @ -1,63 +0,0 @@ | |||||||
| package dfproto; |  | ||||||
| option optimize_for = LITE_RUNTIME; |  | ||||||
| 
 |  | ||||||
| message Tile |  | ||||||
| { |  | ||||||
|     enum TileType |  | ||||||
|     { |  | ||||||
|         EMPTY = 0; |  | ||||||
|         FLOOR = 1; |  | ||||||
|         BOULDER = 2; |  | ||||||
|         PEBBLES = 3; |  | ||||||
|         WALL = 4; |  | ||||||
|         FORTIFICATION = 5; |  | ||||||
|         STAIR_UP = 6; |  | ||||||
|         STAIR_DOWN = 7; |  | ||||||
|         STAIR_UPDOWN = 8; |  | ||||||
|         RAMP = 9; |  | ||||||
|         RAMP_TOP = 10; |  | ||||||
|         BROOK_BED = 11; |  | ||||||
|         BROOK_TOP = 12; |  | ||||||
|         TREE = 13; |  | ||||||
|         SAPLING = 14; |  | ||||||
|         SHRUB = 15; |  | ||||||
|         ENDLESS_PIT = 16; |  | ||||||
|     } |  | ||||||
|     enum LiquidType |  | ||||||
|     { |  | ||||||
|         WATER = 0; |  | ||||||
|         MAGMA = 1; |  | ||||||
|     } |  | ||||||
|     enum TileMaterialType |  | ||||||
|     { |  | ||||||
|         AIR = 0; |  | ||||||
|         SOIL = 1; |  | ||||||
|         STONE = 2; |  | ||||||
|         FEATURE = 3; |  | ||||||
|         LAVA_STONE = 4; |  | ||||||
|         MINERAL = 5; |  | ||||||
|         FROZEN_LIQUID = 6; |  | ||||||
|         CONSTRUCTION = 7; |  | ||||||
|         GRASS_LIGHT = 8; |  | ||||||
|         GRASS_DARK = 9; |  | ||||||
|         GRASS_DRY = 10; |  | ||||||
|         GRASS_DEAD = 11; |  | ||||||
|         HFS = 12; |  | ||||||
|         CAMPFIRE = 13; |  | ||||||
|         FIRE = 14; |  | ||||||
|         ASHES = 15; |  | ||||||
|         MAGMA_TYPE = 16; |  | ||||||
|         DRIFTWOOD = 17; |  | ||||||
|         POOL = 18; |  | ||||||
|         BROOK = 19; |  | ||||||
|         RIVER = 20; |  | ||||||
|     } |  | ||||||
|     required uint32 x = 1; |  | ||||||
|     required uint32 y = 2; |  | ||||||
|     required TileType type = 3; |  | ||||||
|     optional TileMaterialType tile_material = 4; |  | ||||||
|     optional uint32 material_index = 5; |  | ||||||
|     optional uint32 material_type = 6; |  | ||||||
|     optional LiquidType liquid_type = 7; |  | ||||||
|     optional uint32 flow_size = 8; |  | ||||||
| } |  | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue