M Cargo.lock => Cargo.lock +1 -0
@@ 3297,6 3297,7 @@ dependencies = [
"protobuf 3.2.0",
"protobuf-codegen 3.2.0",
"protoc-rust",
+ "serde",
]
[[package]]
M api/config.toml => api/config.toml +12 -6
@@ 1,15 1,21 @@
+game = "localhost:5173"
+internal_tokens = ["01GY803PVK7YJKXZYWFTK6DS1Y-01GY8040ZQY9SG29DXY4HZ4EPD"]
+jwt_signing_secret = "544adbc8144d375d581a1622a4f0cbcf92f006a156ef8b9d4afac6410f51f73c"
+base = "localhost:8080"
+
+[server]
+listen = "0.0.0.0:8080"
+
[realms.discord]
authorize_url = "https://api.e3t.cc/auth/discord/authorize.php"
-public_key_url = "https://api.e3t.cc/auth/discord/public-key.txt"
+public_key = "-----BEGIN PUBLIC KEY-----\nMIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHBcZsCM6ebFDCp3dFc+3EOzLw8B\n+fR+9Tx6S/lXOTghk49s7yaxza/zVRPxWaMqyjegfRCEepgV++jbWzBib7bhy91M\n+zlRbeZ9rf++N30Nf4R/XAnUAmhAHt8TzDC08DNQNYAFz37+r4EZlY7APHyND4qU\nd8w3qB95v/wMVB6nAgMBAAE=\n-----END PUBLIC KEY-----"
issuer = "https://api.e3t.cc"
-[tokens]
-internal_api_tokens = [
- "01GY803PVK7YJKXZYWFTK6DS1Y-01GY8040ZQY9SG29DXY4HZ4EPD"
-]
+[database]
+url = "postgres://postgres@localhost/starkingdoms"
[endpoints]
allowed_return_endpoints = [
"127.0.0.1:5173",
"starkingdoms.tk"
-]>
\ No newline at end of file
+]
M protocol/Cargo.toml => protocol/Cargo.toml +1 -0
@@ 7,6 7,7 @@ edition = "2021"
[dependencies]
protobuf = "3"
+serde = { version = "1", features = ["derive"] }
[build-dependencies]
protobuf-codegen = "3"
A protocol/src/api.rs => protocol/src/api.rs +6 -0
@@ 0,0 1,6 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize)]
+pub struct APISavedPlayerData {
+
+}<
\ No newline at end of file
M protocol/src/lib.rs => protocol/src/lib.rs +3 -1
@@ 6,7 6,9 @@ use crate::planet::PlanetType;
use crate::starkingdoms_protocol::PacketWrapper;
include!(concat!(env!("OUT_DIR"), "/protos/mod.rs"));
-pub const PROTOCOL_VERSION: u32 = 1;
+pub const PROTOCOL_VERSION: u32 = 2;
+
+pub mod api;
#[derive(Debug)]
pub enum MessageC2S {
M protocol/src/pbuf/message_c2s.proto => protocol/src/pbuf/message_c2s.proto +3 -0
@@ 10,6 10,9 @@ message MessageC2SHello {
uint32 version = 1; // Version of the protocol. Currently always 1
string requested_username = 2; // The username that the client is requesting.
protocol.state.State next_state = 3; // The state the connection will go into after the handshake.
+
+ optional string token = 4;
+ optional string user = 5;
}
message MessageC2SGoodbye {
A server/src/api.rs => server/src/api.rs +12 -0
@@ 0,0 1,12 @@
+use std::error::Error;
+use starkingdoms_protocol::api::APISavedPlayerData;
+
+pub async fn load_player_data_from_api(token: &str, user_id: &str, internal_token: &str) -> Result<APISavedPlayerData, Box<dyn Error>> {
+ // TODO
+ Ok(APISavedPlayerData {})
+}
+
+pub async fn save_player_data_to_api(data: &APISavedPlayerData, token: &str, user_id: &str, internal_token: &str) -> Result<(), Box<dyn Error + Send + Sync>> {
+ // TODO
+ Ok(())
+}<
\ No newline at end of file
M server/src/handler.rs => server/src/handler.rs +53 -7
@@ 4,7 4,7 @@ use std::sync::Arc;
use std::time::{Duration, SystemTime};
use futures::stream::{SplitSink, SplitStream};
use futures::{FutureExt, SinkExt, StreamExt};
-use log::{error, info, debug};
+use log::{error, info, debug, warn};
use nalgebra::{vector, point};
use rapier2d_f64::prelude::{RigidBodyBuilder, RigidBodyType, ColliderBuilder, MassProperties, Collider};
use tungstenite::Message;
@@ 18,6 18,8 @@ use crate::{send, recv, SCALE};
use async_std::{sync::RwLock, channel::Receiver};
use async_std::net::TcpStream;
use async_tungstenite::WebSocketStream;
+use starkingdoms_protocol::api::APISavedPlayerData;
+use crate::api::{load_player_data_from_api, save_player_data_to_api};
pub async fn handle_client(mgr: ClientManager, entities: Arc<RwLock<EntityHandler>>, data: Arc<RwLock<PhysicsData>>,
remote_addr: SocketAddr, rx: Receiver<ClientHandlerMessage>,
@@ 152,12 154,34 @@ pub async fn handle_client(mgr: ClientManager, entities: Arc<RwLock<EntityHandle
data_handle.rigid_body_set = rigid_body_set;
data_handle.collider_set = collider_set;
- entities.write().await.entities.insert(get_entity_id(),
- Entity::Player(Player {
- handle: player_handle,
- input: Default::default(),
- addr: remote_addr
- }));
+ let mut player = Player {
+ handle: player_handle,
+ input: Default::default(),
+ addr: remote_addr,
+ auth_token: pkt.token.clone(),
+ auth_user: pkt.user.clone()
+ };
+
+ let mut e_write_handle = entities.write().await;
+
+ if let Some(user) = pkt.user {
+ if let Some(token) = pkt.token {
+ info!("[{}] * Beamin: beaming in {} as {} with token {}", remote_addr, username, user, token);
+
+ let player_data = match load_player_data_from_api(&token, &user, &std::env::var("STK_API_KEY").unwrap()).await {
+ Ok(d) => d,
+ Err(e) => {
+ warn!("[{}] * Beamin: ABORTED. API returned error: {}", remote_addr, e);
+ e_write_handle.entities.insert(get_entity_id(), Entity::Player(player));
+ continue;
+ }
+ };
+
+ player.load_api_data(&player_data);
+ }
+ }
+
+ e_write_handle.entities.insert(get_entity_id(), Entity::Player(player));
debug!("running");
}
},
@@ 224,6 248,28 @@ pub async fn handle_client(mgr: ClientManager, entities: Arc<RwLock<EntityHandle
},
MessageC2S::AuthenticateAndBeamOut(p) => {
info!("[{}] * Beaming out {} as {} with realm token {}", remote_addr, username, p.user_id, p.token);
+
+ let player = entities.read().await.get_player(remote_addr).expect("Player sending messages after disconnect");
+
+ if Some(p.token) != player.auth_token || Some(p.user_id) != player.auth_user {
+ warn!("[{}] invalid beamout packet, ignoring", remote_addr);
+ continue;
+ }
+
+ match save_player_data_to_api(&player.as_api_data(), &player.auth_token.unwrap(), &player.auth_user.unwrap(), &std::env::var("STK_API_KEY").unwrap()).await {
+ Ok(_) => {
+ info!("[{}] * Beamed out successfully", remote_addr);
+ let msg = MessageS2C::Goodbye(MessageS2CGoodbye {
+ reason: GoodbyeReason::Done.into(),
+ special_fields: Default::default(),
+ }).try_into()?;
+ send!(client_tx, msg).await?;
+ break;
+ }
+ Err(e) => {
+ error!("[{}] error beaming out: {}", remote_addr, e);
+ }
+ }
}
}
}
M server/src/main.rs => server/src/main.rs +6 -0
@@ 27,6 27,7 @@ pub mod macros;
pub mod planet;
pub mod orbit;
pub mod entity;
+pub mod api;
const SCALE: f64 = 1.0;
@@ 162,6 163,11 @@ lazy_static! {
async fn main() {
simple_logger::init_with_level(Level::Debug).expect("Unable to start logging service");
+ if std::env::var("STK_API_KEY").is_err() {
+ error!("Unable to read the API key from STK_API_KEY. Ensure it is set, and has a valid value.");
+ std::process::exit(1);
+ }
+
let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
info!("Listening on {} for HTTP/WebSocket connections", addr);
M server/src/manager.rs => server/src/manager.rs +12 -0
@@ 5,6 5,7 @@ use rapier2d_f64::na::Vector2;
use rapier2d_f64::prelude::{IntegrationParameters, PhysicsPipeline, IslandManager, BroadPhase, NarrowPhase, ImpulseJointSet, MultibodyJointSet, CCDSolver, RigidBodySet, ColliderSet, RigidBodyHandle};
use async_std::sync::RwLock;
use async_std::channel::Sender;
+use starkingdoms_protocol::api::APISavedPlayerData;
#[derive(Clone)]
pub struct ClientManager {
@@ 17,6 18,17 @@ pub struct Player {
pub handle: RigidBodyHandle,
pub input: PlayerInput,
pub addr: SocketAddr,
+ pub auth_token: Option<String>,
+ pub auth_user: Option<String>,
+}
+
+impl Player {
+ pub fn as_api_data(&self) -> APISavedPlayerData {
+ APISavedPlayerData {}
+ }
+
+ pub fn load_api_data(&mut self, data: &APISavedPlayerData) {
+ }
}
#[derive(Default, Clone)]