• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Administrator's Toolkit VS plugin


Commit MetaInfo

修订版9e9f04a4367d778dcb2f2d338360533a5c7a7ee2 (tree)
时间2020-09-09 08:35:29
作者melchior <melchior@user...>
Commitermelchior

Log Message

Added Variable Spawnpoints feature (W.I.P.)

更改概述

差异

--- a/AdminToolkit/AdminModConfig.cs
+++ b/AdminToolkit/AdminModConfig.cs
@@ -49,6 +49,11 @@ namespace AdminToolkit
4949 /// <value>The booming voice.</value>
5050 public bool BoomingVoice { get; set; }
5151
52+ /// <summary>
53+ /// Semi-Randomize spawn point from a set list
54+ /// </summary>
55+ public bool VariableSpawnpoints { get; set; }
56+
5257 public AdminModConfig( )
5358 {
5459 this.PlayerRoleRestrain = "suvisitor";
--- a/AdminToolkit/AdminToolkit.csproj
+++ b/AdminToolkit/AdminToolkit.csproj
@@ -76,6 +76,7 @@
7676 <Compile Include="Commands\RulesCommand.cs" />
7777 <Compile Include="Commands\BannerControl.cs" />
7878 <Compile Include="Commands\PingerCommand.cs" />
79+ <Compile Include="Commands\VariableSpawnpoints.cs" />
7980 </ItemGroup>
8081 <ItemGroup>
8182 <Folder Include="VS_libs\" />
--- a/AdminToolkit/AdminToolkitMod.cs
+++ b/AdminToolkit/AdminToolkitMod.cs
@@ -27,6 +27,8 @@ namespace AdminToolkit
2727 * [DONE] Cyclic automatic Backups
2828 * [WIP} Broadcast messages, on a schedule ??????
2929 * [???] Custom Server name : custom formats to indicate server state/time/things
30+ * [IDEA]: Player inventory Insurance; recover lost items for a (two) time fee... one policy per player.
31+ * [WIP]: Variable Player (re)Spawn points from a list ~ at random
3032 */
3133
3234 private ICoreAPI API { get; set; }
@@ -97,8 +99,9 @@ namespace AdminToolkit
9799 this.ServerAPI.RegisterCommand(new RulesCommand(this.ServerAPI) );
98100 this.ServerAPI.RegisterCommand(new AdminListingCommand(this.ServerAPI) );
99101 this.ServerAPI.RegisterCommand(new BackupCycleCommand(this.ServerAPI) );
100- this.ServerAPI.RegisterCommand(new BannerControl(this.ServerAPI));
102+ //this.ServerAPI.RegisterCommand(new BannerControl(this.ServerAPI));
101103 this.ServerAPI.RegisterCommand(new PingerCommand(this.ServerAPI));
104+ this.ServerAPI.RegisterCommand(new VariableSpawnpoints(this.ServerAPI));
102105
103106 if (CachedConfiguration.BoomingVoice) {
104107 this.ServerAPI.Event.PlayerChat += BoomingVoiceOfAuthority;
--- a/AdminToolkit/Commands/BannerControl.cs
+++ b/AdminToolkit/Commands/BannerControl.cs
@@ -1,14 +1,20 @@
11 using System;
2+using System.Collections.ObjectModel;
23
34 using ProtoBuf;
45
56 using Vintagestory.API.Common;
67 using Vintagestory.API.Server;
8+using Vintagestory.API.Util;
79
810 namespace AdminToolkit
911 {
1012 public class BannerControl : AdminModCommand
1113 {
14+ private const string _bannerDataKey = @"banners";
15+
16+ private BannerList Banners { get; set; }
17+
1218 /// <summary>
1319 /// Control and Configuration of automatic Broadcast 'banners' / M.O.T.H.
1420 /// </summary>
@@ -30,17 +36,69 @@ namespace AdminToolkit
3036 this.Command = "banners";
3137 this.Description = "Control future broadcast 'banners' & repeating Messages";
3238 this.RequiredPrivilege = Privilege.announce;
39+ this.Syntax = @"Add / Remove / Replace / List";
3340 this.handler += HandleBannerCommand;
3441 }
3542
3643 private void ReactivateBanners( )
3744 {
45+ var bannerBytes = ServerAPI.WorldManager.SaveGame.GetData(_bannerDataKey);
46+
47+ if (bannerBytes != null) {
48+ this.Banners = SerializerUtil.Deserialize<BannerList>(bannerBytes);
49+ Logger.Notification("Loaded Banners Data; ({0})", Banners.Count);
50+ }
51+ else {
52+ BannerList emptyBannerList = new BannerList( );
53+
54+ var emptybannerListBytes = SerializerUtil.Serialize<BannerList>(emptyBannerList);
55+
56+ ServerAPI.WorldManager.SaveGame.StoreData(_bannerDataKey, emptybannerListBytes);
57+
58+ this.Banners = emptyBannerList;
59+ Logger.Notification("Created (empty) Banners Data");
60+ }
61+
3862
3963 }
4064
4165
4266 private void HandleBannerCommand(IServerPlayer player, int groupId, CmdArgs args)
4367 {
68+
69+ if (args.Length >= 1) {
70+ string cmd = args.PopWord(string.Empty);
71+ switch (cmd.ToLowerInvariant())
72+ {
73+ //Add <slot#> <repeat/once> <DD:HH:MM:SS> "text"
74+ //Remove <slot#>
75+ //Replace <slot#> "text"
76+ //List
77+ case "add":
78+
79+ break;
80+
81+ case "remove":
82+
83+ break;
84+
85+ case "replace":
86+
87+ break;
88+
89+ case "list":
90+
91+ break;
92+
93+ default:
94+ player.SendMessage(groupId, "Unrecognised command ", EnumChatType.CommandError);
95+ break;
96+
97+ }
98+ }
99+ else {
100+ player.SendMessage(groupId, "Supply a command verb", EnumChatType.CommandError);
101+ }
44102
45103 }
46104
@@ -48,16 +106,37 @@ namespace AdminToolkit
48106 public struct BannerEntry
49107 {
50108 [ProtoMember(1)]
51- public string Message;
109+ public byte Entry;
52110
53111 [ProtoMember(2)]
54- public TimeSpan EventTime;
112+ public string Message;
55113
56114 [ProtoMember(3)]
57- public bool Repeat;
115+ public TimeSpan EventTime;//Delay between tick events
58116
117+ [ProtoMember(4)]
118+ public bool Repeat;//Self Re-register on execution of tick event
119+ }
59120
121+ [ProtoContract]
122+ public class BannerList : KeyedCollection<byte, BannerEntry>
123+ {
124+ protected override byte GetKeyForItem(BannerEntry item)
125+ {
126+ return item.Entry;
127+ }
128+
129+ public void Append(BannerEntry banner)
130+ {
131+ banner.Entry = ( byte )this.Count;
132+ Add(banner);
133+ }
134+
135+ private new void Add(BannerEntry item)
136+ {
137+ //Not directly.
138+ }
60139 }
61-}
140+ }
62141 }
63142
--- /dev/null
+++ b/AdminToolkit/Commands/VariableSpawnpoints.cs
@@ -0,0 +1,243 @@
1+using System;
2+using System.Linq;
3+using System.Collections.Generic;
4+
5+using Vintagestory.API.Common;
6+using Vintagestory.API.Config;
7+using Vintagestory.API.MathTools;
8+using Vintagestory.API.Server;
9+using Vintagestory.API.Util;
10+
11+using Vintagestory.Server;
12+
13+using ProtoBuf;
14+
15+
16+namespace AdminToolkit
17+{
18+ [ProtoContract]
19+ public struct Spawnpoint
20+ {
21+ [ProtoMember(1)]
22+ public PlayerSpawnPos Location;
23+
24+ [ProtoMember(2)]
25+ public string Name;
26+
27+ public Spawnpoint(string name, Vec3i loc)
28+ {
29+ Name = name;
30+ Location = new PlayerSpawnPos {
31+ x = loc.X,
32+ y = loc.Y,
33+ z = loc.Z
34+ };
35+ }
36+
37+ }
38+
39+ public class VariableSpawnpoints : AdminModCommand
40+ {
41+ private const string _spawnsDataKey = @"spawnpoints";
42+ private Random random = new Random();
43+
44+ private List<Spawnpoint> Spawnpoints { get; set; }
45+
46+
47+ public VariableSpawnpoints(ICoreServerAPI _serverAPI) : base(_serverAPI)
48+ {
49+ this.Command = "spawnpoints";
50+ this.Description = "Control add/remove/adjust List of approved player spawn points";
51+ this.RequiredPrivilege = Privilege.setspawn;
52+ this.Syntax = @"Add {name} {123,456,-678}|here / Remove {name} / List / Enable / Disable";
53+ this.handler += HandleCommand;
54+
55+ ServerAPI.Event.ServerRunPhase(EnumServerRunPhase.RunGame, ReloadSpawnpoints);
56+ ServerAPI.Event.PlayerCreate += NewPlayerCreation;
57+ ServerAPI.Event.PlayerDeath += PlayerDied;
58+ ServerAPI.Event.ServerRunPhase(EnumServerRunPhase.Shutdown, PersistSpawnpoints);
59+ }
60+
61+ private void ReloadSpawnpoints( )
62+ {
63+ var spawnsBytes = ServerAPI.WorldManager.SaveGame.GetData(_spawnsDataKey);
64+
65+ if (spawnsBytes != null) {
66+ this.Spawnpoints = SerializerUtil.Deserialize<List<Spawnpoint>>(spawnsBytes);
67+ Logger.Notification("Loaded Variable-Spawns # ({0})", Spawnpoints.Count);
68+ }
69+ else {
70+ this.Spawnpoints = new List<Spawnpoint>( );
71+
72+ var emptySpawnsList = SerializerUtil.Serialize(this.Spawnpoints);
73+
74+ ServerAPI.WorldManager.SaveGame.StoreData(_spawnsDataKey, emptySpawnsList);
75+
76+ Logger.Notification("Created (empty) Spawnpoints Data");
77+ }
78+
79+
80+ }
81+
82+ private void PersistSpawnpoints( )
83+ {
84+ if (this.Spawnpoints != null && this.Spawnpoints.Count > 0) {
85+ var spawnDatas = SerializerUtil.Serialize(this.Spawnpoints);
86+ ServerAPI.WorldManager.SaveGame.StoreData(_spawnsDataKey, spawnDatas);
87+ Logger.Notification("Persisted Spawnpoints Data");
88+ }
89+
90+ }
91+
92+ private void HandleCommand(IServerPlayer player, int groupId, CmdArgs args)
93+ {
94+ string name;
95+ Vec3i position;
96+
97+
98+
99+ if (args.Length >= 1) {
100+ string cmd = args.PopWord(string.Empty).ToLowerInvariant();
101+ switch (cmd) {
102+
103+ case "add":
104+ name = args.PopWord("?");
105+
106+ if (String.Equals(args.PeekWord(), "here", StringComparison.OrdinalIgnoreCase)) {
107+ position = player.Entity.Pos.XYZInt;
108+ }
109+ position = args.PopVec3i(player.Entity.Pos.XYZInt);
110+ if (AddSpawnpoint(name, position)) {
111+ player.SendMessage(groupId, "Added Spawnpoint", EnumChatType.CommandSuccess);
112+ }
113+ break;
114+
115+ case "remove":
116+ name = args.PopWord( );
117+ if (RemoveSpawnpoint(name)) {
118+ player.SendMessage(groupId, "Removed Spawnpoint", EnumChatType.CommandSuccess);
119+ }
120+ break;
121+
122+ case "list":
123+ ListSpawnpoints(groupId, player);
124+ break;
125+
126+ case "enable":
127+ Toggle(true);
128+ break;
129+
130+ case "disable":
131+ Toggle(false);
132+ break;
133+
134+ default:
135+ player.SendMessage(groupId, "Unrecognised command ", EnumChatType.CommandError);
136+ break;
137+
138+ }
139+ }
140+ else {
141+ player.SendMessage(groupId, "Supply a command verb", EnumChatType.CommandError);
142+ }
143+
144+ }
145+
146+ private bool AddSpawnpoint(string name, Vec3i position)
147+ {
148+ //Check position is 'safe'; 2~ blocks air, and solid block BELOW...
149+ var surfaceBlock = ServerAPI.World.BlockAccessor.GetBlock(position.AsBlockPos);
150+ var aboveBlock = ServerAPI.World.BlockAccessor.GetBlock(position.AddCopy(BlockFacing.UP).AsBlockPos);
151+ var belowBlock = ServerAPI.World.BlockAccessor.GetBlock(position.AddCopy(BlockFacing.DOWN).AsBlockPos);
152+
153+ if (belowBlock.MatterState == EnumMatterState.Solid &&
154+ aboveBlock.BlockMaterial == EnumBlockMaterial.Air &&
155+ surfaceBlock.BlockMaterial == EnumBlockMaterial.Air) {
156+ //Appears OK...
157+ Logger.VerboseDebug($"Adding variable spawnpoint '{name}' @ {position}");
158+ var newSpawnpoint = new Spawnpoint(name, position);
159+
160+ this.Spawnpoints.Add(newSpawnpoint);
161+ return true;
162+ }
163+ else {
164+ Logger.VerboseDebug($"Apparently spawnpoint Unsafe! @ {position}");
165+ }
166+
167+ return false;
168+ }
169+
170+ private bool RemoveSpawnpoint(string name)
171+ {
172+
173+ if (this.Spawnpoints.Count > 0) {
174+ var count = this.Spawnpoints.RemoveAll(sp => String.Equals(sp.Name, name, StringComparison.InvariantCultureIgnoreCase));
175+ return count > 0;
176+ }
177+
178+ return false;
179+ }
180+
181+ private void ListSpawnpoints( int chatGroupId, IServerPlayer player )
182+ {
183+ if (this.Spawnpoints.Count > 0) {
184+ foreach (var sp in this.Spawnpoints) {
185+ player.SendMessage(chatGroupId, $"Spawn: '{sp.Name}' @({sp.Location})", EnumChatType.CommandSuccess);
186+ }
187+ }
188+ }
189+
190+ private void Toggle(bool state)
191+ {
192+ this.CachedConfiguration.VariableSpawnpoints = state;
193+ }
194+
195+ private void NewPlayerCreation( IServerPlayer byPlayer)
196+ {
197+ if (this.CachedConfiguration.VariableSpawnpoints && this.Spawnpoints.Count > 0) {
198+
199+ var swpd = byPlayer.WorldData as ServerWorldPlayerData;
200+ if (swpd.SpawnPosition == null) {
201+ var newSP = RandomSpawnpoint( );
202+ byPlayer.SetSpawnPosition(newSP.Location);
203+ #if DEBUG
204+ Logger.VerboseDebug($"New spawn Pos: '{newSP.Name}' @ {newSP.Location} ");
205+ #endif
206+ }
207+ }
208+ }
209+
210+ private void PlayerDied(IServerPlayer byPlayer, DamageSource damageSource)
211+ {
212+ if (this.CachedConfiguration.VariableSpawnpoints && this.Spawnpoints.Count > 0) {
213+
214+ var swpd = byPlayer.WorldData as ServerWorldPlayerData;
215+ if (swpd.SpawnPosition == null || KnownSpawn(swpd.SpawnPosition)) {
216+ var newSP = RandomSpawnpoint( );
217+ byPlayer.SetSpawnPosition(newSP.Location);
218+ #if DEBUG
219+ Logger.VerboseDebug( $"Changed spawn Pos: '{newSP.Name}' @ {newSP.Location} ");
220+ #endif
221+ }
222+ }
223+ }
224+
225+ private Spawnpoint RandomSpawnpoint( )
226+ {
227+ return this.Spawnpoints[random.Next(0, Spawnpoints.Count - 1)];
228+ }
229+
230+ private bool KnownSpawn(PlayerSpawnPos aSpawn)
231+ {
232+ if (this.Spawnpoints.Count > 0) {
233+ return this.Spawnpoints.Any(vsps => vsps.Location.x == aSpawn.x
234+ && vsps.Location.y == aSpawn.y
235+ && vsps.Location.z == aSpawn.z);
236+ }
237+
238+ return false;
239+ }
240+ }
241+}
242+
243+
--- a/AdminToolkit/modinfo.json
+++ b/AdminToolkit/modinfo.json
@@ -1,11 +1,11 @@
11 {
22 "type": "code",
33 "name": "Administrator's Toolkit mod",
4- "description" : "Provides misc. Admin functions;\n list admins, print & accept rules (multi-lingual) , auto-backup...",
4+ "description" : "Provides misc. Admin functions;\n admin listing, rules display (multi-lingual), auto-backup & more...",
55 "authors": ["Melchior", ],
6- "version": "0.3.5",
6+ "version": "0.3.6",
77 "dependencies": {
8- "game": "1.12.4"
8+ "game": "1.13.0"
99 },
1010 "requiredonclient":false,
1111 "website": "https://osdn.net/users/melchior/pf/admintoolkit/"