<?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%3AModding_API</id>
	<title>UtilityConnect:Modding 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%3AModding_API"/>
	<link rel="alternate" type="text/html" href="https://wiki.mutigeraffe.com/index.php?title=UtilityConnect:Modding_API&amp;action=history"/>
	<updated>2026-10-19T20:19:29Z</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:Modding_API&amp;diff=506&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:Modding_API&amp;diff=506&amp;oldid=prev"/>
		<updated>2026-10-19T07:07:05Z</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;Utility Connect gives your mod a shared network graph. You register your network blocks, and the library connects them, splits and merges networks, saves them per chunk and rebuilds them after a restart. This page lists the public types. Worked examples are on [[UtilityConnect:Registering Nodes|Registering Nodes]].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Status&lt;br /&gt;
| The network side is complete. The transport types (&amp;lt;code&amp;gt;TransportProvider&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;TransferMode&amp;lt;/code&amp;gt;) are interfaces only: the library does not call them and moves nothing on its own. See [[UtilityConnect:Transport API|Transport API]].&lt;br /&gt;
|-&lt;br /&gt;
! Stability&lt;br /&gt;
| The library is pinned to exact versions. 0.1.0-Alpha to 0.2.0-Alpha broke the API (&amp;lt;code&amp;gt;registerKindResolver&amp;lt;/code&amp;gt; was added). 1.0.0 kept the API of 0.2.0-Alpha unchanged.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Setting up the dependency ==&lt;br /&gt;
Add Utility Connect as a &amp;#039;&amp;#039;&amp;#039;hard dependency&amp;#039;&amp;#039;&amp;#039; in your &amp;lt;code&amp;gt;manifest.json&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;Dependencies&amp;quot;: {&lt;br /&gt;
    &amp;quot;com.cyberpiratepenguin:utilityconnect&amp;quot;: &amp;quot;1.0.0&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With the hytale-tools Gradle plugin, the same line goes into &amp;lt;code&amp;gt;gradle.properties&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
manifest_dependencies = com.cyberpiratepenguin:utilityconnect=1.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Compile against the Utility Connect jar (Java 25), but do not ship it inside your own jar. Players install it as a separate mod. A bundled copy would never be started by the server, so its &amp;lt;code&amp;gt;networks()&amp;lt;/code&amp;gt; would always throw.&lt;br /&gt;
&lt;br /&gt;
The hard dependency makes the server load Utility Connect first. Its &amp;lt;code&amp;gt;setup()&amp;lt;/code&amp;gt; has finished before your plugin&amp;#039;s &amp;lt;code&amp;gt;setup()&amp;lt;/code&amp;gt; runs, so you can use the API from your own &amp;lt;code&amp;gt;setup()&amp;lt;/code&amp;gt; on.&lt;br /&gt;
&lt;br /&gt;
== Packages ==&lt;br /&gt;
Only use the &amp;lt;code&amp;gt;api&amp;lt;/code&amp;gt; packages. Everything under &amp;lt;code&amp;gt;com.cyberpiratepenguin.utilityconnect.internal&amp;lt;/code&amp;gt; is an implementation detail and may change at any time.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Package !! Contents&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;com.cyberpiratepenguin.utilityconnect.api&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;UtilityConnectAPI&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;com.cyberpiratepenguin.utilityconnect.api.network&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Networks&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NodeKind&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NodeKindResolver&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NodePos&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ChunkKey&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;com.cyberpiratepenguin.utilityconnect.api.transport&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;TransportProvider&amp;amp;lt;T&amp;amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;TransferMode&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== UtilityConnectAPI ==&lt;br /&gt;
Static entry point.&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;API_VERSION&amp;lt;/code&amp;gt; || Version string of the public API, currently &amp;lt;code&amp;gt;&amp;quot;1.0.0&amp;quot;&amp;lt;/code&amp;gt;. Compiled into your mod.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;isReady()&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; once the library&amp;#039;s &amp;lt;code&amp;gt;setup()&amp;lt;/code&amp;gt; has run, &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; before that and after shutdown.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;runtimeVersion()&amp;lt;/code&amp;gt; || Version of the installed library, or &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; while it is not running.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;networks()&amp;lt;/code&amp;gt; || The &amp;lt;code&amp;gt;Networks&amp;lt;/code&amp;gt; access. Throws &amp;lt;code&amp;gt;IllegalStateException&amp;lt;/code&amp;gt; when the library is not ready, usually because the manifest dependency is missing.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Networks ==&lt;br /&gt;
Access to the networks of all worlds. Every method takes the Hytale &amp;lt;code&amp;gt;World&amp;lt;/code&amp;gt;; networks never span worlds.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Returns !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;addNode(World, NodePos, NodeKind)&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || Registers a block as a node. It connects at once to all allowed neighbours, also across chunk borders. &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; if the position was new.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;removeNode(World, NodePos)&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || Removes a node. Networks split on their own. &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; if the position was known.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hasNode(World, NodePos)&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || Whether a loaded node exists at that position.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;networkAt(World, NodePos)&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Set&amp;amp;lt;NodePos&amp;amp;gt;&amp;lt;/code&amp;gt; || All nodes in the same network, including the position itself. Empty if there is no loaded node there. A node without connections returns a set with only itself.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sameNetwork(World, NodePos, NodePos)&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || Whether both positions are loaded and in the same network.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;networkCount(World)&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || Number of separate networks in that world (loaded chunks only).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;nodeCount(World)&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || Number of loaded nodes in that world.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;registerKindResolver(NodeKindResolver)&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || Registers a resolver that reads a block&amp;#039;s role on chunk load. Call once at startup.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Threading:&amp;#039;&amp;#039;&amp;#039; call every method on the &amp;#039;&amp;#039;&amp;#039;world thread&amp;#039;&amp;#039;&amp;#039; only, for example from block place and break event handlers. Never from an async command or your own thread. The world thread serialises all player actions, so no locking is needed.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Loaded chunks only:&amp;#039;&amp;#039;&amp;#039; nodes in unloaded chunks are not part of any network and do not show up in queries. They come back when the chunk loads.&lt;br /&gt;
&lt;br /&gt;
== NodeKind ==&lt;br /&gt;
Enum with the role of a node.&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;DEVICE&amp;lt;/code&amp;gt; || Storage, terminal, machine. Connects to connectors only, never directly to another device.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;CONNECTOR&amp;lt;/code&amp;gt; || Pipe, cable. Connects to every adjacent node in all six directions.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;code&amp;gt;isConnector()&amp;lt;/code&amp;gt; and the static &amp;lt;code&amp;gt;connects(a, b)&amp;lt;/code&amp;gt; (true if at least one side is a connector) express the rule in code.&lt;br /&gt;
&lt;br /&gt;
== NodeKindResolver ==&lt;br /&gt;
Functional interface &amp;lt;code&amp;gt;NodeKind resolve(World world, NodePos pos)&amp;lt;/code&amp;gt;. Utility Connect calls it on the world thread for every stored node once a chunk has loaded and its blocks can be read. Return the role of your block, or &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; if the position is not yours. The first registered resolver that returns a value wins, so another mod cannot reinterpret your blocks. Corrected roles are saved.&lt;br /&gt;
&lt;br /&gt;
== NodePos and ChunkKey ==&lt;br /&gt;
* &amp;lt;code&amp;gt;NodePos(int x, int y, int z)&amp;lt;/code&amp;gt;: immutable block position, the identity of a node. &amp;lt;code&amp;gt;of(x, y, z)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;from(BlockPosition)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;toBlockPosition()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;offset(dx, dy, dz)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;adjacent()&amp;lt;/code&amp;gt; (the six face neighbours), &amp;lt;code&amp;gt;isAdjacentTo(other)&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt; value must be inside the world height, because nodes are stored with chunk-relative packed positions.&lt;br /&gt;
* &amp;lt;code&amp;gt;ChunkKey(int x, int z)&amp;lt;/code&amp;gt;: a chunk column. &amp;lt;code&amp;gt;of(chunkX, chunkZ)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;containing(NodePos)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;contains(NodePos)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Transport ==&lt;br /&gt;
&amp;lt;code&amp;gt;TransportProvider&amp;amp;lt;T&amp;amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;TransferMode&amp;lt;/code&amp;gt; are described on [[UtilityConnect:Transport API|Transport API]].&lt;br /&gt;
&lt;br /&gt;
{{UtilityConnect Nav}}&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>
	</entry>
</feed>