minecraft-bot/game.py

165 lines
5.0 KiB
Python

import re
import time
import importlib
from panda3d.core import LPoint3f
from minecraft.networking.packets import Packet, clientbound, serverbound
from protocol.packets import TimeUpdatePacket, SetSlotPacket, PlayerDiggingPacket, BlockBreakAnimationPacket, AcknowledgePlayerDiggingPacket
import utils
importlib.reload(utils)
import path
importlib.reload(path)
class Game:
def __init__(self, global_state):
self.g = global_state
self.l = self.g.local_state
register = self.g.connection.register_packet_listener
register(self.handle_block_change, clientbound.play.BlockChangePacket)
register(self.handle_join_game, clientbound.play.JoinGamePacket)
register(self.handle_position_and_look, clientbound.play.PlayerPositionAndLookPacket)
register(self.handle_time_update, TimeUpdatePacket)
register(self.handle_set_slot, SetSlotPacket)
register(self.handle_break_animation, BlockBreakAnimationPacket)
register(self.handle_break_ack, AcknowledgePlayerDiggingPacket)
self.g.chat.set_handler(self.handle_chat)
def handle_join_game(self, packet):
print('Connected.')
print(packet)
self.g.info = packet
self.g.eid = packet.entity_id
def handle_block_change(self, packet):
l = self.g.local_state
if packet.block_state_id == 3887:
try:
l.goal = LPoint3f(x=packet.location[0], y=packet.location[1], z=packet.location[2])
print('new waypoint:', l.goal)
start = time.time()
solution = path.Pathfinder(self.g.chunks).astar(utils.pint(self.g.pos), utils.pint(l.goal))
if solution:
solution = list(solution)
l.path = solution
#l.jobstate.state = l.jobstate.stop
print(len(solution))
print(solution)
print(round(time.time() - start, 3), 'seconds')
else:
print('No path found')
#say(connection, 'No path found')
#l.y_v = 10.0
#l.y_a = -36.0
except BaseException as e:
import traceback
print(traceback.format_exc())
def handle_position_and_look(self, packet):
print('pos and look:')
print(packet)
p = LPoint3f(x=packet.x, y=packet.y, z=packet.z)
self.g.pos = p
def handle_chat(self, message):
source, text = message
reply = None
match = re.match(r'<(\w+)> (.*)', text)
if match:
sender, text = match.groups()
else:
return
if text.startswith('! '):
text = text[2:]
elif text.startswith('!'):
text = text[1:]
else:
return
if ' ' in text:
command = text.split(' ', 1)[0]
data = text.split(' ', 1)[1]
else:
command = text
if command == 'ping':
reply = 'pong'
if command == 'echo' and data:
reply = data
if command == 'respawn':
packet = serverbound.play.ClientStatusPacket()
packet.action_id = serverbound.play.ClientStatusPacket.RESPAWN
self.g.connection.write_packet(packet)
reply = 'ok'
if command == 'pos':
reply = str(utils.pint(self.g.pos))[1:-1]
if command == 'afk':
reply = '/afk'
if command == 'error':
reply = 'ok'
raise
if command == 'break':
self.break_block((616, 78, 496))
reply = 'ok'
if reply:
print(reply)
self.g.chat.send(reply)
def handle_time_update(self, packet):
l = self.g.local_state
l.time = packet.time_of_day % 24000
def handle_set_slot(self, packet):
print(packet)
if packet.window_id == 0:
self.g.inv[packet.slot] = packet.slot_data
def handle_break_animation(self, packet):
print(packet)
if self.l.breaking and packet.entity_id == self.g.eid:
if packet.destroy_stage >= 10:
packet = PlayerDiggingPacket()
packet.status = 2
packet.location = self.l.breaking
packet.face = 1
self.g.connection.write_packet(packet)
self.l.breaking = None
def handle_break_ack(self, packet):
print(packet)
def break_block(self, location):
if self.g.chunks.get_block_at(*location) != 0:
packet = PlayerDiggingPacket()
packet.status = 0
packet.location = location
packet.face = 1
self.g.connection.write_packet(packet)
self.l.breaking = location
def animate(self):
packet = serverbound.play.AnimationPacket()
packet.hand = packet.HAND_MAIN
self.g.connection.write_packet(packet)
def tick(self):
if self.l.breaking:
self.animate()