using GTANetworkAPI; using ReallifeGamemode.Database.Entities; using ReallifeGamemode.Database.Models; using ReallifeGamemode.Server.Extensions; using ReallifeGamemode.Server.Util; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Timers; namespace ReallifeGamemode.Server.Managers { public class VehicleManager : Script { private static readonly List _enabledMods = new List() { "ninef", "ninef2", "blista", "asea", "asea2", "boattrailer", "bus", "armytanker", "armytrailer", "armytrailer2", "freighttrailer", "coach", "airbus", "asterope", "airtug", "ambulance", "barracks", "barracks2", "baller", "baller2", "bjxl", "banshee", "benson", "bfinjection", "biff", "blazer", "blazer2", "blazer3", "bison", "bison2", "bison3", "boxville", "boxville2", "boxville3", "bobcatxl", "bodhi2", "buccaneer", "buffalo", "buffalo2", "bulldozer", "bullet", "blimp", "burrito", "burrito2", "burrito3", "burrito4", "burrito5", "cavalcade", "cavalcade2", "policet", "gburrito", "cablecar", "caddy", "caddy2", "camper", "carbonizzare", "cheetah", "comet2", "cogcabrio", "coquette", "cutter", "gresley", "dilettante", "dilettante2", "dune", "dune2", "hotknife", "dloader", "dubsta", "dubsta2", "dump", "rubble", "docktug", "dominator", "emperor", "emperor2", "emperor3", "entityxf", "exemplar", "elegy2", "f620", "fbi", "fbi2", "felon", "felon2", "feltzer2", "firetruk", "flatbed", "forklift", "fq2", "fusilade", "fugitive", "futo", "granger", "gauntlet", "habanero", "hauler", "handler", "infernus", "ingot", "intruder", "issi2", "Jackal", "journey", "jb700", "khamelion", "landstalker", "lguard", "manana", "mesa", "mesa2", "mesa3", "crusader", "minivan", "mixer", "mixer2", "monroe", "mower", "mule", "mule2", "oracle", "oracle2", "packer", "patriot", "pbus", "penumbra", "peyote", "phantom", "phoenix", "picador", "pounder", "police", "police4", "police2", "police3", "policeold1", "policeold2", "pony", "pony2", "prairie", "pranger", "premier", "primo", "proptrailer", "rancherxl", "rancherxl2", "rapidgt", "rapidgt2", "radi", "ratloader", "rebel", "regina", "rebel2", "rentalbus", "ruiner", "rumpo", "rumpo2", "rhino", "riot", "ripley", "rocoto", "romero", "sabregt", "sadler", "sadler2", "sandking", "sandking2", "schafter2", "schwarzer", "scrap", "seminole", "sentinel", "sentinel2", "zion", "zion2", "serrano", "sheriff", "sheriff2", "speedo", "speedo2", "stanier", "stinger", "stingergt", "stockade", "stockade3", "stratum", "sultan", "superd", "surano", "surfer", "surfer2", "surge", "taco", "tailgater", "taxi", "trash", "tractor", "tractor2", "tractor3", "graintrailer", "baletrailer", "tiptruck", "tiptruck2", "tornado", "tornado2", "tornado3", "tornado4", "tourbus", "towtruck", "towtruck2", "utillitruck", "utillitruck2", "utillitruck3", "voodoo2", "washington", "stretch", "youga", "ztype", "sanchez", "sanchez2", "scorcher", "tribike", "tribike2", "tribike3", "fixter", "cruiser", "BMX", "policeb", "akuma", "carbonrs", "bagger", "bati", "bati2", "ruffian", "daemon", "double", "pcj", "vader", "vigero", "faggio2", "hexer", "annihilator", "buzzard", "buzzard2", "cargobob", "cargobob2", "cargobob3", "skylift", "polmav", "maverick", "nemesis", "frogger", "frogger2", "cuban800", "duster", "stunt", "mammatus", "jet", "shamal", "luxor", "titan", "lazer", "cargoplane", "squalo", "marquis", "dinghy", "dinghy2", "jetmax", "predator", "tropic", "seashark", "seashark2", "submersible", "freightcar", "freight", "freightcont1", "freightcont2", "freightgrain", "tankercar", "metrotrain", "docktrailer", "trailers", "trailers2", "trailers3", "tvtrailer", "raketrailer", "tanker", "trailerlogs", "tr2", "tr3", "tr4", "trflat", "trailersmall", "velum", "adder", "voltic", "vacca", "suntrap", "submersible2", "dukes", "dukes2", "buffalo3", "dominator2", "dodo", "marshall", "blimp2", "gauntlet2", "stalion", "stalion2", "blista2", "blista3", "bifta", "speeder", "kalahari", "paradise", "btype", "jester", "turismor", "alpha", "vestra", "zentorno", "massacro", "huntley", "thrust", "rhapsody", "warrener", "blade", "glendale", "panto", "dubsta3", "pigalle", "monster", "sovereign", "innovation", "hakuchou", "furoregt", "miljet", "besra", "coquette2", "swift", "jester2", "massacro2", "ratloader2", "slamvan", "mule3", "velum2", "tanker2", "casco", "boxville4", "hydra", "insurgent", "insurgent2", "gburrito2", "technical", "dinghy3", "savage", "enduro", "guardian", "lectro", "kuruma", "kuruma2", "trash2", "barracks3", "valkyrie", "slamvan2", "swift2", "luxor2", "feltzer3", "osiris", "virgo", "windsor", "coquette3", "vindicator", "t20", "brawler", "toro", "chino", "faction", "faction2", "moonbeam", "moonbeam2", "primo2", "chino2", "buccaneer2", "voodoo", "Lurcher", "btype2", "verlierer2", "nightshade", "mamba", "limo2", "schafter3", "schafter4", "schafter5", "schafter6", "cog55", "cog552", "cognoscenti", "cognoscenti2", "baller3", "baller4", "baller5", "baller6", "toro2", "seashark3", "dinghy4", "tropic2", "speeder2", "cargobob4", "supervolito", "supervolito2", "valkyrie2", "tampa", "sultanrs", "banshee2", "btype3", "faction3", "minivan2", "sabregt2", "slamvan3", "tornado5", "virgo2", "virgo3", "nimbus", "xls", "xls2", "seven70", "fmj", "bestiagts", "pfister811", "brickade", "rumpo3", "volatus", "prototipo", "reaper", "tug", "windsor2", "lynx", "gargoyle", "tyrus", "sheava", "omnis", "le7b", "contender", "trophytruck", "trophytruck2", "rallytruck", "cliffhanger", "bf400", "tropos", "brioso", "tampa2", "tornado6", "faggio3", "faggio", "raptor", "vortex", "avarus", "sanctus", "youga2", "hakuchou2", "nightblade", "chimera", "esskey", "wolfsbane", "zombiea", "zombieb", "defiler", "daemon2", "ratbike", "shotaro", "manchez", "blazer4", "elegy", "tempesta", "italigtb", "italigtb2", "nero", "nero2", "specter", "specter2", "diablous", "diablous2", "blazer5", "ruiner2", "dune4", "dune5", "phantom2", "voltic2", "penetrator", "boxville5", "wastelander", "technical2", "fcr", "fcr2", "comet3", "ruiner3", "turismo2", "infernus2", "gp1", "ruston", "trailers4", "xa21", "caddy3", "vagner", "phantom3", "nightshark", "cheetah2", "torero", "hauler2", "trailerlarge", "technical3", "insurgent3", "apc", "tampa3", "dune3", "trailersmall2", "halftrack", "ardent", "oppressor", "vigilante", "bombushka", "alphaz1", "seabreeze", "tula", "havok", "hunter", "microlight", "rogue", "pyro", "howard", "mogul", "starling", "nokota", "molotok", "rapidgt3", "retinue", "cyclone", "visione", "z190", "viseris", "comet5", "raiden", "riata", "sc1", "autarch", "savestra", "gt500", "comet4", "neon", "sentinel3", "khanjali", "barrage", "volatol", "akula", "deluxo", "stromberg", "chernobog", "riot2", "avenger", "avenger2", "thruster", "yosemite", "hermes", "hustler", "streiter", "revolter", "pariah", "kamacho", "entity2", "cheburek", "jester3", "caracara", "hotring", "seasparrow", "flashgt", "ellie", "michelli", "fagaloa", "dominator3", "tyrant", "tezeract", "gb200", "issi3", "taipan", "blimp3", "mule4", "pounder2", "speedo4", "pbus2", "patriot2", "swinger", "terbyte", "oppressor2", "strikeforce", "menacer", "scramjet", "freecrawler", "stafford", "bruiser", "bruiser2", "bruiser3", "brutus", "brutus2", "brutus3", "cerberus", "cerberus2", "cerberus3", "clique", "deathbike", "deathbike2", "deathbike3", "deveste", "deviant", "dominator4", "dominator5", "dominator6", "impaler", "impaler2", "impaler3", "impaler4", "imperator", "imperator2", "imperator3", "issi4", "issi5", "issi6", "italigto", "monster3", "monster4", "monster5", "rcbandito", "scarab", "scarab2", "scarab3", "schlagen", "slamvan4", "slamvan5", "slamvan6", "toros", "tulip", "vamos", "zr380", "zr3802", "zr3803", "streiter2", //Mod "caracara2", "drafter", "dynasty", "emerus", "gauntlet3", "gauntlet4", "hellion", "issi7", "jugular", "krieger", "locust", "nebula", "neo", "novak", "paragon", "paragon2", "peyote2", "rrocket", "s80", "thrax", "zorrusso", "zion3", "lsfd", //Mod "lsfd2", //Mod "lsfd3", //Mod "lsfd4", //Mod "lsfd5", //Mod "lsfdtruck", //Mod "lsfdtruck2", //Mod "lsfdtruck3", //Mod "polbullet", //Mod "polbullet2", //Mod "sherbullet", //Mod "hwaybullet", //Mod "zhaba", "yosemite2", "vstr", "vagrant", "sultan2", "sugoi", "stryder", "retinue2", "rebla", "outlaw", "minitank", "komoda", "kanjo", "jb7002", "imorgon", "furia", "formula2", "formula", "everon", "asbo" }; private static readonly Dictionary _serverVehicles = new Dictionary(); private static readonly Dictionary lastPositions = new Dictionary(); private static DateTime lastSave = DateTime.UtcNow; public static void CheckEnabledMods() { foreach (var name in _enabledMods) { if (_enabledMods.Where(x => x == name).Count() != 1) { NAPI.Util.ConsoleOutput($"{name} double"); } } } public static void VehicleTimerTick() { NAPI.Pools.GetAllVehicles().ForEach(v => { Vector3 lastPosition = v.Position; if (lastPositions.ContainsKey(v.Handle)) lastPosition = lastPositions[v.Handle]; lastPositions[v.Handle] = v.Position; double distanceDriven; try { distanceDriven = v.HasSharedData("drivenDistance") ? (double)v.GetSharedData("drivenDistance") : 0D; } catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) { distanceDriven = 0; } double distance = lastPosition.DistanceTo(v.Position) / 1000.0; if (distance > 0.2) { lastPositions[v.Handle] = v.Position; return; } distanceDriven += distance; v.SetSharedData("drivenDistance", (float)distanceDriven); }); if (DateTime.UtcNow.Subtract(lastSave).Seconds >= 30) { lastSave = DateTime.UtcNow; // save to db using (var dbContext = new DatabaseContext()) { foreach (var key in lastPositions.Keys.ToList()) { Vehicle v = key.Entity(); if (v == null) continue; if (!v.HasSharedData("drivenDistance")) continue; ServerVehicle sVeh = VehicleManager.GetServerVehicleFromVehicle(v, dbContext); if (sVeh == null) continue; sVeh.DistanceDriven = (float)v.GetSharedData("drivenDistance"); } dbContext.SaveChanges(); } } } public static void AddVehicle(ServerVehicle serverVehicle, Vehicle vehicle) { if (_serverVehicles.ContainsKey(serverVehicle.Id)) { return; } if (_serverVehicles.ContainsValue(vehicle.Handle)) { return; } _serverVehicles[serverVehicle.Id] = vehicle.Handle; } internal static void DeleteVehicle(Vehicle veh) { ServerVehicle sVeh; if ((sVeh = GetServerVehicleFromVehicle(veh)) != null) { _serverVehicles.Remove(sVeh.Id); } veh.Delete(); } public static Vehicle GetVehicleFromHandle(NetHandle handle) { return NAPI.Pools.GetAllVehicles().Find(v => v.Handle == handle); } public static Vehicle GetVehicleFromId(int id) { using (var dbcontext = new DatabaseContext()) { ServerVehicle sVeh = dbcontext.ServerVehicles.Where(sV => sV.Id == id).FirstOrDefault(); return GetVehicleFromServerVehicle(sVeh); } } public static Vehicle GetVehicleFromServerVehicle(ServerVehicle serverVehicle) { if (!_serverVehicles.ContainsKey(serverVehicle.Id)) { return null; } return GetVehicleFromHandle(_serverVehicles[serverVehicle.Id]); } public static ServerVehicle GetServerVehicleFromVehicle(Vehicle veh, DatabaseContext dbContext = null) { dbContext = dbContext ?? new DatabaseContext(); foreach (KeyValuePair pair in _serverVehicles) { if (pair.Value == veh.Handle) { return dbContext.ServerVehicles.Find(pair.Key); } } return null; } public static bool IsValidHash(uint hash) { foreach (VehicleHash vh in Enum.GetValues(typeof(VehicleHash))) { if ((uint)vh == hash) return true; } foreach (string mod in _enabledMods) { if (NAPI.Util.GetHashKey(mod) == hash) return true; } return false; } [ServerEvent(Event.VehicleDeath)] public static void VehicleManagerVehicleDeath(Vehicle vehicle) { ServerVehicle serverVehicle = GetServerVehicleFromVehicle(vehicle); NAPI.Util.ConsoleOutput("VehicleDeat: Debug 1"); if (serverVehicle == null) { NAPI.Util.ConsoleOutput("VehicleDeath: Debug 2"); vehicle.Delete(); return; } NAPI.Util.ConsoleOutput("VehicleDeath: Debug 3"); Vehicle newVeh = serverVehicle.Spawn(vehicle); newVeh.Repair(); newVeh.Rotation = new Vector3(0, 0, serverVehicle.Heading); NAPI.Util.ConsoleOutput("VehicleDeath: Debug 4"); } } }