diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a5ceb74a..de404432e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,10 +27,10 @@ endif() # set up versioning. set(DF_VERSION_MAJOR "0") set(DF_VERSION_MINOR "34") -set(DF_VERSION_PATCH "04") +set(DF_VERSION_PATCH "05") set(DF_VERSION "${DF_VERSION_MAJOR}.${DF_VERSION_MINOR}.${DF_VERSION_PATCH}") -set(DFHACK_RELEASE "1") +set(DFHACK_RELEASE "1d") set(DFHACK_VERSION "${DF_VERSION_MAJOR}.${DF_VERSION_MINOR}.${DF_VERSION_PATCH}-r${DFHACK_RELEASE}") add_definitions(-DDFHACK_VERSION="${DFHACK_VERSION}") @@ -78,8 +78,21 @@ IF(UNIX) SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32 -march=i686 -mtune=generic") ENDIF() +# find and make available libz +if(NOT UNIX) + SET(ZLIB_INCLUDE_DIRS ${dfhack_SOURCE_DIR}/library/depends/zlib/include/) + SET(ZLIB_LIBRARIES ${dfhack_SOURCE_DIR}/library/depends/zlib/lib/zlib.lib) +else() + find_package(ZLIB REQUIRED) +endif() +include_directories(${ZLIB_INCLUDE_DIRS}) + #add depends to include path INCLUDE_DIRECTORIES ( library/depends ) +INCLUDE_DIRECTORIES ( library/depends/protobuf/ ) + +# use shared libraries for protobuf +ADD_DEFINITIONS(-DPROTOBUF_USE_DLLS) # build the static lua for dfusion INCLUDE_DIRECTORIES ( lua/include ) diff --git a/README.rst b/README.rst index d1dcc2d21..09c840b27 100644 --- a/README.rst +++ b/README.rst @@ -27,7 +27,7 @@ Compatibility DFHack works on Windows XP, Vista, 7 or any modern Linux distribution. OSX is not supported due to lack of developers with a Mac. -Currently, only version 0.31.25 is supported. If you need DFHack +Currently, only version 0.34.05 is supported. If you need DFHack for older versions, look for older releases. On Windows, you have to use the SDL version of DF. @@ -441,6 +441,8 @@ reveal ====== This reveals the map. By default, HFS will remain hidden so that the demons don't spawn. You can use 'reveal hell' to reveal everything. With hell revealed, you won't be able to unpause until you hide the map again. If you really want to unpause with hell revealed, use 'reveal demons'. +Reveal also works in adventure mode, but any of its effects are negated once you move. When you use it this way, you don't need to run 'unreveal'. + unreveal ======== Reverts the effects of 'reveal'. @@ -489,6 +491,14 @@ You can also paint only over tiles that match a set of properties (filter) For more details, see the 'help' command while using this. +tweak +===== +Contains various tweaks for minor bugs (currently just one). + +Options +------- +:tweak clear-missing: Remove the missing status from the selected unit. This allows engraving slabs for ghostly, but not yet found, creatures. + tubefill ======== Fills all the adamantine veins again. Veins that were empty will be filled in too, but might still trigger a demon invasion (this is a known bug). @@ -662,4 +672,4 @@ Export the current loaded map as a file. This will be eventually usable with vis dwarfexport =========== -Export dwarves to RuneSmith-compatible XML. \ No newline at end of file +Export dwarves to RuneSmith-compatible XML. diff --git a/Readme.html b/Readme.html index 41040b2de..2e7b225a7 100644 --- a/Readme.html +++ b/Readme.html @@ -318,7 +318,7 @@ ul.auto-toc {
-

Introduction

+

Introduction

DFHack is a Dwarf Fortress memory access library and a set of basic tools that use it. Tools come in the form of plugins or (not yet) external tools. It is an attempt to unite the various ways tools @@ -326,165 +326,169 @@ access DF memory and allow for easier development of new tools.

Contents

-

Getting DFHack

+

Getting DFHack

The project is currently hosted on github, for both source and binaries at http://github.com/peterix/dfhack

Releases can be downloaded from here: https://github.com/peterix/dfhack/downloads

All new releases are announced in the bay12 thread: http://tinyurl.com/dfhack-ng

-

Compatibility

+

Compatibility

DFHack works on Windows XP, Vista, 7 or any modern Linux distribution. OSX is not supported due to lack of developers with a Mac.

-

Currently, only version 0.31.25 is supported. If you need DFHack +

Currently, only version 0.34.05 is supported. If you need DFHack for older versions, look for older releases.

On Windows, you have to use the SDL version of DF.

It is possible to use the Windows DFHack under wine/OSX.

-

Installation/Removal

+

Installation/Removal

Installing DFhack involves copying files into your DF folder. Copy the files from a release archive so that:

@@ -504,7 +508,7 @@ Copy the files from a release archive so that:

If any of the plugins or dfhack itself refuses to load, check the stderr.log file created in your DF folder.

-

Using DFHack

+

Using DFHack

DFHack basically extends what DF can do with something similar to the drop-down console found in Quake engine games. On Windows, this is a separate command line window. On linux, the terminal used to launch the dfhack script is taken over (so, make sure you start from a terminal). Basic interaction with dfhack involves entering commands into the console. For some basic instroduction, use the 'help' command. To list all possible commands, use the 'ls' command. Many commands have their own help or detailed description. You can use 'command help' or 'command ?' to show that.

@@ -515,22 +519,22 @@ Many commands have their own help or detailed description. You can use 'command

Most of the commands come from plugins. Those reside in 'hack/plugins/'.

-

Something doesn't work, help!

+

Something doesn't work, help!

First, don't panic :) Second, dfhack keeps a few log files in DF's folder - stderr.log and stdout.log. You can look at those and possibly find out what's happening. If you found a bug, you can either report it in the bay12 DFHack thread, the issues tracker on github, contact me (peterix@gmail.com) or visit the #dfhack IRC channel on freenode.

-

The init file

+

The init file

If your DF folder contains a file named dfhack.init, its contents will be run every time you start DF. This allows setting up keybindings. An example file is provided as dfhack.init-example - you can tweak it and rename to dfhack.init if you want to use this functionality.

-

Commands

+

Commands

Almost all the commands support using the 'help <command-name>' built-in command to retrieve further help without having to look at this document. Alternatively, some accept a 'help'/'?' option on their command line.

-

adv-bodyswap

+

adv-bodyswap

This allows taking control over your followers and other creatures in adventure mode. For example, you can make them pick up new arms and armor and equip them properly.

-

Usage

+

Usage

  • When viewing unit details, body-swaps into that unit.
  • @@ -540,10 +544,10 @@ If you found a bug, you can either report it in the bay12 DFHack thread, the iss
-

advtools

+

advtools

A package of different adventure mode tools (currently just one)

-

Usage

+

Usage

@@ -556,15 +560,15 @@ If you found a bug, you can either report it in the bay12 DFHack thread, the iss
-

changevein

+

changevein

Changes material of the vein under cursor to the specified inorganic RAW material.

-

follow

+

follow

Makes the game view follow the currently highlighted unit after you exit from current menu/cursor mode. Handy for watching dwarves running around. Deactivated by moving the view manually.

-

forcepause

+

forcepause

Forces DF to pause. This is useful when your FPS drops below 1 and you lose control of the game.

    @@ -574,23 +578,23 @@ If you found a bug, you can either report it in the bay12 DFHack thread, the iss
-

nopause

+

nopause

Disables pausing (both manual and automatic) with the exception of pause forced by 'reveal hell'. This is nice for digging under rivers.

-

die

+

die

Instantly kills DF without saving.

-

autodump

+

autodump

This utility lets you quickly move all items designated to be dumped. Items are instantly moved to the cursor position, the dump flag is unset, and the forbid flag is set, as if it had been dumped normally. Be aware that any active dump item tasks still point at the item.

Cursor must be placed on a floor tile so the items can be dumped there.

@@ -610,20 +614,20 @@ Be aware that any active dump item tasks still point at the item.

-

autodump-destroy-here

+

autodump-destroy-here

Destroy items marked for dumping under cursor. Identical to autodump destroy-here, but intended for use as keybinding.

-

autodump-destroy-item

+

autodump-destroy-item

Destroy the selected item. The item may be selected in the 'k' list, or inside a container. If called again before the game is resumed, cancels destroy.

-

clean

+

clean

Cleans all the splatter that get scattered all over the map, items and creatures. In an old fortress, this can significantly reduce FPS lag. It can also spoil your !!FUN!!, so think before you use it.

@@ -638,7 +642,7 @@ In an old fortress, this can significantly reduce FPS lag. It can also spoil you
-

Extra options for 'map'

+

Extra options for 'map'

@@ -652,15 +656,15 @@ In an old fortress, this can significantly reduce FPS lag. It can also spoil you
-

spotclean

+

spotclean

Works like 'clean map snow mud', but only for the tile under the cursor. Ideal if you want to keep that bloody entrance 'clean map' would clean up.

-

cleanowned

+

cleanowned

Confiscates items owned by dwarfs. By default, owned food on the floor and rotten items are confistacted and dumped.

@@ -679,15 +683,15 @@ By default, owned food on the floor and rotten items are confistacted and dumped
-

Example:

+

Example:

cleanowned scattered X : This will confiscate rotten and dropped food, garbage on the floors and any worn items with 'X' damage and above.

-

colonies

+

colonies

Allows listing all the vermin colonies on the map and optionally turning them into honey bee colonies.

-

Options

+

Options

@@ -699,12 +703,12 @@ By default, owned food on the floor and rotten items are confistacted and dumped
-

deramp (by zilpin)

+

deramp (by zilpin)

Removes all ramps designated for removal from the map. This is useful for replicating the old channel digging designation. It also removes any and all 'down ramps' that can remain after a cave-in (you don't have to designate anything for that to happen).

-

df2minecraft

+

df2minecraft

This generates a minecraft world out of the currently loaded fortress. Generated worlds are placed into your DF folder, named "World #".

@@ -718,11 +722,11 @@ Generated worlds are placed into your DF folder, named "World #".

-

dfusion

+

dfusion

This is the DFusion lua plugin system by warmist/darius, running as a DFHack plugin.

See the bay12 thread for details: http://www.bay12forums.com/smf/index.php?topic=69682.15

@@ -742,11 +746,11 @@ Generated worlds are placed into your DF folder, named "World #".

-

drybuckets

+

drybuckets

This utility removes water from all buckets in your fortress, allowing them to be safely used for making lye.

-

fastdwarf

+

fastdwarf

Makes your minions move at ludicrous speeds.

    @@ -756,10 +760,10 @@ Generated worlds are placed into your DF folder, named "World #".

-

filltraffic

+

filltraffic

Set traffic designations using flood-fill starting at the cursor.

@@ -776,7 +780,7 @@ Generated worlds are placed into your DF folder, named "World #".

-

Other Options:

+

Other Options:

@@ -791,15 +795,15 @@ Generated worlds are placed into your DF folder, named "World #".

-

Example:

+

Example:

'filltraffic H' - When used in a room with doors, it will set traffic to HIGH in just that room.

-

alltraffic

+

alltraffic

Set traffic designations for every single tile of the map (useful for resetting traffic designations).

-

Traffic Type Codes:

+

Traffic Type Codes:

@@ -816,35 +820,35 @@ Generated worlds are placed into your DF folder, named "World #".

-

Example:

+

Example:

'alltraffic N' - Set traffic to 'normal' for all tiles.

-

fixdiplomats

+

fixdiplomats

Up to version 0.31.12, Elves only sent Diplomats to your fortress to propose tree cutting quotas due to a bug; once that bug was fixed, Elves stopped caring about excess tree cutting. This command adds a Diplomat position to all Elven civilizations, allowing them to negotiate tree cutting quotas (and allowing you to violate them and potentially start wars) in case you haven't already modified your raws accordingly.

-

fixmerchants

+

fixmerchants

This command adds the Guild Representative position to all Human civilizations, allowing them to make trade agreements (just as they did back in 0.28.181.40d and earlier) in case you haven't already modified your raws accordingly.

-

fixveins

+

fixveins

Removes invalid references to mineral inclusions and restores missing ones. Use this if you broke your embark with tools like tiletypes, or if you accidentally placed a construction on top of a valuable mineral floor.

-

fixwagons

+

fixwagons

Due to a bug in all releases of version 0.31, merchants no longer bring wagons with their caravans. This command re-enables them for all appropriate civilizations.

-

flows

+

flows

A tool for checking how many tiles contain flowing liquids. If you suspect that your magma sea leaks into HFS, you can use this tool to be sure without revealing the map.

-

getplants

+

getplants

This tool allows plant gathering and tree cutting by RAW ID. Specify the types of trees to cut down and/or shrubs to gather by their plant names, separated by spaces.

-

Options

+

Options

@@ -863,15 +867,15 @@ Generated worlds are placed into your DF folder, named "World #".

-

tidlers

+

tidlers

Toggle between all possible positions where the idlers count can be placed.

-

twaterlvl

+

twaterlvl

Toggle between displaying/not displaying liquid depth as numbers.

-

job

+

job

Command for general job query and manipulation.

Options:
@@ -885,7 +889,7 @@ Generated worlds are placed into your DF folder, named "World #".

-

job-material

+

job-material

Alter the material of the selected job. Invoked as: job-material <inorganic-token>

Intended to be used as a keybinding:
@@ -897,7 +901,7 @@ Generated worlds are placed into your DF folder, named "World #".

-

job-duplicate

+

job-duplicate

Duplicate the selected job in a workshop:
    @@ -907,10 +911,10 @@ Generated worlds are placed into your DF folder, named "World #".

-

keybinding

+

keybinding

Manages DFHack keybindings. Currently it supports any combination of Ctrl/Alt/Shift with F1-F9, or A-Z.

@@ -933,7 +937,7 @@ Generated worlds are placed into your DF folder, named "World #".

-

liquids

+

liquids

Allows adding magma, water and obsidian to the game. It replaces the normal dfhack command line and can't be used from a hotkey. For more information, refer to the command's internal help.

@@ -943,7 +947,7 @@ temperatures (creating heat traps). You've been warned.

-

mode

+

mode

This command lets you see and change the game mode directly. Not all combinations are good for every situation and most of them will produce undesirable results. There are a few good ones though.

@@ -955,11 +959,11 @@ You just lost a fortress and gained an adventurer.

I take no responsibility of anything that happens as a result of using this tool :P

-

extirpate

+

extirpate

A tool for getting rid of trees and shrubs. By default, it only kills a tree/shrub under the cursor. The plants are turned into ashes instantly.

@@ -975,22 +979,22 @@ The plants are turned into ashes instantly.

-

grow

+

grow

Makes all saplings present on the map grow into trees (almost) instantly.

-

immolate

+

immolate

Very similar to extirpate, but additionally sets the plants on fire. The fires can and will spread ;)

-

probe

+

probe

Can be used to determine tile properties like temperature.

-

prospect

+

prospect

Prints a big list of all the present minerals and plants. By default, only the visible part of the map is scanned.

@@ -1005,13 +1009,13 @@ The plants are turned into ashes instantly.

-

Pre-embark estimate

+

Pre-embark estimate

If called during the embark selection screen, displays an estimate of layer stone availability. If the 'all' option is specified, also estimates veins. The estimate is computed either for 1 embark tile of the blinking biome, or for all tiles of the embark rectangle.

-

Options

+

Options

@@ -1023,14 +1027,14 @@ for 1 embark tile of the blinking biome, or for all tiles of the embark rectangl
-

regrass

+

regrass

Regrows all surface grass, restoring outdoor plant growth for pre-0.31.19 worlds.

-

rename

+

rename

Allows renaming various things.

@@ -1052,36 +1056,37 @@ for 1 embark tile of the blinking biome, or for all tiles of the embark rectangl
-

reveal

+

reveal

This reveals the map. By default, HFS will remain hidden so that the demons don't spawn. You can use 'reveal hell' to reveal everything. With hell revealed, you won't be able to unpause until you hide the map again. If you really want to unpause with hell revealed, use 'reveal demons'.

+

Reveal also works in adventure mode, but any of its effects are negated once you move. When you use it this way, you don't need to run 'unreveal'.

-

unreveal

+

unreveal

Reverts the effects of 'reveal'.

-

revtoggle

+

revtoggle

Switches between 'reveal' and 'unreveal'.

-

revflood

+

revflood

This command will hide the whole map and then reveal all the tiles that have a path to the in-game cursor.

-

seedwatch

+

seedwatch

Tool for turning cooking of seeds and plants on/off depending on how much you have of them.

See 'seedwatch help' for detailed description.

-

showmood

+

showmood

Shows all items needed for the currently active strange mood.

-

copystock

+

copystock

Copies the parameters of the currently highlighted stockpile to the custom stockpile settings and switches to custom stockpile placement mode, effectively allowing you to copy/paste stockpiles easily.

-

ssense / stonesense

+

ssense / stonesense

An isometric visualizer that runs in a second window. This requires working graphics acceleration and at least a dual core CPU (otherwise it will slow down DF).

All the data resides in the 'stonesense' directory. For detailed instructions, see stonesense/README.txt

Compatible with Windows > XP SP3 and most modern Linux distributions.

@@ -1091,31 +1096,47 @@ for 1 embark tile of the blinking biome, or for all tiles of the embark rectangl http://df.magmawiki.com/index.php/Utility:Stonesense/Content_repository

-

tiletypes

+

tiletypes

Can be used for painting map tiles and is a interactive command, much like liquids. You can paint tiles by their properties - shape, general material and a few others (paint). You can also paint only over tiles that match a set of properties (filter)

For more details, see the 'help' command while using this.

+
+

tweak

+

Contains various tweaks for minor bugs (currently just one).

+
+++ + + + + +
tweak clear-missing:
 Remove the missing status from the selected unit. This allows engraving slabs for ghostly, but not yet found, creatures.
+
+
-

tubefill

+

tubefill

Fills all the adamantine veins again. Veins that were empty will be filled in too, but might still trigger a demon invasion (this is a known bug).

-

vdig

+

vdig

Designates a whole vein for digging. Requires an active in-game cursor placed over a vein tile. With the 'x' option, it will traverse z-levels (putting stairs between the same-material tiles).

-

vdigx

+

vdigx

A permanent alias for 'vdig x'.

-

expdig

+

expdig

This command can be used for exploratory mining.

See: http://df.magmawiki.com/index.php/DF2010:Exploratory_mining

There are two variables that can be set: pattern and filter.

-

Patterns:

+

Patterns:

@@ -1136,7 +1157,7 @@ You can also paint only over tiles that match a set of properties (filter)

-

Filters:

+

Filters:

@@ -1152,7 +1173,7 @@ You can also paint only over tiles that match a set of properties (filter)

After you have a pattern set, you can use 'expdig' to apply it again.

-

Examples:

+

Examples:

designate the diagonal 5 patter over all hidden tiles:
    @@ -1173,11 +1194,11 @@ You can also paint only over tiles that match a set of properties (filter)

-

digcircle

+

digcircle

A command for easy designation of filled and hollow circles. It has several types of options.

@@ -1192,7 +1213,7 @@ It has several types of options.

-

Action:

+

Action:

@@ -1207,7 +1228,7 @@ It has several types of options.

-

Designation types:

+

Designation types:

@@ -1229,8 +1250,8 @@ It has several types of options.

After you have set the options, the command called with no options repeats with the last selected parameters.

-
-

Examples:

+
+

Examples:

  • 'digcircle filled 3' = Dig a filled circle with radius = 3.
  • 'digcircle' = Do it again.
  • @@ -1238,11 +1259,11 @@ repeats with the last selected parameters.

-

weather

+

weather

Prints the current weather map by default.

Also lets you change the current weather to 'clear sky', 'rainy' or 'snowing'.

-
@@ -1258,10 +1279,10 @@ repeats with the last selected parameters.

-

workflow

+

workflow

Manage control of repeat jobs.

-
-

Usage

+
+

Usage

workflow enable [option...], workflow disable [option...]

If no options are specified, enables or disables the plugin. @@ -1282,7 +1303,7 @@ Otherwise, enables or disables any of the following options:

-

Function

+

Function

When the plugin is enabled, it protects all repeat jobs from removal. If they do disappear due to any cause, they are immediately re-added to their workshop and suspended.

@@ -1293,7 +1314,7 @@ the amount has to drop before jobs are resumed; this is intended to reduce the frequency of jobs being toggled.

-

Constraint examples

+

Constraint examples

Keep metal bolts within 900-1000, and wood/bone within 150-200.

 workflow amount AMMO:ITEM_AMMO_BOLTS/METAL 1000 100
@@ -1330,11 +1351,11 @@ the Mill Plants job to MUSHROOM_CUP_DIMPLE using the 'job item-material' command
 
-

mapexport

+

mapexport

Export the current loaded map as a file. This will be eventually usable with visualizers.

-

dwarfexport

+

dwarfexport

Export dwarves to RuneSmith-compatible XML.

diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 3f672eba9..d1b36c68c 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -29,6 +29,7 @@ include/Internal.h include/DFHack.h include/Console.h include/Core.h +include/ColorText.h include/DataDefs.h include/Error.h include/Export.h @@ -66,6 +67,7 @@ include/modules/Graphic.h SET(PROJECT_SRCS Core.cpp +ColorText.cpp DataDefs.cpp DataStatics.cpp DataStaticsCtor.cpp @@ -101,6 +103,7 @@ modules/Vegetation.cpp modules/Vermin.cpp modules/World.cpp modules/Graphic.cpp +modules/Windows.cpp ) SET(PROJECT_HDRS_WINDOWS @@ -140,6 +143,26 @@ ELSE() LIST(APPEND PROJECT_SRCS ${PROJECT_SRCS_WINDOWS}) ENDIF() +# Protobuf + +FILE(GLOB PROJECT_PROTOS ${CMAKE_CURRENT_SOURCE_DIR}/proto/*.proto) + +STRING(REPLACE ".proto" ".pb.cc" PROJECT_PROTO_SRCS ${PROJECT_PROTOS}) +STRING(REPLACE ".proto" ".pb.h" PROJECT_PROTO_HDRS ${PROJECT_PROTOS}) + +LIST(APPEND PROJECT_HDRS ${PROJECT_PROTO_HDRS}) +LIST(APPEND PROJECT_SRCS ${PROJECT_PROTO_SRCS}) + +ADD_CUSTOM_COMMAND( + OUTPUT ${PROJECT_PROTO_SRCS} ${PROJECT_PROTO_HDRS} + COMMAND protoc-bin -I=${CMAKE_CURRENT_SOURCE_DIR}/proto/ + --cpp_out=dllexport_decl=DFHACK_EXPORT:${CMAKE_CURRENT_SOURCE_DIR}/proto/ + ${PROJECT_PROTOS} + DEPENDS protoc-bin ${PROJECT_PROTOS} +) + +# + SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE ) LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS}) @@ -192,10 +215,16 @@ else() ENDIF() endif() +IF(WIN32) + SET_TARGET_PROPERTIES(dfhack PROPERTIES COMPILE_FLAGS "/FI\"Export.h\"" ) +ELSE() + SET_TARGET_PROPERTIES(dfhack PROPERTIES COMPILE_FLAGS "-include Export.h" ) +ENDIF() + #effectively disables debug builds... SET_TARGET_PROPERTIES(dfhack PROPERTIES DEBUG_POSTFIX "-debug" ) -TARGET_LINK_LIBRARIES(dfhack ${PROJECT_LIBS}) +TARGET_LINK_LIBRARIES(dfhack protobuf-lite ${PROJECT_LIBS}) IF(UNIX) # On linux, copy our version of the df launch script which sets LD_PRELOAD diff --git a/library/ColorText.cpp b/library/ColorText.cpp new file mode 100644 index 000000000..fa5d57e0b --- /dev/null +++ b/library/ColorText.cpp @@ -0,0 +1,190 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2011 Petr Mrázek + +A thread-safe logging console with a line editor for windows. + +Based on linenoise win32 port, +copyright 2010, Jon Griffiths . +All rights reserved. +Based on linenoise, copyright 2010, Salvatore Sanfilippo . +The original linenoise can be found at: http://github.com/antirez/linenoise + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Redis nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "ColorText.h" +#include "MiscUtils.h" + +#include +#include +#include + +using namespace DFHack; + +#include "tinythread.h" +using namespace tthread; + +void color_ostream::flush_buffer(bool flush) +{ + auto buffer = buf(); + auto str = buffer->str(); + + if (!str.empty()) { + add_text(cur_color, buffer->str()); + buffer->str(std::string()); + } + + if (flush) + flush_proxy(); +} + +void color_ostream::begin_batch() +{ + flush_buffer(false); +} + +void color_ostream::end_batch() +{ + flush_proxy(); +} + +color_ostream::color_ostream() : ostream(new buffer(this)), cur_color(COLOR_RESET) +{ + // +} + +color_ostream::~color_ostream() +{ + delete buf(); +} + +void color_ostream::print(const char *format, ...) +{ + va_list args; + va_start(args, format); + vprint(format, args); + va_end(args); +} + +void color_ostream::vprint(const char *format, va_list args) +{ + std::string str = stl_vsprintf(format, args); + + if (!str.empty()) { + flush_buffer(false); + add_text(cur_color, str); + if (str[str.size()-1] == '\n') + flush_proxy(); + } +} + +void color_ostream::printerr(const char * format, ...) +{ + va_list args; + va_start(args, format); + vprinterr(format, args); + va_end(args); +} + +void color_ostream::vprinterr(const char *format, va_list args) +{ + color_value save = cur_color; + + fprintf(stderr, format, args); + + color(COLOR_LIGHTRED); + vprint(format, args); + color(save); +} + +void color_ostream::color(color_value c) +{ + if (c == cur_color) + return; + + flush_buffer(false); + cur_color = c; +} + +void color_ostream::reset_color(void) +{ + color(COLOR_RESET); +} + +void buffered_color_ostream::add_text(color_value color, const std::string &text) +{ + if (text.empty()) + return; + + if (buffer.empty()) + { + buffer.push_back(fragment_type(color, text)); + } + else + { + auto &back = buffer.back(); + + if (back.first != color || std::max(back.second.size(), text.size()) > 128) + buffer.push_back(fragment_type(color, text)); + else + buffer.back().second += text; + } +} + +void color_ostream_proxy::flush_proxy() +{ + if (!buffer.empty()) + { + target->begin_batch(); + + for (auto it = buffer.begin(); it != buffer.end(); ++it) + target->add_text(it->first, it->second); + + buffer.clear(); + + target->end_batch(); + } +} + +color_ostream_proxy::color_ostream_proxy(color_ostream &target) + : target(&target) +{ + // +} + +color_ostream_proxy::~color_ostream_proxy() +{ + *this << std::flush; +} diff --git a/library/Console-linux.cpp b/library/Console-linux.cpp index f471d6a10..92f621a8b 100644 --- a/library/Console-linux.cpp +++ b/library/Console-linux.cpp @@ -126,13 +126,14 @@ const char * getANSIColor(const int c) namespace DFHack { - class Private : public std::stringbuf + class Private { public: Private() { dfout_C = NULL; rawmode = false; + in_batch = false; supported_terminal = false; state = con_unclaimed; }; @@ -164,68 +165,71 @@ namespace DFHack return true; } } - protected: - int sync() - { - print(str().c_str()); - str(std::string()); // Clear the string buffer - return 0; - } + public: - /// Print a formatted string, like printf - int print(const char * format, ...) + void print(const char *data) { - va_list args; - va_start( args, format ); - int ret = vprint( format, args ); - va_end( args ); - return ret; + fputs(data, dfout_C); } - int vprint(const char * format, va_list vl) + + void print_text(color_ostream::color_value clr, const std::string &chunk) { - if(state == con_lineedit) + if(!in_batch && state == con_lineedit) { disable_raw(); fprintf(dfout_C,"\x1b[1G"); fprintf(dfout_C,"\x1b[0K"); - int ret = vfprintf( dfout_C, format, vl ); + + color(clr); + print(chunk.c_str()); + + reset_color(); enable_raw(); prompt_refresh(); - return ret; } - else return vfprintf( dfout_C, format, vl ); + else + { + color(clr); + print(chunk.c_str()); + } } - int vprinterr(const char * format, va_list vl) + + void begin_batch() { - if(state == con_lineedit) + assert(!in_batch); + + in_batch = true; + + if (state == con_lineedit) { disable_raw(); - color(Console::COLOR_LIGHTRED); fprintf(dfout_C,"\x1b[1G"); fprintf(dfout_C,"\x1b[0K"); - int ret = vfprintf( dfout_C, format, vl ); - reset_color(); - enable_raw(); - prompt_refresh(); - return ret; } - else + } + + void end_batch() + { + assert(in_batch); + + flush(); + + in_batch = false; + + if (state == con_lineedit) { - color(Console::COLOR_LIGHTRED); - int ret = vfprintf( dfout_C, format, vl ); reset_color(); - return ret; + enable_raw(); + prompt_refresh(); } } - /// Print a formatted string, like printf, in red - int printerr(const char * format, ...) + + void flush() { - va_list args; - va_start( args, format ); - int ret = vprinterr( format, args ); - va_end( args ); - return ret; + if (!rawmode) + fflush(dfout_C); } + /// Clear the console, along with its scrollback void clear() { @@ -243,7 +247,9 @@ namespace DFHack /// Position cursor at x,y. 1,1 = top left corner void gotoxy(int x, int y) { - print("\033[%d;%dH", y,x); + char tmp[64]; + sprintf(tmp,"\033[%d;%dH", y,x); + print(tmp); } /// Set color (ANSI color number) void color(Console::color_value index) @@ -291,18 +297,19 @@ namespace DFHack /// beep. maybe? //void beep (void); /// A simple line edit (raw mode) - int lineedit(const std::string& prompt, std::string& output, mutex * lock, CommandHistory & ch) + int lineedit(const std::string& prompt, std::string& output, recursive_mutex * lock, CommandHistory & ch) { output.clear(); + reset_color(); this->prompt = prompt; if (!supported_terminal) { print(prompt.c_str()); fflush(dfout_C); // FIXME: what do we do here??? - //SDL_mutexV(lock); + //SDL_recursive_mutexV(lock); std::getline(std::cin, output); - //SDL_mutexP(lock); + //SDL_recursive_mutexP(lock); return output.size(); } else @@ -396,7 +403,7 @@ namespace DFHack if (::write(STDIN_FILENO,seq,strlen(seq)) == -1) return; } - int prompt_loop(mutex * lock, CommandHistory & history) + int prompt_loop(recursive_mutex * lock, CommandHistory & history) { int fd = STDIN_FILENO; size_t plen = prompt.size(); @@ -606,6 +613,7 @@ namespace DFHack con_unclaimed, con_lineedit } state; + bool in_batch; std::string prompt; // current prompt string std::string raw_buffer; // current raw mode buffer int raw_cursor; // cursor position in the buffer @@ -615,12 +623,12 @@ namespace DFHack }; } -Console::Console():std::ostream(0), std::ios(0) +Console::Console() { d = 0; inited = false; // we can't create the mutex at this time. the SDL functions aren't hooked yet. - wlock = new mutex(); + wlock = new recursive_mutex(); } Console::~Console() { @@ -643,7 +651,6 @@ bool Console::init(bool sharing) d = new Private(); // make our own weird streams so our IO isn't redirected d->dfout_C = fopen("/dev/tty", "w"); - rdbuf(d); std::cin.tie(this); clear(); d->supported_terminal = !isUnsupportedTerm() && isatty(STDIN_FILENO); @@ -660,7 +667,7 @@ bool Console::shutdown(void) { if(!d) return true; - lock_guard g(*wlock); + lock_guard g(*wlock); if(d->rawmode) d->disable_raw(); d->print("\n"); @@ -670,46 +677,41 @@ bool Console::shutdown(void) return true; } -int Console::print( const char* format, ... ) +void Console::begin_batch() { - va_list args; - lock_guard g(*wlock); - int ret; - if(!inited) ret = -1; - else - { - va_start( args, format ); - ret = d->vprint(format, args); - va_end(args); - } - return ret; + //color_ostream::begin_batch(); + + wlock->lock(); + + if (inited) + d->begin_batch(); } -int Console::printerr( const char* format, ... ) +void Console::end_batch() { - va_list args; - lock_guard g(*wlock); - int ret; - // also mirror in error log - if(!inited) - { - va_start( args, format ); - ret = vfprintf(stderr, format, args); - va_end(args); - } - else - { - va_start( args, format ); - ret = d->vprinterr(format, args); - vfprintf(stderr, format, args); - va_end(args); - } - return ret; + if (inited) + d->end_batch(); + + wlock->unlock(); +} + +void Console::flush_proxy() +{ + lock_guard g(*wlock); + if (inited) + d->flush(); +} + +void Console::add_text(color_value color, const std::string &text) +{ + lock_guard g(*wlock); + if (inited) + d->print_text(color, text); } int Console::get_columns(void) { - lock_guard g(*wlock); + lock_guard g(*wlock); int ret = -1; if(inited) ret = d->get_columns(); @@ -718,7 +720,7 @@ int Console::get_columns(void) int Console::get_rows(void) { - lock_guard g(*wlock); + lock_guard g(*wlock); int ret = -1; if(inited) ret = d->get_rows(); @@ -727,42 +729,28 @@ int Console::get_rows(void) void Console::clear() { - lock_guard g(*wlock); + lock_guard g(*wlock); if(inited) d->clear(); } void Console::gotoxy(int x, int y) { - lock_guard g(*wlock); + lock_guard g(*wlock); if(inited) d->gotoxy(x,y); } -void Console::color(color_value index) -{ - lock_guard g(*wlock); - if(inited) - d->color(index); -} - -void Console::reset_color( void ) -{ - lock_guard g(*wlock); - if(inited) - d->reset_color(); -} - void Console::cursor(bool enable) { - lock_guard g(*wlock); + lock_guard g(*wlock); if(inited) d->cursor(enable); } int Console::lineedit(const std::string & prompt, std::string & output, CommandHistory & ch) { - lock_guard g(*wlock); + lock_guard g(*wlock); int ret = -2; if(inited) ret = d->lineedit(prompt,output,wlock,ch); diff --git a/library/Console-windows.cpp b/library/Console-windows.cpp index de2c2aca8..f9ec43573 100644 --- a/library/Console-windows.cpp +++ b/library/Console-windows.cpp @@ -66,10 +66,10 @@ using namespace tthread; namespace DFHack { - class Private : public std::stringbuf + class Private { public: - Private() : basic_stringbuf::basic_stringbuf() + Private() { dfout_C = 0; rawmode = 0; @@ -78,69 +78,70 @@ namespace DFHack ConsoleWindow = 0; default_attributes = 0; state = con_unclaimed; + in_batch = false; raw_cursor = 0; }; virtual ~Private() { //sync(); } - protected: - int sync() - { - print (str().c_str()); - // Clear the string buffer - str(std::string()); - return 0; - } public: - /// Print a formatted string, like printf - int print(const char * format, ...) + void print(const char *data) { - va_list args; - va_start( args, format ); - int ret = vprint( format, args ); - va_end( args ); - return ret; + fputs(data, dfout_C); } - int vprint(const char * format, va_list vl) + + void print_text(color_ostream::color_value clr, const std::string &chunk) { - if(state == con_lineedit) + if(!in_batch && state == con_lineedit) { clearline(); - int ret = vfprintf( dfout_C, format, vl ); + + color(clr); + print(chunk.c_str()); + + reset_color(); prompt_refresh(); - return ret; } - else return vfprintf( dfout_C, format, vl ); + else + { + color(clr); + print(chunk.c_str()); + } } - int vprinterr(const char * format, va_list vl) + + void begin_batch() { - if(state == con_lineedit) + assert(!in_batch); + + in_batch = true; + + if (state == con_lineedit) { - color(Console::COLOR_LIGHTRED); clearline(); - int ret = vfprintf( dfout_C, format, vl ); - reset_color(); - prompt_refresh(); - return ret; } - else + } + + void end_batch() + { + assert(in_batch); + + flush(); + + in_batch = false; + + if (state == con_lineedit) { - color(Console::COLOR_LIGHTRED); - int ret = vfprintf( dfout_C, format, vl ); reset_color(); - return ret; + prompt_refresh(); } } - /// Print a formatted string, like printf, in red - int printerr(const char * format, ...) + + void flush() { - va_list args; - va_start( args, format ); - int ret = vprinterr( format, args ); - va_end( args ); - return ret; + fflush(dfout_C); } + int get_columns(void) { CONSOLE_SCREEN_BUFFER_INFO inf = { 0 }; @@ -250,7 +251,7 @@ namespace DFHack SetConsoleCursorPosition(console_out, inf.dwCursorPosition); } - int prompt_loop(mutex * lock, CommandHistory & history) + int prompt_loop(recursive_mutex * lock, CommandHistory & history) { raw_buffer.clear(); // make sure the buffer is empty! size_t plen = prompt.size(); @@ -359,9 +360,10 @@ namespace DFHack } } } - int lineedit(const std::string & prompt, std::string & output, mutex * lock, CommandHistory & ch) + int lineedit(const std::string & prompt, std::string & output, recursive_mutex * lock, CommandHistory & ch) { output.clear(); + reset_color(); int count; state = con_lineedit; this->prompt = prompt; @@ -386,6 +388,7 @@ namespace DFHack con_unclaimed, con_lineedit } state; + bool in_batch; std::string prompt; // current prompt string std::string raw_buffer; // current raw mode buffer int raw_cursor; // cursor position in the buffer @@ -393,7 +396,7 @@ namespace DFHack } -Console::Console():std::ostream(0), std::ios(0) +Console::Console() { d = 0; wlock = 0; @@ -453,7 +456,7 @@ bool Console::init(bool) // Allocate a console! AllocConsole(); d->ConsoleWindow = GetConsoleWindow(); - wlock = new mutex(); + wlock = new recursive_mutex(); HMENU hm = GetSystemMenu(d->ConsoleWindow,false); DeleteMenu(hm, SC_CLOSE, MF_BYCOMMAND); @@ -484,7 +487,6 @@ bool Console::init(bool) std::ios::sync_with_stdio(); // make our own weird streams so our IO isn't redirected - rdbuf(d); std::cin.tie(this); clear(); inited = true; @@ -495,51 +497,47 @@ bool Console::init(bool) // FIXME: looks awfully empty, doesn't it? bool Console::shutdown(void) { - lock_guard g(*wlock); + lock_guard g(*wlock); FreeConsole(); inited = false; return true; } -int Console::print( const char* format, ... ) + +void Console::begin_batch() { - va_list args; - lock_guard g(*wlock); - int ret; - if(!inited) ret = -1; - else - { - va_start( args, format ); - ret = d->vprint(format, args); - va_end(args); - } - return ret; + //color_ostream::begin_batch(); + + wlock->lock(); + + if (inited) + d->begin_batch(); } -int Console::printerr( const char* format, ... ) +void Console::end_batch() { - va_list args; - lock_guard g(*wlock); - int ret; - // also mirror in error log - if(!inited) - { - va_start( args, format ); - ret = vfprintf(stderr, format, args); - va_end(args); - } - else - { - va_start( args, format ); - ret = d->vprinterr(format, args); - vfprintf(stderr, format, args); - va_end(args); - } - return ret; + if (inited) + d->end_batch(); + + wlock->unlock(); +} + +void Console::flush_proxy() +{ + lock_guard g(*wlock); + if (inited) + d->flush(); +} + +void Console::add_text(color_value color, const std::string &text) +{ + lock_guard g(*wlock); + if (inited) + d->print_text(color, text); } int Console::get_columns(void) { - lock_guard g(*wlock); + lock_guard g(*wlock); int ret = -1; if(inited) ret = d->get_columns(); @@ -548,7 +546,7 @@ int Console::get_columns(void) int Console::get_rows(void) { - lock_guard g(*wlock); + lock_guard g(*wlock); int ret = -1; if(inited) ret = d->get_rows(); @@ -557,35 +555,21 @@ int Console::get_rows(void) void Console::clear() { - lock_guard g(*wlock); + lock_guard g(*wlock); if(inited) d->clear(); } void Console::gotoxy(int x, int y) { - lock_guard g(*wlock); + lock_guard g(*wlock); if(inited) d->gotoxy(x,y); } -void Console::color(color_value index) -{ - lock_guard g(*wlock); - if(inited) - d->color(index); -} - -void Console::reset_color( void ) -{ - lock_guard g(*wlock); - if(inited) - d->reset_color(); -} - void Console::cursor(bool enable) { - lock_guard g(*wlock); + lock_guard g(*wlock); if(inited) d->cursor(enable); } diff --git a/library/Core.cpp b/library/Core.cpp index 4f75eed90..c250e98c1 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -47,11 +47,9 @@ using namespace std; #include "modules/Gui.h" #include "modules/World.h" #include "modules/Graphic.h" -//#include "modules/Windows.h" +#include "modules/Windows.h" using namespace DFHack; -#include "SDL_events.h" - #include "df/ui.h" #include "df/world.h" #include "df/world_data.h" @@ -156,20 +154,22 @@ void fHKthread(void * iodata) std::string stuff = core->getHotkeyCmd(); // waits on mutex! if(!stuff.empty()) { + color_ostream_proxy out(core->getConsole()); + vector args; cheap_tokenise(stuff, args); if (args.empty()) { - core->con.printerr("Empty hotkey command.\n"); + out.printerr("Empty hotkey command.\n"); continue; } - + string first = args[0]; args.erase(args.begin()); - command_result cr = plug_mgr->InvokeCommand(first, args, false); + command_result cr = plug_mgr->InvokeCommand(out, first, args, false); if(cr == CR_WOULD_BREAK) { - core->con.printerr("It isn't possible to run an interactive command outside the console.\n"); + out.printerr("It isn't possible to run an interactive command outside the console.\n"); } } } @@ -192,7 +192,7 @@ struct sortable static void runInteractiveCommand(Core *core, PluginManager *plug_mgr, int &clueless_counter, const string &command) { - Console & con = core->con; + Console & con = core->getConsole(); if (!command.empty()) { @@ -471,7 +471,7 @@ static void runInteractiveCommand(Core *core, PluginManager *plug_mgr, int &clue } else { - command_result res = plug_mgr->InvokeCommand(first, parts); + command_result res = plug_mgr->InvokeCommand(con, first, parts); if(res == CR_NOT_IMPLEMENTED) { con.printerr("%s is not a recognized command.\n", first.c_str()); @@ -506,7 +506,7 @@ void fIOthread(void * iodata) CommandHistory main_history; main_history.load("dfhack.history"); - Console & con = core->con; + Console & con = core->getConsole(); if(plug_mgr == 0 || core == 0) { con.printerr("Something horrible happened in Core's constructor...\n"); @@ -572,6 +572,7 @@ Core::Core() misc_data_mutex=0; last_world_data_ptr = NULL; top_viewscreen = NULL; + screen_window = NULL; }; void Core::fatal (std::string output, bool deactivate) @@ -677,6 +678,8 @@ bool Core::Init() HotkeyMutex = new mutex(); HotkeyCond = new condition_variable(); thread * HK = new thread(fHKthread, (void *) temp); + screen_window = new Windows::top_level_window(); + screen_window->addChild(new Windows::dfhack_dummy(5,10)); started = true; cerr << "DFHack is running.\n"; return true; @@ -710,6 +713,16 @@ std::string Core::getHotkeyCmd( void ) return returner; } +void Core::printerr(const char *format, ...) +{ + color_ostream_proxy proxy(getInstance().con); + + va_list args; + va_start(args,format); + proxy.vprinterr(format,args); + va_end(args); +} + void Core::RegisterData( void *p, std::string key ) { misc_data_mutex->lock(); @@ -755,29 +768,11 @@ void Core::Resume() AccessMutex->unlock(); } -struct screen_tile -{ - unsigned char symbol; - unsigned char front; - unsigned char back; - unsigned char bright; -}; - -void screen_paint (int x, int y, uint8_t symbol) -{ - int tile = x * df::global::gps->dimy + y; - screen_tile *s = (screen_tile *) (df::global::gps->screen + tile*4); - s->symbol = symbol; -} - int Core::TileUpdate() { - screen_paint(0,0,'D'); - screen_paint(1,0,'F'); - screen_paint(2,0,'H'); - screen_paint(3,0,'a'); - screen_paint(4,0,'c'); - screen_paint(5,0,'k'); + if(!started) + return false; + screen_window->paint(); return true; } @@ -789,6 +784,8 @@ int Core::Update() if(errorstate) return -1; + color_ostream_proxy out(con); + // detect if the game was loaded or unloaded in the meantime void *new_wdata = NULL; if (df::global::world) { @@ -800,7 +797,7 @@ int Core::Update() if (new_wdata != last_world_data_ptr) { last_world_data_ptr = new_wdata; - plug_mgr->OnStateChange(new_wdata ? SC_GAME_LOADED : SC_GAME_UNLOADED); + plug_mgr->OnStateChange(out, new_wdata ? SC_GAME_LOADED : SC_GAME_UNLOADED); } // detect if the viewscreen changed @@ -812,12 +809,14 @@ int Core::Update() if (screen != top_viewscreen) { top_viewscreen = screen; - plug_mgr->OnStateChange(SC_VIEWSCREEN_CHANGED); + plug_mgr->OnStateChange(out, SC_VIEWSCREEN_CHANGED); } } // notify all the plugins that a game tick is finished - plug_mgr->OnUpdate(); + plug_mgr->OnUpdate(out); + + out << std::flush; // wake waiting tools // do not allow more tools to join in while we process stuff here @@ -897,6 +896,40 @@ bool Core::ncurses_wgetch(int in, int & out) return true; } +int Core::UnicodeAwareSym(const SDL::KeyboardEvent& ke) +{ + // Assume keyboard layouts don't change the order of numbers: + if( '0' <= ke.ksym.sym && ke.ksym.sym <= '9') return ke.ksym.sym; + + int unicode = ke.ksym.unicode; + + // convert Ctrl characters to their 0x40-0x5F counterparts: + if (unicode < ' ') + { + unicode += 'A' - 1; + } + + // convert A-Z to their a-z counterparts: + if('A' < unicode && unicode < 'Z') + { + unicode += 'a' - 'A'; + } + + // convert various other punctuation marks: + if('\"' == unicode) unicode = '\''; + if('+' == unicode) unicode = '='; + if(':' == unicode) unicode = ';'; + if('<' == unicode) unicode = ','; + if('>' == unicode) unicode = '.'; + if('?' == unicode) unicode = '/'; + if('{' == unicode) unicode = '['; + if('|' == unicode) unicode = '\\'; + if('}' == unicode) unicode = ']'; + if('~' == unicode) unicode = '`'; + + return unicode; +} + //MEMO: return false if event is consumed int Core::SDL_Event(SDL::Event* ev) { @@ -917,7 +950,18 @@ int Core::SDL_Event(SDL::Event* ev) if (ke->ksym.mod & SDL::KMOD_CTRL) mod |= 2; if (ke->ksym.mod & SDL::KMOD_ALT) mod |= 4; - SelectHotkey(ke->ksym.sym, mod); + // Use unicode so Windows gives the correct value for the + // user's Input Language + if((ke->ksym.unicode & 0xff80) == 0) + { + int key = UnicodeAwareSym(*ke); + SelectHotkey(key, mod); + } + else + { + // Pretend non-ascii characters don't happen: + SelectHotkey(ke->ksym.sym, mod); + } } else if(ke->state == SDL::BTN_RELEASED) { @@ -1005,7 +1049,7 @@ static bool parseKeySpec(std::string keyspec, int *psym, int *pmod) *psym = SDL::K_F1 + (keyspec[1]-'1'); return true; } else - return false; + return false; } bool Core::ClearKeyBindings(std::string keyspec) diff --git a/library/Hooks-windows.cpp b/library/Hooks-windows.cpp index c4e0f0a38..f6d7b7f12 100644 --- a/library/Hooks-windows.cpp +++ b/library/Hooks-windows.cpp @@ -404,6 +404,10 @@ DFhackCExport int SDL_EnableKeyRepeat(int delay, int interval) static int (*_SDL_EnableUNICODE)(int enable) = 0; DFhackCExport int SDL_EnableUNICODE(int enable) { + if(!enable) + { + fprintf(stderr, "SDL_EnableUNICODE turned off. Keybindings may break.\n"); + } return _SDL_EnableUNICODE(enable); } @@ -800,6 +804,8 @@ bool FirstCall() _SDL_SemWait = (int (*)(void *))GetProcAddress(realSDLlib,"SDL_SemWait"); _SDL_ThreadID = (uint32_t (*)(void))GetProcAddress(realSDLlib,"SDL_ThreadID"); + _SDL_EnableUNICODE(1); + fprintf(stderr,"Initized HOOKS!\n"); inited = true; return 1; diff --git a/library/PluginManager.cpp b/library/PluginManager.cpp index 82e53b3f7..824d7a23e 100644 --- a/library/PluginManager.cpp +++ b/library/PluginManager.cpp @@ -140,7 +140,6 @@ Plugin::Plugin(Core * core, const std::string & filepath, const std::string & _f break; name.append(1,ch); } - Console & con = core->con; plugin_lib = 0; plugin_init = 0; plugin_shutdown = 0; @@ -172,7 +171,7 @@ bool Plugin::load() return true; } Core & c = Core::getInstance(); - Console & con = c.con; + Console & con = c.getConsole(); DFLibrary * plug = OpenPlugin(filename.c_str()); if(!plug) { @@ -197,7 +196,7 @@ bool Plugin::load() state = PS_BROKEN; return false; } - plugin_init = (command_result (*)(Core *, std::vector &)) LookupPlugin(plug, "plugin_init"); + plugin_init = (command_result (*)(color_ostream &, std::vector &)) LookupPlugin(plug, "plugin_init"); if(!plugin_init) { con.printerr("Plugin %s has no init function.\n", filename.c_str()); @@ -205,13 +204,13 @@ bool Plugin::load() state = PS_BROKEN; return false; } - plugin_status = (command_result (*)(Core *, std::string &)) LookupPlugin(plug, "plugin_status"); - plugin_onupdate = (command_result (*)(Core *)) LookupPlugin(plug, "plugin_onupdate"); - plugin_shutdown = (command_result (*)(Core *)) LookupPlugin(plug, "plugin_shutdown"); - plugin_onstatechange = (command_result (*)(Core *, state_change_event)) LookupPlugin(plug, "plugin_onstatechange"); + plugin_status = (command_result (*)(color_ostream &, std::string &)) LookupPlugin(plug, "plugin_status"); + plugin_onupdate = (command_result (*)(color_ostream &)) LookupPlugin(plug, "plugin_onupdate"); + plugin_shutdown = (command_result (*)(color_ostream &)) LookupPlugin(plug, "plugin_shutdown"); + plugin_onstatechange = (command_result (*)(color_ostream &, state_change_event)) LookupPlugin(plug, "plugin_onstatechange"); this->name = *plug_name; plugin_lib = plug; - if(plugin_init(&c,commands) == CR_OK) + if(plugin_init(con,commands) == CR_OK) { state = PS_LOADED; parent->registerCommands(this); @@ -229,14 +228,14 @@ bool Plugin::load() bool Plugin::unload() { Core & c = Core::getInstance(); - Console & con = c.con; + Console & con = c.getConsole(); // get the mutex access->lock(); // if we are actually loaded if(state == PS_LOADED) { // notify plugin about shutdown - command_result cr = plugin_shutdown(&Core::getInstance()); + command_result cr = plugin_shutdown(con); // wait for all calls to finish access->wait(); // cleanup... @@ -276,7 +275,7 @@ bool Plugin::reload() return true; } -command_result Plugin::invoke( std::string & command, std::vector & parameters, bool interactive_) +command_result Plugin::invoke(color_ostream &out, std::string & command, std::vector & parameters, bool interactive_) { Core & c = Core::getInstance(); command_result cr = CR_NOT_IMPLEMENTED; @@ -289,7 +288,7 @@ command_result Plugin::invoke( std::string & command, std::vector if(cmd.name == command) { // running interactive things from some other source than the console would break it - if(!interactive_ && cmd.interactive) + if(!(interactive_ && out.is_console()) && cmd.interactive) cr = CR_WOULD_BREAK; else if (cmd.guard) { @@ -300,22 +299,22 @@ command_result Plugin::invoke( std::string & command, std::vector CoreSuspender suspend(&c); df::viewscreen *top = c.getTopViewscreen(); - if (!cmd.guard(&c, top)) + if (!cmd.guard(top)) { - c.con.printerr("Could not invoke %s: unsuitable UI state.\n", command.c_str()); + out.printerr("Could not invoke %s: unsuitable UI state.\n", command.c_str()); cr = CR_WRONG_USAGE; } else { - cr = cmd.function(&c, parameters); + cr = cmd.function(out, parameters); } } else { - cr = cmd.function(&c, parameters); + cr = cmd.function(out, parameters); } if (cr == CR_WRONG_USAGE && !cmd.usage.empty()) - c.con << "Usage:\n" << cmd.usage << flush; + out << "Usage:\n" << cmd.usage << flush; break; } } @@ -339,9 +338,9 @@ bool Plugin::can_invoke_hotkey( std::string & command, df::viewscreen *top ) if (cmd.interactive) cr = false; else if (cmd.guard) - cr = cmd.guard(&c, top); + cr = cmd.guard(top); else - cr = Gui::default_hotkey(&c, top); + cr = Gui::default_hotkey(top); break; } } @@ -350,27 +349,25 @@ bool Plugin::can_invoke_hotkey( std::string & command, df::viewscreen *top ) return cr; } -command_result Plugin::on_update() +command_result Plugin::on_update(color_ostream &out) { - Core & c = Core::getInstance(); command_result cr = CR_NOT_IMPLEMENTED; access->lock_add(); if(state == PS_LOADED && plugin_onupdate) { - cr = plugin_onupdate(&c); + cr = plugin_onupdate(out); } access->lock_sub(); return cr; } -command_result Plugin::on_state_change(state_change_event event) +command_result Plugin::on_state_change(color_ostream &out, state_change_event event) { - Core & c = Core::getInstance(); command_result cr = CR_NOT_IMPLEMENTED; access->lock_add(); if(state == PS_LOADED && plugin_onstatechange) { - cr = plugin_onstatechange(&c, event); + cr = plugin_onstatechange(out, event); } access->lock_sub(); return cr; @@ -436,10 +433,10 @@ Plugin *PluginManager::getPluginByCommand(const std::string &command) } // FIXME: handle name collisions... -command_result PluginManager::InvokeCommand( std::string & command, std::vector & parameters, bool interactive) +command_result PluginManager::InvokeCommand(color_ostream &out, std::string & command, std::vector & parameters, bool interactive) { Plugin *plugin = getPluginByCommand(command); - return plugin ? plugin->invoke(command, parameters, interactive) : CR_NOT_IMPLEMENTED; + return plugin ? plugin->invoke(out, command, parameters, interactive) : CR_NOT_IMPLEMENTED; } bool PluginManager::CanInvokeHotkey(std::string &command, df::viewscreen *top) @@ -448,19 +445,19 @@ bool PluginManager::CanInvokeHotkey(std::string &command, df::viewscreen *top) return plugin ? plugin->can_invoke_hotkey(command, top) : false; } -void PluginManager::OnUpdate( void ) +void PluginManager::OnUpdate(color_ostream &out) { for(size_t i = 0; i < all_plugins.size(); i++) { - all_plugins[i]->on_update(); + all_plugins[i]->on_update(out); } } -void PluginManager::OnStateChange( state_change_event event ) +void PluginManager::OnStateChange(color_ostream &out, state_change_event event) { for(size_t i = 0; i < all_plugins.size(); i++) { - all_plugins[i]->on_state_change(event); + all_plugins[i]->on_state_change(out, event); } } diff --git a/library/depends/protobuf/CMakeLists.txt b/library/depends/protobuf/CMakeLists.txt index 46711b418..0a203e5d4 100644 --- a/library/depends/protobuf/CMakeLists.txt +++ b/library/depends/protobuf/CMakeLists.txt @@ -91,6 +91,8 @@ google/protobuf/wire_format_lite.h google/protobuf/wire_format_lite_inl.h google/protobuf/io/zero_copy_stream.h google/protobuf/io/zero_copy_stream_impl_lite.h +google/protobuf/io/gzip_stream.h +google/protobuf/io/zero_copy_stream_impl.h ) SET(LIBPROTOBUF_FULL_HDRS @@ -99,7 +101,6 @@ google/protobuf/descriptor.pb.h google/protobuf/descriptor_database.h google/protobuf/dynamic_message.h google/protobuf/generated_message_reflection.h -google/protobuf/io/gzip_stream.h google/protobuf/compiler/importer.h google/protobuf/message.h google/protobuf/compiler/parser.h @@ -112,7 +113,6 @@ google/protobuf/text_format.h google/protobuf/io/tokenizer.h google/protobuf/unknown_field_set.h google/protobuf/wire_format.h -google/protobuf/io/zero_copy_stream_impl.h ) LIST(APPEND LIBPROTOBUF_FULL_HDRS ${LIBPROTOBUF_LITE_HDRS}) @@ -128,6 +128,8 @@ google/protobuf/repeated_field.cc google/protobuf/wire_format_lite.cc google/protobuf/io/zero_copy_stream.cc google/protobuf/io/zero_copy_stream_impl_lite.cc +google/protobuf/io/gzip_stream.cc +google/protobuf/io/zero_copy_stream_impl.cc ) SET(LIBPROTOBUF_FULL_SRCS @@ -137,8 +139,8 @@ google/protobuf/descriptor_database.cc google/protobuf/dynamic_message.cc google/protobuf/extension_set_heavy.cc google/protobuf/generated_message_reflection.cc -google/protobuf/io/gzip_stream.cc google/protobuf/compiler/importer.cc +google/protobuf/io/gzip_stream.cc google/protobuf/message.cc google/protobuf/compiler/parser.cc google/protobuf/io/printer.cc @@ -199,11 +201,33 @@ google/protobuf/compiler/zip_writer.cc LIST(APPEND LIBPROTOBUF_FULL_SRCS ${LIBPROTOBUF_LITE_SRCS}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) -INCLUDE_DIRECTORIES(${dfhack_SOURCE_DIR}/library/depends/zlib) +INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS}) + +# Protobuf shared libraries + +ADD_LIBRARY(protobuf SHARED ${LIBPROTOBUF_FULL_SRCS} ${LIBPROTOBUF_FULL_HDRS}) +ADD_LIBRARY(protobuf-lite SHARED ${LIBPROTOBUF_LITE_SRCS} ${LIBPROTOBUF_LITE_HDRS}) + +SET_TARGET_PROPERTIES(protobuf PROPERTIES COMPILE_DEFINITIONS LIBPROTOBUF_EXPORTS) +SET_TARGET_PROPERTIES(protobuf-lite PROPERTIES COMPILE_DEFINITIONS LIBPROTOBUF_EXPORTS) + +TARGET_LINK_LIBRARIES(protobuf ${CMAKE_THREAD_LIBS_INIT} ${ZLIB_LIBRARIES}) +TARGET_LINK_LIBRARIES(protobuf-lite ${CMAKE_THREAD_LIBS_INIT} ${ZLIB_LIBRARIES}) + +install(TARGETS protobuf-lite + LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION}/deplibs + RUNTIME DESTINATION ${DFHACK_LIBRARY_DESTINATION}/deplibs) + +# Protobuf compiler shared library + +ADD_LIBRARY(protoc SHARED ${LIBPROTOC_SRCS} ${LIBPROTOC_HDRS}) + +SET_TARGET_PROPERTIES(protoc PROPERTIES COMPILE_DEFINITIONS LIBPROTOC_EXPORTS) +TARGET_LINK_LIBRARIES(protoc protobuf) + +# Protobuf compiler executable -ADD_LIBRARY(protobuf-lite ${LIBPROTOBUF_LITE_SRCS} ${LIBPROTOBUF_LITE_HDRS}) -ADD_LIBRARY(protobuf ${LIBPROTOBUF_FULL_SRCS} ${LIBPROTOBUF_FULL_HDRS}) -ADD_LIBRARY(protoc ${LIBPROTOC_SRCS} ${LIBPROTOC_HDRS}) ADD_EXECUTABLE(protoc-bin google/protobuf/compiler/main.cc google/protobuf/compiler/command_line_interface.h google/protobuf/compiler/cpp/cpp_generator.h) + SET_TARGET_PROPERTIES(protoc-bin PROPERTIES OUTPUT_NAME protoc) -TARGET_LINK_LIBRARIES(protoc-bin protoc protobuf ${CMAKE_THREAD_LIBS_INIT}) +TARGET_LINK_LIBRARIES(protoc-bin protoc) diff --git a/library/depends/protobuf/google/protobuf/generated_message_util.h b/library/depends/protobuf/google/protobuf/generated_message_util.h index 1a2343d44..239daea59 100644 --- a/library/depends/protobuf/google/protobuf/generated_message_util.h +++ b/library/depends/protobuf/google/protobuf/generated_message_util.h @@ -72,7 +72,7 @@ double Infinity(); double NaN(); // Constant used for empty default strings. -extern const ::std::string kEmptyString; +extern LIBPROTOBUF_EXPORT const ::std::string kEmptyString; } // namespace internal diff --git a/library/depends/protobuf/google/protobuf/repeated_field.h b/library/depends/protobuf/google/protobuf/repeated_field.h index 6080ddccc..aed4ce9f2 100644 --- a/library/depends/protobuf/google/protobuf/repeated_field.h +++ b/library/depends/protobuf/google/protobuf/repeated_field.h @@ -305,7 +305,7 @@ class LIBPROTOBUF_EXPORT StringTypeHandlerBase { static void Merge(const string& from, string* to) { *to = from; } }; -class LIBPROTOBUF_EXPORT StringTypeHandler : public StringTypeHandlerBase { +class StringTypeHandler : public StringTypeHandlerBase { public: static int SpaceUsed(const string& value) { return sizeof(value) + StringSpaceUsedExcludingSelf(value); diff --git a/library/depends/protobuf/google/protobuf/stubs/common.h b/library/depends/protobuf/google/protobuf/stubs/common.h index 7173a84d1..832973574 100644 --- a/library/depends/protobuf/google/protobuf/stubs/common.h +++ b/library/depends/protobuf/google/protobuf/stubs/common.h @@ -96,6 +96,9 @@ namespace protobuf { #else #define LIBPROTOC_EXPORT __declspec(dllimport) #endif +#elif defined(PROTOBUF_USE_DLLS) + #define LIBPROTOBUF_EXPORT __attribute__ ((visibility("default"))) + #define LIBPROTOC_EXPORT __attribute__ ((visibility("default"))) #else #define LIBPROTOBUF_EXPORT #define LIBPROTOC_EXPORT diff --git a/library/depends/tthread/tinythread.h b/library/depends/tthread/tinythread.h index 723370cf8..f4f8c5b22 100644 --- a/library/depends/tthread/tinythread.h +++ b/library/depends/tthread/tinythread.h @@ -67,6 +67,7 @@ freely, subject to the following restrictions: // Platform specific includes #if defined(_TTHREAD_WIN32_) + #define NOMINMAX #include #else #include diff --git a/library/depends/zlib/zconf.h b/library/depends/zlib/include/zconf.h similarity index 100% rename from library/depends/zlib/zconf.h rename to library/depends/zlib/include/zconf.h diff --git a/library/depends/zlib/zlib.h b/library/depends/zlib/include/zlib.h similarity index 100% rename from library/depends/zlib/zlib.h rename to library/depends/zlib/include/zlib.h diff --git a/library/depends/zlib/zlib.lib b/library/depends/zlib/lib/zlib.lib similarity index 100% rename from library/depends/zlib/zlib.lib rename to library/depends/zlib/lib/zlib.lib diff --git a/library/include/ColorText.h b/library/include/ColorText.h new file mode 100644 index 000000000..cdeaa3948 --- /dev/null +++ b/library/include/ColorText.h @@ -0,0 +1,145 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#pragma once +#include "Pragma.h" +#include "Export.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace DFHack +{ + class DFHACK_EXPORT color_ostream : public std::ostream + { + public: + enum color_value + { + COLOR_RESET = -1, + COLOR_BLACK = 0, + COLOR_BLUE, + COLOR_GREEN, + COLOR_CYAN, + COLOR_RED, + COLOR_MAGENTA, + COLOR_BROWN, + COLOR_GREY, + COLOR_DARKGREY, + COLOR_LIGHTBLUE, + COLOR_LIGHTGREEN, + COLOR_LIGHTCYAN, + COLOR_LIGHTRED, + COLOR_LIGHTMAGENTA, + COLOR_YELLOW, + COLOR_WHITE, + COLOR_MAX = COLOR_WHITE + }; + + private: + color_value cur_color; + + class buffer : public std::stringbuf + { + public: + color_ostream *owner; + + buffer(color_ostream *owner) : owner(owner) {} + virtual ~buffer() { } + + protected: + virtual int sync() { + owner->flush_buffer(true); + return 0; + } + }; + + buffer *buf() { return (buffer*)rdbuf(); } + + void flush_buffer(bool flush); + + protected: + // These must be strictly balanced, because + // they might grab and hold mutexes. + virtual void begin_batch(); + virtual void end_batch(); + + virtual void add_text(color_value color, const std::string &text) = 0; + + virtual void flush_proxy() {}; + + friend class color_ostream_proxy; + public: + color_ostream(); + virtual ~color_ostream(); + + /// Print a formatted string, like printf + void print(const char *format, ...); + void vprint(const char *format, va_list args); + + /// Print a formatted string, like printf, in red + void printerr(const char *format, ...); + void vprinterr(const char *format, va_list args); + + /// Set color (ANSI color number) + void color(color_value c); + /// Reset color to default + void reset_color(void); + + virtual bool is_console() { return false; } + }; + + class DFHACK_EXPORT buffered_color_ostream : public color_ostream + { + protected: + virtual void add_text(color_value color, const std::string &text); + + public: + typedef std::pair fragment_type; + + buffered_color_ostream() {} + ~buffered_color_ostream() {} + + const std::list &fragments() { return buffer; } + + protected: + std::list buffer; + }; + + class DFHACK_EXPORT color_ostream_proxy : public buffered_color_ostream + { + protected: + color_ostream *target; + + virtual void flush_proxy(); + + public: + color_ostream_proxy(color_ostream &target); + ~color_ostream_proxy(); + }; +} diff --git a/library/include/Console.h b/library/include/Console.h index 70385d829..a0a098861 100644 --- a/library/include/Console.h +++ b/library/include/Console.h @@ -25,6 +25,7 @@ distribution. #pragma once #include "Pragma.h" #include "Export.h" +#include "ColorText.h" #include #include #include @@ -33,6 +34,7 @@ distribution. namespace tthread { class mutex; + class recursive_mutex; class condition_variable; class thread; } @@ -106,31 +108,18 @@ namespace DFHack std::size_t capacity; std::deque history; }; + class Private; - class DFHACK_EXPORT Console : public std::ostream + class DFHACK_EXPORT Console : public color_ostream { + protected: + virtual void begin_batch(); + virtual void add_text(color_value color, const std::string &text); + virtual void end_batch(); + + virtual void flush_proxy(); + public: - enum color_value - { - COLOR_RESET = -1, - COLOR_BLACK = 0, - COLOR_BLUE, - COLOR_GREEN, - COLOR_CYAN, - COLOR_RED, - COLOR_MAGENTA, - COLOR_BROWN, - COLOR_GREY, - COLOR_DARKGREY, - COLOR_LIGHTBLUE, - COLOR_LIGHTGREEN, - COLOR_LIGHTCYAN, - COLOR_LIGHTRED, - COLOR_LIGHTMAGENTA, - COLOR_YELLOW, - COLOR_WHITE, - COLOR_MAX = COLOR_WHITE - }; ///ctor, NOT thread-safe Console(); ///dtor, NOT thread-safe @@ -140,18 +129,10 @@ namespace DFHack /// shutdown the console. NOT thread-safe bool shutdown( void ); - /// Print a formatted string, like printf - int print(const char * format, ...); - /// Print a formatted string, like printf, in red - int printerr(const char * format, ...); /// Clear the console, along with its scrollback void clear(); /// Position cursor at x,y. 1,1 = top left corner void gotoxy(int x, int y); - /// Set color (ANSI color number) - void color(color_value c); - /// Reset color to default - void reset_color(void); /// Enable or disable the caret/cursor void cursor(bool enable = true); /// Waits given number of milliseconds before continuing. @@ -165,9 +146,11 @@ namespace DFHack /// A simple line edit (raw mode) int lineedit(const std::string& prompt, std::string& output, CommandHistory & history ); bool isInited (void) { return inited; }; + + bool is_console() { return true; } private: Private * d; - tthread::mutex * wlock; + tthread::recursive_mutex * wlock; bool inited; }; } diff --git a/library/include/Core.h b/library/include/Core.h index a2fa27a5f..321939c5d 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -33,6 +33,7 @@ distribution. #include #include "Console.h" #include "modules/Graphic.h" +#include "SDL_events.h" struct WINDOW; @@ -59,6 +60,10 @@ namespace DFHack class VersionInfoFactory; class PluginManager; class Core; + namespace Windows + { + class df_window; + } // anon type, pretty much struct DFLibrary; @@ -120,12 +125,20 @@ namespace DFHack std::vector ListKeyBindings(std::string keyspec); bool isWorldLoaded() { return (last_world_data_ptr != NULL); } - df::viewscreen *getTopViewscreen() { return top_viewscreen; } + + static df::viewscreen *getTopViewscreen() { return getInstance().top_viewscreen; } + + DFHack::Console &getConsole() { return con; } DFHack::Process * p; DFHack::VersionInfo * vinfo; - DFHack::Console con; + DFHack::Windows::df_window * screen_window; + + static void printerr(const char *format, ...); + private: + DFHack::Console con; + Core(); bool Init(); int Update (void); @@ -172,6 +185,7 @@ namespace DFHack tthread::mutex * HotkeyMutex; tthread::condition_variable * HotkeyCond; + int UnicodeAwareSym(const SDL::KeyboardEvent& ke); bool SelectHotkey(int key, int modifiers); void *last_world_data_ptr; // for state change tracking @@ -179,13 +193,14 @@ namespace DFHack // Very important! bool started; - tthread::mutex * misc_data_mutex; - std::map misc_data_map; + tthread::mutex * misc_data_mutex; + std::map misc_data_map; }; class CoreSuspender { Core *core; public: + CoreSuspender() : core(&Core::getInstance()) { core->Suspend(); } CoreSuspender(Core *core) : core(core) { core->Suspend(); } ~CoreSuspender() { core->Resume(); } }; diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index 55dc9e404..039b75b20 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -35,7 +35,7 @@ distribution. using namespace std; template -void print_bits ( T val, DFHack::Console& out ) +void print_bits ( T val, ostream& out ) { stringstream strs; T n_bits = sizeof ( val ) * CHAR_BIT; @@ -63,7 +63,7 @@ void print_bits ( T val, DFHack::Console& out ) val >>= 1; } strs << endl; - out.print(strs.str().c_str()); + out << strs.str(); } /* diff --git a/library/include/PluginManager.h b/library/include/PluginManager.h index 4fcd80ff0..8e8f7760d 100644 --- a/library/include/PluginManager.h +++ b/library/include/PluginManager.h @@ -26,6 +26,7 @@ distribution. #include "Export.h" #include "Hooks.h" +#include "ColorText.h" #include #include #include @@ -61,8 +62,8 @@ namespace DFHack }; struct DFHACK_EXPORT PluginCommand { - typedef command_result (*command_function)(Core *, std::vector &); - typedef bool (*command_hotkey_guard)(Core *, df::viewscreen *); + typedef command_result (*command_function)(color_ostream &out, std::vector &); + typedef bool (*command_hotkey_guard)(df::viewscreen *); /// create a command with a name, description, function pointer to its code /// and saying if it needs an interactive terminal @@ -112,13 +113,13 @@ namespace DFHack friend class PluginManager; Plugin(DFHack::Core* core, const std::string& filepath, const std::string& filename, PluginManager * pm); ~Plugin(); - command_result on_update(); - command_result on_state_change(state_change_event event); + command_result on_update(color_ostream &out); + command_result on_state_change(color_ostream &out, state_change_event event); public: bool load(); bool unload(); bool reload(); - command_result invoke( std::string & command, std::vector & parameters, bool interactive ); + command_result invoke(color_ostream &out, std::string & command, std::vector & parameters, bool interactive ); bool can_invoke_hotkey( std::string & command, df::viewscreen *top ); plugin_state getState () const; const PluginCommand& operator[] (std::size_t index) const @@ -141,11 +142,11 @@ namespace DFHack DFLibrary * plugin_lib; PluginManager * parent; plugin_state state; - command_result (*plugin_init)(Core *, std::vector &); - command_result (*plugin_status)(Core *, std::string &); - command_result (*plugin_shutdown)(Core *); - command_result (*plugin_onupdate)(Core *); - command_result (*plugin_onstatechange)(Core *, state_change_event); + command_result (*plugin_init)(color_ostream &, std::vector &); + command_result (*plugin_status)(color_ostream &, std::string &); + command_result (*plugin_shutdown)(color_ostream &); + command_result (*plugin_onupdate)(color_ostream &); + command_result (*plugin_onstatechange)(color_ostream &, state_change_event); }; class DFHACK_EXPORT PluginManager { @@ -154,15 +155,15 @@ namespace DFHack friend class Plugin; PluginManager(Core * core); ~PluginManager(); - void OnUpdate( void ); - void OnStateChange( state_change_event event ); + void OnUpdate(color_ostream &out); + void OnStateChange(color_ostream &out, state_change_event event); void registerCommands( Plugin * p ); void unregisterCommands( Plugin * p ); // PUBLIC METHODS public: Plugin *getPluginByName (const std::string & name); Plugin *getPluginByCommand (const std::string &command); - command_result InvokeCommand( std::string & command, std::vector & parameters, bool interactive = true ); + command_result InvokeCommand(color_ostream &out, std::string & command, std::vector & parameters, bool interactive = true ); bool CanInvokeHotkey(std::string &command, df::viewscreen *top); Plugin* operator[] (std::size_t index) { @@ -185,9 +186,9 @@ namespace DFHack namespace Gui { // Predefined hotkey guards - DFHACK_EXPORT bool default_hotkey(Core *, df::viewscreen *); - DFHACK_EXPORT bool dwarfmode_hotkey(Core *, df::viewscreen *); - DFHACK_EXPORT bool cursor_hotkey(Core *, df::viewscreen *); + DFHACK_EXPORT bool default_hotkey(df::viewscreen *); + DFHACK_EXPORT bool dwarfmode_hotkey(df::viewscreen *); + DFHACK_EXPORT bool cursor_hotkey(df::viewscreen *); } }; diff --git a/library/include/TileTypes.h b/library/include/TileTypes.h index 318aa2b8e..835be2398 100644 --- a/library/include/TileTypes.h +++ b/library/include/TileTypes.h @@ -24,9 +24,6 @@ distribution. #pragma once -#ifndef TILETYPES_H_INCLUDED -#define TILETYPES_H_INCLUDED - #include "Pragma.h" #include "Export.h" #include "DataDefs.h" @@ -276,4 +273,3 @@ namespace DFHack DFHACK_EXPORT df::tiletype findRandomVariant(const df::tiletype tile); } -#endif // TILETYPES_H_INCLUDED diff --git a/library/include/modules/Gui.h b/library/include/modules/Gui.h index 59d1e789e..6ffe7b8ed 100644 --- a/library/include/modules/Gui.h +++ b/library/include/modules/Gui.h @@ -27,6 +27,7 @@ distribution. #include "Module.h" #include "Virtual.h" #include "BitArray.h" +#include "ColorText.h" #include #include "DataDefs.h" @@ -56,37 +57,37 @@ namespace DFHack namespace Gui { // Full-screen item details view - DFHACK_EXPORT bool item_details_hotkey(Core *, df::viewscreen *top); + DFHACK_EXPORT bool item_details_hotkey(df::viewscreen *top); // 'u'nits or 'j'obs full-screen view - DFHACK_EXPORT bool unitjobs_hotkey(Core *, df::viewscreen *top); + DFHACK_EXPORT bool unitjobs_hotkey(df::viewscreen *top); // A job is selected in a workshop - DFHACK_EXPORT bool workshop_job_hotkey(Core *c, df::viewscreen *top); + DFHACK_EXPORT bool workshop_job_hotkey(df::viewscreen *top); // Building material selection mode - DFHACK_EXPORT bool build_selector_hotkey(Core *c, df::viewscreen *top); + DFHACK_EXPORT bool build_selector_hotkey(df::viewscreen *top); // A unit is selected in the 'v' mode - DFHACK_EXPORT bool view_unit_hotkey(Core *c, df::viewscreen *top); + DFHACK_EXPORT bool view_unit_hotkey(df::viewscreen *top); // Above + the inventory page is selected. - DFHACK_EXPORT bool unit_inventory_hotkey(Core *c, df::viewscreen *top); + DFHACK_EXPORT bool unit_inventory_hotkey(df::viewscreen *top); // In workshop_job_hotkey, returns the job - DFHACK_EXPORT df::job *getSelectedWorkshopJob(Core *c, bool quiet = false); + DFHACK_EXPORT df::job *getSelectedWorkshopJob(color_ostream &out, bool quiet = false); // A job is selected in a workshop, or unitjobs - DFHACK_EXPORT bool any_job_hotkey(Core *c, df::viewscreen *top); - DFHACK_EXPORT df::job *getSelectedJob(Core *c, bool quiet = false); + DFHACK_EXPORT bool any_job_hotkey(df::viewscreen *top); + DFHACK_EXPORT df::job *getSelectedJob(color_ostream &out, bool quiet = false); // A unit is selected via 'v', 'k', unitjobs, or // a full-screen item view of a cage or suchlike - DFHACK_EXPORT bool any_unit_hotkey(Core *c, df::viewscreen *top); - DFHACK_EXPORT df::unit *getSelectedUnit(Core *c, bool quiet = false); + DFHACK_EXPORT bool any_unit_hotkey(df::viewscreen *top); + DFHACK_EXPORT df::unit *getSelectedUnit(color_ostream &out, bool quiet = false); // An item is selected via 'v'->inventory, 'k', 't', or // a full-screen item view of a container. Note that in the // last case, the highlighted contained item is returned, not // the container itself. - DFHACK_EXPORT bool any_item_hotkey(Core *c, df::viewscreen *top); - DFHACK_EXPORT df::item *getSelectedItem(Core *c, bool quiet = false); + DFHACK_EXPORT bool any_item_hotkey(df::viewscreen *top); + DFHACK_EXPORT df::item *getSelectedItem(color_ostream &out, bool quiet = false); // Show a plain announcement, or a titan-style popup message DFHACK_EXPORT void showAnnouncement(std::string message, int color = 7, bool bright = true); diff --git a/library/include/modules/Job.h b/library/include/modules/Job.h index 5534a9d4f..8a82958ee 100644 --- a/library/include/modules/Job.h +++ b/library/include/modules/Job.h @@ -49,7 +49,7 @@ namespace DFHack DFHACK_EXPORT bool operator== (const df::job_item &a, const df::job_item &b); DFHACK_EXPORT bool operator== (const df::job &a, const df::job &b); - DFHACK_EXPORT void printJobDetails(Core *c, df::job *job); + DFHACK_EXPORT void printJobDetails(color_ostream &out, df::job *job); DFHACK_EXPORT df::building *getJobHolder(df::job *job); diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h index d67000048..67e2aac89 100644 --- a/library/include/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -272,6 +272,9 @@ extern DFHACK_EXPORT void getPosition(int32_t& x, int32_t& y, int32_t& z); extern DFHACK_EXPORT df::map_block * getBlock (int32_t blockx, int32_t blocky, int32_t blockz); extern DFHACK_EXPORT df::map_block * getBlockAbs (int32_t x, int32_t y, int32_t z); +inline df::map_block * getBlock (df::coord pos) { return getBlock(pos.x, pos.y, pos.z); } +inline df::map_block * getBlockAbs (df::coord pos) { return getBlockAbs(pos.x, pos.y, pos.z); } + /// copy the whole map block at block coords (see DFTypes.h for the block structure) extern DFHACK_EXPORT bool ReadBlock40d(uint32_t blockx, uint32_t blocky, uint32_t blockz, mapblock40d * buffer); diff --git a/library/include/modules/Windows.h b/library/include/modules/Windows.h new file mode 100644 index 000000000..314b6e292 --- /dev/null +++ b/library/include/modules/Windows.h @@ -0,0 +1,270 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#pragma once +#include "Export.h" +#include + +namespace DFHack +{ +namespace Windows +{ + /* + * DF window stuffs + */ + enum df_color + { + black, + blue, + green, + cyan, + red, + magenta, + brown, + lgray, + dgray, + lblue, + lgreen, + lcyan, + lred, + lmagenta, + yellow, + white + // maybe add transparency? + }; + + // The tile format DF uses internally + struct df_screentile + { + uint8_t symbol; + uint8_t foreground; ///< df_color + uint8_t background; ///< df_color + uint8_t bright; + }; + + + // our silly painter things and window things follow. + class df_window; + struct df_tilebuf + { + df_screentile * data; + unsigned int width; + unsigned int height; + }; + + DFHACK_EXPORT df_screentile *getScreenBuffer(); + + class DFHACK_EXPORT painter + { + friend class df_window; + public: + df_screentile* get(unsigned int x, unsigned int y) + { + if(x >= width || y >= height) + return 0; + return &buffer[x*height + y]; + }; + bool set(unsigned int x, unsigned int y, df_screentile tile ) + { + if(x >= width || y >= height) + return false; + buffer[x*height + y] = tile; + return true; + } + df_color foreground (df_color change = (df_color) -1) + { + if(change != -1) + current_foreground = change; + return current_foreground; + } + df_color background (df_color change = (df_color) -1) + { + if(change != -1) + current_background = change; + return current_background; + } + void bright (bool change) + { + current_bright = change; + } + bool bright () + { + return current_bright; + } + void printStr(std::string & str, bool wrap = false) + { + for ( auto iter = str.begin(); iter != str.end(); iter++) + { + auto elem = *iter; + if(cursor_y >= height) + break; + if(wrap) + { + if(cursor_x >= width) + cursor_x = wrap_column; + } + df_screentile & tile = buffer[cursor_x * height + cursor_y]; + tile.symbol = elem; + tile.foreground = current_foreground; + tile.background = current_background; + tile.bright = current_bright; + cursor_x++; + } + } + void set_wrap (int new_column) + { + wrap_column = new_column; + } + void gotoxy(unsigned int x, unsigned int y) + { + cursor_x = x; + cursor_y = y; + } + void reset() + { + cursor_x = 0; + cursor_y = 0; + current_background = black; + current_foreground = white; + current_bright = false; + wrap_column = 0; + } + private: + painter (df_window * orig, df_screentile * buf, unsigned int width, unsigned int height) + { + origin = orig; + this->width = width; + this->height = height; + this->buffer = buf; + reset(); + } + df_window* origin; + unsigned int width; + unsigned int height; + df_screentile* buffer; + // current paint cursor position + int cursor_x; + int cursor_y; + int wrap_column; + // current foreground color + df_color current_foreground; + // current background color + df_color current_background; + // make bright? + bool current_bright; + }; + + class DFHACK_EXPORT df_window + { + friend class painter; + public: + df_window(int x, int y, unsigned int width, unsigned int height); + virtual ~df_window(); + virtual bool move (int left_, int top_, unsigned int width_, unsigned int height_) = 0; + virtual void paint () = 0; + virtual painter * lock(); + bool unlock (painter * painter); + virtual bool addChild(df_window *); + virtual df_tilebuf getBuffer() = 0; + public: + df_screentile* buffer; + unsigned int width; + unsigned int height; + protected: + df_window * parent; + std::vector children; + int left; + int top; + // FIXME: FAKE + bool locked; + painter * current_painter; + }; + + class DFHACK_EXPORT top_level_window : public df_window + { + public: + top_level_window(); + virtual bool move (int left_, int top_, unsigned int width_, unsigned int height_); + virtual void paint (); + virtual painter * lock(); + virtual df_tilebuf getBuffer(); + }; + class DFHACK_EXPORT buffered_window : public df_window + { + public: + buffered_window(int x, int y, unsigned int width, unsigned int height):df_window(x,y,width, height) + { + buffer = new df_screentile[width*height]; + }; + virtual ~buffered_window() + { + delete buffer; + } + virtual void blit_to_parent () + { + df_tilebuf par = parent->getBuffer(); + for(int xi = 0; xi < width; xi++) + { + for(int yi = 0; yi < height; yi++) + { + int parx = left + xi; + int pary = top + yi; + if(pary >= par.height) continue; + if(parx >= par.width) continue; + par.data[parx * par.height + pary] = buffer[xi * height + yi]; + } + } + } + virtual df_tilebuf getBuffer() + { + df_tilebuf buf; + buf.data = buffer; + buf.width = width; + buf.height = height; + return buf; + }; + }; + class DFHACK_EXPORT dfhack_dummy : public buffered_window + { + public: + dfhack_dummy(int x, int y):buffered_window(x,y,6,1){}; + virtual bool move (int left_, int top_, unsigned int width_, unsigned int height_) + { + top = top_; + left = left_; + return true; + } + virtual void paint () + { + painter * p = lock(); + p->bright(true); + p->background(black); + p->foreground(white); + std::string dfhack = "DFHack"; + p->printStr(dfhack); + blit_to_parent(); + } + }; +} +} \ No newline at end of file diff --git a/library/include/modules/kitchen.h b/library/include/modules/kitchen.h index ea9dec14d..f9d9d3458 100644 --- a/library/include/modules/kitchen.h +++ b/library/include/modules/kitchen.h @@ -58,7 +58,7 @@ const t_exclusionType limitExclusion = 4; // used to store limit as an entry in */ // print the exclusion list, with the material index also translated into its token (for organics) - for debug really -DFHACK_EXPORT void debug_print(Core &); +DFHACK_EXPORT void debug_print(color_ostream &out); // remove this material from the exclusion list if it is in it DFHACK_EXPORT void allowPlantSeedCookery(t_materialIndex materialIndex); diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp index ec43dc766..6317f3e10 100644 --- a/library/modules/Buildings.cpp +++ b/library/modules/Buildings.cpp @@ -74,18 +74,14 @@ bool Buildings::Read (const uint32_t index, t_building & building) bool Buildings::ReadCustomWorkshopTypes(map & btypes) { - Core & c = Core::getInstance(); - vector & bld_def = world->raws.buildings.all; uint32_t size = bld_def.size(); btypes.clear(); - c.con.print("Probing vector at 0x%x for custom workshops.\n", &bld_def); for (auto iter = bld_def.begin(); iter != bld_def.end();iter++) { building_def * temp = *iter; btypes[temp->id] = temp->code; - c.con.print("%d : %s\n",temp->id, temp->code.c_str()); } return true; } diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index ef3e84901..f70d60d2a 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -45,6 +45,7 @@ using namespace DFHack; #include "df/world.h" #include "df/global_objects.h" #include "df/viewscreen_dwarfmodest.h" +#include "df/viewscreen_dungeonmodest.h" #include "df/viewscreen_joblistst.h" #include "df/viewscreen_unitlistst.h" #include "df/viewscreen_itemst.h" @@ -69,37 +70,41 @@ using df::global::gps; // Predefined common guard functions -bool Gui::default_hotkey(Core *, df::viewscreen *top) +bool Gui::default_hotkey(df::viewscreen *top) { // Default hotkey guard function for (;top ;top = top->parent) + { if (strict_virtual_cast(top)) return true; + if (strict_virtual_cast(top)) + return true; + } return false; } -bool Gui::dwarfmode_hotkey(Core *, df::viewscreen *top) +bool Gui::dwarfmode_hotkey(df::viewscreen *top) { // Require the main dwarf mode screen return !!strict_virtual_cast(top); } -bool Gui::unitjobs_hotkey(Core *, df::viewscreen *top) +bool Gui::unitjobs_hotkey(df::viewscreen *top) { // Require the unit or jobs list return !!strict_virtual_cast(top) || !!strict_virtual_cast(top); } -bool Gui::item_details_hotkey(Core *, df::viewscreen *top) +bool Gui::item_details_hotkey(df::viewscreen *top) { // Require the main dwarf mode screen return !!strict_virtual_cast(top); } -bool Gui::cursor_hotkey(Core *c, df::viewscreen *top) +bool Gui::cursor_hotkey(df::viewscreen *top) { - if (!dwarfmode_hotkey(c, top)) + if (!dwarfmode_hotkey(top)) return false; // Also require the cursor. @@ -109,7 +114,7 @@ bool Gui::cursor_hotkey(Core *c, df::viewscreen *top) return true; } -bool Gui::workshop_job_hotkey(Core *c, df::viewscreen *top) +bool Gui::workshop_job_hotkey(df::viewscreen *top) { using namespace ui_sidebar_mode; using df::global::ui; @@ -117,7 +122,7 @@ bool Gui::workshop_job_hotkey(Core *c, df::viewscreen *top) using df::global::ui_workshop_in_add; using df::global::ui_workshop_job_cursor; - if (!dwarfmode_hotkey(c,top)) + if (!dwarfmode_hotkey(top)) return false; switch (ui->main.mode) { @@ -147,13 +152,13 @@ bool Gui::workshop_job_hotkey(Core *c, df::viewscreen *top) } } -bool Gui::build_selector_hotkey(Core *c, df::viewscreen *top) +bool Gui::build_selector_hotkey(df::viewscreen *top) { using namespace ui_sidebar_mode; using df::global::ui; using df::global::ui_build_selector; - if (!dwarfmode_hotkey(c,top)) + if (!dwarfmode_hotkey(top)) return false; switch (ui->main.mode) { @@ -175,13 +180,13 @@ bool Gui::build_selector_hotkey(Core *c, df::viewscreen *top) } } -bool Gui::view_unit_hotkey(Core *c, df::viewscreen *top) +bool Gui::view_unit_hotkey(df::viewscreen *top) { using df::global::ui; using df::global::world; using df::global::ui_selected_unit; - if (!dwarfmode_hotkey(c,top)) + if (!dwarfmode_hotkey(top)) return false; if (ui->main.mode != ui_sidebar_mode::ViewUnits) return false; @@ -191,11 +196,11 @@ bool Gui::view_unit_hotkey(Core *c, df::viewscreen *top) return vector_get(world->units.other[0], *ui_selected_unit) != NULL; } -bool Gui::unit_inventory_hotkey(Core *c, df::viewscreen *top) +bool Gui::unit_inventory_hotkey(df::viewscreen *top) { using df::global::ui_unit_view_mode; - if (!view_unit_hotkey(c,top)) + if (!view_unit_hotkey(top)) return false; if (!ui_unit_view_mode) return false; @@ -203,14 +208,14 @@ bool Gui::unit_inventory_hotkey(Core *c, df::viewscreen *top) return ui_unit_view_mode->value == df::ui_unit_view_mode::Inventory; } -df::job *Gui::getSelectedWorkshopJob(Core *c, bool quiet) +df::job *Gui::getSelectedWorkshopJob(color_ostream &out, bool quiet) { using df::global::world; using df::global::ui_workshop_job_cursor; - if (!workshop_job_hotkey(c, c->getTopViewscreen())) { + if (!workshop_job_hotkey(Core::getTopViewscreen())) { if (!quiet) - c->con.printerr("Not in a workshop, or no job is highlighted.\n"); + out.printerr("Not in a workshop, or no job is highlighted.\n"); return NULL; } @@ -219,14 +224,14 @@ df::job *Gui::getSelectedWorkshopJob(Core *c, bool quiet) if (idx < 0 || idx >= selected->jobs.size()) { - c->con.printerr("Invalid job cursor index: %d\n", idx); + out.printerr("Invalid job cursor index: %d\n", idx); return NULL; } return selected->jobs[idx]; } -bool Gui::any_job_hotkey(Core *c, df::viewscreen *top) +bool Gui::any_job_hotkey(df::viewscreen *top) { if (VIRTUAL_CAST_VAR(screen, df::viewscreen_joblistst, top)) return vector_get(screen->jobs, screen->cursor_pos) != NULL; @@ -234,19 +239,19 @@ bool Gui::any_job_hotkey(Core *c, df::viewscreen *top) if (VIRTUAL_CAST_VAR(screen, df::viewscreen_unitlistst, top)) return vector_get(screen->jobs[screen->page], screen->cursor_pos[screen->page]) != NULL; - return workshop_job_hotkey(c,top); + return workshop_job_hotkey(top); } -df::job *Gui::getSelectedJob(Core *c, bool quiet) +df::job *Gui::getSelectedJob(color_ostream &out, bool quiet) { - df::viewscreen *top = c->getTopViewscreen(); + df::viewscreen *top = Core::getTopViewscreen(); if (VIRTUAL_CAST_VAR(joblist, df::viewscreen_joblistst, top)) { df::job *job = vector_get(joblist->jobs, joblist->cursor_pos); if (!job && !quiet) - c->con.printerr("Selected unit has no job\n"); + out.printerr("Selected unit has no job\n"); return job; } @@ -256,15 +261,15 @@ df::job *Gui::getSelectedJob(Core *c, bool quiet) df::job *job = vector_get(unitlist->jobs[page], unitlist->cursor_pos[page]); if (!job && !quiet) - c->con.printerr("Selected unit has no job\n"); + out.printerr("Selected unit has no job\n"); return job; } else - return getSelectedWorkshopJob(c, quiet); + return getSelectedWorkshopJob(out, quiet); } -static df::unit *getAnyUnit(Core *c, df::viewscreen *top) +static df::unit *getAnyUnit(df::viewscreen *top) { using namespace ui_sidebar_mode; using df::global::ui; @@ -285,7 +290,7 @@ static df::unit *getAnyUnit(Core *c, df::viewscreen *top) return ref ? ref->getUnit() : NULL; } - if (!Gui::dwarfmode_hotkey(c,top)) + if (!Gui::dwarfmode_hotkey(top)) return NULL; switch (ui->main.mode) { @@ -312,22 +317,22 @@ static df::unit *getAnyUnit(Core *c, df::viewscreen *top) } } -bool Gui::any_unit_hotkey(Core *c, df::viewscreen *top) +bool Gui::any_unit_hotkey(df::viewscreen *top) { - return getAnyUnit(c, top) != NULL; + return getAnyUnit(top) != NULL; } -df::unit *Gui::getSelectedUnit(Core *c, bool quiet) +df::unit *Gui::getSelectedUnit(color_ostream &out, bool quiet) { - df::unit *unit = getAnyUnit(c, c->getTopViewscreen()); + df::unit *unit = getAnyUnit(Core::getTopViewscreen()); if (!unit && !quiet) - c->con.printerr("No unit is selected in the UI.\n"); + out.printerr("No unit is selected in the UI.\n"); return unit; } -static df::item *getAnyItem(Core *c, df::viewscreen *top) +static df::item *getAnyItem(df::viewscreen *top) { using namespace ui_sidebar_mode; using df::global::ui; @@ -344,7 +349,7 @@ static df::item *getAnyItem(Core *c, df::viewscreen *top) return ref ? ref->getItem() : NULL; } - if (!Gui::dwarfmode_hotkey(c,top)) + if (!Gui::dwarfmode_hotkey(top)) return NULL; switch (ui->main.mode) { @@ -387,17 +392,17 @@ static df::item *getAnyItem(Core *c, df::viewscreen *top) } } -bool Gui::any_item_hotkey(Core *c, df::viewscreen *top) +bool Gui::any_item_hotkey(df::viewscreen *top) { - return getAnyItem(c, top) != NULL; + return getAnyItem(top) != NULL; } -df::item *Gui::getSelectedItem(Core *c, bool quiet) +df::item *Gui::getSelectedItem(color_ostream &out, bool quiet) { - df::item *item = getAnyItem(c, c->getTopViewscreen()); + df::item *item = getAnyItem(Core::getTopViewscreen()); if (!item && !quiet) - c->con.printerr("No item is selected in the UI.\n"); + out.printerr("No item is selected in the UI.\n"); return item; } @@ -489,7 +494,6 @@ bool Gui::getViewCoords (int32_t &x, int32_t &y, int32_t &z) bool Gui::setViewCoords (const int32_t x, const int32_t y, const int32_t z) { - auto cursor = df::global::cursor; (*df::global::window_x) = x; (*df::global::window_y) = y; (*df::global::window_z) = z; diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index d03f7d8ba..be83c3c49 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -382,7 +382,7 @@ bool ItemTypeInfo::matches(const df::job_item &item, MaterialInfo *mat) if ((item_ok1.whole & ~item_mask1.whole) || (item_ok2.whole & ~item_mask2.whole) || (item_ok3.whole & ~item_mask3.whole)) - Core::getInstance().con.printerr("ItemTypeInfo.matches inconsistent\n"); + Core::printerr("ItemTypeInfo.matches inconsistent\n"); #undef OK #undef RQ diff --git a/library/modules/Job.cpp b/library/modules/Job.cpp index 3a6b25d1a..d1ca7923c 100644 --- a/library/modules/Job.cpp +++ b/library/modules/Job.cpp @@ -139,48 +139,48 @@ bool DFHack::operator== (const df::job &a, const df::job &b) return true; } -static void print_job_item_details(Core *c, df::job *job, unsigned idx, df::job_item *item) +static void print_job_item_details(color_ostream &out, df::job *job, unsigned idx, df::job_item *item) { ItemTypeInfo info(item); - c->con << " Input Item " << (idx+1) << ": " << info.toString(); + out << " Input Item " << (idx+1) << ": " << info.toString(); if (item->quantity != 1) - c->con << "; quantity=" << item->quantity; + out << "; quantity=" << item->quantity; if (item->min_dimension >= 0) - c->con << "; min_dimension=" << item->min_dimension; - c->con << endl; + out << "; min_dimension=" << item->min_dimension; + out << endl; MaterialInfo mat(item); if (mat.isValid() || item->metal_ore >= 0) { - c->con << " material: " << mat.toString(); + out << " material: " << mat.toString(); if (item->metal_ore >= 0) - c->con << "; ore of " << MaterialInfo(0,item->metal_ore).toString(); - c->con << endl; + out << "; ore of " << MaterialInfo(0,item->metal_ore).toString(); + out << endl; } if (item->flags1.whole) - c->con << " flags1: " << bitfieldToString(item->flags1) << endl; + out << " flags1: " << bitfieldToString(item->flags1) << endl; if (item->flags2.whole) - c->con << " flags2: " << bitfieldToString(item->flags2) << endl; + out << " flags2: " << bitfieldToString(item->flags2) << endl; if (item->flags3.whole) - c->con << " flags3: " << bitfieldToString(item->flags3) << endl; + out << " flags3: " << bitfieldToString(item->flags3) << endl; if (!item->reaction_class.empty()) - c->con << " reaction class: " << item->reaction_class << endl; + out << " reaction class: " << item->reaction_class << endl; if (!item->has_material_reaction_product.empty()) - c->con << " reaction product: " << item->has_material_reaction_product << endl; + out << " reaction product: " << item->has_material_reaction_product << endl; if (item->has_tool_use >= 0) - c->con << " tool use: " << ENUM_KEY_STR(tool_uses, item->has_tool_use) << endl; + out << " tool use: " << ENUM_KEY_STR(tool_uses, item->has_tool_use) << endl; } -void DFHack::printJobDetails(Core *c, df::job *job) +void DFHack::printJobDetails(color_ostream &out, df::job *job) { - c->con.color(job->flags.bits.suspend ? Console::COLOR_DARKGREY : Console::COLOR_GREY); - c->con << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type); + out.color(job->flags.bits.suspend ? Console::COLOR_DARKGREY : Console::COLOR_GREY); + out << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type); if (job->flags.whole) - c->con << " (" << bitfieldToString(job->flags) << ")"; - c->con << endl; - c->con.reset_color(); + out << " (" << bitfieldToString(job->flags) << ")"; + out << endl; + out.reset_color(); df::item_type itype = ENUM_ATTR(job_type, item, job->job_type); @@ -190,28 +190,28 @@ void DFHack::printJobDetails(Core *c, df::job *job) if (mat.isValid() || job->material_category.whole) { - c->con << " material: " << mat.toString(); + out << " material: " << mat.toString(); if (job->material_category.whole) - c->con << " (" << bitfieldToString(job->material_category) << ")"; - c->con << endl; + out << " (" << bitfieldToString(job->material_category) << ")"; + out << endl; } if (job->item_subtype >= 0 || job->item_category.whole) { ItemTypeInfo iinfo(itype, job->item_subtype); - c->con << " item: " << iinfo.toString() + out << " item: " << iinfo.toString() << " (" << bitfieldToString(job->item_category) << ")" << endl; } if (job->hist_figure_id >= 0) - c->con << " figure: " << job->hist_figure_id << endl; + out << " figure: " << job->hist_figure_id << endl; if (!job->reaction_name.empty()) - c->con << " reaction: " << job->reaction_name << endl; + out << " reaction: " << job->reaction_name << endl; for (size_t i = 0; i < job->job_items.size(); i++) - print_job_item_details(c, job, i, job->job_items[i]); + print_job_item_details(out, job, i, job->job_items[i]); } df::building *DFHack::getJobHolder(df::job *job) diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 48c8d7709..32c9ac60b 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -200,7 +200,6 @@ bool Maps::WriteDirtyBit(uint32_t x, uint32_t y, uint32_t z, bool dirtybit) } return false; } -/* /* * Block flags */ diff --git a/library/modules/Windows.cpp b/library/modules/Windows.cpp new file mode 100644 index 000000000..6fbe37125 --- /dev/null +++ b/library/modules/Windows.cpp @@ -0,0 +1,118 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "Export.h" +#include "Module.h" +#include "Virtual.h" +#include "BitArray.h" +#include + +#include "DataDefs.h" +#include "df/init.h" +#include "df/ui.h" +#include +#include +#include "modules/Windows.h" + +using namespace DFHack; + +Windows::df_screentile *Windows::getScreenBuffer() +{ + return (df_screentile *) df::global::gps->screen; +} + +Windows::df_window::df_window(int x, int y, unsigned int width, unsigned int height) +:buffer(0), parent(0), left(x), top(y), width(width), height(height), current_painter(NULL) +{ + buffer = 0; +}; +Windows::df_window::~df_window() +{ + for(auto iter = children.begin();iter != children.end();iter++) + { + delete *iter; + } + children.clear(); +}; +Windows::painter * Windows::df_window::lock() +{ + locked = true; + current_painter = new Windows::painter(this,buffer,width, height); + return current_painter; +}; + +bool Windows::df_window::addChild( df_window * child) +{ + children.push_back(child); + child->parent = this; + return true; +} + +bool Windows::df_window::unlock (painter * painter) +{ + if(current_painter == painter) + { + delete current_painter; + current_painter = 0; + locked = false; + return true; + } + return false; +} + +Windows::top_level_window::top_level_window(): df_window(0,0,df::global::gps->dimx,df::global::gps->dimy) +{ + buffer = 0; +} + +bool Windows::top_level_window::move (int left_, int top_, unsigned int width_, unsigned int height_) +{ + width = width_; + height = height_; + // what if we are painting already? Is that possible? + return true; +}; + +Windows::painter * Windows::top_level_window::lock() +{ + buffer = getScreenBuffer(); + return df_window::lock(); +} + +void Windows::top_level_window::paint () +{ + for(auto iter = children.begin();iter != children.end();iter++) + { + (*iter)->paint(); + } +}; + +Windows::df_tilebuf Windows::top_level_window::getBuffer() +{ + df_tilebuf buf; + buf.data = getScreenBuffer(); + buf.height = df::global::gps->dimy; + buf.width = df::global::gps->dimx; + return buf; +} \ No newline at end of file diff --git a/library/modules/kitchen.cpp b/library/modules/kitchen.cpp index 88ed3a42d..4300d63df 100644 --- a/library/modules/kitchen.cpp +++ b/library/modules/kitchen.cpp @@ -28,12 +28,12 @@ using namespace df::enums; using df::global::world; using df::global::ui; -void Kitchen::debug_print(Core &core) +void Kitchen::debug_print(color_ostream &out) { - core.con.print("Kitchen Exclusions\n"); + out.print("Kitchen Exclusions\n"); for(std::size_t i = 0; i < size(); ++i) { - core.con.print("%2u: IT:%2i IS:%i MT:%3i MI:%2i ET:%i %s\n", + out.print("%2u: IT:%2i IS:%i MT:%3i MI:%2i ET:%i %s\n", i, ui->kitchen.item_types[i], ui->kitchen.item_subtypes[i], @@ -43,7 +43,7 @@ void Kitchen::debug_print(Core &core) (ui->kitchen.mat_types[i] >= 419 && ui->kitchen.mat_types[i] <= 618) ? world->raws.plants.all[ui->kitchen.mat_indices[i]]->id.c_str() : "n/a" ); } - core.con.print("\n"); + out.print("\n"); } void Kitchen::allowPlantSeedCookery(t_materialIndex materialIndex) diff --git a/library/proto/.gitignore b/library/proto/.gitignore new file mode 100644 index 000000000..a1fb10cce --- /dev/null +++ b/library/proto/.gitignore @@ -0,0 +1,2 @@ +*.pb.cc +*.pb.h diff --git a/library/proto/CoreProtocol.proto b/library/proto/CoreProtocol.proto new file mode 100644 index 000000000..33ec0f4a0 --- /dev/null +++ b/library/proto/CoreProtocol.proto @@ -0,0 +1,59 @@ +package dfproto; + +option optimize_for = LITE_RUNTIME; + +message CoreTextFragment { + required string text = 1; + + enum Color { + COLOR_BLACK = 0; + COLOR_BLUE = 1; + COLOR_GREEN = 2; + COLOR_CYAN = 3; + COLOR_RED = 4; + COLOR_MAGENTA = 5; + COLOR_BROWN = 6; + COLOR_GREY = 7; + COLOR_DARKGREY = 8; + COLOR_LIGHTBLUE = 9; + COLOR_LIGHTGREEN = 10; + COLOR_LIGHTCYAN = 11; + COLOR_LIGHTRED = 12; + COLOR_LIGHTMAGENTA = 13; + COLOR_YELLOW = 14; + COLOR_WHITE = 15; + }; + optional Color color = 2; +} + +message CoreTextNotification { + repeated CoreTextFragment fragments = 1; +} + +message CoreErrorNotification { + enum ErrorCode { + CR_WOULD_BREAK = -2; + CR_NOT_IMPLEMENTED = -1; + CR_FAILURE = 0; + CR_OK = 1; + CR_WRONG_USAGE = 2; + }; + + required ErrorCode code = 1; +} + +message CoreBindRequest { + required string method = 1; + optional string plugin = 2; + optional int32 min_version = 3; +} + +message CoreBindReply { + required int32 assigned_id = 1; + required int32 version = 2; +} + +message CoreRunStringRequest { + required string command = 1; + repeated string arguments = 2; +} diff --git a/library/xml b/library/xml index cd7c4b1c8..24e809abe 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit cd7c4b1c8f6a73a9ed7cdf04b65ee2a75910202c +Subproject commit 24e809abe07eb139c9f53c358ed3fbd3d8075410 diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index f04726a44..09c0b298d 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -79,6 +79,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(follow follow.cpp) DFHACK_PLUGIN(changevein changevein.cpp) DFHACK_PLUGIN(advtools advtools.cpp) + DFHACK_PLUGIN(tweak tweak.cpp) #DFHACK_PLUGIN(versionosd versionosd.cpp) endif() diff --git a/plugins/advtools.cpp b/plugins/advtools.cpp index 15a7cad92..deaee4856 100644 --- a/plugins/advtools.cpp +++ b/plugins/advtools.cpp @@ -6,6 +6,7 @@ #include "modules/World.h" #include "modules/Translation.h" #include "modules/Materials.h" +#include "modules/Maps.h" #include "modules/Items.h" #include "DataDefs.h" @@ -19,6 +20,8 @@ #include "df/historical_figure.h" #include "df/general_ref_is_nemesisst.h" #include "df/general_ref_contains_itemst.h" +#include "df/general_ref_contained_in_itemst.h" +#include "df/general_ref_unit_holderst.h" #include "df/general_ref_building_civzone_assignedst.h" #include "df/material.h" #include "df/craft_material_class.h" @@ -43,14 +46,14 @@ using namespace DFHack::Translation; * PLUGIN INTERFACE * *********************/ -static bool bodyswap_hotkey(Core *c, df::viewscreen *top); +static bool bodyswap_hotkey(df::viewscreen *top); -command_result adv_bodyswap (Core * c, std::vector & parameters); -command_result adv_tools (Core * c, std::vector & parameters); +command_result adv_bodyswap (color_ostream &out, std::vector & parameters); +command_result adv_tools (color_ostream &out, std::vector & parameters); DFHACK_PLUGIN("advtools"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) { commands.clear(); @@ -88,16 +91,16 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -df::nemesis_record *getPlayerNemesis(Core *c, bool restore_swap); +df::nemesis_record *getPlayerNemesis(color_ostream &out, bool restore_swap); static bool in_transient_swap = false; -DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event event) +DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) { switch (event) { case SC_GAME_LOADED: @@ -110,12 +113,12 @@ DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event ev return CR_OK; } -DFhackCExport command_result plugin_onupdate ( Core * c ) +DFhackCExport command_result plugin_onupdate ( color_ostream &out ) { // Revert transient swaps before trouble happens if (in_transient_swap) { - auto screen = c->getTopViewscreen(); + auto screen = Core::getTopViewscreen(); bool revert = false; if (strict_virtual_cast(screen)) @@ -140,7 +143,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) if (revert) { - getPlayerNemesis(c, true); + getPlayerNemesis(out, true); in_transient_swap = false; } } @@ -152,15 +155,15 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) * UTILITY FUNCTIONS * *********************/ -static bool bodyswap_hotkey(Core *c, df::viewscreen *top) +static bool bodyswap_hotkey(df::viewscreen *top) { return !!virtual_cast(top) || !!virtual_cast(top); } -df::unit *getCurUnit(Core *c) +df::unit *getCurUnit() { - auto top = c->getTopViewscreen(); + auto top = Core::getTopViewscreen(); if (VIRTUAL_CAST_VAR(ms, df::viewscreen_dungeon_monsterstatusst, top)) return ms->unit; @@ -183,11 +186,11 @@ df::nemesis_record *getNemesis(df::unit *unit) return NULL; } -bool bodySwap(Core *c, df::unit *player) +bool bodySwap(color_ostream &out, df::unit *player) { if (!player) { - c->con.printerr("Unit to swap is NULL\n"); + out.printerr("Unit to swap is NULL\n"); return false; } @@ -196,7 +199,7 @@ bool bodySwap(Core *c, df::unit *player) int idx = linear_index(vec, player); if (idx < 0) { - c->con.printerr("Unit to swap not found: %d\n", player->id); + out.printerr("Unit to swap not found: %d\n", player->id); return false; } @@ -206,12 +209,12 @@ bool bodySwap(Core *c, df::unit *player) return true; } -df::nemesis_record *getPlayerNemesis(Core *c, bool restore_swap) +df::nemesis_record *getPlayerNemesis(color_ostream &out, bool restore_swap) { auto real_nemesis = vector_get(world->nemesis.all, ui_advmode->player_id); if (!real_nemesis || !real_nemesis->unit) { - c->con.printerr("Invalid player nemesis id: %d\n", ui_advmode->player_id); + out.printerr("Invalid player nemesis id: %d\n", ui_advmode->player_id); return NULL; } @@ -222,11 +225,11 @@ df::nemesis_record *getPlayerNemesis(Core *c, bool restore_swap) if (ctl_nemesis != real_nemesis) { - if (!bodySwap(c, real_nemesis->unit)) + if (!bodySwap(out, real_nemesis->unit)) return NULL; auto name = TranslateName(&real_nemesis->unit->name, false); - c->con.print("Returned into the body of %s.\n", name.c_str()); + out.print("Returned into the body of %s.\n", name.c_str()); } real_nemesis->unit->relations.group_leader_id = -1; @@ -315,9 +318,9 @@ void sortCompanionNemesis(std::vector *list, int player_id = -1 list->swap(output); } -void listCompanions(Core *c, std::vector *list, bool units = true) +void listCompanions(color_ostream &out, std::vector *list, bool units = true) { - nemesis_record *player = getPlayerNemesis(c, false); + nemesis_record *player = getPlayerNemesis(out, false); if (!player) return; @@ -421,7 +424,7 @@ bool isWeaponArmor(df::item *item) } } -int containsMetalItems(df::item *item, bool all, bool non_trader) +int containsMetalItems(df::item *item, bool all, bool non_trader, bool rec = false) { int cnt = 0; @@ -429,13 +432,19 @@ int containsMetalItems(df::item *item, bool all, bool non_trader) for (size_t i = 0; i < refs.size(); i++) { auto ref = refs[i]; - if (!strict_virtual_cast(ref)) - continue; - df::item *child = ref->getItem(); - if (!child) continue; + if (strict_virtual_cast(ref)) + return 0; + if (!rec && strict_virtual_cast(ref)) + return 0; + + if (strict_virtual_cast(ref)) + { + df::item *child = ref->getItem(); + if (!child) continue; - cnt += containsMetalItems(child, all, non_trader); + cnt += containsMetalItems(child, all, non_trader, true); + } } if (!non_trader && !isShopItem(item)) @@ -476,23 +485,23 @@ void joinCounts(std::map &counts) * FORMATTING * *********************/ -static void printCompanionHeader(Core *c, size_t i, df::unit *unit) +static void printCompanionHeader(color_ostream &out, size_t i, df::unit *unit) { - c->con.color(Console::COLOR_GREY); + out.color(Console::COLOR_GREY); if (i < 28) - c->con << char('a'+i); + out << char('a'+i); else - c->con << i; + out << i; - c->con << ": " << getUnitNameProfession(unit); + out << ": " << getUnitNameProfession(unit); if (unit->flags1.bits.dead) - c->con << " (DEAD)"; + out << " (DEAD)"; if (unit->flags3.bits.ghostly) - c->con << " (GHOST)"; - c->con << endl; + out << " (GHOST)"; + out << endl; - c->con.reset_color(); + out.reset_color(); } static size_t formatSize(std::vector *out, const std::map in, size_t *cnt) @@ -551,7 +560,7 @@ static std::string formatDirection(df::coord delta) return stl_sprintf("%d away %s %+d", dist, dir.c_str(), delta.z); } -static void printEquipped(Core *c, df::unit *unit, bool all) +static void printEquipped(color_ostream &out, df::unit *unit, bool all) { std::vector items; listUnitInventory(&items, unit); @@ -627,10 +636,10 @@ static void printEquipped(Core *c, df::unit *unit, bool all) for (int j = 0; j < 4; j++) { size_t sz = std::max(sizes[j], size_t(18)); - c->con << "| " << std::left << std::setw(sz) << vector_get(cols[j],i) << " "; + out << "| " << std::left << std::setw(sz) << vector_get(cols[j],i) << " "; } - c->con << "|" << std::endl; + out << "|" << std::endl; } } @@ -638,7 +647,7 @@ static void printEquipped(Core *c, df::unit *unit, bool all) * COMMANDS * *********************/ -command_result adv_bodyswap (Core * c, std::vector & parameters) +command_result adv_bodyswap (color_ostream &out, std::vector & parameters) { // HOTKEY COMMAND; CORE IS SUSPENDED bool force = false; @@ -660,19 +669,19 @@ command_result adv_bodyswap (Core * c, std::vector & parameters) } // Get the real player; undo previous transient swap - auto real_nemesis = getPlayerNemesis(c, true); + auto real_nemesis = getPlayerNemesis(out, true); if (!real_nemesis) return CR_FAILURE; // Get the unit to swap to - auto new_unit = getCurUnit(c); + auto new_unit = getCurUnit(); auto new_nemesis = getNemesis(new_unit); if (!new_nemesis) { if (new_unit) { - c->con.printerr("Cannot swap into a non-historical unit.\n"); + out.printerr("Cannot swap into a non-historical unit.\n"); return CR_FAILURE; } @@ -685,16 +694,16 @@ command_result adv_bodyswap (Core * c, std::vector & parameters) // Verify it's a companion if (!force && linear_index(real_nemesis->companions, new_nemesis->id) < 0) { - c->con.printerr("This is not your companion - use force to bodyswap.\n"); + out.printerr("This is not your companion - use force to bodyswap.\n"); return CR_FAILURE; } // Swap - if (!bodySwap(c, new_nemesis->unit)) + if (!bodySwap(out, new_nemesis->unit)) return CR_FAILURE; auto name = TranslateName(&new_nemesis->unit->name, false); - c->con.print("Swapped into the body of %s.\n", name.c_str()); + out.print("Swapped into the body of %s.\n", name.c_str()); // Permanently re-link everything if (permanent) @@ -730,12 +739,12 @@ command_result adv_bodyswap (Core * c, std::vector & parameters) return CR_OK; } -command_result adv_tools (Core * c, std::vector & parameters) +command_result adv_tools (color_ostream &out, std::vector & parameters) { if (parameters.empty()) return CR_WRONG_USAGE; - CoreSuspender suspend(c); + CoreSuspender suspend; const auto &command = parameters[0]; if (command == "list-equipped") @@ -751,7 +760,7 @@ command_result adv_tools (Core * c, std::vector & parameters) std::vector list; - listCompanions(c, &list); + listCompanions(out, &list); sortCompanionNemesis(&list); for (size_t i = 0; i < list.size(); i++) @@ -759,8 +768,8 @@ command_result adv_tools (Core * c, std::vector & parameters) auto item = list[i]; auto unit = item->unit; - printCompanionHeader(c, i, unit); - printEquipped(c, unit, all); + printCompanionHeader(out, i, unit); + printEquipped(out, unit, all); } return CR_OK; @@ -778,7 +787,7 @@ command_result adv_tools (Core * c, std::vector & parameters) return CR_WRONG_USAGE; } - auto *player = getPlayerNemesis(c, false); + auto *player = getPlayerNemesis(out, false); if (!player) return CR_FAILURE; @@ -787,41 +796,39 @@ command_result adv_tools (Core * c, std::vector & parameters) int total = 0; std::map counts; - for (size_t i = 0; i < world->map.map_blocks.size(); i++) + auto &items = world->items.all; + for (size_t i = 0; i < items.size(); i++) { - df::map_block *block = world->map.map_blocks[i]; + df::item *item = items[i]; - for (size_t j = 0; j < block->items.size(); j++) - { - df::item *item = df::item::find(block->items[j]); - if (!item) - continue; + int num = containsMetalItems(item, all, non_trader); + if (!num) + continue; - int num = containsMetalItems(item, all, non_trader); - if (!num) - continue; + df::map_block *block = Maps::getBlockAbs(item->pos); + if (!block) + continue; - total += num; - counts[(item->pos - player_pos)/10] += num; + total += num; + counts[(item->pos - player_pos)/10] += num; - auto &designations = block->designation; - auto &dgn = designations[item->pos.x%16][item->pos.y%16]; + auto &designations = block->designation; + auto &dgn = designations[item->pos.x%16][item->pos.y%16]; - dgn.bits.hidden = 0; // revealed - dgn.bits.pile = 1; // visible - } + dgn.bits.hidden = 0; // revealed + dgn.bits.pile = 1; // visible } joinCounts(counts); - c->con.print("%d items of metal merchandise found in the vicinity.\n", total); + out.print("%d items of metal merchandise found in the vicinity.\n", total); for (auto it = counts.begin(); it != counts.end(); it++) { if (!it->second) continue; df::coord delta = it->first * 10; - c->con.print(" %s: %d\n", formatDirection(delta).c_str(), it->second); + out.print(" %s: %d\n", formatDirection(delta).c_str(), it->second); } return CR_OK; diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index 9541af295..c26d5afdc 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -34,11 +34,11 @@ using df::global::world; DFHACK_PLUGIN("autodump"); -command_result df_autodump(Core * c, vector & parameters); -command_result df_autodump_destroy_here(Core * c, vector & parameters); -command_result df_autodump_destroy_item(Core * c, vector & parameters); +command_result df_autodump(color_ostream &out, vector & parameters); +command_result df_autodump_destroy_here(color_ostream &out, vector & parameters); +command_result df_autodump_destroy_item(color_ostream &out, vector & parameters); -DFhackCExport command_result plugin_init ( Core * c, vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, vector &commands) { commands.push_back(PluginCommand( "autodump", "Teleport items marked for dumping to the cursor.", @@ -69,14 +69,14 @@ DFhackCExport command_result plugin_init ( Core * c, vector &com return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } typedef map coordmap; -static command_result autodump_main(Core * c, vector & parameters) +static command_result autodump_main(color_ostream &out, vector & parameters) { // Command line options bool destroy = false; @@ -103,14 +103,14 @@ static command_result autodump_main(Core * c, vector & parameters) if (need_visible && need_hidden) { - c->con.printerr("An item can't be both hidden and visible.\n"); + out.printerr("An item can't be both hidden and visible.\n"); return CR_WRONG_USAGE; } - DFHack::VersionInfo *mem = c->vinfo; + //DFHack::VersionInfo *mem = Core::getInstance().vinfo; if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } size_t numItems = world->items.all.size(); @@ -125,7 +125,7 @@ static command_result autodump_main(Core * c, vector & parameters) { if (!Gui::getCursorCoords(cx,cy,cz)) { - c->con.printerr("Cursor position not found. Please enabled the cursor.\n"); + out.printerr("Cursor position not found. Please enabled the cursor.\n"); return CR_FAILURE; } pos_cursor = DFCoord(cx,cy,cz); @@ -136,13 +136,13 @@ static command_result autodump_main(Core * c, vector & parameters) Block * b = MC.BlockAt(pos_cursor / 16); if(!b) { - c->con.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n"); + out.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n"); return CR_FAILURE; } df::tiletype ttype = MC.tiletypeAt(pos_cursor); if(!DFHack::isFloorTerrain(ttype)) { - c->con.printerr("Cursor should be placed over a floor.\n"); + out.printerr("Cursor should be placed over a floor.\n"); return CR_FAILURE; } } @@ -274,18 +274,18 @@ static command_result autodump_main(Core * c, vector & parameters) // Is this necessary? Is "forbid" a dirtyable attribute like "dig" is? Maps::WriteDirtyBit(cx/16, cy/16, cz, true); } - c->con.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for destruction" : "quickdumped"); + out.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for destruction" : "quickdumped"); return CR_OK; } -command_result df_autodump(Core * c, vector & parameters) +command_result df_autodump(color_ostream &out, vector & parameters) { - CoreSuspender suspend(c); + CoreSuspender suspend; - return autodump_main(c, parameters); + return autodump_main(out, parameters); } -command_result df_autodump_destroy_here(Core * c, vector & parameters) +command_result df_autodump_destroy_here(color_ostream &out, vector & parameters) { // HOTKEY COMMAND; CORE ALREADY SUSPENDED if (!parameters.empty()) @@ -294,19 +294,19 @@ command_result df_autodump_destroy_here(Core * c, vector & parameters) vector args; args.push_back("destroy-here"); - return autodump_main(c, args); + return autodump_main(out, args); } static map pending_destroy; static int last_frame = 0; -command_result df_autodump_destroy_item(Core * c, vector & parameters) +command_result df_autodump_destroy_item(color_ostream &out, vector & parameters) { // HOTKEY COMMAND; CORE ALREADY SUSPENDED if (!parameters.empty()) return CR_WRONG_USAGE; - df::item *item = Gui::getSelectedItem(c); + df::item *item = Gui::getSelectedItem(out); if (!item) return CR_FAILURE; @@ -332,7 +332,7 @@ command_result df_autodump_destroy_item(Core * c, vector & parameters) // Check the item is good to destroy if (item->flags.bits.garbage_colect) { - c->con.printerr("Item is already marked for destroy.\n"); + out.printerr("Item is already marked for destroy.\n"); return CR_FAILURE; } @@ -340,7 +340,7 @@ command_result df_autodump_destroy_item(Core * c, vector & parameters) item->flags.bits.in_building || item->flags.bits.artifact1) { - c->con.printerr("Choosing not to destroy buildings, constructions and artifacts.\n"); + out.printerr("Choosing not to destroy buildings, constructions and artifacts.\n"); return CR_FAILURE; } @@ -349,7 +349,7 @@ command_result df_autodump_destroy_item(Core * c, vector & parameters) df::general_ref *ref = item->itemrefs[i]; if (ref->getType() == general_ref_type::UNIT_HOLDER) { - c->con.printerr("Choosing not to destroy items in unit inventory.\n"); + out.printerr("Choosing not to destroy items in unit inventory.\n"); return CR_FAILURE; } } diff --git a/plugins/changevein.cpp b/plugins/changevein.cpp index efb045f76..5b8d2e982 100644 --- a/plugins/changevein.cpp +++ b/plugins/changevein.cpp @@ -18,42 +18,42 @@ using namespace df::enums; using df::global::world; using df::global::cursor; -command_result df_changevein (Core * c, vector & parameters) +command_result df_changevein (color_ostream &out, vector & parameters) { if (parameters.size() != 1) return CR_WRONG_USAGE; - CoreSuspender suspend(c); + CoreSuspender suspend; if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } if (!cursor || cursor->x == -30000) { - c->con.printerr("No cursor detected - please place the cursor over a mineral vein.\n"); + out.printerr("No cursor detected - please place the cursor over a mineral vein.\n"); return CR_FAILURE; } MaterialInfo mi; if (!mi.findInorganic(parameters[0])) { - c->con.printerr("No such material!\n"); + out.printerr("No such material!\n"); return CR_FAILURE; } if (mi.inorganic->material.flags.is_set(material_flags::IS_METAL) || mi.inorganic->material.flags.is_set(material_flags::NO_STONE_STOCKPILE) || mi.inorganic->flags.is_set(inorganic_flags::SOIL_ANY)) { - c->con.printerr("Invalid material - you must select a type of stone or gem\n"); + out.printerr("Invalid material - you must select a type of stone or gem\n"); return CR_FAILURE; } df::map_block *block = Maps::getBlockAbs(cursor->x, cursor->y, cursor->z); if (!block) { - c->con.printerr("Invalid tile selected.\n"); + out.printerr("Invalid tile selected.\n"); return CR_FAILURE; } df::block_square_event_mineralst *mineral = NULL; @@ -70,7 +70,7 @@ command_result df_changevein (Core * c, vector & parameters) } if (!mineral) { - c->con.printerr("Selected tile does not contain a mineral vein.\n"); + out.printerr("Selected tile does not contain a mineral vein.\n"); return CR_FAILURE; } mineral->inorganic_mat = mi.index; @@ -80,7 +80,7 @@ command_result df_changevein (Core * c, vector & parameters) DFHACK_PLUGIN("changevein"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand("changevein", "Changes the material of a mineral inclusion.", @@ -89,7 +89,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } diff --git a/plugins/cleaners.cpp b/plugins/cleaners.cpp index 3e5d03767..ea5edc991 100644 --- a/plugins/cleaners.cpp +++ b/plugins/cleaners.cpp @@ -23,7 +23,7 @@ using df::global::cursor; DFHACK_PLUGIN("cleaners"); -command_result cleanmap (Core * c, bool snow, bool mud) +command_result cleanmap (color_ostream &out, bool snow, bool mud) { // Invoked from clean(), already suspended int num_blocks = 0, blocks_total = world->map.map_blocks.size(); @@ -67,11 +67,11 @@ command_result cleanmap (Core * c, bool snow, bool mud) } if(num_blocks) - c->con.print("Cleaned %d of %d map blocks.\n", num_blocks, blocks_total); + out.print("Cleaned %d of %d map blocks.\n", num_blocks, blocks_total); return CR_OK; } -command_result cleanitems (Core * c) +command_result cleanitems (color_ostream &out) { // Invoked from clean(), already suspended int cleaned_items = 0, cleaned_total = 0; @@ -89,11 +89,11 @@ command_result cleanitems (Core * c) } } if (cleaned_total) - c->con.print("Removed %d contaminants from %d items.\n", cleaned_total, cleaned_items); + out.print("Removed %d contaminants from %d items.\n", cleaned_total, cleaned_items); return CR_OK; } -command_result cleanunits (Core * c) +command_result cleanunits (color_ostream &out) { // Invoked from clean(), already suspended int cleaned_units = 0, cleaned_total = 0; @@ -110,27 +110,27 @@ command_result cleanunits (Core * c) } } if (cleaned_total) - c->con.print("Removed %d contaminants from %d creatures.\n", cleaned_total, cleaned_units); + out.print("Removed %d contaminants from %d creatures.\n", cleaned_total, cleaned_units); return CR_OK; } -command_result spotclean (Core * c, vector & parameters) +command_result spotclean (color_ostream &out, vector & parameters) { // HOTKEY COMMAND: CORE ALREADY SUSPENDED if (cursor->x == -30000) { - c->con.printerr("The cursor is not active.\n"); + out.printerr("The cursor is not active.\n"); return CR_WRONG_USAGE; } if (!Maps::IsValid()) { - c->con.printerr("Map is not available.\n"); + out.printerr("Map is not available.\n"); return CR_FAILURE; } df::map_block *block = Maps::getBlockAbs(cursor->x, cursor->y, cursor->z); if (block == NULL) { - c->con.printerr("Invalid map block selected!\n"); + out.printerr("Invalid map block selected!\n"); return CR_FAILURE; } @@ -146,7 +146,7 @@ command_result spotclean (Core * c, vector & parameters) return CR_OK; } -command_result clean (Core * c, vector & parameters) +command_result clean (color_ostream &out, vector & parameters) { bool map = false; bool snow = false; @@ -177,17 +177,18 @@ command_result clean (Core * c, vector & parameters) if(!map && !units && !items) return CR_WRONG_USAGE; - CoreSuspender suspend(c); + CoreSuspender suspend; + if(map) - cleanmap(c,snow,mud); + cleanmap(out,snow,mud); if(units) - cleanunits(c); + cleanunits(out); if(items) - cleanitems(c); + cleanitems(out); return CR_OK; } -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand( "clean","Removes contaminants from map tiles, items and creatures.", @@ -212,7 +213,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } diff --git a/plugins/cleanowned.cpp b/plugins/cleanowned.cpp index 945fb9754..280f2e1c5 100644 --- a/plugins/cleanowned.cpp +++ b/plugins/cleanowned.cpp @@ -25,11 +25,11 @@ using namespace df::enums; using df::global::world; -command_result df_cleanowned (Core * c, vector & parameters); +command_result df_cleanowned (color_ostream &out, vector & parameters); DFHACK_PLUGIN("cleanowned"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand( "cleanowned", "Confiscates and dumps garbage owned by dwarfs.", @@ -51,12 +51,12 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -command_result df_cleanowned (Core * c, vector & parameters) +command_result df_cleanowned (color_ostream &out, vector & parameters) { bool dump_scattered = false; bool confiscate_all = false; @@ -80,15 +80,15 @@ command_result df_cleanowned (Core * c, vector & parameters) return CR_WRONG_USAGE; } - CoreSuspender suspend(c); + CoreSuspender suspend; if (!Translation::IsValid()) { - c->con.printerr("Translation data unavailable!\n"); + out.printerr("Translation data unavailable!\n"); return CR_FAILURE; } - c->con.print("Found total %d items.\n", world->items.all.size()); + out.print("Found total %d items.\n", world->items.all.size()); for (std::size_t i=0; i < world->items.all.size(); i++) { @@ -101,7 +101,7 @@ command_result df_cleanowned (Core * c, vector & parameters) int32_t owner = Items::getItemOwnerID(item); if (owner >= 0) { - c->con.print("Fixing a misflagged item: \t"); + out.print("Fixing a misflagged item: \t"); confiscate = true; } else @@ -112,7 +112,7 @@ command_result df_cleanowned (Core * c, vector & parameters) if (item->flags.bits.rotten) { - c->con.print("Confiscating a rotten item: \t"); + out.print("Confiscating a rotten item: \t"); confiscate = true; } else if (item->flags.bits.on_ground) @@ -130,30 +130,30 @@ command_result df_cleanowned (Core * c, vector & parameters) confiscate = true; if(dump_scattered) { - c->con.print("Dumping a dropped item: \t"); + out.print("Dumping a dropped item: \t"); dump = true; } else { - c->con.print("Confiscating a dropped item: \t"); + out.print("Confiscating a dropped item: \t"); } } else if(dump_scattered) { - c->con.print("Confiscating and dumping litter: \t"); + out.print("Confiscating and dumping litter: \t"); confiscate = true; dump = true; } } else if (item->getWear() >= wear_dump_level) { - c->con.print("Confiscating and dumping a worn item: \t"); + out.print("Confiscating and dumping a worn item: \t"); confiscate = true; dump = true; } else if (confiscate_all) { - c->con.print("Confiscating: \t"); + out.print("Confiscating: \t"); confiscate = true; } @@ -161,7 +161,7 @@ command_result df_cleanowned (Core * c, vector & parameters) { std::string description; item->getItemDescription(&description, 0); - c->con.print( + out.print( "0x%x %s (wear %d)", item, description.c_str(), @@ -171,16 +171,16 @@ command_result df_cleanowned (Core * c, vector & parameters) df::unit *owner = Items::getItemOwner(item); if (owner) - c->con.print(", owner %s", Translation::TranslateName(&owner->name,false).c_str()); + out.print(", owner %s", Translation::TranslateName(&owner->name,false).c_str()); if (!dry_run) { if (!Items::removeItemOwner(item)) - c->con.print("(unsuccessfully) "); + out.print("(unsuccessfully) "); if (dump) item->flags.bits.dump = 1; } - c->con.print("\n"); + out.print("\n"); } } return CR_OK; diff --git a/plugins/colonies.cpp b/plugins/colonies.cpp index 2ba0e7384..3ebfc324c 100644 --- a/plugins/colonies.cpp +++ b/plugins/colonies.cpp @@ -11,11 +11,11 @@ using std::vector; using std::string; using namespace DFHack; -command_result colonies (Core * c, vector & parameters); +command_result colonies (color_ostream &out, vector & parameters); DFHACK_PLUGIN("colonies"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand( "colonies", "List or change wild colonies (ants hills and such)", @@ -28,16 +28,16 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } void destroyColonies(); void convertColonies(Materials *Materials); -void showColonies(Core *c, Materials *Materials); +void showColonies(color_ostream &out, Materials *Materials); -command_result colonies (Core * c, vector & parameters) +command_result colonies (color_ostream &out, vector & parameters) { bool destroy = false; bool convert = false; @@ -53,12 +53,13 @@ command_result colonies (Core * c, vector & parameters) } if (destroy && convert) { - c->con.printerr("Kill or make bees? DECIDE!\n"); + out.printerr("Kill or make bees? DECIDE!\n"); return CR_FAILURE; } - CoreSuspender suspend(c); - Materials * materials = c->getMaterials(); + CoreSuspender suspend; + + Materials * materials = Core::getInstance().getMaterials(); materials->ReadCreatureTypesEx(); @@ -67,7 +68,7 @@ command_result colonies (Core * c, vector & parameters) else if (convert) convertColonies(materials); else - showColonies(c, materials); + showColonies(out, materials); materials->Finish(); @@ -124,7 +125,7 @@ void convertColonies(Materials *Materials) } } -void showColonies(Core *c, Materials *Materials) +void showColonies(color_ostream &out, Materials *Materials) { uint32_t numSpawnPoints = Vermin::getNumVermin(); int numColonies = 0; @@ -141,11 +142,11 @@ void showColonies(Core *c, Materials *Materials) if(sp.race != -1) race = Materials->raceEx[sp.race].id; - c->con.print("Colony %u: %s at %d:%d:%d\n", i, - race.c_str(), sp.x, sp.y, sp.z); + out.print("Colony %u: %s at %d:%d:%d\n", i, + race.c_str(), sp.x, sp.y, sp.z); } } if (numColonies == 0) - c->con << "No colonies present." << std::endl; + out << "No colonies present." << std::endl; } diff --git a/plugins/deramp.cpp b/plugins/deramp.cpp index 75b99cff6..c872f33dd 100644 --- a/plugins/deramp.cpp +++ b/plugins/deramp.cpp @@ -18,16 +18,16 @@ using df::global::world; DFHACK_PLUGIN("deramp"); -command_result df_deramp (Core * c, vector & parameters) +command_result df_deramp (color_ostream &out, vector & parameters) { if (!parameters.empty()) return CR_WRONG_USAGE; - CoreSuspender suspend(c); + CoreSuspender suspend; if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } @@ -75,13 +75,13 @@ command_result df_deramp (Core * c, vector & parameters) } } if (count) - c->con.print("Found and changed %d tiles.\n", count); + out.print("Found and changed %d tiles.\n", count); if (countbad) - c->con.print("Fixed %d bad down ramps.\n", countbad); + out.print("Fixed %d bad down ramps.\n", countbad); return CR_OK; } -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand( "deramp", "De-ramp. All ramps marked for removal are replaced with floors.", @@ -93,7 +93,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } diff --git a/plugins/devel/buildprobe.cpp b/plugins/devel/buildprobe.cpp index d5e570987..6c360455a 100644 --- a/plugins/devel/buildprobe.cpp +++ b/plugins/devel/buildprobe.cpp @@ -18,40 +18,38 @@ using std::string; using std::stack; using namespace DFHack; -command_result readFlag (Core * c, vector & parameters); -command_result writeFlag (Core * c, vector & parameters); +command_result readFlag (color_ostream &out, vector & parameters); +command_result writeFlag (color_ostream &out, vector & parameters); DFHACK_PLUGIN("buildprobe"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand("bshow","Output building occupancy value",readFlag)); commands.push_back(PluginCommand("bset","Set building occupancy value",writeFlag)); return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -command_result readFlag (Core * c, vector & parameters) +command_result readFlag (color_ostream &out, vector & parameters) { - c->Suspend(); + CoreSuspender suspend; // init the map if(!Maps::IsValid()) { - c->con.printerr("Can't init map. Make sure you have a map loaded in DF.\n"); - c->Resume(); + out.printerr("Can't init map. Make sure you have a map loaded in DF.\n"); return CR_FAILURE; } int32_t cx, cy, cz; if(!Gui::getCursorCoords(cx,cy,cz)) { - c->con.printerr("Cursor is not active.\n"); - c->Resume(); + out.printerr("Cursor is not active.\n"); return CR_FAILURE; } @@ -60,24 +58,22 @@ command_result readFlag (Core * c, vector & parameters) MapExtras::MapCache * MCache = new MapExtras::MapCache(); t_occupancy oc = MCache->occupancyAt(cursor); - c->con.print("Current Value: %d\n", oc.bits.building); - - c->Resume(); + out.print("Current Value: %d\n", oc.bits.building); return CR_OK; } -command_result writeFlag (Core * c, vector & parameters) +command_result writeFlag (color_ostream &out, vector & parameters) { if (parameters.size() == 0) { - c->con.print("No value specified\n"); + out.print("No value specified\n"); return CR_FAILURE; } if (parameters[0] == "help" || parameters[0] == "?") { - c->con.print("Set the building occupancy flag.\n" - "Value must be between 0 and 7, inclusive.\n"); + out.print("Set the building occupancy flag.\n" + "Value must be between 0 and 7, inclusive.\n"); return CR_OK; } @@ -97,26 +93,24 @@ command_result writeFlag (Core * c, vector & parameters) break; default: - c->con.print("Invalid value specified\n"); + out.print("Invalid value specified\n"); return CR_FAILURE; break; //Redundant. } - c->Suspend(); + CoreSuspender suspend; // init the map if(!Maps::IsValid()) { - c->con.printerr("Can't init map. Make sure you have a map loaded in DF.\n"); - c->Resume(); + out.printerr("Can't init map. Make sure you have a map loaded in DF.\n"); return CR_FAILURE; } int32_t cx, cy, cz; if(!Gui::getCursorCoords(cx,cy,cz)) { - c->con.printerr("Cursor is not active.\n"); - c->Resume(); + out.printerr("Cursor is not active.\n"); return CR_FAILURE; } @@ -129,6 +123,5 @@ command_result writeFlag (Core * c, vector & parameters) MCache->setOccupancyAt(cursor, oc); MCache->WriteAll(); - c->Resume(); return CR_OK; } diff --git a/plugins/devel/catsplosion.cpp b/plugins/devel/catsplosion.cpp index 7c220641e..49587aa99 100644 --- a/plugins/devel/catsplosion.cpp +++ b/plugins/devel/catsplosion.cpp @@ -25,12 +25,12 @@ using namespace std; using namespace DFHack; -command_result catsplosion (Core * c, std::vector & parameters); +command_result catsplosion (color_ostream &out, std::vector & parameters); DFHACK_PLUGIN("catsplosion"); // Mandatory init function. If you have some global state, create it here. -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { // Fill the command list with your commands. commands.push_back(PluginCommand( @@ -41,13 +41,13 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } typedef df::unit::T_relations::T_pregnancy_ptr pregstruct; -command_result catsplosion (Core * c, std::vector & parameters) +command_result catsplosion (color_ostream &out, std::vector & parameters) { list s_creatures; // only cats for now. @@ -55,7 +55,7 @@ command_result catsplosion (Core * c, std::vector & parameters) // make the creature list unique ... with cats. they are always unique s_creatures.unique(); // SUSPEND THE CORE! ::Evil laugh:: - CoreSuspender susp(c); + CoreSuspender susp; uint32_t numCreatures; if(!(numCreatures = Units::getNumCreatures())) @@ -95,10 +95,10 @@ command_result catsplosion (Core * c, std::vector & parameters) // print (optional) //if (showcreatures == 1) { - c->con.print("Type Male # Female #\n"); + out.print("Type Male # Female #\n"); for(auto it1 = male_counts.begin();it1!=male_counts.end();it1++) { - c->con.print("%20s %6d %8d\n", it1->first.c_str(), it1->second.size(), female_counts[it1->first].size()); + out.print("%20s %6d %8d\n", it1->first.c_str(), it1->second.size(), female_counts[it1->first].size()); } } @@ -133,9 +133,9 @@ command_result catsplosion (Core * c, std::vector & parameters) } } if(totalchanged) - c->con.print("%d pregnancies accelerated.\n", totalchanged); + out.print("%d pregnancies accelerated.\n", totalchanged); if(totalcreated) - c->con.print("%d pregnancies created.\n", totalcreated); - c->con.print("Total creatures checked: %d\n", totalcount); + out.print("%d pregnancies created.\n", totalcreated); + out.print("Total creatures checked: %d\n", totalcount); return CR_OK; } diff --git a/plugins/devel/dumpmats.cpp b/plugins/devel/dumpmats.cpp index 723638d8d..6ee3d693f 100644 --- a/plugins/devel/dumpmats.cpp +++ b/plugins/devel/dumpmats.cpp @@ -19,22 +19,22 @@ using namespace df::enums; using df::global::world; -command_result df_dumpmats (Core *c, vector ¶meters) +command_result df_dumpmats (color_ostream &out, vector ¶meters) { if (!parameters.empty()) return CR_WRONG_USAGE; - CoreSuspender suspend(c); + CoreSuspender suspend; - c->con.print("hardcoded_materials\n\n"); - c->con.print("[OBJECT:MATERIAL]\n"); + out.print("hardcoded_materials\n\n"); + out.print("[OBJECT:MATERIAL]\n"); FOR_ENUM_ITEMS(builtin_mats, mat_num) { df::material *mat = world->raws.mat_table.builtin[mat_num]; if (!mat) continue; - c->con.print("\n[MATERIAL:%s] - reconstructed from data extracted from memory\n", mat->id.c_str()); + out.print("\n[MATERIAL:%s] - reconstructed from data extracted from memory\n", mat->id.c_str()); int32_t def_color[6] = {-1,-1,-1,-1,-1,-1}; bool name_all = false; @@ -58,10 +58,10 @@ command_result df_dumpmats (Core *c, vector ¶meters) { def_color[matter_state::Liquid] = solid_color; def_color[matter_state::Gas] = solid_color; - c->con.print("\t[STATE_COLOR:ALL:%s]\n", world->raws.language.colors[solid_color]->id.c_str()); + out.print("\t[STATE_COLOR:ALL:%s]\n", world->raws.language.colors[solid_color]->id.c_str()); } else - c->con.print("\t[STATE_COLOR:ALL_SOLID:%s]\n", world->raws.language.colors[solid_color]->id.c_str()); + out.print("\t[STATE_COLOR:ALL_SOLID:%s]\n", world->raws.language.colors[solid_color]->id.c_str()); } string solid_name = mat->state_name[matter_state::Solid]; @@ -88,10 +88,10 @@ command_result df_dumpmats (Core *c, vector ¶meters) def_name[matter_state::Gas] = solid_name; def_adj[matter_state::Liquid] = solid_name; def_adj[matter_state::Gas] = solid_name; - c->con.print("\t[STATE_NAME_ADJ:ALL:%s]\n", solid_name.c_str()); + out.print("\t[STATE_NAME_ADJ:ALL:%s]\n", solid_name.c_str()); } else - c->con.print("\t[STATE_NAME_ADJ:ALL_SOLID:%s]\n", solid_name.c_str()); + out.print("\t[STATE_NAME_ADJ:ALL_SOLID:%s]\n", solid_name.c_str()); } } else @@ -110,10 +110,10 @@ command_result df_dumpmats (Core *c, vector ¶meters) { def_name[matter_state::Liquid] = solid_name; def_name[matter_state::Gas] = solid_name; - c->con.print("\t[STATE_NAME:ALL:%s]\n", solid_name.c_str()); + out.print("\t[STATE_NAME:ALL:%s]\n", solid_name.c_str()); } else - c->con.print("\t[STATE_NAME:ALL_SOLID:%s]\n", solid_name.c_str()); + out.print("\t[STATE_NAME:ALL_SOLID:%s]\n", solid_name.c_str()); } if (solid_adj == mat->state_adj[matter_state::Powder] || solid_adj == mat->state_adj[matter_state::Paste] || @@ -129,148 +129,148 @@ command_result df_dumpmats (Core *c, vector ¶meters) { def_adj[matter_state::Liquid] = solid_adj; def_adj[matter_state::Gas] = solid_adj; - c->con.print("\t[STATE_ADJ:ALL:%s]\n", solid_adj.c_str()); + out.print("\t[STATE_ADJ:ALL:%s]\n", solid_adj.c_str()); } else - c->con.print("\t[STATE_ADJ:ALL_SOLID:%s]\n", solid_adj.c_str()); + out.print("\t[STATE_ADJ:ALL_SOLID:%s]\n", solid_adj.c_str()); } } - char *state_names[6] = {"SOLID", "LIQUID", "GAS", "SOLID_POWDER", "SOLID_PASTE", "SOLID_PRESSED"}; + const char *state_names[6] = {"SOLID", "LIQUID", "GAS", "SOLID_POWDER", "SOLID_PASTE", "SOLID_PRESSED"}; FOR_ENUM_ITEMS(matter_state, state) { if (mat->state_color[state] != -1 && mat->state_color[state] != def_color[state]) - c->con.print("\t[STATE_COLOR:%s:%s]\n", state_names[state], world->raws.language.colors[mat->state_color[state]]->id.c_str()); + out.print("\t[STATE_COLOR:%s:%s]\n", state_names[state], world->raws.language.colors[mat->state_color[state]]->id.c_str()); if (mat->state_name[state] == mat->state_adj[state]) { if (mat->state_name[state].size() && mat->state_name[state] != def_name[state] || mat->state_adj[state].size() && mat->state_adj[state] != def_adj[state]) - c->con.print("\t[STATE_NAME_ADJ:%s:%s]\n", state_names[state], mat->state_name[state].c_str()); + out.print("\t[STATE_NAME_ADJ:%s:%s]\n", state_names[state], mat->state_name[state].c_str()); } else { if (mat->state_name[state].size() && mat->state_name[state] != def_name[state]) - c->con.print("\t[STATE_NAME:%s:%s]\n", state_names[state], mat->state_name[state].c_str()); + out.print("\t[STATE_NAME:%s:%s]\n", state_names[state], mat->state_name[state].c_str()); if (mat->state_adj[state].size() && mat->state_adj[state] != def_adj[state]) - c->con.print("\t[STATE_ADJ:%s:%s]\n", state_names[state], mat->state_adj[state].c_str()); + out.print("\t[STATE_ADJ:%s:%s]\n", state_names[state], mat->state_adj[state].c_str()); } } if (mat->basic_color[0] != 7 || mat->basic_color[1] != 0) - c->con.print("\t[BASIC_COLOR:%i:%i]\n", mat->basic_color[0], mat->basic_color[1]); + out.print("\t[BASIC_COLOR:%i:%i]\n", mat->basic_color[0], mat->basic_color[1]); if (mat->build_color[0] != 7 || mat->build_color[1] != 7 || mat->build_color[2] != 0) - c->con.print("\t[BUILD_COLOR:%i:%i:%i]\n", mat->build_color[0], mat->build_color[1], mat->build_color[2]); + out.print("\t[BUILD_COLOR:%i:%i:%i]\n", mat->build_color[0], mat->build_color[1], mat->build_color[2]); if (mat->tile_color[0] != 7 || mat->tile_color[1] != 7 || mat->tile_color[2] != 0) - c->con.print("\t[TILE_COLOR:%i:%i:%i]\n", mat->tile_color[0], mat->tile_color[1], mat->tile_color[2]); + out.print("\t[TILE_COLOR:%i:%i:%i]\n", mat->tile_color[0], mat->tile_color[1], mat->tile_color[2]); if (mat->tile != 0xdb) - c->con.print("\t[TILE:%i]\n", mat->tile); + out.print("\t[TILE:%i]\n", mat->tile); if (mat->item_symbol != 0x07) - c->con.print("\t[ITEM_SYMBOL:%i]\n", mat->item_symbol); + out.print("\t[ITEM_SYMBOL:%i]\n", mat->item_symbol); if (mat->material_value != 1) - c->con.print("\t[MATERIAL_VALUE:%i]\n", mat->material_value); + out.print("\t[MATERIAL_VALUE:%i]\n", mat->material_value); if (mat->gem_name1.size()) - c->con.print("\t[IS_GEM:%s:%s]\n", mat->gem_name1.c_str(), mat->gem_name2.c_str()); + out.print("\t[IS_GEM:%s:%s]\n", mat->gem_name1.c_str(), mat->gem_name2.c_str()); if (mat->stone_name.size()) - c->con.print("\t[STONE_NAME:%s]\n", mat->stone_name.c_str()); + out.print("\t[STONE_NAME:%s]\n", mat->stone_name.c_str()); if (mat->heat.spec_heat != 60001) - c->con.print("\t[SPEC_HEAT:%i]\n", mat->heat.spec_heat); + out.print("\t[SPEC_HEAT:%i]\n", mat->heat.spec_heat); if (mat->heat.heatdam_point != 60001) - c->con.print("\t[HEATDAM_POINT:%i]\n", mat->heat.heatdam_point); + out.print("\t[HEATDAM_POINT:%i]\n", mat->heat.heatdam_point); if (mat->heat.colddam_point != 60001) - c->con.print("\t[COLDDAM_POINT:%i]\n", mat->heat.colddam_point); + out.print("\t[COLDDAM_POINT:%i]\n", mat->heat.colddam_point); if (mat->heat.ignite_point != 60001) - c->con.print("\t[IGNITE_POINT:%i]\n", mat->heat.ignite_point); + out.print("\t[IGNITE_POINT:%i]\n", mat->heat.ignite_point); if (mat->heat.melting_point != 60001) - c->con.print("\t[MELTING_POINT:%i]\n", mat->heat.melting_point); + out.print("\t[MELTING_POINT:%i]\n", mat->heat.melting_point); if (mat->heat.boiling_point != 60001) - c->con.print("\t[BOILING_POINT:%i]\n", mat->heat.boiling_point); + out.print("\t[BOILING_POINT:%i]\n", mat->heat.boiling_point); if (mat->heat.mat_fixed_temp != 60001) - c->con.print("\t[MAT_FIXED_TEMP:%i]\n", mat->heat.mat_fixed_temp); + out.print("\t[MAT_FIXED_TEMP:%i]\n", mat->heat.mat_fixed_temp); if (mat->solid_density != 0xFBBC7818) - c->con.print("\t[SOLID_DENSITY:%i]\n", mat->solid_density); + out.print("\t[SOLID_DENSITY:%i]\n", mat->solid_density); if (mat->liquid_density != 0xFBBC7818) - c->con.print("\t[LIQUID_DENSITY:%i]\n", mat->liquid_density); + out.print("\t[LIQUID_DENSITY:%i]\n", mat->liquid_density); if (mat->molar_mass != 0xFBBC7818) - c->con.print("\t[MOLAR_MASS:%i]\n", mat->molar_mass); + out.print("\t[MOLAR_MASS:%i]\n", mat->molar_mass); if (mat->strength.impact_yield != 10000) - c->con.print("\t[IMPACT_YIELD:%i]\n", mat->strength.impact_yield); + out.print("\t[IMPACT_YIELD:%i]\n", mat->strength.impact_yield); if (mat->strength.impact_fracture != 10000) - c->con.print("\t[IMPACT_FRACTURE:%i]\n", mat->strength.impact_fracture); + out.print("\t[IMPACT_FRACTURE:%i]\n", mat->strength.impact_fracture); if (mat->strength.impact_strain_at_yield != 0) - c->con.print("\t[IMPACT_STRAIN_AT_YIELD:%i]\n", mat->strength.impact_strain_at_yield); + out.print("\t[IMPACT_STRAIN_AT_YIELD:%i]\n", mat->strength.impact_strain_at_yield); if (mat->strength.compressive_yield != 10000) - c->con.print("\t[COMPRESSIVE_YIELD:%i]\n", mat->strength.compressive_yield); + out.print("\t[COMPRESSIVE_YIELD:%i]\n", mat->strength.compressive_yield); if (mat->strength.compressive_fracture != 10000) - c->con.print("\t[COMPRESSIVE_FRACTURE:%i]\n", mat->strength.compressive_fracture); + out.print("\t[COMPRESSIVE_FRACTURE:%i]\n", mat->strength.compressive_fracture); if (mat->strength.compressive_strain_at_yield != 0) - c->con.print("\t[COMPRESSIVE_STRAIN_AT_YIELD:%i]\n", mat->strength.compressive_strain_at_yield); + out.print("\t[COMPRESSIVE_STRAIN_AT_YIELD:%i]\n", mat->strength.compressive_strain_at_yield); if (mat->strength.tensile_yield != 10000) - c->con.print("\t[TENSILE_YIELD:%i]\n", mat->strength.tensile_yield); + out.print("\t[TENSILE_YIELD:%i]\n", mat->strength.tensile_yield); if (mat->strength.tensile_fracture != 10000) - c->con.print("\t[TENSILE_FRACTURE:%i]\n", mat->strength.tensile_fracture); + out.print("\t[TENSILE_FRACTURE:%i]\n", mat->strength.tensile_fracture); if (mat->strength.tensile_strain_at_yield != 0) - c->con.print("\t[TENSILE_STRAIN_AT_YIELD:%i]\n", mat->strength.tensile_strain_at_yield); + out.print("\t[TENSILE_STRAIN_AT_YIELD:%i]\n", mat->strength.tensile_strain_at_yield); if (mat->strength.torsion_yield != 10000) - c->con.print("\t[TORSION_YIELD:%i]\n", mat->strength.torsion_yield); + out.print("\t[TORSION_YIELD:%i]\n", mat->strength.torsion_yield); if (mat->strength.torsion_fracture != 10000) - c->con.print("\t[TORSION_FRACTURE:%i]\n", mat->strength.torsion_fracture); + out.print("\t[TORSION_FRACTURE:%i]\n", mat->strength.torsion_fracture); if (mat->strength.torsion_strain_at_yield != 0) - c->con.print("\t[TORSION_STRAIN_AT_YIELD:%i]\n", mat->strength.torsion_strain_at_yield); + out.print("\t[TORSION_STRAIN_AT_YIELD:%i]\n", mat->strength.torsion_strain_at_yield); if (mat->strength.shear_yield != 10000) - c->con.print("\t[SHEAR_YIELD:%i]\n", mat->strength.shear_yield); + out.print("\t[SHEAR_YIELD:%i]\n", mat->strength.shear_yield); if (mat->strength.shear_fracture != 10000) - c->con.print("\t[SHEAR_FRACTURE:%i]\n", mat->strength.shear_fracture); + out.print("\t[SHEAR_FRACTURE:%i]\n", mat->strength.shear_fracture); if (mat->strength.shear_strain_at_yield != 0) - c->con.print("\t[SHEAR_STRAIN_AT_YIELD:%i]\n", mat->strength.shear_strain_at_yield); + out.print("\t[SHEAR_STRAIN_AT_YIELD:%i]\n", mat->strength.shear_strain_at_yield); if (mat->strength.bending_yield != 10000) - c->con.print("\t[BENDING_YIELD:%i]\n", mat->strength.bending_yield); + out.print("\t[BENDING_YIELD:%i]\n", mat->strength.bending_yield); if (mat->strength.bending_fracture != 10000) - c->con.print("\t[BENDING_FRACTURE:%i]\n", mat->strength.bending_fracture); + out.print("\t[BENDING_FRACTURE:%i]\n", mat->strength.bending_fracture); if (mat->strength.bending_strain_at_yield != 0) - c->con.print("\t[BENDING_STRAIN_AT_YIELD:%i]\n", mat->strength.bending_strain_at_yield); + out.print("\t[BENDING_STRAIN_AT_YIELD:%i]\n", mat->strength.bending_strain_at_yield); if (mat->strength.max_edge != 0) - c->con.print("\t[MAX_EDGE:%i]\n", mat->strength.max_edge); + out.print("\t[MAX_EDGE:%i]\n", mat->strength.max_edge); if (mat->strength.absorption != 0) - c->con.print("\t[ABSORPTION:%i]\n", mat->strength.absorption); + out.print("\t[ABSORPTION:%i]\n", mat->strength.absorption); FOR_ENUM_ITEMS(material_flags, i) { if (mat->flags.is_set(i)) - c->con.print("\t[%s]\n", ENUM_KEY_STR(material_flags, i)); + out.print("\t[%s]\n", ENUM_KEY_STR(material_flags, i)); } if (mat->extract_storage != item_type::BARREL) - c->con.print("\t[EXTRACT_STORAGE:%s]\n", ENUM_KEY_STR(item_type, mat->extract_storage)); + out.print("\t[EXTRACT_STORAGE:%s]\n", ENUM_KEY_STR(item_type, mat->extract_storage)); if (mat->butcher_special_type != item_type::NONE || mat->butcher_special_subtype != -1) - c->con.print("\t[BUTCHER_SPECIAL:%s:%s]\n", ENUM_KEY_STR(item_type, mat->butcher_special_type), (mat->butcher_special_subtype == -1) ? "NONE" : "?"); + out.print("\t[BUTCHER_SPECIAL:%s:%s]\n", ENUM_KEY_STR(item_type, mat->butcher_special_type), (mat->butcher_special_subtype == -1) ? "NONE" : "?"); if (mat->meat_name[0].size() || mat->meat_name[1].size() || mat->meat_name[2].size()) - c->con.print("\t[MEAT_NAME:%s:%s:%s]\n", mat->meat_name[0].c_str(), mat->meat_name[1].c_str(), mat->meat_name[2].c_str()); + out.print("\t[MEAT_NAME:%s:%s:%s]\n", mat->meat_name[0].c_str(), mat->meat_name[1].c_str(), mat->meat_name[2].c_str()); if (mat->block_name[0].size() || mat->block_name[1].size()) - c->con.print("\t[BLOCK_NAME:%s:%s]\n", mat->block_name[0].c_str(), mat->block_name[1].c_str()); + out.print("\t[BLOCK_NAME:%s:%s]\n", mat->block_name[0].c_str(), mat->block_name[1].c_str()); for (int i = 0; i < mat->reaction_class.size(); i++) - c->con.print("\t[REACTION_CLASS:%s]\n", mat->reaction_class[i]->c_str()); + out.print("\t[REACTION_CLASS:%s]\n", mat->reaction_class[i]->c_str()); for (int i = 0; i < mat->reaction_product.id.size(); i++) - c->con.print("\t[MATERIAL_REACTION_PRODUCT:%s:%s:%s%s%s]\n", mat->reaction_product.id[i]->c_str(), mat->reaction_product.str[0][i]->c_str(), mat->reaction_product.str[1][i]->c_str(), mat->reaction_product.str[2][i]->size() ? ":" : "", mat->reaction_product.str[2][i]->c_str()); + out.print("\t[MATERIAL_REACTION_PRODUCT:%s:%s:%s%s%s]\n", mat->reaction_product.id[i]->c_str(), mat->reaction_product.str[0][i]->c_str(), mat->reaction_product.str[1][i]->c_str(), mat->reaction_product.str[2][i]->size() ? ":" : "", mat->reaction_product.str[2][i]->c_str()); if (mat->hardens_with_water.mat_type != -1) - c->con.print("\t[HARDENS_WITH_WATER:%s:%s%s%s]\n", mat->hardens_with_water.str[0].c_str(), mat->hardens_with_water.str[1].c_str(), mat->hardens_with_water.str[2].size() ? ":" : "", mat->hardens_with_water.str[2].c_str()); + out.print("\t[HARDENS_WITH_WATER:%s:%s%s%s]\n", mat->hardens_with_water.str[0].c_str(), mat->hardens_with_water.str[1].c_str(), mat->hardens_with_water.str[2].size() ? ":" : "", mat->hardens_with_water.str[2].c_str()); if (mat->powder_dye != -1) - c->con.print("\t[POWDER_DYE:%s]\n", world->raws.language.colors[mat->powder_dye]->id.c_str()); + out.print("\t[POWDER_DYE:%s]\n", world->raws.language.colors[mat->powder_dye]->id.c_str()); if (mat->soap_level != -0) - c->con.print("\t[SOAP_LEVEL:%o]\n", mat->soap_level); + out.print("\t[SOAP_LEVEL:%o]\n", mat->soap_level); for (int i = 0; i < mat->syndrome.size(); i++) - c->con.print("\t[SYNDROME] ...\n"); + out.print("\t[SYNDROME] ...\n"); } return CR_OK; } diff --git a/plugins/devel/frozen.cpp b/plugins/devel/frozen.cpp index 8311cde3d..338cc37e8 100644 --- a/plugins/devel/frozen.cpp +++ b/plugins/devel/frozen.cpp @@ -41,54 +41,54 @@ int changeLiquid (df::tile_liquid type) return tiles; } -command_result df_frozenlava (Core * c, vector & parameters) +command_result df_frozenlava (color_ostream &out, vector & parameters) { if (parameters.size()) return CR_WRONG_USAGE; - CoreSuspender suspend(c); + CoreSuspender suspend; if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } int tiles = changeLiquid(tile_liquid::Magma); if (tiles) - c->con.print("Changed %i tiles of ice into frozen lava.\n", tiles); + out.print("Changed %i tiles of ice into frozen lava.\n", tiles); return CR_OK; } -command_result df_frozenwater (Core * c, vector & parameters) +command_result df_frozenwater (color_ostream &out, vector & parameters) { if (parameters.size()) return CR_WRONG_USAGE; - CoreSuspender suspend(c); + CoreSuspender suspend; if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } int tiles = changeLiquid(tile_liquid::Water); if (tiles) - c->con.print("Changed %i tiles of ice into frozen water.\n", tiles); + out.print("Changed %i tiles of ice into frozen water.\n", tiles); return CR_OK; } DFHACK_PLUGIN("frozen"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand("frozenlava", "Changes all ice into frozen magma.", df_frozenlava)); commands.push_back(PluginCommand("frozenwater", "Changes all ice into frozen water.", df_frozenwater)); return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } diff --git a/plugins/devel/kittens.cpp b/plugins/devel/kittens.cpp index f2e983e83..67e7ca03a 100644 --- a/plugins/devel/kittens.cpp +++ b/plugins/devel/kittens.cpp @@ -27,16 +27,16 @@ int32_t last_mouse[2] = {-1, -1}; uint32_t last_menu = 0; uint64_t timeLast = 0; -command_result kittens (Core * c, vector & parameters); -command_result ktimer (Core * c, vector & parameters); -command_result trackmenu (Core * c, vector & parameters); -command_result trackpos (Core * c, vector & parameters); -command_result colormods (Core * c, vector & parameters); -command_result zoom (Core * c, vector & parameters); +command_result kittens (color_ostream &out, vector & parameters); +command_result ktimer (color_ostream &out, vector & parameters); +command_result trackmenu (color_ostream &out, vector & parameters); +command_result trackpos (color_ostream &out, vector & parameters); +command_result colormods (color_ostream &out, vector & parameters); +command_result zoom (color_ostream &out, vector & parameters); DFHACK_PLUGIN("kittens"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand("nyan","NYAN CAT INVASION!",kittens, true)); commands.push_back(PluginCommand("ktimer","Measure time between game updates and console lag (toggle).",ktimer)); @@ -47,17 +47,17 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { shutdown_flag = true; while(!final_flag) { - c->con.msleep(60); + Core::getInstance().getConsole().msleep(60); } return CR_OK; } -DFhackCExport command_result plugin_onupdate ( Core * c ) +DFhackCExport command_result plugin_onupdate ( color_ostream &out ) { if(timering == true) { @@ -66,14 +66,14 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) uint64_t delta = time2-timeLast; // harmless potential data race here... timeLast = time2; - c->con.print("Time delta = %d ms\n", delta); + out.print("Time delta = %d ms\n", delta); } if(trackmenu_flg) { if (last_menu != df::global::ui->main.mode) { last_menu = df::global::ui->main.mode; - c->con.print("Menu: %d\n",last_menu); + out.print("Menu: %d\n",last_menu); } } if(trackpos_flg) @@ -85,7 +85,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) last_designation[0] = desig_x; last_designation[1] = desig_y; last_designation[2] = desig_z; - c->con.print("Designation: %d %d %d\n",desig_x, desig_y, desig_z); + out.print("Designation: %d %d %d\n",desig_x, desig_y, desig_z); } int mouse_x, mouse_y; Gui::getMousePos(mouse_x,mouse_y); @@ -93,13 +93,13 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) { last_mouse[0] = mouse_x; last_mouse[1] = mouse_y; - c->con.print("Mouse: %d %d\n",mouse_x, mouse_y); + out.print("Mouse: %d %d\n",mouse_x, mouse_y); } } return CR_OK; } -command_result trackmenu (Core * c, vector & parameters) +command_result trackmenu (color_ostream &out, vector & parameters) { if(trackmenu_flg) { @@ -112,42 +112,41 @@ command_result trackmenu (Core * c, vector & parameters) { trackmenu_flg = true; last_menu = df::global::ui->main.mode; - c->con.print("Menu: %d\n",last_menu); + out.print("Menu: %d\n",last_menu); return CR_OK; } else { - c->con.printerr("Can't read menu state\n"); + out.printerr("Can't read menu state\n"); return CR_FAILURE; } } } -command_result trackpos (Core * c, vector & parameters) +command_result trackpos (color_ostream &out, vector & parameters) { trackpos_flg = !trackpos_flg; return CR_OK; } -command_result colormods (Core * c, vector & parameters) +command_result colormods (color_ostream &out, vector & parameters) { - c->Suspend(); + CoreSuspender suspend; auto & vec = df::global::world->raws.creatures.alphabetic; for(int i = 0; i < vec.size();i++) { df::creature_raw* rawlion = vec[i]; df::caste_raw * caste = rawlion->caste[0]; - c->con.print("%s\nCaste addr 0x%x\n",rawlion->creature_id.c_str(), &caste->color_modifiers); + out.print("%s\nCaste addr 0x%x\n",rawlion->creature_id.c_str(), &caste->color_modifiers); for(int j = 0; j < caste->color_modifiers.size();j++) { - c->con.print("mod %d: 0x%x\n", j, caste->color_modifiers[j]); + out.print("mod %d: 0x%x\n", j, caste->color_modifiers[j]); } } - c->Resume(); return CR_OK; } // FIXME: move cursor properly relative to view position -command_result zoom (Core * c, vector & parameters) +command_result zoom (color_ostream &out, vector & parameters) { if(parameters.size() < 3) return CR_FAILURE; @@ -155,7 +154,7 @@ command_result zoom (Core * c, vector & parameters) int y = atoi( parameters[1].c_str()); int z = atoi( parameters[2].c_str()); int xi, yi, zi; - CoreSuspender cs (c); + CoreSuspender cs; if(Gui::getCursorCoords(xi, yi, zi)) { Gui::setCursorCoords(x,y,z); @@ -163,7 +162,7 @@ command_result zoom (Core * c, vector & parameters) Gui::setViewCoords(x,y,z); } -command_result ktimer (Core * c, vector & parameters) +command_result ktimer (color_ostream &out, vector & parameters) { if(timering) { @@ -171,20 +170,22 @@ command_result ktimer (Core * c, vector & parameters) return CR_OK; } uint64_t timestart = GetTimeMs64(); - c->Suspend(); - c->Resume(); + { + CoreSuspender suspend; + } uint64_t timeend = GetTimeMs64(); - c->con.print("Time to suspend = %d ms\n",timeend - timestart); + out.print("Time to suspend = %d ms\n",timeend - timestart); // harmless potential data race here... timeLast = timeend; timering = true; return CR_OK; } -command_result kittens (Core * c, vector & parameters) +command_result kittens (color_ostream &out, vector & parameters) { final_flag = false; - Console & con = c->con; + assert(out.is_console()); + Console &con = static_cast(out); // http://evilzone.org/creative-arts/nyan-cat-ascii/ const char * nyan []= { diff --git a/plugins/devel/memview.cpp b/plugins/devel/memview.cpp index 35c6e6d3e..2e13f955d 100644 --- a/plugins/devel/memview.cpp +++ b/plugins/devel/memview.cpp @@ -28,11 +28,11 @@ enum HEXVIEW_STATES { STATE_OFF,STATE_ON }; -command_result memview (Core * c, vector & parameters); +command_result memview (color_ostream &out, vector & parameters); DFHACK_PLUGIN("memview"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand("memview","Shows memory in real time. Params: adrr length refresh_rate. If addr==0 then stop viewing",memview)); memdata.state=STATE_OFF; @@ -58,15 +58,13 @@ bool isAddr(uint32_t *trg,vector & ranges) return false; } -void outputHex(uint8_t *buf,uint8_t *lbuf,size_t len,size_t start,Core *c,vector & ranges) +void outputHex(uint8_t *buf,uint8_t *lbuf,size_t len,size_t start,color_ostream &con,vector & ranges) { - Console &con=c->con; const size_t page_size=16; - con.clear(); for(size_t i=0;ilock(); @@ -114,7 +110,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) mymutex->unlock(); return CR_OK; } - //Console &con=c->con; + //Console &con=out; uint64_t time2 = GetTimeMs64(); uint64_t delta = time2-timeLast; @@ -126,8 +122,8 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) } timeLast = time2; - c->p->read(memdata.addr,memdata.len,memdata.buf); - outputHex(memdata.buf,memdata.lbuf,memdata.len,(size_t)memdata.addr,c,memdata.ranges); + Core::getInstance().p->read(memdata.addr,memdata.len,memdata.buf); + outputHex(memdata.buf,memdata.lbuf,memdata.len,(size_t)memdata.addr,out,memdata.ranges); memcpy(memdata.lbuf, memdata.buf, memdata.len); if(memdata.refresh==0) Deinit(); @@ -135,10 +131,10 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) return CR_OK; } -command_result memview (Core * c, vector & parameters) +command_result memview (color_ostream &out, vector & parameters) { mymutex->lock(); - c->p->getMemRanges(memdata.ranges); + Core::getInstance().p->getMemRanges(memdata.ranges); memdata.addr=(void *)convert(parameters[0],true); if(memdata.addr==0) { @@ -156,7 +152,7 @@ command_result memview (Core * c, vector & parameters) isValid=true; if(!isValid) { - c->con.printerr("Invalid address:%x\n",memdata.addr); + out.printerr("Invalid address:%x\n",memdata.addr); mymutex->unlock(); return CR_OK; } @@ -176,11 +172,11 @@ command_result memview (Core * c, vector & parameters) uint8_t *buf,*lbuf; memdata.buf=new uint8_t[memdata.len]; memdata.lbuf=new uint8_t[memdata.len]; - c->p->getMemRanges(memdata.ranges); + Core::getInstance().p->getMemRanges(memdata.ranges); mymutex->unlock(); return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown (color_ostream &out) { mymutex->lock(); Deinit(); diff --git a/plugins/devel/notes.cpp b/plugins/devel/notes.cpp index 494828616..cc394dbd5 100644 --- a/plugins/devel/notes.cpp +++ b/plugins/devel/notes.cpp @@ -10,11 +10,11 @@ using std::vector; using std::string; using namespace DFHack; -command_result df_notes (Core * c, vector & parameters); +command_result df_notes (color_ostream &out, vector & parameters); DFHACK_PLUGIN("notes"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand("dumpnotes", "Dumps in-game notes", @@ -22,30 +22,27 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -command_result df_notes (Core * c, vector & parameters) +command_result df_notes (color_ostream &con, vector & parameters) { - Console & con = c->con; - c->Suspend(); + CoreSuspender suspend; - DFHack::Notes * note_mod = c->getNotes(); + DFHack::Notes * note_mod = Core::getInstance().getNotes(); std::vector* note_list = note_mod->notes; if (note_list == NULL) { con.printerr("Notes are not supported under this version of DF.\n"); - c->Resume(); return CR_OK; } if (note_list->empty()) { con << "There are no notes." << std::endl; - c->Resume(); return CR_OK; } @@ -71,6 +68,5 @@ command_result df_notes (Core * c, vector & parameters) con << std::endl; } - c->Resume(); return CR_OK; } diff --git a/plugins/devel/regrass.cpp b/plugins/devel/regrass.cpp index c69457113..d2d09a517 100644 --- a/plugins/devel/regrass.cpp +++ b/plugins/devel/regrass.cpp @@ -17,12 +17,12 @@ using namespace DFHack; using df::global::world; -command_result df_regrass (Core * c, vector & parameters) +command_result df_regrass (color_ostream &out, vector & parameters) { if (!parameters.empty()) return CR_WRONG_USAGE; - CoreSuspender suspend(c); + CoreSuspender suspend; int count = 0; for (size_t i = 0; i < world->map.map_blocks.size(); i++) @@ -48,20 +48,20 @@ command_result df_regrass (Core * c, vector & parameters) } if (count) - c->con.print("Regrew %d tiles of grass.\n", count); + out.print("Regrew %d tiles of grass.\n", count); return CR_OK; } DFHACK_PLUGIN("regrass"); -DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) { commands.clear(); commands.push_back(PluginCommand("regrass", "Regrows all surface grass, restoring outdoor plant growth for pre-0.31.19 worlds.", df_regrass)); return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } diff --git a/plugins/devel/tilesieve.cpp b/plugins/devel/tilesieve.cpp index 8d663db1c..5c82eabe0 100644 --- a/plugins/devel/tilesieve.cpp +++ b/plugins/devel/tilesieve.cpp @@ -18,13 +18,13 @@ using df::global::world; // 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 tilesieve (Core * c, std::vector & parameters); +command_result tilesieve (color_ostream &out, std::vector & parameters); // A plugin must be able to return its name. This must correspond to the filename - skeleton.plug.so or skeleton.plug.dll DFHACK_PLUGIN("tilesieve"); // Mandatory init function. If you have some global state, create it here. -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { // Fill the command list with your commands. commands.push_back(PluginCommand( @@ -37,7 +37,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector } // This is called right before the plugin library is removed from memory. -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } @@ -48,16 +48,16 @@ struct xyz int z; }; -command_result tilesieve(DFHack::Core * c, std::vector & params) +command_result tilesieve(color_ostream &out, std::vector & params) { - Console & con = c->con; - CoreSuspender suspend(c); + CoreSuspender suspend; + if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } - c->con.print("Scanning.\n"); + out.print("Scanning.\n"); std::set seen; for (auto iter = world->map.map_blocks.begin(); iter != world->map.map_blocks.end(); iter++) { @@ -75,7 +75,7 @@ command_result tilesieve(DFHack::Core * c, std::vector & params) if(seen.count(tt)) continue; seen.insert(tt); - c->con.print("Found tile %x @ %d %d %d\n", tt, block->map_pos.x + x, block->map_pos.y + y, block->map_pos.z); + out.print("Found tile %x @ %d %d %d\n", tt, block->map_pos.x + x, block->map_pos.y + y, block->map_pos.z); } } return CR_OK; diff --git a/plugins/devel/vectors.cpp b/plugins/devel/vectors.cpp index f49c85e06..0a453634b 100644 --- a/plugins/devel/vectors.cpp +++ b/plugins/devel/vectors.cpp @@ -24,14 +24,12 @@ struct t_vecTriplet void * alloc_end; }; -command_result df_vectors (Core * c, - vector & parameters); -command_result df_clearvec (Core * c, - vector & parameters); +command_result df_vectors (color_ostream &out, vector & parameters); +command_result df_clearvec (color_ostream &out, vector & parameters); DFHACK_PLUGIN("vectors"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand("vectors", "Scan memory for vectors.\ @@ -45,7 +43,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } @@ -94,11 +92,11 @@ static bool inAnyRange(vector &ranges, void * ptr) return false; } -static bool getHeapRanges(Core * c, std::vector &heap_ranges) +static bool getHeapRanges(color_ostream &out, std::vector &heap_ranges) { std::vector ranges; - c->p->getMemRanges(ranges); + Core::getInstance().p->getMemRanges(ranges); for (size_t i = 0; i < ranges.size(); i++) { @@ -116,7 +114,7 @@ static bool getHeapRanges(Core * c, std::vector &heap_ranges) if (heap_ranges.empty()) { - c->con << "No possible heap segments." << std::endl; + out << "No possible heap segments." << std::endl; return false; } @@ -127,13 +125,13 @@ static bool getHeapRanges(Core * c, std::vector &heap_ranges) // COMMAND: vectors //////////////////////////////////////// -static void vectorsUsage(Console &con) +static void vectorsUsage(color_ostream &con) { con << "Usage: vectors <# bytes to scan>" << std::endl; } -static void printVec(Console &con, const char* msg, t_vecTriplet *vec, +static void printVec(color_ostream &con, const char* msg, t_vecTriplet *vec, uint32_t start, uint32_t pos) { uint32_t length = (int)vec->end - (int)vec->start; @@ -143,10 +141,8 @@ static void printVec(Console &con, const char* msg, t_vecTriplet *vec, msg, offset, pos, vec->start, length); } -command_result df_vectors (Core * c, vector & parameters) +command_result df_vectors (color_ostream &con, vector & parameters) { - Console & con = c->con; - if (parameters.size() != 2) { vectorsUsage(con); @@ -173,14 +169,13 @@ command_result df_vectors (Core * c, vector & parameters) while (start % 4 != 0) start++; - c->Suspend(); + CoreSuspender suspend; std::vector heap_ranges; - if (!getHeapRanges(c, heap_ranges)) + if (!getHeapRanges(con, heap_ranges)) { return CR_FAILURE; - c->Resume(); } bool startInRange = false; @@ -208,7 +203,6 @@ command_result df_vectors (Core * c, vector & parameters) if (!startInRange) { con << "Address not in any memory range." << std::endl; - c->Resume(); return CR_FAILURE; } @@ -250,7 +244,6 @@ command_result df_vectors (Core * c, vector & parameters) } } // for (uint32_t pos = start; pos < end; pos += ptr_size) - c->Resume(); return CR_OK; } @@ -258,17 +251,15 @@ command_result df_vectors (Core * c, vector & parameters) // COMMAND: clearvec //////////////////////////////////////// -static void clearUsage(Console &con) +static void clearUsage(color_ostream &con) { con << "Usage: clearvec [vector2 addr] ..." << std::endl; con << "Address can be either for vector or pointer to vector." << std::endl; } -command_result df_clearvec (Core * c, vector & parameters) +command_result df_clearvec (color_ostream &con, vector & parameters) { - Console & con = c->con; - if (parameters.size() == 0) { clearUsage(con); @@ -289,13 +280,12 @@ command_result df_clearvec (Core * c, vector & parameters) return CR_FAILURE; } - c->Suspend(); + CoreSuspender suspend; std::vector heap_ranges; - if (!getHeapRanges(c, heap_ranges)) + if (!getHeapRanges(con, heap_ranges)) { - c->Resume(); return CR_FAILURE; } @@ -356,6 +346,5 @@ command_result df_clearvec (Core * c, vector & parameters) con << addr_str << " set to zero length." << std::endl; } // for (size_t i = 0; i < parameters.size(); i++) - c->Resume(); return CR_OK; } diff --git a/plugins/df2mc b/plugins/df2mc index f149da6ef..964026395 160000 --- a/plugins/df2mc +++ b/plugins/df2mc @@ -1 +1 @@ -Subproject commit f149da6efead3c46845d7478d1ff3d11119c589d +Subproject commit 964026395ce2138e4f861594307efda50b17e96c diff --git a/plugins/drybuckets.cpp b/plugins/drybuckets.cpp index 23b63bb44..431edd51b 100644 --- a/plugins/drybuckets.cpp +++ b/plugins/drybuckets.cpp @@ -19,12 +19,12 @@ using df::global::world; DFHACK_PLUGIN("drybuckets"); -command_result df_drybuckets (Core * c, vector & parameters) +command_result df_drybuckets (color_ostream &out, vector & parameters) { if (!parameters.empty()) return CR_WRONG_USAGE; - CoreSuspender suspend(c); + CoreSuspender suspend; int dried_total = 0; for (size_t i = 0; i < world->items.all.size(); i++) @@ -37,17 +37,17 @@ command_result df_drybuckets (Core * c, vector & parameters) } } if (dried_total) - c->con.print("Done. %d buckets of water marked for emptying.\n", dried_total); + out.print("Done. %d buckets of water marked for emptying.\n", dried_total); return CR_OK; } -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand("drybuckets", "Removes water from buckets.", df_drybuckets)); return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } diff --git a/plugins/dwarfexport/dwarfexport.cpp b/plugins/dwarfexport/dwarfexport.cpp index 6c997ca27..9cdf0573a 100644 --- a/plugins/dwarfexport/dwarfexport.cpp +++ b/plugins/dwarfexport/dwarfexport.cpp @@ -18,6 +18,8 @@ using namespace std; #include #include #include +#include +#include using namespace DFHack; using df::global::ui; @@ -30,12 +32,12 @@ using df::global::world; // 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 (Core * c, std::vector & parameters); +command_result export_dwarves (color_ostream &con, std::vector & parameters); DFHACK_PLUGIN("dwarfexport"); // Mandatory init function. If you have some global state, create it here. -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init (color_ostream &con, std::vector &commands) { // Fill the command list with your commands. commands.push_back(PluginCommand("dwarfexport", @@ -46,7 +48,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector } // This is called right before the plugin library is removed from memory. -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown (color_ostream &con) { return CR_OK; } @@ -84,7 +86,7 @@ static void element(const char* name, const uint32_t content, ostream& out, cons out << extra_indent << " <" << name << ">" << content << "" << endl; } -static void printAttributes(Core* c, df::unit* cre, ostream& out) { +static void printAttributes(color_ostream &con, df::unit* cre, ostream& out) { out << " " << endl; for (int i = 0; i < NUM_CREATURE_PHYSICAL_ATTRIBUTES; i++) { element(physicals[i], cre->body.physical_attrs[i].unk1, out, " "); @@ -99,7 +101,7 @@ static void printAttributes(Core* c, df::unit* cre, ostream& out) { out << " " << endl; } -static void printTraits(Core* c, df::unit* cre, ostream& out) +static void printTraits(color_ostream &con, df::unit* cre, ostream& out) { out << " " << endl; @@ -112,7 +114,7 @@ static void printTraits(Core* c, df::unit* cre, ostream& out) "' value='" << s->traits[index] << "'>"; //FIXME: needs reimplementing trait string generation /* - string trait = c->vinfo->getTrait(i, s->traits[i]); + string trait = con->vinfo->getTrait(i, s->traits[i]); if (!trait.empty()) { out << trait.c_str(); } @@ -124,46 +126,101 @@ static void printTraits(Core* c, df::unit* cre, ostream& out) out << " " << 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 << " " << endl; + for (int iCount = 0; iCount < sizeof(cre->status.labors); iCount++) + { + if (cre->status.labors[iCount]) { + // Get the caption for the labor index. + df::enums::unit_labor::unit_labor thisLabor = (df::enums::unit_labor::unit_labor)iCount; + element("Labour", get_caption(thisLabor), out); + } + } + out << " " << endl; +} + +static void printSkill(color_ostream &con, df::unit_skill* skill, ostream& out) +{ + out << " " << endl; + + element("Name", get_caption(skill->id), out); + element("Level", skill->rating, out); + + out << " " << endl; +} + +static void printSkills(color_ostream &con, df::unit* cre, ostream& out) +{ + + std::vector vSkills = cre->status.current_soul->skills; + + out << " " << endl; + for (int iCount = 0; iCount < vSkills.size(); iCount++) + { + printSkill(con, vSkills.at(iCount), out); + } + + out << " " << endl; +} + // GDC needs: // Name // Nickname // Sex // Attributes // Traits -static void export_dwarf(Core* c, df::unit* cre, ostream& out) { +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]); - c->con.print("Exporting %s\n", info.c_str()); - + con.print("Exporting %s\n", info.c_str()); + out << " " << endl; element("Name", info.c_str(), out); element("Nickname", cre->name.nickname.c_str(), out); element("Sex", cre->sex == 0 ? "Female" : "Male", out); - printAttributes(c, cre, out); - printTraits(c, cre, 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 << " " << endl; } -command_result export_dwarves (Core * c, std::vector & parameters) +command_result export_dwarves (color_ostream &con, std::vector & parameters) { string filename; if (parameters.size() == 1) { filename = parameters[0]; } else { - c->con.print("export \n"); + con.print("export \n"); return CR_OK; } ofstream outf(filename); if (!outf) { - c->con.printerr("Failed to open file %s\n", filename.c_str()); + con.printerr("Failed to open file %s\n", filename.c_str()); return CR_FAILURE; } - c->Suspend(); + CoreSuspender suspend; uint32_t race = ui->race_id; uint32_t civ = ui->civ_id; @@ -174,11 +231,10 @@ command_result export_dwarves (Core * c, std::vector & parameters) { df::unit* cre = world->units.all[i]; if (cre->race == race && cre->civ_id == civ) { - export_dwarf(c, cre, outf); + export_dwarf(con, cre, outf); } } outf << "" << endl; - c->Resume(); return CR_OK; } diff --git a/plugins/fastdwarf.cpp b/plugins/fastdwarf.cpp index 6cb6fabbc..87402e428 100644 --- a/plugins/fastdwarf.cpp +++ b/plugins/fastdwarf.cpp @@ -18,14 +18,14 @@ using df::global::ui; // dfhack interface DFHACK_PLUGIN("fastdwarf"); -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } static int enable_fastdwarf; -DFhackCExport command_result plugin_onupdate ( Core * c ) +DFhackCExport command_result plugin_onupdate ( color_ostream &out ) { if (!enable_fastdwarf) return CR_OK; @@ -43,7 +43,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) return CR_OK; } -static command_result fastdwarf (Core * c, vector & parameters) +static command_result fastdwarf (color_ostream &out, vector & parameters) { if (parameters.size() == 1 && (parameters[0] == "0" || parameters[0] == "1")) { @@ -51,11 +51,11 @@ static command_result fastdwarf (Core * c, vector & parameters) enable_fastdwarf = 0; else enable_fastdwarf = 1; - c->con.print("fastdwarf %sactivated.\n", (enable_fastdwarf ? "" : "de")); + out.print("fastdwarf %sactivated.\n", (enable_fastdwarf ? "" : "de")); } else { - c->con.print("Makes your minions move at ludicrous speeds.\n" + out.print("Makes your minions move at ludicrous speeds.\n" "Activate with 'fastdwarf 1', deactivate with 'fastdwarf 0'.\n" "Current state: %d.\n", enable_fastdwarf); } @@ -63,7 +63,7 @@ static command_result fastdwarf (Core * c, vector & parameters) return CR_OK; } -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand("fastdwarf", "enable/disable fastdwarf (parameter=0/1)", diff --git a/plugins/filltraffic.cpp b/plugins/filltraffic.cpp index 37d036868..6e87fd854 100644 --- a/plugins/filltraffic.cpp +++ b/plugins/filltraffic.cpp @@ -21,13 +21,13 @@ using namespace df::enums; typedef void (*checkTile)(DFCoord, MapExtras::MapCache &); //Forward Declarations for Commands -command_result filltraffic(Core * c, std::vector & params); -command_result alltraffic(Core * c, std::vector & params); +command_result filltraffic(color_ostream &out, std::vector & params); +command_result alltraffic(color_ostream &out, std::vector & params); //Forward Declarations for Utility Functions -command_result setAllMatching(Core * c, checkTile checkProc, -DFCoord minCoord = DFCoord(0, 0, 0), -DFCoord maxCoord = DFCoord(0xFFFF, 0xFFFF, 0xFFFF)); +command_result setAllMatching(color_ostream &out, checkTile checkProc, + DFCoord minCoord = DFCoord(0, 0, 0), + DFCoord maxCoord = DFCoord(0xFFFF, 0xFFFF, 0xFFFF)); void allHigh(DFCoord coord, MapExtras::MapCache & map); void allNormal(DFCoord coord, MapExtras::MapCache & map); @@ -36,7 +36,7 @@ void allRestricted(DFCoord coord, MapExtras::MapCache & map); DFHACK_PLUGIN("filltraffic"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand( "filltraffic","Flood-fill with selected traffic designation from cursor", @@ -69,12 +69,12 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -command_result filltraffic(Core * c, std::vector & params) +command_result filltraffic(color_ostream &out, std::vector & params) { // HOTKEY COMMAND; CORE ALREADY SUSPENDED @@ -117,7 +117,7 @@ command_result filltraffic(Core * c, std::vector & params) if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } @@ -128,7 +128,7 @@ command_result filltraffic(Core * c, std::vector & params) Gui::getCursorCoords(cx,cy,cz); while(cx == -30000) { - c->con.printerr("Cursor is not active.\n"); + out.printerr("Cursor is not active.\n"); return CR_FAILURE; } @@ -145,29 +145,29 @@ command_result filltraffic(Core * c, std::vector & params) source = (df::tile_traffic)des.bits.traffic; if(source == target) { - c->con.printerr("This tile is already set to the target traffic type.\n"); + out.printerr("This tile is already set to the target traffic type.\n"); return CR_FAILURE; } if(isWallTerrain(tt)) { - c->con.printerr("This tile is a wall. Please select a passable tile.\n"); + out.printerr("This tile is a wall. Please select a passable tile.\n"); return CR_FAILURE; } if(checkpit && isOpenTerrain(tt)) { - c->con.printerr("This tile is a hole. Please select a passable tile.\n"); + out.printerr("This tile is a hole. Please select a passable tile.\n"); return CR_FAILURE; } if(checkbuilding && oc.bits.building) { - c->con.printerr("This tile contains a building. Please select an empty tile.\n"); + out.printerr("This tile contains a building. Please select an empty tile.\n"); return CR_FAILURE; } - c->con.print("%d/%d/%d ... FILLING!\n", cx,cy,cz); + out.print("%d/%d/%d ... FILLING!\n", cx,cy,cz); //Naive four-way or six-way flood fill with possible tiles on a stack. stack flood; @@ -236,7 +236,7 @@ command_result filltraffic(Core * c, std::vector & params) enum e_checktype {no_check, check_equal, check_nequal}; -command_result alltraffic(Core * c, std::vector & params) +command_result alltraffic(color_ostream &out, std::vector & params) { void (*proc)(DFCoord, MapExtras::MapCache &) = allNormal; @@ -262,22 +262,22 @@ command_result alltraffic(Core * c, std::vector & params) } } - return setAllMatching(c, proc); + return setAllMatching(out, proc); } //Helper function for writing new functions that check every tile on the map. //newTraffic is the traffic designation to set. //check takes a coordinate and the map cache as arguments, and returns true if the criteria is met. //minCoord and maxCoord can be used to specify a bounding cube. -command_result setAllMatching(Core * c, checkTile checkProc, - DFCoord minCoord, DFCoord maxCoord) +command_result setAllMatching(color_ostream &out, checkTile checkProc, + DFCoord minCoord, DFCoord maxCoord) { //Initialization. - CoreSuspender suspend(c); + CoreSuspender suspend; if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } @@ -295,23 +295,23 @@ command_result setAllMatching(Core * c, checkTile checkProc, //Check minimum co-ordinates against maximum map size if (minCoord.x > maxCoord.x) { - c->con.printerr("Minimum x coordinate is greater than maximum x coordinate.\n"); + out.printerr("Minimum x coordinate is greater than maximum x coordinate.\n"); return CR_FAILURE; } if (minCoord.y > maxCoord.y) { - c->con.printerr("Minimum y coordinate is greater than maximum y coordinate.\n"); + out.printerr("Minimum y coordinate is greater than maximum y coordinate.\n"); return CR_FAILURE; } if (minCoord.z > maxCoord.y) { - c->con.printerr("Minimum z coordinate is greater than maximum z coordinate.\n"); + out.printerr("Minimum z coordinate is greater than maximum z coordinate.\n"); return CR_FAILURE; } MapExtras::MapCache MCache; - c->con.print("Setting traffic...\n"); + out.print("Setting traffic...\n"); //Loop through every single tile for(uint32_t x = minCoord.x; x <= maxCoord.x; x++) @@ -327,7 +327,7 @@ command_result setAllMatching(Core * c, checkTile checkProc, } MCache.WriteAll(); - c->con.print("Complete!\n"); + out.print("Complete!\n"); return CR_OK; } diff --git a/plugins/fixpositions.cpp b/plugins/fixpositions.cpp index 76f3e06ef..086848fec 100644 --- a/plugins/fixpositions.cpp +++ b/plugins/fixpositions.cpp @@ -20,12 +20,13 @@ using namespace df::enums; using df::global::world; -command_result df_fixdiplomats (Core *c, vector ¶meters) +command_result df_fixdiplomats (color_ostream &out, vector ¶meters) { if (!parameters.empty()) return CR_WRONG_USAGE; - CoreSuspender suspend(c); + CoreSuspender suspend; + int checked = 0, fixed = 0; for (int i = 0; i < world->entities.all.size(); i++) { @@ -120,16 +121,17 @@ command_result df_fixdiplomats (Core *c, vector ¶meters) if (update || assign) fixed++; } - c->con.print("Fixed %d of %d civilizations to enable tree cap diplomacy.\n", fixed, checked); + out.print("Fixed %d of %d civilizations to enable tree cap diplomacy.\n", fixed, checked); return CR_OK; } -command_result df_fixmerchants (Core *c, vector ¶meters) +command_result df_fixmerchants (color_ostream &out, vector ¶meters) { if (!parameters.empty()) return CR_WRONG_USAGE; - CoreSuspender suspend(c); + CoreSuspender suspend; + int checked = 0, fixed = 0; for (int i = 0; i < world->entities.all.size(); i++) { @@ -220,13 +222,13 @@ command_result df_fixmerchants (Core *c, vector ¶meters) if (update || assign) fixed++; } - c->con.print("Fixed %d of %d civilizations to enable merchant nobility.\n", fixed, checked); + out.print("Fixed %d of %d civilizations to enable merchant nobility.\n", fixed, checked); return CR_OK; } DFHACK_PLUGIN("fixpositions"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand( "fixdiplomats", "Add Diplomat position to Elven civilizations for tree cap diplomacy.", @@ -237,7 +239,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } diff --git a/plugins/fixveins.cpp b/plugins/fixveins.cpp index de6ddf810..474201a81 100644 --- a/plugins/fixveins.cpp +++ b/plugins/fixveins.cpp @@ -34,16 +34,16 @@ bool setTileMaterial(df::tiletype &tile, const df::tiletype_material mat) return false; } -command_result df_fixveins (Core * c, vector & parameters) +command_result df_fixveins (color_ostream &out, vector & parameters) { if (parameters.size()) return CR_WRONG_USAGE; - CoreSuspender suspend(c); + CoreSuspender suspend; if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } @@ -90,15 +90,15 @@ command_result df_fixveins (Core * c, vector & parameters) } } if (mineral_removed || feature_removed) - c->con.print("Removed invalid references from %i mineral inclusion and %i map feature tiles.\n", mineral_removed, feature_removed); + out.print("Removed invalid references from %i mineral inclusion and %i map feature tiles.\n", mineral_removed, feature_removed); if (mineral_added || feature_added) - c->con.print("Restored missing references to %i mineral inclusion and %i map feature tiles.\n", mineral_added, feature_added); + out.print("Restored missing references to %i mineral inclusion and %i map feature tiles.\n", mineral_added, feature_added); return CR_OK; } DFHACK_PLUGIN("fixveins"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand("fixveins", "Remove invalid references to mineral inclusions and restore missing ones.", @@ -106,7 +106,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } diff --git a/plugins/flows.cpp b/plugins/flows.cpp index 287dbc2c9..26188f512 100644 --- a/plugins/flows.cpp +++ b/plugins/flows.cpp @@ -17,12 +17,12 @@ using namespace df::enums; using df::global::world; -command_result df_flows (Core * c, vector & parameters) +command_result df_flows (color_ostream &out, vector & parameters) { - CoreSuspender suspend(c); + CoreSuspender suspend; int flow1 = 0, flow2 = 0, flowboth = 0, water = 0, magma = 0; - c->con.print("Counting flows and liquids ...\n"); + out.print("Counting flows and liquids ...\n"); for (size_t i = 0; i < world->map.map_blocks.size(); i++) { @@ -48,17 +48,17 @@ command_result df_flows (Core * c, vector & parameters) } } - c->con.print("Blocks with liquid_1=true: %d\n", flow1); - c->con.print("Blocks with liquid_2=true: %d\n", flow2); - c->con.print("Blocks with both: %d\n", flowboth); - c->con.print("Water tiles: %d\n", water); - c->con.print("Magma tiles: %d\n", magma); + out.print("Blocks with liquid_1=true: %d\n", flow1); + out.print("Blocks with liquid_2=true: %d\n", flow2); + out.print("Blocks with both: %d\n", flowboth); + out.print("Water tiles: %d\n", water); + out.print("Magma tiles: %d\n", magma); return CR_OK; } DFHACK_PLUGIN("flows"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand("flows", "Counts map blocks with flowing liquids.", @@ -66,7 +66,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } diff --git a/plugins/follow.cpp b/plugins/follow.cpp index aa165899e..b383d95ce 100644 --- a/plugins/follow.cpp +++ b/plugins/follow.cpp @@ -17,7 +17,7 @@ using namespace DFHack; using namespace df::enums; -command_result follow (Core * c, std::vector & parameters); +command_result follow (color_ostream &out, std::vector & parameters); df::unit *followedUnit; int32_t prevX, prevY, prevZ; @@ -25,12 +25,13 @@ uint8_t prevMenuWidth; DFHACK_PLUGIN("follow"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.push_back(PluginCommand( "follow", "Follow the selected unit until camera control is released", follow, Gui::view_unit_hotkey, - " Select a unit and run this plugin to make the camera follow it. Moving the camera yourself deactivates the plugin.\n" + " Select a unit and run this plugin to make the camera follow it.\n" + " Moving the camera yourself deactivates the plugin.\n" )); followedUnit = 0; prevX=prevY=prevZ = -1; @@ -39,12 +40,12 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event event) +DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) { switch (event) { case SC_GAME_LOADED: @@ -60,11 +61,11 @@ DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event ev } -DFhackCExport command_result plugin_onupdate ( Core * c ) +DFhackCExport command_result plugin_onupdate ( color_ostream &out ) { if (!followedUnit) return CR_OK; //Don't do anything if we're not following a unit - DFHack::World *world =c->getWorld(); + DFHack::World *world = Core::getInstance().getWorld(); if (world->ReadPauseState() && prevX==-1) return CR_OK; //Wait until the game is unpaused after first running "follow" to begin following df::coord &unitPos = followedUnit->pos; @@ -100,7 +101,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) followedUnit = 0; prevX=prevY=prevZ = -1; prevMenuWidth = 0; - c->con.print("No longer following anything.\n"); + out.print("No longer following anything.\n"); return CR_OK; } @@ -131,7 +132,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) return CR_OK; } -command_result follow (Core * c, std::vector & parameters) +command_result follow (color_ostream &out, std::vector & parameters) { // HOTKEY COMMAND: CORE ALREADY SUSPENDED @@ -140,17 +141,17 @@ command_result follow (Core * c, std::vector & parameters) if (followedUnit) { - c->con.print("No longer following previously selected unit.\n"); + out.print("No longer following previously selected unit.\n"); followedUnit = 0; } - followedUnit = Gui::getSelectedUnit(c); + followedUnit = Gui::getSelectedUnit(out); if (followedUnit) { std::ostringstream ss; ss << "Unpause to begin following " << df::global::world->raws.creatures.all[followedUnit->race]->name[0]; if (followedUnit->name.has_name) ss << " " << followedUnit->name.first_name; ss << ". Simply manually move the view to break the following.\n"; - c->con.print(ss.str().c_str()); + out.print(ss.str().c_str()); } else followedUnit = 0; return CR_OK; diff --git a/plugins/getplants.cpp b/plugins/getplants.cpp index 0c58f7a6e..56c8457cc 100644 --- a/plugins/getplants.cpp +++ b/plugins/getplants.cpp @@ -23,7 +23,7 @@ using namespace df::enums; using df::global::world; -command_result df_getplants (Core * c, vector & parameters) +command_result df_getplants (color_ostream &out, vector & parameters) { string plantMatStr = ""; set plantIDs; @@ -50,21 +50,21 @@ command_result df_getplants (Core * c, vector & parameters) } if (treesonly && shrubsonly) { - c->con.printerr("Cannot specify both -t and -s at the same time!\n"); + out.printerr("Cannot specify both -t and -s at the same time!\n"); return CR_WRONG_USAGE; } if (all && exclude) { - c->con.printerr("Cannot specify both -a and -x at the same time!\n"); + out.printerr("Cannot specify both -a and -x at the same time!\n"); return CR_WRONG_USAGE; } if (all && plantNames.size()) { - c->con.printerr("Cannot specify -a along with plant IDs!\n"); + out.printerr("Cannot specify -a along with plant IDs!\n"); return CR_WRONG_USAGE; } - CoreSuspender suspend(c); + CoreSuspender suspend; for (size_t i = 0; i < world->raws.plants.all.size(); i++) { @@ -79,22 +79,22 @@ command_result df_getplants (Core * c, vector & parameters) } if (plantNames.size() > 0) { - c->con.printerr("Invalid plant ID(s):"); + out.printerr("Invalid plant ID(s):"); for (set::const_iterator it = plantNames.begin(); it != plantNames.end(); it++) - c->con.printerr(" %s", it->c_str()); - c->con.printerr("\n"); + out.printerr(" %s", it->c_str()); + out.printerr("\n"); return CR_FAILURE; } if (plantIDs.size() == 0) { - c->con.print("Valid plant IDs:\n"); + out.print("Valid plant IDs:\n"); for (size_t i = 0; i < world->raws.plants.all.size(); i++) { df::plant_raw *plant = world->raws.plants.all[i]; if (plant->flags.is_set(plant_raw_flags::GRASS)) continue; - c->con.print("* (%s) %s - %s\n", plant->flags.is_set(plant_raw_flags::TREE) ? "tree" : "shrub", plant->id.c_str(), plant->name.c_str()); + out.print("* (%s) %s - %s\n", plant->flags.is_set(plant_raw_flags::TREE) ? "tree" : "shrub", plant->id.c_str(), plant->name.c_str()); } return CR_OK; } @@ -144,13 +144,13 @@ command_result df_getplants (Core * c, vector & parameters) cur->flags.bits.designated = true; } if (count) - c->con.print("Updated %d plant designations.\n", count); + out.print("Updated %d plant designations.\n", count); return CR_OK; } DFHACK_PLUGIN("getplants"); -DFhackCExport command_result plugin_init ( Core * c, vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, vector &commands) { commands.push_back(PluginCommand( "getplants", "Cut down all of the specified trees or gather specified shrubs", @@ -169,7 +169,7 @@ DFhackCExport command_result plugin_init ( Core * c, vector &com return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } diff --git a/plugins/initflags.cpp b/plugins/initflags.cpp index 1125b625b..6aa78930a 100644 --- a/plugins/initflags.cpp +++ b/plugins/initflags.cpp @@ -14,12 +14,12 @@ using namespace df::enums; using df::global::d_init; -command_result twaterlvl(Core * c, vector & parameters); -command_result tidlers(Core * c, vector & parameters); +command_result twaterlvl(color_ostream &out, vector & parameters); +command_result tidlers(color_ostream &out, vector & parameters); DFHACK_PLUGIN("initflags"); -DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) { if (d_init) { commands.push_back(PluginCommand("twaterlvl", "Toggle display of water/magma depth.", @@ -31,23 +31,23 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -command_result twaterlvl(Core * c, vector & parameters) +command_result twaterlvl(color_ostream &out, vector & parameters) { // HOTKEY COMMAND: CORE ALREADY SUSPENDED d_init->flags1.toggle(d_init_flags1::SHOW_FLOW_AMOUNTS); - c->con << "Toggled the display of water/magma depth." << endl; + out << "Toggled the display of water/magma depth." << endl; return CR_OK; } -command_result tidlers(Core * c, vector & parameters) +command_result tidlers(color_ostream &out, vector & parameters) { // HOTKEY COMMAND: CORE ALREADY SUSPENDED d_init->idlers = ENUM_NEXT_ITEM(d_init_idlers, d_init->idlers); - c->con << "Toggled the display of idlers to " << ENUM_KEY_STR(d_init_idlers, d_init->idlers) << endl; + out << "Toggled the display of idlers to " << ENUM_KEY_STR(d_init_idlers, d_init->idlers) << endl; return CR_OK; } diff --git a/plugins/jobutils.cpp b/plugins/jobutils.cpp index e81414238..ca234423a 100644 --- a/plugins/jobutils.cpp +++ b/plugins/jobutils.cpp @@ -39,15 +39,15 @@ using df::global::job_next_id; /* Plugin registration */ -static bool job_material_hotkey(Core *c, df::viewscreen *top); +static bool job_material_hotkey(df::viewscreen *top); -static command_result job_material(Core *c, vector & parameters); -static command_result job_duplicate(Core *c, vector & parameters); -static command_result job_cmd(Core *c, vector & parameters); +static command_result job_material(color_ostream &out, vector & parameters); +static command_result job_duplicate(color_ostream &out, vector & parameters); +static command_result job_cmd(color_ostream &out, vector & parameters); DFHACK_PLUGIN("jobutils"); -DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) { if (!world || !ui) return CR_FAILURE; @@ -99,31 +99,31 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } /* UI state guards */ -static bool job_material_hotkey(Core *c, df::viewscreen *top) +static bool job_material_hotkey(df::viewscreen *top) { - return Gui::workshop_job_hotkey(c, top) || - Gui::build_selector_hotkey(c, top); + return Gui::workshop_job_hotkey(top) || + Gui::build_selector_hotkey(top); } /* job-material implementation */ -static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) +static command_result job_material_in_job(color_ostream &out, MaterialInfo &new_mat) { - df::job *job = Gui::getSelectedWorkshopJob(c); + df::job *job = Gui::getSelectedWorkshopJob(out); if (!job) return CR_FAILURE; if (!new_mat.isValid() || new_mat.type != 0) { - c->con.printerr("New job material isn't inorganic: %s\n", - new_mat.toString().c_str()); + out.printerr("New job material isn't inorganic: %s\n", + new_mat.toString().c_str()); return CR_FAILURE; } @@ -131,22 +131,22 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) if (!cur_mat.isValid() || cur_mat.type != 0) { - c->con.printerr("Current job material isn't inorganic: %s\n", - cur_mat.toString().c_str()); + out.printerr("Current job material isn't inorganic: %s\n", + cur_mat.toString().c_str()); return CR_FAILURE; } df::craft_material_class old_class = cur_mat.getCraftClass(); if (old_class == craft_material_class::None) { - c->con.printerr("Unexpected current material type: %s\n", - cur_mat.toString().c_str()); + out.printerr("Unexpected current material type: %s\n", + cur_mat.toString().c_str()); return CR_FAILURE; } if (new_mat.getCraftClass() != old_class) { - c->con.printerr("New material %s does not satisfy requirement: %s\n", - new_mat.toString().c_str(), ENUM_KEY_STR(craft_material_class, old_class)); + out.printerr("New material %s does not satisfy requirement: %s\n", + new_mat.toString().c_str(), ENUM_KEY_STR(craft_material_class, old_class)); return CR_FAILURE; } @@ -157,15 +157,15 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) if (item_mat != cur_mat) { - c->con.printerr("Job item %d has different material: %s\n", - i, item_mat.toString().c_str()); + out.printerr("Job item %d has different material: %s\n", + i, item_mat.toString().c_str()); return CR_FAILURE; } if (!new_mat.matches(*item)) { - c->con.printerr("Job item %d requirements not satisfied by %s.\n", - i, new_mat.toString().c_str()); + out.printerr("Job item %d requirements not satisfied by %s.\n", + i, new_mat.toString().c_str()); return CR_FAILURE; } } @@ -181,8 +181,8 @@ static command_result job_material_in_job(Core *c, MaterialInfo &new_mat) item->mat_index = new_mat.index; } - c->con << "Applied material '" << new_mat.toString() - << "' to job " << ENUM_KEY_STR(job_type,job->job_type) << endl; + out << "Applied material '" << new_mat.toString() + << "' to job " << ENUM_KEY_STR(job_type,job->job_type) << endl; return CR_OK; } @@ -212,7 +212,7 @@ static bool build_choice_matches(df::ui_build_item_req *req, df::build_req_choic return false; } -static command_result job_material_in_build(Core *c, MaterialInfo &new_mat) +static command_result job_material_in_build(color_ostream &out, MaterialInfo &new_mat) { df::ui_build_selector *sel = ui_build_selector; df::ui_build_item_req *req = sel->requirements[ui_build_selector->req_index]; @@ -234,11 +234,11 @@ static command_result job_material_in_build(Core *c, MaterialInfo &new_mat) } } - c->con.printerr("Could not find material in list: %s\n", new_mat.toString().c_str()); + out.printerr("Could not find material in list: %s\n", new_mat.toString().c_str()); return CR_FAILURE; } -static command_result job_material(Core * c, vector & parameters) +static command_result job_material(color_ostream &out, vector & parameters) { // HOTKEY COMMAND: CORE ALREADY SUSPENDED @@ -246,7 +246,7 @@ static command_result job_material(Core * c, vector & parameters) if (parameters.size() == 1) { if (!new_mat.find(parameters[0])) { - c->con.printerr("Could not find material: %s\n", parameters[0].c_str()); + out.printerr("Could not find material: %s\n", parameters[0].c_str()); return CR_WRONG_USAGE; } } @@ -254,21 +254,21 @@ static command_result job_material(Core * c, vector & parameters) return CR_WRONG_USAGE; if (ui->main.mode == ui_sidebar_mode::QueryBuilding) - return job_material_in_job(c, new_mat); + return job_material_in_job(out, new_mat); if (ui->main.mode == ui_sidebar_mode::Build) - return job_material_in_build(c, new_mat); + return job_material_in_build(out, new_mat); return CR_WRONG_USAGE; } /* job-duplicate implementation */ -static command_result job_duplicate(Core * c, vector & parameters) +static command_result job_duplicate(color_ostream &out, vector & parameters) { if (!parameters.empty()) return CR_WRONG_USAGE; - df::job *job = Gui::getSelectedWorkshopJob(c); + df::job *job = Gui::getSelectedWorkshopJob(out); if (!job) return CR_FAILURE; @@ -277,14 +277,14 @@ static command_result job_duplicate(Core * c, vector & parameters) job->job_type != job_type::CollectSand && job->job_type != job_type::CollectClay)) { - c->con.printerr("Cannot duplicate job %s\n", ENUM_KEY_STR(job_type,job->job_type)); + out.printerr("Cannot duplicate job %s\n", ENUM_KEY_STR(job_type,job->job_type)); return CR_FAILURE; } df::building *building = world->selected_building; if (building->jobs.size() >= 10) { - c->con.printerr("Job list is already full.\n"); + out.printerr("Job list is already full.\n"); return CR_FAILURE; } @@ -299,40 +299,40 @@ static command_result job_duplicate(Core * c, vector & parameters) /* Main job command implementation */ -static df::job_item *getJobItem(Core *c, df::job *job, std::string idx) +static df::job_item *getJobItem(color_ostream &out, df::job *job, std::string idx) { if (!job) return NULL; int v = atoi(idx.c_str()); if (v < 1 || v > job->job_items.size()) { - c->con.printerr("Invalid item index.\n"); + out.printerr("Invalid item index.\n"); return NULL; } return job->job_items[v-1]; } -static command_result job_cmd(Core * c, vector & parameters) +static command_result job_cmd(color_ostream &out, vector & parameters) { - CoreSuspender suspend(c); + CoreSuspender suspend; std::string cmd = (parameters.empty() ? "query" : parameters[0]); if (cmd == "query" || cmd == "list") { - df::job *job = Gui::getSelectedJob(c); + df::job *job = Gui::getSelectedJob(out); if (!job) return CR_WRONG_USAGE; if (cmd == "query") { - printJobDetails(c, job); + printJobDetails(out, job); } else { - if (!Gui::workshop_job_hotkey(c, c->getTopViewscreen())) + if (!Gui::workshop_job_hotkey(Core::getTopViewscreen())) return CR_WRONG_USAGE; df::building *selected = world->selected_building; for (size_t i = 0; i < selected->jobs.size(); i++) - printJobDetails(c, selected->jobs[i]); + printJobDetails(out, selected->jobs[i]); } } else if (cmd == "item-material") @@ -340,8 +340,8 @@ static command_result job_cmd(Core * c, vector & parameters) if (parameters.size() != 3) return CR_WRONG_USAGE; - df::job *job = Gui::getSelectedJob(c); - df::job_item *item = getJobItem(c, job, parameters[1]); + df::job *job = Gui::getSelectedJob(out); + df::job_item *item = getJobItem(out, job, parameters[1]); if (!item) return CR_WRONG_USAGE; @@ -349,13 +349,13 @@ static command_result job_cmd(Core * c, vector & parameters) MaterialInfo minfo; if (!minfo.find(parameters[2])) { - c->con.printerr("Could not find the specified material.\n"); + out.printerr("Could not find the specified material.\n"); return CR_FAILURE; } if (minfo.isValid() && !iinfo.matches(*item, &minfo)) { - c->con.printerr("Material does not match the requirements.\n"); - printJobDetails(c, job); + out.printerr("Material does not match the requirements.\n"); + printJobDetails(out, job); return CR_FAILURE; } @@ -370,13 +370,13 @@ static command_result job_cmd(Core * c, vector & parameters) item->mat_type = minfo.type; item->mat_index = minfo.index; - c->con << "Job item updated." << endl; + out << "Job item updated." << endl; if (item->item_type < 0 && minfo.isValid()) - c->con.printerr("WARNING: Due to a probable bug, creature & plant material subtype\n" + out.printerr("WARNING: Due to a probable bug, creature & plant material subtype\n" " is ignored unless the item type is also specified.\n"); - printJobDetails(c, job); + printJobDetails(out, job); return CR_OK; } else if (cmd == "item-type") @@ -384,8 +384,8 @@ static command_result job_cmd(Core * c, vector & parameters) if (parameters.size() != 3) return CR_WRONG_USAGE; - df::job *job = Gui::getSelectedJob(c); - df::job_item *item = getJobItem(c, job, parameters[1]); + df::job *job = Gui::getSelectedJob(out); + df::job_item *item = getJobItem(out, job, parameters[1]); if (!item) return CR_WRONG_USAGE; @@ -393,21 +393,21 @@ static command_result job_cmd(Core * c, vector & parameters) MaterialInfo minfo(item); if (!iinfo.find(parameters[2])) { - c->con.printerr("Could not find the specified item type.\n"); + out.printerr("Could not find the specified item type.\n"); return CR_FAILURE; } if (iinfo.isValid() && !iinfo.matches(*item, &minfo)) { - c->con.printerr("Item type does not match the requirements.\n"); - printJobDetails(c, job); + out.printerr("Item type does not match the requirements.\n"); + printJobDetails(out, job); return CR_FAILURE; } item->item_type = iinfo.type; item->item_subtype = iinfo.subtype; - c->con << "Job item updated." << endl; - printJobDetails(c, job); + out << "Job item updated." << endl; + printJobDetails(out, job); return CR_OK; } else diff --git a/plugins/liquids.cpp b/plugins/liquids.cpp index 9e26a9e9b..aff45b66e 100644 --- a/plugins/liquids.cpp +++ b/plugins/liquids.cpp @@ -26,11 +26,11 @@ typedef vector coord_vec; CommandHistory liquids_hist; -command_result df_liquids (Core * c, vector & parameters); +command_result df_liquids (color_ostream &out, vector & parameters); DFHACK_PLUGIN("liquids"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { liquids_hist.load("liquids.history"); commands.clear(); @@ -38,7 +38,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { liquids_hist.save("liquids.history"); return CR_OK; @@ -220,15 +220,18 @@ private: Core *c_; }; -command_result df_liquids (Core * c, vector & parameters) +command_result df_liquids (color_ostream &out_, vector & parameters) { int32_t x,y,z; + assert(out_.is_console()); + Console &out = static_cast(out_); + for(size_t i = 0; i < parameters.size();i++) { if(parameters[i] == "help" || parameters[i] == "?") { - c->con.print("This tool allows placing magma, water and other similar things.\n" + out.print("This tool allows placing magma, water and other similar things.\n" "It is interactive and further help is available when you run it.\n" ); return CR_OK; @@ -237,14 +240,14 @@ command_result df_liquids (Core * c, vector & parameters) if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } Brush * brush = new RectangleBrush(1,1); string brushname = "point"; bool end = false; - c->con << "Welcome to the liquid spawner.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl; + out << "Welcome to the liquid spawner.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl; string mode="magma"; string flowmode="f+"; @@ -256,11 +259,11 @@ command_result df_liquids (Core * c, vector & parameters) string command = ""; std::stringstream str; str <<"[" << mode << ":" << brushname << ":" << amount << ":" << flowmode << ":" << setmode << "]#"; - if(c->con.lineedit(str.str(),command,liquids_hist) == -1) + if(out.lineedit(str.str(),command,liquids_hist) == -1) return CR_FAILURE; if(command=="help" || command == "?") { - c->con << "Modes:" << endl + out << "Modes:" << endl << "m - switch to magma" << endl << "w - switch to water" << endl << "o - make obsidian wall instead" << endl @@ -333,21 +336,21 @@ command_result df_liquids (Core * c, vector & parameters) std::stringstream str; CommandHistory range_hist; str << " :set range width<" << width << "># "; - c->con.lineedit(str.str(),command,range_hist); + out.lineedit(str.str(),command,range_hist); range_hist.add(command); width = command == "" ? width : atoi (command.c_str()); if(width < 1) width = 1; str.str(""); str << " :set range height<" << height << "># "; - c->con.lineedit(str.str(),command,range_hist); + out.lineedit(str.str(),command,range_hist); range_hist.add(command); height = command == "" ? height : atoi (command.c_str()); if(height < 1) height = 1; str.str(""); str << " :set range z-levels<" << z_levels << "># "; - c->con.lineedit(str.str(),command,range_hist); + out.lineedit(str.str(),command,range_hist); range_hist.add(command); z_levels = command == "" ? z_levels : atoi (command.c_str()); if(z_levels < 1) z_levels = 1; @@ -378,7 +381,7 @@ command_result df_liquids (Core * c, vector & parameters) { delete brush; brushname = "flood"; - brush = new FloodBrush(c); + brush = new FloodBrush(&Core::getInstance()); } else if(command == "q") { @@ -427,24 +430,25 @@ command_result df_liquids (Core * c, vector & parameters) amount = 7; else if(command.empty()) { - CoreSuspender suspend(c); + CoreSuspender suspend; + do { if (!Maps::IsValid()) { - c->con << "Can't see any DF map loaded." << endl; + out << "Can't see any DF map loaded." << endl; break;; } if(!Gui::getCursorCoords(x,y,z)) { - c->con << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl; + out << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl; break; } - c->con << "cursor coords: " << x << "/" << y << "/" << z << endl; + out << "cursor coords: " << x << "/" << y << "/" << z << endl; MapCache mcache; DFHack::DFCoord cursor(x,y,z); coord_vec all_tiles = brush->points(mcache,cursor); - c->con << "working..." << endl; + out << "working..." << endl; if(mode == "obsidian") { coord_vec::iterator iter = all_tiles.begin(); @@ -584,21 +588,21 @@ command_result df_liquids (Core * c, vector & parameters) } else { - c->con << "flow bit 1 = " << bflags.bits.liquid_1 << endl; - c->con << "flow bit 2 = " << bflags.bits.liquid_2 << endl; + out << "flow bit 1 = " << bflags.bits.liquid_1 << endl; + out << "flow bit 2 = " << bflags.bits.liquid_2 << endl; } biter ++; } } if(mcache.WriteAll()) - c->con << "OK" << endl; + out << "OK" << endl; else - c->con << "Something failed horribly! RUN!" << endl; + out << "Something failed horribly! RUN!" << endl; } while (0); } else { - c->con << command << " : unknown command." << endl; + out << command << " : unknown command." << endl; } } return CR_OK; diff --git a/plugins/mapexport/CMakeLists.txt b/plugins/mapexport/CMakeLists.txt index d3ff25857..bebdd08ee 100644 --- a/plugins/mapexport/CMakeLists.txt +++ b/plugins/mapexport/CMakeLists.txt @@ -1,15 +1,5 @@ PROJECT(mapexport) -INCLUDE_DIRECTORIES ( - ${CMAKE_CURRENT_SOURCE_DIR} - ${dfhack_SOURCE_DIR}/library/depends/protobuf/ - ${dfhack_SOURCE_DIR}/library/depends/zlib/ -) - -LINK_DIRECTORIES( - ${dfhack_SOURCE_DIR}/library/depends/zlib/ -) - #The protobuf sources we generate will require these headers SET(PROJECT_HDRS ${dfhack_SOURCE_DIR}/library/depends/protobuf/google/protobuf/stubs/once.h @@ -51,7 +41,7 @@ DEPENDS protoc-bin ${PROJECT_PROTOS} ) IF(WIN32) - DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf zlib) + DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf-lite) ELSE() - DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf z) + DFHACK_PLUGIN(mapexport ${PROJECT_SRCS} ${PROJECT_HDRS} LINK_LIBRARIES protobuf-lite) ENDIF() diff --git a/plugins/mapexport/mapexport.cpp b/plugins/mapexport/mapexport.cpp index 2e5197718..c87613fa5 100644 --- a/plugins/mapexport/mapexport.cpp +++ b/plugins/mapexport/mapexport.cpp @@ -23,11 +23,11 @@ using df::global::world; typedef std::vector PlantList; -command_result mapexport (Core * c, std::vector & parameters); +command_result mapexport (color_ostream &out, std::vector & parameters); DFHACK_PLUGIN("mapexport"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { GOOGLE_PROTOBUF_VERIFY_VERSION; commands.clear(); @@ -35,13 +35,12 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { - google::protobuf::ShutdownProtobufLibrary(); return CR_OK; } -command_result mapexport (Core * c, std::vector & parameters) +command_result mapexport (color_ostream &out, std::vector & parameters) { bool showHidden = false; @@ -51,7 +50,7 @@ command_result mapexport (Core * c, std::vector & parameters) { if(parameters[i] == "help" || parameters[i] == "?") { - c->con.print("Exports the currently visible map to a file.\n" + out.print("Exports the currently visible map to a file.\n" "Usage: mapexport [options] \n" "Example: mapexport all embark.dfmap\n" "Options:\n" @@ -66,32 +65,30 @@ command_result mapexport (Core * c, std::vector & parameters) } } + CoreSuspender suspend; uint32_t x_max=0, y_max=0, z_max=0; - c->Suspend(); + if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); - c->Resume(); + out.printerr("Map is not available!\n"); return CR_FAILURE; } if (parameters.size() < filenameParameter) { - c->con.printerr("Please supply a filename.\n"); - c->Resume(); + 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"; - c->con << "Writing to " << filename << "..." << std::endl; + out << "Writing to " << filename << "..." << std::endl; std::ofstream output_file(filename, std::ios::out | std::ios::trunc | std::ios::binary); if (!output_file.is_open()) { - c->con.printerr("Couldn't open the output file.\n"); - c->Resume(); + out.printerr("Couldn't open the output file.\n"); return CR_FAILURE; } ZeroCopyOutputStream *raw_output = new OstreamOutputStream(&output_file); @@ -102,16 +99,16 @@ command_result mapexport (Core * c, std::vector & parameters) Maps::getSize(x_max, y_max, z_max); MapExtras::MapCache map; - DFHack::Materials *mats = c->getMaterials(); + DFHack::Materials *mats = Core::getInstance().getMaterials(); - c->con << "Writing map info..." << std::endl; + 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); - c->con << "Writing material dictionary..." << std::endl; + out << "Writing material dictionary..." << std::endl; for (size_t i = 0; i < world->raws.inorganics.size(); i++) { @@ -143,7 +140,7 @@ command_result mapexport (Core * c, std::vector & parameters) DFHack::t_feature blockFeatureGlobal; DFHack::t_feature blockFeatureLocal; - c->con.print("Writing map block information"); + out.print("Writing map block information"); for(uint32_t z = 0; z < z_max; z++) { @@ -151,7 +148,7 @@ command_result mapexport (Core * c, std::vector & parameters) { for(uint32_t b_x = 0; b_x < x_max; b_x++) { - if (b_x == 0 && b_y == 0 && z % 10 == 0) c->con.print("."); + 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)); @@ -283,7 +280,6 @@ command_result mapexport (Core * c, std::vector & parameters) delete raw_output; mats->Finish(); - c->con.print("\nMap succesfully exported!\n"); - c->Resume(); + out.print("\nMap succesfully exported!\n"); return CR_OK; } diff --git a/plugins/mode.cpp b/plugins/mode.cpp index c275ae69d..4a4f9fb0a 100644 --- a/plugins/mode.cpp +++ b/plugins/mode.cpp @@ -12,11 +12,11 @@ using namespace std; using namespace DFHack; -command_result mode (Core * c, vector & parameters); +command_result mode (color_ostream &out, vector & parameters); DFHACK_PLUGIN("mode"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.clear(); commands.push_back(PluginCommand( @@ -29,12 +29,12 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -DFhackCExport command_result plugin_onupdate ( Core * c ) +DFhackCExport command_result plugin_onupdate ( color_ostream &out ) { // add tracking here return CR_OK; @@ -94,8 +94,11 @@ void printCurrentModes(t_gamemodes gm, Console & con) } } -command_result mode (Core * c, vector & parameters) +command_result mode (color_ostream &out_, vector & parameters) { + assert(out_.is_console()); + Console &out = static_cast(out_); + string command = ""; bool set = false; bool abuse = false; @@ -113,22 +116,28 @@ command_result mode (Core * c, vector & parameters) else return CR_WRONG_USAGE; } - c->Suspend(); - World *world = c->getWorld(); - world->Start(); - world->ReadGameMode(gm); - c->Resume(); - printCurrentModes(gm, c->con); + + World *world; + + { + CoreSuspender suspend; + world = Core::getInstance().getWorld(); + world->Start(); + world->ReadGameMode(gm); + } + + printCurrentModes(gm, out); + if(set) { if(!abuse) { if( gm.g_mode == GAMEMODE_NONE || gm.g_type == GAMETYPE_VIEW_LEGENDS) { - c->con.printerr("It is not safe to set modes in menus.\n"); + out.printerr("It is not safe to set modes in menus.\n"); return CR_FAILURE; } - c->con << "\nPossible choices:" << endl + out << "\nPossible choices:" << endl << "0 = Fortress Mode" << endl << "1 = Adventurer Mode" << endl << "2 = Arena Mode" << endl @@ -140,7 +149,7 @@ command_result mode (Core * c, vector & parameters) string selected; input_again: CommandHistory hist; - c->con.lineedit("Enter new mode: ",selected, hist); + out.lineedit("Enter new mode: ",selected, hist); if(selected == "c") return CR_OK; const char * start = selected.c_str(); @@ -148,7 +157,7 @@ command_result mode (Core * c, vector & parameters) select = strtol(start, &end, 10); if(!end || end==start || select > 4) { - c->con.printerr("This is not a valid selection.\n"); + out.printerr("This is not a valid selection.\n"); goto input_again; } switch(select) @@ -179,21 +188,24 @@ command_result mode (Core * c, vector & parameters) { CommandHistory hist; string selected; - c->con.lineedit("Enter new game mode number (c for exit): ",selected, hist); + out.lineedit("Enter new game mode number (c for exit): ",selected, hist); if(selected == "c") return CR_OK; const char * start = selected.c_str(); gm.g_mode = (GameMode) strtol(start, 0, 10); - c->con.lineedit("Enter new game type number (c for exit): ",selected, hist); + out.lineedit("Enter new game type number (c for exit): ",selected, hist); if(selected == "c") return CR_OK; start = selected.c_str(); gm.g_type = (GameType) strtol(start, 0, 10); } - c->Suspend(); - world->WriteGameMode(gm); - c->Resume(); - c->con << endl; + + { + CoreSuspender suspend; + world->WriteGameMode(gm); + } + + out << endl; } return CR_OK; } diff --git a/plugins/plants.cpp b/plugins/plants.cpp index 951ac0a8b..eecbb17bd 100644 --- a/plugins/plants.cpp +++ b/plugins/plants.cpp @@ -20,13 +20,13 @@ using std::string; using namespace DFHack; using df::global::world; -command_result df_grow (Core * c, vector & parameters); -command_result df_immolate (Core * c, vector & parameters); -command_result df_extirpate (Core * c, vector & parameters); +command_result df_grow (color_ostream &out, vector & parameters); +command_result df_immolate (color_ostream &out, vector & parameters); +command_result df_extirpate (color_ostream &out, vector & parameters); DFHACK_PLUGIN("plants"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.clear(); commands.push_back(PluginCommand("grow", "Grows saplings into trees (with active cursor, only the targetted one).", df_grow)); @@ -35,7 +35,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } @@ -81,13 +81,13 @@ static bool getoptions( vector & parameters, bool & shrubs, bool & tree * And he cursed the plants and trees for their bloodless wood, turning them into ash and smoldering ruin. * Armok was pleased and great temples were built by the dwarves, for they shared his hatred for trees and plants. */ -static command_result immolations (Core * c, do_what what, bool shrubs, bool trees, bool help) +static command_result immolations (color_ostream &out, do_what what, bool shrubs, bool trees, bool help) { static const char * what1 = "destroys"; static const char * what2 = "burns"; if(help) { - c->con.print("Without any options, this command %s a plant under the cursor.\n" + out.print("Without any options, this command %s a plant under the cursor.\n" "Options:\n" "shrubs - affect all shrubs\n" "trees - affect all trees\n" @@ -96,10 +96,10 @@ static command_result immolations (Core * c, do_what what, bool shrubs, bool tre ); return CR_OK; } - CoreSuspender suspend(c); + CoreSuspender suspend; if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } uint32_t x_max, y_max, z_max; @@ -119,7 +119,7 @@ static command_result immolations (Core * c, do_what what, bool shrubs, bool tre destroyed ++; } } - c->con.print("Praise Armok!\n"); + out.print("Praise Armok!\n"); } else { @@ -152,55 +152,55 @@ static command_result immolations (Core * c, do_what what, bool shrubs, bool tre } else { - c->con.printerr("No mass destruction and no cursor...\n" ); + out.printerr("No mass destruction and no cursor...\n" ); } } return CR_OK; } -command_result df_immolate (Core * c, vector & parameters) +command_result df_immolate (color_ostream &out, vector & parameters) { bool shrubs = false, trees = false, help = false; if(getoptions(parameters,shrubs,trees,help)) { - return immolations(c,do_immolate,shrubs,trees, help); + return immolations(out,do_immolate,shrubs,trees, help); } else { - c->con.printerr("Invalid parameter!\n"); + out.printerr("Invalid parameter!\n"); return CR_FAILURE; } } -command_result df_extirpate (Core * c, vector & parameters) +command_result df_extirpate (color_ostream &out, vector & parameters) { bool shrubs = false, trees = false, help = false; if(getoptions(parameters,shrubs,trees, help)) { - return immolations(c,do_extirpate,shrubs,trees, help); + return immolations(out,do_extirpate,shrubs,trees, help); } else { - c->con.printerr("Invalid parameter!\n"); + out.printerr("Invalid parameter!\n"); return CR_FAILURE; } } -command_result df_grow (Core * c, vector & parameters) +command_result df_grow (color_ostream &out, vector & parameters) { for(size_t i = 0; i < parameters.size();i++) { if(parameters[i] == "help" || parameters[i] == "?") { - c->con.print("This command turns all living saplings into full-grown trees.\n"); + out.print("This command turns all living saplings into full-grown trees.\n"); return CR_OK; } } - CoreSuspender suspend(c); - Console & con = c->con; + CoreSuspender suspend; + if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } MapExtras::MapCache map; diff --git a/plugins/probe.cpp b/plugins/probe.cpp index ea3dd85ee..04448d017 100644 --- a/plugins/probe.cpp +++ b/plugins/probe.cpp @@ -33,13 +33,13 @@ using namespace df::enums; using df::global::world; using df::global::cursor; -command_result df_probe (Core * c, vector & parameters); -command_result df_cprobe (Core * c, vector & parameters); -command_result df_bprobe (Core * c, vector & parameters); +command_result df_probe (color_ostream &out, vector & parameters); +command_result df_cprobe (color_ostream &out, vector & parameters); +command_result df_bprobe (color_ostream &out, vector & parameters); DFHACK_PLUGIN("probe"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.clear(); commands.push_back(PluginCommand("probe", @@ -54,20 +54,19 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -command_result df_cprobe (Core * c, vector & parameters) +command_result df_cprobe (color_ostream &out, vector & parameters) { - Console & con = c->con; - CoreSuspender suspend(c); + CoreSuspender suspend; int32_t cursorX, cursorY, cursorZ; Gui::getCursorCoords(cursorX,cursorY,cursorZ); if(cursorX == -30000) { - con.printerr("No cursor; place cursor over creature to probe.\n"); + out.printerr("No cursor; place cursor over creature to probe.\n"); } else { @@ -76,7 +75,7 @@ command_result df_cprobe (Core * c, vector & parameters) df::unit * unit = world->units.all[i]; if(unit->pos.x == cursorX && unit->pos.y == cursorY && unit->pos.z == cursorZ) { - con.print("Creature %d, race %d (%x), civ %d (%x)\n", unit->id, unit->race, unit->race, unit->civ_id, unit->civ_id); + out.print("Creature %d, race %d (%x), civ %d (%x)\n", unit->id, unit->race, unit->race, unit->civ_id, unit->civ_id); break; } } @@ -84,29 +83,29 @@ command_result df_cprobe (Core * c, vector & parameters) return CR_OK; } -command_result df_probe (Core * c, vector & parameters) +command_result df_probe (color_ostream &out, vector & parameters) { //bool showBlock, showDesig, showOccup, showTile, showMisc; - Console & con = c->con; + /* if (!parseOptions(parameters, showBlock, showDesig, showOccup, showTile, showMisc)) { - con.printerr("Unknown parameters!\n"); + out.printerr("Unknown parameters!\n"); return CR_FAILURE; } */ - CoreSuspender suspend(c); + CoreSuspender suspend; + + DFHack::Materials *Materials = Core::getInstance().getMaterials(); - DFHack::Materials *Materials = c->getMaterials(); - DFHack::VersionInfo* mem = c->vinfo; std::vector inorganic; bool hasmats = Materials->CopyInorganicMaterials(inorganic); if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } MapExtras::MapCache mc; @@ -118,7 +117,7 @@ command_result df_probe (Core * c, vector & parameters) Gui::getCursorCoords(cursorX,cursorY,cursorZ); if(cursorX == -30000) { - con.printerr("No cursor; place cursor over tile to probe.\n"); + out.printerr("No cursor; place cursor over tile to probe.\n"); return CR_FAILURE; } DFCoord cursor (cursorX,cursorY,cursorZ); @@ -131,17 +130,17 @@ command_result df_probe (Core * c, vector & parameters) MapExtras::Block * b = mc.BlockAt(cursor/16); if(!b && !b->valid) { - con.printerr("No data.\n"); + out.printerr("No data.\n"); return CR_OK; } mapblock40d & block = b->raw; - con.print("block addr: 0x%x\n\n", block.origin); + out.print("block addr: 0x%x\n\n", block.origin); /* if (showBlock) { - con.print("block flags:\n"); - print_bits(block.blockflags.whole,con); - con.print("\n\n"); + out.print("block flags:\n"); + print_bits(block.blockflags.whole,out); + out.print("\n\n"); } */ df::tiletype tiletype = mc.tiletypeAt(cursor); @@ -149,96 +148,96 @@ command_result df_probe (Core * c, vector & parameters) /* if(showDesig) { - con.print("designation\n"); + out.print("designation\n"); print_bits(block.designation[tileX][tileY].whole, - con); - con.print("\n\n"); + out); + out.print("\n\n"); } if(showOccup) { - con.print("occupancy\n"); + out.print("occupancy\n"); print_bits(block.occupancy[tileX][tileY].whole, - con); - con.print("\n\n"); + out); + out.print("\n\n"); } */ // tiletype - con.print("tiletype: %d", tiletype); + out.print("tiletype: %d", tiletype); if(tileName(tiletype)) - con.print(" = %s",tileName(tiletype)); - con.print("\n"); + out.print(" = %s",tileName(tiletype)); + out.print("\n"); df::tiletype_shape shape = tileShape(tiletype); df::tiletype_material material = tileMaterial(tiletype); df::tiletype_special special = tileSpecial(tiletype); df::tiletype_variant variant = tileVariant(tiletype); - con.print("%-10s: %4d %s\n","Class" ,shape, + out.print("%-10s: %4d %s\n","Class" ,shape, ENUM_KEY_STR(tiletype_shape, shape)); - con.print("%-10s: %4d %s\n","Material" , + out.print("%-10s: %4d %s\n","Material" , material, ENUM_KEY_STR(tiletype_material, material)); - con.print("%-10s: %4d %s\n","Special" , + out.print("%-10s: %4d %s\n","Special" , special, ENUM_KEY_STR(tiletype_special, special)); - con.print("%-10s: %4d %s\n" ,"Variant" , + out.print("%-10s: %4d %s\n" ,"Variant" , variant, ENUM_KEY_STR(tiletype_variant, variant)); - con.print("%-10s: %s\n" ,"Direction", + out.print("%-10s: %s\n" ,"Direction", tileDirection(tiletype).getStr()); - con.print("\n"); + out.print("\n"); - con.print("temperature1: %d U\n",mc.temperature1At(cursor)); - con.print("temperature2: %d U\n",mc.temperature2At(cursor)); + out.print("temperature1: %d U\n",mc.temperature1At(cursor)); + out.print("temperature2: %d U\n",mc.temperature2At(cursor)); // biome, geolayer - con << "biome: " << des.bits.biome << std::endl; - con << "geolayer: " << des.bits.geolayer_index + out << "biome: " << des.bits.biome << std::endl; + out << "geolayer: " << des.bits.geolayer_index << std::endl; int16_t base_rock = mc.baseMaterialAt(cursor); if(base_rock != -1) { - con << "Layer material: " << dec << base_rock; + out << "Layer material: " << dec << base_rock; if(hasmats) - con << " / " << inorganic[base_rock].id + out << " / " << inorganic[base_rock].id << " / " << inorganic[base_rock].name << endl; else - con << endl; + out << endl; } int16_t vein_rock = mc.veinMaterialAt(cursor); if(vein_rock != -1) { - con << "Vein material (final): " << dec << vein_rock; + out << "Vein material (final): " << dec << vein_rock; if(hasmats) - con << " / " << inorganic[vein_rock].id + out << " / " << inorganic[vein_rock].id << " / " << inorganic[vein_rock].name << endl; else - con << endl; + out << endl; } // liquids if(des.bits.flow_size) { if(des.bits.liquid_type == tile_liquid::Magma) - con <<"magma: "; - else con <<"water: "; - con << des.bits.flow_size << std::endl; + out <<"magma: "; + else out <<"water: "; + out << des.bits.flow_size << std::endl; } if(des.bits.flow_forbid) - con << "flow forbid" << std::endl; + out << "flow forbid" << std::endl; if(des.bits.pile) - con << "stockpile?" << std::endl; + out << "stockpile?" << std::endl; if(des.bits.rained) - con << "rained?" << std::endl; + out << "rained?" << std::endl; if(des.bits.smooth) - con << "smooth?" << std::endl; + out << "smooth?" << std::endl; if(des.bits.water_salt) - con << "salty" << endl; + out << "salty" << endl; if(des.bits.water_stagnant) - con << "stagnant" << endl; + out << "stagnant" << endl; - #define PRINT_FLAG( X ) con.print("%-16s= %c\n", #X , ( des.X ? 'Y' : ' ' ) ) + #define PRINT_FLAG( X ) out.print("%-16s= %c\n", #X , ( des.X ? 'Y' : ' ' ) ) PRINT_FLAG( bits.hidden ); PRINT_FLAG( bits.light ); PRINT_FLAG( bits.outside ); @@ -254,37 +253,37 @@ command_result df_probe (Core * c, vector & parameters) PRINT_FLAG( bits.feature_local ); if(local.type != -1) { - con.print("%-16s", ""); - con.print(" %4d", block.local_feature); - con.print(" (%2d)", local.type); - con.print(" addr 0x%X ", local.origin); - con.print(" %s\n", sa_feature(local.type)); + out.print("%-16s", ""); + out.print(" %4d", block.local_feature); + out.print(" (%2d)", local.type); + out.print(" addr 0x%X ", local.origin); + out.print(" %s\n", sa_feature(local.type)); } PRINT_FLAG( bits.feature_global ); if(global.type != -1) { - con.print("%-16s", ""); - con.print(" %4d", block.global_feature); - con.print(" (%2d)", global.type); - con.print(" %s\n", sa_feature(global.type)); + out.print("%-16s", ""); + out.print(" %4d", block.global_feature); + out.print(" (%2d)", global.type); + out.print(" %s\n", sa_feature(global.type)); } #undef PRINT_FLAG - con << "local feature idx: " << block.local_feature + out << "local feature idx: " << block.local_feature << endl; - con << "global feature idx: " << block.global_feature + out << "global feature idx: " << block.global_feature << endl; - con << "mystery: " << block.mystery << endl; - con << std::endl; + out << "mystery: " << block.mystery << endl; + out << std::endl; return CR_OK; } -command_result df_bprobe (Core * c, vector & parameters) +command_result df_bprobe (color_ostream &out, vector & parameters) { - CoreSuspender suspend(c); + CoreSuspender suspend; if(cursor->x == -30000) { - c->con.printerr("No cursor; place cursor over tile to probe.\n"); + out.printerr("No cursor; place cursor over tile to probe.\n"); return CR_FAILURE; } @@ -299,38 +298,38 @@ command_result df_bprobe (Core * c, vector & parameters) continue; string name; building.origin->getName(&name); - c->con.print("Building %i - \"%s\" - type %s", building.origin->id, name.c_str(), ENUM_KEY_STR(building_type, building.type)); + out.print("Building %i - \"%s\" - type %s", building.origin->id, name.c_str(), ENUM_KEY_STR(building_type, building.type)); switch (building.type) { case building_type::Furnace: - c->con.print(", subtype %s", ENUM_KEY_STR(furnace_type, building.furnace_type)); + out.print(", subtype %s", ENUM_KEY_STR(furnace_type, building.furnace_type)); if (building.furnace_type == furnace_type::Custom) - c->con.print(", custom type %i (%s)", building.custom_type, world->raws.buildings.all[building.custom_type]->code.c_str()); + out.print(", custom type %i (%s)", building.custom_type, world->raws.buildings.all[building.custom_type]->code.c_str()); break; case building_type::Workshop: - c->con.print(", subtype %s", ENUM_KEY_STR(workshop_type, building.workshop_type)); + out.print(", subtype %s", ENUM_KEY_STR(workshop_type, building.workshop_type)); if (building.workshop_type == workshop_type::Custom) - c->con.print(", custom type %i (%s)", building.custom_type, world->raws.buildings.all[building.custom_type]->code.c_str()); + out.print(", custom type %i (%s)", building.custom_type, world->raws.buildings.all[building.custom_type]->code.c_str()); break; case building_type::Construction: - c->con.print(", subtype %s", ENUM_KEY_STR(construction_type, building.construction_type)); + out.print(", subtype %s", ENUM_KEY_STR(construction_type, building.construction_type)); break; case building_type::Shop: - c->con.print(", subtype %s", ENUM_KEY_STR(shop_type, building.shop_type)); + out.print(", subtype %s", ENUM_KEY_STR(shop_type, building.shop_type)); break; case building_type::SiegeEngine: - c->con.print(", subtype %s", ENUM_KEY_STR(siegeengine_type, building.siegeengine_type)); + out.print(", subtype %s", ENUM_KEY_STR(siegeengine_type, building.siegeengine_type)); break; case building_type::Trap: - c->con.print(", subtype %s", ENUM_KEY_STR(trap_type, building.trap_type)); + out.print(", subtype %s", ENUM_KEY_STR(trap_type, building.trap_type)); break; default: if (building.subtype != -1) - c->con.print(", subtype %i", building.subtype); + out.print(", subtype %i", building.subtype); break; } - c->con.print("\n"); + out.print("\n"); } return CR_OK; diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp index 91f0c446a..4d89aaae7 100644 --- a/plugins/prospector.cpp +++ b/plugins/prospector.cpp @@ -108,7 +108,7 @@ struct compare_pair_second } }; -static void printMatdata(DFHack::Console & con, const matdata &data) +static void printMatdata(color_ostream &con, const matdata &data) { con << std::setw(9) << data.count; @@ -129,7 +129,7 @@ static int getValue(const df::plant_raw &info) } template class P> -void printMats(DFHack::Console & con, MatMap &mat, std::vector &materials, bool show_value) +void printMats(color_ostream &con, MatMap &mat, std::vector &materials, bool show_value) { unsigned int total = 0; MatSorter sorting_vector; @@ -160,7 +160,7 @@ void printMats(DFHack::Console & con, MatMap &mat, std::vector &materials, b con << ">>> TOTAL = " << total << std::endl << std::endl; } -void printVeins(DFHack::Console & con, MatMap &mat_map, +void printVeins(color_ostream &con, MatMap &mat_map, DFHack::Materials* mats, bool show_value) { MatMap ores; @@ -189,11 +189,11 @@ void printVeins(DFHack::Console & con, MatMap &mat_map, printMats(con, rest, world->raws.inorganics, show_value); } -command_result prospector (Core * c, vector & parameters); +command_result prospector (color_ostream &out, vector & parameters); DFHACK_PLUGIN("prospector"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.clear(); commands.push_back(PluginCommand( @@ -215,7 +215,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } @@ -226,12 +226,12 @@ static coord2d biome_delta[] = { coord2d(-1,-1), coord2d(0,-1), coord2d(1,-1) }; -static command_result embark_prospector(DFHack::Core *c, df::viewscreen_choose_start_sitest *screen, +static command_result embark_prospector(color_ostream &out, df::viewscreen_choose_start_sitest *screen, bool showHidden, bool showValue) { if (!world || !world->world_data) { - c->con.printerr("World data is not available.\n"); + out.printerr("World data is not available.\n"); return CR_FAILURE; } @@ -242,7 +242,7 @@ static command_result embark_prospector(DFHack::Core *c, df::viewscreen_choose_s if (!cur_details) { - c->con.printerr("Current region details are not available.\n"); + out.printerr("Current region details are not available.\n"); return CR_FAILURE; } @@ -251,7 +251,7 @@ static command_result embark_prospector(DFHack::Core *c, df::viewscreen_choose_s if (screen->biome_highlighted) { - c->con.print("Processing one embark tile of biome F%d.\n\n", screen->biome_idx+1); + out.print("Processing one embark tile of biome F%d.\n\n", screen->biome_idx+1); biomes[screen->biome_rgn[screen->biome_idx]]++; } else @@ -279,7 +279,7 @@ static command_result embark_prospector(DFHack::Core *c, df::viewscreen_choose_s if (!geo_biome) { - c->con.printerr("Region geo-biome not found: (%d,%d)\n", bx, by); + out.printerr("Region geo-biome not found: (%d,%d)\n", bx, by); return CR_FAILURE; } @@ -340,21 +340,21 @@ static command_result embark_prospector(DFHack::Core *c, df::viewscreen_choose_s } // Print the report - c->con << "Layer materials:" << std::endl; - printMats(c->con, layerMats, world->raws.inorganics, showValue); + out << "Layer materials:" << std::endl; + printMats(out, layerMats, world->raws.inorganics, showValue); if (showHidden) { - DFHack::Materials *mats = c->getMaterials(); - printVeins(c->con, veinMats, mats, showValue); + DFHack::Materials *mats = Core::getInstance().getMaterials(); + printVeins(out, veinMats, mats, showValue); mats->Finish(); } - c->con << "Warning: the above data is only a very rough estimate." << std::endl; + out << "Warning: the above data is only a very rough estimate." << std::endl; return CR_OK; } -command_result prospector (DFHack::Core * c, vector & parameters) +command_result prospector (color_ostream &con, vector & parameters) { bool showHidden = false; bool showPlants = true; @@ -362,7 +362,7 @@ command_result prospector (DFHack::Core * c, vector & parameters) bool showTemple = true; bool showValue = false; bool showTube = false; - Console & con = c->con; + for(size_t i = 0; i < parameters.size();i++) { if (parameters[i] == "all") @@ -380,15 +380,16 @@ command_result prospector (DFHack::Core * c, vector & parameters) else return CR_WRONG_USAGE; } - CoreSuspender suspend(c); + + CoreSuspender suspend; // Embark screen active: estimate using world geology data - if (VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, c->getTopViewscreen())) - return embark_prospector(c, screen, showHidden, showValue); + if (VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, Core::getTopViewscreen())) + return embark_prospector(con, screen, showHidden, showValue); if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + con.printerr("Map is not available!\n"); return CR_FAILURE; } @@ -396,7 +397,7 @@ command_result prospector (DFHack::Core * c, vector & parameters) Maps::getSize(x_max, y_max, z_max); MapExtras::MapCache map; - DFHack::Materials *mats = c->getMaterials(); + DFHack::Materials *mats = Core::getInstance().getMaterials(); DFHack::t_feature blockFeatureGlobal; DFHack::t_feature blockFeatureLocal; diff --git a/plugins/rename.cpp b/plugins/rename.cpp index 0ff9469de..1a1a8cc30 100644 --- a/plugins/rename.cpp +++ b/plugins/rename.cpp @@ -28,11 +28,11 @@ using namespace df::enums; using df::global::ui; using df::global::world; -static command_result rename(Core * c, vector & parameters); +static command_result rename(color_ostream &out, vector & parameters); DFHACK_PLUGIN("rename"); -DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) { commands.clear(); if (world && ui) { @@ -49,7 +49,7 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } @@ -79,9 +79,9 @@ static df::squad *getSquadByIndex(unsigned idx) return df::squad::find(entity->squads[idx]); } -static command_result rename(Core * c, vector ¶meters) +static command_result rename(color_ostream &out, vector ¶meters) { - CoreSuspender suspend(c); + CoreSuspender suspend; string cmd; if (!parameters.empty()) @@ -96,7 +96,7 @@ static command_result rename(Core * c, vector ¶meters) df::squad *squad = getSquadByIndex(id-1); if (!squad) { - c->con.printerr("Couldn't find squad with index %d.\n", id); + out.printerr("Couldn't find squad with index %d.\n", id); return CR_WRONG_USAGE; } @@ -109,7 +109,7 @@ static command_result rename(Core * c, vector ¶meters) int id = atoi(parameters[1].c_str()); if (id < 1 || id > 16) { - c->con.printerr("Invalid hotkey index\n"); + out.printerr("Invalid hotkey index\n"); return CR_WRONG_USAGE; } @@ -120,7 +120,7 @@ static command_result rename(Core * c, vector ¶meters) if (parameters.size() != 2) return CR_WRONG_USAGE; - df::unit *unit = Gui::getSelectedUnit(c); + df::unit *unit = Gui::getSelectedUnit(out); if (!unit) return CR_WRONG_USAGE; @@ -153,7 +153,7 @@ static command_result rename(Core * c, vector ¶meters) if (parameters.size() != 2) return CR_WRONG_USAGE; - df::unit *unit = Gui::getSelectedUnit(c); + df::unit *unit = Gui::getSelectedUnit(out); if (!unit) return CR_WRONG_USAGE; @@ -162,7 +162,7 @@ static command_result rename(Core * c, vector ¶meters) else { if (!parameters.empty() && cmd != "?") - c->con.printerr("Invalid command: %s\n", cmd.c_str()); + out.printerr("Invalid command: %s\n", cmd.c_str()); return CR_WRONG_USAGE; } diff --git a/plugins/reveal.cpp b/plugins/reveal.cpp index a5d001957..ed9f13321 100644 --- a/plugins/reveal.cpp +++ b/plugins/reveal.cpp @@ -58,15 +58,15 @@ enum revealstate revealstate revealed = NOT_REVEALED; -command_result reveal(DFHack::Core * c, std::vector & params); -command_result unreveal(DFHack::Core * c, std::vector & params); -command_result revtoggle(DFHack::Core * c, std::vector & params); -command_result revflood(DFHack::Core * c, std::vector & params); -command_result nopause(DFHack::Core * c, std::vector & params); +command_result reveal(color_ostream &out, std::vector & params); +command_result unreveal(color_ostream &out, std::vector & params); +command_result revtoggle(color_ostream &out, std::vector & params); +command_result revflood(color_ostream &out, std::vector & params); +command_result nopause(color_ostream &out, std::vector & params); DFHACK_PLUGIN("reveal"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.clear(); commands.push_back(PluginCommand("reveal","Reveal the map. 'reveal hell' will also reveal hell. 'reveal demon' won't pause.",reveal)); @@ -77,9 +77,9 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_onupdate ( Core * c ) +DFhackCExport command_result plugin_onupdate ( color_ostream &out ) { - DFHack::World *World =c->getWorld(); + DFHack::World *World = Core::getInstance().getWorld(); t_gamemodes gm; World->ReadGameMode(gm); if(gm.g_mode == GAMEMODE_DWARF) @@ -97,12 +97,12 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -command_result nopause (Core * c, std::vector & parameters) +command_result nopause (color_ostream &out, std::vector & parameters) { if (parameters.size() == 1 && (parameters[0] == "0" || parameters[0] == "1")) { @@ -110,17 +110,17 @@ command_result nopause (Core * c, std::vector & parameters) nopause_state = 0; else nopause_state = 1; - c->con.print("nopause %sactivated.\n", (nopause_state ? "" : "de")); + out.print("nopause %sactivated.\n", (nopause_state ? "" : "de")); } else { - c->con.print("Disable pausing (doesn't affect pause forced by reveal).\nActivate with 'nopause 1', deactivate with 'nopause 0'.\nCurrent state: %d.\n", nopause_state); + out.print("Disable pausing (doesn't affect pause forced by reveal).\nActivate with 'nopause 1', deactivate with 'nopause 0'.\nCurrent state: %d.\n", nopause_state); } return CR_OK; } -void revealAdventure(DFHack::Core * c) +void revealAdventure(color_ostream &out) { for (size_t i = 0; i < world->map.map_blocks.size(); i++) { @@ -138,10 +138,10 @@ void revealAdventure(DFHack::Core * c) designations[x][y].bits.pile = 1; } } - c->con.print("Local map revealed.\n"); + out.print("Local map revealed.\n"); } -command_result reveal(DFHack::Core * c, std::vector & params) +command_result reveal(color_ostream &out, std::vector & params) { bool no_hell = true; bool pause = true; @@ -151,7 +151,7 @@ command_result reveal(DFHack::Core * c, std::vector & params) no_hell = false; else if(params[i] == "help" || params[i] == "?") { - c->con.print("Reveals the map, by default ignoring hell.\n" + out.print("Reveals the map, by default ignoring hell.\n" "Options:\n" "hell - also reveal hell, while forcing the game to pause.\n" "demon - reveal hell, do not pause.\n" @@ -168,25 +168,26 @@ command_result reveal(DFHack::Core * c, std::vector & params) no_hell = false; pause = false; } - Console & con = c->con; + auto & con = out; if(revealed != NOT_REVEALED) { con.printerr("Map is already revealed or this is a different map.\n"); return CR_FAILURE; } - CoreSuspender suspend(c); - DFHack::World *World =c->getWorld(); + CoreSuspender suspend; + + DFHack::World *World = Core::getInstance().getWorld(); if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } t_gamemodes gm; World->ReadGameMode(gm); if(gm.g_mode == GAMEMODE_ADVENTURE) { - revealAdventure(c); + revealAdventure(out); return CR_OK; } if(gm.g_mode != GAMEMODE_DWARF) @@ -237,14 +238,14 @@ command_result reveal(DFHack::Core * c, std::vector & params) return CR_OK; } -command_result unreveal(DFHack::Core * c, std::vector & params) +command_result unreveal(color_ostream &out, std::vector & params) { - Console & con = c->con; + auto & con = out; for(size_t i = 0; i < params.size();i++) { if(params[i] == "help" || params[i] == "?") { - c->con.print("Reverts the previous reveal operation, hiding the map again.\n"); + out.print("Reverts the previous reveal operation, hiding the map again.\n"); return CR_OK; } } @@ -253,12 +254,12 @@ command_result unreveal(DFHack::Core * c, std::vector & params) con.printerr("There's nothing to revert!\n"); return CR_FAILURE; } - CoreSuspender suspend(c); + CoreSuspender suspend; - DFHack::World *World =c->getWorld(); + DFHack::World *World = Core::getInstance().getWorld(); if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } t_gamemodes gm; @@ -294,56 +295,56 @@ command_result unreveal(DFHack::Core * c, std::vector & params) return CR_OK; } -command_result revtoggle (DFHack::Core * c, std::vector & params) +command_result revtoggle (color_ostream &out, std::vector & params) { for(size_t i = 0; i < params.size();i++) { if(params[i] == "help" || params[i] == "?") { - c->con.print("Toggles between reveal and unreveal.\nCurrently it: "); + out.print("Toggles between reveal and unreveal.\nCurrently it: "); break; } } if(revealed) { - return unreveal(c,params); + return unreveal(out,params); } else { - return reveal(c,params); + return reveal(out,params); } } -command_result revflood(DFHack::Core * c, std::vector & params) +command_result revflood(color_ostream &out, std::vector & params) { for(size_t i = 0; i < params.size();i++) { if(params[i] == "help" || params[i] == "?") { - c->con.print("This command hides the whole map. Then, starting from the cursor,\n" + out.print("This command hides the whole map. Then, starting from the cursor,\n" "reveals all accessible tiles. Allows repairing parma-revealed maps.\n" ); return CR_OK; } } - CoreSuspender suspend(c); + CoreSuspender suspend; uint32_t x_max,y_max,z_max; - World * World = c->getWorld(); + World * World = Core::getInstance().getWorld(); if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } if(revealed != NOT_REVEALED) { - c->con.printerr("This is only safe to use with non-revealed map.\n"); + out.printerr("This is only safe to use with non-revealed map.\n"); return CR_FAILURE; } t_gamemodes gm; World->ReadGameMode(gm); if(gm.g_type != GAMETYPE_DWARF_MAIN && gm.g_mode != GAMEMODE_DWARF ) { - c->con.printerr("Only in proper dwarf mode.\n"); + out.printerr("Only in proper dwarf mode.\n"); return CR_FAILURE; } int32_t cx, cy, cz; @@ -354,7 +355,7 @@ command_result revflood(DFHack::Core * c, std::vector & params) Gui::getCursorCoords(cx,cy,cz); if(cx == -30000) { - c->con.printerr("Cursor is not active. Point the cursor at some empty space you want to be unhidden.\n"); + out.printerr("Cursor is not active. Point the cursor at some empty space you want to be unhidden.\n"); return CR_FAILURE; } DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz); @@ -362,7 +363,7 @@ command_result revflood(DFHack::Core * c, std::vector & params) df::tiletype tt = MCache->tiletypeAt(xy); if(isWallTerrain(tt)) { - c->con.printerr("Point the cursor at some empty space you want to be unhidden.\n"); + out.printerr("Point the cursor at some empty space you want to be unhidden.\n"); delete MCache; return CR_FAILURE; } diff --git a/plugins/seedwatch.cpp b/plugins/seedwatch.cpp index 53a94c665..f98f9213f 100755 --- a/plugins/seedwatch.cpp +++ b/plugins/seedwatch.cpp @@ -42,19 +42,19 @@ bool ignoreSeeds(df::item_flags& f) // seeds with the following flags should not f.bits.in_job; }; -void printHelp(Core& core) // prints help +void printHelp(color_ostream &out) // prints help { - core.con.print( + out.print( "Watches the numbers of seeds available and enables/disables seed and plant cooking.\n" "Each plant type can be assigned a limit. If their number falls below,\n" "the plants and seeds of that type will be excluded from cookery.\n" "If the number rises above the limit + %i, then cooking will be allowed.\n", buffer ); - core.con.printerr( + out.printerr( "The plugin needs a fortress to be loaded and will deactivate automatically otherwise.\n" "You have to reactivate with 'seedwatch start' after you load the game.\n" ); - core.con.print( + out.print( "Options:\n" "seedwatch all - Adds all plants from the abbreviation list to the watch list.\n" "seedwatch start - Start watching.\n" @@ -64,13 +64,13 @@ void printHelp(Core& core) // prints help ); if(!abbreviations.empty()) { - core.con.print("You can use these abbreviations for the plant tokens:\n"); + out.print("You can use these abbreviations for the plant tokens:\n"); for(map::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i) { - core.con.print("%s -> %s\n", i->first.c_str(), i->second.c_str()); + out.print("%s -> %s\n", i->first.c_str(), i->second.c_str()); } } - core.con.print( + out.print( "Examples:\n" "seedwatch MUSHROOM_HELMET_PLUMP 30\n" " add MUSHROOM_HELMET_PLUMP to the watch list, limit = 30\n" @@ -96,14 +96,9 @@ string searchAbbreviations(string in) } }; -command_result df_seedwatch(Core* pCore, vector& parameters) +command_result df_seedwatch(color_ostream &out, vector& parameters) { - Core& core = *pCore; - if(!core.isValid()) - { - return CR_FAILURE; - } - CoreSuspender suspend(pCore); + CoreSuspender suspend; map materialsReverser; for(size_t i = 0; i < world->raws.plants.all.size(); ++i) @@ -111,7 +106,7 @@ command_result df_seedwatch(Core* pCore, vector& parameters) materialsReverser[world->raws.plants.all[i]->id] = i; } - World *w = core.getWorld(); + World *w = Core::getInstance().getWorld(); t_gamemodes gm; w->ReadGameMode(gm);// FIXME: check return value @@ -119,7 +114,7 @@ command_result df_seedwatch(Core* pCore, vector& parameters) if(gm.g_mode != GAMEMODE_DWARF || gm.g_type != GAMETYPE_DWARF_MAIN) { // just print the help - printHelp(core); + printHelp(out); return CR_OK; } @@ -128,50 +123,50 @@ command_result df_seedwatch(Core* pCore, vector& parameters) switch(parameters.size()) { case 0: - printHelp(core); + printHelp(out); break; case 1: par = parameters[0]; - if(par == "help") printHelp(core); - else if(par == "?") printHelp(core); + if(par == "help") printHelp(out); + else if(par == "?") printHelp(out); else if(par == "start") { running = true; - core.con.print("seedwatch supervision started.\n"); + out.print("seedwatch supervision started.\n"); } else if(par == "stop") { running = false; - core.con.print("seedwatch supervision stopped.\n"); + out.print("seedwatch supervision stopped.\n"); } else if(par == "clear") { Kitchen::clearLimits(); - core.con.print("seedwatch watchlist cleared\n"); + out.print("seedwatch watchlist cleared\n"); } else if(par == "info") { - core.con.print("seedwatch Info:\n"); + out.print("seedwatch Info:\n"); if(running) { - core.con.print("seedwatch is supervising. Use 'seedwatch stop' to stop supervision.\n"); + out.print("seedwatch is supervising. Use 'seedwatch stop' to stop supervision.\n"); } else { - core.con.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n"); + out.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n"); } map watchMap; Kitchen::fillWatchMap(watchMap); if(watchMap.empty()) { - core.con.print("The watch list is empty.\n"); + out.print("The watch list is empty.\n"); } else { - core.con.print("The watch list is:\n"); + out.print("The watch list is:\n"); for(map::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i) { - core.con.print("%s : %u\n", world->raws.plants.all[i->first]->id.c_str(), i->second); + out.print("%s : %u\n", world->raws.plants.all[i->first]->id.c_str(), i->second); } } } @@ -179,22 +174,22 @@ command_result df_seedwatch(Core* pCore, vector& parameters) { map watchMap; Kitchen::fillWatchMap(watchMap); - Kitchen::debug_print(core); + Kitchen::debug_print(out); } /* else if(par == "dumpmaps") { - core.con.print("Plants:\n"); + out.print("Plants:\n"); for(auto i = plantMaterialTypes.begin(); i != plantMaterialTypes.end(); i++) { auto t = materialsModule.df_organic->at(i->first); - core.con.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_basic_mat); + out.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_basic_mat); } - core.con.print("Seeds:\n"); + out.print("Seeds:\n"); for(auto i = seedMaterialTypes.begin(); i != seedMaterialTypes.end(); i++) { auto t = materialsModule.df_organic->at(i->first); - core.con.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_seed); + out.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_seed); } } */ @@ -204,11 +199,11 @@ command_result df_seedwatch(Core* pCore, vector& parameters) if(materialsReverser.count(token) > 0) { Kitchen::removeLimit(materialsReverser[token]); - core.con.print("%s is not being watched\n", token.c_str()); + out.print("%s is not being watched\n", token.c_str()); } else { - core.con.print("%s has not been found as a material.\n", token.c_str()); + out.print("%s has not been found as a material.\n", token.c_str()); } } break; @@ -228,16 +223,16 @@ command_result df_seedwatch(Core* pCore, vector& parameters) if(materialsReverser.count(token) > 0) { Kitchen::setLimit(materialsReverser[token], limit); - core.con.print("%s is being watched.\n", token.c_str()); + out.print("%s is being watched.\n", token.c_str()); } else { - core.con.print("%s has not been found as a material.\n", token.c_str()); + out.print("%s has not been found as a material.\n", token.c_str()); } } break; default: - printHelp(core); + printHelp(out); break; } @@ -246,7 +241,7 @@ command_result df_seedwatch(Core* pCore, vector& parameters) DFHACK_PLUGIN("seedwatch"); -DFhackCExport command_result plugin_init(Core* pCore, vector& commands) +DFhackCExport command_result plugin_init(color_ostream &out, vector& commands) { commands.clear(); commands.push_back(PluginCommand("seedwatch", "Switches cookery based on quantity of seeds, to keep reserves", df_seedwatch)); @@ -275,13 +270,13 @@ DFhackCExport command_result plugin_init(Core* pCore, vector& com return CR_OK; } -DFhackCExport command_result plugin_onstatechange(Core* pCore, state_change_event event) +DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) { switch (event) { case SC_GAME_LOADED: case SC_GAME_UNLOADED: if (running) - pCore->con.printerr("seedwatch deactivated due to game load/unload\n"); + out.printerr("seedwatch deactivated due to game load/unload\n"); running = false; break; default: @@ -291,7 +286,7 @@ DFhackCExport command_result plugin_onstatechange(Core* pCore, state_change_even return CR_OK; } -DFhackCExport command_result plugin_onupdate(Core* pCore) +DFhackCExport command_result plugin_onupdate(color_ostream &out) { if (running) { @@ -301,8 +296,7 @@ DFhackCExport command_result plugin_onupdate(Core* pCore) return CR_OK; counter = 0; - Core& core = *pCore; - World *w = core.getWorld(); + World *w = Core::getInstance().getWorld(); t_gamemodes gm; w->ReadGameMode(gm);// FIXME: check return value // if game mode isn't fortress mode @@ -310,7 +304,7 @@ DFhackCExport command_result plugin_onupdate(Core* pCore) { // stop running. running = false; - core.con.printerr("seedwatch deactivated due to game mode switch\n"); + out.printerr("seedwatch deactivated due to game mode switch\n"); return CR_OK; } // this is dwarf mode, continue diff --git a/plugins/server/main.cpp b/plugins/server/main.cpp index a13ae7eb8..23b93c970 100644 --- a/plugins/server/main.cpp +++ b/plugins/server/main.cpp @@ -10,13 +10,13 @@ using namespace DFHack; // 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 server (Core * c, std::vector & parameters); +command_result server (color_ostream &out, std::vector & parameters); // A plugins must be able to return its name. This must correspond to the filename - skeleton.plug.so or skeleton.plug.dll DFHACK_PLUGIN("server"); // Mandatory init function. If you have some global state, create it here. -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { // Fill the command list with your commands. commands.clear(); @@ -27,7 +27,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector } // This is called right before the plugin library is removed from memory. -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { // You *MUST* kill all threads you created before this returns. // If everythin fails, just return CR_FAILURE. Your plugin will be @@ -36,7 +36,7 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) } // This is WRONG and STUPID. Never use this as an example! -command_result server (Core * c, std::vector & parameters) +command_result server (color_ostream &out, std::vector & parameters) { // It's nice to provide a 'help' option for your command. // It's also nice to print the same help if you get invalid options from the user instead of just acting strange @@ -46,7 +46,7 @@ command_result server (Core * c, std::vector & parameters) { // Core has a handle to the console. The console is thread-safe. // Only one thing can read from it at a time though... - c->con.print("This command is a simple Hello World example for zeromq!\n"); + out.print("This command is a simple Hello World example for zeromq!\n"); return CR_OK; } } @@ -61,7 +61,7 @@ command_result server (Core * c, std::vector & parameters) // Wait for next request from client socket.recv (&request); - c->con.print("Received Hello\n"); + out.print("Received Hello\n"); // Do some 'work' #ifdef LINUX_BUILD diff --git a/plugins/showmood.cpp b/plugins/showmood.cpp index 23a5383ad..d47bd8a80 100644 --- a/plugins/showmood.cpp +++ b/plugins/showmood.cpp @@ -26,18 +26,18 @@ using namespace df::enums; using df::global::world; -command_result df_showmood (Core * c, vector & parameters) +command_result df_showmood (color_ostream &out, vector & parameters) { if (!parameters.empty()) return CR_WRONG_USAGE; if (!Translation::IsValid()) { - c->con.printerr("Translation data unavailable!\n"); + out.printerr("Translation data unavailable!\n"); return CR_FAILURE; } - CoreSuspender suspend(c); + CoreSuspender suspend; bool found = false; for (df::job_list_link *cur = world->job_list.next; cur != NULL; cur = cur->next) @@ -58,27 +58,27 @@ command_result df_showmood (Core * c, vector & parameters) } if (!unit) { - c->con.printerr("Found strange mood not attached to any dwarf!\n"); + out.printerr("Found strange mood not attached to any dwarf!\n"); continue; } if (unit->mood == mood_type::None) { - c->con.printerr("Dwarf with strange mood does not have a mood type!\n"); + out.printerr("Dwarf with strange mood does not have a mood type!\n"); continue; } - c->con.print("%s is currently ", Translation::TranslateName(&unit->name, false).c_str()); + out.print("%s is currently ", Translation::TranslateName(&unit->name, false).c_str()); switch (unit->mood) { case mood_type::Macabre: - c->con.print("in a macabre mood"); + out.print("in a macabre mood"); if (job->job_type != job_type::StrangeMoodBrooding) - c->con.print(" (but isn't actually in a macabre mood?)"); + out.print(" (but isn't actually in a macabre mood?)"); break; case mood_type::Fell: - c->con.print("in a fell mood"); + out.print("in a fell mood"); if (job->job_type != job_type::StrangeMoodFell) - c->con.print(" (but isn't actually in a fell mood?)"); + out.print(" (but isn't actually in a fell mood?)"); break; case mood_type::Fey: @@ -87,77 +87,80 @@ command_result df_showmood (Core * c, vector & parameters) switch (unit->mood) { case mood_type::Fey: - c->con.print("in a fey mood"); + out.print("in a fey mood"); break; case mood_type::Secretive: - c->con.print("in a secretive mood"); + out.print("in a secretive mood"); break; case mood_type::Possessed: - c->con.print("possessed"); + out.print("possessed"); break; } - c->con.print(" with intent to "); + out.print(" with intent to "); switch (job->job_type) { case job_type::StrangeMoodCrafter: - c->con.print("become a Craftsdwarf (or Engraver)"); + out.print("become a Craftsdwarf (or Engraver)"); break; case job_type::StrangeMoodJeweller: - c->con.print("become a Jeweler"); + out.print("become a Jeweler"); break; case job_type::StrangeMoodForge: - c->con.print("become a Metalworker"); + out.print("become a Metalworker"); break; case job_type::StrangeMoodMagmaForge: - c->con.print("become a Metalworker using a Magma Forge"); + out.print("become a Metalworker using a Magma Forge"); break; case job_type::StrangeMoodCarpenter: - c->con.print("become a Carpenter"); + out.print("become a Carpenter"); break; case job_type::StrangeMoodMason: - c->con.print("become a Mason (or Miner)"); + out.print("become a Mason (or Miner)"); break; case job_type::StrangeMoodBowyer: - c->con.print("become a Bowyer"); + out.print("become a Bowyer"); break; case job_type::StrangeMoodTanner: - c->con.print("become a Leatherworker (or Tanner)"); + out.print("become a Leatherworker (or Tanner)"); break; case job_type::StrangeMoodWeaver: - c->con.print("become a Clothier (or Weaver)"); + out.print("become a Clothier (or Weaver)"); break; case job_type::StrangeMoodGlassmaker: - c->con.print("become a Glassmaker"); + out.print("become a Glassmaker"); break; case job_type::StrangeMoodMechanics: - c->con.print("become a Mechanic"); + out.print("become a Mechanic"); break; case job_type::StrangeMoodBrooding: - c->con.print("enter a macabre mood?"); + out.print("enter a macabre mood?"); break; case job_type::StrangeMoodFell: - c->con.print("enter a fell mood?"); + out.print("enter a fell mood?"); + break; + default: + out.print("do something else..."); break; } break; default: - c->con.print("insane?"); + out.print("insane?"); break; } if (building) { string name; building->getName(&name); - c->con.print(" and has claimed a %s\n", name.c_str()); + out.print(" and has claimed a %s\n", name.c_str()); } else - c->con.print(" and has not yet claimed a workshop\n"); + out.print(" and has not yet claimed a workshop\n"); for (size_t i = 0; i < job->job_items.size(); i++) { df::job_item *item = job->job_items[i]; - c->con.print("Item %i: ", i + 1); + out.print("Item %i: ", i + 1); MaterialInfo matinfo(item->mat_type, item->mat_index); @@ -166,37 +169,37 @@ command_result df_showmood (Core * c, vector & parameters) switch (item->item_type) { case item_type::BOULDER: - c->con.print("%s boulder", mat_name.c_str()); + out.print("%s boulder", mat_name.c_str()); break; case item_type::BLOCKS: - c->con.print("%s blocks", mat_name.c_str()); + out.print("%s blocks", mat_name.c_str()); break; case item_type::WOOD: - c->con.print("%s logs", mat_name.c_str()); + out.print("%s logs", mat_name.c_str()); break; case item_type::BAR: if (matinfo.isInorganicWildcard()) mat_name = "metal"; if (matinfo.inorganic && matinfo.inorganic->flags.is_set(inorganic_flags::WAFERS)) - c->con.print("%s wafers", mat_name.c_str()); + out.print("%s wafers", mat_name.c_str()); else - c->con.print("%s bars", mat_name.c_str()); + out.print("%s bars", mat_name.c_str()); break; case item_type::SMALLGEM: - c->con.print("%s cut gems", mat_name.c_str()); + out.print("%s cut gems", mat_name.c_str()); break; case item_type::ROUGH: if (matinfo.isAnyInorganic()) { if (matinfo.isInorganicWildcard()) mat_name = "any"; - c->con.print("%s rough gems", mat_name.c_str()); + out.print("%s rough gems", mat_name.c_str()); } else - c->con.print("raw %s", mat_name.c_str()); + out.print("raw %s", mat_name.c_str()); break; case item_type::SKIN_TANNED: - c->con.print("%s leather", mat_name.c_str()); + out.print("%s leather", mat_name.c_str()); break; case item_type::CLOTH: if (matinfo.isNone()) @@ -208,36 +211,36 @@ command_result df_showmood (Core * c, vector & parameters) else if (item->flags2.bits.yarn) mat_name = "any yarn"; } - c->con.print("%s cloth", mat_name.c_str()); + out.print("%s cloth", mat_name.c_str()); break; case item_type::REMAINS: - c->con.print("%s remains", mat_name.c_str()); + out.print("%s remains", mat_name.c_str()); break; case item_type::CORPSE: - c->con.print("%s %scorpse", mat_name.c_str(), (item->flags1.bits.murdered ? "murdered " : "")); + out.print("%s %scorpse", mat_name.c_str(), (item->flags1.bits.murdered ? "murdered " : "")); break; case item_type::NONE: if (item->flags2.bits.body_part) { if (item->flags2.bits.bone) - c->con.print("%s bones", mat_name.c_str()); + out.print("%s bones", mat_name.c_str()); else if (item->flags2.bits.shell) - c->con.print("%s shells", mat_name.c_str()); + out.print("%s shells", mat_name.c_str()); else if (item->flags2.bits.horn) - c->con.print("%s horns", mat_name.c_str()); + out.print("%s horns", mat_name.c_str()); else if (item->flags2.bits.pearl) - c->con.print("%s pearls", mat_name.c_str()); + out.print("%s pearls", mat_name.c_str()); else if (item->flags2.bits.ivory_tooth) - c->con.print("%s ivory/teeth", mat_name.c_str()); + out.print("%s ivory/teeth", mat_name.c_str()); else - c->con.print("%s unknown body parts (%s:%s:%s)", + out.print("%s unknown body parts (%s:%s:%s)", mat_name.c_str(), bitfieldToString(item->flags1).c_str(), bitfieldToString(item->flags2).c_str(), bitfieldToString(item->flags3).c_str()); } else - c->con.print("indeterminate %s item (%s:%s:%s)", + out.print("indeterminate %s item (%s:%s:%s)", mat_name.c_str(), bitfieldToString(item->flags1).c_str(), bitfieldToString(item->flags2).c_str(), @@ -247,7 +250,7 @@ command_result df_showmood (Core * c, vector & parameters) { ItemTypeInfo itinfo(item->item_type, item->item_subtype); - c->con.print("item %s material %s flags (%s:%s:%s)", + out.print("item %s material %s flags (%s:%s:%s)", itinfo.toString().c_str(), mat_name.c_str(), bitfieldToString(item->flags1).c_str(), bitfieldToString(item->flags2).c_str(), @@ -256,25 +259,25 @@ command_result df_showmood (Core * c, vector & parameters) } } - c->con.print(", quantity %i\n", item->quantity); + out.print(", quantity %i\n", item->quantity); } } if (!found) - c->con.print("No strange moods currently active.\n"); + out.print("No strange moods currently active.\n"); return CR_OK; } DFHACK_PLUGIN("showmood"); -DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) { commands.clear(); commands.push_back(PluginCommand("showmood", "Shows items needed for current strange mood.", df_showmood)); return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } diff --git a/plugins/skeleton/skeleton.cpp b/plugins/skeleton/skeleton.cpp index b2db81ff1..3f5c6cd06 100644 --- a/plugins/skeleton/skeleton.cpp +++ b/plugins/skeleton/skeleton.cpp @@ -19,14 +19,14 @@ using namespace df::enums; // 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 skeleton (Core * c, std::vector & parameters); +command_result skeleton (color_ostream &out, std::vector & parameters); // A plugin must be able to return its name and version. // The name string provided must correspond to the filename - skeleton.plug.so or skeleton.plug.dll in this case DFHACK_PLUGIN("skeleton"); // Mandatory init function. If you have some global state, create it here. -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { // Fill the command list with your commands. commands.clear(); @@ -43,7 +43,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector } // This is called right before the plugin library is removed from memory. -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { // You *MUST* kill all threads you created before this returns. // If everything fails, just return CR_FAILURE. Your plugin will be @@ -55,7 +55,7 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) // Invoked with DF suspended, and always before the matching plugin_onupdate. // More event codes may be added in the future. /* -DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event event) +DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) { switch (event) { case SC_GAME_LOADED: @@ -74,7 +74,7 @@ DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event ev // Whatever you put here will be done in each game step. Don't abuse it. // It's optional, so you can just comment it out like this if you don't need it. /* -DFhackCExport command_result plugin_onupdate ( Core * c ) +DFhackCExport command_result plugin_onupdate ( color_ostream &out ) { // whetever. You don't need to suspend DF execution here. return CR_OK; @@ -82,7 +82,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) */ // A command! It sits around and looks pretty. And it's nice and friendly. -command_result skeleton (Core * c, std::vector & parameters) +command_result skeleton (color_ostream &out, std::vector & parameters) { // It's nice to print a help message you get invalid options // from the user instead of just acting strange. @@ -96,9 +96,9 @@ command_result skeleton (Core * c, std::vector & parameters) // Suspend this thread until DF has time for us. If you // use CoreSuspender, it'll automatically resume DF when // execution leaves the current scope. - CoreSuspender suspend(c); + CoreSuspender suspend; // Actually do something here. Yay. - c->con.print("Hello! I do nothing, remember?\n"); + out.print("Hello! I do nothing, remember?\n"); // Give control back to DF. return CR_OK; } diff --git a/plugins/stockpiles.cpp b/plugins/stockpiles.cpp index 06b72c0c5..4f3192f3e 100644 --- a/plugins/stockpiles.cpp +++ b/plugins/stockpiles.cpp @@ -22,12 +22,12 @@ using df::global::selection_rect; using df::building_stockpilest; -static command_result copystock(Core *c, vector & parameters); -static bool copystock_guard(Core *c, df::viewscreen *top); +static command_result copystock(color_ostream &out, vector & parameters); +static bool copystock_guard(df::viewscreen *top); DFHACK_PLUGIN("stockpiles"); -DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) { commands.clear(); if (world && ui) { @@ -47,16 +47,16 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -static bool copystock_guard(Core *c, df::viewscreen *top) +static bool copystock_guard(df::viewscreen *top) { using namespace ui_sidebar_mode; - if (!Gui::dwarfmode_hotkey(c,top)) + if (!Gui::dwarfmode_hotkey(top)) return false; switch (ui->main.mode) { @@ -70,7 +70,7 @@ static bool copystock_guard(Core *c, df::viewscreen *top) } } -static command_result copystock(Core * c, vector & parameters) +static command_result copystock(color_ostream &out, vector & parameters) { // HOTKEY COMMAND: CORE ALREADY SUSPENDED @@ -80,14 +80,14 @@ static command_result copystock(Core * c, vector & parameters) ui->main.mode = ui_sidebar_mode::QueryBuilding; selection_rect->start_x = -30000; - c->con << "Switched back to query building." << endl; + out << "Switched back to query building." << endl; return CR_OK; } building_stockpilest *sp = virtual_cast(world->selected_building); if (!sp) { - c->con.printerr("Selected building isn't a stockpile.\n"); + out.printerr("Selected building isn't a stockpile.\n"); return CR_WRONG_USAGE; } @@ -95,6 +95,6 @@ static command_result copystock(Core * c, vector & parameters) ui->main.mode = ui_sidebar_mode::Stockpiles; world->selected_stockpile_type = stockpile_category::Custom; - c->con << "Stockpile options copied." << endl; + out << "Stockpile options copied." << endl; return CR_OK; } diff --git a/plugins/stonesense b/plugins/stonesense index 34183f96b..f05386bae 160000 --- a/plugins/stonesense +++ b/plugins/stonesense @@ -1 +1 @@ -Subproject commit 34183f96b86394895975fb59ae3c4673cd78f502 +Subproject commit f05386bae01d1840bdc889f30253ed50ee892860 diff --git a/plugins/tiletypes.cpp b/plugins/tiletypes.cpp index 5b322e95e..8825d8114 100644 --- a/plugins/tiletypes.cpp +++ b/plugins/tiletypes.cpp @@ -633,11 +633,11 @@ public: CommandHistory tiletypes_hist; -command_result df_tiletypes (Core * c, vector & parameters); +command_result df_tiletypes (color_ostream &out, vector & parameters); DFHACK_PLUGIN("tiletypes"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { tiletypes_hist.load("tiletypes.history"); commands.clear(); @@ -645,13 +645,13 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { tiletypes_hist.save("tiletypes.history"); return CR_OK; } -command_result df_tiletypes (Core * c, vector & parameters) +command_result df_tiletypes (color_ostream &out, vector & parameters) { uint32_t x_max = 0, y_max = 0, z_max = 0; int32_t x = 0, y = 0, z = 0; @@ -660,7 +660,7 @@ command_result df_tiletypes (Core * c, vector & parameters) { if(parameters[i] == "help" || parameters[i] == "?") { - c->con.print("This tool allows painting tiles types with a brush, using an optional filter.\n" + out.print("This tool allows painting tiles types with a brush, using an optional filter.\n" "The tool is interactive, similarly to the liquids tool.\n" "Further help is available inside.\n" ); @@ -668,25 +668,28 @@ command_result df_tiletypes (Core * c, vector & parameters) } } + assert(out.is_console()); + Console &con = static_cast(out); + TileType filter, paint; Brush *brush = new RectangleBrush(1,1); bool end = false; std::string brushname = "point"; int width = 1, height = 1, z_levels = 1; - c->con << "Welcome to the tiletype tool.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl; - c->con.printerr("THIS TOOL CAN BE DANGEROUS. YOU'VE BEEN WARNED.\n"); + con << "Welcome to the tiletype tool.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl; + con.printerr("THIS TOOL CAN BE DANGEROUS. YOU'VE BEEN WARNED.\n"); while (!end) { - c->con << "Filter: " << filter << std::endl - << "Paint: " << paint << std::endl - << "Brush: " << brushname << std::endl; + con << "Filter: " << filter << std::endl + << "Paint: " << paint << std::endl + << "Brush: " << brushname << std::endl; std::string input = ""; std::string command = ""; std::string option = ""; std::string value = ""; - c->con.lineedit("tiletypes> ",input,tiletypes_hist); + con.lineedit("tiletypes> ",input,tiletypes_hist); tiletypes_hist.add(input); std::istringstream ss(input); ss >> command >> option >> value; @@ -695,7 +698,7 @@ command_result df_tiletypes (Core * c, vector & parameters) if (command == "help" || command == "?") { - help(c->con,option); + help(con,option); } else if (command == "quit" || command == "q") { @@ -720,19 +723,19 @@ command_result df_tiletypes (Core * c, vector & parameters) std::stringstream ss; CommandHistory hist; ss << "Set range width <" << width << "> "; - c->con.lineedit(ss.str(),command,hist); + con.lineedit(ss.str(),command,hist); width = command == "" ? width : toint(command); if (width < 1) width = 1; ss.str(""); ss << "Set range height <" << height << "> "; - c->con.lineedit(ss.str(),command,hist); + con.lineedit(ss.str(),command,hist); height = command == "" ? height : toint(command); if (height < 1) height = 1; ss.str(""); ss << "Set range z-levels <" << z_levels << "> "; - c->con.lineedit(ss.str(),command,hist); + con.lineedit(ss.str(),command,hist); z_levels = command == "" ? z_levels : toint(command); if (z_levels < 1) z_levels = 1; @@ -763,29 +766,30 @@ command_result df_tiletypes (Core * c, vector & parameters) { if (paint.empty()) { - c->con.printerr("Set the paint first.\n"); + con.printerr("Set the paint first.\n"); continue; } - CoreSuspender suspend(c); + CoreSuspender suspend; + if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + con.printerr("Map is not available!\n"); return CR_FAILURE; } Maps::getSize(x_max, y_max, z_max); if (!Gui::getCursorCoords(x,y,z)) { - c->con.printerr("Can't get cursor coords! Make sure you have a cursor active in DF.\n"); + con.printerr("Can't get cursor coords! Make sure you have a cursor active in DF.\n"); return CR_FAILURE; } - c->con.print("Cursor coords: (%d, %d, %d)\n",x,y,z); + con.print("Cursor coords: (%d, %d, %d)\n",x,y,z); DFHack::DFCoord cursor(x,y,z); MapExtras::MapCache map; coord_vec all_tiles = brush->points(map, cursor); - c->con.print("working...\n"); + con.print("working...\n"); for (coord_vec::iterator iter = all_tiles.begin(); iter != all_tiles.end(); ++iter) { @@ -895,11 +899,11 @@ command_result df_tiletypes (Core * c, vector & parameters) if (map.WriteAll()) { - c->con.print("OK\n"); + con.print("OK\n"); } else { - c->con.printerr("Something failed horribly! RUN!\n"); + con.printerr("Something failed horribly! RUN!\n"); } } } diff --git a/plugins/tubefill.cpp b/plugins/tubefill.cpp index 71216c871..93b7abff6 100644 --- a/plugins/tubefill.cpp +++ b/plugins/tubefill.cpp @@ -17,23 +17,23 @@ using namespace DFHack; using namespace df::enums; using df::global::world; -command_result tubefill(DFHack::Core * c, std::vector & params); +command_result tubefill(color_ostream &out, std::vector & params); DFHACK_PLUGIN("tubefill"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.clear(); commands.push_back(PluginCommand("tubefill","Fill in all the adamantine tubes again.",tubefill)); return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -command_result tubefill(DFHack::Core * c, std::vector & params) +command_result tubefill(color_ostream &out, std::vector & params) { uint64_t count = 0; @@ -41,16 +41,18 @@ command_result tubefill(DFHack::Core * c, std::vector & params) { if(params[i] == "help" || params[i] == "?") { - c->con.print("Replenishes mined out adamantine and hollow adamantine tubes.\n" + out.print("Replenishes mined out adamantine and hollow adamantine tubes.\n" "May cause !!FUN!!\n" ); return CR_OK; } } - CoreSuspender suspend(c); + + CoreSuspender suspend; + if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } @@ -102,6 +104,6 @@ command_result tubefill(DFHack::Core * c, std::vector & params) } } } - c->con.print("Found and changed %d tiles.\n", count); + out.print("Found and changed %d tiles.\n", count); return CR_OK; } diff --git a/plugins/tweak.cpp b/plugins/tweak.cpp new file mode 100644 index 000000000..92689552d --- /dev/null +++ b/plugins/tweak.cpp @@ -0,0 +1,121 @@ +// A container for random minor tweaks that don't fit anywhere else, +// in order to avoid creating lots of plugins and polluting the namespace. + +#include "Core.h" +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" + +#include "modules/Gui.h" + +#include "DataDefs.h" +#include "df/ui.h" +#include "df/world.h" +#include "df/squad.h" +#include "df/unit.h" +#include "df/unit_soul.h" +#include "df/historical_entity.h" +#include "df/historical_figure.h" +#include "df/historical_figure_info.h" +#include "df/assumed_identity.h" +#include "df/language_name.h" +#include "df/death_info.h" +#include "df/criminal_case.h" + +#include + +using std::vector; +using std::string; +using std::endl; +using namespace DFHack; +using namespace df::enums; + +using df::global::ui; +using df::global::world; + +using namespace DFHack::Gui; + +static command_result tweak(color_ostream &out, vector & parameters); + +DFHACK_PLUGIN("tweak"); + +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) +{ + commands.clear(); + commands.push_back(PluginCommand( + "tweak", "Various tweaks for minor bugs.", tweak, false, + " tweak clear-missing\n" + " Remove the missing status from the selected unit.\n" + " tweak lair\n" + " Mark the map as monster lair, preventing item scatter on reclaim.\n" + )); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown (color_ostream &out) +{ + return CR_OK; +} + +static command_result lair(color_ostream &out, std::vector & params); + +static command_result tweak(color_ostream &out, vector ¶meters) +{ + CoreSuspender suspend; + + if (parameters.empty()) + return CR_WRONG_USAGE; + + string cmd = parameters[0]; + + if (cmd == "clear-missing") + { + df::unit *unit = getSelectedUnit(out); + if (!unit) + return CR_FAILURE; + + auto death = df::death_info::find(unit->counters.death_id); + + if (death) + { + death->flags.bits.discovered = true; + + auto crime = df::criminal_case::find(death->crime_id); + if (crime) + crime->flags.bits.discovered = true; + } + } + else if(cmd == "lair") + { + return lair(out,parameters); + } + else return CR_WRONG_USAGE; + + return CR_OK; +} + +#include "modules/Maps.h" + +command_result lair(color_ostream &out, std::vector & params) +{ + if (!Maps::IsValid()) + { + out.printerr("Map is not available!\n"); + return CR_FAILURE; + } + uint32_t x_max,y_max,z_max; + Maps::getSize(x_max,y_max,z_max); + for (size_t i = 0; i < world->map.map_blocks.size(); i++) + { + df::map_block *block = world->map.map_blocks[i]; + DFHack::occupancies40d & occupancies = block->occupancy; + // for each tile in block + for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++) + { + // set to revealed + occupancies[x][y].bits.monster_lair = true; + } + } + out.print("Map monsterized.\n"); + return CR_OK; +} \ No newline at end of file diff --git a/plugins/vdig.cpp b/plugins/vdig.cpp index b350e4574..a56d95db0 100644 --- a/plugins/vdig.cpp +++ b/plugins/vdig.cpp @@ -16,16 +16,16 @@ using std::stack; using namespace DFHack; using namespace df::enums; -command_result vdig (Core * c, vector & parameters); -command_result vdigx (Core * c, vector & parameters); -command_result autodig (Core * c, vector & parameters); -command_result expdig (Core * c, vector & parameters); -command_result digcircle (Core *c, vector & parameters); +command_result vdig (color_ostream &out, vector & parameters); +command_result vdigx (color_ostream &out, vector & parameters); +command_result autodig (color_ostream &out, vector & parameters); +command_result expdig (color_ostream &out, vector & parameters); +command_result digcircle (color_ostream &out, vector & parameters); DFHACK_PLUGIN("vdig"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.clear(); commands.push_back(PluginCommand( @@ -45,7 +45,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } @@ -79,12 +79,12 @@ bool dig (MapExtras::MapCache & MCache, return false; if(x == 0 || x == x_max * 16 - 1) { - //c->con.print("not digging map border\n"); + //out.print("not digging map border\n"); return false; } if(y == 0 || y == y_max * 16 - 1) { - //c->con.print("not digging map border\n"); + //out.print("not digging map border\n"); return false; } df::tiletype tt = MCache.tiletypeAt(at); @@ -177,7 +177,7 @@ bool lineY (MapExtras::MapCache & MCache, return true; }; -command_result digcircle (Core * c, vector & parameters) +command_result digcircle (color_ostream &out, vector & parameters) { static bool filled = false; static circle_what what = circle_set; @@ -244,7 +244,7 @@ command_result digcircle (Core * c, vector & parameters) diameter = -diameter; if(force_help || diameter == 0) { - c->con.print( + out.print( "A command for easy designation of filled and hollow circles.\n" "\n" "Options:\n" @@ -272,10 +272,10 @@ command_result digcircle (Core * c, vector & parameters) return CR_OK; } int32_t cx, cy, cz; - CoreSuspender suspend(c); + CoreSuspender suspend; if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } @@ -285,7 +285,7 @@ command_result digcircle (Core * c, vector & parameters) MapExtras::MapCache MCache; if(!Gui::getCursorCoords(cx,cy,cz) || cx == -30000) { - c->con.printerr("Can't get the cursor coords...\n"); + out.printerr("Can't get the cursor coords...\n"); return CR_FAILURE; } int r = diameter / 2; @@ -773,7 +773,7 @@ bool stamp_pattern (uint32_t bx, uint32_t by, int z_level, return true; }; -command_result expdig (Core * c, vector & parameters) +command_result expdig (color_ostream &out, vector & parameters) { bool force_help = false; static explo_how how = EXPLO_NOTHING; @@ -823,7 +823,7 @@ command_result expdig (Core * c, vector & parameters) } if(force_help || how == EXPLO_NOTHING) { - c->con.print( + out.print( "This command can be used for exploratory mining.\n" "http://dwarffortresswiki.org/Exploratory_mining\n" "\n" @@ -846,18 +846,18 @@ command_result expdig (Core * c, vector & parameters) ); return CR_OK; } - CoreSuspender suspend(c); + CoreSuspender suspend; uint32_t x_max, y_max, z_max; if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } Maps::getSize(x_max,y_max,z_max); int32_t xzzz,yzzz,z_level; if(!Gui::getViewCoords(xzzz,yzzz,z_level)) { - c->con.printerr("Can't get view coords...\n"); + out.printerr("Can't get view coords...\n"); return CR_FAILURE; } if(how == EXPLO_DIAG5) @@ -949,15 +949,15 @@ command_result expdig (Core * c, vector & parameters) return CR_OK; } -command_result vdigx (Core * c, vector & parameters) +command_result vdigx (color_ostream &out, vector & parameters) { // HOTKEY COMMAND: CORE ALREADY SUSPENDED vector lol; lol.push_back("x"); - return vdig(c,lol); + return vdig(out,lol); } -command_result vdig (Core * c, vector & parameters) +command_result vdig (color_ostream &out, vector & parameters) { // HOTKEY COMMAND: CORE ALREADY SUSPENDED uint32_t x_max,y_max,z_max; @@ -970,11 +970,11 @@ command_result vdig (Core * c, vector & parameters) return CR_WRONG_USAGE; } - Console & con = c->con; + auto &con = out; if (!Maps::IsValid()) { - c->con.printerr("Map is not available!\n"); + out.printerr("Map is not available!\n"); return CR_FAILURE; } @@ -1114,7 +1114,7 @@ command_result vdig (Core * c, vector & parameters) return CR_OK; } -command_result autodig (Core * c, vector & parameters) +command_result autodig (color_ostream &out, vector & parameters) { return CR_NOT_IMPLEMENTED; } diff --git a/plugins/versionosd.cpp b/plugins/versionosd.cpp index 2aaff49cc..7904c46cb 100644 --- a/plugins/versionosd.cpp +++ b/plugins/versionosd.cpp @@ -15,7 +15,7 @@ using namespace std; #include "modules/Gui.h" using namespace DFHack; -command_result df_versionosd (Core * c, vector & parameters); +command_result df_versionosd (color_ostream &out, vector & parameters); static DFSDL_Surface* (*_IMG_LoadPNG_RW)(void* src) = 0; static vPtr (*_SDL_RWFromFile)(const char* file, const char *mode) = 0; static int (*_SDL_SetAlpha)(vPtr surface, uint32_t flag, uint8_t alpha) = 0; @@ -45,7 +45,7 @@ DFTileSurface* createTile(int x, int y) return tile; } -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.clear(); commands.push_back(PluginCommand("versionosd", @@ -66,7 +66,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector if ( !surface ) { - c->con.print("Couldnt load image from file %s", file); + out.print("Couldnt load image from file %s", file); return CR_FAILURE; } @@ -99,7 +99,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { Graphic* g = c->getGraphic(); g->Unregister(gettile); @@ -114,12 +114,11 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) return CR_OK; } -command_result df_versionosd (Core * c, vector & parameters) +command_result df_versionosd (color_ostream &out, vector & parameters) { On = !On; - c->Suspend(); - c->con.print("Version OSD is %s\n", On ? "On" : "Off"); - c->Resume(); + CoreSuspender suspend; + out.print("Version OSD is %s\n", On ? "On" : "Off"); return CR_OK; } diff --git a/plugins/weather.cpp b/plugins/weather.cpp index d6d83cfa6..8bf171748 100644 --- a/plugins/weather.cpp +++ b/plugins/weather.cpp @@ -13,11 +13,11 @@ using namespace DFHack; bool locked = false; unsigned char locked_data[25]; -command_result weather (Core * c, vector & parameters); +command_result weather (color_ostream &out, vector & parameters); DFHACK_PLUGIN("weather"); -DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { commands.clear(); commands.push_back(PluginCommand( @@ -32,14 +32,13 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; } -command_result weather (Core * c, vector & parameters) +command_result weather (color_ostream &con, vector & parameters) { - Console & con = c->con; int val_override = -1; bool lock = false; bool unlock = false; @@ -81,8 +80,9 @@ command_result weather (Core * c, vector & parameters) } bool something = lock || unlock || rain || snow || clear || val_override != -1; - CoreSuspender suspend(c); - DFHack::World * w = c->getWorld(); + CoreSuspender suspend; + + DFHack::World * w = Core::getInstance().getWorld(); if(!w->wmap) { con << "Weather support seems broken :(" << std::endl; diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index a8ace1b02..57d7c62da 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -50,14 +50,14 @@ using df::global::job_next_id; /* Plugin registration */ -static command_result workflow_cmd(Core *c, vector & parameters); +static command_result workflow_cmd(color_ostream &out, vector & parameters); -static void init_state(Core *c); -static void cleanup_state(Core *c); +static void init_state(color_ostream &out); +static void cleanup_state(color_ostream &out); DFHACK_PLUGIN("workflow"); -DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) { commands.clear(); if (!world || !ui) @@ -118,27 +118,27 @@ DFhackCExport command_result plugin_init (Core *c, std::vector & ); } - init_state(c); + init_state(out); return CR_OK; } -DFhackCExport command_result plugin_shutdown ( Core * c ) +DFhackCExport command_result plugin_shutdown (color_ostream &out) { - cleanup_state(c); + cleanup_state(out); return CR_OK; } -DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event event) +DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) { switch (event) { case SC_GAME_LOADED: - cleanup_state(c); - init_state(c); + cleanup_state(out); + init_state(out); break; case SC_GAME_UNLOADED: - cleanup_state(c); + cleanup_state(out); break; default: break; @@ -392,12 +392,12 @@ static void setOptionEnabled(ConfigFlags flag, bool on) * STATE INITIALIZATION * ******************************/ -static void stop_protect(Core *c) +static void stop_protect(color_ostream &out) { pending_recover.clear(); if (!known_jobs.empty()) - c->con.print("Unprotecting %d jobs.\n", known_jobs.size()); + out.print("Unprotecting %d jobs.\n", known_jobs.size()); for (TKnownJobs::iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) delete it->second; @@ -405,31 +405,33 @@ static void stop_protect(Core *c) known_jobs.clear(); } -static void cleanup_state(Core *c) +static void cleanup_state(color_ostream &out) { config = PersistentDataItem(); - stop_protect(c); + stop_protect(out); for (size_t i = 0; i < constraints.size(); i++) delete constraints[i]; constraints.clear(); } -static void check_lost_jobs(Core *c, int ticks); -static ItemConstraint *get_constraint(Core *c, const std::string &str, PersistentDataItem *cfg = NULL); +static void check_lost_jobs(color_ostream &out, int ticks); +static ItemConstraint *get_constraint(color_ostream &out, const std::string &str, PersistentDataItem *cfg = NULL); -static void start_protect(Core *c) +static void start_protect(color_ostream &out) { - check_lost_jobs(c, 0); + check_lost_jobs(out, 0); if (!known_jobs.empty()) - c->con.print("Protecting %d jobs.\n", known_jobs.size()); + out.print("Protecting %d jobs.\n", known_jobs.size()); } -static void init_state(Core *c) +static void init_state(color_ostream &out) { - config = c->getWorld()->GetPersistentData("workflow/config"); + auto pworld = Core::getInstance().getWorld(); + + config = pworld->GetPersistentData("workflow/config"); if (config.isValid() && config.ival(0) == -1) config.ival(0) = 0; @@ -437,14 +439,14 @@ static void init_state(Core *c) // Parse constraints std::vector items; - c->getWorld()->GetPersistentData(&items, "workflow/constraints"); + pworld->GetPersistentData(&items, "workflow/constraints"); for (int i = items.size()-1; i >= 0; i--) { - if (get_constraint(c, items[i].val(), &items[i])) + if (get_constraint(out, items[i].val(), &items[i])) continue; - c->con.printerr("Lost constraint %s\n", items[i].val().c_str()); - c->getWorld()->DeletePersistentData(items[i]); + out.printerr("Lost constraint %s\n", items[i].val().c_str()); + pworld->DeletePersistentData(items[i]); } last_tick_frame_count = world->frame_counter; @@ -453,35 +455,37 @@ static void init_state(Core *c) if (!enabled) return; - start_protect(c); + start_protect(out); } -static void enable_plugin(Core *c) +static void enable_plugin(color_ostream &out) { + auto pworld = Core::getInstance().getWorld(); + if (!config.isValid()) { - config = c->getWorld()->AddPersistentData("workflow/config"); + config = pworld->AddPersistentData("workflow/config"); config.ival(0) = 0; } setOptionEnabled(CF_ENABLED, true); enabled = true; - c->con << "Enabling the plugin." << endl; + out << "Enabling the plugin." << endl; - start_protect(c); + start_protect(out); } /****************************** * JOB AUTO-RECOVERY * ******************************/ -static void forget_job(Core *c, ProtectedJob *pj) +static void forget_job(color_ostream &out, ProtectedJob *pj) { known_jobs.erase(pj->id); delete pj; } -static bool recover_job(Core *c, ProtectedJob *pj) +static bool recover_job(color_ostream &out, ProtectedJob *pj) { if (pj->isLive()) return true; @@ -490,18 +494,18 @@ static bool recover_job(Core *c, ProtectedJob *pj) pj->holder = df::building::find(pj->building_id); if (!pj->holder) { - c->con.printerr("Forgetting job %d (%s): holder building lost.", + out.printerr("Forgetting job %d (%s): holder building lost.", pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type)); - forget_job(c, pj); + forget_job(out, pj); return true; } // Check its state and postpone or cancel if invalid if (pj->holder->jobs.size() >= 10) { - c->con.printerr("Forgetting job %d (%s): holder building has too many jobs.", + out.printerr("Forgetting job %d (%s): holder building has too many jobs.", pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type)); - forget_job(c, pj); + forget_job(out, pj); return true; } @@ -522,7 +526,7 @@ static bool recover_job(Core *c, ProtectedJob *pj) { deleteJobStruct(recovered); - c->con.printerr("Inconsistency: job %d (%s) already in list.", + out.printerr("Inconsistency: job %d (%s) already in list.", pj->id, ENUM_KEY_STR(job_type, pj->job_copy->job_type)); return true; } @@ -534,7 +538,7 @@ static bool recover_job(Core *c, ProtectedJob *pj) return true; } -static void check_lost_jobs(Core *c, int ticks) +static void check_lost_jobs(color_ostream &out, int ticks) { ProtectedJob::cur_tick_idx++; if (ticks < 0) ticks = 0; @@ -548,7 +552,7 @@ static void check_lost_jobs(Core *c, int ticks) if (pj) { if (!job->flags.bits.repeat) - forget_job(c, pj); + forget_job(out, pj); else pj->tick_job(job, ticks); } @@ -571,7 +575,7 @@ static void check_lost_jobs(Core *c, int ticks) } } -static void update_job_data(Core *c) +static void update_job_data(color_ostream &out) { df::job_list_link *p = world->job_list.next; for (; p; p = p->next) @@ -583,16 +587,16 @@ static void update_job_data(Core *c) } } -static void recover_jobs(Core *c) +static void recover_jobs(color_ostream &out) { for (int i = pending_recover.size()-1; i >= 0; i--) - if (recover_job(c, pending_recover[i])) + if (recover_job(out, pending_recover[i])) vector_erase_at(pending_recover, i); } -static void process_constraints(Core *c); +static void process_constraints(color_ostream &out); -DFhackCExport command_result plugin_onupdate(Core* c) +DFhackCExport command_result plugin_onupdate(color_ostream &out) { if (!enabled) return CR_OK; @@ -602,7 +606,7 @@ DFhackCExport command_result plugin_onupdate(Core* c) if ((++cnt % 5) != 0) return CR_OK; - check_lost_jobs(c, world->frame_counter - last_tick_frame_count); + check_lost_jobs(out, world->frame_counter - last_tick_frame_count); last_tick_frame_count = world->frame_counter; // Proceed every in-game half-day, or when jobs to recover changed @@ -611,7 +615,7 @@ DFhackCExport command_result plugin_onupdate(Core* c) if (pending_recover.size() != last_rlen || check_time) { - recover_jobs(c); + recover_jobs(out); last_rlen = pending_recover.size(); // If the half-day passed, proceed to update @@ -619,8 +623,8 @@ DFhackCExport command_result plugin_onupdate(Core* c) { last_frame_count = world->frame_counter; - update_job_data(c); - process_constraints(c); + update_job_data(out); + process_constraints(out); } } @@ -631,7 +635,7 @@ DFhackCExport command_result plugin_onupdate(Core* c) * ITEM COUNT CONSTRAINT * ******************************/ -static ItemConstraint *get_constraint(Core *c, const std::string &str, PersistentDataItem *cfg) +static ItemConstraint *get_constraint(color_ostream &out, const std::string &str, PersistentDataItem *cfg) { std::vector tokens; split_string(&tokens, str, "/"); @@ -643,7 +647,7 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten ItemTypeInfo item; if (!item.find(tokens[0]) || !item.isValid()) { - c->con.printerr("Cannot find item type: %s\n", tokens[0].c_str()); + out.printerr("Cannot find item type: %s\n", tokens[0].c_str()); return NULL; } @@ -653,7 +657,7 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten df::dfhack_material_category mat_mask; std::string maskstr = vector_get(tokens,1); if (!maskstr.empty() && !parseJobMaterialCategory(&mat_mask, maskstr)) { - c->con.printerr("Cannot decode material mask: %s\n", maskstr.c_str()); + out.printerr("Cannot decode material mask: %s\n", maskstr.c_str()); return NULL; } @@ -663,7 +667,7 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten MaterialInfo material; std::string matstr = vector_get(tokens,2); if (!matstr.empty() && (!material.find(matstr) || !material.isValid())) { - c->con.printerr("Cannot find material: %s\n", matstr.c_str()); + out.printerr("Cannot find material: %s\n", matstr.c_str()); return NULL; } @@ -671,7 +675,7 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten weight += (material.index >= 0 ? 5000 : 1000); if (mat_mask.whole && material.isValid() && !material.matches(mat_mask)) { - c->con.printerr("Material %s doesn't match mask %s\n", matstr.c_str(), maskstr.c_str()); + out.printerr("Material %s doesn't match mask %s\n", matstr.c_str(), maskstr.c_str()); return NULL; } @@ -693,7 +697,7 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten nct->config = *cfg; else { - nct->config = c->getWorld()->AddPersistentData("workflow/constraints"); + nct->config = Core::getInstance().getWorld()->AddPersistentData("workflow/constraints"); nct->init(str); } @@ -701,13 +705,13 @@ static ItemConstraint *get_constraint(Core *c, const std::string &str, Persisten return nct; } -static void delete_constraint(Core *c, ItemConstraint *cv) +static void delete_constraint(color_ostream &out, ItemConstraint *cv) { int idx = linear_index(constraints, cv); if (idx >= 0) vector_erase_at(constraints, idx); - c->getWorld()->DeletePersistentData(cv->config); + Core::getInstance().getWorld()->DeletePersistentData(cv->config); delete cv; } @@ -858,7 +862,7 @@ static void guess_job_material(df::job *job, MaterialInfo &mat, df::dfhack_mater } } -static void compute_job_outputs(Core *c, ProtectedJob *pj) +static void compute_job_outputs(color_ostream &out, ProtectedJob *pj) { using namespace df::enums::job_type; @@ -946,7 +950,7 @@ static void compute_job_outputs(Core *c, ProtectedJob *pj) link_job_constraint(pj, itype, isubtype, mat_mask, mat.type, mat.index); } -static void map_job_constraints(Core *c) +static void map_job_constraints(color_ostream &out) { melt_active = false; @@ -968,7 +972,7 @@ static void map_job_constraints(Core *c) if (!melt_active && pj->actual_job->job_type == job_type::MeltMetalObject) melt_active = pj->isResumed(); - compute_job_outputs(c, pj); + compute_job_outputs(out, pj); } } @@ -1046,7 +1050,7 @@ static bool itemInRealJob(df::item *item) != job_type_class::Hauling; } -static void map_job_items(Core *c) +static void map_job_items(color_ostream &out) { for (size_t i = 0; i < constraints.size(); i++) { @@ -1159,7 +1163,7 @@ static void map_job_items(Core *c) static std::string shortJobDescription(df::job *job); -static void setJobResumed(Core *c, ProtectedJob *pj, bool goal) +static void setJobResumed(color_ostream &out, ProtectedJob *pj, bool goal) { bool current = pj->isResumed(); @@ -1167,14 +1171,14 @@ static void setJobResumed(Core *c, ProtectedJob *pj, bool goal) if (goal != current) { - c->con.print("%s %s%s\n", + out.print("%s %s%s\n", (goal ? "Resuming" : "Suspending"), shortJobDescription(pj->actual_job).c_str(), (!goal || pj->isActuallyResumed() ? "" : " (delayed)")); } } -static void update_jobs_by_constraints(Core *c) +static void update_jobs_by_constraints(color_ostream &out) { for (TKnownJobs::const_iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) { @@ -1185,7 +1189,7 @@ static void update_jobs_by_constraints(Core *c) if (pj->actual_job->job_type == job_type::MeltMetalObject && isOptionEnabled(CF_AUTOMELT)) { - setJobResumed(c, pj, meltable_count > 0); + setJobResumed(out, pj, meltable_count > 0); continue; } @@ -1210,7 +1214,7 @@ static void update_jobs_by_constraints(Core *c) else if (suspend_weight >= 0 && suspend_weight >= resume_weight) goal = false; - setJobResumed(c, pj, goal); + setJobResumed(out, pj, goal); } for (size_t i = 0; i < constraints.size(); i++) @@ -1250,15 +1254,15 @@ static void update_jobs_by_constraints(Core *c) } } -static void process_constraints(Core *c) +static void process_constraints(color_ostream &out) { if (constraints.empty() && !isOptionEnabled(CF_DRYBUCKETS | CF_AUTOMELT)) return; - map_job_constraints(c); - map_job_items(c); - update_jobs_by_constraints(c); + map_job_constraints(out); + map_job_items(out); + update_jobs_by_constraints(out); } /****************************** @@ -1286,7 +1290,7 @@ static std::string shortJobDescription(df::job *job) return rv; } -static void print_constraint(Core *c, ItemConstraint *cv, bool no_job = false, std::string prefix = "") +static void print_constraint(color_ostream &out, ItemConstraint *cv, bool no_job = false, std::string prefix = "") { Console::color_value color; if (cv->request_resume) @@ -1296,24 +1300,24 @@ static void print_constraint(Core *c, ItemConstraint *cv, bool no_job = false, s else color = Console::COLOR_DARKGREY; - c->con.color(color); - c->con << prefix << "Constraint " << flush; - c->con.color(Console::COLOR_GREY); - c->con << cv->config.val() << " " << flush; - c->con.color(color); - c->con << (cv->goalByCount() ? "count " : "amount ") + out.color(color); + out << prefix << "Constraint " << flush; + out.color(Console::COLOR_GREY); + out << cv->config.val() << " " << flush; + out.color(color); + out << (cv->goalByCount() ? "count " : "amount ") << cv->goalCount() << " (gap " << cv->goalGap() << ")" << endl; - c->con.reset_color(); + out.reset_color(); if (cv->item_count || cv->item_inuse) - c->con << prefix << " items: amount " << cv->item_amount << "; " + out << prefix << " items: amount " << cv->item_amount << "; " << cv->item_count << " stacks available, " << cv->item_inuse << " in use." << endl; if (no_job) return; if (cv->jobs.empty()) - c->con.printerr(" (no jobs)\n"); + out.printerr(" (no jobs)\n"); std::vector unique_jobs; std::vector unique_counts; @@ -1347,79 +1351,79 @@ static void print_constraint(Core *c, ItemConstraint *cv, bool no_job = false, s { if (pj->want_resumed) { - c->con.color(Console::COLOR_YELLOW); - c->con << start << " (delayed)" << endl; + out.color(Console::COLOR_YELLOW); + out << start << " (delayed)" << endl; } else { - c->con.color(Console::COLOR_BLUE); - c->con << start << " (suspended)" << endl; + out.color(Console::COLOR_BLUE); + out << start << " (suspended)" << endl; } } else { - c->con.color(Console::COLOR_GREEN); - c->con << start << endl; + out.color(Console::COLOR_GREEN); + out << start << endl; } - c->con.reset_color(); + out.reset_color(); if (unique_counts[i] > 1) - c->con << prefix << " (" << unique_counts[i] << " copies)" << endl; + out << prefix << " (" << unique_counts[i] << " copies)" << endl; } } -static void print_job(Core *c, ProtectedJob *pj) +static void print_job(color_ostream &out, ProtectedJob *pj) { if (!pj) return; df::job *job = pj->isLive() ? pj->actual_job : pj->job_copy; - printJobDetails(c, job); + printJobDetails(out, job); if (job->job_type == job_type::MeltMetalObject && isOptionEnabled(CF_AUTOMELT)) { if (meltable_count <= 0) - c->con.color(Console::COLOR_CYAN); + out.color(Console::COLOR_CYAN); else if (pj->want_resumed && !pj->isActuallyResumed()) - c->con.color(Console::COLOR_YELLOW); + out.color(Console::COLOR_YELLOW); else - c->con.color(Console::COLOR_GREEN); - c->con << " Meltable: " << meltable_count << " objects." << endl; - c->con.reset_color(); + out.color(Console::COLOR_GREEN); + out << " Meltable: " << meltable_count << " objects." << endl; + out.reset_color(); } for (size_t i = 0; i < pj->constraints.size(); i++) - print_constraint(c, pj->constraints[i], true, " "); + print_constraint(out, pj->constraints[i], true, " "); } -static command_result workflow_cmd(Core *c, vector & parameters) +static command_result workflow_cmd(color_ostream &out, vector & parameters) { - CoreSuspender suspend(c); + CoreSuspender suspend; - if (!c->isWorldLoaded()) { - c->con.printerr("World is not loaded: please load a game first.\n"); + if (!Core::getInstance().isWorldLoaded()) { + out.printerr("World is not loaded: please load a game first.\n"); return CR_FAILURE; } if (enabled) { - check_lost_jobs(c, 0); - recover_jobs(c); - update_job_data(c); - map_job_constraints(c); - map_job_items(c); + check_lost_jobs(out, 0); + recover_jobs(out); + update_job_data(out); + map_job_constraints(out); + map_job_items(out); } df::building *workshop = NULL; df::job *job = NULL; - if (Gui::dwarfmode_hotkey(c, c->getTopViewscreen()) && + if (Gui::dwarfmode_hotkey(Core::getTopViewscreen()) && ui->main.mode == ui_sidebar_mode::QueryBuilding) { workshop = world->selected_building; - job = Gui::getSelectedWorkshopJob(c, true); + job = Gui::getSelectedWorkshopJob(out, true); } std::string cmd = parameters.empty() ? "list" : parameters[0]; @@ -1429,7 +1433,7 @@ static command_result workflow_cmd(Core *c, vector & parameters) bool enable = (cmd == "enable"); if (enable && !enabled) { - enable_plugin(c); + enable_plugin(out); } else if (!enable && parameters.size() == 1) { @@ -1437,10 +1441,10 @@ static command_result workflow_cmd(Core *c, vector & parameters) { enabled = false; setOptionEnabled(CF_ENABLED, false); - stop_protect(c); + stop_protect(out); } - c->con << "The plugin is disabled." << endl; + out << "The plugin is disabled." << endl; return CR_OK; } @@ -1455,38 +1459,38 @@ static command_result workflow_cmd(Core *c, vector & parameters) } if (enabled) - c->con << "The plugin is enabled." << endl; + out << "The plugin is enabled." << endl; else - c->con << "The plugin is disabled." << endl; + out << "The plugin is disabled." << endl; if (isOptionEnabled(CF_DRYBUCKETS)) - c->con << "Option drybuckets is enabled." << endl; + out << "Option drybuckets is enabled." << endl; if (isOptionEnabled(CF_AUTOMELT)) - c->con << "Option auto-melt is enabled." << endl; + out << "Option auto-melt is enabled." << endl; return CR_OK; } else if (cmd == "count" || cmd == "amount") { if (!enabled) - enable_plugin(c); + enable_plugin(out); } if (!enabled) - c->con << "Note: the plugin is not enabled." << endl; + out << "Note: the plugin is not enabled." << endl; if (cmd == "jobs") { if (workshop) { for (size_t i = 0; i < workshop->jobs.size(); i++) - print_job(c, get_known(workshop->jobs[i]->id)); + print_job(out, get_known(workshop->jobs[i]->id)); } else { for (TKnownJobs::iterator it = known_jobs.begin(); it != known_jobs.end(); ++it) if (it->second->isLive()) - print_job(c, it->second); + print_job(out, it->second); } bool pending = false; @@ -1497,11 +1501,11 @@ static command_result workflow_cmd(Core *c, vector & parameters) { if (!pending) { - c->con.print("\nPending recovery:\n"); + out.print("\nPending recovery:\n"); pending = true; } - printJobDetails(c, pending_recover[i]->job_copy); + printJobDetails(out, pending_recover[i]->job_copy); } } @@ -1510,7 +1514,7 @@ static command_result workflow_cmd(Core *c, vector & parameters) else if (cmd == "list") { for (size_t i = 0; i < constraints.size(); i++) - print_constraint(c, constraints[i]); + print_constraint(out, constraints[i]); return CR_OK; } @@ -1521,11 +1525,11 @@ static command_result workflow_cmd(Core *c, vector & parameters) int limit = atoi(parameters[2].c_str()); if (limit <= 0) { - c->con.printerr("Invalid limit value.\n"); + out.printerr("Invalid limit value.\n"); return CR_FAILURE; } - ItemConstraint *icv = get_constraint(c, parameters[1]); + ItemConstraint *icv = get_constraint(out, parameters[1]); if (!icv) return CR_FAILURE; @@ -1536,8 +1540,8 @@ static command_result workflow_cmd(Core *c, vector & parameters) else icv->setGoalGap(-1); - process_constraints(c); - print_constraint(c, icv); + process_constraints(out); + print_constraint(out, icv); return CR_OK; } else if (cmd == "unlimit") @@ -1550,11 +1554,11 @@ static command_result workflow_cmd(Core *c, vector & parameters) if (constraints[i]->config.val() != parameters[1]) continue; - delete_constraint(c, constraints[i]); + delete_constraint(out, constraints[i]); return CR_OK; } - c->con.printerr("Constraint not found: %s\n", parameters[1].c_str()); + out.printerr("Constraint not found: %s\n", parameters[1].c_str()); return CR_FAILURE; } else