mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
Merge pull request #11221 from AlfaRojo/fix/player-boarding-cooldown
A player boards a vehicle again right after leaving it
This commit is contained in:
13 files changed
+13
-98
No files matched your search
@@ -3038,10 +3038,6 @@ struct Game<'a> {
|
||||
/// Vehicles that gained a rider this tick whose `START_RIDING_TRIGGER` was
|
||||
/// not fired yet (`game/boarding.rs`), for a guest's turn.
|
||||
started_riding: Vec<u32>,
|
||||
/// `Entity.boardingCooldown` of the acting player, and its vehicle at the
|
||||
/// last tick (`game/boarding.rs`).
|
||||
boarding_cooldown: i32,
|
||||
riding_at_tick: Option<u32>,
|
||||
/// A rotation-only write (`/rotate`, `Entity.forceSetRotation`) to the player of this
|
||||
/// turn: `leave_guest` sends it as `ClientboundPlayerRotationPacket`, not a teleport.
|
||||
rotation_forced: bool,
|
||||
@@ -20300,8 +20296,6 @@ impl<'a> Game<'a> {
|
||||
cart_models: prepared.cart_models,
|
||||
riding: None,
|
||||
started_riding: Vec::new(),
|
||||
boarding_cooldown: 0,
|
||||
riding_at_tick: None,
|
||||
rotation_forced: false,
|
||||
posed_rider: None,
|
||||
pending_vehicle: None,
|
||||
|
||||
@@ -1,23 +1,9 @@
|
||||
//! The player's `Entity.boardingCooldown`: 60 ticks after leaving a vehicle in
|
||||
//! which a non-forced `startRiding` (`Entity.canRide`) is refused.
|
||||
//! Mobs keep theirs in `extra.boarding_cooldown`; a server's guests keep theirs
|
||||
//! in `Guest::boarding_cooldown`, swapped in for their turn like `riding`.
|
||||
use super::{Game, boat_passengers::BOARDING_COOLDOWN};
|
||||
|
||||
/// `Entity.baseTick`: the cooldown counts down while positive.
|
||||
pub(super) fn tick_down(cooldown: i32) -> i32 {
|
||||
(cooldown - 1).max(0)
|
||||
}
|
||||
|
||||
/// `Entity.removePassenger`: the passenger that left sets its cooldown to 60.
|
||||
/// `was` and `now` are its vehicle before and after.
|
||||
pub(super) fn after_leaving(cooldown: i32, was: Option<u32>, now: Option<u32>) -> i32 {
|
||||
if was.is_some() && now.is_none() {
|
||||
BOARDING_COOLDOWN
|
||||
} else {
|
||||
cooldown
|
||||
}
|
||||
}
|
||||
//! A player's `Entity.boardingCooldown` is always 0: `Player.removeVehicle`
|
||||
//! zeroes the 60 ticks `Entity.removePassenger` just set (#11158), so
|
||||
//! `Entity.canRide` only asks that the player is not sneaking, which each
|
||||
//! vehicle's interaction checks. Mobs keep theirs in `extra.boarding_cooldown`
|
||||
//! (`boat_passengers::BOARDING_COOLDOWN`).
|
||||
use super::Game;
|
||||
|
||||
/// `Entity.getIndirectPassengersStream` for `vehicle`: the vehicle and every
|
||||
/// vehicle riding it, directly or through another rider. `mounts` holds
|
||||
@@ -63,48 +49,12 @@ impl Game<'_> {
|
||||
self.trigger_started_riding(vehicle);
|
||||
}
|
||||
}
|
||||
|
||||
/// `Entity.canRide` for the player acting now (the host's, or the guest
|
||||
/// whose turn it is): the cooldown has elapsed, and the player did not
|
||||
/// leave a vehicle since the tick began (the tick that starts the
|
||||
/// cooldown has not run yet).
|
||||
pub(super) fn may_board(&self) -> bool {
|
||||
self.boarding_cooldown <= 0 && !(self.riding_at_tick.is_some() && self.riding.is_none())
|
||||
}
|
||||
/// The host's own cooldown, once per tick.
|
||||
pub(super) fn tick_boarding(&mut self) {
|
||||
self.boarding_cooldown = tick_down(self.boarding_cooldown);
|
||||
self.boarding_cooldown =
|
||||
after_leaving(self.boarding_cooldown, self.riding_at_tick, self.riding);
|
||||
self.riding_at_tick = self.riding;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn leaving_sets_sixty_and_boarding_waits_it_out() {
|
||||
let mut cd = after_leaving(0, Some(7), None);
|
||||
assert_eq!(cd, 60);
|
||||
for _ in 0..59 {
|
||||
cd = tick_down(cd);
|
||||
assert!(cd > 0, "still refused");
|
||||
}
|
||||
cd = tick_down(cd);
|
||||
assert_eq!(cd, 0, "allowed on the sixtieth tick");
|
||||
}
|
||||
#[test]
|
||||
fn staying_or_boarding_does_not_set_it() {
|
||||
assert_eq!(after_leaving(0, Some(7), Some(7)), 0);
|
||||
assert_eq!(after_leaving(0, None, Some(7)), 0);
|
||||
assert_eq!(after_leaving(0, None, None), 0);
|
||||
}
|
||||
#[test]
|
||||
fn never_negative() {
|
||||
assert_eq!(tick_down(0), 0);
|
||||
}
|
||||
#[test]
|
||||
fn started_riding_reaches_every_rider_of_the_vehicle() {
|
||||
// Entity.startRiding: START_RIDING_TRIGGER for every ServerPlayer in
|
||||
// entityToRide.getIndirectPassengersStream(). A mob between two
|
||||
|
||||
@@ -1376,7 +1376,6 @@ impl Game<'_> {
|
||||
if sneaking
|
||||
|| self.boats[i].out_of_control >= 60.0
|
||||
|| self.riding.is_some()
|
||||
|| !self.may_board()
|
||||
|| self.ridden_by_guest(self.boats[i].id)
|
||||
|| !self.boat_has_room(i)
|
||||
{
|
||||
|
||||
@@ -1316,7 +1316,6 @@ impl Game<'_> {
|
||||
}
|
||||
}
|
||||
laps.lap("creature_retain");
|
||||
self.tick_boarding();
|
||||
self.sync_riders();
|
||||
self.tick_skeleton_traps();
|
||||
self.tick_apparition();
|
||||
|
||||
@@ -339,7 +339,7 @@ impl Game<'_> {
|
||||
}
|
||||
// `Entity.startRiding`: a passenger first gets off what it rides
|
||||
// (`stopRiding`), so a seated player moves to this cushion.
|
||||
if !self.may_board() || !self.native_may_board(id) {
|
||||
if !self.native_may_board(id) {
|
||||
return true;
|
||||
}
|
||||
self.stop_riding();
|
||||
|
||||
@@ -91,7 +91,7 @@ impl Game<'_> {
|
||||
if harnessed && !sneaking {
|
||||
// doPlayerRide.
|
||||
let id = self.mobs[index].id;
|
||||
if !self.may_board() || !self.native_may_board(id) {
|
||||
if !self.native_may_board(id) {
|
||||
return true;
|
||||
}
|
||||
self.break_leash(id, true, false);
|
||||
|
||||
@@ -197,7 +197,6 @@ pub(super) struct GuestSwap {
|
||||
left: bool,
|
||||
right: bool,
|
||||
riding: Option<u32>,
|
||||
host_boarding: (i32, Option<u32>),
|
||||
host_station: Option<super::stations::Station>,
|
||||
sleeping: Option<[i32; 3]>,
|
||||
sleep_timer: u32,
|
||||
@@ -572,11 +571,6 @@ impl Game<'_> {
|
||||
self.right = play.using.is_some() || self.using.is_some();
|
||||
// The guest's vehicle (Entity.vehicle) for its turn.
|
||||
let riding = std::mem::replace(&mut self.riding, g.vehicle);
|
||||
// The guest's boarding cooldown for its turn; `guest_server_tick`
|
||||
// counts it down once per tick (Entity.baseTick), not per turn.
|
||||
let host_boarding = (self.boarding_cooldown, self.riding_at_tick);
|
||||
self.boarding_cooldown = g.boarding_cooldown;
|
||||
self.riding_at_tick = g.vehicle;
|
||||
// `Entity.isPassenger()` for that turn, from the same vehicle: the
|
||||
// guest's body keeps no swim (`Entity.updateSwimming` needs it false).
|
||||
// Taken from `g.vehicle` each turn, so boarding and getting out land.
|
||||
@@ -692,7 +686,6 @@ impl Game<'_> {
|
||||
left,
|
||||
right,
|
||||
riding,
|
||||
host_boarding,
|
||||
host_station,
|
||||
sleeping,
|
||||
sleep_timer,
|
||||
@@ -794,7 +787,6 @@ impl Game<'_> {
|
||||
left,
|
||||
right,
|
||||
riding,
|
||||
host_boarding,
|
||||
host_station,
|
||||
sleeping,
|
||||
sleep_timer,
|
||||
@@ -975,11 +967,6 @@ impl Game<'_> {
|
||||
self.guest_attachments.entry(g.uuid).or_default(),
|
||||
);
|
||||
let left_vehicle = g.vehicle.filter(|_| guest_vehicle.is_none());
|
||||
// Entity.removePassenger: 60 ticks before it may board again.
|
||||
let guest_boarding =
|
||||
super::boarding::after_leaving(self.boarding_cooldown, g.vehicle, guest_vehicle);
|
||||
(self.boarding_cooldown, self.riding_at_tick) = host_boarding;
|
||||
g.boarding_cooldown = guest_boarding;
|
||||
if guest_vehicle.is_none() {
|
||||
g.vehicle_good = None;
|
||||
}
|
||||
@@ -4683,10 +4670,6 @@ impl Game<'_> {
|
||||
/// regeneration and the food tick (ServerPlayer.doTick). Their hurt
|
||||
/// sounds are heard at the guest.
|
||||
fn guest_server_tick(&mut self, host: &mut LanHost, conn: u32) {
|
||||
// Entity.baseTick: the boarding cooldown counts down once a tick.
|
||||
if let Some(g) = host.hub.guest_mut(conn) {
|
||||
g.boarding_cooldown = super::boarding::tick_down(g.boarding_cooldown);
|
||||
}
|
||||
self.guest_replay(host, conn);
|
||||
self.guest_vehicle_tick(host, conn);
|
||||
// The last move's fall stands in for the server's delta movement.
|
||||
|
||||
@@ -234,8 +234,6 @@ impl Game<'_> {
|
||||
if dead || (boat.is_none() && !cart && !mount && !cushion) {
|
||||
let g = &mut host.hub.guests[gi];
|
||||
(g.vehicle, g.vehicle_good) = (None, None);
|
||||
// Entity.removePassenger: the rider waits 60 ticks to board again.
|
||||
g.boarding_cooldown = super::boat_passengers::BOARDING_COOLDOWN;
|
||||
return;
|
||||
}
|
||||
let mut ejected = false;
|
||||
|
||||
@@ -134,7 +134,7 @@ impl Game<'_> {
|
||||
}
|
||||
// doPlayerRide; mounting drops a lead.
|
||||
let id = self.mobs[index].id;
|
||||
if !self.may_board() || !self.native_may_board(id) {
|
||||
if !self.native_may_board(id) {
|
||||
return true;
|
||||
}
|
||||
self.break_leash(id, true, false);
|
||||
|
||||
@@ -2166,12 +2166,7 @@ impl Game<'_> {
|
||||
let id = self.carts[i].id;
|
||||
// isVehicle: a mob already sits in it.
|
||||
let has_mob = self.mobs.iter().any(|m| m.extra.mount == Some(id));
|
||||
if sneaking
|
||||
|| self.riding.is_some()
|
||||
|| !self.may_board()
|
||||
|| self.ridden_by_guest(id)
|
||||
|| has_mob
|
||||
{
|
||||
if sneaking || self.riding.is_some() || self.ridden_by_guest(id) || has_mob {
|
||||
return false;
|
||||
}
|
||||
if !self.native_may_board(id) {
|
||||
|
||||
@@ -203,7 +203,7 @@ impl Game<'_> {
|
||||
return false;
|
||||
}
|
||||
let id = m.id;
|
||||
if !self.may_board() || !self.native_may_board(id) {
|
||||
if !self.native_may_board(id) {
|
||||
return true;
|
||||
}
|
||||
self.start_riding(id);
|
||||
@@ -370,7 +370,7 @@ impl Game<'_> {
|
||||
}
|
||||
// doPlayerRide
|
||||
let id = self.mobs[index].id;
|
||||
if !self.may_board() || !self.native_may_board(id) {
|
||||
if !self.native_may_board(id) {
|
||||
return true;
|
||||
}
|
||||
let m = &mut self.mobs[index];
|
||||
|
||||
@@ -129,7 +129,7 @@ impl Game<'_> {
|
||||
if tame && !food {
|
||||
// doPlayerRide.
|
||||
let id = self.mobs[index].id;
|
||||
if !self.may_board() || !self.native_may_board(id) {
|
||||
if !self.native_may_board(id) {
|
||||
return true;
|
||||
}
|
||||
self.break_leash(id, true, false);
|
||||
|
||||
@@ -133,8 +133,6 @@ pub struct Guest {
|
||||
pub input: u8,
|
||||
/// The boat or minecart the player rides (`Entity.getVehicle`).
|
||||
pub vehicle: Option<u32>,
|
||||
/// `Entity.boardingCooldown`: ticks before it may board a vehicle again.
|
||||
pub boarding_cooldown: i32,
|
||||
/// When the player last got into its vehicle, from `Hub.seat_order`:
|
||||
/// `Entity.addPassenger` seats a rider behind the players already in the
|
||||
/// vehicle, so the smallest order on a boat is its controlling rider
|
||||
@@ -447,7 +445,6 @@ impl Guest {
|
||||
sneaking: false,
|
||||
input: 0,
|
||||
vehicle: None,
|
||||
boarding_cooldown: 0,
|
||||
vehicle_order: 0,
|
||||
vehicle_good: None,
|
||||
sprinting: false,
|
||||
|
||||
Reference in new issue
Block a user