Implement 26.3 food consumption
This commit is contained in:
@@ -404,6 +404,11 @@ class Commands:
|
||||
self.g.job.state = self.g.job.sleep
|
||||
reply = 'ok'
|
||||
|
||||
## 1eat - eat one food item when hunger/health requires it
|
||||
if command == 'eat':
|
||||
self.g.job.state = self.g.job.eat
|
||||
reply = 'ok'
|
||||
|
||||
## 1gather wood - gathers wood from the world
|
||||
## 1gather sand - gathers sand from the world
|
||||
if command == 'gather' and data:
|
||||
|
||||
+9
-1
@@ -23,7 +23,9 @@ from mosfet.protocol.packets import (
|
||||
)
|
||||
|
||||
from mosfet.protocol.types import Slot
|
||||
from mosfet.protocol.modern import PlayerCommandPacket, UpdateTimePacket
|
||||
from mosfet.protocol.modern import (
|
||||
PlayerCommandPacket, UpdateTimePacket, UseItemPacket,
|
||||
)
|
||||
|
||||
from mosfet import utils
|
||||
from mosfet import path
|
||||
@@ -713,6 +715,12 @@ class Game(LegacyGame):
|
||||
self._send_action(PlayerCommandPacket(
|
||||
entity_id=self.g.eid, action_id=0, jump_boost=0))
|
||||
|
||||
def use_item(self, hand=0):
|
||||
self._send_action(UseItemPacket(
|
||||
hand=hand, sequence=self._next_sequence(),
|
||||
yaw=float(self.g.get('yaw', 0.0)),
|
||||
pitch=float(self.g.get('pitch', 0.0))))
|
||||
|
||||
def start_drain(self):
|
||||
slots = [slot for slot, item in sorted(self.g.inv.items())
|
||||
if 9 <= slot <= 45 and getattr(item, 'present', False)]
|
||||
|
||||
+6
-1
@@ -272,6 +272,7 @@ class JobStates(LegacyJobStates):
|
||||
self.cache_items_states = cache_items.CacheItemsStates(global_state)
|
||||
self.sleep_with_bed_states = sleep_with_bed.SleepWithBedStates(
|
||||
global_state)
|
||||
self.eat_food_states = eat_food.EatFoodStates(global_state)
|
||||
self.state = self.idle
|
||||
|
||||
def farm_crop(self):
|
||||
@@ -285,7 +286,10 @@ class JobStates(LegacyJobStates):
|
||||
items.BEETROOT_SEEDS_ID,
|
||||
})
|
||||
return [self.gather_crop_states, self.sleep_with_bed_states,
|
||||
self.cache_items_states]
|
||||
self.eat_food_states, self.cache_items_states]
|
||||
|
||||
def eat(self):
|
||||
return [self.eat_food_states]
|
||||
|
||||
def sleep(self):
|
||||
self.sleep_with_bed_states.silent = False
|
||||
@@ -304,5 +308,6 @@ class JobStates(LegacyJobStates):
|
||||
self.cache_items_states.state = self.cache_items_states.idle
|
||||
self.sleep_with_bed_states.state = self.sleep_with_bed_states.idle
|
||||
self.sleep_with_bed_states.force_new_bed = False
|
||||
self.eat_food_states.state = self.eat_food_states.idle
|
||||
self.gather_crop_states.active_section_anchor = None
|
||||
self.state = self.idle
|
||||
|
||||
+63
-18
@@ -21,41 +21,86 @@ class EatFoodStates:
|
||||
return None
|
||||
|
||||
def init(self):
|
||||
if self.g.food < 12:
|
||||
food = self.g.get('food')
|
||||
health = self.g.get('health')
|
||||
if food is None:
|
||||
print('No authoritative hunger status yet; not eating')
|
||||
self.state = self.cleanup
|
||||
return
|
||||
|
||||
if food < 12:
|
||||
print('Hungry, eating')
|
||||
self.state = self.select_food
|
||||
return
|
||||
|
||||
if self.g.health < 20 and self.g.food < 18:
|
||||
elif health is not None and health < 20 and food < 18:
|
||||
print('Low health, eating')
|
||||
self.state = self.select_food
|
||||
else:
|
||||
print('Don\'t need to eat, aborting')
|
||||
self.state = self.cleanup
|
||||
return
|
||||
|
||||
print('Don\'t need to eat, aborting')
|
||||
self.state = self.cleanup
|
||||
self.food_before = food
|
||||
self.saturation_before = self.g.get('food_saturation', 0.0) or 0.0
|
||||
self.health_before = health
|
||||
self.selected_item_id = None
|
||||
self.selected_slot = None
|
||||
self.selected_count = 0
|
||||
self.state = self.select_food
|
||||
|
||||
def select_food(self):
|
||||
if self.g.game.select_item(items.FOOD_IDS):
|
||||
self.state = self.eat_food
|
||||
else:
|
||||
if not self.g.game.select_item(items.FOOD_IDS):
|
||||
print('No food, aborting')
|
||||
self.state = self.cleanup
|
||||
return
|
||||
|
||||
self.selected_item_id = self.g.holding
|
||||
self.selected_slot = (
|
||||
45 if self.g.get('holding_hand', 0) == 1 else
|
||||
36 + self.g.get('holding_slot', 0))
|
||||
self.select_deadline = time.monotonic() + 2.0
|
||||
self.state = self.wait_for_selection
|
||||
|
||||
def wait_for_selection(self):
|
||||
selected = self.g.inv.get(self.selected_slot)
|
||||
if (selected and selected.present and
|
||||
selected.item_id == self.selected_item_id):
|
||||
self.selected_count = selected.item_count
|
||||
self.state = self.eat_food
|
||||
elif time.monotonic() >= self.select_deadline:
|
||||
print('Food did not reach the selected hand; aborting')
|
||||
self.state = self.cleanup
|
||||
|
||||
def eat_food(self):
|
||||
self.g.game.use_item(0)
|
||||
|
||||
print('Eating food')
|
||||
self.wait_time = 3
|
||||
hand = self.g.get('holding_hand', 0)
|
||||
print('Eating food from {} hand'.format(
|
||||
'off' if hand else 'main'))
|
||||
self.g.game.use_item(hand)
|
||||
self.eat_deadline = time.monotonic() + 6.0
|
||||
self.state = self.wait
|
||||
|
||||
def wait(self):
|
||||
if self.wait_time > 0:
|
||||
self.wait_time -= utils.TICK
|
||||
else:
|
||||
selected = self.g.inv.get(self.selected_slot)
|
||||
consumed = (
|
||||
not selected or not selected.present or
|
||||
selected.item_id != self.selected_item_id or
|
||||
selected.item_count < self.selected_count)
|
||||
stats_improved = (
|
||||
(self.g.get('food') is not None and
|
||||
self.g.food > self.food_before) or
|
||||
(self.g.get('food_saturation') is not None and
|
||||
self.g.food_saturation > self.saturation_before) or
|
||||
(self.health_before is not None and self.g.get('health') is not None
|
||||
and self.g.health > self.health_before))
|
||||
if consumed or stats_improved:
|
||||
print('Eating confirmed by server state')
|
||||
self.state = self.cleanup
|
||||
elif time.monotonic() >= self.eat_deadline:
|
||||
print('Food use was not confirmed by server state')
|
||||
self.state = self.cleanup
|
||||
|
||||
def cleanup(self):
|
||||
self.state = self.done
|
||||
if (self.g.get('job') and
|
||||
getattr(self.g.job.state, '__name__', None) == 'eat'):
|
||||
self.g.job.state = self.g.job.idle
|
||||
|
||||
def done(self):
|
||||
# never gets ran, placeholder
|
||||
|
||||
@@ -38,6 +38,16 @@ class PlayerCommandPacket(Packet):
|
||||
]
|
||||
|
||||
|
||||
class UseItemPacket(Packet):
|
||||
"""Use the selected hand, including the 26.3 interaction sequence."""
|
||||
id = 0x43
|
||||
packet_name = 'use item'
|
||||
definition = [
|
||||
{'hand': VarInt}, {'sequence': VarInt},
|
||||
{'yaw': Float}, {'pitch': Float},
|
||||
]
|
||||
|
||||
|
||||
def parse_incoming_private_message(message):
|
||||
"""Return (sender_name, body) for common Minecraft incoming-DM forms."""
|
||||
patterns = (
|
||||
|
||||
Reference in New Issue
Block a user