<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.mutigeraffe.com/index.php?action=history&amp;feed=atom&amp;title=UtilityConnect%3ATransport_API</id>
	<title>UtilityConnect:Transport API - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.mutigeraffe.com/index.php?action=history&amp;feed=atom&amp;title=UtilityConnect%3ATransport_API"/>
	<link rel="alternate" type="text/html" href="https://wiki.mutigeraffe.com/index.php?title=UtilityConnect:Transport_API&amp;action=history"/>
	<updated>2026-10-20T09:03:24Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.11</generator>
	<entry>
		<id>https://wiki.mutigeraffe.com/index.php?title=UtilityConnect:Transport_API&amp;diff=510&amp;oldid=prev</id>
		<title>Maintenance script: UtilityConnect wiki</title>
		<link rel="alternate" type="text/html" href="https://wiki.mutigeraffe.com/index.php?title=UtilityConnect:Transport_API&amp;diff=510&amp;oldid=prev"/>
		<updated>2026-10-19T07:07:06Z</updated>

		<summary type="html">&lt;p&gt;UtilityConnect wiki&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;The package &amp;lt;code&amp;gt;com.cyberpiratepenguin.utilityconnect.api.transport&amp;lt;/code&amp;gt; describes a common contract for blocks that take in or give out a resource: a chest, a tank or a battery.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Important&lt;br /&gt;
| Utility Connect does &amp;#039;&amp;#039;&amp;#039;not&amp;#039;&amp;#039;&amp;#039; use these types itself. It moves no items, fluids or energy, and it does not look up a &amp;lt;code&amp;gt;TransportProvider&amp;lt;/code&amp;gt; for a node. If your mod wants to move resources through a network, it does that on its own, for example by walking the nodes from &amp;lt;code&amp;gt;networkAt&amp;lt;/code&amp;gt;. The interfaces give mods a shared vocabulary for that.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== TransportProvider&amp;amp;lt;T&amp;amp;gt; ==&lt;br /&gt;
Generic over the resource type &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; (for example an item key), so the same contract can be used for items, fluids and energy.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Member !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;long insert(T resource, long amount, TransferMode mode)&amp;lt;/code&amp;gt; || Tries to take in &amp;lt;code&amp;gt;amount&amp;lt;/code&amp;gt; units. Returns how much was actually accepted, between 0 and &amp;lt;code&amp;gt;amount&amp;lt;/code&amp;gt;. Throws &amp;lt;code&amp;gt;IllegalArgumentException&amp;lt;/code&amp;gt; for a negative amount.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;long extract(T resource, long amount, TransferMode mode)&amp;lt;/code&amp;gt; || Tries to give out &amp;lt;code&amp;gt;amount&amp;lt;/code&amp;gt; units. Returns how much was actually removed, between 0 and &amp;lt;code&amp;gt;amount&amp;lt;/code&amp;gt;. Throws &amp;lt;code&amp;gt;IllegalArgumentException&amp;lt;/code&amp;gt; for a negative amount.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;long capacity()&amp;lt;/code&amp;gt; || Total capacity, or &amp;lt;code&amp;gt;UNLIMITED&amp;lt;/code&amp;gt;. Not the free space: ask &amp;lt;code&amp;gt;insert&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;SIMULATE&amp;lt;/code&amp;gt; for that.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;int tier()&amp;lt;/code&amp;gt; || Upgrade tier, 0-based, higher is better. Default &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UNLIMITED&amp;lt;/code&amp;gt; || Constant &amp;lt;code&amp;gt;Long.MAX_VALUE&amp;lt;/code&amp;gt; for &amp;quot;practically unlimited&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Contract for implementations:&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Partial transfers are normal.&amp;#039;&amp;#039;&amp;#039; Return the amount actually moved. Do not throw because less fits than requested.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Simulation must be exact.&amp;#039;&amp;#039;&amp;#039; A call with &amp;lt;code&amp;gt;SIMULATE&amp;lt;/code&amp;gt; changes nothing and returns the same value as an &amp;lt;code&amp;gt;EXECUTE&amp;lt;/code&amp;gt; call made right after it. Callers plan transfers based on this, and breaking it makes resources disappear.&lt;br /&gt;
&lt;br /&gt;
== TransferMode ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Value !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SIMULATE&amp;lt;/code&amp;gt; || Only calculate, change nothing. For questions like &amp;quot;does this fit?&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;EXECUTE&amp;lt;/code&amp;gt; || Actually perform the transfer.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;code&amp;gt;isSimulation()&amp;lt;/code&amp;gt; returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;SIMULATE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
A simple item buffer that implements the contract:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import com.cyberpiratepenguin.utilityconnect.api.transport.TransferMode;&lt;br /&gt;
import com.cyberpiratepenguin.utilityconnect.api.transport.TransportProvider;&lt;br /&gt;
&lt;br /&gt;
public final class ItemBuffer implements TransportProvider&amp;amp;lt;String&amp;amp;gt; {&lt;br /&gt;
    private final long capacity = 1000;&lt;br /&gt;
    private final Map&amp;amp;lt;String, Long&amp;amp;gt; stored = new HashMap&amp;amp;lt;&amp;amp;gt;();&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public long insert(String itemId, long amount, TransferMode mode) {&lt;br /&gt;
        if (amount &amp;amp;lt; 0) throw new IllegalArgumentException(&amp;quot;amount&amp;quot;);&lt;br /&gt;
        long used = stored.values().stream().mapToLong(Long::longValue).sum();&lt;br /&gt;
        long accepted = Math.min(amount, capacity - used);&lt;br /&gt;
        if (!mode.isSimulation() &amp;amp;amp;&amp;amp;amp; accepted &amp;amp;gt; 0) {&lt;br /&gt;
            stored.merge(itemId, accepted, Long::sum);&lt;br /&gt;
        }&lt;br /&gt;
        return accepted;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public long extract(String itemId, long amount, TransferMode mode) {&lt;br /&gt;
        if (amount &amp;amp;lt; 0) throw new IllegalArgumentException(&amp;quot;amount&amp;quot;);&lt;br /&gt;
        long removed = Math.min(amount, stored.getOrDefault(itemId, 0L));&lt;br /&gt;
        if (!mode.isSimulation() &amp;amp;amp;&amp;amp;amp; removed &amp;amp;gt; 0) {&lt;br /&gt;
            stored.merge(itemId, -removed, Long::sum);&lt;br /&gt;
        }&lt;br /&gt;
        return removed;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public long capacity() {&lt;br /&gt;
        return capacity;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Moving 64 units from &amp;lt;code&amp;gt;source&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;target&amp;lt;/code&amp;gt; without losing anything:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
long possible = source.extract(item, 64, TransferMode.SIMULATE);&lt;br /&gt;
long fits = target.insert(item, possible, TransferMode.SIMULATE);&lt;br /&gt;
long moved = source.extract(item, fits, TransferMode.EXECUTE);&lt;br /&gt;
target.insert(item, moved, TransferMode.EXECUTE);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{UtilityConnect Nav}}&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
</feed>