Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/module-durable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,18 @@ jobs:
if: matrix.shard == 0
run: |
cargo test -p lyracore-gateway --bin lyracore-gateway stdb::account_sessions::tests::independent_coordinators_preserve_the_winner_after_delayed_cleanup -- --ignored --exact
cargo test -p lyracore-gateway --bin lyracore-gateway world::tests::competing_world_sessions_close_the_old_socket_without_removing_the_winner -- --ignored --exact
cargo test -p lyracore-gateway --bin lyracore-gateway world::tests::session_tests::competing_world_sessions_close_the_old_socket_without_removing_the_winner -- --ignored --exact
cargo test -p lyracore-gateway --bin lyracore-gateway stdb::subscriptions::character_gone_durable_tests::another_gateway_waits_for_the_transfer_then_cleans_the_deleted_character -- --ignored --exact
cargo test -p lyracore-gateway --bin lyracore-gateway stdb::subscriptions::roster_relay_durable_tests::a_roster_change_made_only_on_realm_core_reaches_every_world_shard_mirror -- --ignored --exact
cargo test -p lyracore-gateway --bin lyracore-gateway stdb::subscriptions::meeting_stone_durable_tests::seekers_on_two_world_shards_form_one_party_that_reaches_every_mirror -- --ignored --exact
cargo test -p lyracore-gateway --bin lyracore-gateway stdb::armor::tests::resistance_projection_adds_property_effects_only_while_the_item_is_worn_and_unbroken -- --ignored --exact
cargo test -p lyracore-gateway --test provision_cli provision_writes_the_account_to_the_world_shard_and_realm_core -- --ignored --exact
cargo test -p lyracore-gateway --test startup_relays -- --ignored --test-threads=1

- name: Run Benilla against private Module instances
if: matrix.shard == 0
run: cargo test --locked -p lyracore-gateway --bin lyracore-gateway benilla_durable_ -- --ignored --test-threads=1

# No Package registers a client command here, so the Module's fixture command carries it.
- name: Run the cross-Shard command transport tests
if: matrix.shard == 1
Expand Down
2 changes: 1 addition & 1 deletion CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,7 @@ _Avoid_: matchmaking, auto-invite
### World clock and weather

**Realm Clock**:
The wall clock the realm runs on, always UTC. There is no realm-timezone setting, so no part of the realm reads host-local time. The Gateway packs it into `SMSG_LOGIN_SETTIMESPEED` once per world entry and the client advances it alone afterwards; the Module reads the same clock to pick the weather season.
The wall clock the realm runs on, always UTC. There is no realm-timezone setting, so no part of the realm reads host-local time. The Gateway packs it into `SMSG_LOGIN_SETTIMESPEED` once per world entry and the client advances it alone afterwards. It also answers `CMSG_QUERY_TIME` with Unix seconds in `SMSG_QUERY_TIME_RESPONSE`, so the client can interpret timed quest deadlines. The Module reads the same clock to pick the weather season.
_Avoid_: server time, game time, local time

**Zone Weather**:
Expand Down
52 changes: 50 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions crates/lyracore-shared/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
/// must be combined with the water-surface test in [`is_submerged`].
pub const MOVEMENT_FLAG_SWIMMING: u32 = 0x0020_0000;

/// Build-5875 transport movement carries a full guid and relative pose.
pub const MOVEMENT_FLAG_ON_TRANSPORT: u32 = 0x0200_0000;

/// Default player collision height.
pub const UNDERWATER_HEAD_HEIGHT: f32 = 2.0;

Expand Down Expand Up @@ -89,15 +92,14 @@ pub fn fall_damage(fall_time_ms: u32, max_health: u32) -> u32 {
}

/// `fall_time` (u32 ms) out of a raw vanilla MovementInfo body: flags u32 LE, time u32, x/y/z/o
/// 16 B, then [transport guid u64 + pos 16 B if flag 0x0200], [pitch f32 if SWIMMING 0x0020_0000],
/// 16 B, then [transport guid u64 + pos 16 B if flag 0x02000000], [pitch f32 if SWIMMING 0x0020_0000],
/// then fall_time. `None` on a short body or an on-transport mover (no fall damage on transports).
/// NOTE the wire TYPE: cmangos reads fall time as u32 MILLISECONDS; gtker's MovementInfo types the
/// same 4 bytes f32 (a field-type lie, like its field-name ones) — this parser and any gtker-side
/// consumer must agree on the raw-u32 reading (`f32::to_bits` at the gtker boundary).
pub fn fall_time_from_movement_info(body: &[u8]) -> Option<u32> {
const ON_TRANSPORT: u32 = 0x0200;
let flags = u32::from_le_bytes(body.get(0..4)?.try_into().ok()?);
if flags & ON_TRANSPORT != 0 {
if flags & MOVEMENT_FLAG_ON_TRANSPORT != 0 {
return None;
}
let mut off = 4 + 4 + 16; // flags + time + x/y/z/o
Expand Down Expand Up @@ -133,7 +135,7 @@ mod tests {
swim.extend_from_slice(&2000u32.to_le_bytes());
assert_eq!(fall_time_from_movement_info(&swim), Some(2000));
// transport: no fall damage
let mut tr = 0x0200u32.to_le_bytes().to_vec();
let mut tr = 0x0200_0000u32.to_le_bytes().to_vec();
tr.extend_from_slice(&[0u8; 60]);
assert_eq!(fall_time_from_movement_info(&tr), None);
// short body: None, never a panic
Expand Down
10 changes: 9 additions & 1 deletion crates/lyracore-shared/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@ pub enum ItemRefusal {
ItemNotUsable,
/// The action is blocked for now: a live bandage cooldown, or a cast Gate.
NotRightNow,
/// The item template forbids destruction.
Indestructible,
/// An equipped bag still contains items.
BagNotEmpty,
/// The Module could not act and has no gameplay reason to name.
Internal,
}

impl ItemRefusal {
pub const ALL: [Self; 12] = [
pub const ALL: [Self; 14] = [
Self::ItemNotFound,
Self::InventoryFull,
Self::WrongSlot,
Expand All @@ -44,6 +48,8 @@ impl ItemRefusal {
Self::BankUnavailable,
Self::ItemNotUsable,
Self::NotRightNow,
Self::Indestructible,
Self::BagNotEmpty,
Self::Internal,
];

Expand All @@ -60,6 +66,8 @@ impl ItemRefusal {
Self::BankUnavailable => "item:bank_unavailable",
Self::ItemNotUsable => "item:item_not_usable",
Self::NotRightNow => "item:not_right_now",
Self::Indestructible => "item:indestructible",
Self::BagNotEmpty => "item:bag_not_empty",
Self::Internal => "item:internal",
}
}
Expand Down
3 changes: 3 additions & 0 deletions crates/lyracore-shared/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,6 @@ pub const ERR_ATTACK_TARGET_DEAD: &str = "target is dead";
pub const ERR_ATTACK_FRIENDLY: &str = "target is friendly";

pub mod item_property;

pub mod spell;
pub mod talent;
8 changes: 8 additions & 0 deletions crates/lyracore-shared/src/spell.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//! Spell channel classification shared by gameplay and its protocol projection.

pub const SPELL_ATTR_CHANNELED: u32 = 0x0080;

/// Periodic triggers retain their legacy channel behavior when the header has no flag.
pub fn is_channel_aura(effect_kind: u8, cast_flags: u32) -> bool {
effect_kind == 0x93 || cast_flags & SPELL_ATTR_CHANNELED != 0
}
9 changes: 9 additions & 0 deletions crates/lyracore-shared/src/talent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! Talent reset pricing shared by the Module and the confirmation dialog.

pub fn respec_cost_copper(respec_count: u32) -> u32 {
match respec_count.min(10) {
0 => 10_000,
1 => 50_000,
n => 100_000 + 50_000 * (n - 2),
}
}
Loading
Loading