JonJac / CommunicationMod

Slay the Spire mod that provides a protocol for allowing another process to control the game

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CommunicationMod

Slay the Spire mod that provides a protocol for allowing another process to control the game

Requirements

Setup

  1. Copy CommunicationMod.jar to your ModTheSpire mods directory
  2. Run ModTheSpire with CommunicationMod enabled
  3. Edit your newly-created SpireConfig file with the command you want to use with CommunicationMod (see https://github.com/kiooeht/ModTheSpire/wiki/SpireConfig for the location of your config file). Your config file should look something like this (note that certain special characters must be escaped):
#Sat Apr 20 02:49:10 CDT 2019
command=python C\:\\Path\\To\\Script\\main.py

What does this mod do?

CommunicationMod launches a specified process and communicates with this process through stdin and stdout, with the following protocol:

(Note: all messages are assumed to be ended by a new line '\n')

  • After starting the external process, CommunicationMod waits for the process to send "ready" on stdout. If "ready" is not received before a specified timeout, the external process will be terminated.
  • Whenever the state of the game is determined to be stable (no longer changing without external input), CommunicationMod sends a message containing the JSON representation of the current game state to the external process's stdin. For example:
{"available_commands":["play","end","state"],"ready_for_command":true,"in_game":true,"game_state":{"screen_type":"NONE","screen_state":{},"seed":-4880945218683215126,"combat_state":{"draw_pile":[{"exhausts":false,"is_playable":true,"cost":1,"name":"Shrug It Off","id":"Shrug It Off","type":"SKILL","uuid":"24dfc10c-72cd-43eb-a1fa-2be92a789c9d","upgrades":0,"rarity":"COMMON","has_target":false},{"exhausts":false,"is_playable":false,"cost":2,"name":"Perfected Strike+","id":"Perfected Strike","type":"ATTACK","uuid":"c23804cc-c540-4d33-9828-545e4cf4fb56","upgrades":1,"rarity":"COMMON","has_target":true},{"exhausts":false,"is_playable":true,"cost":0,"name":"Flex","id":"Flex","type":"SKILL","uuid":"a6de031e-dd68-415b-ad2c-a8a6c633d267","upgrades":0,"rarity":"COMMON","has_target":false},{"exhausts":false,"is_playable":true,"cost":1,"name":"Shrug It Off","id":"Shrug It Off","type":"SKILL","uuid":"65324cd9-fa2d-4a4f-a79b-fdf0e65f9751","upgrades":0,"rarity":"COMMON","has_target":false},{"exhausts":false,"is_playable":true,"cost":1,"name":"Pommel Strike+","id":"Pommel Strike","type":"ATTACK","uuid":"eabe2f55-9a21-478d-a390-040b5ff8cee6","upgrades":1,"rarity":"COMMON","has_target":true},{"exhausts":true,"is_playable":false,"cost":2,"name":"Impervious","id":"Impervious","type":"SKILL","uuid":"251b9c7b-741b-4093-9003-ad49abc4a253","upgrades":0,"rarity":"RARE","has_target":false},{"exhausts":false,"is_playable":true,"cost":1,"name":"Strike","id":"Strike_R","type":"ATTACK","uuid":"681a3595-d8f1-4722-8d47-1a6127dff6bd","upgrades":0,"rarity":"BASIC","has_target":true},{"exhausts":false,"is_playable":true,"cost":0,"name":"Flex+","id":"Flex","type":"SKILL","uuid":"96abf8e7-3801-42f1-bcf9-4faca26d5f98","upgrades":1,"rarity":"COMMON","has_target":false},{"exhausts":false,"is_playable":true,"cost":1,"name":"Strike","id":"Strike_R","type":"ATTACK","uuid":"f71f863d-d925-4223-bfca-a8e7a9feb427","upgrades":0,"rarity":"BASIC","has_target":true},{"exhausts":false,"is_playable":true,"cost":-1,"name":"Whirlwind","id":"Whirlwind","type":"ATTACK","uuid":"f2cb0505-a9b3-4608-9df6-b9920b2784c2","upgrades":0,"rarity":"UNCOMMON","has_target":false},{"exhausts":false,"is_playable":true,"cost":1,"name":"Metallicize","id":"Metallicize","type":"POWER","uuid":"e59b3baf-f44b-4bf9-b5b4-782284f65137","upgrades":0,"rarity":"UNCOMMON","has_target":false},{"exhausts":false,"is_playable":false,"cost":2,"name":"Flame Barrier","id":"Flame Barrier","type":"SKILL","uuid":"e20f5b92-97f0-4a6d-b00e-98f8d5c03494","upgrades":0,"rarity":"UNCOMMON","has_target":false}],"discard_pile":[{"exhausts":false,"is_playable":true,"cost":1,"name":"Double Tap","id":"Double Tap","type":"SKILL","uuid":"aa73afd6-6771-4a4b-853b-3e16bc0a04fc","upgrades":0,"rarity":"RARE","has_target":false},{"exhausts":false,"is_playable":false,"cost":2,"name":"Bash","id":"Bash","type":"ATTACK","uuid":"39e82c5d-c402-4e56-8b69-ef6485a9f0b8","upgrades":0,"rarity":"BASIC","has_target":true},{"exhausts":false,"is_playable":true,"cost":0,"name":"Clash+","id":"Clash","type":"ATTACK","uuid":"c2d52d19-4e27-428a-bf07-914de89f5da6","upgrades":1,"rarity":"COMMON","has_target":true},{"exhausts":false,"is_playable":true,"cost":1,"name":"Strike","id":"Strike_R","type":"ATTACK","uuid":"2b0c6073-6c4c-4dc1-9b27-58df68f5935f","upgrades":0,"rarity":"BASIC","has_target":true},{"exhausts":false,"is_playable":false,"cost":2,"name":"Perfected Strike+","id":"Perfected Strike","type":"ATTACK","uuid":"78f25d9b-5062-4774-b989-9f8e7c9619ca","upgrades":1,"rarity":"COMMON","has_target":true}],"exhaust_pile":[{"exhausts":true,"is_playable":true,"cost":1,"name":"Disarm","id":"Disarm","type":"SKILL","uuid":"4f679e9c-6f09-4ae7-b6ac-25b25998e2e1","upgrades":0,"rarity":"UNCOMMON","has_target":true},{"exhausts":true,"is_playable":true,"cost":1,"name":"Limit Break","id":"Limit Break","type":"SKILL","uuid":"49762b0a-c774-499c-917d-8b30ef5952d4","upgrades":0,"rarity":"RARE","has_target":false}],"monsters":[{"is_gone":false,"move_hits":1,"move_base_damage":7,"half_dead":false,"move_adjusted_damage":10,"max_hp":39,"intent":"ATTACK","move_id":1,"name":"Torch Head","current_hp":39,"block":0,"id":"TorchHead","powers":[{"amount":-1,"name":"Minion","id":"Minion"}]},{"is_gone":true,"move_hits":1,"move_base_damage":7,"half_dead":false,"move_adjusted_damage":10,"max_hp":39,"intent":"ATTACK","move_id":1,"name":"Torch Head","current_hp":0,"block":0,"id":"TorchHead","powers":[]},{"is_gone":true,"move_hits":1,"move_base_damage":7,"half_dead":false,"move_adjusted_damage":10,"max_hp":38,"intent":"ATTACK","move_id":1,"name":"Torch Head","current_hp":0,"block":0,"id":"TorchHead","powers":[{"amount":-1,"name":"Minion","id":"Minion"}]},{"is_gone":true,"move_hits":1,"move_base_damage":7,"half_dead":false,"move_adjusted_damage":10,"max_hp":38,"intent":"ATTACK","move_id":1,"name":"Torch Head","current_hp":0,"block":0,"id":"TorchHead","powers":[]},{"is_gone":false,"move_hits":1,"move_base_damage":18,"half_dead":false,"move_adjusted_damage":28,"max_hp":282,"intent":"ATTACK","move_id":2,"name":"The Collector","current_hp":183,"block":0,"id":"TheCollector","powers":[{"amount":1,"name":"Strength","id":"Strength"}]}],"limbo":[],"hand":[{"exhausts":false,"is_playable":true,"cost":1,"name":"Strike","id":"Strike_R","type":"ATTACK","uuid":"cb8c854b-2142-4eea-abdf-708a059771c9","upgrades":0,"rarity":"BASIC","has_target":true},{"exhausts":false,"is_playable":true,"cost":1,"name":"Strike","id":"Strike_R","type":"ATTACK","uuid":"6295663b-61a9-4365-8f4f-3e6e31d31c73","upgrades":0,"rarity":"BASIC","has_target":true},{"exhausts":false,"is_playable":false,"cost":2,"name":"Perfected Strike+","id":"Perfected Strike","type":"ATTACK","uuid":"83d82aaa-b91f-4e0d-a1a5-4c5a97865c52","upgrades":1,"rarity":"COMMON","has_target":true},{"exhausts":false,"is_playable":false,"cost":2,"name":"Perfected Strike","id":"Perfected Strike","type":"ATTACK","uuid":"f80ece4f-1d49-4045-a9c3-892333c42e25","upgrades":0,"rarity":"COMMON","has_target":true}],"player":{"orbs":[],"current_hp":31,"block":0,"max_hp":80,"powers":[{"amount":16,"name":"Strength","id":"Strength"},{"amount":2,"name":"Demon Form","id":"Demon Form"},{"amount":2,"just_applied":false,"name":"Vulnerable","id":"Vulnerable"},{"amount":1,"name":"Dexterity","id":"Dexterity"},{"amount":2,"just_applied":false,"name":"Frail","id":"Frail"},{"amount":2,"just_applied":false,"name":"Weakened","id":"Weakened"}],"energy":3}},"deck":[{"exhausts":false,"is_playable":true,"cost":1,"name":"Strike","id":"Strike_R","type":"ATTACK","uuid":"681a3595-d8f1-4722-8d47-1a6127dff6bd","upgrades":0,"rarity":"BASIC","has_target":true},{"exhausts":false,"is_playable":true,"cost":1,"name":"Strike","id":"Strike_R","type":"ATTACK","uuid":"cb8c854b-2142-4eea-abdf-708a059771c9","upgrades":0,"rarity":"BASIC","has_target":true},{"exhausts":false,"is_playable":true,"cost":1,"name":"Strike","id":"Strike_R","type":"ATTACK","uuid":"2b0c6073-6c4c-4dc1-9b27-58df68f5935f","upgrades":0,"rarity":"BASIC","has_target":true},{"exhausts":false,"is_playable":true,"cost":1,"name":"Strike","id":"Strike_R","type":"ATTACK","uuid":"f71f863d-d925-4223-bfca-a8e7a9feb427","upgrades":0,"rarity":"BASIC","has_target":true},{"exhausts":false,"is_playable":true,"cost":1,"name":"Strike","id":"Strike_R","type":"ATTACK","uuid":"6295663b-61a9-4365-8f4f-3e6e31d31c73","upgrades":0,"rarity":"BASIC","has_target":true},{"exhausts":false,"is_playable":false,"cost":2,"name":"Bash","id":"Bash","type":"ATTACK","uuid":"39e82c5d-c402-4e56-8b69-ef6485a9f0b8","upgrades":0,"rarity":"BASIC","has_target":true},{"exhausts":true,"is_playable":false,"cost":2,"name":"Impervious","id":"Impervious","type":"SKILL","uuid":"251b9c7b-741b-4093-9003-ad49abc4a253","upgrades":0,"rarity":"RARE","has_target":false},{"exhausts":false,"is_playable":false,"cost":2,"name":"Perfected Strike+","id":"Perfected Strike","type":"ATTACK","uuid":"78f25d9b-5062-4774-b989-9f8e7c9619ca","upgrades":1,"rarity":"COMMON","has_target":true},{"exhausts":false,"is_playable":true,"cost":-1,"name":"Whirlwind","id":"Whirlwind","type":"ATTACK","uuid":"f2cb0505-a9b3-4608-9df6-b9920b2784c2","upgrades":0,"rarity":"UNCOMMON","has_target":false},{"exhausts":false,"is_playable":false,"cost":2,"name":"Perfected Strike+","id":"Perfected Strike","type":"ATTACK","uuid":"c23804cc-c540-4d33-9828-545e4cf4fb56","upgrades":1,"rarity":"COMMON","has_target":true},{"exhausts":false,"is_playable":true,"cost":1,"name":"Shrug It Off","id":"Shrug It Off","type":"SKILL","uuid":"65324cd9-fa2d-4a4f-a79b-fdf0e65f9751","upgrades":0,"rarity":"COMMON","has_target":false},{"exhausts":false,"is_playable":false,"cost":2,"name":"Perfected Strike+","id":"Perfected Strike","type":"ATTACK","uuid":"83d82aaa-b91f-4e0d-a1a5-4c5a97865c52","upgrades":1,"rarity":"COMMON","has_target":true},{"exhausts":false,"is_playable":true,"cost":0,"name":"Flex","id":"Flex","type":"SKILL","uuid":"a6de031e-dd68-415b-ad2c-a8a6c633d267","upgrades":0,"rarity":"COMMON","has_target":false},{"exhausts":false,"is_playable":true,"cost":1,"name":"Double Tap","id":"Double Tap","type":"SKILL","uuid":"aa73afd6-6771-4a4b-853b-3e16bc0a04fc","upgrades":0,"rarity":"RARE","has_target":false},{"exhausts":false,"is_playable":true,"cost":1,"name":"Shrug It Off","id":"Shrug It Off","type":"SKILL","uuid":"24dfc10c-72cd-43eb-a1fa-2be92a789c9d","upgrades":0,"rarity":"COMMON","has_target":false},{"exhausts":false,"is_playable":true,"cost":1,"name":"Metallicize","id":"Metallicize","type":"POWER","uuid":"e59b3baf-f44b-4bf9-b5b4-782284f65137","upgrades":0,"rarity":"UNCOMMON","has_target":false},{"exhausts":true,"is_playable":true,"cost":1,"name":"Limit Break","id":"Limit Break","type":"SKILL","uuid":"49762b0a-c774-499c-917d-8b30ef5952d4","upgrades":0,"rarity":"RARE","has_target":false},{"exhausts":false,"is_playable":true,"cost":0,"name":"Clash+","id":"Clash","type":"ATTACK","uuid":"c2d52d19-4e27-428a-bf07-914de89f5da6","upgrades":1,"rarity":"COMMON","has_target":true},{"exhausts":false,"is_playable":true,"cost":1,"name":"Pommel Strike+","id":"Pommel Strike","type":"ATTACK","uuid":"eabe2f55-9a21-478d-a390-040b5ff8cee6","upgrades":1,"rarity":"COMMON","has_target":true},{"exhausts":false,"is_playable":true,"cost":0,"name":"Flex+","id":"Flex","type":"SKILL","uuid":"96abf8e7-3801-42f1-bcf9-4faca26d5f98","upgrades":1,"rarity":"COMMON","has_target":false},{"exhausts":true,"is_playable":true,"cost":1,"name":"Disarm","id":"Disarm","type":"SKILL","uuid":"4f679e9c-6f09-4ae7-b6ac-25b25998e2e1","upgrades":0,"rarity":"UNCOMMON","has_target":true},{"exhausts":false,"is_playable":false,"cost":2,"name":"Flame Barrier","id":"Flame Barrier","type":"SKILL","uuid":"e20f5b92-97f0-4a6d-b00e-98f8d5c03494","upgrades":0,"rarity":"UNCOMMON","has_target":false},{"exhausts":false,"is_playable":false,"cost":2,"name":"Perfected Strike","id":"Perfected Strike","type":"ATTACK","uuid":"f80ece4f-1d49-4045-a9c3-892333c42e25","upgrades":0,"rarity":"COMMON","has_target":true},{"exhausts":false,"is_playable":false,"cost":3,"name":"Demon Form","id":"Demon Form","type":"POWER","uuid":"20030dc6-af1a-455a-ba6d-2cccf13e169c","upgrades":0,"rarity":"RARE","has_target":false}],"relics":[{"name":"Burning Blood","id":"Burning Blood","counter":-1},{"name":"Potion Belt","id":"Potion Belt","counter":-1},{"name":"Preserved Insect","id":"PreservedInsect","counter":-1},{"name":"Vajra","id":"Vajra","counter":-1},{"name":"Kunai","id":"Kunai","counter":1},{"name":"Astrolabe","id":"Astrolabe","counter":-1},{"name":"Art of War","id":"Art of War","counter":-1},{"name":"Matryoshka","id":"Matryoshka","counter":2}],"max_hp":80,"act_boss":"Champ","gold":126,"action_phase":"WAITING_ON_USER","act":2,"screen_name":"NONE","room_phase":"COMBAT","is_screen_up":false,"potions":[{"requires_target":false,"can_use":false,"can_discard":false,"name":"Potion Slot","id":"Potion Slot"},{"requires_target":false,"can_use":false,"can_discard":false,"name":"Potion Slot","id":"Potion Slot"},{"requires_target":false,"can_use":false,"can_discard":false,"name":"Potion Slot","id":"Potion Slot"},{"requires_target":false,"can_use":false,"can_discard":false,"name":"Potion Slot","id":"Potion Slot"},{"requires_target":false,"can_use":false,"can_discard":false,"name":"Potion Slot","id":"Potion Slot"}],"current_hp":31,"floor":33,"ascension_level":0,"class":"IRONCLAD","map":[{"symbol":"M","children":[{"x":0,"y":1},{"x":1,"y":1}],"x":1,"y":0,"parents":[]},{"symbol":"M","children":[{"x":3,"y":1}],"x":2,"y":0,"parents":[]},{"symbol":"M","children":[{"x":4,"y":1},{"x":5,"y":1}],"x":5,"y":0,"parents":[]},{"symbol":"M","children":[{"x":1,"y":2}],"x":0,"y":1,"parents":[]},{"symbol":"?","children":[{"x":1,"y":2}],"x":1,"y":1,"parents":[]},{"symbol":"?","children":[{"x":3,"y":2},{"x":4,"y":2}],"x":3,"y":1,"parents":[]},{"symbol":"?","children":[{"x":4,"y":2}],"x":4,"y":1,"parents":[]},{"symbol":"M","children":[{"x":6,"y":2}],"x":5,"y":1,"parents":[]},{"symbol":"?","children":[{"x":1,"y":3}],"x":1,"y":2,"parents":[]},{"symbol":"?","children":[{"x":3,"y":3}],"x":3,"y":2,"parents":[]},{"symbol":"M","children":[{"x":4,"y":3},{"x":5,"y":3}],"x":4,"y":2,"parents":[]},{"symbol":"?","children":[{"x":5,"y":3}],"x":6,"y":2,"parents":[]},{"symbol":"?","children":[{"x":0,"y":4},{"x":2,"y":4}],"x":1,"y":3,"parents":[]},{"symbol":"M","children":[{"x":3,"y":4}],"x":3,"y":3,"parents":[]},{"symbol":"M","children":[{"x":3,"y":4}],"x":4,"y":3,"parents":[]},{"symbol":"$","children":[{"x":4,"y":4},{"x":5,"y":4}],"x":5,"y":3,"parents":[]},{"symbol":"?","children":[{"x":1,"y":5}],"x":0,"y":4,"parents":[]},{"symbol":"M","children":[{"x":2,"y":5}],"x":2,"y":4,"parents":[]},{"symbol":"?","children":[{"x":2,"y":5},{"x":3,"y":5}],"x":3,"y":4,"parents":[]},{"symbol":"M","children":[{"x":4,"y":5}],"x":4,"y":4,"parents":[]},{"symbol":"?","children":[{"x":5,"y":5}],"x":5,"y":4,"parents":[]},{"symbol":"E","children":[{"x":1,"y":6}],"x":1,"y":5,"parents":[]},{"symbol":"R","children":[{"x":1,"y":6},{"x":3,"y":6}],"x":2,"y":5,"parents":[]},{"symbol":"E","children":[{"x":4,"y":6}],"x":3,"y":5,"parents":[]},{"symbol":"R","children":[{"x":4,"y":6}],"x":4,"y":5,"parents":[]},{"symbol":"M","children":[{"x":4,"y":6}],"x":5,"y":5,"parents":[]},{"symbol":"M","children":[{"x":0,"y":7},{"x":1,"y":7}],"x":1,"y":6,"parents":[]},{"symbol":"E","children":[{"x":3,"y":7}],"x":3,"y":6,"parents":[]},{"symbol":"M","children":[{"x":3,"y":7},{"x":4,"y":7},{"x":5,"y":7}],"x":4,"y":6,"parents":[]},{"symbol":"M","children":[{"x":1,"y":8}],"x":0,"y":7,"parents":[]},{"symbol":"E","children":[{"x":2,"y":8}],"x":1,"y":7,"parents":[]},{"symbol":"M","children":[{"x":2,"y":8},{"x":3,"y":8}],"x":3,"y":7,"parents":[]},{"symbol":"$","children":[{"x":4,"y":8}],"x":4,"y":7,"parents":[]},{"symbol":"R","children":[{"x":5,"y":8}],"x":5,"y":7,"parents":[]},{"symbol":"T","children":[{"x":1,"y":9}],"x":1,"y":8,"parents":[]},{"symbol":"T","children":[{"x":1,"y":9}],"x":2,"y":8,"parents":[]},{"symbol":"T","children":[{"x":2,"y":9}],"x":3,"y":8,"parents":[]},{"symbol":"T","children":[{"x":3,"y":9}],"x":4,"y":8,"parents":[]},{"symbol":"T","children":[{"x":5,"y":9}],"x":5,"y":8,"parents":[]},{"symbol":"M","children":[{"x":0,"y":10},{"x":2,"y":10}],"x":1,"y":9,"parents":[]},{"symbol":"M","children":[{"x":2,"y":10}],"x":2,"y":9,"parents":[]},{"symbol":"M","children":[{"x":4,"y":10}],"x":3,"y":9,"parents":[]},{"symbol":"M","children":[{"x":6,"y":10}],"x":5,"y":9,"parents":[]},{"symbol":"M","children":[{"x":0,"y":11},{"x":1,"y":11}],"x":0,"y":10,"parents":[]},{"symbol":"R","children":[{"x":1,"y":11},{"x":2,"y":11}],"x":2,"y":10,"parents":[]},{"symbol":"M","children":[{"x":4,"y":11}],"x":4,"y":10,"parents":[]},{"symbol":"M","children":[{"x":5,"y":11}],"x":6,"y":10,"parents":[]},{"symbol":"R","children":[{"x":0,"y":12}],"x":0,"y":11,"parents":[]},{"symbol":"E","children":[{"x":0,"y":12},{"x":1,"y":12}],"x":1,"y":11,"parents":[]},{"symbol":"?","children":[{"x":2,"y":12}],"x":2,"y":11,"parents":[]},{"symbol":"R","children":[{"x":5,"y":12}],"x":4,"y":11,"parents":[]},{"symbol":"M","children":[{"x":6,"y":12}],"x":5,"y":11,"parents":[]},{"symbol":"?","children":[{"x":0,"y":13},{"x":1,"y":13}],"x":0,"y":12,"parents":[]},{"symbol":"M","children":[{"x":1,"y":13}],"x":1,"y":12,"parents":[]},{"symbol":"M","children":[{"x":3,"y":13}],"x":2,"y":12,"parents":[]},{"symbol":"$","children":[{"x":4,"y":13}],"x":5,"y":12,"parents":[]},{"symbol":"R","children":[{"x":5,"y":13}],"x":6,"y":12,"parents":[]},{"symbol":"M","children":[{"x":0,"y":14}],"x":0,"y":13,"parents":[]},{"symbol":"?","children":[{"x":1,"y":14}],"x":1,"y":13,"parents":[]},{"symbol":"M","children":[{"x":4,"y":14}],"x":3,"y":13,"parents":[]},{"symbol":"M","children":[{"x":4,"y":14}],"x":4,"y":13,"parents":[]},{"symbol":"M","children":[{"x":5,"y":14}],"x":5,"y":13,"parents":[]},{"symbol":"R","children":[{"x":3,"y":16}],"x":0,"y":14,"parents":[]},{"symbol":"R","children":[{"x":3,"y":16}],"x":1,"y":14,"parents":[]},{"symbol":"R","children":[{"x":3,"y":16}],"x":4,"y":14,"parents":[]},{"symbol":"R","children":[{"x":3,"y":16}],"x":5,"y":14,"parents":[]}],"room_type":"MonsterRoomBoss"}}
  • CommunicationMod then waits for a message back from the external process, containing a command to be executed. Possible commands are:
    • START PlayerClass [AscensionLevel] [Seed]
      • Starts a new game with the selected class, on the selected Ascension level (default 0), with the selected seed (random seed if omitted).
      • Seeds are alphanumeric, as displayed in game.
      • This and all commands are case insensitive.
      • Only currently available in the main menu of the game.
    • POTION Use|Discard PotionSlot [TargetIndex]
      • Uses or discards the potion in the selected slot, on the selected target, if necessary.
      • TargetIndex is the index of the target monster in the game's monster array (0-indexed).
      • Only available when potions can be used or discarded.
    • PLAY CardIndex [TargetIndex]
      • Plays the selected card in your hand, with the selected target, if necessary.
      • Only available when cards can be played in combat.
      • Currently, CardIndex is 1-indexed to match up with the card numbers in game.
    • END
      • Ends your turn.
      • Only available when the end turn button is available, in combat.
    • CHOOSE ChoiceIndex|ChoiceName
      • Makes a choice relevant to the current screen.
      • A list of names for each choice is provided in the game state. If provided with a name, the first choice index with the matching name is selected.
      • Generally, available at any point when PLAY is not available.
    • PROCEED
      • Clicks the button on the right side of the screen, generally causing the game to proceed to a new screen.
      • Equivalent to CONFIRM.
      • Available whenever the proceed or confirm button is present on the right side of the screen.
    • RETURN
      • Clicks the button on the left side of the screen, generally causing you to return to the previous screen.
      • Equivalent to SKIP, CANCEL, and LEAVE.
      • Available whenever the return, cancel, or leave buttons are present on the left side of the screen. Also used for the skip button on card reward screens.
    • STATE
      • Causes CommunicationMod to immediately send a JSON representation of the current state to the external process, whether or not the game state is stable.
      • Always available.
  • Upon receiving a command, CommunicationMod will execute it, and reply again with a JSON representation of the state of the game, when it is next stable.
  • If there was an error in executing the command, CommunicationMod will instead send an error message of the form:
{"error":"Error message","ready_for_command":True}

Known issues and limitations, to be hopefully fixed soon:

  • The full state of the Match and Keep event is not transmitted.
  • There is no feedback or state change if you attempt to take or buy a potion while your potion inventory is full. Beware!
  • Unselecting cards in hand select screens is not supported.
  • Several actions do not currently register a state change if they are performed manually in game.
  • You must manually edit the mod's config file to set the command for your external process.
  • Communication Mod has only been tested on Windows 10 at this point.
  • Communication Mod has not been tested without fast mode on.
  • Some of the commands will currently hijack your mouse cursor, though the hijacking of your mouse will go away in future versions.

What are some of the potential applications of this mod?

  • Twitch plays Slay the Spire
  • Slay the Spire AIs
  • Streamers can display detailed information about the current run while in game

About

Slay the Spire mod that provides a protocol for allowing another process to control the game

License:MIT License


Languages

Language:Java 100.0%