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.dumping = None
g.draining = False
g.item_lock = False
g.command_lock = False

51
game.py
View File

@ -20,7 +20,7 @@ from protocol.packets import (
ClickWindowPacket, CloseWindowPacket, ServerWindowConfirmationPacket,
ClientWindowConfirmationPacket, EntityMetadataPacket,
SpawnLivingEntityPacket, EntityPositionRotationPacket, DestroyEntitiesPacket,
EntityActionPacket, EntityTeleport,
EntityActionPacket, EntityTeleport, InteractEntityPacket, TradeListPacket
)
from protocol.types import Slot
@ -338,6 +338,7 @@ class Game:
register(self.handle_entity_teleport, EntityTeleport)
register(self.handle_update_health, clientbound.play.UpdateHealthPacket)
#register(self.handle_entity_velocity, clientbound.play.EntityVelocityPacket)
register(self.handle_trade_list, TradeListPacket)
#register(self.handle_packet, Packet, early=True)
@ -535,6 +536,16 @@ class Game:
print(str(k) + ':', v, mobs.MOB_NAMES[v.type])
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':
distance = int(data) if data else 20
p = utils.pint(self.g.pos)
@ -653,6 +664,10 @@ class Game:
else:
reply = 'not found'
if command == 'drain':
self.g.draining = True
reply = 'ok'
if command == 'gapple':
self.g.job.state = self.g.job.find_gapple
if data:
@ -753,6 +768,13 @@ class Game:
if command == 'use':
self.use_item(0)
if command == 'interact' and data:
self.interact(int(data))
if command == 'test':
reply = 'ok'
self.select_next_item()
################# Authorized commands ##########################
if authed:
@ -897,6 +919,15 @@ class Game:
else:
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):
packet = PlayerDiggingPacket()
@ -1098,6 +1129,17 @@ class Game:
packet.hand = hand
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):
if self.g.breaking:
self.animate()
@ -1112,5 +1154,12 @@ class Game:
else:
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:
self.g.correction_count = 0

View File

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

View File

@ -5,8 +5,6 @@ import random
from itertools import count
from math import hypot
from panda3d.core import LPoint3f
from minecraft.networking.types import BlockFace
from protocol.managers import ChunkNotLoadedException
@ -1301,9 +1299,14 @@ class ClearLeavesStates:
self.state = self.cleanup
return
self.state = self.find_leaves
self.state = self.select_log
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):
w = self.g.world
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.DestroyEntitiesPacket)
mc_packets.add(packets.EntityTeleport)
mc_packets.add(packets.TradeListPacket)
return mc_packets

View File

@ -8,7 +8,7 @@ from minecraft.networking.types import (
Float, Direction, PositionAndLook
)
from protocol.types import Nbt, Slot, Entry
from protocol.types import Nbt, Slot, Entry, Trade
import blocks
@ -391,3 +391,48 @@ class EntityActionPacket(Packet):
{'action_id': 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:
return None
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