Document bot commands

This commit is contained in:
Tanner Collin 2021-04-19 03:59:00 +00:00
parent 3aa766926b
commit 679030ff9a
3 changed files with 145 additions and 46 deletions

120
README.md
View File

@ -33,78 +33,108 @@ Talking to bot (All commands can be found in "game.py" under "public commands",
Use prefix (in this case, "1") to call to attention before giving command. (EX. 1ping, 1here, etc.) Use prefix (in this case, "1") to call to attention before giving command. (EX. 1ping, 1here, etc.)
# ping
Will respond "pong" if active and listening
# pos ### Public Commands
Will respond with current position
# afk These can be ran by anyone, all bots will reply
Will afk (if not already)
# unafk !ping - replies with "pong"
Will unafk (if afk)
# error !echo [data] - replies with "data"
---
# inv !pos - replies with position and dimension
Will list inventory (in terminal)
!afk - goes AFK with /afk
# time !unafk - goes not AFK with /afk
---
# count !error - raises an error
---
# loaded !inv - prints current inventory
---
# players !time - replies with Minecraft world time
---
# objects !count [id] - counts the number of items with that id
---
# mobs !loaded - replies with the current loaded area
---
# monsters !players - prints the current players
---
# villagers !players clear - clears the current player list
---
# threats !objects - prints the current items on ground
---
# spiral !objects clear - clears the current object list
---
# sand slice !mobs - prints the current mobs
---
# zzz !mobs clear - clears the current mob list
Will afk if in overworld, and if not already afk
# tree !monsters - prints the current monsters
---
# block !villagers - prints the current villagers
---
# !threats - prints the dangerous monsters within 20 blocks
!threats [num] - prints the dangerous monsters within num blocks
"zzz" or !zzz - bot does /afk to let others sleep
!tree - replies with the closest tree
!block x y z - replies what block is at (x, y, z)
### Bot-specific Commands
## temporary workarounds These will only run for the bot they are addressed to
# Add "?" to line 457, which is "match1 = re.match(r'<(\w+)> (.*)', text)" 1respawn - respawns the bot if it's dead
It should now look like this "match1 = re.match(r'<?(\w+)> (.*)', text)"
This allows the bot to react to commands made by someone else than the creator of code (Tanner6)
1gather wood - gathers wood from the world
1gather sand - gathers sand from the world
1farm wood - farms wood from a certain area
1farm sand - farms sand from a certain area
1farm wart - farms netherwart from a certain area
1farm crop - farms mature crops from a certain area
1loiter - stands still but eats, sleeps, and flees
1trade - sells items to villagers to get emeralds
1stop - stops the current job and resets bot
1drop - drops the current stack its holding
1select [id] - moves item with id into main hand
1dump [id] - drops all items matching id
1drain - drops all items in inventory
1fill [x] [y] [z] [x] [y] [z] - fills the cuboid with the block at the first coordinate
1here - bot comes to your location
1goto [x] [y] [z] - sends the bot to coordinate (x, y, z)
1close - closes the current Minecraft window
1click [slot] [button] [mode] - clicks the current window
1use - use the item it's currently holding
1interact [entity id] - interacts with that entity
### Authorized Commands
These dangerous commands can only be ran by the bot owner
1print [expression] - replies with Python eval(expression)
1exit - exits the program

58
game.py
View File

@ -491,29 +491,37 @@ class Game:
try: try:
################# Public commands ######################## ## ### Public Commands
## These can be ran by anyone, all bots will reply
## !ping - replies with "pong"
if command == 'ping': if command == 'ping':
reply = 'pong' reply = 'pong'
## !echo [data] - replies with "data"
if command == 'echo' and data: if command == 'echo' and data:
reply = data reply = data
## !pos - replies with position and dimension
if command == 'pos': if command == 'pos':
reply = str(utils.pint(self.g.pos))[1:-1] + ', ' + self.g.dimension reply = str(utils.pint(self.g.pos))[1:-1] + ', ' + self.g.dimension
## !afk - goes AFK with /afk
if command == 'afk': if command == 'afk':
if not self.g.afk: if not self.g.afk:
reply = '/afk' reply = '/afk'
## !unafk - goes not AFK with /afk
if command == 'unafk': if command == 'unafk':
if self.g.afk: if self.g.afk:
reply = '/afk' reply = '/afk'
## !error - raises an error
if command == 'error': if command == 'error':
reply = 'ok' reply = 'ok'
raise raise
## !inv - prints current inventory
if command == 'inv': if command == 'inv':
inv_list = [] inv_list = []
for i in self.g.inv.values(): for i in self.g.inv.values():
@ -523,16 +531,21 @@ class Game:
result = '\n'.join(inv_list) result = '\n'.join(inv_list)
print(result or 'Empty') print(result or 'Empty')
## !time - replies with Minecraft world time
if command == 'time': if command == 'time':
reply = str(self.g.time) reply = str(self.g.time)
## !count [id] - counts the number of items with that id
if command == 'count' and data: if command == 'count' and data:
item = int(data) item = int(data)
reply = str(self.count_items([item])) reply = str(self.count_items([item]))
## !loaded - replies with the current loaded area
if command == 'loaded': if command == 'loaded':
reply = str(self.g.chunks.get_loaded_area()) reply = str(self.g.chunks.get_loaded_area())
## !players - prints the current players
## !players clear - clears the current player list
if command == 'players': if command == 'players':
if data == 'clear': if data == 'clear':
self.g.players = {} self.g.players = {}
@ -541,6 +554,8 @@ class Game:
for k, v in self.g.players.items(): for k, v in self.g.players.items():
print(str(k) + ':', v, self.g.player_names[v.player_uuid]) print(str(k) + ':', v, self.g.player_names[v.player_uuid])
## !objects - prints the current items on ground
## !objects clear - clears the current object list
if command == 'objects': if command == 'objects':
if data == 'clear': if data == 'clear':
self.g.objects = {} self.g.objects = {}
@ -550,6 +565,8 @@ class Game:
if data and v.item_id != int(data): continue if data and v.item_id != int(data): continue
print(str(k) + ':', v, items.ITEM_NAMES[v.item_id]) print(str(k) + ':', v, items.ITEM_NAMES[v.item_id])
## !mobs - prints the current mobs
## !mobs clear - clears the current mob list
if command == 'mobs': if command == 'mobs':
if data == 'clear': if data == 'clear':
self.g.mobs = {} self.g.mobs = {}
@ -561,6 +578,7 @@ class Game:
print(str(k) + ':', v, mobs.MOB_NAMES[v.type]) print(str(k) + ':', v, mobs.MOB_NAMES[v.type])
reply = str(len(all_mobs)) + ' mobs' reply = str(len(all_mobs)) + ' mobs'
## !monsters - prints the current monsters
if command == 'monsters': if command == 'monsters':
monsters = sorted(list(self.g.mobs.items()), key=lambda x: x[1].type) monsters = sorted(list(self.g.mobs.items()), key=lambda x: x[1].type)
count = 0 count = 0
@ -571,6 +589,7 @@ class Game:
print(str(k) + ':', v, mobs.MOB_NAMES[v.type]) print(str(k) + ':', v, mobs.MOB_NAMES[v.type])
reply = str(count) + ' monsters' reply = str(count) + ' monsters'
## !villagers - prints the current villagers
if command == 'villagers': if command == 'villagers':
all_mobs = sorted(list(self.g.mobs.items()), key=lambda x: x[1].type) all_mobs = sorted(list(self.g.mobs.items()), key=lambda x: x[1].type)
count = 0 count = 0
@ -581,6 +600,8 @@ class Game:
print(str(k) + ':', v, type_name) print(str(k) + ':', v, type_name)
reply = str(count) + ' villagers' reply = str(count) + ' villagers'
## !threats - prints the dangerous monsters within 20 blocks
## !threats [num] - prints the dangerous monsters within num blocks
if command == 'threats': if command == 'threats':
distance = int(data) if data else 20 distance = int(data) if data else 20
p = utils.pint(self.g.pos) p = utils.pint(self.g.pos)
@ -598,16 +619,19 @@ class Game:
result = self.g.world.find_sand_slice(utils.pint(self.g.pos), 50) result = self.g.world.find_sand_slice(utils.pint(self.g.pos), 50)
reply = str(result) reply = str(result)
## "zzz" or !zzz - bot does /afk to let others sleep
if command == 'zzz': if command == 'zzz':
if not self.g.afk and self.g.dimension == 'overworld': if not self.g.afk and self.g.dimension == 'overworld':
reply = '/afk' reply = '/afk'
self.g.afk_timeout = 5.0 self.g.afk_timeout = 5.0
## !tree - replies with the closest tree
if command == 'tree': if command == 'tree':
pos = utils.pint(self.g.pos) pos = utils.pint(self.g.pos)
tree = next(self.g.world.find_trees(pos, 50)) tree = next(self.g.world.find_trees(pos, 50))
reply = str(tree)[1:-1] reply = str(tree)[1:-1]
## !block x y z - replies what block is at (x, y, z)
if command == 'block': if command == 'block':
try: try:
data = data.replace('(', ' ').replace(')', ' ').replace(',', ' ') data = data.replace('(', ' ').replace(')', ' ').replace(',', ' ')
@ -627,15 +651,22 @@ class Game:
################# Specific commands ########################## ################# Specific commands ##########################
## ### Bot-specific Commands
## These will only run for the bot they are addressed to
if for_me: if for_me:
pass pass
## 1respawn - respawns the bot if it's dead
if command == 'respawn': if command == 'respawn':
packet = serverbound.play.ClientStatusPacket() packet = serverbound.play.ClientStatusPacket()
packet.action_id = serverbound.play.ClientStatusPacket.RESPAWN packet.action_id = serverbound.play.ClientStatusPacket.RESPAWN
self.g.connection.write_packet(packet) self.g.connection.write_packet(packet)
reply = 'ok' reply = 'ok'
## 1gather wood - gathers wood from the world
## 1gather sand - gathers sand from the world
if command == 'gather' and data: if command == 'gather' and data:
if data == 'wood': if data == 'wood':
self.g.job.state = self.g.job.gather_wood self.g.job.state = self.g.job.gather_wood
@ -652,6 +683,10 @@ class Game:
else: else:
reply += ', I need a bed' reply += ', I need a bed'
## 1farm wood - farms wood from a certain area
## 1farm sand - farms sand from a certain area
## 1farm wart - farms netherwart from a certain area
## 1farm crop - farms mature crops from a certain area
if command == 'farm' and data: if command == 'farm' and data:
if data == 'wood': if data == 'wood':
self.g.job.state = self.g.job.farm_wood self.g.job.state = self.g.job.farm_wood
@ -673,22 +708,27 @@ class Game:
else: else:
reply += ', I need a bed' reply += ', I need a bed'
## 1loiter - stands still but eats, sleeps, and flees
if command == 'loiter': if command == 'loiter':
self.g.job.state = self.g.job.loiter self.g.job.state = self.g.job.loiter
reply = 'ok' reply = 'ok'
## 1trade - sells items to villagers to get emeralds
if command == 'trade': if command == 'trade':
self.g.job.state = self.g.job.trade self.g.job.state = self.g.job.trade
reply = 'ok' reply = 'ok'
## 1stop - stops the current job and resets bot
if command == 'stop': if command == 'stop':
self.close_window() self.close_window()
bot.init(self.g) bot.init(self.g)
reply = 'ok' reply = 'ok'
## 1drop - drops the current stack its holding
if command == 'drop': if command == 'drop':
self.drop_stack() self.drop_stack()
## 1select [id] - moves item with id into main hand
if command == 'select' and data: if command == 'select' and data:
item = int(data) item = int(data)
if self.select_item([item]): if self.select_item([item]):
@ -696,6 +736,7 @@ class Game:
else: else:
reply = 'not found' reply = 'not found'
## 1dump [id] - drops all items matching id
if command == 'dump' and data: if command == 'dump' and data:
item = int(data) item = int(data)
if self.count_items([item]): if self.count_items([item]):
@ -704,6 +745,7 @@ class Game:
else: else:
reply = 'not found' reply = 'not found'
## 1drain - drops all items in inventory
if command == 'drain': if command == 'drain':
self.g.draining = True self.g.draining = True
reply = 'ok' reply = 'ok'
@ -720,6 +762,8 @@ class Game:
self.g.job.cache_items_states.silent = True self.g.job.cache_items_states.silent = True
reply = 'ok' reply = 'ok'
## 1fill [x] [y] [z] [x] [y] [z] - fills the cuboid with the block at the first coordinate
if command == 'fill': if command == 'fill':
try: try:
data = data.replace('(', ' ').replace(')', ' ').replace(',', ' ') data = data.replace('(', ' ').replace(')', ' ').replace(',', ' ')
@ -746,6 +790,7 @@ class Game:
self.g.job.state = self.g.job.fill_blocks self.g.job.state = self.g.job.fill_blocks
reply = 'filling ' + str(utils.pvolume(coord1, coord2)) + ' with ' + blocks.BLOCKS[block] reply = 'filling ' + str(utils.pvolume(coord1, coord2)) + ' with ' + blocks.BLOCKS[block]
## 1here - bot comes to your location
if command == 'here': if command == 'here':
try: try:
sender_uuid = self.g.player_names[sender] sender_uuid = self.g.player_names[sender]
@ -780,6 +825,7 @@ class Game:
else: else:
reply = 'no path' reply = 'no path'
## 1goto [x] [y] [z] - sends the bot to coordinate (x, y, z)
if command == 'goto': if command == 'goto':
try: try:
data = data.replace('(', ' ').replace(')', ' ').replace(',', ' ') data = data.replace('(', ' ').replace(')', ' ').replace(',', ' ')
@ -814,6 +860,7 @@ class Game:
if command == 'open': if command == 'open':
self.open_container(blocks.TEST_BLOCK) self.open_container(blocks.TEST_BLOCK)
## 1close - closes the current Minecraft window
if command == 'close': if command == 'close':
if self.g.window: if self.g.window:
self.close_window() self.close_window()
@ -821,6 +868,7 @@ class Game:
else: else:
reply = 'nothing open' reply = 'nothing open'
## 1click [slot] [button] [mode] - clicks the current window
if command == 'click' and data: if command == 'click' and data:
if self.g.window: if self.g.window:
slot, button, mode = [int(x) for x in data.split(' ')] slot, button, mode = [int(x) for x in data.split(' ')]
@ -833,9 +881,11 @@ class Game:
else: else:
reply = 'nothing open' reply = 'nothing open'
## 1use - use the item it's currently holding
if command == 'use': if command == 'use':
self.use_item(0) self.use_item(0)
## 1interact [entity id] - interacts with that entity
if command == 'interact' and data: if command == 'interact' and data:
self.interact(int(data)) self.interact(int(data))
@ -845,12 +895,18 @@ class Game:
print(r) print(r)
################# Authorized commands ########################## ################# Authorized commands ##########################
## ### Authorized Commands
## These dangerous commands can only be ran by the bot owner
if authed: if authed:
## 1print [expression] - replies with Python eval(expression)
if command == 'print': if command == 'print':
data = data.replace('`', '.') data = data.replace('`', '.')
reply = str(eval(data)) reply = str(eval(data))
## 1exit - exits the program
if command == 'exit': if command == 'exit':
import os import os
os._exit(0) os._exit(0)

13
print_help.py Normal file
View File

@ -0,0 +1,13 @@
HELP_LINES = []
with open('game.py', 'r') as f:
for line in f.readlines():
if line.strip().startswith('## '):
HELP_LINES.append(line.strip()[3:])
for line in HELP_LINES:
print(line)
print()