diff --git a/Cargo.lock b/Cargo.lock
index fcb706f..ad05a8c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1040,7 +1040,7 @@ checksum = "739e9d7726dc32173fed2d69d17eef3c54682169e4e20ff1d0a45dcd37063cef"
 [[package]]
 name = "libpso"
 version = "0.1.0"
-source = "git+http://git.sharnoth.com/jake/libpso#5051514fb1d3b39a7eb6ff97b624a9ceebd93e40"
+source = "git+http://git.sharnoth.com/jake/libpso#e71b435ea3dde01a44abf0492bfab12236b1ec06"
 dependencies = [
  "chrono",
  "psopacket",
@@ -1399,7 +1399,7 @@ dependencies = [
 [[package]]
 name = "psopacket"
 version = "1.0.0"
-source = "git+http://git.sharnoth.com/jake/libpso#5051514fb1d3b39a7eb6ff97b624a9ceebd93e40"
+source = "git+http://git.sharnoth.com/jake/libpso#e71b435ea3dde01a44abf0492bfab12236b1ec06"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/src/common/mainloop/client.rs b/src/common/mainloop/client.rs
index faa33c4..d7af211 100644
--- a/src/common/mainloop/client.rs
+++ b/src/common/mainloop/client.rs
@@ -275,7 +275,9 @@ where
                     cipher_out = Some(cout);
                 },
                 OnConnect::Packet(pkt) => {
-                    send_pkt(&mut socket, &mut NullCipher {}, &pkt).await.unwrap();
+                    if let Err(err) = send_pkt(&mut socket, &mut NullCipher {}, &pkt).await {
+                        error!("error sending on_connect packet {:?}", err);
+                    }
                 }
             }
         }
diff --git a/src/ship/packet/handler/settings.rs b/src/ship/packet/handler/settings.rs
index b40da3c..de7bfaa 100644
--- a/src/ship/packet/handler/settings.rs
+++ b/src/ship/packet/handler/settings.rs
@@ -70,3 +70,20 @@ where
         })}).await??;
     Ok(Vec::new())
 }
+
+pub async fn update_tech_menu<EG>(id: ClientId,
+                                update_tech_menu: UpdateTechMenu,
+                                clients: &Clients,
+                                entity_gateway: &mut EG)
+                                -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error>
+where
+    EG: EntityGateway + Clone + 'static,
+{
+    clients.with_mut(id, |client| {
+        let mut entity_gateway = entity_gateway.clone();
+        Box::pin(async move {
+            client.character.tech_menu.tech_menu = update_tech_menu.config;
+            entity_gateway.save_character(&client.character).await
+        })}).await??;
+    Ok(Vec::new())
+}
diff --git a/src/ship/ship.rs b/src/ship/ship.rs
index 6f53fdf..4bbed5e 100644
--- a/src/ship/ship.rs
+++ b/src/ship/ship.rs
@@ -200,6 +200,7 @@ pub enum RecvShipPacket {
     KeyboardConfig(KeyboardConfig),
     GamepadConfig(GamepadConfig),
     UpdateConfig(UpdateConfig),
+    UpdateTechMenu(UpdateTechMenu),
 }
 
 impl RecvServerPacket for RecvShipPacket {
@@ -242,6 +243,7 @@ impl RecvServerPacket for RecvShipPacket {
             0x1ED => Ok(RecvShipPacket::SaveOptions(SaveOptions::from_bytes(data)?)),
             0x4ED => Ok(RecvShipPacket::KeyboardConfig(KeyboardConfig::from_bytes(data)?)),
             0x5ED => Ok(RecvShipPacket::GamepadConfig(GamepadConfig::from_bytes(data)?)),
+            0x6ED => Ok(RecvShipPacket::UpdateTechMenu(UpdateTechMenu::from_bytes(data)?)),
             0x7ED => Ok(RecvShipPacket::UpdateConfig(UpdateConfig::from_bytes(data)?)),
             _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]), data.to_vec()))
         }
@@ -742,6 +744,9 @@ impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> {
                 let block = self.blocks.get_from_client(id, &self.clients).await?;
                 handler::room::room_name_request(id, &block.client_location, &block.rooms).await?
             },
+            RecvShipPacket::UpdateTechMenu(pkt) => {
+                handler::settings::update_tech_menu(id, pkt, &self.clients, &mut self.entity_gateway).await?
+            },
             RecvShipPacket::UpdateConfig(pkt) => {
                 handler::settings::update_config(id, pkt, &self.clients, &mut self.entity_gateway).await?
             },