I’m working on a player inventory system for a game.
I have a struct Slot which has a List<Loot> collection that represents which kinds of items are allowed in it. The abstract class Loot is subclassed by all items which are lootable – i.e.: would be valid Content values for the Slot struct.
I want to express that a Slot can have restrictions on what subclasses of Loot it can contain. For instance, if the Slot represents an ammo container, I want it to only hold Loot subclasses which are ammo containers, like “Quivers” and “Shot Pouches” (which would subclass Container somewhere along the line).
Loot class
public abstract class Loot : GameEntity, ILootable
{
public int MaxUnitsPerStack { get; set; }
public int MaxUnitsCarriable { get; set; }
public int MaxUnitsOwnable { get; set; }
public void Stack() { }
public void Split() { }
public void Scrap() { }
}
Container class
public abstract class Container : Loot
{
public List<Slot> Slots { get; set; }
public Container(int slots)
{
this.Slots = new List<Slot>(slots);
}
}
Slot struct
public struct Slot
{
public Loot Content;
public int Count;
public List<Loot> ExclusiveLootTypes;
public Slot(Loot[] exclusiveLootTypes)
{
this.Content = null;
this.Count = 0;
List<Loot> newList;
if (exclusiveLootTypes.Count() > 0)
{
newList = new List<Loot>(exclusiveLootTypes.Count());
foreach (Loot l in exclusiveLootTypes)
{
newList.Add(l);
}
}
else { newList = new List<Loot>(); }
this.ExclusiveLootTypes = newList;
}
}
PlayerInventory
public struct PlayerInventory
{
static Dictionary<Slot, string> Slots;
static void Main()
{
Slots = new Dictionary<Slot, string>();
/* Add a bunch of slots */
Slots.Add(new Slot(/* I don't know the
syntax for this:
Quiver, Backpack */), "Backpack"); // Container
}
}
I don’t know how to provide the arguments for the Loot subclasses in the Slot constructor call in the Main method of the PlayerInventory class.
I hope this is clear. Thanks in advance.
EDIT
I was able to solve this (and by that, I mean get it to compile) using David Sieler’s approach along with some Reflection.
Slot struct
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
public struct Slot
{
private Loot _content;
private int _count;
public List ExclusiveLootTypes;
public Loot Content
{
get { return _content; }
private set
{
if ((ExclusiveLootTypes.Contains(value.GetType())) && (value.GetType().IsSubclassOf(Type.GetType("Loot"))))
{
_content = value;
}
}
}
public int Count
{
get { return _count; }
set { _count = value; }
}
public Slot(params Type[] exclusiveLootTypes)
{
this._content = null;
this._count = 0;
List newList;
if (exclusiveLootTypes.Count() > 0)
{
newList = new List(exclusiveLootTypes.Count());
foreach (Type l in exclusiveLootTypes)
{
newList.Add(l);
}
}
else { newList = new List(); }
this.ExclusiveLootTypes = newList;
}
}
PlayerInventory call to Slot constructor
Slots.Add(new Slot(typeof(Backpack)));
Thanks again everyone for the discussion.
One approach would be to pass an array of
Typeobjects to the Slot constructor:Then write a property setter for
Contentthat checks the type of the assigned object, and signals some sort of error if that type isn’t contained in ExclusiveLootTypes.