Skip to content

Commit 3fe2c94

Browse files
committed
teleport maze
1 parent c404898 commit 3fe2c94

File tree

6 files changed

+273
-27
lines changed

6 files changed

+273
-27
lines changed

server/src/player/sidebar.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use crate::types::sized_string::SizedString;
55
use std::convert::Into;
66
use std::ops::Deref;
77

8-
const OBJECTIVE_NAME: SizedString<16> = unsafe { SizedString::slice_truncated(*b"sidebar") };
8+
// todo rework
9+
10+
const OBJECTIVE_NAME: SizedString<16> = unsafe { SizedString::slice_truncated(*b"SBScoreboard") };
911

1012
pub struct Sidebar {
1113
lines: Vec<SizedString<64>>,

server/src/types/aabb.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use glam::DVec3;
22

3-
#[derive(Debug, Clone)]
3+
#[derive(Debug, Copy, Clone)]
44
pub struct AABB {
55
pub min: DVec3,
66
pub max: DVec3,
@@ -40,7 +40,7 @@ impl AABB {
4040
dx * dy * dz
4141
}
4242

43-
pub const fn from_height_width(height: f64, width: f64) -> Self {
43+
pub const fn from_width_height(width: f64, height: f64) -> Self {
4444
Self {
4545
min: DVec3 { x: -width / 2.0, y: 0.0, z: -width / 2.0 },
4646
max: DVec3 { x: width / 2.0, y: height, z: width / 2.0 }

src/dungeon/room/puzzles/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod three_weirdos;
2-
pub mod quiz;
2+
pub mod quiz;
3+
pub mod teleport_maze;
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
use crate::dungeon::dungeon::{Dungeon, DungeonState};
2+
use crate::dungeon::room::room::Room;
3+
use crate::dungeon::room::room_implementation::RoomImplementation;
4+
use crate::dungeon::seeded_rng::{seeded_rng, SeededRng};
5+
use glam::{dvec3, ivec3, IVec3};
6+
use rand::prelude::SliceRandom;
7+
use rand::Rng;
8+
use server::block::rotatable::Rotate;
9+
use server::network::protocol::play::clientbound::PositionLook;
10+
use server::types::aabb::AABB;
11+
use server::World;
12+
13+
pub struct TeleportMaze {
14+
teleport_pads: Vec<TeleportPad>,
15+
target: IVec3,
16+
}
17+
18+
struct TeleportPad {
19+
position: IVec3,
20+
teleports_to: IVec3,
21+
rotate_type: TeleportPadRotation,
22+
}
23+
24+
enum TeleportPadRotation {
25+
Static { yaw: f32 },
26+
TowardsEnd
27+
}
28+
29+
impl TeleportPad {
30+
pub fn aabb(&self) -> AABB {
31+
let position = self.position.as_dvec3();
32+
AABB::new(position, position + dvec3(1.0, 0.1, 1.0))
33+
}
34+
}
35+
36+
impl Default for TeleportMaze {
37+
fn default() -> Self {
38+
let mut teleport_pads: Vec<TeleportPad> = Vec::new();
39+
40+
// not the prettiest
41+
let rng = &mut seeded_rng();
42+
let mut sections: Vec<Vec<(IVec3, IVec3)>> = Vec::new();
43+
44+
for index in 0..7 {
45+
let offset = match index {
46+
0 => ivec3(20, 70, 6),
47+
1 => ivec3(20, 70, 14),
48+
2 => ivec3(20, 70, 22),
49+
3 => ivec3(12, 70, 22),
50+
4 => ivec3(4, 70, 22),
51+
5 => ivec3(4, 70, 14),
52+
6 => ivec3(4, 70, 6),
53+
_ => unreachable!()
54+
};
55+
sections.push(vec![
56+
(offset, offset + ivec3(1, -1, 1)),
57+
(offset + ivec3(6, 0, 0), offset + ivec3(5, -1, 1)),
58+
(offset + ivec3(0, 0, 6), offset + ivec3(1, -1, 5)),
59+
(offset + ivec3(6, 0, 6), offset + ivec3(5, -1, 5)),
60+
]);
61+
}
62+
63+
sections.shuffle(rng);
64+
65+
const ENTRANCE_PAD: IVec3 = ivec3(15, 70, 12);
66+
const EXIT_PAD: IVec3 = ivec3(15, 70, 14);
67+
const ENTRANCE_PAD_TO: IVec3 = ivec3(15, 69, 11);
68+
const EXIT_PAD_TO: IVec3 = ivec3(15, 69, 15);
69+
70+
// entrance
71+
let pads = &mut sections[0];
72+
let (pad, to_pad) = pop_with_rng(pads, rng);
73+
74+
teleport_pads.push(TeleportPad {
75+
position: ENTRANCE_PAD,
76+
teleports_to: to_pad,
77+
rotate_type: TeleportPadRotation::TowardsEnd,
78+
});
79+
teleport_pads.push(TeleportPad {
80+
position: pad,
81+
teleports_to: ENTRANCE_PAD_TO,
82+
rotate_type: TeleportPadRotation::Static { yaw: 180.0 },
83+
});
84+
85+
// exit
86+
let pads = &mut sections[6];
87+
let (pad_leading_to_end, _) = pop_with_rng(pads, rng);
88+
89+
teleport_pads.push(TeleportPad {
90+
position: pad_leading_to_end,
91+
teleports_to: EXIT_PAD_TO,
92+
rotate_type: TeleportPadRotation::Static { yaw: 0.0 },
93+
});
94+
teleport_pads.push(TeleportPad {
95+
position: EXIT_PAD,
96+
teleports_to: ENTRANCE_PAD_TO,
97+
rotate_type: TeleportPadRotation::Static { yaw: 180.0 },
98+
});
99+
100+
// this makes sure every section is able to be travelled to
101+
for index in 0..6 {
102+
let section_a = &mut sections[index];
103+
let (pad_a, to_pad_a) = pop_with_rng(section_a, rng);
104+
let section_b = &mut sections[index + 1];
105+
let (pad_b, to_pad_b) = pop_with_rng(section_b, rng);
106+
107+
teleport_pads.push(TeleportPad {
108+
position: pad_a,
109+
teleports_to: to_pad_b,
110+
rotate_type: TeleportPadRotation::TowardsEnd,
111+
});
112+
teleport_pads.push(TeleportPad {
113+
position: pad_b,
114+
teleports_to: to_pad_a,
115+
rotate_type: TeleportPadRotation::TowardsEnd,
116+
});
117+
}
118+
119+
let mut remaining: Vec<(usize, IVec3, IVec3)> = sections
120+
.iter()
121+
.enumerate()
122+
.flat_map(|(section_idx, pads)| {
123+
pads.iter().map(move |&(pad, to_pad)| (section_idx, pad, to_pad))
124+
})
125+
.collect();
126+
127+
remaining.shuffle(rng);
128+
129+
let mut index = 0;
130+
while index + 1 < remaining.len() {
131+
if remaining[index].0 == remaining[index + 1].0 {
132+
let j = remaining[index + 2..]
133+
.iter()
134+
.position(|(s, _, _)| *s != remaining[index].0)
135+
.expect("no valid cross-section partner found");
136+
137+
remaining.swap(index + 1, index + 2 + j);
138+
}
139+
140+
let (_, pad_a, to_pad_a) = remaining[index];
141+
let (_, pad_b, to_pad_b) = remaining[index + 1];
142+
teleport_pads.push(TeleportPad {
143+
position: pad_a,
144+
teleports_to: to_pad_b,
145+
rotate_type: TeleportPadRotation::TowardsEnd,
146+
});
147+
teleport_pads.push(TeleportPad {
148+
position: pad_b,
149+
teleports_to: to_pad_a,
150+
rotate_type: TeleportPadRotation::TowardsEnd,
151+
});
152+
153+
index += 2;
154+
}
155+
156+
Self {
157+
teleport_pads,
158+
target: pad_leading_to_end,
159+
}
160+
}
161+
}
162+
163+
impl RoomImplementation for TeleportMaze {
164+
fn discover(&mut self, room: &mut Room, _world: &mut World<Dungeon>) {
165+
// convert teleport pad data to absolute position
166+
for pad in self.teleport_pads.iter_mut() {
167+
pad.position = room.get_world_block_position(pad.position);
168+
pad.teleports_to = room.get_world_block_position(pad.teleports_to);
169+
}
170+
self.target = room.get_world_block_position(self.target);
171+
172+
// for pad in self.teleport_pads.iter() {
173+
// _world.spawn_entity(
174+
// pad.position.as_dvec3(),
175+
// 0.0,
176+
// 0.0,
177+
// MobAppearance {
178+
// variant: EntityVariant::Zombie,
179+
// metadata: EntityMetadata::Zombie(Default::default()),
180+
// },
181+
// ()
182+
// );
183+
// }
184+
}
185+
186+
fn tick(&mut self, room: &mut Room, world: &mut World<Dungeon>) {
187+
// todo, improve accuracy
188+
if let DungeonState::Started { ticks } = world.state && ticks % 10 != 0 {
189+
return;
190+
}
191+
'outer: for player in room.players() {
192+
let player_aabb = player.collision_aabb();
193+
for pad in self.teleport_pads.iter() {
194+
if !pad.aabb().intersects(&player_aabb) {
195+
continue
196+
}
197+
198+
let mut origin = pad.teleports_to.as_dvec3();
199+
origin.x += 0.5;
200+
origin.y += 0.5;
201+
origin.z += 0.5;
202+
203+
let yaw = match pad.rotate_type {
204+
TeleportPadRotation::Static { yaw } => {
205+
yaw.rotate(room.rotation)
206+
},
207+
TeleportPadRotation::TowardsEnd => {
208+
let mut target = self.target.as_dvec3();
209+
target.x += 0.5;
210+
target.z += 0.5;
211+
let diff = target - origin;
212+
f64::atan2(-diff.x, diff.z).to_degrees() as f32
213+
}
214+
};
215+
player.write_packet(&PositionLook {
216+
x: origin.x,
217+
y: origin.y,
218+
z: origin.z,
219+
yaw,
220+
pitch: 0.0,
221+
flags: Default::default(),
222+
});
223+
continue 'outer
224+
}
225+
}
226+
}
227+
228+
// todo interact
229+
}
230+
231+
fn pop_with_rng(vec: &mut Vec<(IVec3, IVec3)>, rng: &mut SeededRng) -> (IVec3, IVec3) {
232+
let pad_index = rng.random_range(0..vec.len());
233+
let it = vec[pad_index];
234+
vec.remove(pad_index);
235+
it
236+
}

src/dungeon/room/room.rs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ use crate::dungeon::door::door::Door;
22
use crate::dungeon::dungeon::{Dungeon, DUNGEON_ORIGIN};
33
use crate::dungeon::dungeon_player::DungeonPlayer;
44
use crate::dungeon::room::puzzles::quiz::QuizPuzzle;
5+
use crate::dungeon::room::puzzles::teleport_maze::TeleportMaze;
56
use crate::dungeon::room::puzzles::three_weirdos::ThreeWeirdosPuzzle;
67
use crate::dungeon::room::room_data::RoomData;
78
use crate::dungeon::room::room_implementation::{MobRoom, RoomImplementation};
89
use glam::{dvec3, ivec3, usize, IVec3};
910
use server::block::rotatable::Rotate;
1011
use server::block::Block;
12+
use server::network::protocol::play::clientbound::Chat;
1113
use server::types::aabb::AABB;
14+
use server::types::chat_component::ChatComponent;
1215
use server::types::direction::Direction;
1316
use server::world::chunk::chunk_grid::ChunkGrid;
1417
use server::{ClientId, Player, World};
@@ -99,6 +102,7 @@ impl Room {
99102
let implementation: UnsafeCell<Box<dyn RoomImplementation>> = match room_data.name.as_str() {
100103
"Three Weirdos" => UnsafeCell::new(Box::new(ThreeWeirdosPuzzle::default())),
101104
"Quiz" => UnsafeCell::new(Box::new(QuizPuzzle {})),
105+
"Teleport Maze" => UnsafeCell::new(Box::new(TeleportMaze::default())),
102106
_ => UnsafeCell::new(Box::new(MobRoom {})),
103107
};
104108

@@ -117,7 +121,7 @@ impl Room {
117121
self.segments.iter().flat_map(|seg| seg.neighbours.iter().flatten())
118122
}
119123

120-
pub fn players(&mut self) -> impl Iterator<Item = &mut Player<DungeonPlayer>> {
124+
pub fn players(&self) -> impl Iterator<Item = &mut Player<DungeonPlayer>> {
121125
self.players.values().map(|it| unsafe { &mut *it.get() })
122126
}
123127

@@ -176,8 +180,8 @@ impl Room {
176180
}
177181

178182
pub fn get_world_block_position(&self, room_position: IVec3) -> IVec3 {
179-
let corner = self.get_corner_pos();
180183
let mut position = room_position.rotate(self.rotation);
184+
let corner = self.get_corner_pos();
181185
position.x += corner.x;
182186
position.z += corner.z;
183187
position
@@ -216,26 +220,26 @@ impl Room {
216220

217221
drop(room);
218222

219-
// let room = room_rc.borrow();
220-
// let relative = {
221-
// let corner = room.get_corner_pos();
222-
// let p = IVec3 {
223-
// x: position.x - corner.x,
224-
// y: position.y,
225-
// z: position.z - corner.z,
226-
// };
227-
// match room.rotation {
228-
// Direction::North => p,
229-
// Direction::East => IVec3 { x: p.z, y: p.y, z: -p.x },
230-
// Direction::South => IVec3 { x: -p.x, y: p.y, z: -p.z },
231-
// Direction::West => IVec3 { x: -p.z, y: p.y, z: p.x },
232-
// }
233-
// };
223+
let room = room_rc.borrow();
224+
let relative = {
225+
let corner = room.get_corner_pos();
226+
let p = IVec3 {
227+
x: position.x - corner.x,
228+
y: position.y,
229+
z: position.z - corner.z,
230+
};
231+
match room.rotation {
232+
Direction::North => p,
233+
Direction::East => IVec3 { x: p.z, y: p.y, z: -p.x },
234+
Direction::South => IVec3 { x: -p.x, y: p.y, z: -p.z },
235+
Direction::West => IVec3 { x: -p.z, y: p.y, z: p.x },
236+
}
237+
};
234238

235-
// player.write_packet(&Chat {
236-
// component: ChatComponent::new(format!("relative position {}", relative)),
237-
// chat_type: 0,
238-
// })
239+
player.write_packet(&Chat {
240+
component: ChatComponent::new(format!("relative position {}", relative)),
241+
chat_type: 0,
242+
})
239243
}
240244

241245
pub fn attack_block(room_rc: &Rc<RefCell<Room>>, player: &mut Player<DungeonPlayer>, position: IVec3) {

src/main.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,12 @@ mod dungeon;
3232

3333
pub fn initialize_world(tx: Sender<NetworkThreadMessage>) -> anyhow::Result<World<Dungeon>> {
3434
let rng_seed: u64 = rand::random();
35-
SeededRng::set_seed(16795237019042391353);
35+
SeededRng::set_seed(rng_seed);
3636

37-
// println!("seed {rng_seed}");
37+
// tp maze, ice fill, boulder seed 18158556563918935308
38+
// three weirdo seed 16795237019042391353
39+
40+
println!("seed {rng_seed}");
3841

3942
let dungeon_layouts = include_str!("../DungeonData/dungeon_layouts.txt")
4043
.split("\n")

0 commit comments

Comments
 (0)