示例#1
0
        public void TestChangingCallbackAddLocks()
        {
            var obj  = new DummyLockable(1);
            var obj2 = new DummyLockable(2);
            var obj3 = new DummyLockable(3);

            int callCount = 0;

            CallbackLock.CallbackLockHandler lockFunc = delegate
            {
                if (callCount == 0)
                {
                    callCount++;
                    return(new ILockable[] { obj2 });
                }

                callCount++;
                return(new ILockable[] { obj3, obj2 });
            };
            var lck = new CallbackLock(multiObjectLockFactory).Lock(lockFunc, null, obj);

            DefaultMultiObjectLock.IsLocked(obj).Should().BeTrue();
            DefaultMultiObjectLock.IsLocked(obj2).Should().BeTrue();
            DefaultMultiObjectLock.IsLocked(obj3).Should().BeTrue();

            lck.UnlockAll();

            DefaultMultiObjectLock.IsLocked(obj).Should().BeFalse();
            DefaultMultiObjectLock.IsLocked(obj2).Should().BeFalse();
            DefaultMultiObjectLock.IsLocked(obj3).Should().BeFalse();
        }
示例#2
0
        private void Delete(Session session, Packet packet)
        {
            if (!session.Player.IsInTribe)
            {
                ReplyError(session, packet, Error.TribeIsNull);
                return;
            }

            ITribe tribe = session.Player.Tribesman.Tribe;

            CallbackLock.CallbackLockHandler lockHandler = delegate
            {
                var locks =
                    strongholdManager.StrongholdsForTribe(tribe)
                    .SelectMany(stronghold => stronghold.LockList())
                    .ToList();

                locks.AddRange(tribe.Tribesmen);

                return(locks.ToArray());
            };

            locker.Lock(lockHandler, new object[] {}, tribe).Do(() =>
            {
                if (!session.Player.Tribesman.Tribe.IsOwner(session.Player))
                {
                    ReplyError(session, packet, Error.TribesmanNotAuthorized);
                    return;
                }

                var result = tribeManager.Remove(tribe);
                ReplyWithResult(session, packet, result);
            });
        }
示例#3
0
        public void Leave(Session session, Packet packet)
        {
            var tribe = session.Player.Tribesman == null ? null : session.Player.Tribesman.Tribe;

            if (tribe == null)
            {
                ReplyError(session, packet, Error.TribeIsNull);
                return;
            }

            CallbackLock.CallbackLockHandler lockHandler = delegate
            {
                var locks =
                    strongholdManager.StrongholdsForTribe(tribe)
                    .SelectMany(stronghold => stronghold.LockList())
                    .ToList();

                return(locks.ToArray());
            };

            locker.Lock(lockHandler, new object[] {}, tribe, session.Player).Do(() =>
            {
                if (session.Player.Tribesman == null || session.Player.Tribesman.Tribe != tribe)
                {
                    ReplyError(session, packet, Error.Unexpected);
                    return;
                }

                var result = tribe.LeaveTribesman(session.Player);

                ReplyWithResult(session, packet, result);
            });
        }
示例#4
0
        private void AfterGateBattle(ActionState state)
        {
            if (state != ActionState.Completed)
            {
                return;
            }

            ICity       city;
            IStronghold targetStronghold;

            if (!gameObjectLocator.TryGetObjects(cityId, out city))
            {
                throw new Exception("City not found");
            }

            if (!gameObjectLocator.TryGetObjects(targetStrongholdId, out targetStronghold))
            {
                throw new Exception("Stronghold not found");
            }

            CallbackLock.CallbackLockHandler lockAll = delegate { return(targetStronghold.LockList().ToArray()); };

            locker.Lock(lockAll, null, city, targetStronghold).Do(() =>
            {
                ITroopObject troopObject;
                if (!city.TryGetTroop(troopObjectId, out troopObject))
                {
                    throw new Exception("Troop object should still exist");
                }

                // Remove troop if he's dead
                if (TroopIsDead(troopObject, city))
                {
                    StateChange(ActionState.Completed);
                    return;
                }

                if (city.Owner.IsInTribe && targetStronghold.GateOpenTo == city.Owner.Tribesman.Tribe)
                {
                    // If our city is the one that now has access to the stronghold then join the real battle
                    JoinOrCreateStrongholdMainBattle(city);
                }
                else if (city.Owner.IsInTribe && targetStronghold.Tribe == city.Owner.Tribesman.Tribe)
                {
                    StationTroopInStronghold(troopObject, targetStronghold);
                }
                else
                {
                    //Remove notification to target once battle is over
                    city.Notifications.Remove(this);

                    city.Notifications.Add(troopObject, this);

                    // Send troop back home
                    var tma = actionFactory.CreateTroopMovePassiveAction(city.Id, troopObject.ObjectId, city.PrimaryPosition.X, city.PrimaryPosition.Y, true, true);
                    ExecuteChainAndWait(tma, AfterTroopMovedHome);
                }
            });
        }
示例#5
0
        private string Delete(Session session, string[] parms)
        {
            bool   help      = false;
            string tribeName = string.Empty;

            try
            {
                var p = new OptionSet
                {
                    { "?|help|h", v => help = true },
                    { "tribe=", v => tribeName = v.TrimMatchingQuotes() },
                };
                p.Parse(parms);
            }
            catch (Exception)
            {
                help = true;
            }

            if (help || string.IsNullOrEmpty(tribeName))
            {
                return("TribeDelete --name=tribe_name");
            }

            uint tribeId;

            if (!tribeManager.FindTribeId(tribeName, out tribeId))
            {
                return("Tribe not found");
            }

            ITribe tribe;

            if (!world.TryGetObjects(tribeId, out tribe))
            {
                return("Tribe not found");
            }

            CallbackLock.CallbackLockHandler lockHandler = delegate
            {
                var locks = strongholdManager.StrongholdsForTribe(tribe)
                            .SelectMany(stronghold => stronghold.LockList())
                            .ToList();

                locks.AddRange(tribe.Tribesmen);

                return(locks.ToArray());
            };

            locker.Lock(lockHandler, new object[] {}, tribe).Do(() =>
            {
                tribeManager.Remove(tribe);
            });

            return("OK!");
        }
示例#6
0
        public void TestEmptyListFromCallback()
        {
            var obj = new DummyLockable(1);

            CallbackLock.CallbackLockHandler lockFunc = custom => new ILockable[] {};
            var lck = new CallbackLock(multiObjectLockFactory).Lock(lockFunc, null, obj);

            DefaultMultiObjectLock.IsLocked(obj).Should().BeTrue();
            lck.UnlockAll();
            DefaultMultiObjectLock.IsLocked(obj).Should().BeFalse();
        }
示例#7
0
        public override void Callback(object custom)
        {
            IBarbarianTribe barbarianTribe;

            if (!gameObjectLocator.TryGetObjects(barbarianTribeId, out barbarianTribe))
            {
                throw new Exception("Barb tribe is missing");
            }

            CallbackLock.CallbackLockHandler lockHandler = delegate
            {
                var toBeLocked = new List <ILockable>();
                toBeLocked.AddRange(barbarianTribe.Battle.LockList);
                toBeLocked.Add(barbarianTribe);
                return(toBeLocked.ToArray());
            };

            locker.Lock(lockHandler, null, barbarianTribe).Do(() =>
            {
                if (barbarianTribe.Battle.ExecuteTurn())
                {
                    // Battle continues, just save it and reschedule
                    dbManager.Save(barbarianTribe.Battle);
                    endTime = SystemClock.Now.AddSeconds(formula.GetBattleInterval(barbarianTribe.Battle.Defenders, barbarianTribe.Battle.Attackers));
                    StateChange(ActionState.Fired);
                    return;
                }

                // Battle has ended
                // Delete the battle
                world.Remove(barbarianTribe.Battle);
                dbManager.Delete(barbarianTribe.Battle);

                barbarianTribe.BeginUpdate();
                barbarianTribe.Battle = null;
                barbarianTribe.State  = GameObjectStateFactory.NormalState();

                var initialBarbResources = formula.BarbarianTribeResources(barbarianTribe);
                if (!initialBarbResources.Equals(barbarianTribe.Resource))
                {
                    // Lower camps remaining
                    barbarianTribe.CampRemains--;

                    // Reset resources
                    barbarianTribe.Resource.Clear();
                    barbarianTribe.Resource.Add(formula.BarbarianTribeResources(barbarianTribe));
                }

                barbarianTribe.EndUpdate();

                StateChange(ActionState.Completed);
            });
        }
示例#8
0
        private void AfterTroopMoved(ActionState state)
        {
            if (state == ActionState.Completed)
            {
                ICity        city;
                ICity        targetCity;
                ITroopObject troopObject;

                if (!gameObjectLocator.TryGetObjects(cityId, troopObjectId, out city, out troopObject))
                {
                    throw new Exception("City or troop object is missing");
                }

                if (!gameObjectLocator.TryGetObjects(targetCityId, out targetCity))
                {
                    //If the target is missing, walk back
                    locker.Lock(city).Do(() =>
                    {
                        TroopMovePassiveAction tma = actionFactory.CreateTroopMovePassiveAction(city.Id,
                                                                                                troopObject.ObjectId,
                                                                                                city.PrimaryPosition.X,
                                                                                                city.PrimaryPosition.Y,
                                                                                                true,
                                                                                                true);
                        ExecuteChainAndWait(tma, AfterTroopMovedHome);
                    });
                    return;
                }

                // Get all of the stationed city id's from the target city since they will be used by the engage attack action
                CallbackLock.CallbackLockHandler lockAllStationed = delegate
                {
                    return(targetCity.Troops.StationedHere()
                           .Select(stationedStub => stationedStub.City)
                           .Cast <ILockable>()
                           .ToArray());
                };

                locker.Lock(lockAllStationed, null, city, targetCity).Do(() =>
                {
                    var bea = actionFactory.CreateCityEngageAttackPassiveAction(cityId,
                                                                                troopObject.ObjectId,
                                                                                targetCityId);
                    ExecuteChainAndWait(bea, AfterBattle);
                });
            }
        }
示例#9
0
        public override void Callback(object custom)
        {
            IStronghold stronghold;

            if (!gameObjectLocator.TryGetObjects(strongholdId, out stronghold))
            {
                throw new Exception("Stronghold is missing");
            }

            CallbackLock.CallbackLockHandler lockHandler = delegate { return(stronghold.LockList().ToArray()); };

            locker.Lock(lockHandler, null, stronghold).Do(() =>
            {
                if (stronghold.GateBattle.ExecuteTurn())
                {
                    // Battle continues, just save it and reschedule
                    dbManager.Save(stronghold.GateBattle);
                    endTime = SystemClock.Now.AddSeconds(formula.GetGateBattleInterval(stronghold));
                    StateChange(ActionState.Fired);
                    return;
                }

                // Battle has ended
                // Delete the battle
                stronghold.GateBattle.GroupKilled    -= BattleOnGroupKilled;
                stronghold.GateBattle.ActionAttacked -= BattleOnActionAttacked;

                world.Remove(stronghold.GateBattle);
                dbManager.Delete(stronghold.GateBattle);
                stronghold.BeginUpdate();
                stronghold.GateBattle = null;
                stronghold.State      = GameObjectStateFactory.NormalState();
                // Heal the gate if no one made through otherwise we let it be healed after the main battle
                if (stronghold.GateOpenTo == null)
                {
                    stronghold.GateMax = (int)formula.StrongholdGateLimit(stronghold.Lvl);
                    stronghold.Gate    = Math.Max(Math.Min(stronghold.GateMax, stronghold.Gate), formula.StrongholdGateHealHp(stronghold.StrongholdState, stronghold.Lvl));
                }
                stronghold.EndUpdate();

                StateChange(ActionState.Completed);
            });
        }
示例#10
0
        public override void Callback(object custom)
        {
            ICity city;

            if (!gameObjectLocator.TryGetObjects(cityId, out city))
            {
                throw new Exception("City is missing");
            }

            CallbackLock.CallbackLockHandler lockHandler = delegate
            {
                var toBeLocked = new List <ILockable>();
                toBeLocked.AddRange(city.Battle.LockList);
                toBeLocked.Add(city);
                toBeLocked.AddRange(city.Troops.StationedHere().Select(stub => stub.City).Distinct());
                return(toBeLocked.ToArray());
            };

            locker.Lock(lockHandler, null, city).Do(() =>
            {
                if (city.Battle.ExecuteTurn())
                {
                    // Battle continues, just save it and reschedule
                    dbManager.Save(city.Battle);
                    endTime = SystemClock.Now.AddSeconds(formula.GetBattleInterval(city.Battle.Defenders, city.Battle.Attackers));
                    StateChange(ActionState.Fired);
                    return;
                }

                // Battle has ended
                // Delete the battle
                city.Battle.ActionAttacked -= BattleActionAttacked;
                city.Battle.UnitKilled     -= BattleUnitKilled;
                city.Battle.EnterRound     -= BattleEnterRound;
                world.Remove(city.Battle);
                dbManager.Delete(city.Battle);
                city.Battle = null;

                // Move the default troop back into normal and clear its temporary battle stats
                city.DefaultTroop.BeginUpdate();
                city.DefaultTroop.Template.ClearStats();
                city.DefaultTroop.State = TroopState.Idle;
                cityBattleProcedure.MoveUnitFormation(city.DefaultTroop, FormationType.InBattle, FormationType.Normal);
                city.DefaultTroop.EndUpdate();

                // Get a COPY of the stubs that are stationed in the town since the loop below will modify city.Troops
                var stationedTroops = city.Troops.StationedHere().Where(stub => stub.State == TroopState.BattleStationed).ToList();

                // Go through each stationed troop and either remove them from the city if they died
                // or set their states back to normal
                foreach (var stub in stationedTroops)
                {
                    // Check if stub has died, if so, remove it completely from both cities
                    if (stub.TotalCount == 0)
                    {
                        city.Troops.RemoveStationed(stub.StationTroopId);
                        stub.City.Troops.Remove(stub.TroopId);
                        continue;
                    }

                    // Set the stationed stub back to just TroopState.Stationed
                    stub.BeginUpdate();
                    stub.State = TroopState.Stationed;
                    stub.EndUpdate();
                }

                // Handle SenseOfUrgency technology
                if (destroyedHp > 0)
                {
                    battleProcedure.SenseOfUrgency(city, destroyedHp);
                }

                StateChange(ActionState.Completed);
            });
        }
示例#11
0
        public override void Callback(object custom)
        {
            IStronghold stronghold;

            if (!gameObjectLocator.TryGetObjects(strongholdId, out stronghold))
            {
                throw new Exception("Stronghold is missing");
            }

            CallbackLock.CallbackLockHandler lockHandler = delegate { return(stronghold.LockList().ToArray()); };

            locker.Lock(lockHandler, null, stronghold).Do(() =>
            {
                if (stronghold.MainBattle.ExecuteTurn())
                {
                    // Battle continues, just save it and reschedule
                    dbManager.Save(stronghold.MainBattle);
                    endTime = SystemClock.Now.AddSeconds(formula.GetBattleInterval(stronghold.MainBattle.Defenders, stronghold.MainBattle.Attackers));
                    StateChange(ActionState.Fired);
                    return;
                }

                // Battle has ended
                // Delete the battle
                stronghold.MainBattle.UnitCountDecreased -= MainBattleOnUnitKilled;
                stronghold.MainBattle.GroupKilled        -= MainBattleOnGroupKilled;
                stronghold.MainBattle.ActionAttacked     -= MainBattleOnActionAttacked;
                stronghold.MainBattle.ExitTurn           -= MainBattleOnExitTurn;
                stronghold.MainBattle.EnterBattle        -= MainBattleOnEnterBattle;

                // Set troop states to stationed and
                // send back anyone stationed here that doesn't belong
                // Make copy because it may change
                var stationedHere = stronghold.Troops.StationedHere().ToList();
                foreach (var stub in stationedHere)
                {
                    stub.BeginUpdate();
                    stub.State = TroopState.Stationed;
                    stub.EndUpdate();

                    if (stub.City.Owner.IsInTribe && stub.City.Owner.Tribesman.Tribe == stronghold.Tribe)
                    {
                        continue;
                    }

                    var troopInitializer   = troopInitializerFactory.CreateStationedTroopObjectInitializer(stub);
                    var retreatChainAction = actionFactory.CreateRetreatChainAction(stub.City.Id, troopInitializer);
                    var result             = stub.City.Worker.DoPassive(stub.City, retreatChainAction, true);
                    if (result != Error.Ok)
                    {
                        throw new Exception("Unexpected failure when retreating a unit from stronghold");
                    }
                }

                world.Remove(stronghold.MainBattle);
                dbManager.Delete(stronghold.MainBattle);
                stronghold.BeginUpdate();
                stronghold.GateOpenTo = null;
                stronghold.MainBattle = null;
                stronghold.GateMax    = (int)formula.StrongholdGateLimit(stronghold.Lvl);
                stronghold.Gate       = Math.Max(Math.Min(stronghold.GateMax, stronghold.Gate), formula.StrongholdGateHealHp(stronghold.StrongholdState, stronghold.Lvl));
                stronghold.State      = GameObjectStateFactory.NormalState();
                stronghold.EndUpdate();

                StateChange(ActionState.Completed);
            });
        }
示例#12
0
        private void AfterMainBattle(ActionState state)
        {
            if (state != ActionState.Completed)
            {
                return;
            }

            ICity       city;
            IStronghold targetStronghold;

            if (!gameObjectLocator.TryGetObjects(cityId, out city))
            {
                throw new Exception("City not found");
            }

            if (!gameObjectLocator.TryGetObjects(targetStrongholdId, out targetStronghold))
            {
                throw new Exception("Stronghold not found");
            }

            CallbackLock.CallbackLockHandler lockAll = delegate
            {
                var locks = targetStronghold.LockList().ToList();
                if (city.Owner.IsInTribe)
                {
                    locks.Add(city.Owner.Tribesman.Tribe);
                }

                return(locks.ToArray());
            };

            locker.Lock(lockAll, null, city, targetStronghold).Do(() =>
            {
                ITroopObject troopObject;
                if (!city.TryGetTroop(troopObjectId, out troopObject))
                {
                    throw new Exception("Troop object should still exist");
                }

                //Remove notification once battle is over
                city.Notifications.Remove(this);

                // Attack points from SH battles go to tribe
                if (city.Owner.IsInTribe)
                {
                    city.Owner.Tribesman.Tribe.AttackPoint += troopObject.Stats.AttackPoint;
                }

                city.BeginUpdate();
                city.AttackPoint += troopObject.Stats.AttackPoint;
                city.EndUpdate();

                // Remove troop if he's dead
                if (TroopIsDead(troopObject, city))
                {
                    StateChange(ActionState.Completed);
                    return;
                }

                if (city.Owner.IsInTribe && targetStronghold.Tribe == city.Owner.Tribesman.Tribe)
                {
                    // If our city is the one that now owns the stronghold then station there and we're done
                    StationTroopInStronghold(troopObject, targetStronghold);
                }
                else
                {
                    city.Notifications.Add(troopObject, this);
                    // Send troop back home
                    var tma = actionFactory.CreateTroopMovePassiveAction(city.Id,
                                                                         troopObject.ObjectId,
                                                                         city.PrimaryPosition.X,
                                                                         city.PrimaryPosition.Y,
                                                                         true,
                                                                         true);
                    ExecuteChainAndWait(tma, AfterTroopMovedHome);
                }
            });
        }
示例#13
0
        private void AfterTroopMoved(ActionState state)
        {
            if (state == ActionState.Fired)
            {
                // Verify the target is still good, otherwise we walk back immediately

                ICity        city;
                IStronghold  targetStronghold;
                ITroopObject troopObject;

                if (!gameObjectLocator.TryGetObjects(cityId, troopObjectId, out city, out troopObject))
                {
                    throw new Exception("City or troop object is missing");
                }

                if (!gameObjectLocator.TryGetObjects(targetStrongholdId, out targetStronghold))
                {
                    CancelCurrentChain();
                    return;
                }

                bool invalidTarget = false;
                locker.Lock(city, targetStronghold).Do(() =>
                {
                    invalidTarget = strongholdBattleProcedure.CanStrongholdBeDefended(city, targetStronghold) != Error.Ok;
                });

                // If the stronghold is not there or we are unable to attack/defense it, then cancel the current TroopMoveAction
                if (invalidTarget)
                {
                    CancelCurrentChain();
                }
            }
            else if (state == ActionState.Failed)
            {
                // If TroopMove failed it's because we cancelled it and the target is invalid. Walk back home
                ICity        city;
                ITroopObject troopObject;

                locker.Lock(cityId, troopObjectId, out city, out troopObject).Do(() =>
                {
                    TroopMovePassiveAction tma = actionFactory.CreateTroopMovePassiveAction(city.Id,
                                                                                            troopObject.ObjectId,
                                                                                            city.PrimaryPosition.X,
                                                                                            city.PrimaryPosition.Y,
                                                                                            true,
                                                                                            false);
                    ExecuteChainAndWait(tma, AfterTroopMovedHome);
                });
            }
            else if (state == ActionState.Completed)
            {
                ICity        city;
                IStronghold  targetStronghold;
                ITroopObject troopObject;

                if (!gameObjectLocator.TryGetObjects(cityId, troopObjectId, out city, out troopObject))
                {
                    throw new Exception("City or troop object is missing");
                }

                if (!gameObjectLocator.TryGetObjects(targetStrongholdId, out targetStronghold))
                {
                    throw new Exception("Stronghold is missing");
                }

                CallbackLock.CallbackLockHandler lockAll = delegate { return(targetStronghold.LockList().ToArray()); };

                locker.Lock(lockAll, null, city, targetStronghold).Do(() =>
                {
                    if (targetStronghold.Tribe == city.Owner.Tribesman.Tribe)
                    {
                        if (targetStronghold.MainBattle != null)
                        {
                            battleProcedure.AddReinforcementToBattle(targetStronghold.MainBattle, troopObject.Stub, FormationType.Defense);
                            StationTroopInStronghold(troopObject, targetStronghold, TroopState.BattleStationed);
                        }
                        else
                        {
                            StationTroopInStronghold(troopObject, targetStronghold);
                        }

                        return;
                    }

                    // Walk back to city if we dont own it anymore
                    TroopMovePassiveAction tma = actionFactory.CreateTroopMovePassiveAction(city.Id,
                                                                                            troopObject.ObjectId,
                                                                                            city.PrimaryPosition.X,
                                                                                            city.PrimaryPosition.Y,
                                                                                            true,
                                                                                            false);
                    ExecuteChainAndWait(tma, AfterTroopMovedHome);
                });
            }
        }
示例#14
0
 public IMultiObjectLock Lock(CallbackLock.CallbackLockHandler lockHandler,
                              object[] lockHandlerParams,
                              params ILockable[] baseLocks)
 {
     return(callbackLockFactory().Lock(lockHandler, lockHandlerParams, baseLocks));
 }
示例#15
0
        public void Remove(Session session, Packet packet)
        {
            uint playerId;

            try
            {
                playerId = packet.GetUInt32();
            }
            catch (Exception)
            {
                ReplyError(session, packet, Error.Unexpected);
                return;
            }

            IPlayer playerToBeRemoved;

            if (!world.TryGetObjects(playerId, out playerToBeRemoved))
            {
                ReplyError(session, packet, Error.PlayerNotFound);
                return;
            }

            CallbackLock.CallbackLockHandler lockHandler = delegate
            {
                var tribe = session.Player.IsInTribe ? session.Player.Tribesman.Tribe : null;

                if (tribe == null)
                {
                    return(new ILockable[] {});
                }

                var locks =
                    strongholdManager.StrongholdsForTribe(tribe)
                    .SelectMany(stronghold => stronghold.LockList())
                    .ToList();

                locks.Add(tribe);

                return(locks.ToArray());
            };

            locker.Lock(lockHandler, new object[] {}, session.Player, playerToBeRemoved).Do(() =>
            {
                if (!session.Player.IsInTribe || !playerToBeRemoved.IsInTribe ||
                    playerToBeRemoved.Tribesman.Tribe != session.Player.Tribesman.Tribe)
                {
                    ReplyError(session, packet, Error.TribeIsNull);
                    return;
                }

                ITribe tribe = session.Player.Tribesman.Tribe;
                if (!tribe.HasRight(session.Player.PlayerId, TribePermission.Kick))
                {
                    ReplyError(session, packet, Error.TribesmanNotAuthorized);
                    return;
                }

                if (tribe.IsOwner(playerToBeRemoved))
                {
                    ReplyError(session, packet, Error.TribesmanIsOwner);
                    return;
                }

                var result = session.Player.Tribesman.Tribe.KickTribesman(playerToBeRemoved, session.Player);

                ReplyWithResult(session, packet, result);
            });
        }
示例#16
0
        private void Subscribe(Session session, Packet packet)
        {
            uint battleId;

            try
            {
                battleId = packet.GetUInt32();
            }
            catch (Exception)
            {
                ReplyError(session, packet, Error.Unexpected);
                return;
            }

            IBattleManager battleManager;

            if (!world.TryGetObjects(battleId, out battleManager))
            {
                ReplyError(session, packet, Error.BattleNotViewable);
                return;
            }

            CallbackLock.CallbackLockHandler lockHandler = delegate
            {
                var toBeLocked = new List <ILockable>();

                toBeLocked.AddRange(battleManager.LockList);

                return(toBeLocked.ToArray());
            };

            locker.Lock(lockHandler, null, session.Player).Do(() =>
            {
                IEnumerable <string> errorParams;
                var canWatchBattle = battleManager.CanWatchBattle(session.Player, out errorParams);
                if (!Config.battle_instant_watch && canWatchBattle != Error.Ok)
                {
                    packet = ReplyError(session, packet, canWatchBattle, false);
                    packet.AddByte((byte)errorParams.Count());
                    foreach (var errorParam in errorParams)
                    {
                        packet.AddString(errorParam);
                    }
                    session.Write(packet);
                    return;
                }

                var reply = new Packet(packet);
                reply.AddByte((byte)battleManager.Location.Type);
                reply.AddUInt32(battleManager.Location.Id);
                reply.AddString(battleManager.Location.GetName());
                reply.AddUInt32(battleManager.Round);

                // Battle properties
                PacketHelper.AddBattleProperties(battleManager.ListProperties(), reply);
                PacketHelper.AddToPacket(battleManager.Attackers, reply);
                PacketHelper.AddToPacket(battleManager.Defenders, reply);

                try
                {
                    Global.Current.Channel.Subscribe(session, "/BATTLE/" + battleManager.BattleId);
                }
                catch (DuplicateSubscriptionException)
                {
                }

                session.Write(reply);
            });
        }
示例#17
0
        private void AfterTroopMoved(ActionState state)
        {
            if (state == ActionState.Fired)
            {
                // Verify the target is still good, otherwise we walk back immediately
                ICity        city;
                IStronghold  targetStronghold;
                ITroopObject troopObject;

                if (!gameObjectLocator.TryGetObjects(cityId, troopObjectId, out city, out troopObject))
                {
                    throw new Exception("City or troop object is missing");
                }

                if (!gameObjectLocator.TryGetObjects(targetStrongholdId, out targetStronghold))
                {
                    CancelCurrentChain();
                    return;
                }

                /*
                 * Commenting out this logic to return if stronghold is not attackable/defendable until we are able to correctly cancel assignments. At the moment,
                 * there are cases where when troops are in an assignment and a stronghold is taken over,
                 * the ones that are on the walk will return and then the ones that are dispatched will be sent to the stronghold.
                 *
                 * bool invalidTarget;
                 * using (locker.Lock(city, targetStronghold))
                 * {
                 *  invalidTarget = strongholdBattleProcedure.CanStrongholdBeAttacked(city, targetStronghold) != Error.Ok &&
                 *                  strongholdBattleProcedure.CanStrongholdBeDefended(city, targetStronghold) != Error.Ok;
                 * }
                 */

                // If player is no longer in a tribe, return
                if (!city.Owner.IsInTribe)
                {
                    CancelCurrentChain();
                }

                return;
            }

            if (state == ActionState.Failed)
            {
                // If TroopMove failed it's because we cancelled it and the target is invalid. Walk back home
                ICity        city;
                ITroopObject troopObject;

                locker.Lock(cityId, troopObjectId, out city, out troopObject).Do(() =>
                {
                    // Remove from remote stronghold and add only to this troop
                    city.Notifications.Remove(this);
                    city.Notifications.Add(troopObject, this);

                    TroopMovePassiveAction tma = actionFactory.CreateTroopMovePassiveAction(city.Id,
                                                                                            troopObject.ObjectId,
                                                                                            city.PrimaryPosition.X,
                                                                                            city.PrimaryPosition.Y,
                                                                                            true,
                                                                                            true);
                    ExecuteChainAndWait(tma, AfterTroopMovedHome);
                });

                return;
            }

            if (state == ActionState.Completed)
            {
                ICity        city;
                IStronghold  targetStronghold;
                ITroopObject troopObject;

                if (!gameObjectLocator.TryGetObjects(cityId, troopObjectId, out city, out troopObject))
                {
                    throw new Exception("City or troop object is missing");
                }

                if (!gameObjectLocator.TryGetObjects(targetStrongholdId, out targetStronghold))
                {
                    throw new Exception("Stronghold is missing");
                }

                CallbackLock.CallbackLockHandler lockAll = delegate { return(targetStronghold.LockList().ToArray()); };

                locker.Lock(lockAll, null, city, targetStronghold).Do(() =>
                {
                    if (city.Owner.IsInTribe)
                    {
                        if (targetStronghold.Tribe == city.Owner.Tribesman.Tribe)
                        {
                            if (targetStronghold.MainBattle != null)
                            {
                                MoveFromAttackToDefenseFormation(troopObject);
                                battleProcedure.AddReinforcementToBattle(targetStronghold.MainBattle, troopObject.Stub, FormationType.Defense);
                                StationTroopInStronghold(troopObject, targetStronghold, TroopState.BattleStationed);
                            }
                            else
                            {
                                StationTroopInStronghold(troopObject, targetStronghold);
                            }

                            return;
                        }

                        if (targetStronghold.GateOpenTo == city.Owner.Tribesman.Tribe)
                        {
                            // If stronghold's gate is open to the tribe, then it should engage the stronghold
                            JoinOrCreateStrongholdMainBattle(city);
                            return;
                        }

                        if (targetStronghold.GateOpenTo == null)
                        {
                            // If gate isn't open to anyone then engage the gate
                            var bea = actionFactory.CreateStrongholdEngageGateAttackPassiveAction(cityId,
                                                                                                  troopObject.ObjectId,
                                                                                                  targetStrongholdId);
                            ExecuteChainAndWait(bea, AfterGateBattle);
                            return;
                        }
                    }

                    city.Notifications.Remove(this);
                    city.Notifications.Add(troopObject, this);

                    // Walk back to city if none of the above conditions apply
                    TroopMovePassiveAction tma = actionFactory.CreateTroopMovePassiveAction(city.Id,
                                                                                            troopObject.ObjectId,
                                                                                            city.PrimaryPosition.X,
                                                                                            city.PrimaryPosition.Y,
                                                                                            true,
                                                                                            true);
                    ExecuteChainAndWait(tma, AfterTroopMovedHome);
                });
            }
        }