using GTANetworkAPI; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; using ReallifeGamemode.Database.Entities; using ReallifeGamemode.Database.Models; using ReallifeGamemode.Server.Extensions; using ReallifeGamemode.Server.Services; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ReallifeGamemode.Server.Managers { public class HouseManager : Script { private static readonly Dictionary houseMarkers = new Dictionary(); private static readonly Dictionary houseLabels = new Dictionary(); private static readonly Dictionary houseColShapes = new Dictionary(); private static readonly Dictionary houseBlips = new Dictionary(); private static readonly Dictionary> playerInColShape = new Dictionary>(); public static async void LoadHouses() { using (var dbContext = new DatabaseContext()) { List houses = await dbContext.Houses.Include(h => h.Owner).ToListAsync(); foreach (House house in houses) { LoadHouse(house, true); } } } public static async void ReloadAllHouses() { using (var dbContext = new DatabaseContext()) { foreach (House house in await dbContext.Houses.Include(h => h.Owner).ToListAsync()) { RemoveHouse(house); LoadHouse(house, false); } } } public static House GetNearHouse(Vector3 position, DatabaseContext dbContext = null) { if (dbContext == null) { using (dbContext = new DatabaseContext()) { return dbContext.Houses.Where(h => h.Position.DistanceTo(position) <= 5f).Include(h => h.Owner).OrderBy(h => h.Position.DistanceTo(position)).FirstOrDefault(); } } else { return dbContext.Houses.Where(h => h.Position.DistanceTo(position) <= 5f).Include(h => h.Owner).OrderBy(h => h.Position.DistanceTo(position)).FirstOrDefault(); } } public void AddHouse(string type, int price, Vector3 position) { using (var dbContext = new DatabaseContext()) { var house = new House() { Price = price, Type = type, X = position.X, Y = position.Y, Z = position.Z }; dbContext.Houses.Add(house); dbContext.SaveChanges(); LoadHouse(house); } } public static House GetHouseById(int id, DatabaseContext dbContext = null) { if (dbContext == null) { using (dbContext = new DatabaseContext()) { return dbContext.Houses.Where(h => h.Id == id).Include(h => h.Owner).FirstOrDefault(); } } else { return dbContext.Houses.Where(h => h.Id == id).Include(h => h.Owner).FirstOrDefault(); } } public static void LoadHouse(House house, bool loadUser = true) { if (loadUser) house = house.Refresh(); playerInColShape[house.Id] = new List(); houseMarkers[house.Id] = NAPI.Marker.CreateMarker(MarkerType.VerticalCylinder, house.Position.Subtract(new Vector3(0, 0, 1.7)), new Vector3(), new Vector3(), 1.6f, new Color(255, 255, 255)).Handle; string text = $"~g~Zum Verkauf\n~s~{house.Type}\nPreis: ~y~{(house.Price == 0 ? "~r~Nicht verkäuflich" : house.Price.ToMoneyString())}"; if (house.OwnerId != null) { text = $"{house.Type}\n~s~Besitzer: ~y~{house.Owner.Name}"; if (house.RentalFee != 0) { text += $"\n~s~Mietpreis: ~g~{house.RentalFee.ToMoneyString()}"; } } else { //houseBlips[house.Id] = NAPI.Blip.CreateBlip(40, house.Position, 0.7f, 11, "Haus", shortRange: true); too many blips } houseLabels[house.Id] = NAPI.TextLabel.CreateTextLabel(text, house.Position, 10f, 1f, 0, new Color(255, 255, 255)); if (house.Price != 0) { houseColShapes[house.Id] = NAPI.ColShape.CreateCylinderColShape(house.Position.Subtract(new Vector3(0, 0, 2)), 2.0f, 5f); houseColShapes[house.Id].Entity().OnEntityEnterColShape += HouseManager_OnEntityEnterColShape; houseColShapes[house.Id].Entity().OnEntityExitColShape += HouseManager_OnEntityExitColShape; } } private static void HouseManager_OnEntityExitColShape(ColShape colShape, Player client) { if (!client.IsLoggedIn() || client.IsInVehicle) return; if (!houseColShapes.ContainsValue(colShape.Handle)) { return; } int houseId = houseColShapes.Where(p => p.Value.Value == colShape.Handle.Value).FirstOrDefault().Key; playerInColShape[houseId].Remove(client); client.TriggerEvent("SERVER:CloseHouseMenu"); } private static void HouseManager_OnEntityEnterColShape(ColShape colShape, Player client) { if (!client.IsLoggedIn() || client.IsInVehicle) return; if (!houseColShapes.ContainsValue(colShape.Handle)) { return; } int houseId = houseColShapes.Where(p => p.Value.Value == colShape.Handle.Value).FirstOrDefault().Key; playerInColShape[houseId].Add(client); House house = GetHouseById(houseId); User user = client.GetUser(); client.TriggerEvent("SERVER:ShowHouseMenu"); SendPlayerHouseData(client, house); } private static void SendPlayerHouseData(Player player, House house) { User user = player.GetUser(); var userHouseStatus = -1; using (var dbContext = new DatabaseContext()) { if (house.OwnerId == null) userHouseStatus = 0; else if (house.OwnerId == user?.Id) userHouseStatus = 1; else if (dbContext.HouseRentals.Where(h => h.HouseId == house.Id && h.UserId == user.Id).Count() == 1) userHouseStatus = 2; var rentals = dbContext.HouseRentals.Where(h => h.HouseId == house.Id).Include(h => h.User).Select(h => h.User.Name).ToList(); var newHouse = new { OwnerName = house.Owner?.Name, house.RentalFee, house.Price, house.Type, Rentals = rentals }; player.TriggerEvent("SERVER:SetHouseData", JsonConvert.SerializeObject(newHouse), userHouseStatus); } } public static void RemoveHouse(House house) { if (houseMarkers.ContainsKey(house.Id)) { houseMarkers[house.Id].Entity().Delete(); houseMarkers.Remove(house.Id); } if (houseLabels.ContainsKey(house.Id)) { houseLabels[house.Id].Entity().Delete(); houseLabels.Remove(house.Id); } if (houseColShapes.ContainsKey(house.Id)) { houseColShapes[house.Id].Entity().Delete(); houseColShapes.Remove(house.Id); } if (houseBlips.ContainsKey(house.Id)) { houseBlips[house.Id].Entity().Delete(); houseBlips.Remove(house.Id); } foreach (Player client in playerInColShape[house.Id]) { client.TriggerEvent("SERVER:CloseHouseMenu"); } } [RemoteEvent("CLIENT:House_BuyHouse")] public void HouseManagerBuyHouseEvent(Player player) { using (var dbContext = new DatabaseContext()) { User user = player.GetUser(dbContext); if (user.HouseId != null) { ChatService.ErrorMessage(player, "Du kann nicht mehrere Häuser besitzen"); return; } House house = GetNearHouse(player.Position, dbContext); var userBank = user.BankAccount; if (userBank.Balance < house.Price) { ChatService.ErrorMessage(player, $"Du hast nicht genug Geld für das Haus ({house.Price.ToMoneyString()})"); return; } house.Owner = user; user.House = house; userBank.Balance -= house.Price; dbContext.SaveChanges(); RemoveHouse(house); LoadHouse(house); } } [RemoteEvent("CLIENT:House_SetRentalFee")] public void HouseManagerSetRentalFeeEvent(Player player, int rentalFee) { using (var dbContext = new DatabaseContext()) { User user = player.GetUser(dbContext); if (user.HouseId == null) { ChatService.ErrorMessage(player, "Du besitzt kein Haus"); return; } House house = GetHouseById(user.HouseId.Value, dbContext); if (DateTime.Now - house.LastRentSetTime < TimeSpan.FromDays(7)) { DateTime newPossibility = house.LastRentSetTime.AddDays(7); string dateStr = newPossibility.ToLongDateString(); string timeStr = newPossibility.ToShortTimeString(); player.SendNotification( $"~r~Die Miete wurde in den letzten 7 Tagen schon verändert. Die nächste Änderung kann am {dateStr} um {timeStr} Uhr geändert werden."); return; } if (rentalFee < 0) { player.SendNotification("~r~Die Miete darf kein negativer Betrag sein!"); return; } house.LastRentSetTime = DateTime.Now; house.RentalFee = rentalFee; dbContext.SaveChanges(); player.SendNotification($"Der Mietpreis wurde auf ~g~{rentalFee.ToMoneyString()}~s~ gesetzt"); RemoveHouse(house); LoadHouse(house); } } [RemoteEvent("CLIENT:House_CancelUserRental")] public void HouseManagerCancelUserRentalEvent(Player player, string userName) { using (var dbContext = new DatabaseContext()) { User user = player.GetUser(dbContext); if (user.HouseId == null) { ChatService.ErrorMessage(player, "Du besitzt kein Haus"); return; } User target = dbContext.Users.Where(u => u.Name == userName).FirstOrDefault(); if (target == null) { player.SendNotification("~r~Dieser Spieler wurde nicht gefunden."); return; } House house = GetHouseById(user.HouseId.Value, dbContext); HouseRental rental = dbContext.HouseRentals.Where(h => h.HouseId == house.Id && h.UserId == target.Id).FirstOrDefault(); if (rental == null) { player.SendNotification("~r~Der Spieler ist nicht in deinem Haus eingemietet"); return; } dbContext.HouseRentals.Remove(rental); dbContext.SaveChanges(); target.Player?.SendNotification($"~y~{player.Name}~s~ hat deinen Mietvertrag ~g~gekündigt~s~."); player.SendNotification("Du hast dem Spieler ~y~" + target.Name + "~s~ den Mietvertrag gekündigt."); SendPlayerHouseData(player, house); } } [RemoteEvent("CLIENT:House_RentInHouse")] public void HouseManagerRentInHouseEvent(Player player) { using (var dbContext = new DatabaseContext()) { User user = player.GetUser(dbContext); House house = GetNearHouse(player.Position, dbContext); if (house == null) { ChatService.ErrorMessage(player, "In deiner Nähe ist kein Haus"); return; } HouseRental newRental = new HouseRental { HouseId = house.Id, UserId = user.Id }; dbContext.HouseRentals.Add(newRental); dbContext.SaveChanges(); player.SendNotification("~g~Du hast dich in das Haus eingemietet"); house.User?.SendNotification($"~y~{player.Name}~s~ hat sich in dein Haus eingemietet."); SendPlayerHouseData(player, house); } } [RemoteEvent("CLIENT:House_CancelOwnRental")] public void HouseManagerCancelOwnRentalEvent(Player player) { using (var dbContext = new DatabaseContext()) { User user = player.GetUser(dbContext); House house = GetNearHouse(player.Position, dbContext); if (house == null) { ChatService.ErrorMessage(player, "In deiner Nähe ist kein Haus"); return; } HouseRental rental = dbContext.HouseRentals.Where(h => h.HouseId == house.Id && h.UserId == user.Id).FirstOrDefault(); if (rental == null) { player.SendNotification("~r~Du bist nin diesem Haus nicht eingemietet"); return; } dbContext.HouseRentals.Remove(rental); dbContext.SaveChanges(); player.SendNotification("~g~Du hast den Mietvertrag gekündigt."); house.User?.SendNotification($"~y~{player.Name}~s~ hat seinen Mietvertrag gekündigt."); RemoveHouse(house); LoadHouse(house); SendPlayerHouseData(player, house); } } [RemoteEvent("CLIENT:House_SellHouse")] public void HouseManagerSellHouseEvent(Player player) { using (var dbContext = new DatabaseContext()) { User user = player.GetUser(dbContext); if (user.HouseId == null) { ChatService.ErrorMessage(player, "Du besitzt kein Haus"); return; } House house = GetHouseById(user.HouseId.Value, dbContext); house.OwnerId = null; user.HouseId = null; var backMoney = (int)(house.Price * 0.4); ChatService.SendMessage(player, "Du bekommst vom Hausverkauf ~g~" + backMoney.ToMoneyString() + "~s~ zurück."); user.BankAccount.Balance += backMoney; dbContext.SaveChanges(); player.SendChatMessage("!{#81F7BE}* Du hast dein Haus verkauft."); RemoveHouse(house); LoadHouse(house); SendPlayerHouseData(player, house); } } } }