using GTANetworkAPI; using ReallifeGamemode.Server.Entities; using ReallifeGamemode.Server.Models; using System; using System.Collections.Generic; using System.Linq; using System.Timers; namespace ReallifeGamemode.Server.Managers { public class VehicleManager { private static readonly List _enabledMods = new List() { "Dinghy", "Dinghy2", "Dinghy3", "Dinghy4", "Jetmax", "Marquis", "Seashark", "Seashark2", "Seashark3", "Speeder", "Speeder2", "Squalo", "Submersible", "Submersible2", "Suntrap", "Toro", "Toro2", "Tropic", "Tropic2", "Tug", "Benson", "Biff", "Cerberus", "Cerberus2", "Cerberus3", "Hauler", "Hauler2", "Mule", "Mule2", "Mule3", "Mule4", "Packer", "Phantom", "Phantom2", "Phantom3", "Pounder", "Pounder2", "Stockade", "Stockade3", "Terbyte", "Blista", "Blista2", "Blista3", "Brioso", "Dilettante", "Dilettante2", "Issi2", "Issi3", "Issi4", "Issi5", "Issi6", "Panto", "Prairie", "Rhapsody", "CogCabrio", "Exemplar", "F620", "Felon", "Felon2", "Jackal", "Oracle", "Oracle2", "Sentinel", "Sentinel2", "Windsor", "Windsor2", "Zion", "Zion2", "Bmx", "Cruiser", "Fixter", "Scorcher", "TriBike", "TriBike2", "TriBike3", "Ambulance", "FBI", "FBI2", "FireTruk", "PBus", "Police", "Police2", "Police3", "Police4", "PoliceOld1", "PoliceOld2", "PoliceT", "Policeb", "Polmav", "Pranger", "Predator", "Riot", "Riot2", "Sheriff", "Sheriff2", "Akula", "Annihilator", "Buzzard", "Buzzard2", "Cargobob", "Cargobob2", "Cargobob3", "Cargobob4", "Frogger", "Frogger2", "Havok", "Hunter", "Maverick", "Savage", "Seasparrow", "Skylift", "volito", "volito2", "Swift", "Swift2", "Valkyrie", "Valkyrie2", "Volatus", "Bulldozer", "Cutter", "Dump", "Flatbed", "Guardian", "Handler", "Mixer", "Mixer2", "Rubble", "TipTruck", "TipTruck2", "APC", "Barracks", "Barracks2", "Barracks3", "Barrage", "Chernobog", "Crusader", "Halftrack", "Khanjali", "Rhino", "Scarab", "Scarab2", "Scarab3", "Thruster", "Trailersmall2", "Akuma", "Avarus", "Bagger", "Bati2", "Bati", "BF400", "Blazer4", "CarbonRS", "Chimera", "Cliffhanger", "Daemon2", "Daemon", "Defiler", "Deathbike", "Deathbike2", "Deathbike3", "Diablous", "Diablous2", "Double", "Enduro", "Esskey", "Faggio2", "Faggio3", "Faggio", "Fcr2", "Fcr", "Gargoyle", "Hakuchou2", "Hakuchou", "Hexer", "Innovation", "Lectro", "Manchez", "Nemesis", "Nightblade", "Oppressor", "Oppressor2", "PCJ", "Ratbike", "Ruffian", "Sanchez2", "Sanchez", "Sanctus", "Shotaro", "Sovereign", "Thrust", "Vader", "Vindicator", "Vortex", "Wolfsbane", "Zombiea", "Zombieb", "Blade", "Buccaneer", "Buccaneer2", "Chino", "Chino2", "Clique", "Deviant", "Dominator", "Dominator2", "Dominator3", "Dominator4", "Dominator5", "Dominator6", "Dukes", "Dukes2", "Ellie", "Faction", "Faction2", "Faction3", "Gauntlet", "Gauntlet2", "Hermes", "Hotknife", "Hustler", "Impaler", "Impaler2", "Impaler3", "Impaler4", "Imperator", "Imperator2", "Imperator3", "Lurcher", "Moonbeam", "Moonbeam2", "Nightshade", "Phoenix", "Picador", "RatLoader", "RatLoader2", "Ruiner", "Ruiner2", "Ruiner3", "SabreGT", "SabreGT2", "Sadler2", "SlamVan", "SlamVan2", "SlamVan3", "SlamVan4", "SlamVan5", "SlamVan6", "Stalion", "Stalion2", "Tampa", "Tampa3", "Tulip", "Vamos", "Vigero", "Virgo", "Virgo2", "Virgo3", "Voodoo", "Voodoo2", "Yosemite", "BfInjection", "Bifta", "Blazer", "Blazer2", "Blazer3", "Blazer5", "Bodhi2", "Brawler", "Bruiser", "Bruiser2", "Bruiser3", "Caracara", "DLoader", "Dune", "Dune2", "Dune3", "Dune4", "Dune5", "Insurgent", "Insurgent2", "Insurgent3", "Kalahari", "Kamacho", "Lguard", "Marshall", "Mesa", "Mesa2", "Mesa3", "Monster", "Monster3", "Monster4", "Monster5", "Nightshark", "RancherXL", "RancherXL2", "Rebel", "Rebel2", "RCBandito", "Riata", "Sandking", "Sandking2", "Technical", "Technical2", "Technical3", "TrophyTruck", "TrophyTruck2", "Freecrawler", "Menacer", "AlphaZ1", "Avenger", "Avenger2", "Besra", "Blimp", "Blimp2", "Blimp3", "Bombushka", "CargoPlane", "Cuban", "Dodo", "Duster", "Howard", "Hydra", "Jet", "Lazer", "Luxor", "Luxor2", "Mammatus", "Microlight", "Miljet", "Mogul", "Molotok", "Nimbus", "Nokota", "Pyro", "Rogue", "Seabreeze", "Shamal", "Starling", "Stunt", "Titan", "Tula", "Velum", "Velum2", "Vestra", "Volatol", "Strikeforce", "BJXL", "Baller", "Baller2", "Baller3", "Baller4", "Baller5", "Baller6", "Cavalcade", "Cavalcade2", "Contender", "Dubsta", "Dubsta2", "Dubsta3", "FQ2", "Granger", "Gresley", "Habanero", "Huntley", "Landstalker", "Patriot", "Patriot2", "Radi", "Rocoto", "Seminole", "Serrano", "Toros", "XLS", "XLS2", "Asea", "Asea2", "Asterope", "Cog55", "Cog552", "Cognoscenti", "Cognoscenti2", "Emperor", "Emperor2", "Emperor3", "Fugitive", "Glendale", "Ingot", "Intruder", "Limo2", "Premier", "Primo", "Primo2", "Regina", "Romero", "Stafford", "Stanier", "Stratum", "Stretch", "Surge", "Tailgater", "Warrener", "Washington", "Airbus", "Brickade", "Bus", "Coach", "Rallytruck", "RentalBus", "Taxi", "Tourbus", "Trash", "Trash2", "Wastlndr", "Pbus2", "Alpha", "Banshee", "Banshee2", "BestiaGTS", "Buffalo", "Buffalo2", "Buffalo3", "Carbonizzare", "Comet2", "Comet3", "Comet4", "Comet5", "Coquette", "Deveste", "Elegy", "Elegy2", "Feltzer2", "Feltzer3", "FlashGT", "Furoregt", "Fusilade", "Futo", "GB200", "Hotring", "Infernus2", "Italigto", "Jester", "Jester2", "Khamelion", "Kuruma", "Kuruma2", "Lynx", "Massacro", "Massacro2", "Neon", "Ninef", "Ninef2", "Omnis", "Pariah", "Penumbra", "Raiden", "RapidGT", "RapidGT2", "Raptor", "Revolter", "Ruston", "Schafter2", "Schafter3", "Schafter4", "Schafter5", "Schafter6", "Schlagen", "Schwarzer", "Sentinel3", "Seven70", "Specter", "Specter2", "Streiter", "Sultan", "Surano", "Tampa2", "Tropos", "Verlierer2", "ZR380", "ZR3802", "ZR3803", "Ardent", "BType", "BType2", "BType3", "Casco", "Cheetah2", "Cheburek", "Coquette2", "Coquette3", "Deluxo", "Fagaloa", "GT500", "JB700", "Jester3", "Mamba", "Manana", "Michelli", "Monroe", "Peyote", "Pigalle", "RapidGT3", "Retinue", "Savestra", "Stinger", "StingerGT", "Stromberg", "Swinger", "Torero", "Tornado", "Tornado2", "Tornado3", "Tornado4", "Tornado5", "Tornado6", "Viseris", "Z190", "ZType", "Adder", "Autarch", "Bullet", "Cheetah", "Cyclone", "EntityXF", "Entity2", "FMJ", "GP1", "Infernus", "LE7B", "Nero", "Nero2", "Osiris", "Penetrator", "Pfister", "Prototipo", "Reaper", "SC1", "Scramjet", "Sheava", "SultanRS", "Superd", "T20", "Taipan", "Tempesta", "Tezeract", "Turismo2", "Turismor", "Tyrant", "Tyrus", "Vacca", "Vagner", "Vigilante", "Visione", "Voltic", "Voltic2", "Zentorno", "Italigtb", "Italigtb2", "XA21", "ArmyTanker", "ArmyTrailer", "ArmyTrailer2", "BaleTrailer", "BoatTrailer", "CableCar", "DockTrailer", "GrainTrailer", "PropTrailer", "RakeTrailer", "TR2", "TR3", "TR4", "TRFlat", "TVTrailer", "Tanker", "Tanker2", "TrailerLogs", "TrailerSmall", "Trailers2", "Trailers3", "FreightCar", "FreightCont1", "FreightCont2", "FreightGrain", "Freight", "TankerCar", "Airtug", "Caddy", "Caddy2", "Caddy3", "Docktug", "Forklift", "Mower", "Ripley", "Sadler", "Scrap", "TowTruck", "TowTruck2", "Tractor", "Tractor2", "Tractor3", "TrailerLarge", "UtilliTruck", "UtilliTruck3", "UtilliTruck2", "Bison", "Bison2", "Bison3", "BobcatXL", "Boxville", "Boxville2", "Boxville3", "Boxville4", "Boxville5", "Burrito", "Burrito2", "Burrito3", "Burrito4", "Burrito5", "Camper", "GBurrito", "GBurrito2", "Journey", "Minivan", "Minivan2", "Paradise", "Pony", "Pony2", "Rumpo", "Rumpo2", "Rumpo3", "Speedo", "Speedo2", "Speedo4", "Surfer", "Surfer2", "Taco", "Youga", "Youga2", "streiter2", "models", "polamggtr" }; private static readonly Dictionary _serverVehicles = new Dictionary(); private static readonly Dictionary lastPositions = new Dictionary(); private static DateTime lastSave = DateTime.UtcNow; public static void StartTimer() { Timer timer = new Timer(500); timer.Elapsed += VehicleTimerTick; timer.Start(); foreach(var name in _enabledMods) { if(_enabledMods.Where(x => x == name).Count() != 1) { NAPI.Util.ConsoleOutput($"{name} double"); } } } private static void VehicleTimerTick(object sender, ElapsedEventArgs e) { NAPI.Pools.GetAllVehicles().ForEach(v => { Vector3 lastPosition = v.Position; if (lastPositions.ContainsKey(v.Handle)) lastPosition = lastPositions[v.Handle]; double distanceDriven = v.HasSharedData("drivenDistance") ? (double)v.GetSharedData("drivenDistance") : 0D; distanceDriven += (lastPosition.DistanceTo(v.Position) / 1000.0); v.SetSharedData("drivenDistance", (float)distanceDriven); lastPositions[v.Handle] = v.Position; }); if (DateTime.UtcNow.Subtract(lastSave).Seconds >= 30) { lastSave = DateTime.UtcNow; // save to db using (var dbContext = new DatabaseContext()) { foreach (var key in lastPositions.Keys) { Vehicle v = key.Entity(); 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) { return NAPI.Pools.GetAllVehicles().Find(v => v.Handle.Value == id); } 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; } } }