-
Notifications
You must be signed in to change notification settings - Fork 9
Adapter extensibility
MechTransfer implements a simple way of adding support for different item containers using TModLoader's call()
functionality.
First, you should define a class to contain the necessary methods for the adapter. This class should have the following layout:
class MyAdapter
{
public bool InjectItem(int x, int y, Item item)
{
return false;
}
public IEnumerable<Tuple<Item, object>> EnumerateItems(int x, int y)
{
yield break;
}
public void TakeItem(int x, int y, object slot, int amount)
{
}
}
The adapter should also sync the state of the adapter in multiplayer. These adapter functions will only be called on the server.
This method will be called when a device tries to inject a stack item into the container.
-
int x
- This is the x coordinate of the targeted tile. -
int y
- This is the y coordinate of the targeted tile. -
Item item
- This is the item, that the device is trying to inject.
item.Stack
should be decremented by the number of items the container was able to receive.
The method should return true
if it was able to receive at least one item. This will trigger the visual effects.
(The method may return true
even if item.Stack
was not decremented. The Omni turret adapter does this when it receives infinite ammo items, such as the Endless Quiver.) item
may not be stored in the container directly, it should be cloned via item.Clone()
. The method may simply return false
and remain otherwise unimplemented if the container does not support injection.
This method is used to query the items stored by the container.
-
int x
- This is the x coordinate of the targeted tile. -
int y
- This is the y coordinate of the targeted tile.
In most cases EnumerateItems
will be an iterator method. It should yield a Tuple for each slot that the container has. Item1
of the Tuple should be an Item
object representing the stored stack of items in the slot. The Stack
value of this item should not be larger than maxStack
. It is safe to use the item object stored by the container directly, it will not be modified. Item2
of the tuple should be a key, that identifies the slot. MechTransfer does not use this value directly, it will be sent to TakeItem
to specify the slot. If the container does not use a slot based system, Item2
may be null. The method may simply yield break
and remain otherwise unimplemented if the container does not support item extraction.
This method may be called immediately after EnumerateItems
if a device has successfully transferred an item.
-
int x
- This is the x coordinate of the targeted tile. -
int y
- This is the y coordinate of the targeted tile. -
object slot
- This is the slot identifier, as specified inEnumerateItems
. -
int amount
- The number of items that were transferred.
Amount will always be less then or equal to the Stack
value of the item returned by EnumerateItems
for the slot. This method may remain unimplemented if the container does not implement EnumerateItems
.
For a general use case see ChestAdapter or ItemFrameAdapter. For an example of a partially implemented adapter see CrystalStandAdapter.
Adapters have to register to MechTransfer via Call()
. This should always happen in PostSetupContent()
. There are two different way to register adapters.
public override void PostSetupContent()
{
Mod mechTansfer = ModLoader.GetMod("MechTransfer");
if (mechTansfer != null)
{
MyAdapter adapter = new MyAdapter();
mechTansfer.Call("RegisterAdapterReflection", adapter, new int[] { TileType<MyContainerTile>() });
}
}
The third argument to mechTansfer.Call
is an array containing the tile types this adapter should be used for. In this case, the names of the adapter methods should exactly match the ones outlined above. Although these methods will be loaded through reflection, there shouldn't be any noticeable performance drop.
public override void PostSetupContent()
{
Mod mechTansfer = ModLoader.GetMod("MechTransfer");
if (mechTansfer != null)
{
MyAdapter adapter = new MyAdapter();
Func<int, int, Item, bool> injectMethod = new Func<int, int, Item, bool>(adapter.InjectItem);
Func<int, int, IEnumerable<Tuple<Item, object>>> enumerateMethod = new Func<int, int, IEnumerable<Tuple<Item, object>>>(adapter.EnumerateItems);
Action<int, int, object, int> takeMethod = new Action<int, int, object, int>(adapter.TakeItem);
mechTansfer.Call("RegisterAdapter", injectMethod, enumerateMethod, takeMethod, new int[] { TileType<MyContainerTile>() });
}
}