agones.dev/agones@v1.54.0/sdks/rust/src/alpha.rs (about)

     1  // Copyright 2020 Google LLC All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  use crate::errors::Result;
    16  use tonic::transport::Channel;
    17  
    18  mod api {
    19      tonic::include_proto!("agones.dev.sdk.alpha");
    20  }
    21  
    22  use api::sdk_client::SdkClient;
    23  
    24  /// Alpha is an instance of the Agones Alpha SDK
    25  #[derive(Clone)]
    26  pub struct Alpha {
    27      client: SdkClient<Channel>,
    28  }
    29  
    30  impl Alpha {
    31      /// new creates a new instance of the Alpha SDK
    32      pub(crate) fn new(ch: Channel) -> Self {
    33          Self {
    34              client: SdkClient::new(ch),
    35          }
    36      }
    37  
    38      /// This returns the last player capacity that was set through the SDK.
    39      /// If the player capacity is set from outside the SDK, use
    40      /// [`Sdk::get_gameserver`] instead.
    41      #[inline]
    42      pub async fn get_player_capacity(&mut self) -> Result<i64> {
    43          Ok(self
    44              .client
    45              .get_player_capacity(api::Empty {})
    46              .await
    47              .map(|c| c.into_inner().count)?)
    48      }
    49  
    50      /// This changes the player capacity to a new value.
    51      #[inline]
    52      pub async fn set_player_capacity(&mut self, count: i64) -> Result<()> {
    53          Ok(self
    54              .client
    55              .set_player_capacity(api::Count { count })
    56              .await
    57              .map(|_| ())?)
    58      }
    59  
    60      /// This function increases the SDK’s stored player count by one, and appends
    61      /// this playerID to `GameServer.status.players.ids`.
    62      ///
    63      /// Returns true and adds the playerID to the list of playerIDs if the
    64      /// playerIDs was not already in the list of connected playerIDs.
    65      #[inline]
    66      pub async fn player_connect(&mut self, id: impl Into<String>) -> Result<bool> {
    67          Ok(self
    68              .client
    69              .player_connect(api::PlayerId {
    70                  player_id: id.into(),
    71              })
    72              .await
    73              .map(|b| b.into_inner().bool)?)
    74      }
    75  
    76      /// This function decreases the SDK’s stored player count by one, and removes
    77      /// the playerID from GameServer.status.players.ids.
    78      ///
    79      /// Will return true and remove the supplied playerID from the list of
    80      /// connected playerIDs if the playerID value exists within the list.
    81      #[inline]
    82      pub async fn player_disconnect(&mut self, id: impl Into<String>) -> Result<bool> {
    83          Ok(self
    84              .client
    85              .player_disconnect(api::PlayerId {
    86                  player_id: id.into(),
    87              })
    88              .await
    89              .map(|b| b.into_inner().bool)?)
    90      }
    91  
    92      /// Returns the current player count.
    93      #[inline]
    94      pub async fn get_player_count(&mut self) -> Result<i64> {
    95          Ok(self
    96              .client
    97              .get_player_count(api::Empty {})
    98              .await
    99              .map(|c| c.into_inner().count)?)
   100      }
   101  
   102      /// This returns if the playerID is currently connected to the GameServer.
   103      /// This is always accurate, even if the value hasn’t been updated to the
   104      /// Game Server status yet.
   105      #[inline]
   106      pub async fn is_player_connected(&mut self, id: impl Into<String>) -> Result<bool> {
   107          Ok(self
   108              .client
   109              .is_player_connected(api::PlayerId {
   110                  player_id: id.into(),
   111              })
   112              .await
   113              .map(|b| b.into_inner().bool)?)
   114      }
   115  
   116      /// This returns the list of the currently connected player ids.
   117      /// This is always accurate, even if the value has not been updated to the
   118      /// Game Server status yet.
   119      #[inline]
   120      pub async fn get_connected_players(&mut self) -> Result<Vec<String>> {
   121          Ok(self
   122              .client
   123              .get_connected_players(api::Empty {})
   124              .await
   125              .map(|pl| pl.into_inner().list)?)
   126      }
   127  }
   128  
   129  
   130  #[cfg(test)]
   131  mod tests {
   132      use tokio;
   133  
   134      // MockAlpha simulates Alpha's async methods for unit testing
   135      struct MockAlpha {
   136          capacity: i64,
   137          player_count: i64,
   138          player_connected: Option<String>,
   139          player_disconnected: Option<String>,
   140      }
   141  
   142      impl MockAlpha {
   143          fn new() -> Self {
   144              Self {
   145                  capacity: 0,
   146                  player_count: 0,
   147                  player_connected: None,
   148                  player_disconnected: None,
   149              }
   150          }
   151  
   152          async fn get_player_capacity(&mut self) -> i64 {
   153              self.capacity
   154          }
   155  
   156          async fn set_player_capacity(&mut self, count: i64) {
   157              self.capacity = count;
   158          }
   159  
   160          async fn player_connect(&mut self, id: impl Into<String>) -> bool {
   161              let id = id.into();
   162              self.player_connected = Some(id.clone());
   163              self.player_count += 1;
   164              true
   165          }
   166  
   167          async fn player_disconnect(&mut self, id: impl Into<String>) -> bool {
   168              let id = id.into();
   169              self.player_disconnected = Some(id.clone());
   170              if self.player_count > 0 {
   171                  self.player_count -= 1;
   172              }
   173              true
   174          }
   175  
   176          async fn get_player_count(&mut self) -> i64 {
   177              self.player_count
   178          }
   179  
   180          async fn is_player_connected(&mut self, id: impl Into<String>) -> bool {
   181              match &self.player_connected {
   182                  Some(connected) => id.into() == *connected,
   183                  None => false,
   184              }
   185          }
   186  
   187          async fn get_connected_players(&mut self) -> Vec<String> {
   188              match &self.player_connected {
   189                  Some(id) => vec![id.clone()],
   190                  None => vec![],
   191              }
   192          }
   193      }
   194  
   195      #[tokio::test]
   196      async fn test_alpha_player_flow() {
   197          let mut alpha = MockAlpha::new();
   198  
   199          // Set and get player capacity
   200          alpha.set_player_capacity(15).await;
   201          assert_eq!(alpha.capacity, 15);
   202  
   203          let capacity = alpha.get_player_capacity().await;
   204          assert_eq!(capacity, 15);
   205  
   206          // Connect player
   207          let player_id = "one";
   208          let ok = alpha.player_connect(player_id).await;
   209          assert!(ok);
   210          assert_eq!(alpha.player_connected.as_deref(), Some(player_id));
   211  
   212          // Get player count
   213          let count = alpha.get_player_count().await;
   214          assert_eq!(count, 1);
   215  
   216          // Disconnect player
   217          let ok = alpha.player_disconnect(player_id).await;
   218          assert!(ok);
   219          assert_eq!(alpha.player_disconnected.as_deref(), Some(player_id));
   220  
   221          // Put the player back in
   222          let ok = alpha.player_connect(player_id).await;
   223          assert!(ok);
   224          let count = alpha.get_player_count().await;
   225          assert_eq!(count, 1);
   226  
   227          // Is player connected (should be true)
   228          let ok = alpha.is_player_connected(player_id).await;
   229          assert!(ok, "Player should be connected");
   230  
   231          // Is player connected (should be false)
   232          let ok = alpha.is_player_connected("false").await;
   233          assert!(!ok, "Player should not be connected");
   234  
   235          // Get connected players
   236          let list = alpha.get_connected_players().await;
   237          assert_eq!(list, vec![player_id]);
   238      }
   239  }