using heh; using net.luckperms.api; using NLog; using PetaPoco; using Sandbox.Game; using Sandbox.Game.Entities; using Sandbox.Game.GameSystems.BankingAndCurrency; using Sandbox.Game.Multiplayer; using Sandbox.Game.World; using Torch.API; using Torch.API.Managers; using Torch.Managers; using Torch.Server.Managers; using VRage; using VRage.Game.Entity; using VRage.Library.Utils; using VRage.ObjectBuilders; namespace Kits; public class KitManager : Manager, IKitManager { private static readonly ILogger Log = LogManager.GetCurrentClassLogger(); private readonly Config _config; [Dependency] private readonly IDbManager _dbManager = null!; [Dependency] private readonly MultiplayerManagerDedicated _multiplayerManager = null!; private IDatabase _db = null!; public KitManager(ITorchBase torchInstance, Config config) : base(torchInstance) { _config = config; } public override void Attach() { base.Attach(); _db = _dbManager.Create("kits"); MyVisualScriptLogicProvider.RespawnShipSpawned += RespawnShipSpawned; } private void RespawnShipSpawned(long shipEntityId, long playerId, string respawnShipPrefabName) { if (!MyEntities.TryGetEntityById(shipEntityId, out MyCubeGrid grid) || !Sync.Players.TryGetPlayerId(playerId, out var playerClientId) || Sync.Players.GetPlayerById(playerClientId) is not { } player) return; foreach (var kit in _config.Kits.Where(b => CanGiveRespawnKit(player, b, respawnShipPrefabName, out _))) { GiveKit(player, grid.GetFatBlocks().First(b => b is MyCargoContainer or MyCockpit).GetInventoryBase(), kit); } } public void GiveKit(MyPlayer player, MyInventoryBase inventory, string kitName) { GiveKit(player, inventory, GetKit(kitName)); } public bool CanGiveKit(MyPlayer player, string kitName, out string reason) { return CanGiveKit(player, GetKit(kitName), out reason); } public bool CanGiveRespawnKit(MyPlayer player, string kitName, string respawnName, out string reason) { return CanGiveRespawnKit(player, GetKit(kitName), respawnName, out reason); } public KitViewModel GetKit(string kitName) { return _config.Kits.First(b => b.Name == kitName); } public bool TryGetKit(string kitName, out KitViewModel? kit) { kit = _config.Kits.FirstOrDefault(b => b.Name == kitName); return kit is not null; } public void GiveKit(MyPlayer player, MyInventoryBase inventory, KitViewModel kit) { if (kit.UseCooldownMinutes > 0) { CheckTable(); _db.Insert(new PlayerCooldown {Id = player.Id.SteamId.ToString(), KitName = kit.Name, LastUsed = DateTime.Now}); } MyBankingSystem.ChangeBalance(player.Identity.IdentityId, kit.UseCost); foreach (var item in kit.Items.Where(b => b.Probability >= 1 || b.Probability < MyRandom.Instance.GetRandomFloat(0, 1))) { inventory.AddItems((MyFixedPoint)item.Amount, MyObjectBuilderSerializer.CreateNewObject(item.Id)); } Log.Info($"Given kit {kit.Name} to {player.DisplayName} ({player.Id.SteamId})"); } public bool CanGiveKit(MyPlayer player, KitViewModel kit, out string reason) { reason = string.Empty; var level = MySession.Static.GetUserPromoteLevel(player.Id.SteamId); if (level < kit.RequiredPromoteLevel || !string.IsNullOrEmpty(kit.LpPermission)) { var api = LuckPermsProvider.get(); var torchPlayer = _multiplayerManager.Players[player.Id.SteamId]; if (!api.getPlayerAdapter(typeof(IPlayer)).getPermissionData(torchPlayer).checkPermission(kit.LpPermission).asBoolean()) { reason = "Not enough rights to acquire this"; return false; } } if (kit.UseCost > 0 && kit.UseCost > MyBankingSystem.GetBalance(player.Identity.IdentityId)) { reason = "Not enough money to acquire this"; return false; } if (kit.UseCooldownMinutes <= 0) return true; var sql = Sql.Builder.Where("id = @0", player.Id.SteamId).Append("AND kit_name = @0", kit.Name); CheckTable(); var playerCooldown = _db.SingleOrDefault(sql); var cooldown = DateTime.Now - playerCooldown?.LastUsed; if (cooldown is null) return true; if (cooldown > TimeSpan.FromMinutes(kit.UseCooldownMinutes)) { _db.Delete(sql); return true; } reason = $"Next use available in {TimeSpan.FromMinutes(kit.UseCooldownMinutes) - cooldown:dd\\.hh\\:mm\\:ss}"; return false; } public bool CanGiveRespawnKit(MyPlayer player, KitViewModel kit, string respawnName, out string reason) { reason = "Invalid respawn name"; return kit.RespawnPodWildcards.Any(respawnName.Glob) && CanGiveKit(player, kit, out reason); } private void CheckTable() { _db.Execute("create table if not exists cooldown (uid INTEGER PRIMARY KEY AUTOINCREMENT, id TEXT NOT NULL, kit_name TEXT NOT NULL, last_used DATETIME NOT NULL)"); } } [TableName("cooldown")] [PrimaryKey(nameof(Uid), AutoIncrement = true)] public class PlayerCooldown { [Column] public long Uid { get; set; } [Column] public string Id { get; set; } = string.Empty; [Column] public string KitName { get; set; } = string.Empty; [Column] public DateTime LastUsed { get; set; } } public interface IKitManager : IManager { void GiveKit(MyPlayer player, MyInventoryBase inventory, string kitName); void GiveKit(MyPlayer player, MyInventoryBase inventory, KitViewModel kit); bool CanGiveKit(MyPlayer player, string kitName, out string reason); bool CanGiveKit(MyPlayer player, KitViewModel kit, out string reason); bool CanGiveRespawnKit(MyPlayer player, KitViewModel kit, string respawnName, out string reason); bool CanGiveRespawnKit(MyPlayer player, string kitName, string respawnName, out string reason); KitViewModel GetKit(string kitName); bool TryGetKit(string kitName, out KitViewModel? kit); }