Skip to content

Commit fcaa2a1

Browse files
committed
Allow bloodstains in pvp-enabled region of Roundtable Hold
1 parent 0120987 commit fcaa2a1

4 files changed

Lines changed: 74 additions & 16 deletions

File tree

message/src/eldenring/bloodstain.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use serde::{Deserialize, Serialize};
1+
use serde::{de, Deserialize, Serialize};
22

33
use super::*;
44

@@ -10,6 +10,30 @@ pub struct RequestCreateBloodstainParams {
1010
pub group_passwords: Vec<String>,
1111
}
1212

13+
#[derive(Serialize, Deserialize, Debug)]
14+
pub struct BloodstainAdvertisementData {
15+
pub magic: [u8; 8],
16+
pub version: u32,
17+
pub unkc: u32,
18+
pub unk10: u32,
19+
pub unk14: u32,
20+
pub unk18: u32,
21+
pub location: Location,
22+
pub yaw: f32,
23+
pub ghost_spawn_position: Position,
24+
pub unk3c: u32,
25+
pub unk40: u16,
26+
pub unk42: u16,
27+
pub unk44: u16,
28+
pub unk46: u8,
29+
pub unk47: u8,
30+
pub unk48: u64,
31+
pub play_region: u32,
32+
pub character_name: [u16; 18],
33+
pub unk70: u32,
34+
pub unk74: u32,
35+
}
36+
1337
#[derive(Serialize, Deserialize, Debug)]
1438
pub struct ResponseCreateBloodstainParams {
1539
pub identifier: ObjectIdentifier,
@@ -66,6 +90,15 @@ mod test {
6690
assert_eq!(deserialized.replay_data.len(), 1165);
6791
assert_eq!(deserialized.group_passwords.len(), 1);
6892
assert_eq!(deserialized.group_passwords[0], "schlong");
93+
94+
let adv_data: super::BloodstainAdvertisementData =
95+
deserialize(&deserialized.advertisement_data).unwrap();
96+
assert_eq!(&adv_data.magic, &[7, 0, 0, 0, 120, 0, 0, 0]);
97+
assert_eq!(adv_data.version, 7);
98+
assert_eq!(adv_data.play_region, 1400001);
99+
assert_eq!(adv_data.location.position.x, 150.72684);
100+
assert_eq!(adv_data.location.position.y, 112.589775);
101+
assert_eq!(adv_data.location.position.z, -180.64731);
69102
}
70103

71104
#[test]

message/src/eldenring/log.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ mod test {
5757
assert_eq!(deserialized.used_items[0].times_used, 1);
5858
assert_eq!(deserialized.used_items[0].new_count, 1);
5959
assert_eq!(deserialized.location.map, 60423600);
60-
assert_eq!(deserialized.location.x, -45.939575);
61-
assert_eq!(deserialized.location.y, 92.36392);
62-
assert_eq!(deserialized.location.z, 79.65545);
60+
assert_eq!(deserialized.location.position.x, -45.939575);
61+
assert_eq!(deserialized.location.position.y, 92.36392);
62+
assert_eq!(deserialized.location.position.z, 79.65545);
6363
}
6464
}

message/src/eldenring/shared.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,14 @@ pub struct MatchingParameters {
6060
}
6161

6262
#[derive(Serialize, Deserialize, Clone, Debug)]
63-
pub struct Location {
64-
pub map: u32,
63+
pub struct Position {
6564
pub x: f32,
6665
pub y: f32,
6766
pub z: f32,
6867
}
68+
69+
#[derive(Serialize, Deserialize, Clone, Debug)]
70+
pub struct Location {
71+
pub map: u32,
72+
pub position: Position,
73+
}

server/src/handler/eldenring/bloodstain.rs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use message::eldenring::{
2-
ObjectIdentifier, PlayRegionArea, RequestCreateBloodstainParams,
3-
RequestGetBloodstainListParams, RequestGetDeadingGhostParams, ResponseCreateBloodstainParams,
4-
ResponseGetBloodstainListParams, ResponseGetBloodstainListParamsEntry,
5-
ResponseGetDeadingGhostParams,
2+
BloodstainAdvertisementData, ObjectIdentifier, PlayRegionArea, Position,
3+
RequestCreateBloodstainParams, RequestGetBloodstainListParams, RequestGetDeadingGhostParams,
4+
ResponseCreateBloodstainParams, ResponseGetBloodstainListParams,
5+
ResponseGetBloodstainListParamsEntry, ResponseGetDeadingGhostParams,
66
};
77
use sqlx::Row;
8+
use wire::deserialize;
89

910
use crate::handler::HandleRequest;
1011

@@ -56,7 +57,23 @@ const SELECT_BY_ID_QUERY: &str = "
5657
SELECT *
5758
FROM bloodstains
5859
WHERE bloodstain_id = $1";
60+
5961
const ROUNDTABLE_PLAY_REGION_ID: i32 = 1110000;
62+
/// BBOX defining the PVP-enabled area within the Roundtable Hold
63+
/// (lower part where player can be invaded by npc invader)
64+
const ROUNDTABLE_PVP_ENABLED_AREA_BBOX: [(f32, f32, f32); 2] =
65+
[(-325.0, -35.0, -325.0), (-245.0, -25.0, -245.0)];
66+
67+
fn is_in_bbox(pos: Position, bbox: [(f32, f32, f32); 2]) -> bool {
68+
let min = bbox[0];
69+
let max = bbox[1];
70+
pos.x >= min.0
71+
&& pos.x <= max.0
72+
&& pos.y >= min.1
73+
&& pos.y <= max.1
74+
&& pos.z >= min.2
75+
&& pos.z <= max.2
76+
}
6077

6178
impl HandleRequest<Box<RequestCreateBloodstainParams>, ResponseCreateBloodstainParams>
6279
for DefaultClientHandler<'_>
@@ -65,11 +82,15 @@ impl HandleRequest<Box<RequestCreateBloodstainParams>, ResponseCreateBloodstainP
6582
&mut self,
6683
request: &Box<RequestCreateBloodstainParams>,
6784
) -> Result<ResponseCreateBloodstainParams, Box<dyn std::error::Error>> {
68-
if request.area.play_region == ROUNDTABLE_PLAY_REGION_ID {
69-
// Don't store bloodstains in the Roundtable Hold area.
70-
return Ok(ResponseCreateBloodstainParams {
71-
identifier: ObjectIdentifier(0),
72-
});
85+
if request.area.play_region as i32 == ROUNDTABLE_PLAY_REGION_ID {
86+
// check that location is in the pvp-enabled area of the roundtable
87+
let adv_data: BloodstainAdvertisementData = deserialize(&request.advertisement_data)?;
88+
let pos = adv_data.location.position;
89+
if !is_in_bbox(pos, ROUNDTABLE_PVP_ENABLED_AREA_BBOX) {
90+
return Ok(ResponseCreateBloodstainParams {
91+
identifier: ObjectIdentifier(0),
92+
});
93+
}
7394
}
7495
let bloodstain_id = sqlx::query(INSERT_QUERY)
7596
.bind(self.session.player_id)
@@ -100,7 +121,6 @@ impl HandleRequest<Box<RequestGetBloodstainListParams>, ResponseGetBloodstainLis
100121
.search_areas
101122
.iter()
102123
.map(|a| a.play_region as i32)
103-
.filter(|&pr| pr != ROUNDTABLE_PLAY_REGION_ID)
104124
.collect::<Vec<i32>>();
105125

106126
if play_regions.is_empty() {

0 commit comments

Comments
 (0)