using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Timers; using GTANetworkAPI; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using ReallifeGamemode.Database.Entities; using ReallifeGamemode.Database.Models; using ReallifeGamemode.Server.Extensions; using ReallifeGamemode.Server.Inventory.Interfaces; using ReallifeGamemode.Server.Inventory.Items; using ReallifeGamemode.Server.Services; using ReallifeGamemode.Server.Util; namespace ReallifeGamemode.Server.Managers { public class HanfManager : BaseScript { /// /// Punkte zum Samen kaufen /// private readonly static List _seedsBuyPoints = new List(); /// /// Aktueller Samen-Preis /// public static int SEED_PRICE = 50; /// /// Wie viele Joints man aus einem Cannabis bekommt /// public static int CANNABIS_TO_JOINT_RATIO = 3; /// /// Flag, ob der Verarbeiter aktuell benutzt wird /// private static bool _manufacturerCurrentlyUsed = false; /// /// Marihuana -> Joint /// private readonly static Vector3 _jointManufacturerPoint = new Vector3(-127.726105, 1921.5142, 197.31104); /// /// Animations-ID des Verarbeitens /// private const string _manufacturerAnim = "manufacturJoint"; /// /// Data-Key, ob der Spieler grade eine Pflanze anpflanzt /// private const string PLAYER_CURRENTLY_PLANTING_DATA_KEY = "isPlantingCannabis"; /// /// Ab welcher Zeit Pflanzen verwelken /// private static readonly TimeSpan MAX_PLANT_TIME = TimeSpan.FromHours(6); private static readonly TimeSpan MIN_PLANT_TIME_TO_HARVEST = TimeSpan.FromHours(4); /// /// Timer der den Status des Verarbeiters zurücksetzt /// private static Timer _manufacturerDoneTimer = new Timer(TimeSpan.FromSeconds(10).TotalMilliseconds); /// /// Zufallsgenerator für weibliche Pflanze und erhaltenes Cannabis /// private static Random _random = new Random(); private static List _currentCannabisData = new List(); static HanfManager() { _manufacturerDoneTimer.Elapsed += ManufacturerDoneTimerCallback; } /// /// Ladefunktion zum /// public static void Load() { _seedsBuyPoints.Add(new Vector3(-30.21876, -585.3222, 17.917326)); _seedsBuyPoints.Add(new Vector3(-680.89386, -634.6783, 25.29923)); _seedsBuyPoints.Add(new Vector3(-1310.743, -608.9064, 29.382874)); _seedsBuyPoints.Add(new Vector3(-758.6156, -1595.2686, 6.302392)); _seedsBuyPoints.Add(new Vector3(-441.0504, 1595.4435, 358.4195)); ColShape colShape = null; foreach (Vector3 buyPoint in _seedsBuyPoints) { colShape = NAPI.ColShape.CreateSphereColShape(buyPoint, 20.0f); colShape.OnEntityEnterColShape += OnSeedBuyRangeColShapeEnter; } UpdateHanfWorldData(new DatabaseContext()); Timer updateHanfDataTimer = new Timer(TimeSpan.FromMinutes(1).TotalMilliseconds); updateHanfDataTimer.Elapsed += UpdateHanfDataTimer_Elapsed; updateHanfDataTimer.Start(); } private static void UpdateHanfDataTimer_Elapsed(object sender, ElapsedEventArgs e) { using var dbContext = new DatabaseContext(); UpdateHanfWorldData(dbContext); } private static void OnSeedBuyRangeColShapeEnter(ColShape colShape, Player player) { if (!player.IsLoggedIn()) { return; } var user = player.GetUser(); if (user?.Faction?.StateOwned == true) { return; } ChatService.SendMessage(player, $"Fremder sagt: Pssst.. Willst du Samen kaufen?"); } internal static bool IsPlayerNearSeedBuyPoint(Player player) { return _seedsBuyPoints.Any(p => player.Position.DistanceTo(p) <= 2.5f); } internal static bool IsPlayerNearJointManufacturer(Player player) { return _jointManufacturerPoint.DistanceTo(player.Position) <= 2.5f; } internal static void StartCannabisPlanting(Player player) { player.ToggleInventory(InventoryToggleOption.HIDE); if (!player.IsAlive()) { return; } var dbContext = new DatabaseContext(); var user = player.GetUser(dbContext); if (user.Faction?.StateOwned ?? false) { player.SendNotification("~r~Du darfst keine Hanfsamen einfplanzen"); return; } if (player.HasData(PLAYER_CURRENTLY_PLANTING_DATA_KEY) && player.GetData(PLAYER_CURRENTLY_PLANTING_DATA_KEY)) { player.SendNotification("~r~Du pflanzt aktuell schon einen Hanfsamen ein"); return; } player.SetData(PLAYER_CURRENTLY_PLANTING_DATA_KEY, true); player.TriggerEvent("SERVER:Hanf_StartPlanting"); } [RemoteEvent("CLIENT:Hanf_PlantHanf")] public void HanfManagerPlantHanf(Player player, float x, float y, float z) { player.ResetData(PLAYER_CURRENTLY_PLANTING_DATA_KEY); IItem cannabisSeedItem = InventoryManager.GetItem(); UserItem userCannabisSeedsItem = InventoryManager.UserHasThisItem(player, cannabisSeedItem.Id); if (userCannabisSeedsItem == null) { player.SendNotification("~r~Du hast keine Samen mehr"); return; } logger.LogInformation("Player {0} planted a cannabis plant at x: {1}, y: {2}, z: {3}", player.Name, x, y, z); using var dbContext = new DatabaseContext(); var user = player.GetUser(dbContext); InventoryManager.RemoveUserItem(user, userCannabisSeedsItem, 1); CannabisPlant newPlant = new CannabisPlant() { X = x, Y = y, Z = z, PlantedBy = user, PlantDate = DateTime.Now, }; dbContext.CannabisPlants.Add(newPlant); dbContext.SaveChanges(); UpdateHanfWorldData(dbContext); } public static void UpdateHanfWorldData(DatabaseContext dbContext) { var activePlants = dbContext.CannabisPlants.Where(p => !p.Harvested).Select(p => new CannabisData() { Id = p.Id, Time = p.PlantDate, X = p.X, Y = p.Y, Z = p.Z }).ToList(); _currentCannabisData = activePlants; NAPI.Pools.GetAllPlayers().ForEach(p => { UpdateHanfForPlayer(p, activePlants); }); } public async static void UpdateHanfForPlayer(Player player, List cannabisData = null) { cannabisData ??= _currentCannabisData; var x = await NAPI.Task.WaitForMainThread(); player.TriggerEvent("SERVER:Hanf_UpdateHanfData", JsonConvert.SerializeObject(cannabisData)); } [RemoteEvent("CLIENT:Hanf_BuySeeds")] public void HanfManagerBuySeeds(Player player, int amount) { if (!player.IsLoggedIn()) { return; } using var dbContext = new DatabaseContext(); var user = player.GetUser(dbContext); IItem seedItem = InventoryManager.GetItem(); var newAmount = seedItem.Gewicht * amount; if (!InventoryManager.CanPlayerHoldMoreWeight(player, newAmount)) { player.TriggerEvent("~r~So viele Samen passen nicht mehr in deine Hosentasche"); return; } var price = amount * SEED_PRICE; if (user.Handmoney < price) { player.SendNotification("~r~Du hast nicht genug Geld dafür"); return; } logger.LogInformation("Player {0} bought {1} cannabis seeds for {2} dollars (price per seed: {3})", player.Name, amount, price, SEED_PRICE); // <-- WICHTIG LOGS user.Handmoney -= price; dbContext.SaveChanges(); InventoryManager.AddItemToInventory(player, seedItem.Id, amount); player.SendNotification($"Du hast {amount} Hanfsamen gekauft"); } [RemoteEvent("CLIENT:Hanf_HarvestHanf")] public void HanfManagerHarvestHanf(Player player, long hanfId) { if (!player.IsLoggedIn()) { return; } using var dbContext = new DatabaseContext(); User user = player.GetUser(dbContext); CannabisPlant plant = dbContext.CannabisPlants.Find(hanfId); if (plant == null) { logger.LogError("Player {0} tried to harvest cannabis plant {1} but it was not found in database", player.Name, hanfId); } if (user.Faction?.StateOwned == true && !(user.FactionId == 3 && player.IsDuty())) { player.SendNotification("~r~Du kannst kein Hanf ernten"); return; } if (plant.Harvested) { return; } plant.Harvested = true; if (user.FactionId != 3) // Zivi / Gangmember erntet ab { bool isPlantRotten = DateTime.Now - plant.PlantDate > MAX_PLANT_TIME; if (isPlantRotten) { player.SendNotification("~r~Die Pflanze ist leider verrottet"); } else { bool isPlantReadyToHarvest = DateTime.Now - plant.PlantDate > MIN_PLANT_TIME_TO_HARVEST; if (!isPlantReadyToHarvest) // Wenn die Pflanze noch nicht ausgewachsen ist { bool getSeedBack = _random.Next(0, 2) == 1; // 50% Chance if(getSeedBack) { IItem cannabisSeedItem = InventoryManager.GetItem(); InventoryManager.AddItemToInventory(player, cannabisSeedItem.Id, 1); player.SendNotification("~g~Du konntest den Samen wieder ausgraben"); } else { player.SendNotification("~r~Du konntest den Samen leider nicht wieder ausgraben"); } } else { bool isFemalePlant = _random.Next(0, 10) + 1 <= 8; // 80% Chance dass es eine weibliche Pflanze ist if (isFemalePlant) { int cannabisAmount = _random.Next(4, 10) + 1; // zwischen 5 und 10g Cannabis IItem cannabisItem = InventoryManager.GetItem(); var newWeight = cannabisAmount * cannabisItem.Gewicht; if (!InventoryManager.CanPlayerHoldMoreWeight(player, newWeight)) { int restWeightPlayerCanHold = InventoryManager.MAX_USER_INVENTORY - InventoryManager.GetUserInventoryWeight(player); cannabisAmount = restWeightPlayerCanHold / cannabisItem.Gewicht; player.SendNotification("~o~Warnung:~s~ Du hast nicht das komplette Cannabis der Pflanze erhalten, da dein Inventar voll ist"); } player.SendNotification("~g~" + cannabisAmount + "g Cannabis geerntet"); InventoryManager.AddItemToInventory(player, cannabisItem.Id, cannabisAmount); } else { player.SendNotification("~r~Du hast die falschen Samen eingesät und keinen Ertrag aus dieser Pflanze erhalten"); } } } } else // FIB erntet ab { } dbContext.SaveChanges(); UpdateHanfWorldData(dbContext); } internal static void BuildJointsFromCannabis(Player player) { if (player.HasAnimation(_manufacturerAnim) || _manufacturerCurrentlyUsed) { return; } using var dbContext = new DatabaseContext(); var user = player.GetUser(dbContext); var userItems = InventoryManager.GetUserItems(player, dbContext); IItem cannabisItem = InventoryManager.GetItem(); IItem jointItem = InventoryManager.GetItem(); var addWeight = jointItem.Gewicht * CANNABIS_TO_JOINT_RATIO - cannabisItem.Gewicht; if (!InventoryManager.CanPlayerHoldMoreWeight(player, addWeight)) { player.SendNotification("~r~Für die Verarbeitung hast du nicht genug Platz im Rucksack"); return; } UserItem userCannabisItem = userItems.Where(i => i.ItemId == cannabisItem.Id).FirstOrDefault(); if (userCannabisItem == null) { player.SendNotification("~r~Du hast kein Cannabis dabei"); return; } _manufacturerCurrentlyUsed = true; _manufacturerDoneTimer.Start(); player.SyncAnimation(_manufacturerAnim); InventoryManager.RemoveUserItem(user, userCannabisItem, 1); InventoryManager.AddItemToInventory(player, jointItem.Id, CANNABIS_TO_JOINT_RATIO); player.SendNotification($"Du hast 1 Cannabis in {CANNABIS_TO_JOINT_RATIO} Joints verarbeitet"); NAPI.ClientEvent.TriggerClientEventInRange(player.Position, 100.0f, "SERVER:Hanf_PlayManufacturerAnim", _manufacturerAnim); } private static void ManufacturerDoneTimerCallback(object sender, EventArgs args) { _manufacturerDoneTimer.Stop(); _manufacturerCurrentlyUsed = false; } } }