diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 93138ad..d8ecf0c 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -88,7 +88,7 @@ Documentation must be kept up to date when adding or changing functionality.
 
 ### Javadoc
 
-Javadoc is available after every release on https://refinedmods.com/rangedpumps/.
+Javadoc is available after every release on https://refinedmods.com/javadoc/rangedpumps/.
 
 ### API annotations
 
@@ -196,7 +196,7 @@ The workflow takes care of the following:
 - Running a build.
 - Publishing on [GitHub packages](https://github.com/refinedmods/rangedpumps/packages) and
   CreeperHost Maven.
-- Publishing Javadoc on [GitHub pages](https://github.com/refinedmods/rangedpumps/tree/gh-pages).
+- Publishing Javadoc on [GitHub pages](https://github.com/refinedmods/javadoc).
 - Deploying on [GitHub releases](https://github.com/refinedmods/rangedpumps/releases).
 - Announcing the release on Discord and Twitter.
 - Creating a PR that merges `main` back into `develop` to get the changes to `CHANGELOG.md` and `build.gradle`
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 5813d99..8ac7ae7 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -8,7 +8,7 @@ on:
     types: [ opened, synchronize, reopened ]
 jobs:
   build:
-    uses: refinedmods/refinedarchitect/.github/workflows/build.yml@v0.6.0
+    uses: refinedmods/refinedarchitect/.github/workflows/build.yml@v0.11.3
     with:
       mutation-testing: false
       sonarqube: false
diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml
index fd2b11e..196cb28 100644
--- a/.github/workflows/draft-release.yml
+++ b/.github/workflows/draft-release.yml
@@ -17,7 +17,7 @@ on:
         type: string
 jobs:
   draft:
-    uses: refinedmods/refinedarchitect/.github/workflows/draft-release.yml@v0.6.0
+    uses: refinedmods/refinedarchitect/.github/workflows/draft-release.yml@v0.11.3
     with:
       release-type: ${{ inputs.release-type }}
       version-number-override: ${{ inputs.version-number-override }}
diff --git a/.github/workflows/issue-for-unsupported-version.yml b/.github/workflows/issue-for-unsupported-version.yml
index b80bdc2..1fc7129 100644
--- a/.github/workflows/issue-for-unsupported-version.yml
+++ b/.github/workflows/issue-for-unsupported-version.yml
@@ -4,4 +4,4 @@ on:
     types: [ labeled, unlabeled, reopened ]
 jobs:
   unsupported-labeler:
-    uses: refinedmods/refinedarchitect/.github/workflows/issue-for-unsupported-version.yml@v0.6.0
\ No newline at end of file
+    uses: refinedmods/refinedarchitect/.github/workflows/issue-for-unsupported-version.yml@v0.11.3
\ No newline at end of file
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
index 399fba6..a9de795 100644
--- a/.github/workflows/publish-release.yml
+++ b/.github/workflows/publish-release.yml
@@ -7,7 +7,7 @@ on:
       - closed
 jobs:
   publish-release:
-    uses: refinedmods/refinedarchitect/.github/workflows/publish-release.yml@v0.6.0
+    uses: refinedmods/refinedarchitect/.github/workflows/publish-release.yml@v0.11.3
     secrets: inherit
     with:
       project-name: 'Ranged Pumps'
diff --git a/.github/workflows/resolved-issue-locking.yml b/.github/workflows/resolved-issue-locking.yml
index 73023ae..8d3457d 100644
--- a/.github/workflows/resolved-issue-locking.yml
+++ b/.github/workflows/resolved-issue-locking.yml
@@ -4,4 +4,4 @@ on:
     - cron: '0 0 * * *'
 jobs:
   lock:
-    uses: refinedmods/refinedarchitect/.github/workflows/resolved-issue-locking.yml@v0.6.0
\ No newline at end of file
+    uses: refinedmods/refinedarchitect/.github/workflows/resolved-issue-locking.yml@v0.11.3
\ No newline at end of file
diff --git a/.github/workflows/validate-branch-name.yml b/.github/workflows/validate-branch-name.yml
index 5db6ae8..b3852e5 100644
--- a/.github/workflows/validate-branch-name.yml
+++ b/.github/workflows/validate-branch-name.yml
@@ -2,4 +2,4 @@ name: Validate branch name
 on: [ pull_request ]
 jobs:
   validate-branch-name:
-    uses: refinedmods/refinedarchitect/.github/workflows/validate-branch-name.yml@v0.6.0
\ No newline at end of file
+    uses: refinedmods/refinedarchitect/.github/workflows/validate-branch-name.yml@v0.11.3
\ No newline at end of file
diff --git a/.github/workflows/validate-changelog.yml b/.github/workflows/validate-changelog.yml
index 8f3f0d0..58cbc6a 100644
--- a/.github/workflows/validate-changelog.yml
+++ b/.github/workflows/validate-changelog.yml
@@ -4,4 +4,6 @@ on:
     types: [ opened, synchronize, reopened, ready_for_review, labeled, unlabeled ]
 jobs:
   validate-changelog:
-    uses: refinedmods/refinedarchitect/.github/workflows/validate-changelog.yml@v0.6.0
\ No newline at end of file
+    uses: refinedmods/refinedarchitect/.github/workflows/validate-changelog.yml@v0.11.3
+    with:
+      validation-level: 'warn'
\ No newline at end of file
diff --git a/.github/workflows/validate-commit-messages.yml b/.github/workflows/validate-commit-messages.yml
index 4decd4a..f08e600 100644
--- a/.github/workflows/validate-commit-messages.yml
+++ b/.github/workflows/validate-commit-messages.yml
@@ -2,4 +2,4 @@ name: Validate commit messages
 on: [ pull_request ]
 jobs:
   validate-commit-messages:
-    uses: refinedmods/refinedarchitect/.github/workflows/validate-commit-messages.yml@v0.6.0
\ No newline at end of file
+    uses: refinedmods/refinedarchitect/.github/workflows/validate-commit-messages.yml@v0.11.3
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 32c9771..1353ebd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,7 @@ eclipse/
 .nb-gradle-properties
 .project
 *.launch
-run/
+runs/
 *.iml
 *.ipr
 *.iws
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 802040a..25d0a00 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,12 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 ## [Unreleased]
 
+## [1.2.0] - 2024-01-29
+
+### Changed
+
+-   Ported to Minecraft 1.20.4.
+
 ## [1.1.0] - 2023-07-07
 
 ### Changed
@@ -65,7 +71,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 -   Port to Minecraft 1.16.
 
-## [0.7.1] - 2020-01-30
+## [0.11.3] - 2020-01-30
 
 ### Added
 
@@ -140,7 +146,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 -   Initial release for Minecraft 1.10.2.
 
-[Unreleased]: https://github.com/refinedmods/rangedpumps/compare/v1.1.0...HEAD
+[Unreleased]: https://github.com/refinedmods/rangedpumps/compare/v1.2.0...HEAD
+
+[1.2.0]: https://github.com/refinedmods/rangedpumps/compare/v1.1.0...v1.2.0
 
 [1.1.0]: https://github.com/refinedmods/rangedpumps/compare/v1.0.0...v1.1.0
 
@@ -156,9 +164,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 [0.8.1]: https://github.com/refinedmods/rangedpumps/compare/v0.8.0...v0.8.1
 
-[0.8.0]: https://github.com/refinedmods/rangedpumps/compare/v0.7.1...v0.8.0
+[0.8.0]: https://github.com/refinedmods/rangedpumps/compare/v0.11.3...v0.8.0
 
-[0.7.1]: https://github.com/refinedmods/rangedpumps/compare/v0.7.0...v0.7.1
+[0.11.3]: https://github.com/refinedmods/rangedpumps/compare/v0.7.0...v0.11.3
 
 [0.7.0]: https://github.com/refinedmods/rangedpumps/compare/v0.6.1...v0.7.0
 
diff --git a/LICENSE.md b/LICENSE.md
index 655dc3a..4e49080 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,6 @@
 # The MIT License (MIT)
 
-Copyright © 2016 - 2023 Refined Mods
+Copyright © 2016 - 2024 Refined Mods
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
diff --git a/README.md b/README.md
index cbc6fad..c2a1e47 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Ranged Pumps [![Build Status](https://github.com/refinedmods/rangedpumps/actions/workflows/build.yml/badge.svg?branch=develop)](https://github.com/refinedmods/rangedpumps/actions/workflows/build.yml) [![Downloads on CurseForge](http://cf.way2muchnoise.eu/full_247496_downloads.svg)](http://minecraft.curseforge.com/projects/ranged-pumps) [![Discord](https://img.shields.io/discord/342942776494653441)](https://discordapp.com/invite/VYzsydb) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE.md)
+# Ranged Pumps [![Build Status](https://github.com/refinedmods/rangedpumps/actions/workflows/build.yml/badge.svg?branch=develop)](https://github.com/refinedmods/rangedpumps/actions/workflows/build.yml) [![Downloads on CurseForge](http://cf.way2muchnoise.eu/full_247496_downloads.svg)](http://minecraft.curseforge.com/projects/ranged-pumps) [![Downloads on Modrinth](https://img.shields.io/modrinth/dt/ranged-pumps?logo=modrinth)](https://modrinth.com/mod/ranged-pumps) [![Discord](https://img.shields.io/discord/342942776494653441)](https://discordapp.com/invite/VYzsydb) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE.md)
 
 ## About
 
@@ -14,6 +14,7 @@ Ranged Pumps is a simple mod that adds a pump that pumps liquids in a range.
 - [CurseForge](https://curseforge.com/minecraft/mc-mods/ranged-pumps)
 - [Modrinth](https://modrinth.com/mod/ranged-pumps)
 - [Wiki](https://refinedmods.com/ranged-pumps/)
+- [Javadoc](https://refinedmods.com/javadoc/rangedpumps)
 - [Discord](https://discordapp.com/invite/VYzsydb)
 - [Twitter](https://twitter.com/refinedmods)
 - [Mastodon](https://anvil.social/@refinedmods)
diff --git a/build.gradle b/build.gradle
index 46acff9..1ba732c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,4 +1,4 @@
-apply from: "https://raw.githubusercontent.com/refinedmods/refinedarchitect/v0.6.0/helper.gradle"
+apply from: "https://raw.githubusercontent.com/refinedmods/refinedarchitect/v0.11.3/helper.gradle"
 
 group = 'com.refinedmods'
 
diff --git a/docs/assets/pump.png b/docs/assets/pump.png
new file mode 100644
index 0000000..85aec35
Binary files /dev/null and b/docs/assets/pump.png differ
diff --git a/docs/assets/recipe.png b/docs/assets/recipe.png
new file mode 100644
index 0000000..e732d75
Binary files /dev/null and b/docs/assets/recipe.png differ
diff --git a/docs/assets/scanning-mc110-1.png b/docs/assets/scanning-mc110-1.png
new file mode 100644
index 0000000..1909ff1
Binary files /dev/null and b/docs/assets/scanning-mc110-1.png differ
diff --git a/docs/assets/scanning-mc110-2.png b/docs/assets/scanning-mc110-2.png
new file mode 100644
index 0000000..e91f8c4
Binary files /dev/null and b/docs/assets/scanning-mc110-2.png differ
diff --git a/docs/assets/scanning.png b/docs/assets/scanning.png
new file mode 100644
index 0000000..941b331
Binary files /dev/null and b/docs/assets/scanning.png differ
diff --git a/docs/nav.json b/docs/nav.json
new file mode 100644
index 0000000..999afc2
--- /dev/null
+++ b/docs/nav.json
@@ -0,0 +1,14 @@
+[
+  {
+    "ref": "index.adoc"
+  },
+  {
+    "ref": "pump-in-minecraft-1.10.2.adoc",
+    "title": "Pump (Minecraft 1.10.2)"
+  },
+  {
+    "title": "What's new",
+    "ref": "whats-new.adoc",
+    "icon": "bi-lightbulb-fill"
+  }
+]
\ No newline at end of file
diff --git a/docs/pages/index.adoc b/docs/pages/index.adoc
new file mode 100644
index 0000000..a2e79fb
--- /dev/null
+++ b/docs/pages/index.adoc
@@ -0,0 +1,58 @@
+= Pump
+:icon: pump.png
+
+Ranged Pumps is a simple mod that adds a pump that pumps liquids in a range.
+
+The {doctitle} is the only block that is added by Ranged Pumps.
+It pumps liquids in a range.
+
+image::../assets/recipe.png[The crafting recipe of the pump]
+
+== Placement
+
+Place the {doctitle} down, and it'll only work *without* a redstone signal.
+
+== Redstone signal
+
+If you give the {doctitle} a redstone signal, it will stop working until you disable the redstone signal.
+
+== Energy requirements
+
+By default, the {doctitle} requires Forge Energy, but can be configured to not use energy in the config.
+
+== Internal tank
+
+The size of the internal tank of the {doctitle} is 32 buckets (by default).
+You can increase or decrease this in the config.
+
+The {doctitle} will stop running if the internal tank is full.
+
+== Status updates
+
+Right-click on the {doctitle} to know what it is doing and to know if it is running.
+
+== Scanning and range
+
+image::../assets/scanning.png[Diagram describing the scanning direction and order]
+
+It'll start pumping liquids in rectangular spiral shape 1 block under the {doctitle.
+
+The default range is 64 blocks.
+That'll mean it scan 64 blocks in any direction, nearest-first.
+
+On a vertical (Y) level, it will scan liquids from the {doctitle} to bedrock.
+
+== Liquids to stone
+
+The {doctitle} will also replace any liquids to stone by default.
+This can be turned off in the config.
+
+== Auto-pushing liquids
+
+The {doctitle} will auto-push liquids to neighboring tanks.
+You can also get the liquids out with pipes.
+
+== Chunkloading
+
+The mod doesn't chunkload the {doctitle} automatically.
+You'll need another mod to get this behavior.
\ No newline at end of file
diff --git a/docs/pages/pump-in-minecraft-1.10.2.adoc b/docs/pages/pump-in-minecraft-1.10.2.adoc
new file mode 100644
index 0000000..5db4c1e
--- /dev/null
+++ b/docs/pages/pump-in-minecraft-1.10.2.adoc
@@ -0,0 +1,58 @@
+= Pump
+:icon: pump.png
+
+This documentation page refers to the **Minecraft 1.10.2** version of Ranged Pumps.
+Consult the xref:index.adoc[latest version of the documentation].
+
+The {doctitle} is the only block that is added by Ranged Pumps.
+It pumps liquids in a range.
+
+image::../assets/recipe.png[The crafting recipe of the pump]
+
+== Placement
+
+Place the {doctitle} down, apply a redstone signal, and it'll work.
+
+== Energy requirements
+
+By default, the {doctitle} requires no energy, but the {doctitle} can be configured to use RF energy in the config.
+
+== Internal tank
+
+The size of the internal tank of the {doctitle} is by default 32 buckets, you can increase or decrease this in the config.
+
+The {doctitle} will stop running if the internal tank is full.
+
+== Status updates
+
+Right-click on the {doctitle} to know what it is doing and if it is running.
+
+== Scanning and range
+
+It'll pump liquids in a rectangular area 1 block under the {doctitle}, the size of this rectangular area can be specified in the config.
+
+The default range specified in the config is 128 blocks.
+That means it will search 64 blocks in any direction of the {doctitle}.
+
+image::../assets/scanning-mc110-1.png[Diagram showing the scanning range of the pump]
+
+This is how it will scan for liquids (from the top left to the bottom right):
+
+image::../assets/scanning-mc110-2.png[Diagram showing the scanning order of the pump]
+
+== Liquids to stone
+
+The {doctitle} will also replace any liquids to stone by default.
+This can be turned off in the config.
+
+== Auto-pushing liquids
+
+The {doctitle} doesn't auto-push liquids.
+You have to suck them out manually with an external mod that can do that, for example pipes.
+
+Make sure you're not disabling the pipe with the redstone signal that you're providing to the pump!
+
+== Chunkloading
+
+The mod doesn't chunkload the {doctitle} automatically.
+You'll need another mod to get this behavior.
\ No newline at end of file
diff --git a/docs/pages/whats-new.adoc b/docs/pages/whats-new.adoc
new file mode 100644
index 0000000..578a8f9
--- /dev/null
+++ b/docs/pages/whats-new.adoc
@@ -0,0 +1 @@
+= What's new
\ No newline at end of file
diff --git a/docs/pages/whats-new.html b/docs/pages/whats-new.html
new file mode 100644
index 0000000..a52b2eb
--- /dev/null
+++ b/docs/pages/whats-new.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<html layout:decorate="~{layout.html}">
+<head>
+    <title th:utext="${title}"></title>
+</head>
+<body>
+<div layout:fragment="content">
+    <div th:if="${currentRelease != null}" class="card">
+        <div class="card-body">
+            <h2 class="card-title">
+                In version <span th:text="${currentRelease.release.getName()}" th:remove="tag"></span>
+
+                <span class="badge bg-primary" th:if="${currentRelease.release.type.name() == 'BETA'}">Beta</span>
+                <span class="badge bg-warning text-dark"
+                      th:if="${currentRelease.release.type.name() == 'ALPHA'}">Alpha</span>
+            </h2>
+
+            <div class="text-muted d-flex gap-3 mb-2">
+                <span>
+                    <i class="bi bi-calendar"></i>
+                    <span
+                            th:text="${#dates.format(currentRelease.release.createdAt, 'yyyy-MM-dd')}"
+                            th:remove="tag"></span>
+                </span>
+                <span>
+                    <i class="bi bi-download"></i>
+                    <span th:remove="tag"
+                          th:text="${currentRelease.release.stats.totalDownloads}"></span>
+                </span>
+            </div>
+
+            <div th:utext="${currentRelease.changelogHtml}"></div>
+
+            <div class="d-flex flex-wrap gap-1">
+                <a th:href="${currentRelease.curseforgeUrl}" th:if="${currentRelease.curseforgeUrl != null}"
+                   class="btn btn-primary">
+                    <svg class="distribution-platform-logo" xmlns="http://www.w3.org/2000/svg"
+                         viewBox="-2017 853 43 23">
+                        <path d="M-2005.7,853l0.7,3c-3.5,0-12,0-12,0s0.2,0.9,0.3,1c0.3,0.5,0.6,1.1,1,1.5c1.9,2.2,5.2,3.1,7.9,3.6 c1.9,0.4,3.8,0.5,5.7,0.6l2.2,5.9h1.2l0.7,1.9h-1l-1.7,5.5h16.7l-1.7-5.5h-1l0.7-1.9h1.2c0,0,1-6.1,4.1-8.9c3-2.8,6.7-3.2,6.7-3.2 V853H-2005.7z M-1988.9,868.1c-0.8,0.5-1.7,0.5-2.3,0.9c-0.4,0.2-0.6,0.8-0.6,0.8c-0.4-0.9-0.9-1.2-1.5-1.4 c-0.6-0.2-1.7-0.1-3.2-1.4c-1-0.9-1.1-2.1-1-2.7v-0.1c0-0.1,0-0.1,0-0.2s0-0.2,0.1-0.3l0,0l0,0c0.2-0.6,0.7-1.2,1.7-1.6 c0,0-0.7,1,0,2c0.4,0.6,1.2,0.9,1.9,0.5c0.3-0.2,0.5-0.6,0.6-0.9c0.2-0.7,0.2-1.4-0.4-1.9c-0.9-0.8-1.1-1.9-0.5-2.6 c0,0,0.2,0.9,1.1,0.8c0.6,0,0.6-0.2,0.4-0.4c-0.1-0.3-1.4-2.2,0.5-3.6c0,0,1.2-0.8,2.6-0.7c-0.8,0.1-1.7,0.6-2,1.4c0,0,0,0,0,0.1 c-0.3,0.8-0.1,1.7,0.5,2.5c0.4,0.6,0.9,1.1,1.1,1.9c-0.3-0.1-0.5,0-0.7,0.2c-0.2,0.2-0.3,0.6-0.2,0.9c0.1,0.2,0.3,0.4,0.5,0.4 c0.1,0,0.1,0,0.2,0h0.1c0.3-0.1,0.5-0.5,0.4-0.8c0.2,0.2,0.3,0.7,0.2,1c0,0.3-0.2,0.6-0.3,0.8c-0.1,0.2-0.3,0.4-0.4,0.6 s-0.2,0.4-0.2,0.6c0,0.2,0,0.5,0.1,0.7c0.4,0.6,1.2,0,1.4-0.5c0.3-0.6,0.2-1.3-0.2-1.9c0,0,0.7,0.4,1.2,1.8 C-1987.4,866.2-1988.1,867.6-1988.9,868.1z"></path>
+                    </svg>
+                    Download on CurseForge
+                </a>
+                <a th:href="${currentRelease.modrinthUrl}" th:if="${currentRelease.modrinthUrl != null}"
+                   class="btn btn-primary">
+                    <svg class="distribution-platform-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 514">
+                        <path fill-rule="evenodd" clip-rule="evenodd"
+                              d="M503.16 323.56C514.55 281.47 515.32 235.91 503.2 190.76C466.57 54.2299 326.04 -26.8001 189.33 9.77991C83.8101 38.0199 11.3899 128.07 0.689941 230.47H43.99C54.29 147.33 113.74 74.7298 199.75 51.7098C306.05 23.2598 415.13 80.6699 453.17 181.38L411.03 192.65C391.64 145.8 352.57 111.45 306.3 96.8198L298.56 140.66C335.09 154.13 364.72 184.5 375.56 224.91C391.36 283.8 361.94 344.14 308.56 369.17L320.09 412.16C390.25 383.21 432.4 310.3 422.43 235.14L464.41 223.91C468.91 252.62 467.35 281.16 460.55 308.07L503.16 323.56Z"/>
+                        <path d="M321.99 504.22C185.27 540.8 44.7501 459.77 8.11011 323.24C3.84011 307.31 1.17 291.33 0 275.46H43.27C44.36 287.37 46.4699 299.35 49.6799 311.29C53.0399 323.8 57.45 335.75 62.79 347.07L101.38 323.92C98.1299 316.42 95.39 308.6 93.21 300.47C69.17 210.87 122.41 118.77 212.13 94.7601C229.13 90.2101 246.23 88.4401 262.93 89.1501L255.19 133C244.73 133.05 234.11 134.42 223.53 137.25C157.31 154.98 118.01 222.95 135.75 289.09C136.85 293.16 138.13 297.13 139.59 300.99L188.94 271.38L174.07 231.95L220.67 184.08L279.57 171.39L296.62 192.38L269.47 219.88L245.79 227.33L228.87 244.72L237.16 267.79C237.16 267.79 253.95 285.63 253.98 285.64L277.7 279.33L294.58 260.79L331.44 249.12L342.42 273.82L304.39 320.45L240.66 340.63L212.08 308.81L162.26 338.7C187.8 367.78 226.2 383.93 266.01 380.56L277.54 423.55C218.13 431.41 160.1 406.82 124.05 361.64L85.6399 384.68C136.25 451.17 223.84 484.11 309.61 461.16C371.35 444.64 419.4 402.56 445.42 349.38L488.06 364.88C457.17 431.16 398.22 483.82 321.99 504.22Z"/>
+                    </svg>
+                    Download on Modrinth
+                </a>
+                <a th:href="${currentRelease.githubUrl}" th:if="${currentRelease.githubUrl != null}"
+                   class="btn btn-primary">
+                    <i class="bi bi-github"></i>
+                    Download on GitHub
+                </a>
+            </div>
+        </div>
+    </div>
+
+    <h3 class="mt-2 mb-2">Other releases</h3>
+
+    <div class="accordion" id="other-releases">
+        <div class="accordion-item" th:each="otherRelease : ${otherReleases}">
+            <h2 class="accordion-header">
+                <button class="accordion-button d-flex gap-2 collapsed"
+                        type="button"
+                        data-bs-toggle="collapse"
+                        th:attr="data-bs-target='#collapse-' + ${otherRelease.slug}, aria-controls='collapse-' + ${otherRelease.slug}">
+                    <span th:text="${otherRelease.release.name}"></span>
+                    <span class="badge bg-primary" th:if="${otherRelease.release.type.name() == 'BETA'}">Beta</span>
+                    <span class="badge bg-warning text-dark"
+                          th:if="${otherRelease.release.type.name() == 'ALPHA'}">Alpha</span>
+                </button>
+            </h2>
+            <div th:id="'collapse-' + ${otherRelease.slug}"
+                 class="accordion-collapse collapse"
+                 data-bs-parent="#other-releases">
+                <div class="accordion-body">
+                    <h2 class="card-title">
+                        In version <span th:text="${otherRelease.release.getName()}" th:remove="tag"></span>
+                    </h2>
+
+                    <div class="text-muted d-flex gap-3 mb-2">
+                        <span>
+                            <i class="bi bi-calendar"></i>
+                            <span
+                                    th:text="${#dates.format(otherRelease.release.createdAt, 'yyyy-MM-dd')}"
+                                    th:remove="tag"></span>
+                        </span>
+                        <span>
+                            <i class="bi bi-download"></i>
+                            <span th:remove="tag"
+                                  th:text="${otherRelease.release.stats.totalDownloads}"></span>
+                        </span>
+                    </div>
+
+                    <div th:utext="${otherRelease.changelogHtml}"></div>
+
+                    <div class="d-flex flex-wrap gap-1">
+                        <a th:href="${otherRelease.curseforgeUrl}" th:if="${otherRelease.curseforgeUrl != null}"
+                           class="btn btn-primary">
+                            <svg class="distribution-platform-logo" xmlns="http://www.w3.org/2000/svg"
+                                 viewBox="-2017 853 43 23">
+                                <path d="M-2005.7,853l0.7,3c-3.5,0-12,0-12,0s0.2,0.9,0.3,1c0.3,0.5,0.6,1.1,1,1.5c1.9,2.2,5.2,3.1,7.9,3.6 c1.9,0.4,3.8,0.5,5.7,0.6l2.2,5.9h1.2l0.7,1.9h-1l-1.7,5.5h16.7l-1.7-5.5h-1l0.7-1.9h1.2c0,0,1-6.1,4.1-8.9c3-2.8,6.7-3.2,6.7-3.2 V853H-2005.7z M-1988.9,868.1c-0.8,0.5-1.7,0.5-2.3,0.9c-0.4,0.2-0.6,0.8-0.6,0.8c-0.4-0.9-0.9-1.2-1.5-1.4 c-0.6-0.2-1.7-0.1-3.2-1.4c-1-0.9-1.1-2.1-1-2.7v-0.1c0-0.1,0-0.1,0-0.2s0-0.2,0.1-0.3l0,0l0,0c0.2-0.6,0.7-1.2,1.7-1.6 c0,0-0.7,1,0,2c0.4,0.6,1.2,0.9,1.9,0.5c0.3-0.2,0.5-0.6,0.6-0.9c0.2-0.7,0.2-1.4-0.4-1.9c-0.9-0.8-1.1-1.9-0.5-2.6 c0,0,0.2,0.9,1.1,0.8c0.6,0,0.6-0.2,0.4-0.4c-0.1-0.3-1.4-2.2,0.5-3.6c0,0,1.2-0.8,2.6-0.7c-0.8,0.1-1.7,0.6-2,1.4c0,0,0,0,0,0.1 c-0.3,0.8-0.1,1.7,0.5,2.5c0.4,0.6,0.9,1.1,1.1,1.9c-0.3-0.1-0.5,0-0.7,0.2c-0.2,0.2-0.3,0.6-0.2,0.9c0.1,0.2,0.3,0.4,0.5,0.4 c0.1,0,0.1,0,0.2,0h0.1c0.3-0.1,0.5-0.5,0.4-0.8c0.2,0.2,0.3,0.7,0.2,1c0,0.3-0.2,0.6-0.3,0.8c-0.1,0.2-0.3,0.4-0.4,0.6 s-0.2,0.4-0.2,0.6c0,0.2,0,0.5,0.1,0.7c0.4,0.6,1.2,0,1.4-0.5c0.3-0.6,0.2-1.3-0.2-1.9c0,0,0.7,0.4,1.2,1.8 C-1987.4,866.2-1988.1,867.6-1988.9,868.1z"></path>
+                            </svg>
+                            Download on CurseForge
+                        </a>
+                        <a th:href="${otherRelease.modrinthUrl}" th:if="${otherRelease.modrinthUrl != null}"
+                           class="btn btn-primary">
+                            <svg class="distribution-platform-logo" xmlns="http://www.w3.org/2000/svg"
+                                 viewBox="0 0 512 514">
+                                <path fill-rule="evenodd" clip-rule="evenodd"
+                                      d="M503.16 323.56C514.55 281.47 515.32 235.91 503.2 190.76C466.57 54.2299 326.04 -26.8001 189.33 9.77991C83.8101 38.0199 11.3899 128.07 0.689941 230.47H43.99C54.29 147.33 113.74 74.7298 199.75 51.7098C306.05 23.2598 415.13 80.6699 453.17 181.38L411.03 192.65C391.64 145.8 352.57 111.45 306.3 96.8198L298.56 140.66C335.09 154.13 364.72 184.5 375.56 224.91C391.36 283.8 361.94 344.14 308.56 369.17L320.09 412.16C390.25 383.21 432.4 310.3 422.43 235.14L464.41 223.91C468.91 252.62 467.35 281.16 460.55 308.07L503.16 323.56Z"/>
+                                <path d="M321.99 504.22C185.27 540.8 44.7501 459.77 8.11011 323.24C3.84011 307.31 1.17 291.33 0 275.46H43.27C44.36 287.37 46.4699 299.35 49.6799 311.29C53.0399 323.8 57.45 335.75 62.79 347.07L101.38 323.92C98.1299 316.42 95.39 308.6 93.21 300.47C69.17 210.87 122.41 118.77 212.13 94.7601C229.13 90.2101 246.23 88.4401 262.93 89.1501L255.19 133C244.73 133.05 234.11 134.42 223.53 137.25C157.31 154.98 118.01 222.95 135.75 289.09C136.85 293.16 138.13 297.13 139.59 300.99L188.94 271.38L174.07 231.95L220.67 184.08L279.57 171.39L296.62 192.38L269.47 219.88L245.79 227.33L228.87 244.72L237.16 267.79C237.16 267.79 253.95 285.63 253.98 285.64L277.7 279.33L294.58 260.79L331.44 249.12L342.42 273.82L304.39 320.45L240.66 340.63L212.08 308.81L162.26 338.7C187.8 367.78 226.2 383.93 266.01 380.56L277.54 423.55C218.13 431.41 160.1 406.82 124.05 361.64L85.6399 384.68C136.25 451.17 223.84 484.11 309.61 461.16C371.35 444.64 419.4 402.56 445.42 349.38L488.06 364.88C457.17 431.16 398.22 483.82 321.99 504.22Z"/>
+                            </svg>
+                            Download on Modrinth
+                        </a>
+                        <a th:href="${otherRelease.githubUrl}" th:if="${otherRelease.githubUrl != null}"
+                           class="btn btn-primary">
+                            <i class="bi bi-github"></i>
+                            Download on GitHub
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index fae0804..1af9e09 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,7 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/images/description.md b/images/description.md
index ece54ac..83c03ef 100644
--- a/images/description.md
+++ b/images/description.md
@@ -28,7 +28,7 @@ Right click on the pump to know what it is doing and to know if it is running.
 
 ## Scanning and range
 
-![Scanning behavior of a ranged pump](/assets/ranged-pumps/scanning.png)
+![Scanning behavior of a ranged pump](scanning.png)
 
 It'll start pumping liquids in rectangular spiral shape 1 block under the pump.
 
diff --git a/src/main/java/com/refinedmods/rangedpumps/RangedPumps.java b/src/main/java/com/refinedmods/rangedpumps/RangedPumps.java
index 5fdfe3d..5b7037f 100644
--- a/src/main/java/com/refinedmods/rangedpumps/RangedPumps.java
+++ b/src/main/java/com/refinedmods/rangedpumps/RangedPumps.java
@@ -3,50 +3,69 @@
 import com.refinedmods.rangedpumps.block.PumpBlock;
 import com.refinedmods.rangedpumps.blockentity.PumpBlockEntity;
 import com.refinedmods.rangedpumps.config.ServerConfig;
+
+import net.minecraft.core.registries.BuiltInRegistries;
 import net.minecraft.core.registries.Registries;
 import net.minecraft.network.chat.Component;
+import net.minecraft.resources.ResourceLocation;
 import net.minecraft.world.item.BlockItem;
 import net.minecraft.world.item.CreativeModeTab;
 import net.minecraft.world.item.Item;
 import net.minecraft.world.item.ItemStack;
 import net.minecraft.world.level.block.Block;
 import net.minecraft.world.level.block.entity.BlockEntityType;
-import net.minecraftforge.fml.ModLoadingContext;
-import net.minecraftforge.fml.common.Mod;
-import net.minecraftforge.fml.config.ModConfig;
-import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
-import net.minecraftforge.registries.DeferredRegister;
-import net.minecraftforge.registries.ForgeRegistries;
-import net.minecraftforge.registries.RegisterEvent;
-import net.minecraftforge.registries.RegistryObject;
+import net.neoforged.bus.api.IEventBus;
+import net.neoforged.fml.ModLoadingContext;
+import net.neoforged.fml.common.Mod;
+import net.neoforged.fml.config.ModConfig;
+import net.neoforged.neoforge.capabilities.Capabilities;
+import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
+import net.neoforged.neoforge.registries.DeferredHolder;
+import net.neoforged.neoforge.registries.DeferredRegister;
+import net.neoforged.neoforge.registries.RegisterEvent;
 
 @Mod(RangedPumps.ID)
 public final class RangedPumps {
     public static final String ID = "rangedpumps";
 
-    private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, ID);
-    private static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, ID);
-    private static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITY_TYPES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, ID);
+    private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(BuiltInRegistries.ITEM, ID);
+    private static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(BuiltInRegistries.BLOCK, ID);
+    private static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITY_TYPES =
+        DeferredRegister.create(BuiltInRegistries.BLOCK_ENTITY_TYPE, ID);
 
-    public static RegistryObject<PumpBlock> PUMP_BLOCK;
-    public static RegistryObject<BlockEntityType<PumpBlockEntity>> PUMP_BLOCK_ENTITY_TYPE;
+    public static DeferredHolder<Block, PumpBlock> PUMP_BLOCK = BLOCKS.register("pump", PumpBlock::new);
+    public static DeferredHolder<BlockEntityType<?>, BlockEntityType<PumpBlockEntity>> PUMP_BLOCK_ENTITY_TYPE =
+        BLOCK_ENTITY_TYPES
+            .register("pump", () -> BlockEntityType.Builder.of(PumpBlockEntity::new, PUMP_BLOCK.get()).build(null));
 
     public static final ServerConfig SERVER_CONFIG = new ServerConfig();
 
-    public RangedPumps() {
-        PUMP_BLOCK = BLOCKS.register("pump", PumpBlock::new);
+    public RangedPumps(final IEventBus eventBus) {
         ITEMS.register("pump", () -> new BlockItem(PUMP_BLOCK.get(), new Item.Properties()));
-        PUMP_BLOCK_ENTITY_TYPE = BLOCK_ENTITY_TYPES.register("pump", () -> BlockEntityType.Builder.of(PumpBlockEntity::new, PUMP_BLOCK.get()).build(null));
         ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, SERVER_CONFIG.getSpec());
-        BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus());
-        ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus());
-        BLOCK_ENTITY_TYPES.register(FMLJavaModLoadingContext.get().getModEventBus());
-        FMLJavaModLoadingContext.get().getModEventBus().addListener(RangedPumps::onRegister);
+        BLOCKS.register(eventBus);
+        ITEMS.register(eventBus);
+        BLOCK_ENTITY_TYPES.register(eventBus);
+        eventBus.addListener(RangedPumps::onRegister);
+        eventBus.addListener(RangedPumps::onRegisterCapabilities);
+    }
+
+    public static void onRegisterCapabilities(RegisterCapabilitiesEvent e) {
+        e.registerBlockEntity(
+            Capabilities.EnergyStorage.BLOCK,
+            PUMP_BLOCK_ENTITY_TYPE.get(),
+            (be, ctx) -> be.getEnergy()
+        );
+        e.registerBlockEntity(
+            Capabilities.FluidHandler.BLOCK,
+            PUMP_BLOCK_ENTITY_TYPE.get(),
+            (be, ctx) -> be.getTank()
+        );
     }
 
     public static void onRegister(RegisterEvent e) {
         e.register(Registries.CREATIVE_MODE_TAB, helper -> {
-            helper.register("general", CreativeModeTab.builder()
+            helper.register(new ResourceLocation(RangedPumps.ID, "general"), CreativeModeTab.builder()
                 .title(Component.translatable("itemGroup.rangedpumps"))
                 .icon(() -> new ItemStack(RangedPumps.PUMP_BLOCK.get()))
                 .displayItems((params, output) -> {
diff --git a/src/main/java/com/refinedmods/rangedpumps/block/PumpBlock.java b/src/main/java/com/refinedmods/rangedpumps/block/PumpBlock.java
index 8a05573..568f0f3 100644
--- a/src/main/java/com/refinedmods/rangedpumps/block/PumpBlock.java
+++ b/src/main/java/com/refinedmods/rangedpumps/block/PumpBlock.java
@@ -3,7 +3,9 @@
 import com.refinedmods.rangedpumps.RangedPumps;
 import com.refinedmods.rangedpumps.blockentity.PumpBlockEntity;
 import com.refinedmods.rangedpumps.blockentity.PumpState;
+
 import net.minecraft.core.BlockPos;
+import net.minecraft.core.Direction;
 import net.minecraft.network.chat.Component;
 import net.minecraft.world.InteractionHand;
 import net.minecraft.world.InteractionResult;
@@ -17,8 +19,8 @@
 import net.minecraft.world.level.block.entity.BlockEntityType;
 import net.minecraft.world.level.block.state.BlockState;
 import net.minecraft.world.phys.BlockHitResult;
-import net.minecraftforge.common.capabilities.ForgeCapabilities;
-import net.minecraftforge.energy.IEnergyStorage;
+import net.neoforged.neoforge.capabilities.Capabilities;
+import net.neoforged.neoforge.energy.IEnergyStorage;
 
 public class PumpBlock extends Block implements EntityBlock {
     public PumpBlock() {
@@ -26,12 +28,17 @@ public PumpBlock() {
     }
 
     @SuppressWarnings("deprecation")
-    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
+    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand,
+                                 BlockHitResult hit) {
         if (!level.isClientSide) {
             BlockEntity blockEntity = level.getBlockEntity(pos);
 
             if (blockEntity instanceof PumpBlockEntity pump) {
-                IEnergyStorage energy = pump.getCapability(ForgeCapabilities.ENERGY).orElse(null);
+                IEnergyStorage energy = level.getCapability(
+                    Capabilities.EnergyStorage.BLOCK,
+                    pos,
+                    Direction.NORTH
+                );
                 if (energy == null) {
                     return InteractionResult.SUCCESS;
                 }
@@ -43,9 +50,12 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player
                 }
 
                 if (pump.getTank().getFluidAmount() == 0) {
-                    player.sendSystemMessage(Component.translatable("block." + RangedPumps.ID + ".pump.state_empty", energy.getEnergyStored(), energy.getMaxEnergyStored()));
+                    player.sendSystemMessage(Component.translatable("block." + RangedPumps.ID + ".pump.state_empty",
+                        energy.getEnergyStored(), energy.getMaxEnergyStored()));
                 } else {
-                    player.sendSystemMessage(Component.translatable("block." + RangedPumps.ID + ".pump.state", pump.getTank().getFluidAmount(), pump.getTank().getFluid().getDisplayName(), energy.getEnergyStored(), energy.getMaxEnergyStored()));
+                    player.sendSystemMessage(Component.translatable("block." + RangedPumps.ID + ".pump.state",
+                        pump.getTank().getFluidAmount(), pump.getTank().getFluid().getDisplayName(),
+                        energy.getEnergyStored(), energy.getMaxEnergyStored()));
                 }
             }
         }
@@ -59,7 +69,9 @@ public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
     }
 
     @Override
-    public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
-        return !level.isClientSide ? (levelTicker, pos, stateTicker, blockEntity) -> ((PumpBlockEntity) blockEntity).tick() : null;
+    public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state,
+                                                                  BlockEntityType<T> type) {
+        return !level.isClientSide ?
+            (levelTicker, pos, stateTicker, blockEntity) -> ((PumpBlockEntity) blockEntity).tick() : null;
     }
 }
diff --git a/src/main/java/com/refinedmods/rangedpumps/blockentity/PumpBlockEntity.java b/src/main/java/com/refinedmods/rangedpumps/blockentity/PumpBlockEntity.java
index 905f331..433bab4 100644
--- a/src/main/java/com/refinedmods/rangedpumps/blockentity/PumpBlockEntity.java
+++ b/src/main/java/com/refinedmods/rangedpumps/blockentity/PumpBlockEntity.java
@@ -1,8 +1,16 @@
 package com.refinedmods.rangedpumps.blockentity;
 
 import com.refinedmods.rangedpumps.RangedPumps;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import net.minecraft.core.BlockPos;
 import net.minecraft.core.Direction;
+import net.minecraft.core.registries.BuiltInRegistries;
 import net.minecraft.nbt.CompoundTag;
 import net.minecraft.nbt.ListTag;
 import net.minecraft.nbt.LongTag;
@@ -14,31 +22,19 @@
 import net.minecraft.world.level.block.entity.BlockEntity;
 import net.minecraft.world.level.block.state.BlockState;
 import net.minecraft.world.level.material.Fluid;
-import net.minecraftforge.common.capabilities.Capability;
-import net.minecraftforge.common.capabilities.ForgeCapabilities;
-import net.minecraftforge.common.util.LazyOptional;
-import net.minecraftforge.energy.EnergyStorage;
-import net.minecraftforge.energy.IEnergyStorage;
-import net.minecraftforge.fluids.FluidStack;
-import net.minecraftforge.fluids.FluidType;
-import net.minecraftforge.fluids.IFluidBlock;
-import net.minecraftforge.fluids.capability.IFluidHandler;
-import net.minecraftforge.fluids.capability.templates.FluidTank;
-import net.minecraftforge.registries.ForgeRegistries;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
+import net.neoforged.neoforge.capabilities.Capabilities;
+import net.neoforged.neoforge.energy.EnergyStorage;
+import net.neoforged.neoforge.energy.IEnergyStorage;
+import net.neoforged.neoforge.fluids.FluidStack;
+import net.neoforged.neoforge.fluids.FluidType;
+import net.neoforged.neoforge.fluids.IFluidBlock;
+import net.neoforged.neoforge.fluids.capability.IFluidHandler;
+import net.neoforged.neoforge.fluids.capability.templates.FluidTank;
 
 public class PumpBlockEntity extends BlockEntity {
     private PumpTank tank = new PumpTank();
     private IEnergyStorage energy = new EnergyStorage(RangedPumps.SERVER_CONFIG.getEnergyCapacity());
 
-    private final LazyOptional<IEnergyStorage> energyProxyCap = LazyOptional.of(() -> energy);
-    private final LazyOptional<IFluidHandler> fluidHandlerCap = LazyOptional.of(() -> tank);
-
     private int ticks;
 
     @Nullable
@@ -93,6 +89,10 @@ public void clearRemoved() {
     }
 
     public void tick() {
+        if (level == null) {
+            return;
+        }
+
         if (!RangedPumps.SERVER_CONFIG.getUseEnergy()) {
             energy.receiveEnergy(energy.getMaxEnergyStored(), false);
         }
@@ -102,14 +102,13 @@ public void tick() {
             List<IFluidHandler> fluidHandlers = new LinkedList<>();
 
             for (Direction facing : Direction.values()) {
-                BlockEntity blockEntity = level.getBlockEntity(worldPosition.relative(facing));
-
-                if (blockEntity != null) {
-                    IFluidHandler handler = blockEntity.getCapability(ForgeCapabilities.FLUID_HANDLER, facing.getOpposite()).orElse(null);
-
-                    if (handler != null) {
-                        fluidHandlers.add(handler);
-                    }
+                IFluidHandler handler = level.getCapability(
+                    Capabilities.FluidHandler.BLOCK,
+                    worldPosition.relative(facing),
+                    facing.getOpposite()
+                );
+                if (handler != null) {
+                    fluidHandlers.add(handler);
                 }
             }
 
@@ -120,12 +119,14 @@ public void tick() {
                     FluidStack toFill = tank.getFluid().copy();
                     toFill.setAmount(transfer);
 
-                    tank.drain(fluidHandler.fill(toFill, IFluidHandler.FluidAction.EXECUTE), IFluidHandler.FluidAction.EXECUTE);
+                    tank.drain(fluidHandler.fill(toFill, IFluidHandler.FluidAction.EXECUTE),
+                        IFluidHandler.FluidAction.EXECUTE);
                 }
             }
         }
 
-        if ((RangedPumps.SERVER_CONFIG.getSpeed() == 0 || (ticks % RangedPumps.SERVER_CONFIG.getSpeed() == 0)) && getState() == PumpState.WORKING) {
+        if ((RangedPumps.SERVER_CONFIG.getSpeed() == 0 || (ticks % RangedPumps.SERVER_CONFIG.getSpeed() == 0)) &&
+            getState() == PumpState.WORKING) {
             if (currentPos == null || currentPos.getY() == level.dimensionType().minY()) {
                 if (surfaces.isEmpty()) {
                     range++;
@@ -146,7 +147,8 @@ public void tick() {
 
             FluidStack drained = drainAt(currentPos, IFluidHandler.FluidAction.SIMULATE);
 
-            if (!drained.isEmpty() && tank.fillInternal(drained, IFluidHandler.FluidAction.SIMULATE) == drained.getAmount()) {
+            if (!drained.isEmpty() &&
+                tank.fillInternal(drained, IFluidHandler.FluidAction.SIMULATE) == drained.getAmount()) {
                 drained = drainAt(currentPos, IFluidHandler.FluidAction.EXECUTE);
 
                 if (!drained.isEmpty()) {
@@ -154,7 +156,9 @@ public void tick() {
 
                     if (RangedPumps.SERVER_CONFIG.getReplaceLiquidWithBlock()) {
                         if (blockToReplaceLiquidsWith == null) {
-                            blockToReplaceLiquidsWith = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(RangedPumps.SERVER_CONFIG.getBlockIdToReplaceLiquidsWith()));
+                            blockToReplaceLiquidsWith = BuiltInRegistries.BLOCK.get(
+                                new ResourceLocation(RangedPumps.SERVER_CONFIG.getBlockIdToReplaceLiquidsWith())
+                            );
                         }
 
                         if (blockToReplaceLiquidsWith != null) {
@@ -225,6 +229,10 @@ public FluidTank getTank() {
         return tank;
     }
 
+    public IEnergyStorage getEnergy() {
+        return energy;
+    }
+
     @Override
     public void saveAdditional(CompoundTag tag) {
         super.saveAdditional(tag);
@@ -273,20 +281,6 @@ public void load(CompoundTag tag) {
         tank.readFromNBT(tag);
     }
 
-    @Nonnull
-    @Override
-    public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction direction) {
-        if (cap == ForgeCapabilities.ENERGY) {
-            return energyProxyCap.cast();
-        }
-
-        if (cap == ForgeCapabilities.FLUID_HANDLER) {
-            return fluidHandlerCap.cast();
-        }
-
-        return super.getCapability(cap, direction);
-    }
-
     private static class PumpTank extends FluidTank {
         public PumpTank() {
             super(RangedPumps.SERVER_CONFIG.getTankCapacity());
diff --git a/src/main/java/com/refinedmods/rangedpumps/config/ServerConfig.java b/src/main/java/com/refinedmods/rangedpumps/config/ServerConfig.java
index b6a8f26..b816ebf 100644
--- a/src/main/java/com/refinedmods/rangedpumps/config/ServerConfig.java
+++ b/src/main/java/com/refinedmods/rangedpumps/config/ServerConfig.java
@@ -1,34 +1,43 @@
 package com.refinedmods.rangedpumps.config;
 
-import net.minecraftforge.common.ForgeConfigSpec;
-import net.minecraftforge.fluids.FluidType;
+import net.neoforged.neoforge.common.ModConfigSpec;
+import net.neoforged.neoforge.fluids.FluidType;
 
 public class ServerConfig {
-    private ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
-    private ForgeConfigSpec spec;
-
-    private ForgeConfigSpec.IntValue range;
-    private ForgeConfigSpec.IntValue speed;
-    private ForgeConfigSpec.IntValue tankCapacity;
-    private ForgeConfigSpec.IntValue energyCapacity;
-    private ForgeConfigSpec.IntValue energyUsagePerMove;
-    private ForgeConfigSpec.IntValue energyUsagePerDrain;
-    private ForgeConfigSpec.BooleanValue useEnergy;
-    private ForgeConfigSpec.BooleanValue replaceLiquidWithBlock;
-    private ForgeConfigSpec.ConfigValue<String> blockIdToReplaceLiquidsWith;
+    private final ModConfigSpec.Builder builder = new ModConfigSpec.Builder();
+    private final ModConfigSpec spec;
+
+    private final ModConfigSpec.IntValue range;
+    private final ModConfigSpec.IntValue speed;
+    private final ModConfigSpec.IntValue tankCapacity;
+    private final ModConfigSpec.IntValue energyCapacity;
+    private final ModConfigSpec.IntValue energyUsagePerMove;
+    private final ModConfigSpec.IntValue energyUsagePerDrain;
+    private final ModConfigSpec.BooleanValue useEnergy;
+    private final ModConfigSpec.BooleanValue replaceLiquidWithBlock;
+    private final ModConfigSpec.ConfigValue<String> blockIdToReplaceLiquidsWith;
 
     public ServerConfig() {
         builder.push("pump");
 
         range = builder.comment("The range of the pump").defineInRange("range", 64, 0, 1024);
-        speed = builder.comment("The interval in ticks for when to move on to the next block (higher is slower)").defineInRange("speed", 8, 0, 1024);
-        tankCapacity = builder.comment("The capacity of the internal pump tank").defineInRange("tankCapacity", FluidType.BUCKET_VOLUME * 32, FluidType.BUCKET_VOLUME, Integer.MAX_VALUE);
-        energyCapacity = builder.comment("The capacity of the energy storage").defineInRange("energyCapacity", 32000, 0, Integer.MAX_VALUE);
-        energyUsagePerMove = builder.comment("Energy drained when moving to the next block").defineInRange("energyUsagePerMove", 0, 0, Integer.MAX_VALUE);
-        energyUsagePerDrain = builder.comment("Energy drained when draining liquid").defineInRange("energyUsagePerDrain", 100, 0, Integer.MAX_VALUE);
+        speed = builder.comment("The interval in ticks for when to move on to the next block (higher is slower)")
+            .defineInRange("speed", 8, 0, 1024);
+        tankCapacity = builder.comment("The capacity of the internal pump tank")
+            .defineInRange("tankCapacity", FluidType.BUCKET_VOLUME * 32, FluidType.BUCKET_VOLUME, Integer.MAX_VALUE);
+        energyCapacity = builder.comment("The capacity of the energy storage")
+            .defineInRange("energyCapacity", 32000, 0, Integer.MAX_VALUE);
+        energyUsagePerMove = builder.comment("Energy drained when moving to the next block")
+            .defineInRange("energyUsagePerMove", 0, 0, Integer.MAX_VALUE);
+        energyUsagePerDrain = builder.comment("Energy drained when draining liquid")
+            .defineInRange("energyUsagePerDrain", 100, 0, Integer.MAX_VALUE);
         useEnergy = builder.comment("Whether the pump uses energy to work").define("useEnergy", true);
-        replaceLiquidWithBlock = builder.comment("Replaces liquids that are removed with a block defined in 'blockIdToReplaceLiquidsWith' (to reduce lag)").define("replaceLiquidWithBlock", true);
-        blockIdToReplaceLiquidsWith = builder.comment("The block that liquids are replaced with when 'replaceLiquidWithBlock' is true").define("blockIdToReplaceLiquidsWith", "minecraft:stone");
+        replaceLiquidWithBlock = builder.comment(
+                "Replaces liquids that are removed with a block defined in 'blockIdToReplaceLiquidsWith' (to reduce lag)")
+            .define("replaceLiquidWithBlock", true);
+        blockIdToReplaceLiquidsWith =
+            builder.comment("The block that liquids are replaced with when 'replaceLiquidWithBlock' is true")
+                .define("blockIdToReplaceLiquidsWith", "minecraft:stone");
 
         builder.pop();
 
@@ -71,7 +80,7 @@ public String getBlockIdToReplaceLiquidsWith() {
         return blockIdToReplaceLiquidsWith.get();
     }
 
-    public ForgeConfigSpec getSpec() {
+    public ModConfigSpec getSpec() {
         return spec;
     }
 }
diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml
index 3bbd1a4..9b23caf 100644
--- a/src/main/resources/META-INF/mods.toml
+++ b/src/main/resources/META-INF/mods.toml
@@ -1,5 +1,5 @@
 modLoader = "javafml"
-loaderVersion = "[47,)"
+loaderVersion = "[2,)"
 issueTrackerURL = "https://github.com/refinedmods/rangedpumps"
 license = "MIT"
 [[mods]]
diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta
index 7fc7110..fbab8f8 100644
--- a/src/main/resources/pack.mcmeta
+++ b/src/main/resources/pack.mcmeta
@@ -3,6 +3,6 @@
     "description": {
       "text": "Ranged Pumps resources"
     },
-    "pack_format": 15
+    "pack_format": 18
   }
 }