diff --git a/sources/Events/Events.uc b/sources/Events/Events.uc index 4a6ca1e..c965989 100644 --- a/sources/Events/Events.uc +++ b/sources/Events/Events.uc @@ -70,7 +70,7 @@ var private array< class > listeners; var public const class relatedListener; -// Even class can also auto-spawn a `Service`, +// Event class can also auto-spawn a `Service`, // in case it's require to generate events var public const class connectedServiceClass; // Set this to `true`if you want `connectedServiceClass` service to also diff --git a/sources/Players/APlayer.uc b/sources/Players/APlayer.uc index f98a38e..bb3c3be 100644 --- a/sources/Players/APlayer.uc +++ b/sources/Players/APlayer.uc @@ -1,9 +1,11 @@ /** - * Objects of this class are meant to represent a "server user": - * not a particular `PlayerController`, but an entity that server would - * recognize to be the same person even after reconnections. - * It is supposed to store and recognize various stats and - * server privileges. + * Represents a connected player connection and serves to provide access to + * both it's server data and in-game pawn representation. + * Unlike `User`, - changes when player reconnects the server. + * This object SHOULD NOT be created manually, please rely on + * `AcediaCore` for that. + * Killing floor 1 note: inherently linked to + * a particular `PlayerController`. * Copyright 2020 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. @@ -23,25 +25,50 @@ */ class APlayer extends AcediaActor; +// How this `APlayer` is identified by the server var private User identity; +// Controller var private PlayerController ownerController; // Shortcut to `ConnectionEvents`, so that we don't have to write // `class'ConnectionEvents'` every time. var const class events; -public final function Initialize(PlayerController initOwnerController) +/** + * Initializes caller `APlayer`. Should be called right after `APlayer` + * was spawned. + * + * Initialization should (and can) only be done once. + * Before a `Initialize()` call, any other method calls on such `User` + * must be considerate to have undefined behavior. + * + * @param newController Controller that caller `APLayer` will correspond to. + */ +public final function Initialize(PlayerController newController) { ownerController = initOwnerController; identity = _.users.FetchByIDHash(initOwnerController.GetPlayerIDHash()); events.static.CallPlayerConnected(self); } +/** + * Returns associated controller. + * + * @return Controller that caller `APLayer` corresponds to. + */ public final function PlayerController GetController() { return ownerController; } +/** + * IMPORTANT: this is a helper function that is not supposed to be + * called manually. + * + * Causes `APlayer` to update it's inner state and should be triggered by + * various outside events. A necessary work-around, since we cannot make + * an event to trigger a protected function. + */ public final function Update() { if (ownerController == none) { @@ -50,6 +77,8 @@ public final function Update() } } +// This is one of the most important objects for `Acedia` and should be kept +// up-to-date as much as possible. event Tick(float delta) { Update(); diff --git a/sources/Players/ConnectionListener_Player.uc b/sources/Players/ConnectionListener_Player.uc index 0837192..977c6d8 100644 --- a/sources/Players/ConnectionListener_Player.uc +++ b/sources/Players/ConnectionListener_Player.uc @@ -1,5 +1,5 @@ /** - * Listener for events generated by 'ConnectionService'. + * `PlayerService`'s listener for events generated by 'ConnectionService'. * Copyright 2019 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. @@ -19,7 +19,6 @@ */ class ConnectionListener_Player extends ConnectionListenerBase; -// `PlayerConnected` is called the moment we detect a new player on a server. static function ConnectionEstablished(ConnectionService.Connection connection) { local PlayerService service; @@ -32,8 +31,6 @@ static function ConnectionEstablished(ConnectionService.Connection connection) service.RegisterPlayer(connection.controllerReference); } -// `PlayerDisconnected` is called the moment we -// detect a player leaving the server. static function ConnectionLost(ConnectionService.Connection connection) { local PlayerService service; diff --git a/sources/Players/PlayerListenerBase.uc b/sources/Players/PlayerListenerBase.uc index d95b559..2dd2213 100644 --- a/sources/Players/PlayerListenerBase.uc +++ b/sources/Players/PlayerListenerBase.uc @@ -20,11 +20,21 @@ class PlayerListenerBase extends Listener abstract; -// `PlayerConnected` is called the moment we detect a new player on a server. +/** + * `PlayerConnected` is called the moment we detect a new player on a server. + * + * @param newPlayer Player that just connected. + */ static function PlayerConnected(APlayer newPlayer); // `PlayerDisconnected` is called the moment we // detect a player leaving the server. +/** + * `PlayerDisconnected` is called the moment we detect a player leaving + * the server. + * + * @param lostPlayer Player that just disconnected. + */ static function PlayerDisconnected(APlayer lostPlayer); defaultproperties diff --git a/sources/Players/PlayerService.uc b/sources/Players/PlayerService.uc index f99dca3..9a21770 100644 --- a/sources/Players/PlayerService.uc +++ b/sources/Players/PlayerService.uc @@ -1,7 +1,5 @@ /** * Service for tracking currently connected players. - * Besides simply storing all players it also separately stores (caches) - * players belonging to specific groups to make appropriate getters faster. * Copyright 2020 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. @@ -21,8 +19,11 @@ */ class PlayerService extends Service; +// Record of all current players var private array allPlayers; +// Cleans all our player records just in case something caused certain +// `APlayer` to get destroyed. private final function RemoveNonePlayers() { local int i; @@ -37,6 +38,17 @@ private final function RemoveNonePlayers() } } +/** + * Creates a new `APlayer` instance for a given `newPlayerController` + * controller. + * + * If given controller is `none` or it's `APLayer` was already created, + * - does nothing. + * + * @param newPlayerController Controller for which we must + * create new `APlayer`. + * @return `true` if new `APlayer` was created and `false` otherwise. + */ public final function bool RegisterPlayer(PlayerController newPlayerController) { local int i; @@ -63,12 +75,25 @@ public final function bool RegisterPlayer(PlayerController newPlayerController) return true; } +/** + * Fetches current array of all player (registered `APLayer`s). + * + * @return Current array of all player (registered `APLayer`s). Guaranteed to + * not contain `none` values. + */ public final function array GetAllPlayers() { RemoveNonePlayers(); return allPlayers; } +/** + * IMPORTANT: this is a helper function that is not supposed to be + * called manually. + * + * Causes status of all players to update. + * See `APlayer.Update()` for details. + */ public final function UpdateAllPlayers() { local int i; diff --git a/sources/Users/Tests/TEST_User.uc b/sources/Users/Tests/TEST_User.uc index 6120ecf..46472ce 100644 --- a/sources/Users/Tests/TEST_User.uc +++ b/sources/Users/Tests/TEST_User.uc @@ -1,5 +1,5 @@ /** - * Set of tests for `APlayer` and related classes. + * Set of tests for `User` and related classes. * Copyright 2020 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. diff --git a/sources/Users/User.uc b/sources/Users/User.uc index 7486c09..021dbcf 100644 --- a/sources/Users/User.uc +++ b/sources/Users/User.uc @@ -1,9 +1,7 @@ /** - * Objects of this class are meant to represent a "server user": - * not a particular `PlayerController`, but an entity that server would - * recognize to be the same person even after reconnections. - * It is supposed to store and recognize various stats and - * server privileges. + * Object that is supposed to store a persistent data about the + * certain player. That is data that will be remembered even after player + * reconnects or server changes map/restarts. * Copyright 2020 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. @@ -23,20 +21,41 @@ */ class User extends AcediaObject; +// Unique identifier for which this `User` stores it's data var private UserID id; +// A numeric "key" assigned to this user for a session that can serve as +// an easy reference in console commands var private int key; +/** + * Initializes caller `User` with id and it's session key. Should be called + * right after `APlayer` was created. + * + * Initialization should (and can) only be done once. + * Before a `Initialize()` call, any other method calls on such `User` + * must be considerate to have undefined behavior. + */ public final function Initialize(UserID initID, int initKey) { id = initID; key = initKey; } +/** + * Return id for which caller `User` stores data. + * + * @return `UserID` that caller `User` was initialized with. + */ public final function UserID GetID() { return id; } +/** + * Return session key of the caller `User`. + * + * @return Session key of the caller `User`. + */ public final function int GetKey() { return key; diff --git a/sources/Users/UserAPI.uc b/sources/Users/UserAPI.uc index 189b060..e5bacf4 100644 --- a/sources/Users/UserAPI.uc +++ b/sources/Users/UserAPI.uc @@ -1,10 +1,5 @@ /** - * API that provides functions for managing objects and actors by providing - * easy and general means to create and destroy them, that allow to make use of - * temporary `Object`s in a more efficient way. - * This is a low-level API that most users of Acedia, most likely, - * would not have to use, since creation of most objects would use their own - * wrapper functions around this API. + * API that allows easy access to `User` persistent data and `UserID`s. * Copyright 2020 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. @@ -24,16 +19,38 @@ */ class UserAPI extends Singleton; +/** + * Returns reference to the database of user records that Acedia was + * set up to use. + * + * @return Main `UserDatabase` that Acedia currently uses to load and + * store user information. Guaranteed to be a valid non-`none` reference. + */ public final function UserDatabase GetDatabase() { return class'UserDatabase'.static.GetInstance(); } +/** + * Fetches `User` object that stores persistent data for a given `userID`. + * + * @param userID ID for which to fetch a persistent data storage. + * @return `User` object for a given `UserID`. Guaranteed to be a valid + * non-`none` reference if passed `userID` is not `none` and initialized + * (which is guaranteed unless you manually created it). + */ public final function User Fetch(UserID userID) { return class'UserDatabase'.static.GetInstance().FetchUser(userID); } +/** + * Fetches appropriate `User` object for a player, given his id as a `string`. + * + * @param idHash `string` representation of someone's id. + * @return Corresponding `User` object. Guaranteed to be a valid non-`none` + * reference. + */ public final function User FetchByIDHash(string idHash) { local UserID userID; @@ -43,6 +60,14 @@ public final function User FetchByIDHash(string idHash) return userDB.FetchUser(userID); } +/** + * Fetches appropriate `User` object for a player, given his session key. + * + * @param userKey Key corresponding to a `User` method must to get. + * @return Corresponding `User` object. Guaranteed to be a valid non-`none` + * reference if `userKey` was actually assigned to any `User` during + * current playing session; `none` otherwise. + */ public final function User FetchByKey(int userKey) { return class'UserDatabase'.static.GetInstance().FetchUserByKey(userKey); diff --git a/sources/Users/UserDatabase.uc b/sources/Users/UserDatabase.uc index 1fc3469..2fd8ed7 100644 --- a/sources/Users/UserDatabase.uc +++ b/sources/Users/UserDatabase.uc @@ -1,5 +1,6 @@ /** * Simple user database for Acedia. + * Only stores data for a session, map or server restarts will clear it. * Copyright 2020 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. @@ -21,10 +22,25 @@ class UserDatabase extends AcediaObject config(Acedia) abstract; +// This is used as a global variable only (`default.activeDatabase`) to store +// a reference to main database for persistent data, used by Acedia. var private UserDatabase activeDatabase; +// `User` records that were stored this session var private array sessionUsers; +// `UserID`s generated during this session. +// Instead of constantly creating new ones - just reuse already created. +// This array should not grow too huge under normal circumstances. var private array storedUserIDs; +/** + * Provides a reference to the database of user records that Acedia was + * set up to use. + * + * Provided reference is guaranteed to not change during one session. + * + * @return reference to the database of user records that Acedia was + * set up to use. + */ public final static function UserDatabase GetInstance() { if (default.activeDatabase == none) @@ -35,6 +51,12 @@ public final static function UserDatabase GetInstance() return default.activeDatabase; } +/** + * Converts `string` representation of someone's id into appropriate + * `UserID` object. + * + * Always returns the same object for the same `idHash`. + */ public final function UserID FetchUserID(string idHash) { local int i; @@ -53,6 +75,14 @@ public final function UserID FetchUserID(string idHash) return newUserID; } +/** + * Fetches `User` object that stores persistent data for a given `userID`. + * + * @param userID ID for which to fetch a persistent data storage. + * @return `User` object for a given `UserID`. Guaranteed to be a valid + * non-`none` reference if passed `userID` is not `none` and initialized + * (which is guaranteed unless you manually created it). + */ public final function User FetchUser(UserID userID) { local int i; @@ -69,6 +99,14 @@ public final function User FetchUser(UserID userID) return newUser; } +/** + * Fetches appropriate `User` object for a player, given his session key. + * + * @param userKey Key corresponding to a `User` method must to get. + * @return Corresponding `User` object. Guaranteed to be a valid non-`none` + * reference if `userKey` was actually assigned to any `User` during + * current playing session; `none` otherwise. + */ public final function User FetchUserByKey(int userKey) { local int i; diff --git a/sources/Users/UserID.uc b/sources/Users/UserID.uc index 94d47ea..d75224e 100644 --- a/sources/Users/UserID.uc +++ b/sources/Users/UserID.uc @@ -1,9 +1,5 @@ /** * Acedia's class for storing user's ID. - * This class is inherently linked to steam and it's SteamIDs, since - * Killing Floor 1 is all but guaranteed to be steam-exclusive. - * Still, if you wish to use it in a portable manner, limit yourself to - * `Initialize()`, `IsInitialized()`, `IsEqual()` and `GetUniqueID()`. * Copyright 2020 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia.