Exemple #1
0
    // Start is called before the first frame update
    void Start()
    {
        // States init
        normal       = new NormalState();
        faster       = new FasterState();
        stronger     = new StrongerState();
        berzerk      = new BerzerkState();
        secondPeriod = new SecondPeriodState();

        // Stats init
        speed = Stats.BossStat.Speed;
        life  = Stats.BossStat.MaxHP;

        // AI init
        target            = GameObject.Find("Player").transform;
        seeker            = GetComponent <Pathfinding.Seeker>();
        rb                = GetComponent <Rigidbody2D>();
        groundCheckRadius = 0.25f;
        collisionLayer    = LayerMask.GetMask("Foundation");
        enemyGFX          = this.transform;

        InvokeRepeating("UpdatePath", 0f, 0.5f);

        // As the boss stats are updated widely during the fight we reset them at the begining
        //Stats.BossStat.ResetStat();
        // The first two bosses appear in their normal state
        if (Stats.BossStat.Level < 2)
        {
            stateMachine.Initialize(normal);
        }
        // All the other bosses do more damage on start
        else
        {
            stateMachine.Initialize(stronger);
        }
    }
        /// <summary>
        ///     A transactional (exactly once) processing loop that reads individual words and updates
        ///     the corresponding total count state.
        ///
        ///     When a rebalance occurs (including on startup), the count state for the incrementally
        ///     assigned partitions is reloaded before the loop commences to update it. For this use-
        ///     case, the CooperativeSticky assignor is much more efficient than the Range or RoundRobin
        ///     assignors since it keeps to a minimum the count state that needs to be materialized.
        /// </summary>
        /// <remarks>
        ///     Refer to Processor_MapWords for more detailed comments.
        /// </remarks>
        public static void Processor_AggregateWords(string brokerList, string clientId, CancellationToken ct)
        {
            if (clientId == null)
            {
                throw new Exception("Aggregate words processor requires that a client id is specified.");
            }

            var txnCommitPeriod = TimeSpan.FromSeconds(10);

            var pConfig = new ProducerConfig
            {
                BootstrapServers = brokerList,
                ClientId         = clientId + "_producer",
                TransactionalId  = TransactionalIdPrefix_Aggregate + "-" + clientId
            };

            var cConfig = new ConsumerConfig
            {
                BootstrapServers = brokerList,
                ClientId         = clientId + "_consumer",
                GroupId          = ConsumerGroup_Aggregate,
                AutoOffsetReset  = AutoOffsetReset.Earliest,
                // This should be greater than the maximum amount of time required to read in
                // existing count state. It should not be too large, since a rebalance may be
                // blocked for this long.
                MaxPollIntervalMs = 600000, // 10 minutes.
                EnableAutoCommit  = false,
                // Enable incremental rebalancing by using the CooperativeSticky
                // assignor (avoid stop-the-world rebalances). This is particularly important,
                // in the AggregateWords case, since the entire count state for newly assigned
                // partitions is loaded in the partitions assigned handler.
                PartitionAssignmentStrategy = PartitionAssignmentStrategy.CooperativeSticky,
            };

            var lastTxnCommit = DateTime.Now;

            using (var producer = new ProducerBuilder <string, int>(pConfig).Build())
                using (var consumer = new ConsumerBuilder <string, Null>(cConfig)
                                      .SetPartitionsRevokedHandler((c, partitions) => {
                    var remaining = c.Assignment.Where(tp => partitions.Where(x => x.TopicPartition == tp).Count() == 0);
                    Console.WriteLine(
                        "** AggregateWords consumer group partitions revoked: [" +
                        string.Join(',', partitions.Select(p => p.Partition.Value)) +
                        "], remaining: [" +
                        string.Join(',', remaining.Select(p => p.Partition.Value)) +
                        "]");

                    // Remove materialized word count state for the partitions that have been revoked.
                    foreach (var tp in partitions)
                    {
                        WordCountState[tp.Partition].Dispose();
                        WordCountState.Remove(tp.Partition);
                    }

                    producer.SendOffsetsToTransaction(
                        c.Assignment.Select(a => new TopicPartitionOffset(a, c.Position(a))),
                        c.ConsumerGroupMetadata,
                        DefaultTimeout);
                    producer.CommitTransaction();
                    producer.BeginTransaction();
                })

                                      .SetPartitionsLostHandler((c, partitions) => {
                    Console.WriteLine(
                        "** AggregateWords consumer group partitions lost: [" +
                        string.Join(',', partitions.Select(p => p.Partition.Value)) +
                        "]");

                    // clear materialized word count state for all partitions.
                    foreach (var tp in partitions)
                    {
                        WordCountState[tp.Partition].Dispose();
                        WordCountState.Remove(tp.Partition);
                    }

                    producer.AbortTransaction();
                    producer.BeginTransaction();
                })

                                      .SetPartitionsAssignedHandler((c, partitions) => {
                    Console.WriteLine(
                        "** AggregateWords consumer group partition assigned: [" +
                        string.Join(',', partitions.Select(p => p.Partition.Value)) +
                        "], all: [" +
                        string.Join(',', c.Assignment.Concat(partitions).Select(p => p.Partition.Value)) +
                        "]");

                    if (partitions.Count > 0)
                    {
                        // Initialize FASTER KV stores for each new partition.
                        foreach (var tp in partitions)
                        {
                            var partitionState = new FasterState(tp.Partition);
                            WordCountState.Add(tp.Partition, partitionState);
                        }

                        // Materialize count state for partitions into the FASTER KV stores.
                        // Note: the partiioning of Topic_Counts matches Topic_Words.
                        LoadCountState(brokerList, partitions.Select(tp => tp.Partition), ct);
                    }
                })
                                      .Build())
                {
                    consumer.Subscribe(Topic_Words);

                    producer.InitTransactions(DefaultTimeout);
                    producer.BeginTransaction();

                    var wCount = 0;

                    while (true)
                    {
                        try
                        {
                            ct.ThrowIfCancellationRequested();

                            var cr = consumer.Consume(TimeSpan.FromSeconds(1));

                            if (cr != null)
                            {
                                string key = cr.Message.Key;
                                var(_, count) = WordCountState[cr.Partition].Session.Read(cr.Message.Key);
                                count        += 1;
                                WordCountState[cr.Partition].Session.Upsert(key, count);

                                producer.Produce(Topic_Counts, new Message <string, int> {
                                    Key = cr.Message.Key, Value = count
                                });

                                wCount += 1;
                            }

                            if (DateTime.Now > lastTxnCommit + txnCommitPeriod)
                            {
                                producer.SendOffsetsToTransaction(
                                    // Note: committed offsets reflect the next message to consume, not last
                                    // message consumed. consumer.Position returns the last consumed offset
                                    // values + 1, as required.
                                    consumer.Assignment.Select(a => new TopicPartitionOffset(a, consumer.Position(a))),
                                    consumer.ConsumerGroupMetadata,
                                    DefaultTimeout);
                                producer.CommitTransaction();

                                producer.BeginTransaction();

                                Console.WriteLine($"Committed AggregateWords transaction(s) comprising updates to {wCount} words.");
                                lastTxnCommit = DateTime.Now;
                                wCount        = 0;
                            }
                        }
                        catch (Exception e)
                        {
                            producer.AbortTransaction();

                            Console.WriteLine("Exiting AggregateWords consume loop due to an exception: " + e);
                            consumer.Close();
                            Console.WriteLine("AggregateWords consumer closed");
                            break;
                        }
                    }
                }
        }