Compare commits

...

3 Commits

7 changed files with 156 additions and 5 deletions

1
bot.py
View File

@ -201,6 +201,7 @@ def init(global_state):
g.break_time = 0 g.break_time = 0
g.dumping = None g.dumping = None
g.draining = False
g.item_lock = False g.item_lock = False
g.command_lock = False g.command_lock = False

51
game.py
View File

@ -20,7 +20,7 @@ from protocol.packets import (
ClickWindowPacket, CloseWindowPacket, ServerWindowConfirmationPacket, ClickWindowPacket, CloseWindowPacket, ServerWindowConfirmationPacket,
ClientWindowConfirmationPacket, EntityMetadataPacket, ClientWindowConfirmationPacket, EntityMetadataPacket,
SpawnLivingEntityPacket, EntityPositionRotationPacket, DestroyEntitiesPacket, SpawnLivingEntityPacket, EntityPositionRotationPacket, DestroyEntitiesPacket,
EntityActionPacket, EntityTeleport, EntityActionPacket, EntityTeleport, InteractEntityPacket, TradeListPacket
) )
from protocol.types import Slot from protocol.types import Slot
@ -338,6 +338,7 @@ class Game:
register(self.handle_entity_teleport, EntityTeleport) register(self.handle_entity_teleport, EntityTeleport)
register(self.handle_update_health, clientbound.play.UpdateHealthPacket) register(self.handle_update_health, clientbound.play.UpdateHealthPacket)
#register(self.handle_entity_velocity, clientbound.play.EntityVelocityPacket) #register(self.handle_entity_velocity, clientbound.play.EntityVelocityPacket)
register(self.handle_trade_list, TradeListPacket)
#register(self.handle_packet, Packet, early=True) #register(self.handle_packet, Packet, early=True)
@ -535,6 +536,16 @@ 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'
if command == 'villagers':
all_mobs = sorted(list(self.g.mobs.items()), key=lambda x: x[1].type)
count = 0
for k, v in all_mobs:
type_name = mobs.MOB_NAMES[v.type]
if type_name != 'villager' : continue
count += 1
print(str(k) + ':', v, type_name)
reply = str(count) + ' villagers'
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)
@ -653,6 +664,10 @@ class Game:
else: else:
reply = 'not found' reply = 'not found'
if command == 'drain':
self.g.draining = True
reply = 'ok'
if command == 'gapple': if command == 'gapple':
self.g.job.state = self.g.job.find_gapple self.g.job.state = self.g.job.find_gapple
if data: if data:
@ -753,6 +768,13 @@ class Game:
if command == 'use': if command == 'use':
self.use_item(0) self.use_item(0)
if command == 'interact' and data:
self.interact(int(data))
if command == 'test':
reply = 'ok'
self.select_next_item()
################# Authorized commands ########################## ################# Authorized commands ##########################
if authed: if authed:
@ -897,6 +919,15 @@ class Game:
else: else:
return False return False
def select_next_item(self):
# select the next item slot that has an item
for slot, item in self.g.inv.items():
if item.present:
self.g.game.choose_slot(slot)
self.g.holding = item.item_id
return True
else: # for
return False
def drop_stack(self): def drop_stack(self):
packet = PlayerDiggingPacket() packet = PlayerDiggingPacket()
@ -1098,6 +1129,17 @@ class Game:
packet.hand = hand packet.hand = hand
self.g.connection.write_packet(packet) self.g.connection.write_packet(packet)
def interact(self, eid):
packet = InteractEntityPacket()
packet.entity_id = eid
packet.type = 0
packet.hand = 0
packet.sneaking = False
self.g.connection.write_packet(packet)
def handle_trade_list(self, packet):
print(packet)
def tick(self): def tick(self):
if self.g.breaking: if self.g.breaking:
self.animate() self.animate()
@ -1112,5 +1154,12 @@ class Game:
else: else:
self.g.dumping = None self.g.dumping = None
if self.g.draining and not self.g.item_lock:
if self.select_next_item():
self.drop_stack()
self.g.item_lock = True
else:
self.g.draining = False
if not self.g.path: if not self.g.path:
self.g.correction_count = 0 self.g.correction_count = 0

View File

@ -58,6 +58,15 @@ FOOD = [
'cooked_salmon', 'cooked_salmon',
] ]
LOGS = [
'oak_log',
'spruce_log',
'birch_log',
'jungle_log',
'acacia_log',
'dark_oak_log',
]
BED_IDS = set() BED_IDS = set()
for item_name in BEDS: for item_name in BEDS:
BED_IDS.add(ITEMS['minecraft:'+item_name]['protocol_id']) BED_IDS.add(ITEMS['minecraft:'+item_name]['protocol_id'])
@ -78,6 +87,10 @@ SAPLING_IDS = set()
for item_name in SAPLINGS: for item_name in SAPLINGS:
SAPLING_IDS.add(ITEMS['minecraft:'+item_name]['protocol_id']) SAPLING_IDS.add(ITEMS['minecraft:'+item_name]['protocol_id'])
LOG_IDS = set()
for item_name in LOGS:
LOG_IDS.add(ITEMS['minecraft:'+item_name]['protocol_id'])
ITEM_NAMES = {} ITEM_NAMES = {}
for item_name, item in ITEMS.items(): for item_name, item in ITEMS.items():
ITEM_NAMES[ITEMS[item_name]['protocol_id']] = item_name.replace('minecraft:', '') ITEM_NAMES[ITEMS[item_name]['protocol_id']] = item_name.replace('minecraft:', '')

View File

@ -5,8 +5,6 @@ import random
from itertools import count from itertools import count
from math import hypot from math import hypot
from panda3d.core import LPoint3f
from minecraft.networking.types import BlockFace from minecraft.networking.types import BlockFace
from protocol.managers import ChunkNotLoadedException from protocol.managers import ChunkNotLoadedException
@ -1301,9 +1299,14 @@ class ClearLeavesStates:
self.state = self.cleanup self.state = self.cleanup
return return
self.state = self.find_leaves self.state = self.select_log
print('Clearing leaves...') print('Clearing leaves...')
def select_log(self):
# select a log to avoid using tools
self.g.game.select_item(items.LOG_IDS)
self.state = self.find_leaves
def find_leaves(self): def find_leaves(self):
w = self.g.world w = self.g.world
p = utils.pint(self.g.pos) p = utils.pint(self.g.pos)

View File

@ -18,6 +18,7 @@ def get_packets(old_get_packets):
mc_packets.add(packets.EntityPositionRotationPacket) mc_packets.add(packets.EntityPositionRotationPacket)
mc_packets.add(packets.DestroyEntitiesPacket) mc_packets.add(packets.DestroyEntitiesPacket)
mc_packets.add(packets.EntityTeleport) mc_packets.add(packets.EntityTeleport)
mc_packets.add(packets.TradeListPacket)
return mc_packets return mc_packets

View File

@ -8,7 +8,7 @@ from minecraft.networking.types import (
Float, Direction, PositionAndLook Float, Direction, PositionAndLook
) )
from protocol.types import Nbt, Slot, Entry from protocol.types import Nbt, Slot, Entry, Trade
import blocks import blocks
@ -391,3 +391,48 @@ class EntityActionPacket(Packet):
{'action_id': VarInt}, {'action_id': VarInt},
{'jump_boost': VarInt}, {'jump_boost': VarInt},
] ]
class InteractEntityPacket(Packet):
# Sent when the client attacks or right-clicks another entity
# https://wiki.vg/Protocol#Interact_Entity
id = 0x0E
packet_name = 'interact entity'
definition = [
{'entity_id': VarInt},
{'type': VarInt},
#{'target_x': Float},
#{'target_y': Float},
#{'target_z': Float},
{'hand': VarInt},
{'sneaking': Boolean},
]
class TradeListPacket(Packet):
# The list of trades a villager NPC is offering.
# https://wiki.vg/Protocol#Trade_List
id = 0x26
packet_name = 'trade list'
fields = (
'window_id',
'size',
'trades',
'villager_level',
'experience',
'is_regular_villager',
'can_restock',
)
def read(self, file_object):
self.window_id = VarInt.read(file_object)
self.size = Byte.read(file_object)
self.trades = []
for _ in range(self.size):
trade = Trade.read(file_object)
self.trades.append(trade)
self.villager_level = VarInt.read(file_object)
self.experience = VarInt.read(file_object)
self.is_regular_villager = Boolean.read(file_object)
self.can_restock = Boolean.read(file_object)

View File

@ -172,3 +172,42 @@ class Entry(Type):
except KeyError: except KeyError:
return None return None
return Entry(index, type, value) return Entry(index, type, value)
class Trade(Type):
fields = (
'input_item_1',
'output_item',
'has_second_item',
'input_item_2',
'trade_disabled',
'num_uses',
'max_num_uses',
'xp',
'special_price',
'price_multiplier',
'demand',
)
def __str__(self):
return str(self.__dict__)
def __repr__(self):
inner_str = ', '.join('%s=%s' % (a, getattr(self, a, None)) for a in self.fields if hasattr(self, a))
return 'Trade(%s)' % inner_str
@staticmethod
def read(file_object):
trade = Trade()
trade.input_item_1 = Slot.read(file_object)
trade.output_item = Slot.read(file_object)
trade.has_second_item = Boolean.read(file_object)
if trade.has_second_item:
trade.input_item_2 = Slot.read(file_object)
trade.trade_disabled = Boolean.read(file_object)
trade.num_uses = Integer.read(file_object)
trade.max_num_uses = Integer.read(file_object)
trade.xp = Integer.read(file_object)
trade.special_price = Integer.read(file_object)
trade.price_multiplier = Float.read(file_object)
trade.demand = Integer.read(file_object)
return trade