diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index d8476f963..377f73eab 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -4,6 +4,20 @@ When contributing to this repository, please first discuss the change you wish t
[GitHub issues](https://github.com/refinedmods/refinedstorage2/issues), [Discord](https://discordapp.com/invite/VYzsydb),
or any other method with the owners of this repository before making a change.
+## Quickstart
+
+These are the most important things to know before contributing (also explained in more detail later in this document):
+
+- Commit messages must adhere to [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
+- Branch names must be formatted correctly. The format is `{category}/GH-{issue number}/{lowercase-description}`.
+ Category must match a
+ category [used in our Commitlint config](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum).
+- We use [Checkstyle](https://checkstyle.sourceforge.io/) in our build workflow to validate coding style. It is
+ recommended to import the [config/checkstyle/checkstyle.xml](../config/checkstyle/checkstyle.xml) file into your
+ IDE, so that formatting rules are respected.
+- Branches are kept up to date by rebasing, not by merging.
+- For non-technical changes, adding a changelog entry is required.
+
## Pull requests
- Keep your pull request (PR) as small as possible, this makes reviewing easier.
@@ -51,26 +65,6 @@ use [Crowdin](https://crowdin.com/project/refined-storage-2).
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-### Version metadata
-
-The code doesn't contain version metadata: `build.gradle` specifies a version of `0.0.0` (via Refined Architect).
-The versioning information is entirely contained in Git by using tags.
-
-Per [Semantic Versioning](https://semver.org/spec/v2.0.0.html), the version number being released depends on the changes
-in that release. We usually can't predict those
-changes at the start of a release cycle, so we can't bump the version at the start of a release cycle. That means that
-the version number being released is determined at release time.
-
-Because the version number is determined at release time, we can't store any versioning metadata in the
-code (`build.gradle`). If we did, `build.gradle` would have the version number of the latest released version during the
-release cycle of the new version, which isn't correct.
-
-### Dealing with Minecraft
-
-Whenever we port to a new Minecraft version, at least the minor version should be incremented.
-
-This is needed so that we can still support older Minecraft versions without the version numbers conflicting.
-
## Changelog
The changelog is kept in `CHANGELOG.md`.
@@ -93,7 +87,7 @@ Documentation must be kept up to date when adding or changing functionality.
### Javadoc
-Javadoc is available after every release on https://refinedmods.com/refinedstorage2/.
+Javadoc is available after every release on https://refinedmods.com/javadoc/refinedstorage2/.
### API annotations
@@ -110,6 +104,19 @@ IDE, so that formatting rules are respected.
Moreover, the [CheckStyle-IDEA plugin](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea) can be used to check
if there are no style violations.
+### Import order
+
+IntellIJ does not import the `import` order rules correctly. Apply following order manually:
+
+- import `com.refinedmods.*`
+- blank line
+- import `java.*`
+- import `javax.*`
+- blank line
+- import all other imports
+- blank line
+- import static all other imports
+
## Architecture
### Architecture Decision Records
@@ -138,7 +145,8 @@ Tests in the API modules are regular unit tests. Don't see a "unit" here as a co
These tests don't rely on, nor know about, Minecraft.
-Additionally, tests in the `refinedstorage2-network` module use the `refinedstorage2-network-test` JUnit plugin to easily set up networks for testing.
+Additionally, tests in the `refinedstorage2-network` module use the `refinedstorage2-network-test` JUnit plugin to
+easily set up networks for testing.
### Integration testing
@@ -255,7 +263,7 @@ The workflow takes care of the following:
- Running a build.
- Publishing on [GitHub packages](https://github.com/refinedmods/refinedstorage2/packages) and
CreeperHost Maven.
-- Publishing Javadoc on [GitHub pages](https://github.com/refinedmods/refinedstorage2/tree/gh-pages).
+- Publishing Javadoc on [GitHub pages](https://github.com/refinedmods/javadoc).
- Deploying on [GitHub releases](https://github.com/refinedmods/refinedstorage2/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/doc/architecture/decision/000-template.md b/doc/architecture/decision/000-template.md
new file mode 100644
index 000000000..23a45a200
--- /dev/null
+++ b/doc/architecture/decision/000-template.md
@@ -0,0 +1,13 @@
+# 0.
+
+Date:
+
+## Status
+
+## Context
+
+## Decision
+
+## Consequences
+
+## References
diff --git a/doc/architecture/decision/007-refined-architect.md b/doc/architecture/decision/007-refined-architect.md
new file mode 100644
index 000000000..032dd55e5
--- /dev/null
+++ b/doc/architecture/decision/007-refined-architect.md
@@ -0,0 +1,24 @@
+# 7. Refined Architect
+
+Date: 2023-03-07
+
+## Status
+
+Accepted
+
+## Context
+
+For Refined Storage, we want to build a large ecosystem of addon mods. However, all those addon mods, and even unrelated mods managed by Refined Mods, have a lot of duplication in terms of build infrastructure, GitHub Actions workflows and Gradle setup code.
+
+This duplication makes it difficult to maintain the soon-to-be suite of mods as a whole, especially if we have to upgrade Minecraft.
+
+## Decision
+
+We introduce [Refined Architect](https://github.com/refinedmods/refinedarchitect): a project that is used by all the mods of Refined Mods.
+
+It contains GitHub workflows, version management and Gradle helpers to help making (cross-platform) mods easier.
+
+## Consequences
+
+- Refined Storage adopts Refined Architect.
+- Refined Architect must be kept up to date and maintained in order to upgrade Refined Storage.
diff --git a/doc/architecture/decision/008-versioning.md b/doc/architecture/decision/008-versioning.md
new file mode 100644
index 000000000..605af230a
--- /dev/null
+++ b/doc/architecture/decision/008-versioning.md
@@ -0,0 +1,51 @@
+# 8. Versioning scheme
+
+Date: 2023-01-11
+
+## Status
+
+Accepted
+
+## Context
+
+We must think about:
+
+- What versioning scheme do we use?
+- How do we store versioning information?
+- When do we determine the next version number?
+- How do we deal with Minecraft?
+
+## Decision
+
+### What versioning scheme do we use?
+
+We choose [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+### How do we store versioning information?
+
+The code doesn't contain version metadata: `build.gradle` specifies a version of `0.0.0` (via [Refined Architect](https://github.com/refinedmods/refinedarchitect)).
+The versioning information is entirely contained in Git by using tags.
+
+### When do we determine the next version number?
+
+Per [Semantic Versioning](https://semver.org/spec/v2.0.0.html), the version number being released depends on the changes
+in that release. We usually can't predict those
+changes at the start of a release cycle, so we can't bump the version at the start of a release cycle. That means that
+the version number being released is determined at release time.
+
+Because the version number is determined at release time, we can't store any versioning metadata in the
+code (`build.gradle`). If we did, `build.gradle` would have the version number of the latest released version during the
+release cycle of the new version, which isn't correct.
+
+### How do we deal with Minecraft?
+
+Whenever we port to a new Minecraft version, at least the minor version should be incremented.
+
+This is needed so that we can still support older Minecraft versions without the version numbers conflicting.
+
+## Consequences
+
+- This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+- The code itself doesn't store versioning information.
+- We choose the next version number upon release.
+- Whenever we port to a new Minecraft version, at least the minor version should be incremented.
\ No newline at end of file
diff --git a/doc/architecture/decision/009-package-by-feature.md b/doc/architecture/decision/009-package-by-feature.md
new file mode 100644
index 000000000..c3b4dd125
--- /dev/null
+++ b/doc/architecture/decision/009-package-by-feature.md
@@ -0,0 +1,25 @@
+# 9. Package by feature
+
+Date: 2023-11-01
+
+## Status
+
+Accepted
+
+## Context
+
+Refined Storage adds a lot of content. For ease of maintenance, we need to think about how we are going to segment our packages.
+
+## Decision
+
+We [package by feature, not by layer](https://wayback-api.archive.org/web/20240000000000*/http://www.javapractices.com/topic/TopicAction.do?Id=205).
+
+Implementation provided in [[1]](#1).
+
+## Consequences
+
+- Code is able to use package-private scope a lot more.
+
+## References
+
+- [1] See [implementation](https://github.com/refinedmods/refinedstorage2/commit/d109b09be863c6ea71138091b6ce66c2a573546e)
diff --git a/doc/architecture/decision/010-shared-storage.md b/doc/architecture/decision/010-shared-storage.md
new file mode 100644
index 000000000..f4843306a
--- /dev/null
+++ b/doc/architecture/decision/010-shared-storage.md
@@ -0,0 +1,43 @@
+# 10. Shared storages
+
+Date: 2024-03-03
+
+## Status
+
+Accepted
+
+## Context
+
+Refined Storage 2 has the concept of a storage channel. A storage channel is the highest-level storage of a network. It
+is used by other network devices to interact with the storage network.
+
+As Refined Storage 2 supports multiple resource types, we must decide how we partition those resource types.
+
+## Decision
+
+At the lowest level, we allow mixed resource types within a storage. Since a storage channel is a storage as well, this
+means that the highest level, the storage channel, will allow mixed resource types as well.
+
+We don't partition storages by resource type because:
+
+- This implies the use of a generic type on the `Storage` class, which becomes cumbersome quickly when we don't know the
+ resource type at runtime (relying on unchecked and rawtypes operations).
+- There's no real technical reason to partition storages by resource type. We can have a single storage channel with
+ mixed resource types.
+- If there is a single storage channel, blocks like the Disk Drive don't need to maintain a storage per storage channel.
+ They can expose one storage for all the storage channels, making it easier to reason about.
+
+Implementation provided in [[1]](#1).
+
+## Consequences
+
+- We do remove some compile time safety because we won't have a generic on `Storage`. However:
+ 1) It's a natural consequence if we want to allow mixed storage channels.
+ 2) The compile time safety was mostly gone anyway already due to all the unchecked and raw types operations.
+- We introduce `ResourceKey` to provide some level of safety (not using `Object`).
+- We don't need a storage channel type abstraction (there is only a single storage channel) and move some logic
+ to `ResourceKey`.
+
+## References
+
+- [1] See [implementation](https://github.com/refinedmods/refinedstorage2/commit/1fd63d17417e387d427b2e018a93df89e31edc0f)