using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using GTANetworkAPI; using Newtonsoft.Json; using ReallifeGamemode.Database.Entities; using ReallifeGamemode.Database.Models; using ReallifeGamemode.Server.Extensions; using ReallifeGamemode.Server.Job; using ReallifeGamemode.Server.Services; using ReallifeGamemode.Server.Util; using ReallifeGamemode.Services; using ReallifeGamemode.Server.Types; namespace ReallifeGamemode.Server.Managers { public class JobManager : Script { private static List _jobs = new List(); private Dictionary playerJobStartPosition = new Dictionary(); public static void LoadJobs() { IEnumerable jobTypes = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsSubclassOf(typeof(JobBase)) && !t.IsAbstract); foreach (var type in jobTypes) { var instance = Activator.CreateInstance(type) as JobBase; if (GetJob(instance.Id) != null) { throw new InvalidOperationException($"Double Job ID found: {instance.Id} | {instance.Name}"); } if (instance.Deactivated) { NAPI.Util.ConsoleOutput("Job {0} is deactivated", instance.Name); continue; } _jobs.Add(instance); NAPI.Util.ConsoleOutput($"Loading job {instance.Name}"); } NAPI.Util.ConsoleOutput($"Loaded {_jobs.Count} jobs"); } public static JobBase GetJob(int id) => _jobs.Where(j => j.Id == id).FirstOrDefault(); public static T GetJob() where T : JobBase { return _jobs.Where(j => j.GetType() == typeof(T)).FirstOrDefault() as T; } public static List GetJobs() => _jobs.OrderBy(j => j.Id).ToList(); public static Dictionary playerTimersJobVehicleRespawn = new Dictionary(); [RemoteEvent("CLIENT:JobCenter_CancelJob")] public void CancelJobEvent(Player player) { using (var dbContext = new DatabaseContext()) { User u = player.GetUser(dbContext); if (u == null) return; if (u.JobId == null) { ChatService.ErrorMessage(player, "Du hast momentan keinen Job, den du kündigen könntest."); return; } u.JobId = null; ChatService.SendMessage(player, "~y~[JOBCENTER]~s~ Du hast deinen Job erfolgreich gekündigt."); dbContext.SaveChanges(); } } [RemoteEvent("CLIENT:JobCenter_AcceptJob")] public void AcceptJobEvent(Player player, int jobId) { using (var dbContext = new DatabaseContext()) { User u = player.GetUser(dbContext); if (u == null) return; if (u.JobId != null) { ChatService.ErrorMessage(player, "Du musst deinen alten Job kündigen, bevor du einen neuen ausüben kannst."); return; } //Pilotjob if (jobId == 3 && u.FlyingLicensePlane == false) { ChatService.ErrorMessage(player, "Um diesen Job annehmen zu können, musst du einen Flugschein besitzen."); return; } if (u.DriverLicenseVehicle == false) { ChatService.ErrorMessage(player, "Um diesen Job annehmen zu können, musst du einen Führerschein besitzen."); return; } JobBase job = JobManager.GetJob(jobId); if (job == null) { ChatService.ErrorMessage(player, "Bei der Job-Annahme ist ein Fehler aufgetretet: Dieser Job wurde nicht gefunden"); return; } ChatService.SendMessage(player, $"~y~[JOBCENTER]~s~ Du hast erfolgreich deinen neuen Job: ~o~{job.Name}~s~ angenommen."); u.JobId = jobId; dbContext.SaveChanges(); } } [RemoteEvent("CLIENT:JobManager_ShowJobMenu")] public void ShowJobMenuEvent(Player player) { User u = player.GetUser(); if (u.JobId == null) return; JobBase job = GetJob(u.JobId.Value); dynamic data = null; if (job.Id == 1 && job.GetUsersInJob().Contains(player)) { var taxiCalls = JobManager.GetJob().TaxiContracts; if (!taxiCalls.Any(t => t.Driver?.Handle == player.Handle)) // Spieler in keiner aktiven Fahrt { data = new { job.Id, Status = 0, JobData = new { TaxiCalls = taxiCalls .Where(t => t.Driver == null) .Select(t => new { t.Name, Distance = Math.Round(t.Position.DistanceTo(player.Position), 0) }) .OrderBy(t => t.Distance) } }; } else // Spieler in aktiver Fahrt { data = new { job.Id, Status = 1, JobData = new { taxiCalls.Where(t => t.Driver.Handle == player.Handle).First().Name } }; } } //JobPoint nearJobPoint = PositionManager.JobPoints.Find(p => p.Position.DistanceTo(player.Position) <= 2); if (u.JobId == 2 || u.JobId == 3 || u.JobId == 4) { return; } var json = JsonConvert.SerializeObject(data); player.TriggerEvent("SERVER:Job_ShowJobMenu", job.Name, json); } [RemoteEvent("CLIENT:Job_StartJob")] public void StartJobEvent(Player player) { User u = player.GetUser(); if (u.JobId == null) return; JobBase job = GetJob(u.JobId.Value); if (job.GetUsersInJob().Contains(player)) { ChatService.ErrorMessage(player, "Du bist schon in deinem Job aktiv"); return; } if (job.NeedVehicleToStart && !job.GetJobVehicles().Any(v => v.GetVehicle().Handle.Value == player.Vehicle?.Handle.Value)) { ChatService.ErrorMessage(player, "Zum Start dieses Jobs musst du in einem Jobfahrzeug sein"); return; } if (player.Vehicle != null) { player.SetData("LastVehicle", player.Vehicle); } playerJobStartPosition[player] = player.Position; job.StartJob(player); } [ServerEvent(Event.PlayerExitVehicle)] public void JobManagerPlayerExitVehicle(Player player, Vehicle veh) { ServerVehicle sVeh = VehicleManager.GetServerVehicleFromVehicle(veh); User u = player.GetUser(); if (u.JobId == null) return; JobBase job = GetJob(u.JobId.Value); if (veh.GetServerVehicle() is JobVehicle vehJ && player.VehicleSeat == 0) { if (vehJ.GetJob().GetUsersInJob().Contains(player)) { if (u.JobId != 2) { if (!player.HasData("JobVehicleFrei") || player.GetData("JobVehicleFrei") == false) { player.SetData("DelayTime", 30000); veh.SetData("timerJobVehicleRespawn", true); player.SetData("LastVehicle", veh); player.SetData("LastSVehicle", sVeh); if (playerTimersJobVehicleRespawn.ContainsKey(player)) { playerTimersJobVehicleRespawn[player].Stop(); } PlayerTimer playerTimer = new PlayerTimer(player, veh, 30000); playerTimer.Elapsed += PlayerTimer_Elapsed; playerTimersJobVehicleRespawn[player] = playerTimer; player.SendChatMessage("~y~[JOB] ~w~Du hast das Fahrzeug verlassen,"); player.SendChatMessage("~y~[JOB] ~w~Bist du nicht in 30 Sekunden zurück, ~r~wird der Job beendet!"); //job.StopJob(player); return; } if (player.HasData("JobVehicleFrei") && player.GetData("JobVehicleFrei") == true) { player.SetData("JobVehicleFrei", false); return; } } if (u.JobId == 2) { if (!player.HasData("JobVehicleFrei") || player.GetData("JobVehicleFrei") == false) { player.SetData("DelayTime", 60000 * 5); veh.SetData("timerJobVehicleRespawn", true); player.SetData("LastVehicle", veh); player.SetData("LastSVehicle", sVeh); if (playerTimersJobVehicleRespawn.ContainsKey(player)) { playerTimersJobVehicleRespawn[player].Stop(); } PlayerTimer playerTimer = new PlayerTimer(player, veh, 60000 * 5); playerTimer.Elapsed += PlayerTimer_Elapsed; playerTimersJobVehicleRespawn[player] = playerTimer; //player.SendChatMessage("~y~[JOB] ~w~Du hast das Fahrzeug verlassen,"); //player.SendChatMessage("~y~[JOB] ~w~Bist du nicht in 30 Sekunden zurück, ~r~wird der Job beendet!"); //job.StopJob(player); return; } if (player.HasData("JobVehicleFrei") && player.GetData("JobVehicleFrei") == true) { player.SetData("JobVehicleFrei", false); return; } } } } } private void PlayerTimer_Elapsed(Player player, Vehicle veh) { NAPI.Task.Run(() => { //Vehicle LastVehicle = player.GetData("LastVehicle"); Vehicle LastVehicle = veh; JobBase job = GetJob(player?.GetUser()?.JobId ?? -1); if (LastVehicle == null || job == null) { return; } if (LastVehicle.GetServerVehicle() is JobVehicle vehJ) { if (LastVehicle.GetData("timerJobVehicleRespawn") == true) { if (vehJ.GetJob().GetUsersInJob().Contains(player)) { if (LastVehicle != null) { if (job.Id != 2) //Müllman Handelt Fahrzeug respawn eigenständig { LastVehicle.ResetData("timerJobVehicleRespawn"); ServerVehicle sVeh = VehicleManager.GetServerVehicleFromVehicle(LastVehicle); ServerVehicleExtensions.Spawn(sVeh, LastVehicle); } job.StopJob(player); ChatService.SendMessage(player, $"~y~[JOB]~s~ Du hast deinen Job ~o~{job.Name}~s~ beendet."); CheckPointHandle.DeleteCheckpoints(player); if (!player.HasData("isDead") || player.GetData("isDead") == false) { if (player.GetUser().JobId == 1)//Taxifahrer { player.TriggerEvent("CLIENT:stopFare"); player.Position = new Vector3(-628.598388671875, -2107.609130859375, 6.072586536407471); player.Heading = (-171.50303649902344f); } if (player.GetUser().JobId == 2)//Müllmann { player.Position = new Vector3(485.4114685058594, -2173.25, 5.918273448944092); player.Heading = (-15.922085762023926f); } if (player.GetUser().JobId == 3)//Pilot { if (!player.HasData("PilotenBase") || player.GetData("PilotenBase") == 1) //Sandyshores { player.Position = new Vector3(1707.2711181640625, 3276.216064453125, 41.155494689941406); player.Heading = (-154.65234375f); } if (player.HasData("PilotenBase") && player.GetData("PilotenBase") == 2) //LS Airport { player.Position = new Vector3(-1622.48, -3151.58, 13); player.Heading = (48.44f); } } if (player.GetUser().JobId == 4)//Busfahrer { player.Position = new Vector3(-535.46, -2144.97, 5.95); player.Heading = (57.03f); } } } } } } }); } [RemoteEvent("CLIENT:Job_StopJob")] public void StopJob(Player player) { User u = player.GetUser(); if (u.JobId == null) return; JobBase job = GetJob(u.JobId.Value); if (!job.GetUsersInJob().Contains(player)) { ChatService.ErrorMessage(player, "Du führst deinen Job momentan nicht aus"); return; } if (job.NeedVehicleToStart && player.Vehicle != null) { VehicleStreaming.SetEngineState(player.Vehicle, false); } job.StopJob(player); if (player.GetUser().JobId == 1)//Taxifahrer { //player.Position = new Vector3(-628.598388671875, -2107.609130859375, 6.072586536407471); //player.Heading = (-171.50303649902344f); player.Position = playerJobStartPosition[player]; } if (player.GetUser().JobId == 2)//Müllmann { player.Position = new Vector3(485.4114685058594, -2173.25, 5.918273448944092); player.Heading = (-15.922085762023926f); } if (player.GetUser().JobId == 3)//Pilot { if (player.HasData("PilotenBase") || player.GetData("PilotenBase") == 1) //Sandyshores { player.Position = new Vector3(1707.2711181640625, 3276.216064453125, 41.155494689941406); player.Heading = (-154.65234375f); player.GetUser().SetData("PilotenBase", 0); } if (player.HasData("PilotenBase") && player.GetData("PilotenBase") == 2) //LS Airport { player.Position = new Vector3(-1622.48, -3151.58, 13); player.Heading = (48.44f); player.GetUser().SetData("PilotenBase", 0); } } if (player.GetUser().JobId == 4)//Busfahrer { player.Position = new Vector3(-535.46, -2144.97, 5.95); player.Heading = (57.03f); } Vehicle LastVehicle = player.GetData("LastVehicle"); if (LastVehicle != null) { LastVehicle.ResetData("timerJobVehicleRespawn"); ServerVehicle sVeh = VehicleManager.GetServerVehicleFromVehicle(LastVehicle); ServerVehicleExtensions.Spawn(sVeh, LastVehicle); } if (playerTimersJobVehicleRespawn.ContainsKey(player)) { playerTimersJobVehicleRespawn[player].Stop(); } CheckPointHandle.DeleteCheckpoints(player); ChatService.SendMessage(player, $"~y~[JOB]~s~ Du hast deinen Job ~o~{job.Name}~s~ beendet."); } [ServerEvent(Event.PlayerEnterVehicle)] public void JobManagerPlayerEnterVehicle(Player player, Vehicle veh, sbyte seat) { ServerVehicle sVeh = veh.GetServerVehicle(); if (sVeh == null) { return; } if (seat != 0) { if (sVeh is JobVehicle jV && jV.JobId == 1) // Spieler steigt in Taxi ein { var taxiJob = JobManager.GetJob(); Player driver = veh.GetDriver(); if (driver == null) { return; } if (!driver.HasData("DriverPrice")) return; int taxiPrice = driver.GetData("DriverPrice"); float km = 0; if (!driver.HasData("FareKm")) { driver.SetData("FareKm", km); } km = driver.GetData("FareKm"); if (driver.HasData("Passager")) return; driver.SetData("Passager", player.GetUser().Id); driver.SetData("hasPassager", true); /* using (var dbContext = new DatabaseContext()) { int amount = (int)Math.Round(km * taxiPrice); User contractUser = player.GetUser(dbContext); contractUser.Handmoney -= amount; driver.GetUser(dbContext).Wage += amount; dbContext.SaveChanges(); //contractUser.Player.TriggerEvent("SERVER:SET_HANDMONEY", contractUser.Handmoney); } */ player.TriggerEvent("CLIENT:startCustomerFare", taxiPrice, km); var taxiContracts = taxiJob.TaxiContracts.Where(t => t.Name == player.Name); if (taxiContracts.Count() == 0) return; var contract = taxiContracts.First(); taxiJob.TaxiContracts.Remove(contract); if (driver != null && contract.Driver != null && contract.Driver.Handle != veh.GetDriver().Handle) { ChatService.SendMessage(contract.Driver, $"!{{02FCFF}}{player.Name} ist in ein Taxi eingestiegen, der Auftrag wurde beendet."); ChatService.SendMessage(player, $"!{{02FCFF}}Du bist in ein Taxi eingestiegen, der Auftrag wurde beendet."); } } } JobBase job = GetJob(player.GetUser().JobId ?? -1); if (job?.GetUsersInJob()?.Contains(player) ?? false) { if (sVeh != null) { if (sVeh is JobVehicle JV) { if (player.GetUser().JobId == 3 || player.GetUser().JobId == 4) { if (seat == 0) { JobVehicle c = new JobVehicle(); if (JV.GetJob().GetUsersInJob().Contains(player)) { if (!player.HasData("LastVehicle") || player.GetData("LastVehicle") == null) return; if (player.HasData("LastVehicle") && veh == player.GetData("LastVehicle")) { veh.SetData("timerJobVehicleRespawn", false); if (playerTimersJobVehicleRespawn.ContainsKey(player)) { playerTimersJobVehicleRespawn[player].Stop(); } } else { if (player.GetData("HatRoute") == true) { StopJob(player); } } } } else { job.StopJob(player); ChatService.SendMessage(player, $"~y~[JOB]~s~ Du hast deinen Job ~o~{job.Name}~s~ beendet."); if (playerTimersJobVehicleRespawn.ContainsKey(player)) { playerTimersJobVehicleRespawn[player].Stop(); } CheckPointHandle.DeleteCheckpoints(player); if (!player.HasData("LastVehicle") || player.GetData("LastVehicle") == null) return; player.GetData("LastVehicle").ResetData("timerJobVehicleRespawn"); ServerVehicle nsSVeh = VehicleManager.GetServerVehicleFromVehicle(player.GetData("LastVehicle")); ServerVehicleExtensions.Spawn(nsSVeh, player.GetData("LastVehicle")); return; } } if (player.GetUser().JobId == 2) { JobVehicle c = new JobVehicle(); if (JV.GetJob().GetUsersInJob().Contains(player)) { if (!player.HasData("LastVehicle") || player.GetData("LastVehicle") == null) return; if (player.HasData("LastVehicle") && veh == player.GetData("LastVehicle")) { veh.SetData("timerJobVehicleRespawn", false); if (playerTimersJobVehicleRespawn.ContainsKey(player)) { playerTimersJobVehicleRespawn[player].Stop(); } } else { if (player.GetData("HatRoute") == true) { StopJob(player); } } } } } else { job.StopJob(player); ChatService.SendMessage(player, $"~y~[JOB]~s~ Du hast deinen Job ~o~{job.Name}~s~ beendet."); if (playerTimersJobVehicleRespawn.ContainsKey(player)) { playerTimersJobVehicleRespawn[player].Stop(); } CheckPointHandle.DeleteCheckpoints(player); if (!player.HasData("LastVehicle")) { return; } if (player.GetData("LastVehicle") == null) { return; } player.GetData("LastVehicle").ResetData("timerJobVehicleRespawn"); ServerVehicle nsSVeh = VehicleManager.GetServerVehicleFromVehicle(player.GetData("LastVehicle")); ServerVehicleExtensions.Spawn(nsSVeh, player.GetData("LastVehicle")); } } else if (sVeh! is JobVehicle || veh != null) { job.StopJob(player); ChatService.SendMessage(player, $"~y~[JOB]~s~ Du hast deinen Job ~o~{job.Name}~s~ beendet."); if (playerTimersJobVehicleRespawn.ContainsKey(player)) { playerTimersJobVehicleRespawn[player].Stop(); } CheckPointHandle.DeleteCheckpoints(player); if (!player.HasData("LastVehicle") || player.GetData("LastVehicle") == null) return; player.GetData("LastVehicle").ResetData("timerJobVehicleRespawn"); ServerVehicle nsSVeh = VehicleManager.GetServerVehicleFromVehicle(player.GetData("LastVehicle")); ServerVehicleExtensions.Spawn(nsSVeh, player.GetData("LastVehicle")); } else if (sVeh is JobVehicle JV) { if (JV.JobId != player.GetUser().JobId) { job.StopJob(player); ChatService.SendMessage(player, $"~y~[JOB]~s~ Du hast deinen Job ~o~{job.Name}~s~ beendet."); if (playerTimersJobVehicleRespawn.ContainsKey(player)) { playerTimersJobVehicleRespawn[player].Stop(); } CheckPointHandle.DeleteCheckpoints(player); if (!player.HasData("LastVehicle") || player.GetData("LastVehicle") == null) return; player.GetData("LastVehicle").ResetData("timerJobVehicleRespawn"); ServerVehicle nsSVeh = VehicleManager.GetServerVehicleFromVehicle(player.GetData("LastVehicle")); ServerVehicleExtensions.Spawn(nsSVeh, player.GetData("LastVehicle")); } } } } [ServerEvent(Event.PlayerEnterVehicleAttempt)] private void JobManagerEnterVehicleAttempt(Player player, Vehicle vehicle, sbyte seat) { if (JobManager.GetJob().GetUsersInJob().Contains(player)) { JobManager.GetJob().MuellmannOnPlayerEnterVehicle(player, vehicle, seat); } } [ServerEvent(Event.PlayerDeath)] private void JobManagerOnPlayerDeath(Player player, Player killer, uint reason) { if (JobManager.GetJob().GetUsersInJob().Contains(player)) { JobManager.GetJob().MuellmannOnPlayerDeath(player); } } [ServerEvent(Event.PlayerDisconnected)] private void JobManagerOnPlayerDisconnect(Player player, DisconnectionType type, string reason) { if (JobManager.GetJob().GetUsersInJob().Contains(player)) { JobManager.GetJob().MuellmannOnPlayerDc(player); } } [ServerEvent(Event.PlayerExitVehicle)] public void JobManagerPlayerExitVehicle2(Player player, Vehicle veh) { ServerVehicle sVeh = veh.GetServerVehicle(); if (sVeh == null) return; if (sVeh is JobVehicle jV && jV.JobId == 1) // Spieler steigt vom Taxi aus { var taxiJob = JobManager.GetJob(); if (veh.Occupants.Count == 0) return; Player driver = veh.GetDriver(); if (driver == null) return; if (player.GetUser().Id != driver.GetData("Passager")) { player.TriggerEvent("CLIENT:cancelFare"); return; } player.TriggerEvent("CLIENT:cancelFareCustomer"); driver.TriggerEvent("CLIENT:resetFareClock"); driver.ResetData("Passager"); driver.ResetData("hasPassager"); driver.SetData("FareKm", 0); driver.TriggerEvent("CLIENT:cancelFare"); driver.TriggerEvent("CLIENT:startFare"); foreach (Player occupant in veh.Occupants) { if (occupant == driver) continue; occupant.WarpOutOfVehicle(); } } } [RemoteEvent("CLIENT:JobManager_TaxiJob_AcceptCall")] public void TaxiJobAcceptCall(Player player, string name) { var taxiJob = JobManager.GetJob(); if (!taxiJob.TaxiContracts.Any(t => t.Name == name)) { ChatService.ErrorMessage(player, "Dieser Spieler hat kein Taxi gerufen oder der Auftrag ist nicht mehr aktuell"); return; } var job = taxiJob.TaxiContracts.Where(t => t.Name == name).First(); var target = PlayerService.GetPlayerByNameOrId(name); if (target == null) { taxiJob.TaxiContracts.Remove(job); ChatService.ErrorMessage(player, "Dieser Spieler ist nicht mehr online"); return; } if (target == player) { ChatService.ErrorMessage(player, "Du kannst deinen eigenen Auftrag nicht annehmen"); } job.Driver = player; player.TriggerEvent("SERVER:Util_setWaypoint", target.Position.X, target.Position.Y); player.SetData("hasPassager", true); ChatService.SendMessage(target, $"!{{02FCFF}}Dein Auftrag wurde von {player.Name} angenommen. Warte an deiner aktuellen Position."); ChatService.SendMessage(target, $"!{{02FCFF}}Für die Anfahrt fallen zusätzlich Kosten auf."); ChatService.SendMessage(player, $"!{{02FCFF}}Du hast den Auftrag von {name} angenommen. Hole ihn nun ab."); } } }