• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#objective-cqt誰得cocoawindowspythonphprubygameguibathyscaphec翻訳omegat計画中(planning stage)frameworktwittertestdombtronvb.netdirectxarduinopreviewerゲームエンジン

Administrator's Toolkit VS plugin


Commit MetaInfo

Revisionca0f0d1c56f86ab1dddfe64e3900f6743b50b603 (tree)
Time2022-06-22 10:18:57
Authormelchior <melchior@user...>
Commitermelchior

Log Message

Idler W.I.P. ,

Change Summary

Incremental Difference

--- a/AdminToolkit/AdminModConfig.cs
+++ b/AdminToolkit/AdminModConfig.cs
@@ -54,6 +54,12 @@ namespace AdminToolkit
5454 /// </summary>
5555 public bool VariableSpawnpoints { get; set; }
5656
57+ /// <summary>
58+ /// Time to permit players to Idle (no movement), before Auto-kick
59+ /// </summary>
60+ /// <value>Time span</value>
61+ public TimeSpan IdleTimeout { get; set; }
62+
5763 public AdminModConfig( )
5864 {
5965 this.PlayerRoleRestrain = "suvisitor";
@@ -64,6 +70,7 @@ namespace AdminToolkit
6470 this.BackupDelay = new TimeSpan(4, 0, 0);
6571 this.BackupCount = 6;
6672 this.Autobackup = false;
73+ this.IdleTimeout = new TimeSpan(0, 0, 0);// 0 = OFF
6774 }
6875
6976
--- a/AdminToolkit/AdminToolkit.csproj
+++ b/AdminToolkit/AdminToolkit.csproj
@@ -83,6 +83,7 @@
8383 <Compile Include="Commands\VariableSpawnpoints.cs" />
8484 <Compile Include="ATK_BasicFeatures.cs" />
8585 <Compile Include="Helpers\MultiLang.cs" />
86+ <Compile Include="Commands\IdlePlayerControl.cs" />
8687 </ItemGroup>
8788 <ItemGroup>
8889 <Folder Include="VS_libs\" />
--- a/AdminToolkit/AdminToolkitMod.cs
+++ b/AdminToolkit/AdminToolkitMod.cs
@@ -28,10 +28,10 @@ namespace AdminToolkit
2828 * [DONE] Keeps track of Elapsed game calendar days for players
2929 * [DONE] Alter ADMIN text to look 'different' (optional)
3030 * [DONE] Cyclic automatic Backups
31- * [WIP} Broadcast messages, on a schedule ??????
32- * [???] Custom Server name : custom formats to indicate server state/time/things
33- * [IDEA]: Player VIRTUAL (temp) Inventory; Move Player inventory to alternate [world] D.B. as Inventory backup
34- * [WIP]: Variable Player (re)Spawn points from a list ~ at random
31+ * [WIP] Broadcast messages, on a schedule ??????
32+ * [RSCH] Custom Server name : custom formats to indicate server state/time/season/things
33+ * [DONE?]: Variable Player (re)Spawn points from a list ~ at random
34+ * [RSCH] Idle player eject on time(out)
3535 *
3636 * WORKAROUND -- Localized messages are by SERVERS Native Language code...Not the players...
3737 */
@@ -109,6 +109,8 @@ namespace AdminToolkit
109109 this.ServerAPI.RegisterCommand(new BackupCycleCommand(this.ServerAPI) );
110110 //this.ServerAPI.RegisterCommand(new BannerControl(this.ServerAPI));
111111 this.ServerAPI.RegisterCommand(new PingerCommand(this.ServerAPI));
112+ this.ServerAPI.RegisterCommand(new IdlePlayerControl(this.ServerAPI));
113+
112114 if (this.CachedConfiguration.VariableSpawnpoints) { this.ServerAPI.RegisterCommand(new VariableSpawnpoints(this.ServerAPI)); }
113115
114116 if (CachedConfiguration.BoomingVoice) {
--- /dev/null
+++ b/AdminToolkit/Commands/IdlePlayerControl.cs
@@ -0,0 +1,124 @@
1+using System;
2+
3+using System.Linq;
4+using System.Text;
5+using System.Collections.Generic;
6+
7+using Vintagestory.API.Common;
8+using Vintagestory.API.Server;
9+using Vintagestory.Server;
10+using Vintagestory.API.Common.Entities;
11+
12+namespace AdminToolkit
13+{
14+ public class IdlePlayerControl : AdminModCommand
15+ {
16+ const string idleKick_Key = @"atk:idle-kick";
17+
18+ uint kick_tally;
19+ long timerIdent;
20+
21+ Dictionary<string, EntityPos> playerPositions;
22+
23+
24+ public IdlePlayerControl(ICoreServerAPI _serverAPI) : base(_serverAPI)
25+ {
26+ playerPositions = new Dictionary<string, EntityPos>(32);
27+ this.Command = "idlekick";
28+ this.Description = "Adjust Idle-ejector system settings.";
29+ this.Syntax = @" set {time} | stats ";
30+ this.RequiredPrivilege = Privilege.kick;
31+ this.handler += HandleIdlerCommand;
32+ ServerAPI.Event.PlayerLeave += PlayerLeft;
33+ ServerAPI.Event.PlayerDisconnect += PlayerLeft;
34+
35+ if (this.CachedConfiguration.IdleTimeout.TotalMinutes >= 5f) {
36+ ServerAPI.Event.ServerRunPhase(EnumServerRunPhase.RunGame, RestartTimers);
37+ }
38+
39+ }
40+
41+ private void HandleIdlerCommand(IServerPlayer player, int groupId, CmdArgs args)
42+ {
43+ var command = args.PopWord(string.Empty).ToLowerInvariant();
44+
45+ switch (command) {
46+ case @"set":
47+ //Change default & next cycle check time
48+ var timeMinutes = args.PopInt(0);
49+ if (timeMinutes >= 5) {
50+ TimeSpan newTimeout = new TimeSpan(0, timeMinutes.Value, 0);
51+ this.CachedConfiguration.IdleTimeout = newTimeout;
52+ player.SendMessage(groupId, $"Changed Idle timeout to: {newTimeout}", EnumChatType.CommandSuccess);
53+ RestartTimers();
54+ } else
55+ player.SendMessage(groupId, "no change; Value must be >= 5", EnumChatType.CommandError);
56+ break;
57+
58+ case @"stats":
59+ if (this.CachedConfiguration.IdleTimeout.TotalMinutes >= 5f)
60+ { player.SendMessage(groupId, $"Ejected: {kick_tally} player(s), Timeout = {this.CachedConfiguration.IdleTimeout}", EnumChatType.CommandSuccess); }
61+ else { player.SendMessage(groupId, "offline.", EnumChatType.CommandSuccess); }
62+ break;
63+
64+ default:
65+ player.SendMessage(groupId, $"Unrecognised command: {command}", EnumChatType.CommandError);
66+ break;
67+ }
68+ }
69+
70+ private void RestartTimers( )
71+ {
72+ if (timerIdent != 0L)
73+ {
74+ ServerAPI.Event.UnregisterCallback(timerIdent);
75+ playerPositions.Clear( );
76+ FindIdlers(0f );
77+ }
78+ timerIdent = ServerAPI.Event.RegisterCallback(FindIdlers, ( int )this.CachedConfiguration.IdleTimeout.TotalMilliseconds);
79+ }
80+
81+ private void FindIdlers(float delta )
82+ {
83+ #if DEBUG
84+ Logger.VerboseDebug("Starting idle player check");
85+ #endif
86+
87+ foreach (var srvPlayer in ServerAPI.Server.Players.Where(plr => plr.ConnectionState == EnumClientState.Playing)) {
88+ if (srvPlayer?.WorldData?.CurrentGameMode != EnumGameMode.Spectator) {
89+ EntityPos oldPos;
90+ if (playerPositions.TryGetValue(srvPlayer.PlayerUID, out oldPos)) {
91+ if (oldPos.BasicallySameAsIgnoreAngles(srvPlayer.Entity.ServerPos, 0.001f)) {
92+ if ( srvPlayer.Entity.CurrentControls.HasFlag( EnumEntityActivity.Idle) ||
93+ srvPlayer.Entity.CurrentControls.HasFlag(EnumEntityActivity.FloorSitting) ||
94+ srvPlayer.Entity.CurrentControls.HasFlag(EnumEntityActivity.Dead) ||
95+ srvPlayer.Entity.CurrentControls.HasFlag(EnumEntityActivity.None) )
96+ {
97+ //Eee's not movin'
98+ KickIdler(srvPlayer);
99+ }
100+
101+ }
102+ }
103+ else {
104+ playerPositions.Add(srvPlayer.PlayerUID, srvPlayer.Entity.ServerPos);
105+ }
106+ }
107+ }
108+ }
109+
110+ private void KickIdler(IServerPlayer them)
111+ {
112+ kick_tally++;
113+ var message = MultiLang.Get(them.LanguageCode, idleKick_Key, them.PlayerName);
114+ them.Disconnect(message);
115+ ServerAPI.BroadcastMessageToAllGroups(message, EnumChatType.Notification);
116+ }
117+
118+ private void PlayerLeft(IServerPlayer byPlayer)
119+ {
120+ if (playerPositions.ContainsKey(byPlayer.PlayerUID)) playerPositions.Remove(byPlayer.PlayerUID);
121+ }
122+}
123+}
124+
--- a/AdminToolkit/assets/atk/lang/en.json
+++ b/AdminToolkit/assets/atk/lang/en.json
@@ -10,4 +10,5 @@
1010 "atk:accepted-rules":"{0} HAS ACCEPTED THE RULES!",
1111 "atk:promoted-to":"{0} have been promoted to: {1}",
1212 "atk:demoted-to":"{0} have been demoted to: {1}",
13+ "atk:idle-kick":"{0} Ejected because of Idleness...",
1314 }