Skip to content

Commit c96f59d

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents ae24fe6 + 5de065b commit c96f59d

File tree

12 files changed

+350
-144
lines changed

12 files changed

+350
-144
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ opt-level = 3
2424

2525
[profile.release]
2626
codegen-units = 1
27-
lto = "thin"
27+
lto = "thin"

src/dungeon/crushers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::server::utils::direction::Direction;
55
use crate::server::world::World;
66
use serde_json::Value;
77

8+
#[derive(Debug)]
89
pub struct Crusher {
910
pub block_pos: BlockPos,
1011
pub direction: Direction,

src/dungeon/dungeon.rs

Lines changed: 265 additions & 80 deletions
Large diffs are not rendered by default.

src/dungeon/map.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::dungeon::door::DoorType;
1+
use crate::dungeon::door::{Door, DoorType};
22
use crate::dungeon::room::room::Room;
33
use crate::dungeon::room::room_data::{RoomData, RoomShape, RoomType::*};
44
use crate::server::block::block_parameter::Axis;
@@ -121,52 +121,52 @@ impl DungeonMap {
121121
}
122122
}
123123
}
124-
125-
pub fn draw_room(&mut self, room: &Room) {
126-
124+
125+
pub fn draw_room(&mut self, rooms: &[Room], doors: &[Door], room_index: usize) {
126+
let room = &rooms[room_index];
127127
let color = get_room_color(&room.room_data);
128-
128+
129129
for segment in room.segments.iter() {
130130
let x = segment.x * 20;
131131
let y = segment.z * 20;
132-
132+
133133
self.fill_px(x, y, 16, 16, color);
134-
135134
if room.segments.iter().find(|seg| seg.x == segment.x + 1 && seg.z == segment.z).is_some() {
136135
self.fill_px(x + 16, y, 4, 16, color);
137136
}
138137
if room.segments.iter().find(|seg| seg.x == segment.x && seg.z == segment.z + 1).is_some() {
139138
self.fill_px(x, y + 16, 16, 4, color);
140139
}
141-
140+
142141
for (index, neighbour) in segment.neighbours.iter().enumerate() {
143142
if neighbour.is_none() {
144143
continue;
145144
}
146-
let (neighbour, door) = {
145+
146+
let (neighbour_room, door) = {
147147
let neighbour = neighbour.as_ref().unwrap();
148-
(neighbour.room.borrow(), neighbour.door.borrow())
148+
(&rooms[neighbour.room_index], &doors[neighbour.door_index])
149149
};
150-
150+
151151
let mut x = segment.x * 20 + 6;
152152
let mut y = segment.z * 20 + 6;
153-
153+
154154
match index {
155155
0 => y -= 10,
156156
1 => x += 10,
157157
2 => y += 10,
158158
3 => x -= 10,
159159
_ => unreachable!()
160160
}
161-
161+
162162
let (width, height) = match door.direction {
163163
Axis::X => (4, 5),
164164
Axis::Z => (5, 4),
165165
_ => unreachable!()
166166
};
167-
168-
if neighbour.entered {
169-
let color = get_door_color(room, &*neighbour);
167+
168+
if neighbour_room.entered {
169+
let color = get_door_color(room, neighbour_room);
170170
self.fill_px(x, y, width, height, color);
171171
} else {
172172
let color = match door.door_type {
@@ -195,7 +195,7 @@ impl DungeonMap {
195195
}
196196
}
197197
}
198-
198+
199199
// fill in hole
200200
if room.room_data.shape == RoomShape::TwoByTwo {
201201
let x = room.segments[0].x * 20 + 16;

src/dungeon/room/room.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,22 @@ use crate::server::block::blocks::Blocks;
77
use crate::server::block::rotatable::Rotatable;
88
use crate::server::utils::direction::Direction;
99
use crate::server::world::World;
10-
use std::cell::RefCell;
1110
use std::collections::HashSet;
12-
use std::rc::Rc;
1311

12+
#[derive(Debug)]
1413
pub struct RoomSegment {
1514
pub x: usize,
1615
pub z: usize,
1716
pub neighbours: [Option<RoomNeighbour>; 4]
1817
}
1918

19+
#[derive(Debug)]
2020
pub struct RoomNeighbour {
21-
pub door: Rc<RefCell<Door>>,
22-
pub room: Rc<RefCell<Room>>,
21+
pub door_index: usize,
22+
pub room_index: usize,
2323
}
2424

25+
#[derive(Debug)]
2526
pub struct Room {
2627
pub segments: Vec<RoomSegment>,
2728
pub room_data: RoomData,
@@ -37,7 +38,7 @@ impl Room {
3738

3839
pub fn new(
3940
mut segments: Vec<RoomSegment>,
40-
dungeon_doors: &Vec<Door>,
41+
dungeon_doors: &[Door],
4142
room_data: RoomData
4243
) -> Room {
4344
// Sort room segments by z and then x
@@ -87,7 +88,7 @@ impl Room {
8788
Room::get_corner_pos_from(&self.segments, &self.rotation, &self.room_data)
8889
}
8990

90-
pub fn get_corner_pos_from(segments: &Vec<RoomSegment>, rotation: &Direction, room_data: &RoomData) -> BlockPos {
91+
pub fn get_corner_pos_from(segments: &[RoomSegment], rotation: &Direction, room_data: &RoomData) -> BlockPos {
9192
let min_x = segments.iter().min_by(|a, b| a.x.cmp(&b.x)).unwrap().x;
9293
let min_z = segments.iter().min_by(|a, b| a.z.cmp(&b.z)).unwrap().z;
9394

@@ -108,7 +109,7 @@ impl Room {
108109
self.tick_amount += 1;
109110
}
110111

111-
pub fn get_1x1_shape_and_type(segments: &Vec<RoomSegment>, dungeon_doors: &Vec<Door>) -> (RoomShape, Direction) {
112+
pub fn get_1x1_shape_and_type(segments: &[RoomSegment], dungeon_doors: &[Door]) -> (RoomShape, Direction) {
112113
let center_x = segments[0].x as i32 * 32 + 15 + DUNGEON_ORIGIN.0;
113114
let center_z = segments[0].z as i32 * 32 + 15 + DUNGEON_ORIGIN.1;
114115

@@ -158,7 +159,7 @@ impl Room {
158159
}
159160
}
160161

161-
pub fn get_rotation_from_segments(segments: &Vec<RoomSegment>, dungeon_doors: &Vec<Door>) -> Direction {
162+
pub fn get_rotation_from_segments(segments: &[RoomSegment], dungeon_doors: &[Door]) -> Direction {
162163
let unique_x = segments.iter()
163164
.map(|segment| segment.x)
164165
.collect::<HashSet<usize>>();

src/dungeon/room/room_data.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl RoomShape {
4242
}
4343
}
4444

45-
pub fn from_segments(segments: &Vec<RoomSegment>, dungeon_doors: &Vec<Door>) -> RoomShape {
45+
pub fn from_segments(segments: &[RoomSegment], dungeon_doors: &[Door]) -> RoomShape {
4646

4747
let unique_x = segments.iter()
4848
.map(|segment| segment.x)

src/main.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::server::utils::dvec3::DVec3;
3131
use crate::server::world::VIEW_DISTANCE;
3232
use crate::utils::hasher::deterministic_hasher::DeterministicHashMap;
3333
use crate::utils::seeded_rng::SeededRng;
34-
use anyhow::Result;
34+
use anyhow::{bail, Result};
3535
use chrono::Local;
3636
use include_dir::include_dir;
3737
use indoc::formatdoc;
@@ -41,6 +41,7 @@ use std::env;
4141
use std::ops::Add;
4242
use std::time::{Duration, SystemTime, UNIX_EPOCH};
4343
use tokio::sync::mpsc::unbounded_channel;
44+
use tokio::sync::mpsc::error::TryRecvError;
4445

4546
#[tokio::main]
4647
async fn main() -> Result<()> {
@@ -130,7 +131,7 @@ async fn main() -> Result<()> {
130131
println!("Rng Seed: {}", rng_seed);
131132
SeededRng::set_seed(rng_seed);
132133

133-
let dungeon = Dungeon::from_string(dungeon_str, &room_data_storage)?;
134+
let dungeon = Dungeon::from_str(dungeon_str, &room_data_storage)?;
134135
let mut server = Server::initialize_with_dungeon(network_tx, dungeon);
135136
server.world.server = &mut server;
136137
server.dungeon.server = &mut server;
@@ -145,7 +146,6 @@ async fn main() -> Result<()> {
145146
let dungeon = &server.dungeon;
146147

147148
for room in &dungeon.rooms {
148-
let room = room.borrow();
149149
// println!("Room: {:?} type={:?} rotation={:?} shape={:?} corner={:?}", room.segments, room.room_data.room_type, room.rotation, room.room_data.shape, room.get_corner_pos());
150150
room.load_into_world(&mut server.world);
151151

@@ -166,7 +166,7 @@ async fn main() -> Result<()> {
166166

167167
// test
168168
pub struct MortImpl;
169-
169+
170170
impl EntityImpl for MortImpl {
171171
fn tick(&mut self, _: &mut Entity, _: &mut PacketBuffer) {
172172
// rotate
@@ -178,7 +178,7 @@ async fn main() -> Result<()> {
178178
player.open_ui(UI::MortReadyUpMenu);
179179
}
180180
}
181-
181+
182182
let id = server.world.spawn_entity(
183183
room.get_world_block_pos(&BlockPos { x: 15, y: 69, z: 4 })
184184
.as_dvec3()
@@ -192,7 +192,7 @@ async fn main() -> Result<()> {
192192
}
193193

194194
for door in &dungeon.doors {
195-
door.borrow().load_into_world(&mut server.world, &door_type_blocks);
195+
door.load_into_world(&mut server.world, &door_type_blocks);
196196
}
197197

198198
// let zombie_spawn_pos = DVec3 {
@@ -226,10 +226,14 @@ async fn main() -> Result<()> {
226226
tick_interval.tick().await;
227227
// let start = std::time::Instant::now();
228228

229-
while let Ok(message) = main_rx.try_recv() {
230-
server.process_event(message).unwrap_or_else(|err| eprintln!("Error processing event: {err}"));
229+
loop {
230+
match main_rx.try_recv() {
231+
Ok(message) => server.process_event(message).unwrap_or_else(|err| eprintln!("Error processing event: {err}")),
232+
Err(TryRecvError::Empty) => break,
233+
Err(TryRecvError::Disconnected) => bail!("Network thread dropped its reciever."),
234+
}
231235
}
232-
236+
233237
server.dungeon.tick()?;
234238
server.world.tick()?;
235239

@@ -356,8 +360,8 @@ async fn main() -> Result<()> {
356360
format!("{} {}{}", SKYBLOCK_MONTHS[month], day_of_month, suffix)
357361
};
358362

359-
let room_id = if let Some(room) = player.server_mut().dungeon.get_player_room(player) {
360-
&room.borrow().room_data.id
363+
let room_id = if let Some(room) = server.dungeon.get_player_room(player) {
364+
&server.dungeon.rooms[room].room_data.id
361365
} else {
362366
""
363367
};

src/net/client.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ impl Client {
2929
}
3030
}
3131

32+
// main thread tx errors can be ignored since the network/client threads will close eachother properly regardless of client status,
33+
// which will in turn close the client handlers.
34+
3235
pub async fn handle_client(
3336
client_id: ClientId,
3437
mut socket: TcpStream,

src/net/internal_packets.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub enum NetworkThreadMessage {
1919
/// Disconnects the client from the server.
2020
/// This sends a close handler message to the client's handler.
2121
/// It should be sent after the vanilla disconnect packet is sent.
22+
/// the main thread should wait for a ClientDisconnected response to handle actually removing the player.
2223
DisconnectClient {
2324
client_id: ClientId,
2425
},
@@ -41,11 +42,8 @@ pub enum MainThreadMessage {
4142
profile: GameProfile,
4243
},
4344

45+
/// sent to the main thread when a client is removed for any reason, even reasons caused by the main thread.
4446
ClientDisconnected {
4547
client_id: ClientId,
4648
},
47-
48-
Abort {
49-
reason: String,
50-
},
5149
}

src/net/run_network.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,22 @@ use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
77
use crate::net::internal_packets::{ClientHandlerMessage, MainThreadMessage, NetworkThreadMessage};
88
use crate::server::player::player::ClientId;
99

10-
/// runs the network thread. It is very important that nothing here panics without alerting the main thread.
11-
/// if a handle_client panics, it should send a disconnect player to the main thread. (however we dont have anything that could panic there atm)
10+
type ClientMap = HashMap<ClientId, UnboundedSender<ClientHandlerMessage>>;
11+
1212
pub async fn run_network_thread(
1313
mut network_rx: UnboundedReceiver<NetworkThreadMessage>,
1414
network_tx: UnboundedSender<NetworkThreadMessage>,
1515
main_tx: UnboundedSender<MainThreadMessage>,
1616
) {
17-
let listener = TcpListener::bind("127.0.0.1:4972").await.unwrap_or_else(|err| {
18-
let _ = main_tx.send(MainThreadMessage::Abort { reason: format!("TCP failed to bind: {}", err) });
19-
panic!("{}", err)
20-
});
17+
let listener = TcpListener::bind("127.0.0.1:4972").await.unwrap();
2118
println!("Network thread listening on 127.0.0.1:4972");
2219

23-
let mut clients: HashMap<ClientId, UnboundedSender<ClientHandlerMessage>> = HashMap::new();
20+
let mut clients: ClientMap = HashMap::new();
2421
let mut client_id_counter: ClientId = 1;
2522

2623
loop {
2724
tokio::select! {
25+
// a client failing to connect here is recoverable and doesnt really do anything, so we can just ignore it.
2826
Ok((socket, _)) = listener.accept() => {
2927
let client_id: ClientId = client_id_counter;
3028
client_id_counter += 1;
@@ -35,28 +33,39 @@ pub async fn run_network_thread(
3533
tokio::spawn(handle_client(client_id, socket, client_rx, main_tx.clone(), network_tx.clone()));
3634
}
3735

36+
// this can never be none since this function owns a network_tx.
3837
Some(msg) = network_rx.recv() => {
39-
match msg {
38+
// we can just discard main thread -> network thread messages with a disconnected client_id
39+
// as the main thread either already has or will be be informed shortly of this issue
40+
match msg {
4041
NetworkThreadMessage::SendPackets { client_id, buffer } => {
4142
if let Some(client_tx) = clients.get(&client_id) {
42-
let _ = client_tx.send(ClientHandlerMessage::Send(buffer));
43+
if let Err(e) = client_tx.send(ClientHandlerMessage::Send(buffer)) {
44+
eprintln!("Client {} handler dropped its reciever: {}", client_id, e);
45+
disconnect_client(client_id, &main_tx, &mut clients);
46+
}
4347
}
4448
}
45-
49+
4650
NetworkThreadMessage::DisconnectClient { client_id } => {
4751
if let Some(client_tx) = clients.get(&client_id) {
48-
let _ = client_tx.send(ClientHandlerMessage::CloseHandler);
49-
} else {
50-
eprintln!("Attempted to disconnect nonexistent client {}", client_id);
52+
if let Err(e) = client_tx.send(ClientHandlerMessage::CloseHandler) {
53+
eprintln!("Client {} handler dropped its reciever: {}", client_id, e);
54+
disconnect_client(client_id, &main_tx, &mut clients);
55+
}
5156
}
5257
}
53-
58+
5459
NetworkThreadMessage::ConnectionClosed { client_id } => {
55-
let _ = main_tx.send(MainThreadMessage::ClientDisconnected { client_id });
56-
clients.remove(&client_id);
60+
disconnect_client(client_id, &main_tx, &mut clients);
5761
}
5862
}
5963
}
6064
}
6165
}
66+
}
67+
68+
fn disconnect_client(client_id: ClientId, main_tx: &UnboundedSender<MainThreadMessage>, clients: &mut ClientMap) {
69+
main_tx.send(MainThreadMessage::ClientDisconnected { client_id }).expect("Main thread should never drop its network reciever.");
70+
clients.remove(&client_id);
6271
}

0 commit comments

Comments
 (0)