Implement 26.3 food consumption

This commit is contained in:
Tanner
2026-11-04 20:06:02 +00:00
parent 1ecec547ae
commit 7d4f045100
8 changed files with 200 additions and 25 deletions
+99
View File
@@ -0,0 +1,99 @@
import unittest
from munch import Munch
from minecraft.networking.modern import ClientTickEnd
from minecraft.networking.packets import PacketBuffer
from mosfet.game import Game
from mosfet.info import items
from mosfet.jobs.eat_food import EatFoodStates
from mosfet.protocol.modern import UseItemPacket
from mosfet.protocol.types import Slot
class FakeConnection:
def __init__(self):
self.packets = []
def write_packet(self, packet, force=False):
self.packets.append((packet, force))
class FakeGame:
def __init__(self, state):
self.state = state
self.used_hands = []
def select_item(self, item_ids):
for slot, item in self.state.g.inv.items():
if item.present and item.item_id in item_ids:
self.state.g.holding = item.item_id
self.state.g.holding_hand = 0
self.state.g.holding_slot = slot - 36
return True
return False
def use_item(self, hand=0):
self.used_hands.append(hand)
class TestEatFood(unittest.TestCase):
def test_use_item_packet_encodes_hand_sequence_and_rotation(self):
packet = UseItemPacket(hand=1, sequence=300, yaw=90.0, pitch=-30.0)
buffer = PacketBuffer()
packet.write_fields(buffer)
self.assertEqual(packet.id, 0x43)
self.assertEqual(buffer.get_writable(), bytes.fromhex(
'01ac0242b40000c1f00000'))
def test_game_use_item_sends_packet_and_tick_end(self):
connection = FakeConnection()
game = Game.__new__(Game)
game.g = Munch(connection=connection, yaw=45.0, pitch=-5.0)
game.sequence = 0
game.use_item(1)
packet, forced = connection.packets[0]
self.assertIsInstance(packet, UseItemPacket)
self.assertEqual((packet.hand, packet.sequence,
packet.yaw, packet.pitch), (1, 1, 45.0, -5.0))
self.assertTrue(forced)
self.assertIsInstance(connection.packets[1][0], ClientTickEnd)
def test_eat_uses_authoritative_hunger_and_waits_for_confirmation(self):
food_id = next(iter(items.FOOD_IDS))
state = EatFoodStates(Munch(
food=8, health=20.0, food_saturation=0.0,
inv={36: Slot(True, food_id, 3)}, holding_hand=0,
holding_slot=0, job=None))
fake_game = FakeGame(state)
state.g.game = fake_game
state.init()
self.assertEqual(state.state, state.select_food)
state.select_food()
self.assertEqual(state.state, state.wait_for_selection)
state.wait_for_selection()
self.assertEqual(state.state, state.eat_food)
state.eat_food()
self.assertEqual(fake_game.used_hands, [0])
self.assertEqual(state.state, state.wait)
# Don't declare success until the server sends a hunger/saturation
# update or confirms that it consumed the selected stack.
state.wait()
self.assertEqual(state.state, state.wait)
state.g.food = 16
state.g.food_saturation = 4.0
state.wait()
self.assertEqual(state.state, state.cleanup)
def test_no_hunger_packet_does_not_eat(self):
state = EatFoodStates(Munch(food=None, health=None))
state.init()
self.assertEqual(state.state, state.cleanup)
if __name__ == '__main__':
unittest.main()