private void ApplyAttackingPawnJob(Pawn pawn) { var pId = pawn.thingIDNumber; AttackPawnCommand comm = null; bool stopJob = !AttackingPawnDic.ContainsKey(pId) || !AttackingPawnJobDic.TryGetValue(pId, out comm); try { var tick = (long)Find.TickManager.TicksGame; APJBT check; if (ApplyPawnJobByTick.TryGetValue(pId, out check)) { //Если в один тик мы второй раз пытаемся установить задачу, значит система её сразу отменяет //В этом случае сбрасываем задачу, считаем что цель достигнута или недоступна if (check.Comm == comm && check.Tick == tick) { if (MainHelper.DebugMode && pawn.Label == "Douglas, Клерк") { Loger.Log("HostAttackUpdate ApplyAttackingPawnJob stopJob(repeat) " + comm.TargetPos.Get().ToString()); } stopJob = true; } } //UIEventNewJobDisable = true; Thing target = null; if (!stopJob && (comm.Command == AttackPawnCommand.PawnCommand.Attack || comm.Command == AttackPawnCommand.PawnCommand.AttackMelee)) { var mapPawns = GameMap.mapPawns.AllPawnsSpawned; target = mapPawns.Where(p => p.thingIDNumber == comm.TargetID).FirstOrDefault(); if (target == null) { target = GameMap.listerThings.AllThings.Where(p => p.thingIDNumber == comm.TargetID).FirstOrDefault(); } if (target == null) { if (MainHelper.DebugMode && pawn.Label == "Douglas, Клерк") { Loger.Log("HostAttackUpdate ApplyAttackingPawnJob TargetThing == null " + comm.HostPawnID.ToString()); } stopJob = true; } } if (!stopJob) { if (comm.Command == AttackPawnCommand.PawnCommand.Attack) { //задаем команду атаковать if (MainHelper.DebugMode && pawn.Label == "Douglas, Клерк") { Loger.Log("HostAttackUpdate ApplyAttackingPawnJob StartJob Attack " + comm.TargetID.ToString()); } pawn.jobs.StartJob(new Job(JobDefOf.AttackStatic, target) { playerForced = true, expiryInterval = int.MaxValue, checkOverrideOnExpire = false, } , JobCondition.InterruptForced); } else if (comm.Command == AttackPawnCommand.PawnCommand.AttackMelee) { if (MainHelper.DebugMode && pawn.Label == "Douglas, Клерк") { Loger.Log("HostAttackUpdate ApplyAttackingPawnJob StartJob AttackMelee " + comm.TargetID.ToString()); } pawn.jobs.StartJob(new Job(JobDefOf.AttackMelee, target) { playerForced = true, expiryInterval = int.MaxValue, checkOverrideOnExpire = false, } , JobCondition.InterruptForced); } else if (comm.Command == AttackPawnCommand.PawnCommand.Goto) { //задаем команду идти if (MainHelper.DebugMode && pawn.Label == "Douglas, Клерк") { Loger.Log("HostAttackUpdate ApplyAttackingPawnJob StartJob Goto " + comm.TargetPos.Get().ToString()); } pawn.jobs.StartJob(new Job(JobDefOf.Goto, comm.TargetPos.Get()) { playerForced = true, expiryInterval = int.MaxValue, checkOverrideOnExpire = false, } , JobCondition.InterruptForced); } else { stopJob = true; } } if (stopJob) { if (AttackingPawnJobDic.ContainsKey(pId)) { if (MainHelper.DebugMode && pawn.Label == "Douglas, Клерк") { Loger.Log("HostAttackUpdate ApplyAttackingPawnJob Remove Job " + comm.TargetPos.Get().ToString()); } AttackingPawnJobDic.Remove(pId); } pawn.jobs.StartJob(new Job(JobDefOf.Wait_Combat) { playerForced = true, expiryInterval = int.MaxValue, checkOverrideOnExpire = false, } , JobCondition.InterruptForced); } else { ApplyPawnJobByTick[pId] = new APJBT() { Comm = comm, Tick = tick }; } } catch (Exception exp) { if (MainHelper.DebugMode && pawn.Label == "Douglas, Клерк") { Loger.Log("HostAttackUpdate ApplyAttackingPawnJob " + exp.ToString()); } if (AttackingPawnJobDic.ContainsKey(pId)) { AttackingPawnJobDic.Remove(pId); } } //UIEventNewJobDisable = false; }
public void UIEventNewJob(Pawn pawn, Job job) //если job == null значит команда стоять и не двигаться Wait_Combat { try { if (UIEventNewJobDisable) { return; } var pawnId = pawn.thingIDNumber; //помимо главной обработки события изменения задания помечаем цель задачи для обновления её состояния позже, когда задача пешки завершиться //это всё для того, чтобы поймать, что кол-во какой-то вещи изменилось //добавляем тут намерение пешки взять вещь в новый словарь если Job не null, //а если null (когда джоб завершился) помещаем в предварительный массив к отправке //в момент отправки из предварительного массива данные переносятся в массив к отправке, а те что там были отправляются атакующиму с их текущим количеством стака Thing jobThing; if (ThingPrepareChange2.TryGetValue(pawnId, out jobThing) && !ThingPrepareChange1.Contains(jobThing)) { Loger.Log("HostAttackUpdate UIEventNewJob AddFromJob " + jobThing.Label); ThingPrepareChange1.Add(jobThing); ThingPrepareChange2.Remove(pawnId); } if (job != null && job.targetA.HasThing && !(job.targetA.Thing is Pawn)) { ThingPrepareChange2[pawnId] = job.targetA.Thing; } //у атакующих отменяем все команды и повторяем те, которые были переданы нам последний раз if (!AttackingPawnDic.ContainsKey(pawnId)) { if (MainHelper.DebugMode && pawn.Label == "Douglas, Клерк") { Loger.Log("HostAttackUpdate UIEventNewJob StartJob " + pawn.Label + " job=" + (job == null ? "null" : job.def.defName.ToString()) + " -> ignore"); } return; } var stack = ""; /* * if (job == null || (job == null ? "null" : job.def.defName.ToString()) == "Wait_MaintainPosture") * { * var stackTrace = new StackTrace(); * var frames = stackTrace.GetFrames(); * foreach (var frame in frames) * { * var methodDescription = frame.GetMethod(); * stack += Environment.NewLine + methodDescription.Name; * } * } */ UIEventNewJobDisable = true; if (MainHelper.DebugMode && pawn.Label == "Douglas, Клерк") { Loger.Log("HostAttackUpdate UIEventNewJob StartJob " + pawn.Label + " job=" + (job == null ? "null" : job.def.defName.ToString()) + " -> <...> " + stack); } ApplyAttackingPawnJob(pawn); } catch (Exception exp) { if (MainHelper.DebugMode && pawn.Label == "Douglas, Клерк") { Loger.Log("HostAttackUpdate UIEventNewJob " + exp.ToString()); } } UIEventNewJobDisable = false; }
private void AttackUpdate() { bool inTimerEvent = false; try { if (InTimer) { return; } InTimer = true; AttackUpdateTick++; // Loger.Log("Client HostAttackUpdate #" + AttackUpdateTick.ToString()); SessionClientController.Command((connect) => { try { List <Pawn> mapPawns; AttackHostFromSrv toClient; lock (ToSendListsSync) { // Loger.Log("Client HostAttackUpdate 1"); //обновляем списки mapPawns = GameMap.mapPawns.AllPawnsSpawned; var mapPawnsId = new HashSet <int>(mapPawns.Select(p => p.thingIDNumber)); mapPawnsId.SymmetricExceptWith(SendedPawnsId); //новые пешки + те что на сервере, но их уже нет на карте if (mapPawnsId.Count > 0) { var toSendAddId = new HashSet <int>(mapPawnsId); toSendAddId.ExceptWith(SendedPawnsId); //только новые пешки if (toSendAddId.Count > 0) { toSendAddId.ExceptWith(ToSendAddId); //исключаем те, которые уже есть в списке ToSendAddId.AddRange(toSendAddId); } var toSendDeleteId = new HashSet <int>(mapPawnsId); toSendDeleteId.IntersectWith(SendedPawnsId); //только те, что на сервере но их уже нет на карте if (toSendDeleteId.Count > 0) { toSendDeleteId.ExceptWith(ToSendDeleteId); //исключаем те, которые уже есть в списке ToSendDeleteId.AddRange(toSendDeleteId); } } //посылаем пакеты с данными // Loger.Log("Client HostAttackUpdate 2"); var newPawns = new List <ThingEntry>(); var newPawnsId = new List <int>(); int cnt = ToSendAddId.Count < 3 || ToSendAddId.Count > 6 || AttackUpdateTick == 0 ? ToSendAddId.Count : 3; int i = 0; int[] added = new int[cnt]; foreach (int id in ToSendAddId) { if (i >= cnt) { break; } added[i++] = id; var thing = mapPawns.Where(p => p.thingIDNumber == id).FirstOrDefault(); var tt = ThingEntry.CreateEntry(thing, 1); //передаем те, что были исходные у атакуемого (хотя там используется только как признак TransportID != 0 - значит те кто атакует) if (AttackingPawnDic.ContainsKey(tt.OriginalID)) { tt.TransportID = AttackingPawnDic[tt.OriginalID]; } newPawns.Add(tt); newPawnsId.Add(id); } for (i = 0; i < cnt; i++) { ToSendAddId.Remove(added[i]); SendedPawnsId.Add(added[i]); } foreach (int id in ToSendDeleteId) { SendedPawnsId.Remove(id); } //вещи var newThings = ToSendThingAdd .Where(thing => !ToSendDeleteId.Any(d => thing.thingIDNumber == d)) .Select(thing => ThingEntry.CreateEntry(thing, thing.stackCount)) .ToList(); //передаем изменение местоположения и пр. по ID хоста var toSendState = new List <AttackThingState>(); var toSendStateId = new List <int>(); for (int imp = 0; imp < mapPawns.Count; imp++) { var mp = mapPawns[imp]; var mpID = mp.thingIDNumber; if (ToUpdateStateId.Contains(mpID)) { continue; } var mpHash = AttackThingState.GetHash(mp); int mpHS; if (!SendedState.TryGetValue(mpID, out mpHS) || mpHS != mpHash) { SendedState[mpID] = mpHash; toSendState.Add(new AttackThingState(mp)); } } for (int imp = 0; imp < ToUpdateState.Count; imp++) { var mp = ToUpdateState[imp]; var mpID = mp.thingIDNumber; if (ToSendDeleteId.Contains(mpID)) { continue; } if (mp is Pawn) { var mpHash = AttackThingState.GetHash(mp); SendedState[mpID] = mpHash; //заносим только для проверки выше } toSendState.Add(new AttackThingState(mp)); } //обновляем поколения вещей учавствующих в Job и отправляем нужные foreach (var mp in ThingPrepareChange0) { var mpID = mp.thingIDNumber; if (ToSendDeleteId.Contains(mpID)) { continue; } toSendState.Add(new AttackThingState(mp)); } Loger.Log("HostAttackUpdate UpdateCommand FromJob Count=" + ThingPrepareChange0.Count.ToString()); ThingPrepareChange0 = ThingPrepareChange1; ThingPrepareChange1 = new HashSet <Thing>(); //Loger.Log("Client HostAttackUpdate 3"); toClient = connect.AttackOnlineHost(new AttackHostToSrv() { State = 10, NewPawns = newPawns, NewPawnsId = newPawnsId, NewThings = newThings, NewThingsId = newThings.Select(th => th.OriginalID).ToList(), Delete = ToSendDeleteId.ToList(), UpdateState = toSendState }); ToSendThingAdd.Clear(); ToSendDeleteId.Clear(); ToUpdateStateId.Clear(); ToUpdateState.Clear(); } //принимаем обновление команд атакующих if (toClient.UpdateCommand.Count > 0) { Loger.Log("HostAttackUpdate UpdateCommand Count=" + toClient.UpdateCommand.Count.ToString()); UIEventNewJobDisable = true; for (int ii = 0; ii < toClient.UpdateCommand.Count; ii++) { var comm = toClient.UpdateCommand[ii]; var pawn = mapPawns.Where(p => p.thingIDNumber == comm.HostPawnID).FirstOrDefault() as Pawn; if (pawn == null) { Loger.Log("HostAttackUpdate UpdateCommand pawn == null " + comm.HostPawnID.ToString()); continue; } AttackingPawnJobDic[comm.HostPawnID] = comm; ApplyAttackingPawnJob(pawn); } UIEventNewJobDisable = false; } // Loger.Log("Client HostAttackUpdate 4"); } catch (Exception ext) { InTimer = false; Loger.Log("HostAttackUpdate Event Exception " + ext.ToString()); } finally { InTimer = false; } }); } catch (Exception ext) { Loger.Log("HostAttackUpdate Exception " + ext.ToString()); } if (!inTimerEvent) { InTimer = false; } }