Features
This a complex API using many factors (configurable) to decide, if player is AFK. Plugin could be useful even for people who does not develop plugins (chat commands for certain actions are included here, see Commands).
- Getting player's AFK status
- Getting player's AFK time
- Getting list of AFK players
- Setting up this plugin config through API, if needed and allowed in native config file
Permissions
afkapi.use- Allows player to use/isafkand/getafkcommandsafkapi.kick- Allows player to kick all the AFK players at once
Chat Commands
/isafk <Player name or id>- gives caller the status of targeted player (AFK, NOT AFK or OFFLINE)/getafk- gives caller the list of AFK players/kickafk- kicks all the AFK players from the server at once
Configuration
{
"General Settings": {
"Seconds to consider player is AFK": 300,
"AFK Check Interval": 5,
"Allow other plugins change settings of this API": true
},
"Accuracy Settings": {
"Check rotation in pair with position (more accurate)": true,
"Check for build attempts": true,
"Check for communication attempts (chat/voice)": true,
"Check for item actions (craft/change/use/move)": true
},
"Notification Settings": {
"Notify player before considering him AFK": true,
"Notify player X seconds before considering him AFK": 60,
"Notify with sound": true
}
}
Localization
{
"Plugin prefix": "<color=#6797e5>[AFK API]</color>",
"Player AFK status": "The player <color=#fff268>{0}</color> AFK status: {1}",
"No valid arguments error": "<color=orange>Wrong command usage, no valid arguments specified</color>",
"Offline status": "<color=red>OFFLINE</color>",
"Is AFK status": "<color=yellow>IS AFK</color>",
"Is not AFK status": "<color=lime>NOT AFK</color>",
"AFK player list": "<color=yellow>AFK player list:</color>{0}",
"No players AFK atm": "<color=lime>Currently no players are AFK</color>",
"Notification for AFK player": "<color=red>Start moving, or you will be punished for AFK!</color>",
"No permission": "<color=red>You have no permission to run this command!</color>"
}
Developer API
Getting started
You'd need to reference plugin explicitely to use most hooks.
Use the magic reference to make plugin manager automatically check if the plugin is present
// Requires: AFKAPI
Use PluginReferenceAttribute to define the plugin field
[PluginReference] Plugin AFKAPI;
Check if player is AFK
API method
Will return true if the player is AFK, returns false if it's not or player is offline (or never been on the server)
bool IsPlayerAFK(<ulong|string|IPlayer> player)
Example call
private void CallIsPlayerAFK()
{
AFKAPI.Call<bool>("IsPlayerAFK", BasePlayer.Find("2CHEVSKII")?.userID);
}
Get player AFK time
Note that this method will return time of player doing nothing (what is tracked by API), even if he is not considered AFK at the moment
API method
Will return number of seconds. Returns -1 if the player is not AFK / offline
long GetPlayerAFKTime(ulong id) // Deprecated, use GetPlayerAFKTime(<string|IPlayer> player) : float
float GetPlayerAFKTime(<string|IPlayer> player)
Example call
private void CallGetPlayerAFKTime()
{
AFKAPI.Call<float>("GetPlayerAFKTime", BasePlayer.Find("2CHEVSKII")?.userIDString);
}
Get list of AFK players
API method
List<BasePlayer> GetAFKPlayers()
Example call
private void CallGetAFKPlayers()
{
var list = AFKAPI.Call<List<BasePlayer>>("GetAFKPlayers");
}
Setup plugin config through API
Use this function only if highly required, it's always better to setup the native config manually to avoid conflicts with other plugins using this API and features
New plugin settings must be given as serialized json string. Use the class below and the example method to avoid errors.
API method
Will return true if settings are applied, needToSave might be used to save config file with new parameters (You can omit this, so settings will be keeped for this session only)
bool AFKAPI_Setup(string newSettings, bool needToSave = false)
Settings class
class PluginSettings
{
[JsonProperty(PropertyName = "General Settings")]
internal GeneralPluginSettings GeneralSettings { get; set; }
[JsonProperty(PropertyName = "Accuracy Settings")]
internal ComparePluginSettings CompareSettings { get; set; }
[JsonProperty(PropertyName = "Notification Settings")]
internal NotificationPluginSettings NotificationSettings { get; set; }
internal class GeneralPluginSettings
{
[JsonProperty(PropertyName = "Seconds to consider player is AFK")]
internal int SecondsToAFKStatus { get; set; }
[JsonProperty(PropertyName = "AFK Check Interval")]
internal int StatusRefreshInterval { get; set; }
[JsonProperty(PropertyName = "Allow other plugins change settings of this API")]
internal bool AllowSetupThroughAPI { get; set; }
}
internal class ComparePluginSettings
{
[JsonProperty(PropertyName = "Check rotation in pair with position (more accurate)")]
internal bool CompareRotation { get; set; }
[JsonProperty(PropertyName = "Check for build attempts")]
internal bool CompareBuild { get; set; }
[JsonProperty(PropertyName = "Check for communication attempts (chat/voice)")]
internal bool CompareCommunication { get; set; }
[JsonProperty(PropertyName = "Check for item actions (craft/change/use/move)")]
internal bool CompareItemActions { get; set; }
}
internal class NotificationPluginSettings
{
[JsonProperty(PropertyName = "Notify player before considering him AFK")]
internal bool NotifyPlayer { get; set; }
[JsonProperty(PropertyName = "Notify player X seconds before considering him AFK")]
internal int NotifyPlayerTime { get; set; }
[JsonProperty(PropertyName = "Notify with sound")]
internal bool NotifyPlayerSound { get; set; }
}
}
Generate string
private string GetNewSettings()
{
return JsonConvert.SerializeObject(new PluginSettings
{
GeneralSettings = new PluginSettings.GeneralPluginSettings
{
SecondsToAFKStatus = 300,
StatusRefreshInterval = 5,
AllowSetupThroughAPI = true
},
CompareSettings = new PluginSettings.ComparePluginSettings
{
CompareBuild = true,
CompareCommunication = true,
CompareItemActions = true,
CompareRotation = true
},
NotificationSettings = new PluginSettings.NotificationPluginSettings
{
NotifyPlayer = true,
NotifyPlayerSound = true,
NotifyPlayerTime = 60
}
});
}
Example call
private void CallAFKAPI_Setup()
{
AFKAPI.Call<bool>("AFKAPI_Setup", GetNewSettings(), true);
}
MIT License
Copyright (c) 2020 2CHEVSKII
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

