Consolidate bot runtime on Minecraft 26.3
This commit is contained in:
+117
-1
@@ -6,6 +6,10 @@ from munch import Munch
|
||||
|
||||
from minecraft.networking.packets import Packet, clientbound, serverbound
|
||||
from minecraft.networking.types import BlockFace
|
||||
from minecraft.networking.modern import (
|
||||
ClientTickEnd, ContainerClickSwapPacket, PlayerActionPacket,
|
||||
SetCarriedItemPacket, UseItemOnBlockPacket,
|
||||
)
|
||||
|
||||
from mosfet.protocol.packets import (
|
||||
SetSlotPacket, PlayerDiggingPacket,
|
||||
@@ -29,7 +33,7 @@ from mosfet.info import items
|
||||
from mosfet.info import mcdata
|
||||
from mosfet.info import mobs
|
||||
|
||||
class Game:
|
||||
class LegacyGame:
|
||||
def __init__(self, global_state):
|
||||
self.g = global_state
|
||||
|
||||
@@ -568,3 +572,115 @@ class Game:
|
||||
|
||||
if not self.g.path:
|
||||
self.g.correction_count = 0
|
||||
|
||||
|
||||
# Active game facade. The constructor registers no legacy packet listeners;
|
||||
# migrated actions use the 26.3 packet classes imported above.
|
||||
class Game(LegacyGame):
|
||||
def __init__(self, global_state):
|
||||
self.g = global_state
|
||||
self.sequence = 0
|
||||
self.break_deadline = None
|
||||
self.breaking_state = None
|
||||
|
||||
def _send_action(self, packet):
|
||||
self.g.connection.write_packet(packet, force=True)
|
||||
self.g.connection.write_packet(ClientTickEnd(), force=True)
|
||||
|
||||
def _next_sequence(self):
|
||||
self.sequence += 1
|
||||
return self.sequence
|
||||
|
||||
def break_block(self, location):
|
||||
location = tuple(int(value) for value in location)
|
||||
block_id = self.g.chunks.get_block_at(*location)
|
||||
if block_id is None or block_id == blocks.AIR:
|
||||
return False
|
||||
packet = PlayerActionPacket(
|
||||
action=0, location=location, face=1,
|
||||
sequence=self._next_sequence())
|
||||
self._send_action(packet)
|
||||
self.g.breaking = location
|
||||
self.breaking_state = block_id
|
||||
hardness_time = utils.break_time(block_id, self.g.get('holding', 0))
|
||||
self.break_deadline = time.monotonic() + max(0.05, hardness_time)
|
||||
return True
|
||||
|
||||
def tick(self):
|
||||
if not self.g.get('breaking') or self.break_deadline is None:
|
||||
return
|
||||
if time.monotonic() < self.break_deadline:
|
||||
return
|
||||
packet = PlayerActionPacket(
|
||||
action=3, location=self.g.breaking, face=1,
|
||||
sequence=self._next_sequence())
|
||||
self._send_action(packet)
|
||||
location = self.g.breaking
|
||||
if self.g.chunks.get_block_at(*location) == self.breaking_state:
|
||||
# Predict the normal client-side block removal. The server's later
|
||||
# block update is authoritative and will correct the cache if the
|
||||
# action was denied or the block changed differently.
|
||||
self.g.chunks.set_block_at(*location, blocks.AIR)
|
||||
self.g.breaking = None
|
||||
self.break_deadline = None
|
||||
self.breaking_state = None
|
||||
|
||||
def cancel_break(self):
|
||||
if not self.g.get('breaking'):
|
||||
return
|
||||
packet = PlayerActionPacket(
|
||||
action=2, location=self.g.breaking, face=1,
|
||||
sequence=self._next_sequence())
|
||||
self._send_action(packet)
|
||||
self.g.breaking = None
|
||||
self.break_deadline = None
|
||||
self.breaking_state = None
|
||||
|
||||
def select_item(self, item_ids):
|
||||
item_ids = set(item_ids)
|
||||
matches = [(slot, item) for slot, item in self.g.inv.items()
|
||||
if item.present and item.item_id in item_ids]
|
||||
if not matches:
|
||||
return False
|
||||
|
||||
# Prefer an already-hotbar stack; otherwise swap the requested stack
|
||||
# into an empty hotbar slot using the modern container SWAP input.
|
||||
slot, item = next(
|
||||
((slot, item) for slot, item in matches if 36 <= slot <= 44),
|
||||
matches[0])
|
||||
if 36 <= slot <= 44:
|
||||
hotbar_slot = slot - 36
|
||||
elif 9 <= slot <= 35:
|
||||
empty_hotbar = next(
|
||||
(candidate - 36 for candidate in range(36, 45)
|
||||
if candidate not in self.g.inv or
|
||||
not self.g.inv[candidate].present), None)
|
||||
hotbar_slot = (empty_hotbar if empty_hotbar is not None else
|
||||
self.g.get('holding_slot', 0) or 0)
|
||||
self.g.connection.write_packet(ContainerClickSwapPacket(
|
||||
container_id=0,
|
||||
state_id=self.g.inventory_state_ids.get(0, 0),
|
||||
slot=slot, button=hotbar_slot), force=True)
|
||||
else:
|
||||
return False
|
||||
|
||||
if self.g.get('holding_slot') != hotbar_slot:
|
||||
self.g.connection.write_packet(SetCarriedItemPacket(
|
||||
slot=hotbar_slot), force=True)
|
||||
self.g.holding_slot = hotbar_slot
|
||||
self.g.holding = item.item_id
|
||||
self.g.connection.write_packet(ClientTickEnd(), force=True)
|
||||
return True
|
||||
|
||||
def place_block(self, location, face):
|
||||
location = tuple(int(value) for value in location)
|
||||
packet = UseItemOnBlockPacket(
|
||||
hand=0, location=location, face=int(face),
|
||||
cursor_x=0.5, cursor_y=0.99 if int(face) == 1 else 0.5,
|
||||
cursor_z=0.5, inside_block=False, world_border_hit=False,
|
||||
sequence=self._next_sequence())
|
||||
self._send_action(packet)
|
||||
|
||||
def close_window(self):
|
||||
# Container open/close packet migration is not part of the crop path.
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user