コード例 #1
0
        public void Test()
        {
            IThingFactory factory = Registry.Factory.Create <IThingFactory>();
            IThing        thing   = factory.CreateItem();

            Assert.AreEqual(typeof(Thing), thing.GetType());
            Assert.IsInstanceOf(typeof(IThing), thing);

            thing = factory.CreateItem <object>(null);
            Assert.AreEqual(typeof(Thing), thing.GetType());
            Assert.IsInstanceOf(typeof(IThing), thing);

            thing = factory.CreateItem <Empty>(new Empty());
            Assert.AreEqual(typeof(Thing), thing.GetType());
            Assert.IsInstanceOf(typeof(IThing), thing);

            thing = factory.CreateItem(new Empty());
            Assert.AreEqual(typeof(Thing), thing.GetType());
            Assert.IsInstanceOf(typeof(IThing), thing);

            thing = factory.CreateItem("");
            Assert.IsInstanceOf(typeof(IThing <string>), thing);
            thing = factory.CreateItem <object>("");
            Assert.IsInstanceOf(typeof(IThing <string>), thing);

            thing = factory.CreateItem(0);
            Assert.IsInstanceOf(typeof(INumberThing), thing);
            thing = factory.CreateItem <object>(0);
            Assert.IsInstanceOf(typeof(INumberThing), thing);

            thing = factory.CreateItem(0f);
            Assert.IsInstanceOf(typeof(INumberThing), thing);
            thing = factory.CreateItem <object>(0f);
            Assert.IsInstanceOf(typeof(INumberThing), thing);

            thing = factory.CreateItem(0d);
            Assert.IsInstanceOf(typeof(INumberThing), thing);
            thing = factory.CreateItem <object>(0d);
            Assert.IsInstanceOf(typeof(INumberThing), thing);

            thing = factory.CreateItem(DateTime.Now);
            Assert.IsInstanceOf(typeof(INumberThing), thing);
            thing = factory.CreateItem <object>(DateTime.Now);
            Assert.IsInstanceOf(typeof(INumberThing), thing);

            thing = factory.CreateItem(new Quad16(0, 0, 0, 0));
            Assert.IsInstanceOf(typeof(INumberThing), thing);
            thing = factory.CreateItem <object>(new Quad16(0, 0, 0, 0));
            Assert.IsInstanceOf(typeof(INumberThing), thing);

            using (var stream = new MemoryStream()) {
                thing = factory.CreateItem(stream);
                Assert.IsInstanceOf(typeof(IStreamThing), thing);
                thing = factory.CreateItem <object> (stream);
                Assert.IsInstanceOf(typeof(IStreamThing), thing);
            }

            thing = factory.CreateItem <Stream>(null);
            Assert.IsInstanceOf(typeof(IStreamThing), thing);
        }
コード例 #2
0
        /// <summary>
        /// Attempts to replace a <see cref="IThing"/> from this container with another.
        /// </summary>
        /// <param name="thingFactory">A reference to the factory of things to use.</param>
        /// <param name="fromThing">The <see cref="IThing"/> to remove from the container.</param>
        /// <param name="toThing">The <see cref="IThing"/> to add to the container.</param>
        /// <param name="index">Optional. The index from which to replace the <see cref="IThing"/>. Defaults to byte.MaxValue, which instructs to replace the <see cref="IThing"/> if found at any index.</param>
        /// <param name="amount">Optional. The amount of the <paramref name="fromThing"/> to replace.</param>
        /// <returns>A tuple with a value indicating whether the attempt was at least partially successful, and false otherwise. If the result was only partially successful, a remainder of the thing may be returned.</returns>
        public (bool result, IThing remainderToChange) ReplaceContent(IThingFactory thingFactory, IThing fromThing, IThing toThing, byte index = byte.MaxValue, byte amount = 1)
        {
            if (this.Inventory[index] is IContainerItem bodyContainer)
            {
                return(bodyContainer.ReplaceContent(thingFactory, fromThing, toThing, DefaultBodyContainerIndex, amount));
            }

            return(false, fromThing);
        }
コード例 #3
0
        public void TestIThingFactory()
        {
            IThingFactory itf   = ThingFactory.GiveMeAFactory();
            IThing        thing =
                itf
                .AddInteger(94)
                .AddString("hello, world")
                .Create();

            Assert.AreEqual(94, thing.SomeIntegerFunction(8));
            Assert.AreEqual("goodbye", thing.SaySomething("g'day"));
        }
コード例 #4
0
        /// <summary>
        /// Attempts to remove a thing from this container.
        /// </summary>
        /// <param name="thingFactory">A reference to the factory of things to use.</param>
        /// <param name="thing">The <see cref="IThing"/> to remove from the container.</param>
        /// <param name="index">Optional. The index from which to remove the <see cref="IThing"/>. Defaults to byte.MaxValue, which instructs to remove the <see cref="IThing"/> if found at any index.</param>
        /// <param name="amount">Optional. The amount of the <paramref name="thing"/> to remove.</param>
        /// <returns>A tuple with a value indicating whether the attempt was at least partially successful, and false otherwise. If the result was only partially successful, a remainder of the thing may be returned.</returns>
        public virtual (bool result, IThing remainder) RemoveContent(IThingFactory thingFactory, ref IThing thing, byte index = byte.MaxValue, byte amount = 1)
        {
            thingFactory.ThrowIfNull(nameof(thingFactory));
            thing.ThrowIfNull(nameof(thing));

            if (!(thingFactory is IItemFactory itemFactory))
            {
                throw new ArgumentException($"The {nameof(thingFactory)} must be derived of type {nameof(IItemFactory)}.");
            }

            IItem  existingItem = null;
            ushort thingId      = thing.TypeId;

            if (index == byte.MaxValue)
            {
                existingItem = this.Content.FirstOrDefault(i => i.TypeId == thingId);
            }
            else
            {
                // Attempt to get the item at that index.
                existingItem = index >= this.Content.Count ? null : this.Content[index];
            }

            if (existingItem == null || thing.TypeId != existingItem.TypeId || existingItem.Amount < amount)
            {
                return(false, null);
            }

            if (!existingItem.IsCumulative || existingItem.Amount == amount)
            {
                // Item has the exact amount we're looking for, just remove it.
                this.Content.RemoveAt(index);
                this.InvokeContentRemoved(index);

                return(true, null);
            }

            (bool success, IItem itemProduced) = existingItem.Split(itemFactory, amount);

            if (success)
            {
                if (itemProduced != null)
                {
                    thing = itemProduced;
                }

                // We've changed an item at this index, so we notify observers.
                this.InvokeContentUpdated(index, existingItem);
            }

            return(success, existingItem);
        }
コード例 #5
0
        public static IThingFactory ThingFactory(this IGraph <IVisual, IVisualEdge> graph)
        {
            IThingFactory result      = null;
            var           sourceGraph = graph.Source <IVisual, IVisualEdge, IThing, ILink>();

            if (sourceGraph != null)
            {
                var adapter = sourceGraph.Mapper.Transformer as VisualThingTransformer;
                result = adapter?.ThingFactory;
            }
            if (result == null)
            {
                result = Registry.Factory.Create <IThingFactory>();
            }
            return(result);
        }
コード例 #6
0
ファイル: Tile.cs プロジェクト: OpenTibiaArchives/fibula-mmo
        /// <summary>
        /// Attempts to replace a <see cref="IThing"/> from this container with another.
        /// </summary>
        /// <param name="thingFactory">A reference to the factory of things to use.</param>
        /// <param name="fromThing">The <see cref="IThing"/> to remove from the container.</param>
        /// <param name="toThing">The <see cref="IThing"/> to add to the container.</param>
        /// <param name="index">Optional. The index from which to replace the <see cref="IThing"/>. Defaults to byte.MaxValue, which instructs to replace the <see cref="IThing"/> if found at any index.</param>
        /// <param name="amount">Optional. The amount of the <paramref name="fromThing"/> to replace.</param>
        /// <returns>A tuple with a value indicating whether the attempt was at least partially successful, and false otherwise. If the result was only partially successful, a remainder of the thing may be returned.</returns>
        public (bool result, IThing remainderToChange) ReplaceContent(IThingFactory thingFactory, IThing fromThing, IThing toThing, byte index = byte.MaxValue, byte amount = 1)
        {
            (bool removeSuccessful, IThing removeRemainder) = this.RemoveContent(thingFactory, ref fromThing, index, amount);

            if (!removeSuccessful)
            {
                return(false, removeRemainder);
            }

            if (removeRemainder != null)
            {
                (bool addedRemainder, IThing remainderOfRemainder) = this.AddContent(thingFactory, removeRemainder, byte.MaxValue);

                if (!addedRemainder)
                {
                    return(false, remainderOfRemainder);
                }
            }

            return(this.AddContent(thingFactory, toThing, index));
        }
コード例 #7
0
        /// <summary>
        /// Attempts to replace a <see cref="IThing"/> from this container with another.
        /// </summary>
        /// <param name="thingFactory">A reference to the factory of things to use.</param>
        /// <param name="fromThing">The <see cref="IThing"/> to remove from the container.</param>
        /// <param name="toThing">The <see cref="IThing"/> to add to the container.</param>
        /// <param name="index">Optional. The index from which to replace the <see cref="IThing"/>. Defaults to byte.MaxValue, which instructs to replace the <see cref="IThing"/> if found at any index.</param>
        /// <param name="amount">Optional. The amount of the <paramref name="fromThing"/> to replace.</param>
        /// <returns>A tuple with a value indicating whether the attempt was at least partially successful, and false otherwise. If the result was only partially successful, a remainder of the thing may be returned.</returns>
        public (bool result, IThing remainderToChange) ReplaceContent(IThingFactory thingFactory, IThing fromThing, IThing toThing, byte index = byte.MaxValue, byte amount = 1)
        {
            thingFactory.ThrowIfNull(nameof(thingFactory));
            fromThing.ThrowIfNull(nameof(fromThing));
            toThing.ThrowIfNull(nameof(toThing));

            if (!(thingFactory is IItemFactory itemFactory))
            {
                throw new ArgumentException($"The {nameof(thingFactory)} must be derived of type {nameof(IItemFactory)}.");
            }

            IItem existingItem = null;

            if (index == byte.MaxValue)
            {
                existingItem = this.Content.FirstOrDefault(i => i.TypeId == fromThing.TypeId);
            }
            else
            {
                // Attempt to get the item at that index.
                existingItem = index >= this.Content.Count ? null : this.Content[index];
            }

            if (existingItem == null || fromThing.TypeId != existingItem.TypeId || existingItem.Amount < amount)
            {
                return(false, null);
            }

            this.Content.RemoveAt(index);
            this.Content.Insert(index, toThing as IItem);

            toThing.ParentContainer = this;

            // We've changed an item at this index, so we notify observers.
            this.InvokeContentUpdated(index, toThing as IItem);

            return(true, null);
        }
コード例 #8
0
 /// <summary>
 /// Attempts to remove a thing from this container.
 /// </summary>
 /// <param name="thingFactory">A reference to the factory of things to use.</param>
 /// <param name="thing">The <see cref="IThing"/> to remove from the container.</param>
 /// <param name="index">Optional. The index from which to remove the <see cref="IThing"/>. Defaults to byte.MaxValue, which instructs to remove the <see cref="IThing"/> if found at any index.</param>
 /// <param name="amount">Optional. The amount of the <paramref name="thing"/> to remove.</param>
 /// <returns>A tuple with a value indicating whether the attempt was at least partially successful, and false otherwise. If the result was only partially successful, a remainder of the thing may be returned.</returns>
 public (bool result, IThing remainder) RemoveContent(IThingFactory thingFactory, ref IThing thing, byte index = byte.MaxValue, byte amount = 1)
 {
     // TODO: try to delete from that specific body container.
     throw new NotImplementedException();
 }
コード例 #9
0
 /// <summary>
 /// Attempts to add a <see cref="IThing"/> to this container.
 /// </summary>
 /// <param name="thingFactory">A reference to the factory of things to use.</param>
 /// <param name="thing">The <see cref="IThing"/> to add to the container.</param>
 /// <param name="index">Optional. The index at which to add the <see cref="IThing"/>. Defaults to byte.MaxValue, which instructs to add the <see cref="IThing"/> at any free index.</param>
 /// <returns>A tuple with a value indicating whether the attempt was at least partially successful, and false otherwise. If the result was only partially successful, a remainder of the thing may be returned.</returns>
 public (bool result, IThing remainder) AddContent(IThingFactory thingFactory, IThing thing, byte index = byte.MaxValue)
 {
     // TODO: try to add at that specific body container.
     return(false, thing);
 }
コード例 #10
0
 public ThingContentFacade(IThingFactory factory)
 {
     _factory = factory;
 }
コード例 #11
0
 public ThingModelBinder(IThingFactory thingFactory)
 {
     this.IThingFactory = thingFactory;
 }
コード例 #12
0
 /// <summary>
 /// Initializes a new instance of the <see cref="WorldGenerator"/> class.
 /// </summary>
 /// <param name="seed">The seed to use.</param>
 /// <param name="thingFactory">The thing factory.</param>
 public WorldGenerator(int seed, IThingFactory thingFactory)
 {
     this.Seed         = seed;
     this.Random       = new Random(this.Seed);
     this.thingFactory = thingFactory;
 }
コード例 #13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="WorldGenerator"/> class.
 /// </summary>
 /// <param name="thingFactory">The thing factory.</param>
 public WorldGenerator(IThingFactory thingFactory)
 {
     this.Seed         = new Random().Next();
     this.Random       = new Random(this.Seed);
     this.thingFactory = thingFactory;
 }
コード例 #14
0
        /// <summary>
        /// Attempts to add a <see cref="IThing"/> to this container.
        /// </summary>
        /// <param name="thingFactory">A reference to the factory of things to use.</param>
        /// <param name="thing">The <see cref="IThing"/> to add to the container.</param>
        /// <param name="index">Optional. The index at which to add the <see cref="IThing"/>. Defaults to byte.MaxValue, which instructs to add the <see cref="IThing"/> at any free index.</param>
        /// <returns>A tuple with a value indicating whether the attempt was at least partially successful, and false otherwise. If the result was only partially successful, a remainder of the thing may be returned.</returns>
        public override (bool result, IThing remainder) AddContent(IThingFactory thingFactory, IThing thing, byte index = byte.MaxValue)
        {
            thingFactory.ThrowIfNull(nameof(thingFactory));
            thing.ThrowIfNull(nameof(thing));

            if (!(thingFactory is IItemFactory itemFactory))
            {
                throw new ArgumentException($"The {nameof(thingFactory)} must be derived of type {nameof(IItemFactory)}.");
            }

            if (!(thing is IItem item))
            {
                // Containers like this can only add items.
                return(false, null);
            }

            // Validate that the item being added is not a parent of this item.
            if (this.IsChildOf(item) || !this.CanDressItemHere(item))
            {
                // TODO: error message 'This is impossible'.
                return(false, thing);
            }

            // Find an index which falls in within the actual content boundaries.
            var targetIndex = index < this.Content.Count ? index : -1;

            // Then get an item if there is one, at that index.
            var existingItemAtIndex = targetIndex == -1 ? this.Content.FirstOrDefault() : this.Content[targetIndex];

            (bool success, IThing remainderItem) = (false, item);

            if (existingItemAtIndex != null)
            {
                // We matched with an item, let's attempt to add or join with it first.
                if (existingItemAtIndex.IsContainer && existingItemAtIndex is IContainerItem existingContainer)
                {
                    return(existingContainer.AddContent(itemFactory, remainderItem));
                }
                else
                {
                    (success, remainderItem) = existingItemAtIndex.Merge(remainderItem as IItem);

                    if (success)
                    {
                        // Regardless if we're done, we've changed an item at this index, so we notify observers.
                        this.InvokeContentUpdated((byte)targetIndex, remainderItem as IItem);
                    }
                }
            }

            if (success)
            {
                // If we have partially succeeded, we need to return now.
                return(true, remainderItem);
            }

            if (existingItemAtIndex == null)
            {
                remainderItem.ParentContainer = this;

                this.Content.Insert(0, remainderItem as IItem);

                this.InvokeContentAdded(remainderItem as IItem);

                remainderItem = null;
            }
            else
            {
                // Swap the items.
                this.Content.Clear();

                remainderItem.ParentContainer = this;

                this.Content.Insert(0, remainderItem as IItem);
                this.InvokeContentUpdated(0, remainderItem as IItem);

                remainderItem = existingItemAtIndex;
            }

            return(true, remainderItem);
        }
コード例 #15
0
ファイル: Tile.cs プロジェクト: OpenTibiaArchives/fibula-mmo
        /// <summary>
        /// Attempts to remove a specific thing from this container.
        /// </summary>
        /// <param name="thingFactory">A reference to the factory of things to use.</param>
        /// <param name="thing">The <see cref="IThing"/> to remove from the container.</param>
        /// <param name="index">Optional. The index from which to remove the <see cref="IThing"/>. Defaults to byte.MaxValue, which instructs to remove the <see cref="IThing"/> if found at any index.</param>
        /// <param name="amount">Optional. The amount of the <paramref name="thing"/> to remove.</param>
        /// <returns>A tuple with a value indicating whether the attempt was at least partially successful, and false otherwise. If the result was only partially successful, a remainder of the thing may be returned.</returns>
        public (bool result, IThing remainder) RemoveContent(IThingFactory thingFactory, ref IThing thing, byte index = byte.MaxValue, byte amount = 1)
        {
            thingFactory.ThrowIfNull(nameof(thingFactory));

            if (!(thingFactory is IItemFactory itemFactory))
            {
                throw new ArgumentException($"The {nameof(thingFactory)} must be derived of type {nameof(IItemFactory)}.");
            }

            if (amount == 0)
            {
                throw new ArgumentException($"Invalid {nameof(amount)} zero.");
            }

            IItem remainder = null;

            if (thing is ICreature creature)
            {
                return(this.InternalRemoveCreature(creature), null);
            }
            else if (thing is IItem item)
            {
                if (item.IsGround)
                {
                    if (this.Ground != item)
                    {
                        return(false, item);
                    }

                    this.Ground = null;
                }
                else if (item.IsGroundFix)
                {
                    if (amount > 1)
                    {
                        throw new ArgumentException($"Invalid {nameof(amount)} while removing a ground border item: {amount}.");
                    }

                    return(this.InternalRemoveGroundBorderItem(thing), null);
                }
                else if (item.IsLiquidPool)
                {
                    if (this.LiquidPool != item)
                    {
                        return(false, item);
                    }

                    this.LiquidPool = null;
                }
                else if (item.StaysOnTop)
                {
                    if (amount > 1)
                    {
                        throw new ArgumentException($"Invalid {nameof(amount)} while removing a stay-on-top item: {amount}.");
                    }

                    return(this.InternalRemoveStayOnTopItem(thing), null);
                }
                else if (item.StaysOnBottom)
                {
                    if (amount > 1)
                    {
                        throw new ArgumentException($"Invalid {nameof(amount)} while removing a stay-on-bottom item: {amount}.");
                    }

                    return(this.InternalRemoveStayOnBottomItem(thing), null);
                }
                else
                {
                    lock (this.tileLock)
                    {
                        if ((!item.IsCumulative && amount > 1) || (item.IsCumulative && item.Amount < amount))
                        {
                            return(false, null);
                        }

                        if (!item.IsCumulative || item.Amount == amount)
                        {
                            // Since we have the exact amount, we can remove the item instance from the tile.
                            this.itemsOnTile.Pop();
                        }
                        else
                        {
                            // We're removing less than the entire amount, so we need to calculate the remainder to add back.
                            var newExistingAmount = (byte)(item.Amount - amount);

                            item.Amount = newExistingAmount;

                            // item amount is left wrong.

                            // Create a new item as the remainder.
                            remainder = itemFactory.CreateItem(new ItemCreationArguments()
                            {
                                TypeId = item.Type.TypeId
                            });

                            remainder.Amount = amount;

                            thing     = remainder;
                            remainder = item;
                        }
                    }
                }
            }
            else
            {
                throw new InvalidCastException($"Thing did not cast to either a {nameof(ICreature)} or {nameof(IItem)}.");
            }

            // Update the tile's version so that it invalidates the cache.
            this.LastModified = DateTimeOffset.UtcNow;

            return(true, remainder);
        }
コード例 #16
0
ファイル: Tile.cs プロジェクト: OpenTibiaArchives/fibula-mmo
        /// <summary>
        /// Attempts to add a <see cref="IThing"/> to this container.
        /// </summary>
        /// <param name="thingFactory">A reference to the factory of things to use.</param>
        /// <param name="thing">The <see cref="IThing"/> to add to the container.</param>
        /// <param name="index">Optional. The index at which to add the <see cref="IThing"/>. Defaults to byte.MaxValue, which instructs to add the <see cref="IThing"/> at any free index.</param>
        /// <returns>A tuple with a value indicating whether the attempt was at least partially successful, and false otherwise. If the result was only partially successful, a remainder of the thing may be returned.</returns>
        public (bool result, IThing remainder) AddContent(IThingFactory thingFactory, IThing thing, byte index = byte.MaxValue)
        {
            thingFactory.ThrowIfNull(nameof(thingFactory));

            if (!(thingFactory is IItemFactory itemFactory))
            {
                throw new ArgumentException($"The {nameof(thingFactory)} must be derived of type {nameof(IItemFactory)}.");
            }

            lock (this.tileLock)
            {
                if (thing is ICreature creature)
                {
                    this.creaturesOnTile.Push(creature);
                }
                else if (thing is IItem item)
                {
                    if (item.IsGround)
                    {
                        this.Ground = item;
                    }
                    else if (item.IsGroundFix)
                    {
                        this.groundBorders.Push(item);
                    }
                    else if (item.IsLiquidPool)
                    {
                        this.LiquidPool = item;
                    }
                    else if (item.StaysOnTop)
                    {
                        this.stayOnTopItems.Push(item);
                    }
                    else if (item.StaysOnBottom)
                    {
                        this.stayOnBottomItems.Push(item);
                    }
                    else
                    {
                        var remainingAmountToAdd = item.Amount;

                        while (remainingAmountToAdd > 0)
                        {
                            if (!item.IsCumulative)
                            {
                                this.itemsOnTile.Push(item);
                                break;
                            }

                            var existingItem = this.itemsOnTile.Count > 0 ? this.itemsOnTile.Peek() : null;

                            // Check if there is an existing top item and if it is of the same type.
                            if (existingItem == null || existingItem.Type != item.Type || existingItem.Amount >= ItemConstants.MaximumAmountOfCummulativeItems)
                            {
                                this.itemsOnTile.Push(item);
                                break;
                            }

                            remainingAmountToAdd += existingItem.Amount;

                            // Modify the existing item with the new amount, or the maximum permitted.
                            var newExistingAmount = Math.Min(remainingAmountToAdd, ItemConstants.MaximumAmountOfCummulativeItems);

                            existingItem.Amount = newExistingAmount;

                            remainingAmountToAdd -= newExistingAmount;

                            if (remainingAmountToAdd == 0)
                            {
                                break;
                            }

                            item = itemFactory.CreateItem(new ItemCreationArguments()
                            {
                                TypeId = item.Type.TypeId
                            });

                            item.Amount = remainingAmountToAdd;

                            item.ParentContainer = this;
                        }
                    }

                    // Update the tile's version so that it invalidates the cache.
                    // TOOD: if we start caching creatures, move to outer scope.
                    this.LastModified = DateTimeOffset.UtcNow;
                }
            }

            if (thing != null && thing is IContainedThing containedThing)
            {
                containedThing.ParentContainer = this;
            }

            return(true, null);
        }
コード例 #17
0
        /// <summary>
        /// Attempts to add a <see cref="IThing"/> to this container.
        /// </summary>
        /// <param name="thingFactory">A reference to the factory of things to use.</param>
        /// <param name="thing">The <see cref="IThing"/> to add to the container.</param>
        /// <param name="index">Optional. The index at which to add the <see cref="IThing"/>. Defaults to byte.MaxValue, which instructs to add the <see cref="IThing"/> at any free index.</param>
        /// <returns>A tuple with a value indicating whether the attempt was at least partially successful, and false otherwise. If the result was only partially successful, a remainder of the thing may be returned.</returns>
        public virtual (bool result, IThing remainder) AddContent(IThingFactory thingFactory, IThing thing, byte index = byte.MaxValue)
        {
            thingFactory.ThrowIfNull(nameof(thingFactory));
            thing.ThrowIfNull(nameof(thing));

            if (!(thingFactory is IItemFactory itemFactory))
            {
                throw new ArgumentException($"The {nameof(thingFactory)} must be derived of type {nameof(IItemFactory)}.");
            }

            if (!(thing is IItem item))
            {
                // Containers like this can only add items.
                return(false, null);
            }

            // Validate that the item being added is not itself, or a parent of this item.
            if (thing == this || this.IsChildOf(item))
            {
                // TODO: error message 'This is impossible'.
                return(false, thing);
            }

            // Find an index which falls in within the actual content boundaries.
            var targetIndex = index < this.Content.Count ? index : -1;
            var atCapacity  = this.Capacity == this.Content.Count;

            // Then get an item if there is one, at that index.
            var existingItemAtIndex = targetIndex == -1 ? null : this.Content[targetIndex];

            (bool success, IThing remainderToAdd) = (false, item);

            if (existingItemAtIndex != null)
            {
                // We matched with an item, let's attempt to add or join with it first.
                if (existingItemAtIndex.IsContainer && existingItemAtIndex is IContainerItem existingContainer)
                {
                    (success, remainderToAdd) = existingContainer.AddContent(itemFactory, remainderToAdd);
                }
                else
                {
                    (success, remainderToAdd) = existingItemAtIndex.Merge(remainderToAdd as IItem);

                    if (success)
                    {
                        // Regardless if we're done, we've changed an item at this index, so we notify observers.
                        if (remainderToAdd != null && !atCapacity)
                        {
                            targetIndex++;
                        }

                        this.InvokeContentUpdated((byte)targetIndex, existingItemAtIndex);
                    }
                }
            }

            if (remainderToAdd == null)
            {
                // If there's nothing still waiting to be added, we're done.
                return(true, null);
            }

            // Now we need to add whatever is remaining to this container.
            if (atCapacity)
            {
                // This is full.
                return(success, remainderToAdd);
            }

            remainderToAdd.ParentContainer = this;

            this.Content.Insert(0, remainderToAdd as IItem);

            this.InvokeContentAdded(remainderToAdd as IItem);

            return(true, null);
        }