private void HandlePipeline(Config config) { var periods = new Dictionary <PipelineStage, TimeSpan> { [PipelineStage.Simplifying] = config.SimplifyingPeriod, [PipelineStage.CheckingRecipes] = config.CheckingRecipesPeriod, [PipelineStage.CheckingConversions] = config.CheckingConversionsPeriod }; foreach (var transaction in _credits.Concat(_debits)) { var info = transaction.Info; if (_updateTime > info.LastUpdate + periods.Get(info.Stage, TimeSpan.MaxValue)) { info.LastUpdate = _updateTime; ++info.Stage; Debug.WriteLine($"DEBUG: [{transaction.GetHashCode():X8}] is at {info.Stage}"); } } var session = _player.GetOrCreateSession(); foreach (var debit in _debits.Where(d => d.StackSize < 0 && d.Info.Stage == PipelineStage.Expired)) { // First, try to remove the expired debit from the player's inventory. If that fails, then give them an // infraction as a last resort. var playerItems = _player.GetAllItems().ToList(); for (var i = 0; i < playerItems.Count; ++i) { var playerItem = playerItems[i]; if (playerItem.type == debit.ItemId && playerItem.prefix == debit.PrefixId) { var payment = Math.Min(playerItem.stack, -debit.StackSize); Debug.Assert(payment > 0, "Payment must be positive."); playerItem.stack -= payment; debit.StackSize += payment; Debug.WriteLine($"DEBUG: [{debit.GetHashCode():X8}] paid for, x{payment}"); _player.SendData(PacketTypes.PlayerSlot, "", _player.Index, i, playerItem.prefix); } if (debit.StackSize == 0) { break; } } var item = debit.ToItem(); var points = -item.stack * config.PointOverrides.Get(item.type, config.Points.Get(item.rare)); if (points > 0) { session.AddInfraction(points, config.Duration, $"spawning {item.Name} x{-item.stack}"); } } _credits.RemoveAll(c => c.StackSize == 0 || c.Info.Stage == PipelineStage.Expired); _debits.RemoveAll(d => d.StackSize == 0 || d.Info.Stage == PipelineStage.Expired); }