Как сообразить таймер после срабатывания функции с последующей его проверкой C#?
Есть плагин написанный на C# (это для сервера игры Rust Legacy Oxide)
using System.Collections.Generic;
using System;
using System.Reflection;
using System.Data;
using UnityEngine;
using Oxide.Core;
using RustExtended;
using Oxide.Core.Plugins;
using RustProto;
namespace Oxide.Plugins
{
[Info("CallAirDrop", "XBOCT", "1.0.2")]
[Description("Вызов дропа игроками за валюту")]
class CallAirDrop : RustLegacyPlugin
{
const float AirCallTime = 300f;//Время обновления до следующего вызова самолета
NetUser cachedUser;
string cachedSteamid;
string cachedReason;
string cachedName;
Vector3 cachedPos;
string chatName = "MegaPUB";
static string calledAirdrop = "Самолёт уже летит...";
static string airdropPlayer = "Дроп упадет возле [color red]{0}";
static string wrongarguments = "Что то не правильно написал, или такого игрока нет";
Dictionary<ulong, DateTime> players = new Dictionary<ulong, DateTime>();
void LoadDefaultConfig() { }
private void CheckCfg<T>(string Key, ref T var)
{
if (Config[Key] is T)
var = (T)Config[Key];
else
Config[Key] = var;
}
void Init()
{
CheckCfg<string>("Messages: Called 1 airdrop", ref calledAirdrop);
CheckCfg<string>("Messages: Airdrop on player position", ref airdropPlayer);
CheckCfg<string>("Messages: Wrong Arguments", ref wrongarguments);
SaveConfig();
}
[ChatCommand("air")] //Команда вызова
void cmdChatBan(NetUser netuser, string command, string[] args)
{
ulong money = RustExtended.Economy.GetBalance(netuser.userID);
// Меню информации
if(args.Length == 0) {
rust.SendChatMessage(netuser, chatName, "[COLOR#00BFFF]Вызов [COLOR#d9ae04]Самолета с лутом[COLOR#00BFFF]:");
rust.SendChatMessage(netuser, chatName, "➩[COLOR#00BFFF]/air map Случайное место - [COLOR#FFFFFF]Цена: 10 000 Р");
rust.SendChatMessage(netuser, chatName, "➩[COLOR#00BFFF]/air me Вызвать себе - [COLOR#FFFFFF]Цена: 50 000 Р");
rust.SendChatMessage(netuser, chatName, "➩[COLOR#00BFFF]/air [COLOR#FFFFFF][ник] [COLOR#00BFFF]Вызвать игроку - [COLOR#FFFFFF]Цена: 75 000 Р");
return;
}
// Случайную точку
if (args.Length == 1 && args[0].ToString() == "map")
{
if (money < 10000)
{
ulong ost = 10000 - money;
rust.SendChatMessage(netuser, "[COLOR#00BFFF]Вам не хватает: [COLOR#d9ae04]" + ost + "[COLOR#00BFFF]. У вас: [COLOR#17c90e]" + money);
Puts(netuser + "Попытался вызвать случайный дроп. Не хватает: " + ost + ". Денег всего: " + money);
return;
} else {
RustExtended.Economy.BalanceSub(netuser.userID, 10000);
SendReply(netuser, calledAirdrop); SupplyDropZone.CallAirDrop(); return;
Puts(netuser + " вызвал дроп в случайную точку. Денег осталось: " +money);
}
}
// Вызвать себе
if (args.Length == 1 && args[0].ToString() == "me")
{
if (money < 50000)
{
ulong ost = 50000 - money;
rust.SendChatMessage(netuser, "[COLOR#00BFFF]Вам не хватает: [COLOR#d9ae04]" + ost + "[COLOR#00BFFF]. У вас: [COLOR#17c90e]" + money);
Puts(netuser + "Попытался вызвать дроп себе. Не хватает: " + ost + ". Денег всего: " + money);
return;
} else {
RustExtended.Economy.BalanceSub(netuser.userID, 50000);
cachedPos = netuser.playerClient.lastKnownPosition;
if(cachedPos != default(Vector3))
{
SupplyDropZone.CallAirDropAt(cachedPos);
SendReply(netuser, string.Format(airdropPlayer, cachedPos.ToString(), netuser.playerClient.userName.ToString()));
Puts(netuser + " вызвал себе дроп. Денег осталось: " +money);
}
}
}
// Вызвать игроку
if (money < 75000)
{
ulong ost = 75000 - money;
rust.SendChatMessage(netuser, "[COLOR#00BFFF]Вам не хватает: [COLOR#d9ae04]" + ost + "[COLOR#00BFFF]. У вас: [COLOR#17c90e]" + money);
Puts(netuser + "Попытался вызвать дроп себе. Не хватает: " + ost + ". Денег всего: " + money);
return;
} else {
RustExtended.Economy.BalanceSub(netuser.userID, 75000);
NetUser targetuser = rust.FindPlayer(args[0]);
if (targetuser != null)
{
cachedPos = targetuser.playerClient.lastKnownPosition;
if(cachedPos != default(Vector3))
{
SupplyDropZone.CallAirDropAt(cachedPos);
SendReply(netuser, string.Format(airdropPlayer, cachedPos.ToString(), targetuser.playerClient.userName.ToString()));
Puts(netuser + " вызвал дроп для " + targetuser + ". Денег осталось: " +money);
}
return;
} else {
SendReply(netuser, wrongarguments);
}
}
}
}
Я в C# вообще дуб, бдубом. Этот плагин был сделан мной на основе другого плагина, я не использую visual studio, а отлаживаю плагины прямо на сервере, благо консоль выдаст ошибку если что то не так.
Пытаюсь встроить таймер в эту систему, таким образом, что бы после каждого вызова cmdChatBan при чем для каждого его аргумента отдельно запускался таймер и шла проверка на его истечение, если истек то команду можно использовать повторно, если нет выводить об этом сообщение в саму игру таким образом rust.SendChatMessage(netuser, "Самолет заправляется, ждите еще: "+TimeSpan.FromMinutes(AirCallTime));.
Из другого плагина скопировал переменную const float AirCallTime = 300f; в которой указано время в секундах, так же из того же плагина я скопировал это Dictionary<ulong, DateTime> players = new Dictionary<ulong, DateTime>(); так как считаю, что без него мне не обойтись.
Так как блокировать команду нужно всем игрокам, из того же вспомогательного плагина копирую еще код
foreach (var playerClient in PlayerClient.All)
{
if (!players.ContainsKey(playerClient.userID))
{
players.Add(playerClient.userID, DateTime.Now);
rust.SendChatMessage(NetUser.FindByUserID(playerClient.userID), ChatName, $"[COLOR#FF0000]Вам заблокированы команды /{String.Join(", /", BlockedCommands.Concat(BlockedPluginCommands).ToArray())} на {AirCallTime} секунд");
}
else
{
if (DateTime.Now - players[playerClient.userID] >= TimeSpan.FromSeconds(AirCallTime))
{
rust.SendChatMessage(NetUser.FindByUserID(playerClient.userID), ChatName, $"[COLOR#FF0000]Вам заблокированы команды /{String.Join(", /", BlockedCommands.Concat(BlockedPluginCommands).ToArray())} на {AirCallTime} секунд");
}
players[playerClient.userID] = DateTime.Now;
}
}
Естественно все текста перепишу, просто не могу понять, как совместить сие чудо? Или может есть вариант попроще?
(Вкратце, возможно более понятней: плагин написанный на C# который я целиком выложил выше, был мною переделан из другого который лежал на github, смысл его работы в том, что любой игрок на сервере может прописать команду /air при чем с аргументами '/air map', '/air me', '/air <ник другого игрока>', все было бы хорошо, игроки беспощадно пользуются данными командами тем самым нагружая сервер и что бы их ограничить, пытаюсь втулить сюда ограничение на вызов по времени, если кто то из игроков вызвал любую из команд, команда сразу блокируется для всех игроков на время указанное в константе)
З.Ы. Сильно не пинайте за всю эту ахинею, делаю все что могу, но получается пока что лишь самая малость. upd:рабочий плагин с таймером
using System.Collections.Generic;
using System;
using System.Reflection;
using UnityEngine;
using Oxide.Core;
using System.Collections;
using RustExtended;
namespace Oxide.Plugins
{
[Info("MathEvent", "XBOCT", "1.3.0")]
[Description("Математический ивент в чате с наградой")]
class MathEvent : RustLegacyPlugin
{
float repeatTime = 300f;//Ивент каждые * секнуда (f после числа обязательно)
float timeForAnswer = 15f;//Время для ответа (f после числа обязательно)
int minReward = 500;//Минимальная награда
int maxReward = 2000;//Максимальная награда
string ChatName = "MegaPUB";//Префикс в чате
int TrueAnswer;
int Reward;
bool eventRunning = false;
void Loaded()
{
timer.Repeat(repeatTime, 0, () =>
{
timer.Once(timeForAnswer, () =>
{
if (eventRunning)
{
Broadcast.MessageAll($"[COLOR#FF0000]Время для ответа вышло. Следующий ивент через {repeatTime - timeForAnswer} секунд!", ChatName);
eventRunning = false;
}
});
StartEvent();
});
}
void StartEvent()
{
eventRunning = true;
int number_1 = Core.Random.Range(1, 500);
int number_2 = Core.Random.Range(1, 500);
Reward = Core.Random.Range(minReward, maxReward);
TrueAnswer = number_1 + number_2;
string text = $"[COLOR#FF0000][COLOR#FFFF00]Сколько будет {number_1} + {number_2}? Победитель получит [COLOR#00FF00]{Reward} Р[COLOR#FFFF00] за правильный ответ!";
Broadcast.MessageAll(text, ChatName);
}
bool OnPlayerChat(NetUser netUser, string message)
{
if (eventRunning && message.Length < 5)
{
int answer;
try
{
answer = Int32.Parse(message);
}
catch
{
return false;
}
if (answer == TrueAnswer)
{
eventRunning = false;
string text = $"[COLOR#FF0000]{netUser.user.displayname_} [COLOR#FFFF00]дал правильный ответ [COLOR#FF0000]{TrueAnswer} [COLOR#FFFF00]и получает [COLOR#00FF00]{Reward} Р[COLOR#FFFF00] на свой счет!";
Broadcast.MessageAll(text, ChatName);
ulong reward = (ulong) Reward;
Economy.Get(netUser.userID).Balance += reward;
return true;
}
}
return false;
}
}
}
Ответы (1 шт):
Вот вариант с таймером и очередью.
private readonly Queue<Vector3> dropQueue = new Queue<Vector3>();
void Loaded()
{
timer.Repeat(1f, 0, () =>
{
if (dropQueue.Count > 0)
{
Vector3 pos = dropQueue.Dequeue();
if (pos != default(Vector3))
SupplyDropZone.CallAirDropAt(pos);
else
SupplyDropZone.CallAirDrop();
}
});
}
В остальном коде замените:
SupplyDropZone.CallAirDropAt(cachedPos)наdropQueue.Enqueue(cachedPos)SupplyDropZone.CallAirDrop()наdropQueue.Enqueue(default(Vector3))