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)