diff --git a/.github/ISSUE_TEMPLATE/bug-report-cm5.yml b/.github/ISSUE_TEMPLATE/bug-report-cm5.yml
new file mode 100644
index 00000000..6f4b7a4e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug-report-cm5.yml
@@ -0,0 +1,77 @@
+name: Bug Report - Compact Machines 5 (1.19)
+description: Submit a report for Compact Machines 5
+labels:
+ - triage
+ - 1.19
+ - bug
+ - unverified
+assignees: []
+body:
+ - type: markdown
+ attributes:
+ value: "*Please do not create an issue if you have not tried fixing it by using the latest version of the mod!*"
+
+ - type: checkboxes
+ attributes:
+ label: I am not using performance mods.
+ description: We request you remove performance mods and try to reproduce your issue before submitting this report. Examples include Optifine, Lithium, Sodium, and BetterFPS.
+ options:
+ - label: Confirm
+ required: true
+
+ - type: textarea
+ attributes:
+ label: Description
+ description: Description of the problem, including expected versus actual behavior.
+ placeholder: I attempted to do X, but Y happened instead.
+ validations:
+ required: true
+
+ - type: markdown
+ attributes:
+ value: "## Mod and Forge Versions"
+
+ - type: markdown
+ attributes:
+ value: >
+ *Do not use 'latest' for versions. Be exact; it helps us track down the issue accurately.*
+ If you need help finding the mod version, check the mods menu, accessible from the Main Menu of the game.
+
+ - type: input
+ attributes:
+ label: Mod Version
+ placeholder: 5.0.0
+ validations:
+ required: true
+
+ - type: input
+ attributes:
+ label: Forge Version
+ placeholder: 1.19.2 - 43.1.0
+ validations:
+ required: true
+
+ - type: markdown
+ attributes:
+ value: "## Crash Information"
+
+ - type: input
+ attributes:
+ label: Link to Crashlog
+ placeholder: pastebin/gist/etc.
+
+ - type: textarea
+ attributes:
+ label: Screenshot (if available)
+ description: If you have an image, you can attach it by dragging and dropping it from your file browser to the text area here.
+
+ - type: textarea
+ attributes:
+ label: How to reproduce
+ description: "How do you trigger this bug?"
+ value: |
+ 1.
+ 2.
+ 3.
+ validations:
+ required: true
diff --git a/.github/stale.yml b/.github/stale.yml
new file mode 100644
index 00000000..c33c1911
--- /dev/null
+++ b/.github/stale.yml
@@ -0,0 +1,25 @@
+# Number of days of inactivity before an issue becomes stale
+daysUntilStale: 45
+
+# Number of days of inactivity before a stale issue is closed
+daysUntilClose: 30
+
+# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
+onlyLabels:
+ - triage
+ - awaiting-user
+
+# Issues with these labels will never be considered stale
+exemptLabels:
+ - verified
+ - ready-for-release
+
+staleLabel: stale
+exemptMilestones: true
+
+markComment: >
+ This issue has been automatically marked as stale because it has not had
+ recent activity. It will be closed in one month if no further activity occurs.
+ Thank you for your contributions.
+
+closeComment: false
diff --git a/.github/workflows/announce-latest-nightly.yml b/.github/workflows/announce-latest-nightly.yml
new file mode 100644
index 00000000..df9f4a75
--- /dev/null
+++ b/.github/workflows/announce-latest-nightly.yml
@@ -0,0 +1,99 @@
+name: Announce Latest Nightly to Discord
+
+on:
+ workflow_dispatch:
+ inputs:
+ diagnostic_mode:
+ description: Diagnostic Mode
+ type: boolean
+ default: false
+ required: true
+
+jobs:
+ vars:
+ name: Get Variables
+ runs-on: ubuntu-22.04
+ outputs:
+ mcVersion: ${{steps.gradle_props.outputs.minecraft_version}}
+ forgeVersion: ${{steps.gradle_props.outputs.forge_version}}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: Read MC and Forge versions
+ id: gradle_props
+ uses: christian-draeger/read-properties@1.1.0
+ with:
+ path: "gradle.properties"
+ properties: "minecraft_version forge_version"
+
+ get-package-info:
+ name: Get Latest Package Info
+ runs-on: ubuntu-22.04
+ outputs:
+ version: ${{ steps.download-info.outputs.version }}
+ steps:
+ - name: Download Package Info
+ id: download-info
+ uses: compactmods/dl-package-info@1.0.2
+ env:
+ GQL_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ owner: compactmods
+ repo: compactmachines
+ group: dev.compactmods.compactmachines
+ filter: "^compactmachines-forge-(?:[\\d\\.]+)-nightly.jar$"
+ outputFile: compactmachines-nightly.json
+
+ - name: Debug output
+ run: |
+ echo "Version: ${{ steps.download-info.outputs.version }}"
+ cat compactmachines-nightly.json
+
+ - name: Read info into variable [latest]
+ id: info
+ run: echo "latestJson=$(cat compactmachines-nightly.json)" >> $GITHUB_OUTPUT
+
+ - name: Download JAR and prepare artifacts
+ run: |
+ mkdir release
+ curl -L "${{ fromJson(steps.info.outputs.latestJson)[0].url }}" -o "release/${{ fromJson(steps.info.outputs.latestJson)[0].name}}"
+ mv compactmachines-nightly.json release/compactmachines-nightly.json
+
+ - name: Add Artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: release
+ path: release
+
+ announce:
+ name: Discord Announcement
+ needs: [ vars, get-package-info ]
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Grab JAR and Info
+ uses: actions/download-artifact@v3
+ with:
+ name: release
+ path: .
+
+ - name: Read info into variable [latest]
+ id: info
+ run: echo "latestJson=$(cat compactmachines-nightly.json)" >> $GITHUB_OUTPUT
+
+ - name: Announce Release
+ uses: compactmods/discord-releaser@0.1.5
+ env:
+ DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }}
+ with:
+ filename: ${{ fromJson(steps.info.outputs.latestJson)[0].name}}
+ channel: ${{ secrets.NIGHTLY_CHANNEL_ID }}
+ modName: Compact Machines
+ modVersion: ${{ needs.get-package-info.outputs.version }}
+ thumbnail: https://media.forgecdn.net/avatars/10/602/635460270800375500.png
+
+ forgeVersion: ${{ needs.vars.outputs.forgeVersion }}
+ mcVersion: ${{ needs.vars.outputs.mcVersion }}
diff --git a/.github/workflows/ci-tests-nightly.yml b/.github/workflows/ci-tests-nightly.yml
index 8a66b571..6ba3076f 100644
--- a/.github/workflows/ci-tests-nightly.yml
+++ b/.github/workflows/ci-tests-nightly.yml
@@ -1,12 +1,11 @@
name: Gradle Tests and Nightly (CI)
+env:
+ GH_PKG_URL: "https://maven.pkg.github.com/${{ github.repository }}"
+
on:
workflow_dispatch:
push:
- branches:
- - '**'
- tags-ignore:
- - v*
paths-ignore:
- "README.md"
- "LICENSE"
@@ -15,56 +14,72 @@ on:
jobs:
vars:
name: Get Variables
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
outputs:
- release_type: ${{steps.cf_release_type.outputs.value }}
+ version: ${{steps.version.outputs.version}}
+ mcVersion: ${{steps.gradle_props.outputs.minecraft_version}}
+ forgeVersion: ${{steps.gradle_props.outputs.forge_version}}
+
steps:
- name: Checkout
- uses: actions/checkout@v2.4.0
-
- - name: Release Type
- id: cf_release_type
- uses: christian-draeger/read-properties@1.0.1
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: Version
+ id: version
+ uses: paulhatch/semantic-version@v5.0.2
+ with:
+ change_path: "forge-main"
+ version_format: "${major}.${minor}.${patch}.${increment}-nightly"
+ search_commit_body: true
+
+ - name: Read MC and Forge versions
+ id: gradle_props
+ uses: christian-draeger/read-properties@1.1.1
with:
- path: './gradle.properties'
- property: 'cf_release_type'
+ path: "gradle.properties"
+ properties: "minecraft_version forge_version"
tests:
name: Gradle Tests
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
needs: [ vars ]
steps:
- name: Checkout
- uses: actions/checkout@v2.4.0
+ uses: actions/checkout@v3
- - name: Unshallow and Get Tags
- run: git fetch --prune --unshallow --tags
-
- name: Set up JDK
- uses: actions/setup-java@v2
+ uses: actions/setup-java@v3
with:
- distribution: 'temurin'
- java-version: "17"
+ distribution: temurin
+ java-version: 17
- - name: Cache Gradle packages
- uses: actions/cache@v2
- with:
- path: |
- ~/.gradle/caches
- ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- restore-keys: ${{ runner.os }}-gradle-
+ - name: Prepare Gradle
+ uses: gradle/gradle-build-action@v2
- - name: Grant execute permission for gradlew
- run: chmod +x gradlew
+ - name: Datagen
+ uses: gradle/gradle-build-action@v2
+ with:
+ arguments: :forge-datagen:runData
+ env:
+ CM_VERSION: ${{ needs.vars.outputs.version }}
+ GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- - name: Create datagen assets
- continue-on-error: true
- run: ./gradlew runData
+ - name: Store Built Assets
+ if: success()
+ uses: actions/upload-artifact@v3
+ with:
+ name: generated-data
+ path: forge-main/src/generated/resources
- - name: Test JAR with GameTest Server
- run: ./gradlew runGameTestServer
+ - name: Game Tests
+ uses: gradle/gradle-build-action@v2
+ with:
+ arguments: runGameTestServer
env:
+ CM_VERSION: ${{ needs.vars.outputs.version }}
GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -75,41 +90,102 @@ jobs:
name: test-data
path: run/gametest
- nightly:
- name: Publish Nightly
- runs-on: ubuntu-20.04
+ publish-gh-package:
+ name: Publish Github Package - Nightly
+ runs-on: ubuntu-22.04
needs: [ vars, tests ]
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- - name: Unshallow and Get Tags
- run: git fetch --prune --unshallow --tags
-
- name: Set up JDK
- uses: actions/setup-java@v2
+ uses: actions/setup-java@v3
with:
- distribution: 'temurin'
- java-version: "17"
+ distribution: temurin
+ java-version: 17
- - name: Cache Gradle packages
- uses: actions/cache@v2
+ - name: Pull Built Generated Data
+ uses: actions/download-artifact@v3
with:
- path: |
- ~/.gradle/caches
- ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- restore-keys: ${{ runner.os }}-gradle-
-
- - name: Grant execute permission for gradlew
- run: chmod +x gradlew
+ name: generated-data
+ path: forge-main/src/generated/resources
- - name: Generate Resources
- run: ./gradlew runData
-
- - name: Publish gradle nightly jar
- run: ./gradlew publishNightlyPublicationToGitHubPackagesRepository
+ - name: Publish
+ uses: gradle/gradle-build-action@v2
+ with:
+ arguments: publish
env:
- CM_RELEASE: false
+ CM_VERSION: ${{ needs.vars.outputs.version }}
GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ get-package-info:
+ name: Get Latest Package Info
+ runs-on: ubuntu-22.04
+ needs: [ publish-gh-package ]
+ outputs:
+ version: ${{ steps.download-info.outputs.version }}
+ steps:
+ - name: Download Package Info
+ id: download-info
+ uses: compactmods/dl-package-info@1.0.2
+ env:
+ GQL_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ owner: compactmods
+ repo: compactmachines
+ group: dev.compactmods.compactmachines
+ filter: "^compactmachines-forge-(?:[\\d\\.]+)-nightly.jar$"
+ outputFile: compactmachines-nightly.json
+
+ - name: Store Package Info
+ if: success()
+ uses: actions/upload-artifact@v3
+ with:
+ name: package-info
+ path: compactmachines-nightly.json
+
+ - name: Read info into variable [latest]
+ id: info
+ run: echo "latestJson=$(cat compactmachines-nightly.json)" >> $GITHUB_OUTPUT
+
+ - name: Download JAR and prepare artifacts
+ run: |
+ mkdir release
+ curl -L "${{ fromJson(steps.info.outputs.latestJson)[0].url }}" -o "release/${{ fromJson(steps.info.outputs.latestJson)[0].name}}"
+ mv compactmachines-nightly.json release/compactmachines-nightly.json
+
+ - name: Add Artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: release
+ path: release
+
+ announce:
+ name: Discord Announcement
+ needs: [ vars, get-package-info ]
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Grab JAR and Info
+ uses: actions/download-artifact@v3
+ with:
+ name: release
+ path: .
+
+ - name: Read info into variable [latest]
+ id: info
+ run: echo "latestJson=$(cat compactmachines-nightly.json)" >> $GITHUB_OUTPUT
+
+ - name: Announce Release
+ uses: compactmods/discord-releaser@0.1.5
+ env:
+ DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }}
+ with:
+ filename: ${{ fromJson(steps.info.outputs.latestJson)[0].name}}
+ channel: ${{ secrets.NIGHTLY_CHANNEL_ID }}
+ modName: Compact Machines
+ modVersion: ${{ needs.get-package-info.outputs.version }}
+ thumbnail: https://media.forgecdn.net/avatars/10/602/635460270800375500.png
+
+ forgeVersion: ${{ needs.vars.outputs.forgeVersion }}
+ mcVersion: ${{ needs.vars.outputs.mcVersion }}
\ No newline at end of file
diff --git a/.github/workflows/tagged-release.yml b/.github/workflows/tagged-release.yml
index 2a73612b..41722bc2 100644
--- a/.github/workflows/tagged-release.yml
+++ b/.github/workflows/tagged-release.yml
@@ -13,10 +13,11 @@ jobs:
cf_project: ${{steps.cf_project.outputs.value }}
mod_id: ${{steps.mod_id.outputs.value }}
version: ${{steps.version.outputs.version }}
+ build: ${{steps.build.outputs.buildver}}
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Unshallow
run: git fetch --prune --unshallow
@@ -57,12 +58,19 @@ jobs:
version=$(echo "${{steps.current.outputs.tag}}" | cut -dv -f2)
echo "::set-output name=version::$version"
+ - name: Build Version
+ id: build
+ run: |
+ buildver=$(git describe --tags --match v* | cut -d- -f2)
+ echo "build = $buildver"
+ echo "::set-output name=buildver::$buildver"
+
changelog:
name: Generate Changelog (tags)
runs-on: ubuntu-20.04
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Unshallow
run: git fetch --prune --unshallow
@@ -118,7 +126,7 @@ jobs:
path: changelog
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v2
@@ -135,14 +143,15 @@ jobs:
env:
CM_RELEASE: true
CM_SEMVER_VERSION: ${{ needs.vars.outputs.version }}
- CM_BUILD_NUM: "0"
+ CM_BUILD_NUM: ${{ needs.vars.outputs.build }}
- name: Test JAR with GameTest Server
run: ./gradlew runGameTestServer
timeout-minutes: 20
env:
+ CM_RELEASE: true
CM_SEMVER_VERSION: ${{ needs.vars.outputs.version }}
- CM_BUILD_NUM: "0"
+ CM_BUILD_NUM: ${{ needs.vars.outputs.build }}
GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -159,7 +168,7 @@ jobs:
env:
CM_RELEASE: true
CM_SEMVER_VERSION: ${{ needs.vars.outputs.version }}
- CM_BUILD_NUM: "0"
+ CM_BUILD_NUM: ${{ needs.vars.outputs.build }}
GITHUB_ACTOR: ${{ secrets.GITHUB_ACTOR }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -168,8 +177,8 @@ jobs:
with:
name: libs
path: |
- build-out/${{ needs.vars.outputs.mod_id }}-${{ needs.vars.outputs.version }}.jar
- build-out/${{ needs.vars.outputs.mod_id }}-${{ needs.vars.outputs.version }}-api.jar
+ build/libs/${{ needs.vars.outputs.mod_id }}-${{ needs.vars.outputs.version }}.jar
+ build/libs/${{ needs.vars.outputs.mod_id }}-${{ needs.vars.outputs.version }}-api.jar
view:
name: View Changelog Output
@@ -212,8 +221,8 @@ jobs:
prerelease: false
files: |
changelog/CHANGELOG.md
- build-out/${{ needs.vars.outputs.mod_id }}-${{ needs.vars.outputs.version }}.jar
- build-out/${{ needs.vars.outputs.mod_id }}-${{ needs.vars.outputs.version }}-api.jar
+ build/libs/${{ needs.vars.outputs.mod_id }}-${{ needs.vars.outputs.version }}.jar
+ build/libs/${{ needs.vars.outputs.mod_id }}-${{ needs.vars.outputs.version }}-api.jar
release-cf:
name: Make Curseforge Release
@@ -257,7 +266,7 @@ jobs:
needs: [changelog, vars, jar]
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v2
diff --git a/.gitignore b/.gitignore
index 82e424a6..a4111ad0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,6 +33,10 @@ logs/
*.dot
-src/generated/
+forge-main/src-old/generated/
raw-assets/
+
+forge-main/src/generated/resources/.cache/
+
+forge-main/src/generated/
diff --git a/README.md b/README.md
index 63663bae..fef036ad 100644
--- a/README.md
+++ b/README.md
@@ -1,38 +1,50 @@
-# Compact Machines 4
+
-Minecraft Mod. Adds one simple game mechanic: Small rooms inside of blocks.
+A Minecraft mod that adds one simple game mechanic: small rooms inside of blocks. You can grab the latest build off [Curseforge] or on [Github Releases].
-You can grab the latest build (tagged) in the releases tab.
+| Version | Minecraft Version | Released | Support | Support Ends |
+| :-------------- | :---------------: | ------------: | :-----: | -------------- |
+| 5.2 | 1.19.2 | - | ✅ | - |
+| **5.1** | 1.19.2 | July 2022 | ✅ | - |
+| 5.0 | 1.19.2 | July 2022 | ❌ | July 2022 |
+| **4.5** | 1.18.2 | July 2022 | ❌ | September 2022 |
+| 4.4 | 1.18.2 | July 2022 | ❌ | - |
+| 4.3 | 1.18.2 | May 2022 | ❌ | - |
+| 4.2 | 1.18.2 | April 2022 | ❌ | - |
+| **4.0-beta2** | 1.16.5 | March 2021 | ❌ | July 2022 |
+| **3.0.19-b278** | 1.12.2 | May 2019 | ❌ | 2021 |
+| **2.0.1-b141** | 1.10.2 | October 2017 | ❌ | 2019 |
+| **1.21** | 1.7.10 | November 2015 | ❌ | 2017 |
-## Compact Machines
+\* *Note - only the most recent versions are shown here for brevity.*
-These are the main component of this mod and allow you to build complicated machine contraptions and hide them within a single Compact Machine block.
+Standard support policy is after a new version is released for the current Minecraft version, support for the previous version is dropped. If a new major Minecraft version is released and CM is updated, support for the previous major version is currently ***45*** days.
-#### Sizes
-There are 6 different sizes of machines:
+
-| Name | Description |
-| ----------------------------| -------------|
-| Tiny | 3x3x3 |
-| Small | 5x5x5 |
-| Normal | 7x7x7 |
-| Large | 9x9x9 |
-| Giant | 11x11x11 |
-| Maximum | 13x13x13 |
+# Contributing
-#### Personal Shrinking Device
+## Prerequisite: Github Packages
+First of all, thank you for wanting to help! To get started, you will need to set up authentication for Github Packages. Github has a guide for how to set up authentication here:
-This little tool allows you to enter your Compact Machines. Right clicking a Compact Machine world will teleport you inside.
+https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry#authenticating-to-github-packages
-#### Spawn location
+It is recommended to create a `gradle.properties` file in your user-level gradle folder to simplify working across multiple repositories.
-By default, you spawn in the center of the room. You can change this by shift-right-clicking a Personal Shrinking Device at the location you want to set the spawn to.
+## Modules
+Compact Machines is split into multiple modules to make updating and version maintenance easier. The following is a quick summary of each module's purpose:
-Make sure not to obstruct the spawn location, there is currently no mechanic to automatically search for a better spawn location. You don't want to have to break the blocks you spawn in.
+| Module | Description
+| --- | ---
+| core-api | Contains classes used across all other modules; modloader-independent.
+| core | Contains data classes and core functionality not tied to a mod loader.
+| tunnels-api | Shipped to end users as a baseline for working with tunnel integration.
+| forge-tunnels-api | Contains Forge-specific API code for tunnels. (Mainly capability support)
-## Miniaturization Crafting
-See the [Compact Crafting] mod instead. The crafting mechanic was split in 1.16 due to the dimension and worldgen changes.
+If you are interested in working with `core-api`, `core`, or `tunnels-api`, you can find them in the [core repository](https://github.com/CompactMods/compactmachines-core).
+---
-[Compact Crafting]: https://github.com/robotgryphon/CompactCrafting
+[Curseforge]: https://www.curseforge.com/minecraft/mc-mods/compact-machines
+[Github Releases]: https://github.com/CompactMods/CompactMachines/releases
\ No newline at end of file
diff --git a/assets/machine.aseprite b/assets/machine.aseprite
new file mode 100644
index 00000000..d0dc4564
Binary files /dev/null and b/assets/machine.aseprite differ
diff --git a/assets/personal_shrinking_device.aseprite b/assets/personal_shrinking_device.aseprite
new file mode 100644
index 00000000..bee07c41
Binary files /dev/null and b/assets/personal_shrinking_device.aseprite differ
diff --git a/raw-assets/personal_shrinking_device.png b/assets/personal_shrinking_device.png
similarity index 100%
rename from raw-assets/personal_shrinking_device.png
rename to assets/personal_shrinking_device.png
diff --git a/assets/room-core.aseprite b/assets/room-core.aseprite
new file mode 100644
index 00000000..782e1a6c
Binary files /dev/null and b/assets/room-core.aseprite differ
diff --git a/build.gradle b/build.gradle
deleted file mode 100644
index e5bc8cf4..00000000
--- a/build.gradle
+++ /dev/null
@@ -1,375 +0,0 @@
-buildscript {
- repositories {
- maven { url = 'https://maven.minecraftforge.net' }
- maven { url = 'https://maven.parchmentmc.org' }
- maven { url = 'https://repo.spongepowered.org/repository/maven-public' }
- mavenCentral()
- mavenLocal()
- }
-
- dependencies {
- classpath "net.minecraftforge.gradle:ForgeGradle:5.1.+"
- classpath 'org.parchmentmc:librarian:1.+'
- }
-}
-
-plugins {
- id "idea"
- id "eclipse"
- id "maven-publish"
-}
-
-apply plugin: "net.minecraftforge.gradle"
-apply plugin: 'org.parchmentmc.librarian.forgegradle'
-
-def semver = System.getenv("CM_SEMVER_VERSION")
-def buildNumber = System.getenv("CM_BUILD_NUM")
-
-def nightlyVersion = "${semver}.${buildNumber}"
-def isRelease = (System.getenv("CM_RELEASE") ?: "false").equalsIgnoreCase("true")
-
-task getBuildInfo() {
- println("Mod ID: ${mod_id}")
- println("Version: ${isRelease ? semver : nightlyVersion}")
- println("Semver Version: ${semver}")
- println("Nightly Build: ${nightlyVersion}")
-}
-
-version = isRelease ? "${semver}" : nightlyVersion
-group = "dev.compactmods"
-archivesBaseName = mod_id
-
-java.toolchain.languageVersion = JavaLanguageVersion.of(17)
-sourceSets {
- api {
- resources.srcDirs = []
- compileClasspath += configurations.getByName("minecraft")
- }
-
- datagen {
- compileClasspath += configurations.getByName("minecraft")
- compileClasspath += sourceSets.api.output
- runtimeClasspath += sourceSets.api.output
- compileClasspath += sourceSets.main.output
- runtimeClasspath += sourceSets.main.output
- }
-
- tunnels {
- compileClasspath += configurations.getByName("minecraft")
- compileClasspath += sourceSets.api.output
- runtimeClasspath += sourceSets.api.output
- }
-
- main {
- java {
- srcDir "src/main/java"
- }
-
- resources {
- srcDir "src/main/resources"
- srcDir "src/generated/resources"
- }
-
- compileClasspath += sourceSets.api.output
- runtimeClasspath += sourceSets.api.output
- compileClasspath += sourceSets.tunnels.output
- runtimeClasspath += sourceSets.tunnels.output
- }
-
- test {
- java { srcDir "src/test/java" }
- resources { srcDir "src/test/resources" }
-
- compileClasspath += sourceSets.api.output
- runtimeClasspath += sourceSets.api.output
- }
-}
-
-println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
-minecraft {
- mappings channel: 'parchment', version: parchment_version
- // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
-
- accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
-
- // Default run configurations.
- // These can be tweaked, removed, or duplicated as needed.
- runs {
- client {
- workingDirectory project.file('run/client')
-
- // Recommended logging data for a userdev environment
- property 'forge.logging.markers', '' // 'SCAN,REGISTRIES,REGISTRYDUMP'
-
- // Recommended logging level for the console
- property 'forge.logging.console.level', 'debug'
-
- property 'mixin.env.remapRefMap', 'true'
- property 'mixin.env.refMapRemappingFile', "${buildDir}/createSrgToMcp/output.srg"
-
- args '--username', 'Nano'
- args '--width', 1920
- args '--height', 1080
-
- mods {
- compactmachines {
- source sourceSets.tunnels
- source sourceSets.main
- source sourceSets.api
- }
- }
- }
-
- server {
- workingDirectory project.file('run/server')
-
- // Recommended logging data for a userdev environment
- property 'forge.logging.markers', '' // 'SCAN,REGISTRIES,REGISTRYDUMP'
-
- // Recommended logging level for the console
- property 'forge.logging.console.level', 'debug'
-
- property 'forge.enabledGameTestNamespaces', mod_id
-
- property 'mixin.env.remapRefMap', 'true'
- property 'mixin.env.refMapRemappingFile', "${buildDir}/createSrgToMcp/output.srg"
-
- mods {
- compactmachines {
- source sourceSets.tunnels
- source sourceSets.main
- source sourceSets.api
- source sourceSets.test
- }
- }
- }
-
- data {
- workingDirectory project.file('run')
-
- // Recommended logging data for a userdev environment
- property 'forge.logging.markers', '' // 'SCAN,REGISTRIES,REGISTRYDUMP'
-
- // Recommended logging level for the console
- property 'forge.logging.console.level', 'debug'
-
- property 'mixin.env.remapRefMap', 'true'
- property 'mixin.env.refMapRemappingFile', "${buildDir}/createSrgToMcp/output.srg"
-
- args '--mod', mod_id
- args '--existing', file('src/main/resources')
- args '--all'
- args '--output', file('src/generated/resources/')
-
- forceExit false
-
- mods {
- compactmachines {
- source sourceSets.tunnels
- source sourceSets.main
- source sourceSets.api
- source sourceSets.datagen
- }
- }
- }
-
- gameTestServer {
- workingDirectory project.file('run/gametest')
-
- // Recommended logging data for a userdev environment
- // The markers can be added/remove as needed separated by commas.
- // "SCAN": For mods scan.
- // "REGISTRIES": For firing of registry events.
- // "REGISTRYDUMP": For getting the contents of all registries.
- property 'forge.logging.markers', ''
-
- // Recommended logging level for the console
- // You can set various levels here.
- // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
- property 'forge.logging.console.level', 'info'
-
- property 'mixin.env.remapRefMap', 'true'
- property 'mixin.env.refMapRemappingFile', "${buildDir}/createSrgToMcp/output.srg"
-
- forceExit false
-
- mods {
- compactmachines {
- source sourceSets.tunnels
- source sourceSets.api
- source sourceSets.main
- source sourceSets.test
- }
- }
- }
- }
-}
-
-repositories {
- mavenLocal()
-
- maven {
- url "https://www.cursemaven.com"
- content {
- includeGroup "curse.maven"
- }
- }
-
- // location of the maven that hosts JEI files
- maven {
- name "Progwml Repo"
- url "https://dvs1.progwml6.com/files/maven"
- }
-
- // TheOneProbe
- maven {
- url "https://maven.k-4u.nl"
- }
-
- maven {
- name "tterrag maven"
- url "https://maven.tterrag.com/"
- }
-}
-
-dependencies {
- // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
- // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied.
- // The userdev artifact is a special name and will get all sorts of transformations applied to it.
- minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
-
- // JEI
- compileOnly fg.deobf("mezz.jei:jei-${jei_mc_version}-common-api:${jei_version}")
- compileOnly fg.deobf("mezz.jei:jei-${jei_mc_version}-forge-api:${jei_version}")
- runtimeOnly fg.deobf("mezz.jei:jei-${jei_mc_version}-forge:${jei_version}")
-
- // The One Probe
- implementation(fg.deobf("curse.maven:theoneprobe-245211:3871444"))
-
- if (!System.getenv().containsKey("CI") && include_test_mods.equals("true")) {
- // Nicephore - Screenshots and Stuff
- runtimeOnly(fg.deobf("curse.maven:nicephore-401014:3741832"))
-
- // // Testing Mods - Trash Cans, Pipez, Create, Refined Pipes, Pretty Pipes, Refined Storage
- runtimeOnly(fg.deobf("curse.maven:SuperMartijn642-454372:3649270"))
- runtimeOnly(fg.deobf("curse.maven:trashcans-394535:3597654"))
- runtimeOnly(fg.deobf("curse.maven:pipez-443900:3760255"))
-
- runtimeOnly(fg.deobf("curse.maven:flywheel-486392:3737402"))
- runtimeOnly(fg.deobf("curse.maven:create-328085:3737418"))
-
- // runtimeOnly(fg.deobf("curse.maven:refinedpipes-370696:3570151"))
- // runtimeOnly(fg.deobf("curse.maven:prettypipes-376737:3573145"))
- // runtimeOnly(fg.deobf("curse.maven:refinedstorage-243076:3623324"))
- //
- // // Scalable Cat's Force, BdLib, Advanced Generators
- // runtimeOnly(fg.deobf("curse.maven:scalable-320926:3634756"))
- // runtimeOnly(fg.deobf("curse.maven:bdlib-70496:3663149"))
- // runtimeOnly(fg.deobf("curse.maven:advgen-223622:3665335"))
- //
- // // Immersive Eng - 7.1.0-145 (Dec 31)
- // runtimeOnly(fg.deobf("curse.maven:immersiveeng-231951:3587149"))
-
- // FTB Chunks
- runtimeOnly(fg.deobf("curse.maven:architectury-forge-419699:3781711"))
- runtimeOnly(fg.deobf("curse.maven:ftb-teams-404468:3725501"))
- runtimeOnly(fg.deobf("curse.maven:ftblib-404465:3725485"))
- runtimeOnly(fg.deobf("curse.maven:ftbchunks-314906:3780113"))
-
- // Mekanism + Mek Generators - Tunnel testing
- runtimeOnly(fg.deobf("curse.maven:mekanism-268560:3743835"))
- runtimeOnly(fg.deobf("curse.maven:mekanismgenerators-268566:3743837"))
-
- // Soul Shards (FTB)
- runtimeOnly(fg.deobf("curse.maven:polylib-576589:3751528"))
- runtimeOnly(fg.deobf("curse.maven:soulshards-551523:3757202"))
-
- // Everlasting Abilities
- runtimeOnly(fg.deobf("curse.maven:cyclopscore-232758:3809427"))
- runtimeOnly(fg.deobf("curse.maven:everlastabilities-248353:3768481"))
- }
-}
-
-processResources {
- duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
-}
-
-processTestResources {
- duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
-}
-
-compileDatagenJava {
- options.encoding = 'UTF-8'
-}
-
-jar {
- from sourceSets.tunnels.output
- from sourceSets.main.output
- from sourceSets.api.output
- destinationDirectory = file("$rootDir/build-out")
-
- finalizedBy('reobfJar')
-
- manifest {
- attributes([
- "Specification-Title" : "Compact Machines",
- "Specification-Vendor" : "",
- "Specification-Version" : "1", // We are version 1 of ourselves
- "Implementation-Title" : project.name,
- "Implementation-Version" : archiveVersion,
- "Implementation-Vendor" : "",
- "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
- ])
- }
-}
-
-task apiJar(type: Jar) {
- from sourceSets.api.output
- // Sources included because of MinecraftForge/ForgeGradle#369
- archiveClassifier = 'api'
- destinationDirectory = file("$rootDir/build-out")
-}
-
-artifacts {
- archives jar, apiJar
-}
-
-publishing {
- publications {
- release(MavenPublication) {
- artifactId = mod_id
- groupId = "dev.compactmods"
-
- artifacts {
- artifact jar
- artifact(apiJar) {
- classifier = "api"
- }
- }
- }
-
- nightly(MavenPublication) {
- artifactId = mod_id
- groupId = "dev.compactmods.nightly"
-
- artifacts {
- artifact(jar)
- artifact(apiJar) {
- classifier = "api"
- }
- }
- }
- }
-
- repositories {
- // GitHub Packages
- maven {
- name = "GitHubPackages"
- url = "https://maven.pkg.github.com/CompactMods/CompactMachines"
- credentials {
- username = System.getenv("GITHUB_ACTOR")
- password = System.getenv("GITHUB_TOKEN")
- }
- }
- }
-}
diff --git a/forge-builtin/build.gradle.kts b/forge-builtin/build.gradle.kts
new file mode 100644
index 00000000..613f56aa
--- /dev/null
+++ b/forge-builtin/build.gradle.kts
@@ -0,0 +1,46 @@
+val coreVersion: String = property("core_version") as String
+val tunnelsApiVersion: String = property("tunnels_version") as String
+
+plugins {
+ id("net.minecraftforge.gradle") version("5.1.+")
+ id("org.parchmentmc.librarian.forgegradle") version("1.+")
+}
+
+java {
+ toolchain.languageVersion.set(JavaLanguageVersion.of(17))
+ withSourcesJar()
+}
+
+var minecraft_version: String by extra
+var forge_version: String by extra
+var parchment_version: String by extra
+
+project.evaluationDependsOn(project(":forge-tunnels-api").path)
+
+repositories {
+ maven("https://maven.pkg.github.com/compactmods/compactmachines-core") {
+ credentials {
+ username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR")
+ password = project.findProperty("gpr.token") as String? ?: System.getenv("GITHUB_TOKEN")
+ }
+ }
+}
+
+dependencies {
+ minecraft (group = "net.minecraftforge", name = "forge", version = "${minecraft_version}-${forge_version}")
+
+ implementation(project(":forge-tunnels-api"))
+
+ implementation("dev.compactmods.compactmachines", "core-api", coreVersion) {
+ isTransitive = false
+ }
+
+ implementation("dev.compactmods.compactmachines", "tunnels-api", tunnelsApiVersion) {
+ isTransitive = false
+ }
+}
+
+minecraft {
+ mappings("parchment", "${parchment_version}-${minecraft_version}")
+ accessTransformer(file("../forge-main/src/main/resources/META-INF/accesstransformer.cfg"))
+}
\ No newline at end of file
diff --git a/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/CMBuiltInAddon.java b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/CMBuiltInAddon.java
new file mode 100644
index 00000000..79ccc235
--- /dev/null
+++ b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/CMBuiltInAddon.java
@@ -0,0 +1,37 @@
+package dev.compactmods.machines.forgebuiltin;
+
+import dev.compactmods.machines.api.CompactMachinesAddon;
+import dev.compactmods.machines.api.ICompactMachinesAddon;
+import dev.compactmods.machines.api.inject.InjectField;
+import dev.compactmods.machines.api.room.IRoomOwnerLookup;
+import dev.compactmods.machines.api.room.registration.IRoomSpawnLookup;
+import dev.compactmods.machines.forgebuiltin.tunnel.BuiltInTunnels;
+import dev.compactmods.machines.forgebuiltin.upgrade.BuiltInUpgrades;
+import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
+
+import java.util.function.Supplier;
+
+@CompactMachinesAddon
+public class CMBuiltInAddon implements ICompactMachinesAddon {
+
+ @InjectField
+ public Supplier roomOwnerLookup;
+
+ @InjectField
+ public Supplier roomSpawnLookup;
+
+ private static CMBuiltInAddon INSTANCE;
+
+ public CMBuiltInAddon() {
+ INSTANCE = this;
+ BuiltInTunnels.prepare();
+ BuiltInUpgrades.prepare();
+ }
+
+ @Override
+ public void afterRegistration() {
+ var bus = FMLJavaModLoadingContext.get().getModEventBus();
+ BuiltInTunnels.REGISTRATION.register(bus);
+ BuiltInUpgrades.REGISTRATION.register(bus);
+ }
+}
diff --git a/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/BuiltInTunnels.java b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/BuiltInTunnels.java
new file mode 100644
index 00000000..ea26bb6a
--- /dev/null
+++ b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/BuiltInTunnels.java
@@ -0,0 +1,29 @@
+package dev.compactmods.machines.forgebuiltin.tunnel;
+
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.tunnels.TunnelDefinition;
+import dev.compactmods.machines.forgebuiltin.tunnel.definitions.BufferedItemTunnel;
+import dev.compactmods.machines.forgebuiltin.tunnel.definitions.FluidTunnel;
+import dev.compactmods.machines.forgebuiltin.tunnel.definitions.ForgeEnergyTunnel;
+import net.minecraftforge.registries.DeferredRegister;
+import net.minecraftforge.registries.RegistryObject;
+
+public class BuiltInTunnels {
+
+ public static DeferredRegister REGISTRATION = DeferredRegister.create(TunnelDefinition.REGISTRY_KEY, Constants.MOD_ID);
+
+ // ================================================================================================================
+ // TUNNEL TYPE DEFINITIONS
+ // ================================================================================================================
+ public static final RegistryObject ITEM_TUNNEL_DEF = REGISTRATION.register("item", BufferedItemTunnel::new);
+
+ public static final RegistryObject FLUID_TUNNEL_DEF = REGISTRATION.register("fluid", FluidTunnel::new);
+
+ public static final RegistryObject FORGE_ENERGY = REGISTRATION.register("energy", ForgeEnergyTunnel::new);
+
+ // public static final RegistryObject REDSTONE_IN = REGISTRATION.register("redstone_in", RedstoneInTunnelDefinition::new);
+
+ public static void prepare() {
+
+ }
+}
diff --git a/src/tunnels/java/dev/compactmods/machines/tunnel/definitions/ItemTunnel.java b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/definitions/BufferedItemTunnel.java
similarity index 62%
rename from src/tunnels/java/dev/compactmods/machines/tunnel/definitions/ItemTunnel.java
rename to forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/definitions/BufferedItemTunnel.java
index bd9ffa61..2143e398 100644
--- a/src/tunnels/java/dev/compactmods/machines/tunnel/definitions/ItemTunnel.java
+++ b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/definitions/BufferedItemTunnel.java
@@ -1,11 +1,11 @@
-package dev.compactmods.machines.tunnel.definitions;
+package dev.compactmods.machines.forgebuiltin.tunnel.definitions;
import com.google.common.collect.ImmutableSet;
import dev.compactmods.machines.api.tunnels.TunnelDefinition;
-import dev.compactmods.machines.api.tunnels.TunnelPosition;
import dev.compactmods.machines.api.tunnels.capability.CapabilityTunnel;
+import dev.compactmods.machines.api.tunnels.lifecycle.IPlayerLifecycleEventReason;
import dev.compactmods.machines.api.tunnels.lifecycle.TunnelInstance;
-import dev.compactmods.machines.api.tunnels.lifecycle.TunnelTeardownHandler;
+import dev.compactmods.machines.api.tunnels.lifecycle.removal.ITunnelRemoveEventListener;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.NonNullList;
@@ -14,15 +14,17 @@
import net.minecraft.world.Containers;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.capabilities.Capability;
+import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.common.util.LazyOptional;
-import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
+import org.jetbrains.annotations.Nullable;
import javax.annotation.Nonnull;
-public class ItemTunnel implements TunnelDefinition, CapabilityTunnel, TunnelTeardownHandler {
+public class BufferedItemTunnel implements TunnelDefinition, CapabilityTunnel,
+ ITunnelRemoveEventListener {
@Override
public int ringColor() {
@@ -38,7 +40,7 @@ public Instance newInstance(BlockPos pos, Direction side) {
@Override
public ImmutableSet> getSupportedCapabilities() {
- return ImmutableSet.of(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
+ return ImmutableSet.of(ForgeCapabilities.ITEM_HANDLER);
}
/**
@@ -49,30 +51,41 @@ public ImmutableSet> getSupportedCapabilities() {
*/
@Override
public LazyOptional getCapability(Capability capType, Instance instance) {
- if (capType == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
+ if (capType == ForgeCapabilities.ITEM_HANDLER) {
return instance.lazy();
}
return LazyOptional.empty();
}
+ @Override
+ public @Nullable BeforeRemove createBeforeRemoveHandler(Instance instance) {
+ // Only allow players to remove item tunnels
+ return (server, position, reason) -> reason instanceof IPlayerLifecycleEventReason;
+ }
+
/**
* Drops items into the machine room before the tunnel is removed from the wall.
*
* @param instance The tunnel instance being modified.
*/
@Override
- public void onRemoved(TunnelPosition position, Instance instance) {
- BlockPos dropAt = position.pos().relative(position.side(), 1);
-
- NonNullList stacks = NonNullList.create();
- for (int i = 0; i < instance.handler.getSlots(); i++) {
- ItemStack stack = instance.handler.getStackInSlot(i);
- if (!stack.isEmpty())
- stacks.add(stack);
- }
-
- Containers.dropContents(position.level(), dropAt, stacks);
+ public @Nullable AfterRemove createAfterRemoveHandler(Instance instance) {
+ return (server, position, reason) -> {
+ if(reason instanceof IPlayerLifecycleEventReason playerReason) {
+ var player = playerReason.player();
+ var dropAt = player.position();
+
+ NonNullList stacks = NonNullList.create();
+ for (int i = 0; i < instance.handler.getSlots(); i++) {
+ ItemStack stack = instance.handler.getStackInSlot(i);
+ if (!stack.isEmpty())
+ stacks.add(stack);
+ }
+
+ stacks.forEach(s -> Containers.dropItemStack(player.level, dropAt.x, dropAt.y + 0.5, dropAt.z, s));
+ }
+ };
}
public static class Instance implements TunnelInstance, INBTSerializable {
diff --git a/src/tunnels/java/dev/compactmods/machines/tunnel/definitions/FluidTunnel.java b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/definitions/FluidTunnel.java
similarity index 89%
rename from src/tunnels/java/dev/compactmods/machines/tunnel/definitions/FluidTunnel.java
rename to forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/definitions/FluidTunnel.java
index 0c17e47b..0acd12c7 100644
--- a/src/tunnels/java/dev/compactmods/machines/tunnel/definitions/FluidTunnel.java
+++ b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/definitions/FluidTunnel.java
@@ -1,4 +1,4 @@
-package dev.compactmods.machines.tunnel.definitions;
+package dev.compactmods.machines.forgebuiltin.tunnel.definitions;
import com.google.common.collect.ImmutableSet;
import dev.compactmods.machines.api.tunnels.TunnelDefinition;
@@ -9,9 +9,9 @@
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.FastColor;
import net.minecraftforge.common.capabilities.Capability;
+import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.common.util.LazyOptional;
-import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.templates.FluidTank;
@@ -25,12 +25,12 @@ public int ringColor() {
@Override
public ImmutableSet> getSupportedCapabilities() {
- return ImmutableSet.of(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY);
+ return ImmutableSet.of(ForgeCapabilities.FLUID_HANDLER);
}
@Override
public LazyOptional getCapability(Capability type, FluidTunnel.Instance instance) {
- if(type == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
+ if(type == ForgeCapabilities.FLUID_HANDLER)
return instance.lazy().cast();
return LazyOptional.empty();
diff --git a/src/tunnels/java/dev/compactmods/machines/tunnel/definitions/ForgeEnergyTunnel.java b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/definitions/ForgeEnergyTunnel.java
similarity index 91%
rename from src/tunnels/java/dev/compactmods/machines/tunnel/definitions/ForgeEnergyTunnel.java
rename to forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/definitions/ForgeEnergyTunnel.java
index 000c906a..c9adb85e 100644
--- a/src/tunnels/java/dev/compactmods/machines/tunnel/definitions/ForgeEnergyTunnel.java
+++ b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/definitions/ForgeEnergyTunnel.java
@@ -1,4 +1,4 @@
-package dev.compactmods.machines.tunnel.definitions;
+package dev.compactmods.machines.forgebuiltin.tunnel.definitions;
import com.google.common.collect.ImmutableSet;
import dev.compactmods.machines.api.tunnels.TunnelDefinition;
@@ -9,9 +9,9 @@
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.FastColor;
import net.minecraftforge.common.capabilities.Capability;
+import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.common.util.LazyOptional;
-import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.EnergyStorage;
import net.minecraftforge.energy.IEnergyStorage;
@@ -25,12 +25,12 @@ public int ringColor() {
@Override
public ImmutableSet> getSupportedCapabilities() {
- return ImmutableSet.of(CapabilityEnergy.ENERGY);
+ return ImmutableSet.of(ForgeCapabilities.ENERGY);
}
@Override
public LazyOptional getCapability(Capability type, Instance instance) {
- if (type == CapabilityEnergy.ENERGY) {
+ if (type == ForgeCapabilities.ENERGY) {
return instance.lazy().cast();
}
diff --git a/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/definitions/redstone/RedstoneInTunnelDefinition.java b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/definitions/redstone/RedstoneInTunnelDefinition.java
new file mode 100644
index 00000000..8c9f2a57
--- /dev/null
+++ b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/tunnel/definitions/redstone/RedstoneInTunnelDefinition.java
@@ -0,0 +1,38 @@
+package dev.compactmods.machines.forgebuiltin.tunnel.definitions.redstone;
+
+import dev.compactmods.machines.api.tunnels.TunnelDefinition;
+import dev.compactmods.machines.api.tunnels.TunnelPosition;
+import dev.compactmods.machines.api.tunnels.redstone.RedstoneReaderTunnel;
+import net.minecraft.core.GlobalPos;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.world.level.LevelReader;
+import net.minecraft.world.level.block.state.BlockState;
+
+import java.awt.*;
+
+public class RedstoneInTunnelDefinition implements RedstoneReaderTunnel, TunnelDefinition {
+
+ @Override
+ public int ringColor() {
+ return new Color(167, 38, 38).getRGB();
+ }
+
+ @Override
+ public int indicatorColor() {
+ return Color.blue.getRGB();
+ // return Color.ORANGE.darker().getRGB();
+ }
+
+ @Override
+ public int powerLevel(MinecraftServer server, GlobalPos machine, TunnelPosition tunnel) {
+ LevelReader connectedWorld = server.getLevel(machine.dimension());
+ if (connectedWorld != null) {
+ final var relPos = machine.pos().relative(tunnel.machineSide()).immutable();
+ BlockState state = connectedWorld.getBlockState(relPos);
+ return state.getSignal(connectedWorld, relPos, tunnel.machineSide());
+ }
+
+ return 0;
+ }
+}
+
diff --git a/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/upgrade/BuiltInUpgrades.java b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/upgrade/BuiltInUpgrades.java
new file mode 100644
index 00000000..43efafd8
--- /dev/null
+++ b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/upgrade/BuiltInUpgrades.java
@@ -0,0 +1,18 @@
+package dev.compactmods.machines.forgebuiltin.upgrade;
+
+import dev.compactmods.machines.api.core.CMRegistryKeys;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.upgrade.RoomUpgrade;
+import net.minecraftforge.registries.DeferredRegister;
+import net.minecraftforge.registries.RegistryObject;
+
+public class BuiltInUpgrades {
+
+ public static DeferredRegister REGISTRATION =
+ DeferredRegister.create(CMRegistryKeys.ROOM_UPGRADES, Constants.MOD_ID);
+
+ public static final RegistryObject CHUNKLOAD =
+ REGISTRATION.register("chunkload", ChunkloadAction::new);
+
+ public static void prepare() {}
+}
diff --git a/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/upgrade/ChunkloadAction.java b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/upgrade/ChunkloadAction.java
new file mode 100644
index 00000000..592695f7
--- /dev/null
+++ b/forge-builtin/src/main/java/dev/compactmods/machines/forgebuiltin/upgrade/ChunkloadAction.java
@@ -0,0 +1,69 @@
+package dev.compactmods.machines.forgebuiltin.upgrade;
+
+import com.mojang.serialization.Codec;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.room.registration.IRoomRegistration;
+import dev.compactmods.machines.api.upgrade.ILevelLoadedUpgradeListener;
+import dev.compactmods.machines.api.upgrade.IUpgradeAppliedListener;
+import dev.compactmods.machines.api.upgrade.IUpgradeRemovedListener;
+import dev.compactmods.machines.api.upgrade.RoomUpgrade;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.TicketType;
+import net.minecraft.world.level.ChunkPos;
+
+import java.util.Comparator;
+
+public class ChunkloadAction implements RoomUpgrade,
+ IUpgradeAppliedListener, IUpgradeRemovedListener,
+ ILevelLoadedUpgradeListener {
+
+ private static final TicketType CHUNKLOAD_LOAD_TYPE = TicketType.create(Constants.MOD_ID + ":rooms", Comparator.comparingLong(ChunkPos::toLong));
+
+ private static final Codec CODEC = Codec.unit(new ChunkloadAction());
+
+ @Override
+ public Codec extends RoomUpgrade> codec() {
+ return CODEC;
+ }
+
+ @Override
+ public void onAdded(ServerLevel level, IRoomRegistration room) {
+ forceLoad(level, room);
+ }
+
+ @Override
+ public void onRemoved(ServerLevel level, IRoomRegistration room) {
+ normalLoad(level, room);
+ }
+
+ @Override
+ public void onLevelLoaded(ServerLevel level, IRoomRegistration room) {
+ forceLoad(level, room);
+ }
+
+ @Override
+ public void onLevelUnloaded(ServerLevel level, IRoomRegistration room) {
+ normalLoad(level, room);
+ }
+
+ private static void forceLoad(ServerLevel level, IRoomRegistration room) {
+ final var chunks = level.getChunkSource();
+ room.chunks().forEach(chunk -> {
+ level.setChunkForced(chunk.x, chunk.z, true);
+ chunks.addRegionTicket(CHUNKLOAD_LOAD_TYPE, chunk, 2, chunk);
+ });
+
+ chunks.save(false);
+ }
+
+ private static void normalLoad(ServerLevel level, IRoomRegistration room) {
+ final var chunks = level.getChunkSource();
+ room.chunks().forEach(chunk -> {
+ level.setChunkForced(chunk.x, chunk.z, false);
+ chunks.removeRegionTicket(CHUNKLOAD_LOAD_TYPE, chunk, 2, chunk);
+ });
+
+ chunks.save(false);
+ }
+}
+
diff --git a/forge-builtin/src/main/resources/META-INF/MANIFEST.MF b/forge-builtin/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..e69de29b
diff --git a/forge-builtin/src/main/resources/compactmachines/upgrades/wip.json b/forge-builtin/src/main/resources/compactmachines/upgrades/wip.json
new file mode 100644
index 00000000..1b3be6e4
--- /dev/null
+++ b/forge-builtin/src/main/resources/compactmachines/upgrades/wip.json
@@ -0,0 +1,25 @@
+{
+ "max_allowed": 1,
+ "apply_conditions": [
+ { "type": "compactmachines:room_owner" }
+ ],
+ "actions": [
+ { "type": "compactmachines:chunkload" },
+ {
+ "type": "compactmachines:generate_item_fixed",
+ "cooldown": 20,
+ "count": 16,
+ "item": {
+ "item": "minecraft:cobblestone"
+ }
+ },
+ {
+ "type": "compactmachines:generate_item_scaled",
+ "cooldown": 20,
+ "scale_factor": 4,
+ "item": {
+ "item": "minecraft:iron_ore"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/forge-datagen/build.gradle.kts b/forge-datagen/build.gradle.kts
new file mode 100644
index 00000000..da4a9ab4
--- /dev/null
+++ b/forge-datagen/build.gradle.kts
@@ -0,0 +1,113 @@
+val modVersion: String = System.getenv("CM_VERSION") ?: "9.9.9"
+
+val coreVersion: String = property("core_version") as String
+val tunnelsApiVersion: String = property("tunnels_version") as String
+
+var modId = property("mod_id") as String
+var minecraft_version: String by extra
+var forge_version: String by extra
+var parchment_version: String by extra
+
+val forgeMain = project(":forge-main")
+
+plugins {
+ id("net.minecraftforge.gradle") version ("5.1.+")
+ id("org.parchmentmc.librarian.forgegradle") version ("1.+")
+}
+
+base {
+ group = "dev.compactmods.compactmachines"
+ version = modVersion
+}
+
+java {
+ toolchain.languageVersion.set(JavaLanguageVersion.of(17))
+}
+
+sourceSets.main {
+ resources {
+ srcDir(file("src/main/resources"))
+ }
+}
+
+repositories {
+ mavenLocal()
+
+ maven("https://maven.pkg.github.com/compactmods/compactmachines-core") {
+ name = "Github PKG Core"
+ credentials {
+ username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR")
+ password = project.findProperty("gpr.token") as String? ?: System.getenv("GITHUB_TOKEN")
+ }
+ }
+}
+
+val runDepends: List = listOf(
+ project(":forge-tunnels-api"),
+ project(":forge-builtin"),
+ forgeMain
+)
+
+runDepends.forEach {
+ project.evaluationDependsOn(it.path)
+}
+
+dependencies {
+ minecraft("net.minecraftforge", "forge", version = "${minecraft_version}-${forge_version}")
+
+ implementation("dev.compactmods.compactmachines:core-api:$coreVersion")
+ implementation("dev.compactmods.compactmachines:core:$coreVersion")
+ implementation("dev.compactmods.compactmachines:tunnels-api:$tunnelsApiVersion")
+
+ compileOnly(project(":forge-tunnels-api"))
+ compileOnly(project(":forge-builtin"))
+ compileOnly(project(":forge-main")) {
+ isTransitive = false
+ }
+}
+
+minecraft {
+ mappings("parchment", "${parchment_version}-${minecraft_version}")
+ accessTransformer(file("src/main/resources/META-INF/accesstransformer.cfg"))
+
+ runs {
+ all {
+ // Recommended logging data for a userdev environment
+ property("forge.logging.markers", "") // "SCAN,REGISTRIES,REGISTRYDUMP"
+
+ // Recommended logging level for the console
+ property("forge.logging.console.level", "debug")
+
+ property("mixin.env.remapRefMap", "true")
+ property("mixin.env.refMapRemappingFile", "${buildDir}/createSrgToMcp/output.srg")
+
+ ideaModule("Compact_Machines.forge-datagen.main")
+
+ source(sourceSets.main.get())
+ mods.create(modId) {
+ source(sourceSets.main.get())
+ for (p in runDepends)
+ source(p.sourceSets.main.get())
+ }
+ }
+
+ create("data") {
+ taskName("runData")
+ workingDirectory(file("run"))
+ forceExit(false)
+
+ args("--mod", modId)
+ args("--existing", forgeMain.file("src/main/resources"))
+ args("--all")
+ args("--output", forgeMain.file("src/generated/resources"))
+ }
+ }
+}
+
+tasks.compileJava {
+ options.encoding = "UTF-8";
+}
+
+tasks.withType {
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+}
\ No newline at end of file
diff --git a/src/datagen/java/dev/compactmods/machines/datagen/AdvancementGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/AdvancementGenerator.java
similarity index 93%
rename from src/datagen/java/dev/compactmods/machines/datagen/AdvancementGenerator.java
rename to forge-datagen/src/main/java/dev/compactmods/machines/datagen/AdvancementGenerator.java
index c4a2e13a..d5323a8d 100644
--- a/src/datagen/java/dev/compactmods/machines/datagen/AdvancementGenerator.java
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/AdvancementGenerator.java
@@ -3,14 +3,15 @@
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
-import dev.compactmods.machines.CompactMachines;
import dev.compactmods.machines.advancement.trigger.BasicPlayerAdvTrigger;
import dev.compactmods.machines.advancement.trigger.HowDidYouGetHereTrigger;
import dev.compactmods.machines.api.core.Advancements;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.LoggingUtil;
import dev.compactmods.machines.i18n.TranslationUtil;
-import dev.compactmods.machines.machine.Machines;
-import dev.compactmods.machines.shrinking.Shrinking;
-import dev.compactmods.machines.wall.Walls;
+import dev.compactmods.machines.forge.machine.Machines;
+import dev.compactmods.machines.forge.shrinking.Shrinking;
+import dev.compactmods.machines.forge.wall.Walls;
import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.DisplayInfo;
import net.minecraft.advancements.FrameType;
@@ -22,8 +23,9 @@
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
+import org.apache.logging.log4j.Logger;
+import org.jetbrains.annotations.NotNull;
-import javax.annotation.Nonnull;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Set;
@@ -32,6 +34,8 @@
public class AdvancementGenerator implements DataProvider {
+ private static final Logger LOGGER = LoggingUtil.modLog();
+
private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create();
private final DataGenerator generator;
@@ -40,7 +44,7 @@ public AdvancementGenerator(DataGenerator gen) {
}
@Override
- public void run(@Nonnull CachedOutput cache) {
+ public void run(@NotNull CachedOutput cache) {
Path path = this.generator.getOutputFolder();
Set set = Sets.newHashSet();
Consumer consumer = (adv) -> {
@@ -52,7 +56,7 @@ public void run(@Nonnull CachedOutput cache) {
try {
DataProvider.saveStable(cache, adv.deconstruct().serializeToJson(), path1);
} catch (IOException ioexception) {
- CompactMachines.LOGGER.error("Couldn't save advancement {}", path1, ioexception);
+ LOGGER.error("Couldn't save advancement {}", path1, ioexception);
}
}
@@ -62,7 +66,7 @@ public void run(@Nonnull CachedOutput cache) {
}
private ResourceLocation modLoc(String i) {
- return new ResourceLocation(CompactMachines.MOD_ID, i);
+ return new ResourceLocation(Constants.MOD_ID, i);
}
private void generateAdvancements(Consumer consumer) {
diff --git a/src/datagen/java/dev/compactmods/machines/datagen/AdvancementLangBuilder.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/AdvancementLangBuilder.java
similarity index 100%
rename from src/datagen/java/dev/compactmods/machines/datagen/AdvancementLangBuilder.java
rename to forge-datagen/src/main/java/dev/compactmods/machines/datagen/AdvancementLangBuilder.java
diff --git a/src/datagen/java/dev/compactmods/machines/datagen/BlockLootGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/BlockLootGenerator.java
similarity index 86%
rename from src/datagen/java/dev/compactmods/machines/datagen/BlockLootGenerator.java
rename to forge-datagen/src/main/java/dev/compactmods/machines/datagen/BlockLootGenerator.java
index 53118ec3..d902c20e 100644
--- a/src/datagen/java/dev/compactmods/machines/datagen/BlockLootGenerator.java
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/BlockLootGenerator.java
@@ -2,14 +2,13 @@
import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.util.Pair;
-import dev.compactmods.machines.machine.Machines;
-import dev.compactmods.machines.room.data.CopyRoomBindingFunction;
-import dev.compactmods.machines.wall.Walls;
+import dev.compactmods.machines.forge.machine.Machines;
+import dev.compactmods.machines.forge.data.functions.CopyRoomBindingFunction;
+import dev.compactmods.machines.forge.wall.Walls;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.loot.BlockLoot;
import net.minecraft.data.loot.LootTableProvider;
import net.minecraft.resources.ResourceLocation;
-import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.LootTable;
@@ -56,21 +55,24 @@ protected void addTables() {
.add(LootItem.lootTableItem(Walls.ITEM_BREAKABLE_WALL.get()))));
// Compact Machines
- registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK_TINY, Machines.MACHINE_BLOCK_ITEM_TINY);
- registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK_SMALL, Machines.MACHINE_BLOCK_ITEM_SMALL);
- registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK_NORMAL, Machines.MACHINE_BLOCK_ITEM_NORMAL);
- registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK_LARGE, Machines.MACHINE_BLOCK_ITEM_LARGE);
- registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK_GIANT, Machines.MACHINE_BLOCK_ITEM_GIANT);
- registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK_MAXIMUM, Machines.MACHINE_BLOCK_ITEM_MAXIMUM);
+ registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK);
+
+ // Legacy Machines
+ registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK_TINY);
+ registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK_SMALL);
+ registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK_NORMAL);
+ registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK_LARGE);
+ registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK_GIANT);
+ registerCompactMachineBlockDrops(Machines.MACHINE_BLOCK_MAXIMUM);
}
- private void registerCompactMachineBlockDrops(RegistryObject block, RegistryObject- item) {
+ private void registerCompactMachineBlockDrops(RegistryObject block) {
LootPool.Builder builder = LootPool.lootPool()
.name(block.getId().toString())
.setRolls(ConstantValue.exactly(1))
.when(ExplosionCondition.survivesExplosion())
.apply(CopyRoomBindingFunction.binding())
- .add(LootItem.lootTableItem(item.get()));
+ .add(LootItem.lootTableItem(Machines.BOUND_MACHINE_BLOCK_ITEM.get()));
this.add(block.get(), LootTable.lootTable().withPool(builder));
}
@@ -82,6 +84,7 @@ protected Iterable getKnownBlocks() {
Walls.BLOCK_BREAKABLE_WALL.get(),
// Compact Machines
+ Machines.MACHINE_BLOCK.get(),
Machines.MACHINE_BLOCK_TINY.get(),
Machines.MACHINE_BLOCK_SMALL.get(),
Machines.MACHINE_BLOCK_NORMAL.get(),
diff --git a/src/datagen/java/dev/compactmods/machines/datagen/DataGenUtil.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/DataGenUtil.java
similarity index 87%
rename from src/datagen/java/dev/compactmods/machines/datagen/DataGenUtil.java
rename to forge-datagen/src/main/java/dev/compactmods/machines/datagen/DataGenUtil.java
index c3dd4d76..5a95ee54 100644
--- a/src/datagen/java/dev/compactmods/machines/datagen/DataGenUtil.java
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/DataGenUtil.java
@@ -5,7 +5,8 @@
import com.google.gson.JsonElement;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
-import dev.compactmods.machines.CompactMachines;
+import dev.compactmods.machines.forge.CompactMachines;
+import dev.compactmods.machines.api.core.Constants;
import net.minecraft.data.CachedOutput;
import net.minecraft.data.DataProvider;
import net.minecraft.resources.ResourceLocation;
@@ -17,8 +18,8 @@
import java.util.function.BiConsumer;
import java.util.function.Function;
-class DataGenUtil {
- static BiConsumer makeWriter(Gson gson, @Nonnull CachedOutput cache, Path dataDir, ImmutableSet pathParts, Codec codec, HashMap set) {
+public class DataGenUtil {
+ public static BiConsumer makeWriter(Gson gson, @Nonnull CachedOutput cache, Path dataDir, ImmutableSet pathParts, Codec codec, HashMap set) {
return (T resource, ResourceLocation regName) -> {
if (set.containsKey(regName)) {
throw new IllegalStateException("Duplicate resource " + regName);
@@ -26,7 +27,7 @@ static BiConsumer makeWriter(Gson gson, @Nonnull Cached
String namespace = regName.getNamespace();
String path = regName.getPath();
- Path fileLocation = dataDir.resolve(Path.of("data", CompactMachines.MOD_ID));
+ Path fileLocation = dataDir.resolve(Path.of("data", Constants.MOD_ID));
for (String p : pathParts)
fileLocation = fileLocation.resolve(p);
@@ -52,7 +53,7 @@ static BiConsumer makeCustomWriter(Gson gson, @Nonnull
String namespace = regName.getNamespace();
String path = regName.getPath();
- Path fileLocation = dataDir.resolve(Path.of("data", CompactMachines.MOD_ID));
+ Path fileLocation = dataDir.resolve(Path.of("data", Constants.MOD_ID));
for (String p : pathParts)
fileLocation = fileLocation.resolve(p);
diff --git a/forge-datagen/src/main/java/dev/compactmods/machines/datagen/DataGeneration.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/DataGeneration.java
new file mode 100644
index 00000000..a95cb9e5
--- /dev/null
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/DataGeneration.java
@@ -0,0 +1,46 @@
+package dev.compactmods.machines.datagen;
+
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.datagen.lang.EnglishLangGenerator;
+import dev.compactmods.machines.datagen.lang.RussianLangGenerator;
+import dev.compactmods.machines.datagen.room.RoomTemplates;
+import dev.compactmods.machines.datagen.tags.BlockTagGenerator;
+import dev.compactmods.machines.datagen.tags.ItemTagGenerator;
+import dev.compactmods.machines.datagen.tags.PointOfInterestTagGenerator;
+import net.minecraftforge.data.event.GatherDataEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.common.Mod;
+
+@Mod.EventBusSubscriber(modid = Constants.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
+public class DataGeneration {
+
+ @SubscribeEvent
+ public static void gatherData(GatherDataEvent event) {
+ final var helper = event.getExistingFileHelper();
+ final var generator = event.getGenerator();
+
+ // Server
+ boolean server = event.includeServer();
+ generator.addProvider(server, new LevelBiomeGenerator(generator));
+ generator.addProvider(server, new BlockLootGenerator(generator));
+ generator.addProvider(server, new RecipeGenerator(generator));
+ generator.addProvider(server, new AdvancementGenerator(generator));
+
+ final var blocks = new BlockTagGenerator(generator, helper);
+ generator.addProvider(server, blocks);
+ generator.addProvider(server, new ItemTagGenerator(generator, blocks, helper));
+
+ generator.addProvider(server, new PointOfInterestTagGenerator(generator, helper));
+
+ RoomTemplates.make(event);
+
+ // Client
+ boolean client = event.includeClient();
+ generator.addProvider(client, new StateGenerator(generator, helper));
+ generator.addProvider(client, new TunnelWallStateGenerator(generator, helper));
+ generator.addProvider(client, new ItemModelGenerator(generator, helper));
+
+ generator.addProvider(client, new EnglishLangGenerator(generator));
+ generator.addProvider(client, new RussianLangGenerator(generator));
+ }
+}
diff --git a/src/datagen/java/dev/compactmods/machines/datagen/DimensionTypeBuilder.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/DimensionTypeBuilder.java
similarity index 100%
rename from src/datagen/java/dev/compactmods/machines/datagen/DimensionTypeBuilder.java
rename to forge-datagen/src/main/java/dev/compactmods/machines/datagen/DimensionTypeBuilder.java
diff --git a/src/datagen/java/dev/compactmods/machines/datagen/ItemModelGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/ItemModelGenerator.java
similarity index 63%
rename from src/datagen/java/dev/compactmods/machines/datagen/ItemModelGenerator.java
rename to forge-datagen/src/main/java/dev/compactmods/machines/datagen/ItemModelGenerator.java
index 85b1caf5..2c9dee26 100644
--- a/src/datagen/java/dev/compactmods/machines/datagen/ItemModelGenerator.java
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/ItemModelGenerator.java
@@ -1,8 +1,9 @@
package dev.compactmods.machines.datagen;
-import dev.compactmods.machines.CompactMachines;
+import dev.compactmods.machines.api.core.Constants;
import dev.compactmods.machines.api.room.RoomSize;
-import dev.compactmods.machines.upgrade.MachineRoomUpgrades;
+import dev.compactmods.machines.forge.machine.Machines;
+import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades;
import net.minecraft.data.DataGenerator;
import net.minecraftforge.client.model.generators.ItemModelProvider;
import net.minecraftforge.common.data.ExistingFileHelper;
@@ -10,7 +11,7 @@
public class ItemModelGenerator extends ItemModelProvider {
public ItemModelGenerator(DataGenerator generator, ExistingFileHelper existingFileHelper) {
- super(generator, CompactMachines.MOD_ID, existingFileHelper);
+ super(generator, Constants.MOD_ID, existingFileHelper);
}
@Override
@@ -18,6 +19,9 @@ protected void registerModels() {
for (var size : RoomSize.values())
machine(size.getSerializedName());
+ withExistingParent(Machines.BOUND_MACHINE_BLOCK_ITEM.getId().getPath(), modLoc("block/machine/machine"));
+ withExistingParent(Machines.UNBOUND_MACHINE_BLOCK_ITEM.getId().getPath(), modLoc("block/machine/machine"));
+
withExistingParent("solid_wall", modLoc("block/wall"));
withExistingParent("wall", modLoc("block/wall"));
@@ -27,8 +31,10 @@ protected void registerModels() {
withExistingParent("tunnel", mcLoc("item/generated"))
.texture("layer0", modLoc("item/tunnel"));
- withExistingParent(MachineRoomUpgrades.CHUNKLOADER.getId().toString(), mcLoc("item/generated"))
+ withExistingParent(MachineRoomUpgrades.ROOM_UPGRADE.getId().toString(), mcLoc("item/generated"))
.texture("layer0", modLoc("upgrades/chunkloader"));
+
+ withExistingParent(MachineRoomUpgrades.WORKBENCH_ITEM.getId().getPath(), modLoc("block/workbench"));
}
private void machine(String size) {
diff --git a/src/datagen/java/dev/compactmods/machines/datagen/LevelBiomeGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/LevelBiomeGenerator.java
similarity index 84%
rename from src/datagen/java/dev/compactmods/machines/datagen/LevelBiomeGenerator.java
rename to forge-datagen/src/main/java/dev/compactmods/machines/datagen/LevelBiomeGenerator.java
index c8f454d0..86256337 100644
--- a/src/datagen/java/dev/compactmods/machines/datagen/LevelBiomeGenerator.java
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/LevelBiomeGenerator.java
@@ -7,8 +7,10 @@
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.serialization.JsonOps;
-import dev.compactmods.machines.CompactMachines;
-import dev.compactmods.machines.dimension.Dimension;
+import dev.compactmods.machines.forge.CompactMachines;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.dimension.CompactDimension;
+import dev.compactmods.machines.forge.dimension.Dimension;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
@@ -36,8 +38,7 @@ public class LevelBiomeGenerator implements DataProvider {
private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create();
private final DataGenerator generator;
- private final ResourceLocation COMPACT_BIOME = new ResourceLocation(CompactMachines.MOD_ID, "machine");
- private final ResourceLocation COMPACT_LEVEL = new ResourceLocation(CompactMachines.MOD_ID, "compact_world");
+ private final ResourceLocation COMPACT_BIOME = new ResourceLocation(Constants.MOD_ID, "machine");
LevelBiomeGenerator(DataGenerator generator) {
this.generator = generator;
@@ -65,7 +66,11 @@ public void run(@Nonnull CachedOutput cache) {
private JsonElement writeFlatDimension(LevelStem dimension) {
JsonObject d = new JsonObject();
- d.addProperty("type", COMPACT_LEVEL.toString());
+ final var regAccess = RegistryAccess.builtinCopy();
+ final var dimTypes = regAccess.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY);
+
+ d.add("type", ResourceLocation.CODEC.encodeStart(JsonOps.INSTANCE, CompactDimension.LEVEL_KEY.location())
+ .getOrThrow(false, CompactMachines.LOGGER::fatal));
var gen = ChunkGenerator.CODEC.encodeStart(JsonOps.INSTANCE, dimension.generator())
.getOrThrow(false, CompactMachines.LOGGER::error)
@@ -93,11 +98,11 @@ private void writeDimensions(HashMap biomes, HashMap consumer) {
@@ -110,7 +115,7 @@ private void writeDimensionTypes(BiConsumer con
.heightBounds(0, 256)
.build();
- consumer.accept(dim, COMPACT_LEVEL);
+ consumer.accept(dim, CompactDimension.LEVEL_KEY.location());
}
private void writeBiomes(BiConsumer biomeWriter) {
@@ -140,6 +145,6 @@ private void writeBiomes(BiConsumer biomeWriter) {
@Override
public String getName() {
- return CompactMachines.MOD_ID + ":levelgen";
+ return Constants.MOD_ID + ":levelgen";
}
}
diff --git a/forge-datagen/src/main/java/dev/compactmods/machines/datagen/RecipeGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/RecipeGenerator.java
new file mode 100644
index 00000000..c24ca823
--- /dev/null
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/RecipeGenerator.java
@@ -0,0 +1,134 @@
+package dev.compactmods.machines.datagen;
+
+import com.google.gson.JsonObject;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.machine.MachineEntityNbt;
+import dev.compactmods.machines.api.machine.MachineIds;
+import dev.compactmods.machines.api.machine.MachineNbt;
+import dev.compactmods.machines.api.recipe.ShapedWithNbtRecipeBuilder;
+import dev.compactmods.machines.api.room.RoomTemplate;
+import dev.compactmods.machines.api.tunnels.recipe.TunnelRecipeBuilder;
+import dev.compactmods.machines.machine.LegacySizedTemplates;
+import dev.compactmods.machines.forge.machine.Machines;
+import dev.compactmods.machines.forge.shrinking.Shrinking;
+import dev.compactmods.machines.forgebuiltin.tunnel.BuiltInTunnels;
+import dev.compactmods.machines.forge.wall.Walls;
+import net.minecraft.data.DataGenerator;
+import net.minecraft.data.recipes.FinishedRecipe;
+import net.minecraft.data.recipes.RecipeProvider;
+import net.minecraft.data.recipes.ShapedRecipeBuilder;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.tags.TagKey;
+import net.minecraft.util.FastColor;
+import net.minecraft.world.item.Item;
+import net.minecraft.world.item.Items;
+import net.minecraft.world.item.crafting.Ingredient;
+import net.minecraftforge.common.Tags;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.function.Consumer;
+
+public class RecipeGenerator extends RecipeProvider {
+ public RecipeGenerator(DataGenerator generatorIn) {
+ super(generatorIn);
+ }
+
+ @Override
+ protected void buildCraftingRecipes(@NotNull Consumer consumer) {
+ ShapedRecipeBuilder.shaped(Walls.ITEM_BREAKABLE_WALL.get(), 8)
+ .pattern("DDD")
+ .pattern("D D")
+ .pattern("DDD")
+ .define('D', Items.POLISHED_DEEPSLATE)
+ .unlockedBy("picked_up_deepslate", has(Tags.Items.COBBLESTONE_DEEPSLATE))
+ .save(consumer);
+
+ ShapedRecipeBuilder.shaped(Shrinking.PERSONAL_SHRINKING_DEVICE.get())
+ .pattern(" P ")
+ .pattern("EBE")
+ .pattern(" I ")
+ .define('P', Tags.Items.GLASS_PANES)
+ .define('E', Items.ENDER_EYE)
+ .define('B', Items.BOOK)
+ .define('I', Tags.Items.INGOTS_IRON)
+ .unlockedBy("picked_up_ender_eye", has(Items.ENDER_EYE))
+ .save(consumer);
+
+ TunnelRecipeBuilder.tunnel(BuiltInTunnels.ITEM_TUNNEL_DEF.getId(), 2)
+ .requires(Ingredient.of(Tags.Items.CHESTS))
+ .requires(Items.ENDER_PEARL)
+ .requires(Items.REDSTONE)
+ .requires(Items.OBSERVER)
+ .unlockedBy("observer", has(Items.OBSERVER))
+ .save(consumer);
+
+ TunnelRecipeBuilder.tunnel(BuiltInTunnels.FLUID_TUNNEL_DEF.getId(), 2)
+ .requires(Items.BUCKET)
+ .requires(Items.ENDER_PEARL)
+ .requires(Items.REDSTONE)
+ .requires(Items.OBSERVER)
+ .unlockedBy("observer", has(Items.OBSERVER))
+ .save(consumer);
+
+ TunnelRecipeBuilder.tunnel(BuiltInTunnels.FORGE_ENERGY.getId(), 2)
+ .requires(Items.GLOWSTONE_DUST)
+ .requires(Items.ENDER_PEARL)
+ .requires(Items.REDSTONE)
+ .requires(Items.OBSERVER)
+ .unlockedBy("observer", has(Items.OBSERVER))
+ .save(consumer);
+
+ addMachineRecipes(consumer);
+ }
+
+ @SuppressWarnings("removal")
+ private void addMachineRecipes(Consumer consumer) {
+ registerMachineRecipe(consumer, LegacySizedTemplates.EMPTY_TINY, Tags.Items.STORAGE_BLOCKS_COPPER);
+ registerMachineRecipe(consumer, LegacySizedTemplates.EMPTY_SMALL, Tags.Items.STORAGE_BLOCKS_IRON);
+ registerMachineRecipe(consumer, LegacySizedTemplates.EMPTY_NORMAL, Tags.Items.STORAGE_BLOCKS_GOLD);
+ registerMachineRecipe(consumer, LegacySizedTemplates.EMPTY_LARGE, Tags.Items.STORAGE_BLOCKS_DIAMOND);
+ registerMachineRecipe(consumer, LegacySizedTemplates.EMPTY_GIANT, Tags.Items.OBSIDIAN);
+ registerMachineRecipe(consumer, LegacySizedTemplates.EMPTY_COLOSSAL, Tags.Items.INGOTS_NETHERITE);
+
+ registerMachineRecipe(consumer, new ResourceLocation(Constants.MOD_ID, "absurd"),
+ new RoomTemplate(25, FastColor.ARGB32.color(255, 0, 166, 88)),
+ Tags.Items.NETHER_STARS);
+ }
+
+ @SuppressWarnings("removal")
+ @Deprecated(forRemoval = true, since = "5.2.0")
+ protected void registerMachineRecipe(Consumer consumer, LegacySizedTemplates template, TagKey
- center) {
+ registerMachineRecipe(consumer, template.id(), template.template(), center);
+ }
+
+ protected void registerMachineRecipe(Consumer consumer, ResourceLocation temId, RoomTemplate tem, TagKey
- center) {
+ Item wall = Walls.ITEM_BREAKABLE_WALL.get();
+ ShapedWithNbtRecipeBuilder recipe = ShapedWithNbtRecipeBuilder.shaped(Machines.UNBOUND_MACHINE_BLOCK_ITEM.get())
+ .pattern("WWW");
+
+ if (center != null)
+ recipe.pattern("WCW");
+ else
+ recipe.pattern("W W");
+
+ recipe.pattern("WWW").define('W', wall);
+ if (center != null)
+ recipe.define('C', center);
+
+ recipe.unlockedBy("has_recipe", has(wall));
+ recipe.addWriter(r -> {
+ final var nbt = new JsonObject();
+ nbt.addProperty(MachineNbt.NBT_TEMPLATE_ID, temId.toString());
+
+ final var blockTag = new JsonObject();
+ blockTag.addProperty("id", MachineIds.UNBOUND_MACHINE_ITEM_ID.toString());
+ blockTag.addProperty(MachineEntityNbt.NBT_TEMPLATE_ID, temId.toString());
+
+ nbt.add("BlockEntityTag", blockTag);
+ r.add("nbt", nbt);
+ });
+
+ final var recipeId = new ResourceLocation(Constants.MOD_ID, "new_machine_" + temId.getPath());
+ recipe.save(consumer, recipeId);
+ }
+}
diff --git a/forge-datagen/src/main/java/dev/compactmods/machines/datagen/StateGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/StateGenerator.java
new file mode 100644
index 00000000..0d3503f3
--- /dev/null
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/StateGenerator.java
@@ -0,0 +1,78 @@
+package dev.compactmods.machines.datagen;
+
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.room.RoomSize;
+import dev.compactmods.machines.forge.machine.Machines;
+import dev.compactmods.machines.forge.machine.block.LegacySizedCompactMachineBlock;
+import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades;
+import dev.compactmods.machines.forge.wall.Walls;
+import net.minecraft.data.DataGenerator;
+import net.minecraftforge.client.model.generators.BlockModelProvider;
+import net.minecraftforge.client.model.generators.BlockStateProvider;
+import net.minecraftforge.client.model.generators.ConfiguredModel;
+import net.minecraftforge.common.data.ExistingFileHelper;
+
+public class StateGenerator extends BlockStateProvider {
+ public StateGenerator(DataGenerator gen, ExistingFileHelper exFileHelper) {
+ super(gen, Constants.MOD_ID, exFileHelper);
+ }
+
+ @Override
+ @SuppressWarnings("removal")
+ protected void registerStatesAndModels() {
+ // Wall block model
+ BlockModelProvider models = models();
+
+ var wall = models.cubeAll("block/wall", modLoc("block/wall"));
+ simpleBlock(Walls.BLOCK_SOLID_WALL.get(), wall);
+ simpleBlock(Walls.BLOCK_BREAKABLE_WALL.get(), wall);
+
+ // New machine block
+ final var m = models
+ .withExistingParent("block/machine/machine", mcLoc("block/block"))
+ .texture("border", modLoc("block/machine/border"))
+ .texture("tint", modLoc("block/machine/tint"))
+ .texture("overlay", modLoc("block/machine/overlay"))
+ .renderType(mcLoc("cutout"))
+ .element()
+ .allFaces((dir, face) -> face.texture("#border")
+ .uvs(0, 0, 16, 16)
+ .cullface(dir)
+ .end())
+ .end()
+ .element()
+ .allFaces((dir, face) -> face.texture("#tint")
+ .emissivity(2)
+ .uvs(0, 0, 16, 16)
+ .cullface(dir)
+ .tintindex(0)
+ .end())
+ .end()
+ .element()
+ .allFaces((dir, face) -> face.texture("#overlay")
+ .uvs(0, 0, 16, 16)
+ .cullface(dir)
+ .tintindex(1)
+ .end())
+ .end();
+
+ simpleBlock(Machines.UNBOUND_MACHINE_BLOCK.get(), ConfiguredModel.builder()
+ .modelFile(m)
+ .build());
+
+ simpleBlock(Machines.MACHINE_BLOCK.get(), ConfiguredModel.builder()
+ .modelFile(m)
+ .build());
+
+ // Legacy-sized machines
+ for (RoomSize size : RoomSize.values()) {
+ String sizeName = size.getName();
+ simpleBlock(LegacySizedCompactMachineBlock.getBySize(size), ConfiguredModel.builder()
+ .modelFile(models.cubeAll("block/machine/machine_" + sizeName, modLoc("block/machine/machine_" + sizeName)))
+ .build());
+ }
+
+ this.simpleBlock(MachineRoomUpgrades.WORKBENCH_BLOCK.get(), models()
+ .cubeTop("block/workbench", modLoc("block/workbench/top"), modLoc("block/workbench/sides")));
+ }
+}
diff --git a/src/datagen/java/dev/compactmods/machines/datagen/TunnelWallStateGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/TunnelWallStateGenerator.java
similarity index 81%
rename from src/datagen/java/dev/compactmods/machines/datagen/TunnelWallStateGenerator.java
rename to forge-datagen/src/main/java/dev/compactmods/machines/datagen/TunnelWallStateGenerator.java
index 5363a79f..e9d634be 100644
--- a/src/datagen/java/dev/compactmods/machines/datagen/TunnelWallStateGenerator.java
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/TunnelWallStateGenerator.java
@@ -1,9 +1,9 @@
package dev.compactmods.machines.datagen;
-import dev.compactmods.machines.CompactMachines;
-import dev.compactmods.machines.tunnel.TunnelWallBlock;
-import dev.compactmods.machines.tunnel.Tunnels;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.forge.tunnel.TunnelWallBlock;
+import dev.compactmods.machines.forge.tunnel.Tunnels;
import net.minecraft.core.Direction;
import net.minecraft.data.DataGenerator;
import net.minecraft.resources.ResourceLocation;
@@ -16,7 +16,7 @@
public class TunnelWallStateGenerator extends BlockStateProvider {
public TunnelWallStateGenerator(DataGenerator gen, ExistingFileHelper exFileHelper) {
- super(gen, CompactMachines.MOD_ID, exFileHelper);
+ super(gen, Constants.MOD_ID, exFileHelper);
}
@Override
@@ -28,9 +28,10 @@ protected void registerStatesAndModels() {
for (Direction dir : Direction.values()) {
String typedTunnelDirectional = "tunnels/" + dir.getSerializedName();
- models()
+ final var dirModel = models()
.withExistingParent(typedTunnelDirectional, modLoc("tunnels/base"))
- .texture("wall", modLoc("block/" + typedTunnelDirectional));
+ .texture("wall", modLoc("block/" + typedTunnelDirectional))
+ .renderType(mcLoc("cutout")); // NamedRenderTypeManager
/*
@@ -39,14 +40,14 @@ protected void registerStatesAndModels() {
int y = dir.getAxis().isVertical() ? 0 : (((int) dir.getHorizontalAngle()) + 180) % 360;
*/
+ var dirModelConfigured = ConfiguredModel.builder()
+ .modelFile(dirModel)
+ .build();
+
getVariantBuilder(block)
.partialState()
- .with(TunnelWallBlock.CONNECTED_SIDE, dir)
- .setModels(
- ConfiguredModel.builder()
- .modelFile(models().getExistingFile(modLoc(typedTunnelDirectional)))
- .build()
- );
+ .with(TunnelWallBlock.CONNECTED_SIDE, dir)
+ .setModels(dirModelConfigured);
}
}
diff --git a/forge-datagen/src/main/java/dev/compactmods/machines/datagen/VillagerTrades.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/VillagerTrades.java
new file mode 100644
index 00000000..90b4da3a
--- /dev/null
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/VillagerTrades.java
@@ -0,0 +1,4 @@
+package dev.compactmods.machines.datagen;
+
+public class VillagerTrades {
+}
diff --git a/src/datagen/java/dev/compactmods/machines/datagen/lang/BaseLangGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/lang/BaseLangGenerator.java
similarity index 78%
rename from src/datagen/java/dev/compactmods/machines/datagen/lang/BaseLangGenerator.java
rename to forge-datagen/src/main/java/dev/compactmods/machines/datagen/lang/BaseLangGenerator.java
index 58548616..39ef16b3 100644
--- a/src/datagen/java/dev/compactmods/machines/datagen/lang/BaseLangGenerator.java
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/lang/BaseLangGenerator.java
@@ -1,18 +1,21 @@
package dev.compactmods.machines.datagen.lang;
-import dev.compactmods.machines.CompactMachines;
+import dev.compactmods.machines.datagen.AdvancementLangBuilder;
+import dev.compactmods.machines.forge.machine.block.LegacySizedCompactMachineBlock;
+import dev.compactmods.machines.forge.tunnel.Tunnels;
+import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades;
import dev.compactmods.machines.api.core.Advancements;
-import dev.compactmods.machines.api.room.upgrade.RoomUpgrade;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.room.RoomSize;
+import dev.compactmods.machines.api.upgrade.RoomUpgrade;
import dev.compactmods.machines.api.tunnels.TunnelDefinition;
-import dev.compactmods.machines.tunnel.Tunnels;
-import dev.compactmods.machines.datagen.AdvancementLangBuilder;
import dev.compactmods.machines.i18n.TranslationUtil;
-import dev.compactmods.machines.machine.CompactMachineBlock;
-import dev.compactmods.machines.api.room.RoomSize;
+import net.minecraft.Util;
import net.minecraft.core.Direction;
import net.minecraft.data.DataGenerator;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.data.LanguageProvider;
+import net.minecraftforge.registries.IForgeRegistry;
import java.util.function.Supplier;
@@ -22,9 +25,12 @@ public abstract class BaseLangGenerator extends LanguageProvider {
private final String locale;
+ private final IForgeRegistry ACTIONS_REG;
+
public BaseLangGenerator(DataGenerator gen, String locale) {
- super(gen, CompactMachines.MOD_ID, locale);
+ super(gen, Constants.MOD_ID, locale);
this.locale = locale;
+ ACTIONS_REG = MachineRoomUpgrades.REGISTRY.get();
}
protected abstract String getSizeTranslation(RoomSize size);
@@ -39,15 +45,17 @@ protected String getMachineTranslation() {
}
@Override
+ @SuppressWarnings("removal")
protected void addTranslations() {
// Machine Block names
+ final var machineTranslation = getMachineTranslation();
for(var size : RoomSize.values()) {
- add(CompactMachineBlock.getBySize(size), String.format("%s (%s)", getMachineTranslation(), getSizeTranslation(size)));
+ add(LegacySizedCompactMachineBlock.getBySize(size), "%s (%s)".formatted(machineTranslation, getSizeTranslation(size)));
}
// Direction Names
for (var dir : Direction.values()) {
- add(CompactMachines.MOD_ID + ".direction." + dir.getSerializedName(), getDirectionTranslation(dir));
+ add(Constants.MOD_ID + ".direction." + dir.getSerializedName(), getDirectionTranslation(dir));
}
}
@@ -59,10 +67,11 @@ protected void addTunnel(Supplier tunnel, String name) {
add(TranslationUtil.tunnelId(Tunnels.getRegistryId(tunnel.get())), name);
}
- void addUpgradeItem(Supplier upgrade, String translation) {
+ void add(Supplier upgrade, String translation) {
final var u = upgrade.get();
+ final var id = ACTIONS_REG.getKey(u);
if(u != null)
- add(u.getTranslationKey(), translation);
+ add(Util.makeDescriptionId("upgrade.action", id), translation);
}
protected void addAdvancementTranslations() {
diff --git a/src/datagen/java/dev/compactmods/machines/datagen/lang/EnglishLangGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/lang/EnglishLangGenerator.java
similarity index 70%
rename from src/datagen/java/dev/compactmods/machines/datagen/lang/EnglishLangGenerator.java
rename to forge-datagen/src/main/java/dev/compactmods/machines/datagen/lang/EnglishLangGenerator.java
index 518f7d4d..287e5eed 100644
--- a/src/datagen/java/dev/compactmods/machines/datagen/lang/EnglishLangGenerator.java
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/lang/EnglishLangGenerator.java
@@ -1,17 +1,21 @@
package dev.compactmods.machines.datagen.lang;
-import dev.compactmods.machines.CompactMachines;
+import dev.compactmods.machines.forge.client.RoomExitKeyMapping;
+import dev.compactmods.machines.forge.dimension.VoidAirBlock;
+import dev.compactmods.machines.forge.tunnel.Tunnels;
+import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades;
+import dev.compactmods.machines.forge.wall.Walls;
import dev.compactmods.machines.api.core.CMCommands;
+import dev.compactmods.machines.api.core.Constants;
import dev.compactmods.machines.api.core.Messages;
import dev.compactmods.machines.api.core.Tooltips;
-import dev.compactmods.machines.api.room.upgrade.RoomUpgrade;
-import dev.compactmods.machines.dimension.VoidAirBlock;
-import dev.compactmods.machines.shrinking.Shrinking;
-import dev.compactmods.machines.tunnel.Tunnels;
import dev.compactmods.machines.api.room.RoomSize;
-import dev.compactmods.machines.upgrade.MachineRoomUpgrades;
-import dev.compactmods.machines.wall.Walls;
+import dev.compactmods.machines.forge.shrinking.Shrinking;
+import dev.compactmods.machines.forgebuiltin.tunnel.BuiltInTunnels;
+import dev.compactmods.machines.forgebuiltin.upgrade.BuiltInUpgrades;
+import net.minecraft.Util;
import net.minecraft.data.DataGenerator;
+import net.minecraft.resources.ResourceLocation;
import static org.apache.commons.lang3.StringUtils.capitalize;
@@ -24,6 +28,15 @@ public EnglishLangGenerator(DataGenerator gen) {
protected void addTranslations() {
super.addTranslations();
+ final var machineTranslation = getMachineTranslation();
+ add("machine.compactmachines.tiny", "%s (%s)".formatted(machineTranslation, "Tiny"));
+ add("machine.compactmachines.small", "%s (%s)".formatted(machineTranslation, "Small"));
+ add("machine.compactmachines.normal", "%s (%s)".formatted(machineTranslation, "Normal"));
+ add("machine.compactmachines.large", "%s (%s)".formatted(machineTranslation, "Large"));
+ add("machine.compactmachines.giant", "%s (%s)".formatted(machineTranslation, "Giant"));
+ add("machine.compactmachines.colossal", "%s (%s)".formatted(machineTranslation, "Colossal"));
+ add("machine.compactmachines.absurd", "%s (%s)".formatted(machineTranslation, "Absurd"));
+
addMessage(Messages.CANNOT_ENTER_MACHINE, "You fumble with the shrinking device, to no avail. It refuses to work.");
addMessage(Messages.NO_MACHINE_DATA, "No machine data loaded; report this.");
addMessage(Messages.ROOM_SPAWNPOINT_SET, "New spawn point set.");
@@ -49,30 +62,30 @@ protected void addTranslations() {
addCommand(CMCommands.LEVEL_REGISTERED, "Compact Machine dimension found.");
addCommand(CMCommands.LEVEL_NOT_FOUND, "Compact Machine dimension could not be found.");
addCommand(CMCommands.ROOM_NOT_FOUND, "Room [%s] could not be found.");
- addCommand(CMCommands.SPAWN_CHANGED_SUCCESSFULLY, "Spawnpoint for room [%s] was changed successfully.");
+ addCommand(CMCommands.SPAWN_CHANGED_SUCCESSFULLY, "Spawn point for room [%s] was changed successfully.");
addAdvancementTranslations();
addBlock(Walls.BLOCK_BREAKABLE_WALL, "Compact Machine Wall");
addBlock(Walls.BLOCK_SOLID_WALL, "Solid Compact Machine Wall");
addBlock(Tunnels.BLOCK_TUNNEL_WALL, "Solid Compact Machine Wall (with Tunnel)");
+ add(Util.makeDescriptionId("block", new ResourceLocation(Constants.MOD_ID, "bound_machine_fallback")), "Bound Compact Machine");
add(Shrinking.PERSONAL_SHRINKING_DEVICE.get(), "Personal Shrinking Device");
- add(CompactMachines.MOD_ID + ".direction.side", "Side: %s");
- add(CompactMachines.MOD_ID + ".connected_block", "Connected: %s");
-
- add(RoomUpgrade.UNNAMED_TRANS_KEY, "Unnamed Room Upgrade");
+ add(Constants.MOD_ID + ".direction.side", "Side: %s");
+ add(Constants.MOD_ID + ".connected_block", "Connected: %s");
- addTunnel(Tunnels.ITEM_TUNNEL_DEF, "Item Tunnel");
- addTunnel(Tunnels.FLUID_TUNNEL_DEF, "Fluid Tunnel");
- addTunnel(Tunnels.FORGE_ENERGY, "Energy Tunnel");
+ addTunnel(BuiltInTunnels.ITEM_TUNNEL_DEF, "Item Tunnel");
+ addTunnel(BuiltInTunnels.FLUID_TUNNEL_DEF, "Fluid Tunnel");
+ addTunnel(BuiltInTunnels.FORGE_ENERGY, "Energy Tunnel");
// addTunnel(Tunnels.REDSTONE_IN_DEF.get(), "Redstone Tunnel (In)");
// addTunnel(Tunnels.REDSTONE_OUT_DEF.get(), "Redstone Tunnel (Out)");
addTooltip(Tooltips.Details.PERSONAL_SHRINKING_DEVICE, "Used as in-game documentation and to enter Compact Machines.");
addTooltip(Tooltips.Details.SOLID_WALL, "Warning! Unbreakable for non-creative players!");
+ addTooltip(Tooltips.CRAFT_TO_UPGRADE, "Craft to upgrade to a new machine.");
addTooltip(Tooltips.HINT_HOLD_SHIFT, "Hold shift for details.");
addTooltip(Tooltips.UNKNOWN_PLAYER_NAME, "Unknown Player");
@@ -86,8 +99,10 @@ protected void addTranslations() {
addTooltip(Tooltips.ROOM_NAME, "Bound to room: %s");
+ addTooltip(Tooltips.NOT_YET_IMPLEMENTED, "Not Yet Implemented");
+
//region Upgrades
- addUpgradeItem(MachineRoomUpgrades.CHUNKLOAD, "Chunkloader Upgrade");
+ add(BuiltInUpgrades.CHUNKLOAD, "Chunkloader Upgrade");
addMessage(Messages.ALREADY_HAS_UPGRADE, "Upgrade has already been applied to room.");
addMessage(Messages.UPGRADE_NOT_PRESENT, "Upgrade is not applied to the room.");
@@ -107,9 +122,9 @@ protected void addTranslations() {
addMessage(Messages.UNKNOWN_ROOM_CHUNK, "Unknown room at %s; please verify it exists.");
- add("itemGroup." + CompactMachines.MOD_ID, "Compact Machines");
+ add("itemGroup." + Constants.MOD_ID, "Compact Machines");
- add("biome." + CompactMachines.MOD_ID + ".machine", "Compact Machine");
+ add("biome." + Constants.MOD_ID + ".machine", "Compact Machine");
add("compactmachines.psd.pages.machines.title", "Compact Machines");
add("compactmachines.psd.pages.machines", "Compact Machines are the core mechanic of this mod. They allow you to build large " +
@@ -121,6 +136,14 @@ protected void addTranslations() {
add("jei.compactmachines.shrinking_device", "Use the Personal Shrinking Device (PSD) on a machine in order to enter a compact space. " +
"You can also right click it in the overworld for more info.");
add("death.attack." + VoidAirBlock.DAMAGE_SOURCE.msgId, "%1$s failed to enter the void");
+
+ add("curios.identifier.psd", "Personal Shrinking Device");
+
+ add(MachineRoomUpgrades.WORKBENCH_BLOCK.get(), "Workbench");
+ add("entity.minecraft.villager.compactmachines.tinkerer", "Tinkerer");
+
+ add(RoomExitKeyMapping.CATEGORY, "Compact Machines");
+ add(RoomExitKeyMapping.NAME, "Quick-Exit Compact Machine");
}
@Override
diff --git a/forge-datagen/src/main/java/dev/compactmods/machines/datagen/lang/GermanLangGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/lang/GermanLangGenerator.java
new file mode 100644
index 00000000..92624cf9
--- /dev/null
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/lang/GermanLangGenerator.java
@@ -0,0 +1,153 @@
+package dev.compactmods.machines.datagen.lang;
+
+import dev.compactmods.machines.forge.client.RoomExitKeyMapping;
+import dev.compactmods.machines.forge.dimension.VoidAirBlock;
+import dev.compactmods.machines.forge.tunnel.Tunnels;
+import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades;
+import dev.compactmods.machines.forge.wall.Walls;
+import dev.compactmods.machines.api.core.CMCommands;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.core.Messages;
+import dev.compactmods.machines.api.core.Tooltips;
+import dev.compactmods.machines.api.room.RoomSize;
+import dev.compactmods.machines.forge.shrinking.Shrinking;
+import dev.compactmods.machines.forgebuiltin.tunnel.BuiltInTunnels;
+import dev.compactmods.machines.forgebuiltin.upgrade.BuiltInUpgrades;
+import net.minecraft.Util;
+import net.minecraft.data.DataGenerator;
+import net.minecraft.resources.ResourceLocation;
+
+import static org.apache.commons.lang3.StringUtils.capitalize;
+
+public class EnglishLangGenerator extends BaseLangGenerator {
+ public EnglishLangGenerator(DataGenerator gen) {
+ super(gen, "de_de");
+ }
+
+ @Override
+ protected void addTranslations() {
+ super.addTranslations();
+
+ final var machineTranslation = getMachineTranslation();
+ add("machine.compactmachines.tiny", "%s (%s)".formatted(machineTranslation, "Winzig"));
+ add("machine.compactmachines.small", "%s (%s)".formatted(machineTranslation, "Klein"));
+ add("machine.compactmachines.normal", "%s (%s)".formatted(machineTranslation, "Normal"));
+ add("machine.compactmachines.large", "%s (%s)".formatted(machineTranslation, "Groß"));
+ add("machine.compactmachines.giant", "%s (%s)".formatted(machineTranslation, "Gigantisch"));
+ add("machine.compactmachines.colossal", "%s (%s)".formatted(machineTranslation, "Kolossal"));
+ add("machine.compactmachines.absurd", "%s (%s)".formatted(machineTranslation, "Absurd"));
+
+ addMessage(Messages.CANNOT_ENTER_MACHINE, "Sie fummeln vergeblich am Schrumpfgerät herum. Es weigert sich zu arbeiten.");
+ addMessage(Messages.NO_MACHINE_DATA, "Keine Maschinendaten geladen; melde dies.");
+ addMessage(Messages.ROOM_SPAWNPOINT_SET, "Neuer Spawnpunkt gesetzt.");
+ addMessage(Messages.HOW_DID_YOU_GET_HERE, "Wie bist du hier her gekommen?!");
+ addMessage(Messages.NEW_MACHINE, "Neue Maschine");
+ addMessage(Messages.TELEPORT_OUT_OF_BOUNDS, "Eine jenseitige Kraft verhindert Ihre Teleportation.");
+ addMessage(Messages.NO_TUNNEL_SIDE, "Für diesen Tunneltyp sind keine Seiten verfügbar.");
+
+ addMessage(Messages.NOT_ROOM_OWNER, "Sie sind nicht der Zimmereigentümer; Nur %s darf Änderungen vornehmen.");
+
+ // 1 = Display Name, 2 = Chunk, 3 = Size
+ addMessage(Messages.PLAYER_ROOM_INFO, "Spieler '%1$s' befindet sich in einem %3$s-Raum bei %2$s.");
+ addMessage(Messages.MACHINE_ROOM_INFO, "Die Maschine bei %1$s ist an einen Raum der Größe %2$s bei %3$s gebunden");
+
+ addMessage(Messages.CANNOT_RENAME_NOT_OWNER, "Nur %s darf diesen Raum umbenennen.");
+
+ addCommand(CMCommands.NOT_IN_COMPACT_DIMENSION, "Dieser Befehl kann nicht außerhalb eines Maschinenraums verwendet werden.");
+ addCommand(CMCommands.FAILED_CMD_FILE_ERROR, "Befehl konnte nicht ausgeführt werden; Es ist ein Dateifehler aufgetreten. Bericht prüfen.");
+ addCommand(CMCommands.MACHINE_NOT_BOUND, "Maschine bei %s ist nicht an einen Raum gebunden.");
+ addCommand(CMCommands.ROOM_REG_COUNT, "Anzahl der registrierten Räume: %s");
+ addCommand(CMCommands.MACHINE_REG_DIM, "[%s]: %s");
+ addCommand(CMCommands.MACHINE_REG_TOTAL, "Insgesamt: %s");
+ addCommand(CMCommands.LEVEL_REGISTERED, "Compact Machine Dimension gefunden.");
+ addCommand(CMCommands.LEVEL_NOT_FOUND, "Compact Machine Dimension konnte nicht gefunden werden.");
+ addCommand(CMCommands.ROOM_NOT_FOUND, "Raum [%s] konnte nicht gefunden werden.");
+ addCommand(CMCommands.SPAWN_CHANGED_SUCCESSFULLY, "Spawnpunkt für Raum [%s] erfolgreich geändert.");
+
+ addAdvancementTranslations();
+
+ addBlock(Walls.BLOCK_BREAKABLE_WALL, "Kompakte Maschinenwand");
+ addBlock(Walls.BLOCK_SOLID_WALL, "Solide kompakte Maschinenwand");
+ addBlock(Tunnels.BLOCK_TUNNEL_WALL, "Solide kompakte Maschinenwand (mit Tunnel)");
+ add(Util.makeDescriptionId("block", new ResourceLocation(Constants.MOD_ID, "bound_machine_fallback")), "Gebundene Kompaktmaschine");
+
+ add(Shrinking.PERSONAL_SHRINKING_DEVICE.get(), "Persönliches Schrumpfgerät");
+
+ add(Constants.MOD_ID + ".direction.side", "Seite: %s");
+ add(Constants.MOD_ID + ".connected_block", "Verbunden: %s");
+
+ addTunnel(BuiltInTunnels.ITEM_TUNNEL_DEF, "Itemtunnel");
+ addTunnel(BuiltInTunnels.FLUID_TUNNEL_DEF, "Flüssigkeitstunnel");
+ addTunnel(BuiltInTunnels.FORGE_ENERGY, "Energietunnel");
+ // addTunnel(Tunnels.REDSTONE_IN_DEF.get(), "Redstone Tunnel (In)");
+ // addTunnel(Tunnels.REDSTONE_OUT_DEF.get(), "Redstone Tunnel (Out)");
+
+ addTooltip(Tooltips.Details.PERSONAL_SHRINKING_DEVICE, "Wird als In-Game-Dokumentation und zum Betreten von Compact Machines verwendet.");
+ addTooltip(Tooltips.Details.SOLID_WALL, "Warnung! Unzerbrechlich für nicht-kreative Spieler!");
+
+ addTooltip(Tooltips.CRAFT_TO_UPGRADE, "Craft, um auf eine neue Maschine aufzurüsten.");
+ addTooltip(Tooltips.HINT_HOLD_SHIFT, "Halten Sie die Umschalttaste gedrückt, um Details anzuzeigen.");
+ addTooltip(Tooltips.UNKNOWN_PLAYER_NAME, "Unbekannter Spieler");
+
+ addTooltip(Tooltips.Machines.ID, "Maschine #%s");
+ addTooltip(Tooltips.Machines.OWNER, "Besitzer: %s");
+ addTooltip(Tooltips.Machines.SIZE, "Interne Größe: %1$sx%1$sx%1$s");
+ addTooltip(Tooltips.Machines.BOUND_TO, "Gebunden zu: %1$s");
+
+ addTooltip(Tooltips.TUNNEL_TYPE, "Typ ID: %1$s");
+ addTooltip(Tooltips.UNKNOWN_TUNNEL_TYPE, "Unbekannter Tunneltyp (%s)");
+
+ addTooltip(Tooltips.ROOM_NAME, "An den Raum gebunden: %s");
+
+ addTooltip(Tooltips.NOT_YET_IMPLEMENTED, "Noch nicht implementiert");
+
+ //region Upgrades
+ add(BuiltInUpgrades.CHUNKLOAD, "Chunkloader-Upgrade");
+
+ addMessage(Messages.ALREADY_HAS_UPGRADE, "Das Upgrade wurde bereits auf den Raum angewendet.");
+ addMessage(Messages.UPGRADE_NOT_PRESENT, "Das Upgrade wurde nicht auf den Raum angewendet.");
+
+ addMessage(Messages.UPGRADE_APPLIED, "Upgrade auf Raum angewendet.");
+ addMessage(Messages.UPGRADE_ADD_FAILED, "Das Upgrade konnte nicht auf den Raum angewendet werden.");
+
+ addMessage(Messages.UPGRADE_REMOVED, "Upgrade aus dem Raum entfernt.");
+ addMessage(Messages.UPGRADE_REM_FAILED, "Die Upgradeentfernung konnte nicht auf den Raum angewendet werden.");
+
+ addTooltip(Tooltips.ROOM_UPGRADE_TYPE, "Typ: %s");
+ addTooltip(Tooltips.TUTORIAL_APPLY_ROOM_UPGRADE, "Auf einem gebundenen Maschinenblock verwenden, um ein Upgrade anzuwenden.");
+ //endregion
+
+ addCommand(CMCommands.CANNOT_GIVE_MACHINE, "Dem Spieler konnte keine neue Maschine gegeben werden.");
+ addCommand(CMCommands.MACHINE_GIVEN, "Ein neues Maschinenelement erstellt und an %s übergeben.");
+
+ addMessage(Messages.UNKNOWN_ROOM_CHUNK, "Unbekannter Raum bei %s; Bitte überprüfen Sie, ob es existiert.");
+
+ add("itemGroup." + Constants.MOD_ID, "Kompakte Maschine");
+
+ add("biome." + Constants.MOD_ID + ".machine", "Compact Machine");
+
+ add("compactmachines.psd.pages.machines.title", "Kompakte Maschinen");
+ add("compactmachines.psd.pages.machines", "Kompakte Maschinen sind die Kernmechanik dieses Mods." +
+ "Sie ermöglichen den Bau großer Räume in einem einzigen Block, der mit der Außenwelt verbunden ist. Es gibt sie in verschiedenen Größen von 3x3x3 bis 13x13x13.\n\n" +
+ "Sie können Tunnel verwenden, um die äußeren Blockflächen mit den Innenwänden zu verbinden und so Gegenstände, Flüssigkeiten usw. zu transportieren.\n\n" +
+ "Sie können eine Kompaktmaschine betreten, indem Sie mit einem persönlichen Schrumpfgerät mit der rechten Maustaste darauf klicken. Bitte verwenden Sie JEI, um nach den Craftingrezepten zu suchen.");
+
+ add("jei.compactmachines.machines", "Die Maschinen erschaffen die Taschen-Dimensionen. Crafte eine Maschine und platziere sie in der Welt. Benutze dann ein persönliches Schrumpfgerät, um hineinzugehen.");
+ add("jei.compactmachines.shrinking_device", "Verwenden Sie das Persönliche Schrumpfgerät (PSD) an einer Maschine, um einen kompakten Raum zu betreten. " +
+ "Sie können auch mit der rechten Maustaste in der Oberwelt darauf klicken, um weitere Informationen zu erhalten.");
+ add("death.attack." + VoidAirBlock.DAMAGE_SOURCE.msgId, "%1$s konnte das Nichts nicht betreten");
+
+ add("curios.identifier.psd", "Persönliches Schrumpfgerät");
+
+ add(MachineRoomUpgrades.WORKBENCH_BLOCK.get(), "Werkbank");
+ add("entity.minecraft.villager.compactmachines.tinkerer", "Bastler");
+
+ add(RoomExitKeyMapping.CATEGORY, "Kompakte Maschine");
+ add(RoomExitKeyMapping.NAME, " Kompakte Maschine");
+ }
+
+ @Override
+ protected String getSizeTranslation(RoomSize size) {
+ return capitalize(size.getSerializedName());
+ }
+}
diff --git a/src/datagen/java/dev/compactmods/machines/datagen/lang/RussianLangGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/lang/RussianLangGenerator.java
similarity index 91%
rename from src/datagen/java/dev/compactmods/machines/datagen/lang/RussianLangGenerator.java
rename to forge-datagen/src/main/java/dev/compactmods/machines/datagen/lang/RussianLangGenerator.java
index 4f6239c6..826a4d66 100644
--- a/src/datagen/java/dev/compactmods/machines/datagen/lang/RussianLangGenerator.java
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/lang/RussianLangGenerator.java
@@ -1,12 +1,12 @@
package dev.compactmods.machines.datagen.lang;
-import dev.compactmods.machines.CompactMachines;
+import dev.compactmods.machines.forge.tunnel.Tunnels;
+import dev.compactmods.machines.forge.wall.Walls;
+import dev.compactmods.machines.api.core.Constants;
import dev.compactmods.machines.api.core.Messages;
import dev.compactmods.machines.api.core.Tooltips;
-import dev.compactmods.machines.shrinking.Shrinking;
-import dev.compactmods.machines.tunnel.Tunnels;
import dev.compactmods.machines.api.room.RoomSize;
-import dev.compactmods.machines.wall.Walls;
+import dev.compactmods.machines.forge.shrinking.Shrinking;
import net.minecraft.core.Direction;
import net.minecraft.data.DataGenerator;
@@ -54,8 +54,8 @@ protected void addTranslations() {
add(Tunnels.BLOCK_TUNNEL_WALL.get(), "Прочная стена компактного механизма (с Туннелем)");
// Basics
- add(CompactMachines.MOD_ID + ".connected_block", "Подключено: %s");
- add(CompactMachines.MOD_ID + ".direction.side", "Сторона: %s");
+ add(Constants.MOD_ID + ".connected_block", "Подключено: %s");
+ add(Constants.MOD_ID + ".direction.side", "Сторона: %s");
// PSD
add(Shrinking.PERSONAL_SHRINKING_DEVICE.get(), "Персональное сжимающее устройство");
@@ -64,7 +64,7 @@ protected void addTranslations() {
add(Tunnels.ITEM_TUNNEL.get(), "Предметный туннель");
// Creative Tabs
- add("itemGroup." + CompactMachines.MOD_ID, "Компактные механизмы");
+ add("itemGroup." + Constants.MOD_ID, "Компактные механизмы");
// PSD Guide Pages
add("compactmachines.psd.pages.machines.title", "Компактные механизмы");
diff --git a/forge-datagen/src/main/java/dev/compactmods/machines/datagen/room/RoomTemplates.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/room/RoomTemplates.java
new file mode 100644
index 00000000..55df9ff3
--- /dev/null
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/room/RoomTemplates.java
@@ -0,0 +1,45 @@
+package dev.compactmods.machines.datagen.room;
+
+import com.mojang.serialization.JsonOps;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.room.RoomTemplate;
+import dev.compactmods.machines.api.room.Rooms;
+import dev.compactmods.machines.machine.LegacySizedTemplates;
+import net.minecraft.core.RegistryAccess;
+import net.minecraft.core.Vec3i;
+import net.minecraft.resources.RegistryOps;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.util.FastColor;
+import net.minecraftforge.common.data.JsonCodecProvider;
+import net.minecraftforge.data.event.GatherDataEvent;
+
+import java.util.HashMap;
+
+public class RoomTemplates {
+
+ @SuppressWarnings("removal")
+ public static void make(GatherDataEvent event) {
+
+ final var templates = new HashMap();
+ templates.put(new ResourceLocation(Constants.MOD_ID, "tiny"), LegacySizedTemplates.EMPTY_TINY.template());
+ templates.put(new ResourceLocation(Constants.MOD_ID, "small"), LegacySizedTemplates.EMPTY_SMALL.template());
+ templates.put(new ResourceLocation(Constants.MOD_ID, "normal"), LegacySizedTemplates.EMPTY_NORMAL.template());
+ templates.put(new ResourceLocation(Constants.MOD_ID, "large"), LegacySizedTemplates.EMPTY_LARGE.template());
+ templates.put(new ResourceLocation(Constants.MOD_ID, "giant"), LegacySizedTemplates.EMPTY_GIANT.template());
+ templates.put(new ResourceLocation(Constants.MOD_ID, "colossal"), LegacySizedTemplates.EMPTY_COLOSSAL.template());
+
+ templates.put(new ResourceLocation(Constants.MOD_ID, "absurd"), new RoomTemplate(new Vec3i(25, 25, 25),
+ FastColor.ARGB32.color(255, 0, 166, 88),
+ RoomTemplate.NO_TEMPLATE));
+
+ final var ops = RegistryOps.create(JsonOps.INSTANCE, RegistryAccess.builtinCopy());
+
+ final var gen = event.getGenerator();
+ final var files = event.getExistingFileHelper();
+
+ final var provider = JsonCodecProvider.forDatapackRegistry(gen, files,
+ Constants.MOD_ID, ops, Rooms.TEMPLATE_REG_KEY, templates);
+
+ gen.addProvider(event.includeServer(), provider);
+ }
+}
diff --git a/forge-datagen/src/main/java/dev/compactmods/machines/datagen/tags/BlockTagGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/tags/BlockTagGenerator.java
new file mode 100644
index 00000000..996892a2
--- /dev/null
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/tags/BlockTagGenerator.java
@@ -0,0 +1,59 @@
+package dev.compactmods.machines.datagen.tags;
+
+import dev.compactmods.machines.api.core.CMTags;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.forge.machine.Machines;
+import dev.compactmods.machines.forge.machine.block.LegacySizedCompactMachineBlock;
+import dev.compactmods.machines.forge.wall.Walls;
+import net.minecraft.data.DataGenerator;
+import net.minecraft.data.tags.BlockTagsProvider;
+import net.minecraft.tags.BlockTags;
+import net.minecraftforge.common.data.ExistingFileHelper;
+
+import java.util.Set;
+
+public class BlockTagGenerator extends BlockTagsProvider {
+
+ public BlockTagGenerator(DataGenerator generator, ExistingFileHelper files) {
+ super(generator, Constants.MOD_ID, files);
+ }
+
+ @Override
+ @SuppressWarnings("removal")
+ public void addTags() {
+ var legacySizedMachines = Set.of(Machines.MACHINE_BLOCK_TINY.get(),
+ Machines.MACHINE_BLOCK_SMALL.get(),
+ Machines.MACHINE_BLOCK_NORMAL.get(),
+ Machines.MACHINE_BLOCK_LARGE.get(),
+ Machines.MACHINE_BLOCK_GIANT.get(),
+ Machines.MACHINE_BLOCK_MAXIMUM.get());
+
+ var legacyMachines = tag(LegacySizedCompactMachineBlock.LEGACY_MACHINES_TAG);
+ var allMachines = tag(CMTags.MACHINE_BLOCK);
+ var pickaxe = tag(BlockTags.MINEABLE_WITH_PICKAXE);
+ var ironTool = tag(BlockTags.NEEDS_IRON_TOOL);
+
+ var breakableWall = Walls.BLOCK_BREAKABLE_WALL.get();
+ pickaxe.add(breakableWall);
+ ironTool.add(breakableWall);
+
+ legacySizedMachines.forEach(mach -> {
+ legacyMachines.add(mach);
+ allMachines.add(mach);
+ pickaxe.add(mach);
+ ironTool.add(mach);
+ });
+
+ var boundMachine = Machines.MACHINE_BLOCK.get();
+ allMachines.add(boundMachine);
+ pickaxe.add(boundMachine);
+ ironTool.add(boundMachine);
+
+ var unboundTag = tag(CMTags.UNBOUND_MACHINE_BLOCK);
+ var unboundMachine = Machines.UNBOUND_MACHINE_BLOCK.get();
+ allMachines.add(unboundMachine);
+ unboundTag.add(unboundMachine);
+ pickaxe.add(unboundMachine);
+ ironTool.add(unboundMachine);
+ }
+}
diff --git a/forge-datagen/src/main/java/dev/compactmods/machines/datagen/tags/ItemTagGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/tags/ItemTagGenerator.java
new file mode 100644
index 00000000..8b7e1d82
--- /dev/null
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/tags/ItemTagGenerator.java
@@ -0,0 +1,56 @@
+package dev.compactmods.machines.datagen.tags;
+
+import dev.compactmods.machines.forge.Registries;
+import dev.compactmods.machines.forge.machine.Machines;
+import dev.compactmods.machines.forge.machine.item.LegacyCompactMachineItem;
+import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades;
+import dev.compactmods.machines.api.core.CMTags;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.shrinking.PSDTags;
+import dev.compactmods.machines.forge.shrinking.Shrinking;
+import net.minecraft.data.DataGenerator;
+import net.minecraft.data.tags.BlockTagsProvider;
+import net.minecraft.data.tags.ItemTagsProvider;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.tags.TagKey;
+import net.minecraftforge.common.data.ExistingFileHelper;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Set;
+
+public class ItemTagGenerator extends ItemTagsProvider {
+ public ItemTagGenerator(DataGenerator gen, BlockTagsProvider blockTags, @Nullable ExistingFileHelper files) {
+ super(gen, blockTags, Constants.MOD_ID, files);
+ }
+
+ @Override
+ protected void addTags() {
+ var upgradeTag = tag(CMTags.ROOM_UPGRADE_ITEM);
+ var machinesTag = tag(CMTags.MACHINE_ITEM);
+ var legacyMachinesTag = tag(LegacyCompactMachineItem.TAG);
+
+ var legacySizedMachines = Set.of(Machines.MACHINE_BLOCK_ITEM_TINY.get(),
+ Machines.MACHINE_BLOCK_ITEM_SMALL.get(),
+ Machines.MACHINE_BLOCK_ITEM_NORMAL.get(),
+ Machines.MACHINE_BLOCK_ITEM_LARGE.get(),
+ Machines.MACHINE_BLOCK_ITEM_GIANT.get(),
+ Machines.MACHINE_BLOCK_ITEM_MAXIMUM.get());
+
+ var boundMachineItem = Machines.BOUND_MACHINE_BLOCK_ITEM.get();
+ var unboundMachineItem = Machines.UNBOUND_MACHINE_BLOCK_ITEM.get();
+
+ legacySizedMachines.forEach(machinesTag::add);
+ legacySizedMachines.forEach(legacyMachinesTag::add);
+
+ machinesTag.add(boundMachineItem);
+ machinesTag.add(unboundMachineItem);
+
+ upgradeTag.add(MachineRoomUpgrades.ROOM_UPGRADE.get());
+
+ final var psd = Shrinking.PERSONAL_SHRINKING_DEVICE.get();
+ final var curiosPsdTag = tag(TagKey.create(Registries.ITEMS.getRegistryKey(), new ResourceLocation("curios", "psd")));
+ final var cmShrinkTag = tag(PSDTags.ITEM);
+ curiosPsdTag.add(psd);
+ cmShrinkTag.add(psd);
+ }
+}
diff --git a/forge-datagen/src/main/java/dev/compactmods/machines/datagen/tags/PointOfInterestTagGenerator.java b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/tags/PointOfInterestTagGenerator.java
new file mode 100644
index 00000000..c98d0cdd
--- /dev/null
+++ b/forge-datagen/src/main/java/dev/compactmods/machines/datagen/tags/PointOfInterestTagGenerator.java
@@ -0,0 +1,22 @@
+package dev.compactmods.machines.datagen.tags;
+
+import dev.compactmods.machines.forge.villager.Villagers;
+import dev.compactmods.machines.api.core.Constants;
+import net.minecraft.data.DataGenerator;
+import net.minecraft.data.tags.PoiTypeTagsProvider;
+import net.minecraft.tags.PoiTypeTags;
+import net.minecraft.world.entity.ai.village.poi.PoiType;
+import net.minecraftforge.common.data.ExistingFileHelper;
+import org.jetbrains.annotations.Nullable;
+
+public class PointOfInterestTagGenerator extends PoiTypeTagsProvider {
+ public PointOfInterestTagGenerator(DataGenerator gen, @Nullable ExistingFileHelper files) {
+ super(gen, Constants.MOD_ID, files);
+ }
+
+ @Override
+ protected void addTags() {
+ TagAppender builder = tag(PoiTypeTags.ACQUIRABLE_JOB_SITE);
+ builder.add(Villagers.TINKERER_WORKBENCH_KEY);
+ }
+}
diff --git a/forge-main/.gitignore b/forge-main/.gitignore
new file mode 100644
index 00000000..454ab39a
--- /dev/null
+++ b/forge-main/.gitignore
@@ -0,0 +1,3 @@
+build/
+run/
+src/generated/
\ No newline at end of file
diff --git a/forge-main/build.gradle.kts b/forge-main/build.gradle.kts
new file mode 100644
index 00000000..ec8c4bba
--- /dev/null
+++ b/forge-main/build.gradle.kts
@@ -0,0 +1,321 @@
+import java.text.SimpleDateFormat
+import java.util.*
+
+val modVersion: String = System.getenv("CM_VERSION") ?: "9.9.9"
+
+val coreVersion: String = property("core_version") as String
+val tunnelsApiVersion: String = property("tunnels_version") as String
+
+var modId = property("mod_id") as String
+var minecraft_version: String by extra
+var forge_version: String by extra
+var parchment_version: String by extra
+
+plugins {
+ id("maven-publish")
+ id("net.minecraftforge.gradle") version ("5.1.+")
+ id("org.parchmentmc.librarian.forgegradle") version ("1.+")
+}
+
+base {
+ group = "dev.compactmods.compactmachines"
+ version = modVersion
+}
+
+java {
+ toolchain.languageVersion.set(JavaLanguageVersion.of(17))
+}
+
+sourceSets.main {
+ resources {
+ srcDir("src/main/resources")
+ srcDir("src/generated/resources")
+ }
+}
+
+sourceSets.test {
+ java.srcDir("src/test/java")
+ resources.srcDir("src/test/resources")
+}
+
+
+repositories {
+ mavenLocal()
+
+ mavenCentral() {
+ name = "Central"
+ content {
+ includeGroup("com.aventrix.jnanoid")
+ }
+ }
+
+ maven("https://www.cursemaven.com") {
+ name = "Curse Maven"
+ content {
+ includeGroup("curse.maven")
+ }
+ }
+
+ // location of the maven that hosts JEI files
+ maven("https://maven.blamejared.com") {
+ content {
+ includeGroup("mezz.jei")
+ }
+ }
+
+ maven("https://maven.theillusivec4.top/") {
+ name = "Illusive"
+ content {
+ includeGroup("top.theillusivec4.curios")
+ }
+ }
+
+ maven("https://maven.pkg.github.com/compactmods/compactmachines-core") {
+ name = "Github PKG Core"
+ credentials {
+ username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR")
+ password = project.findProperty("gpr.token") as String? ?: System.getenv("GITHUB_TOKEN")
+ }
+ }
+}
+
+val jei_version: String? by extra
+val jei_mc_version: String by extra
+val curios_version: String? by extra
+
+val runDepends: List = listOf(
+ project(":forge-tunnels-api"),
+ project(":forge-builtin")
+)
+
+runDepends.forEach {
+ project.evaluationDependsOn(it.path)
+}
+
+dependencies {
+ minecraft("net.minecraftforge", "forge", version = "${minecraft_version}-${forge_version}")
+
+ implementation("dev.compactmods.compactmachines:core-api:$coreVersion")
+ implementation("dev.compactmods.compactmachines:core:$coreVersion")
+ implementation("dev.compactmods.compactmachines:tunnels-api:$tunnelsApiVersion")
+
+ jarJar("dev.compactmods.compactmachines", "core", "[$coreVersion]", classifier = "srg") {
+ isTransitive = false
+ }
+
+ jarJar("dev.compactmods.compactmachines", "core-api", "[$coreVersion]", classifier = "srg") {
+ isTransitive = false
+ }
+
+ jarJar("dev.compactmods.compactmachines", "tunnels-api", "[$tunnelsApiVersion]", classifier = "srg") {
+ isTransitive = false
+ }
+
+ implementation(project(":forge-tunnels-api"))
+ testImplementation(project(":forge-tunnels-api"))
+
+ implementation(project(":forge-builtin"))
+ testImplementation(project(":forge-builtin"))
+
+ minecraftLibrary("com.aventrix.jnanoid", "jnanoid", "2.0.0")
+ jarJar("com.aventrix.jnanoid", "jnanoid", "[2.0.0]")
+
+ // JEI
+ if (project.extra.has("jei_version") && project.extra.has("jei_mc_version")) {
+ compileOnly(fg.deobf("mezz.jei:jei-${jei_mc_version}-common-api:${jei_version}"))
+ compileOnly(fg.deobf("mezz.jei:jei-${jei_mc_version}-forge-api:${jei_version}"))
+ runtimeOnly(fg.deobf("mezz.jei:jei-${jei_mc_version}-forge:${jei_version}"))
+ }
+
+ // The One Probe
+ implementation(fg.deobf("curse.maven:theoneprobe-245211:3927520"))
+
+ // Curios
+ if (project.extra.has("curios_version")) {
+ runtimeOnly(fg.deobf("top.theillusivec4.curios:curios-forge:${curios_version}"))
+ compileOnly(fg.deobf("top.theillusivec4.curios:curios-forge:${curios_version}:api"))
+ }
+
+ val include_test_mods: String? by project.extra
+ if (!System.getenv().containsKey("CI") && include_test_mods.equals("true")) {
+ // Nicephore - Screenshots and Stuff
+ runtimeOnly(fg.deobf("curse.maven:nicephore-401014:3879841"))
+
+ // Testing Mods - Trash Cans, Pipez, Create, Refined Pipes, Pretty Pipes, Refined Storage
+ runtimeOnly(fg.deobf("curse.maven:SuperMartijn642-454372:3910759"))
+ runtimeOnly(fg.deobf("curse.maven:trashcans-394535:3871885"))
+
+ // Flywheel/Create - v0.6.8.a / v0.5.0i - Jan 29, 2023
+ runtimeOnly(fg.deobf("curse.maven:flywheel-486392:4341471"))
+ runtimeOnly(fg.deobf("curse.maven:create-328085:4371809"))
+
+ // 1.18 runtimeOnly(fg.deobf("curse.maven:refinedpipes-370696:3570151"))
+
+ // Pretty Pipes - 1.13.6 - Oct 25, 2022
+ runtimeOnly(fg.deobf("curse.maven:prettypipes-376737:4049655"))
+
+ // Refined Storage - 1.11.6 - Mar 30, 2023
+ runtimeOnly(fg.deobf("curse.maven:refinedstorage-243076:4465872"))
+
+ // Scalable Cat's Force, BdLib, Advanced Generators
+ // 2.13.10-b10 - Oct 13, 2022 / 1.25.0.5 - Nov 20, 2022 / 1.4.0.5 - Nov 22, 2022
+ runtimeOnly(fg.deobf("curse.maven:scalable-320926:4028119"))
+ runtimeOnly(fg.deobf("curse.maven:bdlib-70496:4100704"))
+ runtimeOnly(fg.deobf("curse.maven:advgen-223622:4104739"))
+
+ // Immersive Eng - 7.1.0-145 (Dec 31)
+ // runtimeOnly(fg.deobf("curse.maven:immersiveeng-231951:3587149"))
+
+ // FTB Chunks
+// runtimeOnly(fg.deobf("curse.maven:architectury-forge-419699:3781711"))
+// runtimeOnly(fg.deobf("curse.maven:ftb-teams-404468:3725501"))
+// runtimeOnly(fg.deobf("curse.maven:ftblib-404465:3725485"))
+// runtimeOnly(fg.deobf("curse.maven:ftbchunks-314906:3780113"))
+
+ // Mekanism + Mek Generators - Tunnel testing
+ // 10.3.8.477 - Feb 7, 2023 / 10.3.8.477 - Feb 7, 2023
+ runtimeOnly(fg.deobf("curse.maven:mekanism-268560:4385637"))
+ runtimeOnly(fg.deobf("curse.maven:mekanismgenerators-268566:4385639"))
+
+ // Soul Shards (FTB)
+ // runtimeOnly(fg.deobf("curse.maven:polylib-576589:3751528"))
+ // runtimeOnly(fg.deobf("curse.maven:soulshards-551523:3757202"))
+
+ // Everlasting Abilities
+ // runtimeOnly(fg.deobf("curse.maven:cyclopscore-232758:3809427"))
+ // runtimeOnly(fg.deobf("curse.maven:everlastabilities-248353:3768481"))
+ }
+}
+
+minecraft {
+ mappings("parchment", "${parchment_version}-${minecraft_version}")
+ accessTransformer(file("src/main/resources/META-INF/accesstransformer.cfg"))
+
+ runs {
+ all {
+ // Recommended logging data for a userdev environment
+ property("forge.logging.markers", "") // "SCAN,REGISTRIES,REGISTRYDUMP"
+
+ // Recommended logging level for the console
+ property("forge.logging.console.level", "debug")
+
+ property("mixin.env.remapRefMap", "true")
+ property("mixin.env.refMapRemappingFile", "${buildDir}/createSrgToMcp/output.srg")
+
+ ideaModule("Compact_Machines.forge-main.main")
+
+ if (!System.getenv().containsKey("CI")) {
+ // JetBrains Runtime Hotswap
+ jvmArg("-XX:+AllowEnhancedClassRedefinition")
+ }
+
+ source(sourceSets.main.get())
+ mods.create(modId) {
+ source(sourceSets.main.get())
+ for (p in runDepends)
+ source(p.sourceSets.main.get())
+ }
+ }
+
+ create("client") {
+ taskName("runClient-Nano")
+ workingDirectory(file("run/client"))
+
+ args("--username", "Nano")
+ args("--width", 1920)
+ args("--height", 1080)
+ }
+
+ create("gameTestServer") {
+ taskName("runGameTestServer")
+ workingDirectory(file("run/gametests"))
+ ideaModule("Compact_Machines.forge-main.test")
+
+ forceExit(false)
+ environment("CM5_TEST_RESOURCES", file("src/test/resources"))
+
+ mods.named(modId) {
+ source(sourceSets.test.get())
+ }
+ }
+ }
+}
+
+reobf {
+ this.create("jarJar")
+}
+
+tasks.compileJava {
+ options.encoding = "UTF-8";
+}
+
+tasks.withType {
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+}
+
+tasks.withType {
+ val forgeBuiltin = project(":forge-builtin").tasks.jar.get().archiveFile;
+ val forgeTunnelsApi = project(":forge-builtin").tasks.jar.get().archiveFile;
+ from(forgeBuiltin.map { zipTree(it) })
+ from(forgeTunnelsApi.map { zipTree(it) })
+
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+
+ manifest {
+ val now = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(Date())
+ attributes(mapOf(
+ "Specification-Title" to "Compact Machines",
+ "Specification-Vendor" to "",
+ "Specification-Version" to "1", // We are version 1 of ourselves
+ "Implementation-Title" to "Compact Machines",
+ "Implementation-Version" to archiveVersion,
+ "Implementation-Vendor" to "",
+ "Implementation-Timestamp" to now
+ ))
+ }
+}
+
+tasks.jar {
+ archiveClassifier.set("slim")
+ finalizedBy("reobfJar")
+}
+
+jarJar.enable()
+tasks.jarJar {
+ archiveClassifier.set("")
+ finalizedBy("reobfJarJar")
+}
+
+tasks.reobfJarJar {
+// doFirst {
+// println("Reobfuscating JarJar")
+// this.inputs.files.forEach {
+// println(it.path)
+// }
+// }
+}
+
+artifacts {
+ archives(tasks.jar.get())
+ archives(tasks.jarJar.get())
+}
+
+val PACKAGES_URL = System.getenv("GH_PKG_URL") ?: "https://maven.pkg.github.com/compactmods/compactcrafting"
+publishing {
+ publications.register("forge") {
+ artifactId = "$modId-forge"
+ artifact(tasks.getByName("jar"))
+ artifact(tasks.getByName("jarJar"))
+ }
+
+ repositories {
+ // GitHub Packages
+ maven(PACKAGES_URL) {
+ name = "GitHubPackages"
+ credentials {
+ username = System.getenv("GITHUB_ACTOR")
+ password = System.getenv("GITHUB_TOKEN")
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/forge-main/gradle.properties b/forge-main/gradle.properties
new file mode 100644
index 00000000..89d64c59
--- /dev/null
+++ b/forge-main/gradle.properties
@@ -0,0 +1,5 @@
+# Dependencies and Libs
+jei_mc_version=1.19.2
+jei_version=11.2.0.247
+#top_version=1.16-3.1.4-22
+curios_version=1.19.2-5.1.1.0
\ No newline at end of file
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/CompactMachines.java b/forge-main/src/main/java/dev/compactmods/machines/forge/CompactMachines.java
new file mode 100644
index 00000000..3e69824f
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/CompactMachines.java
@@ -0,0 +1,148 @@
+package dev.compactmods.machines.forge;
+
+import dev.compactmods.machines.ICompactMachinesMod;
+import dev.compactmods.machines.api.CompactMachinesAddon;
+import dev.compactmods.machines.api.ICompactMachinesAddon;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.room.IPlayerRoomMetadataProvider;
+import dev.compactmods.machines.api.room.IRoomHistory;
+import dev.compactmods.machines.command.Commands;
+import dev.compactmods.machines.forge.client.ClientConfig;
+import dev.compactmods.machines.forge.config.CommonConfig;
+import dev.compactmods.machines.forge.config.ServerConfig;
+import dev.compactmods.machines.forge.data.functions.LootFunctions;
+import dev.compactmods.machines.forge.dimension.Dimension;
+import dev.compactmods.machines.forge.machine.Machines;
+import dev.compactmods.machines.forge.room.Rooms;
+import dev.compactmods.machines.forge.room.ui.RoomUserInterfaceRegistration;
+import dev.compactmods.machines.forge.shrinking.Shrinking;
+import dev.compactmods.machines.forge.tunnel.Tunnels;
+import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades;
+import dev.compactmods.machines.forge.util.AnnotationScanner;
+import dev.compactmods.machines.forge.villager.Villagers;
+import dev.compactmods.machines.forge.wall.Walls;
+import net.minecraft.world.item.CreativeModeTab;
+import net.minecraft.world.item.ItemStack;
+import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
+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.forgespi.language.ModFileScanData;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
+
+import javax.annotation.Nonnull;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Mod(Constants.MOD_ID)
+public class CompactMachines implements ICompactMachinesMod {
+ /**
+ * @deprecated Switch usages to use api {@link Constants#MOD_ID} in 1.20, eliminate it here
+ */
+ @Deprecated(forRemoval = true, since = "5.2.0")
+ public static final String MOD_ID = Constants.MOD_ID;
+
+ public static final Marker ADDON_LIFECYCLE = MarkerManager.getMarker("addons");
+
+ public static final CreativeModeTab COMPACT_MACHINES_ITEMS = new CreativeModeTab(Constants.MOD_ID) {
+ @Override
+ public @Nonnull
+ ItemStack makeIcon() {
+ return new ItemStack(Machines.MACHINE_BLOCK_ITEM_NORMAL.get());
+ }
+ };
+
+ private static Set loadedAddons;
+
+ public CompactMachines() {
+ Registries.setup();
+ preparePackages();
+ doRegistration();
+
+ // Configuration
+ ModLoadingContext mlCtx = ModLoadingContext.get();
+ mlCtx.registerConfig(ModConfig.Type.CLIENT, ClientConfig.CONFIG);
+ mlCtx.registerConfig(ModConfig.Type.COMMON, CommonConfig.CONFIG);
+ mlCtx.registerConfig(ModConfig.Type.SERVER, ServerConfig.CONFIG);
+
+ final var bus = FMLJavaModLoadingContext.get().getModEventBus();
+ bus.addListener(this::registerCapabilities);
+ }
+
+ private void registerCapabilities(final RegisterCapabilitiesEvent caps) {
+ caps.register(IPlayerRoomMetadataProvider.class);
+ caps.register(IRoomHistory.class);
+ }
+
+ /**
+ * Sets up the deferred registration for usage in package/module setup.
+ */
+ private static void doRegistration() {
+ var bus = FMLJavaModLoadingContext.get().getModEventBus();
+
+ Registries.BLOCKS.register(bus);
+ Registries.ITEMS.register(bus);
+ Registries.BLOCK_ENTITIES.register(bus);
+ Registries.TUNNEL_DEFINITIONS.register(bus);
+ Registries.CONTAINERS.register(bus);
+ Registries.ROOM_TEMPLATES.register(bus);
+ Registries.UPGRADES.register(bus);
+ Registries.COMMAND_ARGUMENT_TYPES.register(bus);
+ Registries.LOOT_FUNCS.register(bus);
+ Registries.VILLAGERS.register(bus);
+ // Villagers.TRADES.register(bus);
+ Registries.POINTS_OF_INTEREST.register(bus);
+
+// CompactMachines.loadedAddons = ServiceLoader.load(ICompactMachinesAddon.class)
+// .stream()
+// .filter(p -> Arrays.stream(p.type().getAnnotationsByType(CompactMachinesAddon.class))
+// .anyMatch(cma -> cma.major() == 2))
+// .map(allowedThisMajor -> {
+// allowedThisMajor.get();
+// })
+// .collect(Collectors.toSet());
+
+ CompactMachines.loadedAddons = AnnotationScanner.scanModList(CompactMachinesAddon.class)
+ .map(ModFileScanData.AnnotationData::memberName)
+ .map(cmAddonClass -> {
+ try {
+ final var cl = Class.forName(cmAddonClass);
+ final var cla = cl.asSubclass(ICompactMachinesAddon.class);
+ return cla.getDeclaredConstructor().newInstance();
+ } catch (Exception e) {
+ return null;
+ }
+ })
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+
+ CompactMachines.loadedAddons.forEach(addon -> {
+ LOGGER.debug(ADDON_LIFECYCLE, "Sending registration hook to addon: {}", addon.getClass().getName());
+ addon.afterRegistration();
+ });
+ }
+
+ private static void preparePackages() {
+ // Package initialization here, this kickstarts the rest of the DR code (classloading)
+ Machines.prepare();
+ Walls.prepare();
+ Tunnels.prepare();
+ Shrinking.prepare();
+
+ RoomUserInterfaceRegistration.prepare();
+ Dimension.prepare();
+ Rooms.prepare();
+ MachineRoomUpgrades.prepare();
+ Commands.prepare();
+ LootFunctions.prepare();
+
+ Villagers.prepare();
+ }
+
+ public static Set getAddons() {
+ return loadedAddons;
+ }
+}
diff --git a/src/main/java/dev/compactmods/machines/core/ModBusEvents.java b/forge-main/src/main/java/dev/compactmods/machines/forge/ModBusEvents.java
similarity index 62%
rename from src/main/java/dev/compactmods/machines/core/ModBusEvents.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/ModBusEvents.java
index e249f4ff..6e9f820c 100644
--- a/src/main/java/dev/compactmods/machines/core/ModBusEvents.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/ModBusEvents.java
@@ -1,9 +1,10 @@
-package dev.compactmods.machines.core;
+package dev.compactmods.machines.forge;
-import dev.compactmods.machines.CompactMachines;
+import dev.compactmods.machines.LoggingUtil;
import dev.compactmods.machines.advancement.AdvancementTriggers;
import dev.compactmods.machines.api.core.Constants;
-import dev.compactmods.machines.room.network.RoomNetworkHandler;
+import dev.compactmods.machines.forge.network.CompactMachinesNet;
+import dev.compactmods.machines.forge.network.RoomNetworkHandler;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
@@ -13,11 +14,13 @@ public class ModBusEvents {
@SubscribeEvent
public static void setup(final FMLCommonSetupEvent event) {
- CompactMachines.LOGGER.trace("Initializing network handler.");
+ var logger = LoggingUtil.modLog();
+
+ logger.trace("Initializing network handler.");
CompactMachinesNet.setupMessages();
RoomNetworkHandler.setupMessages();
- CompactMachines.LOGGER.trace("Registering advancement triggers.");
+ logger.trace("Registering advancement triggers.");
AdvancementTriggers.init();
}
}
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/ModDataUpgrader.java b/forge-main/src/main/java/dev/compactmods/machines/forge/ModDataUpgrader.java
new file mode 100644
index 00000000..d60a6bb2
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/ModDataUpgrader.java
@@ -0,0 +1,135 @@
+package dev.compactmods.machines.forge;
+
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.dimension.CompactDimension;
+import dev.compactmods.machines.forge.data.migration.EarlyLevelDataFileReader;
+import dev.compactmods.machines.forge.data.migration.Pre520RoomDataMigrator;
+import dev.compactmods.machines.room.graph.CompactRoomProvider;
+import net.minecraft.world.level.storage.LevelStorageSource;
+import net.minecraftforge.event.ModMismatchEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.common.Mod;
+import org.apache.commons.io.file.PathUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.SignStyle;
+import java.time.temporal.ChronoField;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+@Mod.EventBusSubscriber(modid = Constants.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
+public class ModDataUpgrader {
+
+ private static final Logger UPDATER_LOGGER = LogManager.getLogger(Constants.MOD_ID);
+ private static final Marker UPDATER = MarkerManager.getMarker("pre520_data_updater");
+
+ static final DateTimeFormatter DATETIME_FORMAT = new DateTimeFormatterBuilder()
+ .appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
+ .appendLiteral('-')
+ .appendValue(ChronoField.MONTH_OF_YEAR, 2)
+ .appendLiteral('-')
+ .appendValue(ChronoField.DAY_OF_MONTH, 2)
+ .appendLiteral('_')
+ .appendValue(ChronoField.HOUR_OF_DAY, 2)
+ .appendLiteral('-')
+ .appendValue(ChronoField.MINUTE_OF_HOUR, 2)
+ .appendLiteral('-')
+ .appendValue(ChronoField.SECOND_OF_MINUTE, 2)
+ .toFormatter();
+
+ @SubscribeEvent
+ public static void onUpgrade(final ModMismatchEvent mismatch) {
+ mismatch.getVersionDifference(Constants.MOD_ID).ifPresent(versions -> {
+ // If we're migrating from a version pre-5.2.0 (1.19.2)
+ if (versions.oldVersion().compareTo(new DefaultArtifactVersion("5.2.0")) < 0) {
+ // do upgrade
+ try {
+ ModDataUpgrader.doUpgrade(mismatch.getLevelDirectory());
+ mismatch.markResolved(Constants.MOD_ID);
+ } catch (IOException e) {
+ CompactMachines.LOGGER.fatal("Exception occurred while trying to upgrade world data.", e);
+ }
+ }
+ });
+ }
+
+ public static void doUpgrade(@Nullable LevelStorageSource.LevelDirectory levelDirectory) throws IOException {
+ if (levelDirectory != null) {
+ final var dataStore = CompactDimension.getDataStorage(levelDirectory);
+ final var backupDir = levelDirectory.path().resolve("cm5_backup");
+
+ final var earlyFileReader = new EarlyLevelDataFileReader(levelDirectory);
+
+ Files.deleteIfExists(backupDir);
+ Files.createDirectories(backupDir);
+
+ var oldData = Pre520RoomDataMigrator.loadOldRoomData(dataStore);
+
+ if (oldData.oldRoomData().isEmpty()) {
+ UPDATER_LOGGER.info(UPDATER, "No room data found to update. Exiting early.");
+ return;
+ }
+
+ Pre520RoomDataMigrator.makeRoomDataBackup(dataStore, backupDir);
+ if(!dataStore.getDataFile(Pre520RoomDataMigrator.ROOM_DATA_NAME).delete())
+ UPDATER_LOGGER.warn(UPDATER, "Failed to remove original room data file after backup; things might get weird.");
+
+ final var roomChunkLookup = oldData.roomChunkLookup();
+
+ Pre520RoomDataMigrator.addMissingRoomEntries(dataStore, CompactRoomProvider.empty(), oldData);
+
+ UPDATER_LOGGER.debug(UPDATER, "Updating room data for {} rooms.", roomChunkLookup.size());
+
+ final var levels = earlyFileReader.dimensions();
+ Pre520RoomDataMigrator.migrateConnectionInfo(levelDirectory, roomChunkLookup, levels, backupDir);
+
+ Pre520RoomDataMigrator.migrateTunnelFiles(levelDirectory, roomChunkLookup, backupDir);
+
+ makeBackupZip(levelDirectory.path().resolve("cm520-data-backup-%s.zip".formatted(LocalDateTime.now().format(DATETIME_FORMAT))), backupDir);
+ PathUtils.delete(backupDir);
+ }
+ }
+
+
+ private static void makeBackupZip(Path destinationFile, Path backupDir) throws IOException {
+ final ZipOutputStream zipoutputstream = new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(destinationFile)));
+
+ try {
+ Files.walkFileTree(backupDir, new SimpleFileVisitor<>() {
+ public FileVisitResult visitFile(Path filename, BasicFileAttributes attrs) throws IOException {
+ String shortFilename = backupDir.relativize(filename).toString().replace('\\', '/');
+ zipoutputstream.putNextEntry(new ZipEntry(shortFilename));
+
+ com.google.common.io.Files.asByteSource(filename.toFile()).copyTo(zipoutputstream);
+ zipoutputstream.closeEntry();
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ } catch (Throwable throwable1) {
+ try {
+ zipoutputstream.close();
+ } catch (Throwable throwable) {
+ throwable1.addSuppressed(throwable);
+ }
+
+ throw throwable1;
+ }
+
+ zipoutputstream.close();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/dev/compactmods/machines/core/Registries.java b/forge-main/src/main/java/dev/compactmods/machines/forge/Registries.java
similarity index 57%
rename from src/main/java/dev/compactmods/machines/core/Registries.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/Registries.java
index bc5d3391..08ca248f 100644
--- a/src/main/java/dev/compactmods/machines/core/Registries.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/Registries.java
@@ -1,13 +1,14 @@
-package dev.compactmods.machines.core;
+package dev.compactmods.machines.forge;
-import dev.compactmods.machines.api.room.upgrade.RoomUpgrade;
+import dev.compactmods.machines.api.core.CMRegistryKeys;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.room.RoomTemplate;
import dev.compactmods.machines.api.tunnels.TunnelDefinition;
-import dev.compactmods.machines.graph.IGraphEdgeType;
-import dev.compactmods.machines.graph.IGraphNodeType;
+import dev.compactmods.machines.api.upgrade.RoomUpgrade;
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.core.Registry;
-import net.minecraft.resources.ResourceKey;
-import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.entity.ai.village.poi.PoiType;
+import net.minecraft.world.entity.npc.VillagerProfession;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
@@ -26,24 +27,13 @@ public class Registries {
public static final DeferredRegister> BLOCK_ENTITIES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, MOD_ID);
// Tunnels
- public static final ResourceLocation TYPES_REG_KEY = new ResourceLocation(MOD_ID, "tunnel_types");
- public static final DeferredRegister TUNNEL_DEFINITIONS = DeferredRegister.create(TYPES_REG_KEY, MOD_ID);
+ public static final DeferredRegister TUNNEL_DEFINITIONS = DeferredRegister.create(TunnelDefinition.REGISTRY_KEY, MOD_ID);
// UIRegistration
public static final DeferredRegister> CONTAINERS = DeferredRegister.create(ForgeRegistries.MENU_TYPES, MOD_ID);
// MachineRoomUpgrades
- public static final ResourceKey> ROOM_UPGRADES_REG_KEY = ResourceKey
- .createRegistryKey(new ResourceLocation(MOD_ID, "room_upgrades"));
- public static final DeferredRegister UPGRADES = DeferredRegister.create(ROOM_UPGRADES_REG_KEY, MOD_ID);
-
- // Graph
- public static final ResourceKey> NODES_REG_KEY = ResourceKey
- .createRegistryKey(new ResourceLocation(MOD_ID, "graph_nodes"));
- public static final ResourceKey> EDGES_REG_KEY = ResourceKey
- .createRegistryKey(new ResourceLocation(MOD_ID, "graph_edges"));
- public static final DeferredRegister NODE_TYPES = DeferredRegister.create(NODES_REG_KEY, MOD_ID);
- public static final DeferredRegister EDGE_TYPES = DeferredRegister.create(EDGES_REG_KEY, MOD_ID);
+ public static final DeferredRegister UPGRADES = DeferredRegister.create(CMRegistryKeys.ROOM_UPGRADES, MOD_ID);
// Commands
public static final DeferredRegister> COMMAND_ARGUMENT_TYPES = DeferredRegister.create(Registry.COMMAND_ARGUMENT_TYPE_REGISTRY, MOD_ID);
@@ -51,6 +41,14 @@ public class Registries {
// LootFunctions
public static final DeferredRegister LOOT_FUNCS = DeferredRegister.create(Registry.LOOT_FUNCTION_REGISTRY, MOD_ID);
+ public static DeferredRegister ROOM_TEMPLATES = DeferredRegister
+ .create(CMRegistryKeys.ROOM_TEMPLATES, Constants.MOD_ID);
+
+ // Villagers
+ public static final DeferredRegister VILLAGERS = DeferredRegister.create(ForgeRegistries.VILLAGER_PROFESSIONS, Constants.MOD_ID);
+
+ public static final DeferredRegister POINTS_OF_INTEREST = DeferredRegister.create(ForgeRegistries.POI_TYPES, Constants.MOD_ID);
+
public static void setup() {
}
diff --git a/src/main/java/dev/compactmods/machines/core/ServerEventHandler.java b/forge-main/src/main/java/dev/compactmods/machines/forge/ServerEventHandler.java
similarity index 57%
rename from src/main/java/dev/compactmods/machines/core/ServerEventHandler.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/ServerEventHandler.java
index d0b650fe..f84f439b 100644
--- a/src/main/java/dev/compactmods/machines/core/ServerEventHandler.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/ServerEventHandler.java
@@ -1,9 +1,16 @@
-package dev.compactmods.machines.core;
+package dev.compactmods.machines.forge;
+import dev.compactmods.machines.LoggingUtil;
import dev.compactmods.machines.api.core.Constants;
import dev.compactmods.machines.api.dimension.CompactDimension;
-import dev.compactmods.machines.api.room.upgrade.ILevelLoadedUpgradeListener;
-import dev.compactmods.machines.upgrade.RoomUpgradeManager;
+import dev.compactmods.machines.api.inject.InjectField;
+import dev.compactmods.machines.api.room.IRoomOwnerLookup;
+import dev.compactmods.machines.api.room.registration.IRoomSpawnLookup;
+import dev.compactmods.machines.api.upgrade.ILevelLoadedUpgradeListener;
+import dev.compactmods.machines.forge.room.ForgeCompactRoomProvider;
+import dev.compactmods.machines.room.graph.CompactRoomProvider;
+import dev.compactmods.machines.forge.room.upgrade.RoomUpgradeManager;
+import dev.compactmods.machines.forge.util.AnnotationScanner;
import net.minecraft.network.protocol.game.ClientboundInitializeBorderPacket;
import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket;
import net.minecraft.server.level.ServerLevel;
@@ -12,28 +19,45 @@
import net.minecraft.world.level.border.WorldBorder;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.level.LevelEvent;
+import net.minecraftforge.event.server.ServerAboutToStartEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.network.PacketDistributor;
+import java.util.function.Supplier;
import java.util.stream.Collectors;
@Mod.EventBusSubscriber(modid = Constants.MOD_ID)
public class ServerEventHandler {
+ @SubscribeEvent
+ public static void onServerAboutToStart(final ServerAboutToStartEvent server) {
+ final var modLog = LoggingUtil.modLog();
+
+ modLog.debug("Starting addon scan and injection for server startup.");
+ CompactMachines.getAddons().forEach(addon -> {
+ final Supplier ownerLookup = ForgeCompactRoomProvider::instance;
+ final Supplier spawnLookup = ForgeCompactRoomProvider::instance;
+
+ final var injectableFields = AnnotationScanner.scanFields(addon, InjectField.class)
+ .filter(field -> field.canAccess(addon))
+ .collect(Collectors.toSet());
+
+ if(injectableFields.isEmpty()) return;
+
+ modLog.debug("Injecting lookup data into addon {} ...", addon.getClass());
+ AnnotationScanner.injectFields(addon, ownerLookup, injectableFields);
+ AnnotationScanner.injectFields(addon, spawnLookup, injectableFields);
+ });
+ }
+
@SubscribeEvent
public static void onWorldLoaded(final LevelEvent.Load evt) {
- if(evt.getLevel() instanceof ServerLevel sl && sl.dimension().equals(CompactDimension.LEVEL_KEY))
+ if(evt.getLevel() instanceof ServerLevel compactDim && compactDim.dimension().equals(CompactDimension.LEVEL_KEY))
{
- final var serv = sl.getServer();
+ final var serv = compactDim.getServer();
final var owBorder = serv.overworld().getWorldBorder();
- final var cwBorder = sl.getWorldBorder();
-
- final var levelUpgrades = RoomUpgradeManager.get(sl);
- levelUpgrades.implementing(ILevelLoadedUpgradeListener.class).forEach(inst -> {
- final var upg = inst.upgrade();
- upg.onLevelLoaded(sl, inst.room());
- });
+ final var cwBorder = compactDim.getWorldBorder();
// Filter border listeners down to the compact world, then remove them from the OW listener list
final var listeners = owBorder.listeners.stream()
@@ -51,6 +75,16 @@ public static void onWorldLoaded(final LevelEvent.Load evt) {
PacketDistributor.DIMENSION.with(() -> CompactDimension.LEVEL_KEY)
.send(new ClientboundSetBorderSizePacket(cwBorder));
+
+ // Room upgrade initialization
+ final var levelUpgrades = RoomUpgradeManager.get(compactDim);
+ final var roomInfo = CompactRoomProvider.instance(compactDim);
+
+ levelUpgrades.implementing(ILevelLoadedUpgradeListener.class).forEach(inst -> {
+ final var upg = inst.upgrade();
+ roomInfo.forRoom(inst.room()).ifPresent(ri -> upg.onLevelLoaded(compactDim, ri));
+ });
+
}
}
diff --git a/src/main/java/dev/compactmods/machines/client/shader/CM4Shaders.java b/forge-main/src/main/java/dev/compactmods/machines/forge/client/CM4Shaders.java
similarity index 96%
rename from src/main/java/dev/compactmods/machines/client/shader/CM4Shaders.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/client/CM4Shaders.java
index 00d48510..50511ceb 100644
--- a/src/main/java/dev/compactmods/machines/client/shader/CM4Shaders.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/client/CM4Shaders.java
@@ -1,4 +1,4 @@
-package dev.compactmods.machines.client.shader;
+package dev.compactmods.machines.forge.client;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import net.minecraft.client.renderer.ShaderInstance;
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/client/ClientConfig.java b/forge-main/src/main/java/dev/compactmods/machines/forge/client/ClientConfig.java
new file mode 100644
index 00000000..2fa91e52
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/client/ClientConfig.java
@@ -0,0 +1,48 @@
+package dev.compactmods.machines.forge.client;
+
+import dev.compactmods.machines.api.core.Constants;
+import net.minecraftforge.common.ForgeConfigSpec;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.event.config.ModConfigEvent;
+
+@Mod.EventBusSubscriber(modid = Constants.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
+public class ClientConfig {
+
+ public static ForgeConfigSpec CONFIG;
+
+ private static ForgeConfigSpec.BooleanValue SHOW_LEGACY_ITEMS_IN_CREATIVE;
+ private static boolean showLegacyItems;
+
+ static {
+ generateConfig();
+ }
+
+ private static void generateConfig() {
+ ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
+
+ builder
+ .comment("Machines")
+ .push("machines");
+
+ SHOW_LEGACY_ITEMS_IN_CREATIVE = builder
+ .comment("Show the old machine items in creative/JEI?")
+ .comment("Requires re-joining the world/server to take effect.")
+ .define("showLegacyItems", false);
+
+ builder.pop();
+
+ CONFIG = builder.build();
+ }
+
+ public static boolean showLegacyItems() {
+ return showLegacyItems;
+ }
+
+ @SubscribeEvent
+ public static void onLoadedOrChanged(ModConfigEvent loading) {
+ if(loading.getConfig().getModId().equals(Constants.MOD_ID)) {
+ showLegacyItems = SHOW_LEGACY_ITEMS_IN_CREATIVE.get();
+ }
+ }
+}
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/client/ClientForgeBusEventHandler.java b/forge-main/src/main/java/dev/compactmods/machines/forge/client/ClientForgeBusEventHandler.java
new file mode 100644
index 00000000..02832438
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/client/ClientForgeBusEventHandler.java
@@ -0,0 +1,19 @@
+package dev.compactmods.machines.forge.client;
+
+import dev.compactmods.machines.api.core.Constants;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.event.TickEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.common.Mod;
+
+@Mod.EventBusSubscriber(modid = Constants.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT)
+public class ClientForgeBusEventHandler {
+ @SubscribeEvent
+ public static void onClientTick(final TickEvent.ClientTickEvent clientTick) {
+ if(clientTick.phase != TickEvent.Phase.END)
+ return;
+
+ if(RoomExitKeyMapping.MAPPING.consumeClick())
+ RoomExitKeyMapping.handle();
+ }
+}
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/client/ClientModBusEventHandler.java b/forge-main/src/main/java/dev/compactmods/machines/forge/client/ClientModBusEventHandler.java
new file mode 100644
index 00000000..a6742ce2
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/client/ClientModBusEventHandler.java
@@ -0,0 +1,64 @@
+package dev.compactmods.machines.forge.client;
+
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.forge.compat.curios.CuriosCompat;
+import dev.compactmods.machines.forge.machine.Machines;
+import dev.compactmods.machines.forge.machine.entity.UnboundCompactMachineEntity;
+import dev.compactmods.machines.forge.room.ui.MachineRoomScreen;
+import dev.compactmods.machines.forge.room.ui.RoomUserInterfaceRegistration;
+import dev.compactmods.machines.forge.tunnel.Tunnels;
+import dev.compactmods.machines.forge.tunnel.client.TunnelColors;
+import dev.compactmods.machines.machine.client.MachineColors;
+import net.minecraft.client.gui.screens.MenuScreens;
+import net.minecraft.core.BlockPos;
+import net.minecraft.world.level.BlockAndTintGetter;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.client.event.RegisterColorHandlersEvent;
+import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
+import net.minecraftforge.client.event.TextureStitchEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.ModList;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
+
+@Mod.EventBusSubscriber(modid = Constants.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
+public class ClientModBusEventHandler {
+
+ @SubscribeEvent
+ public static void onItemColors(final RegisterColorHandlersEvent.Item colors) {
+ colors.register(TunnelColors.ITEM, Tunnels.ITEM_TUNNEL.get());
+ colors.register(MachineColors.ITEM, Machines.BOUND_MACHINE_BLOCK_ITEM.get());
+ colors.register(MachineColors.ITEM, Machines.UNBOUND_MACHINE_BLOCK_ITEM.get());
+ }
+
+ @SubscribeEvent
+ public static void onBlockColors(final RegisterColorHandlersEvent.Block colors) {
+ colors.register(TunnelColors.BLOCK, Tunnels.BLOCK_TUNNEL_WALL.get());
+ colors.register(MachineColors.BLOCK, Machines.MACHINE_BLOCK.get());
+ colors.register(ClientModBusEventHandler::unboundMachineColor, Machines.UNBOUND_MACHINE_BLOCK.get());
+ }
+
+ private static int unboundMachineColor(BlockState state, BlockAndTintGetter level, BlockPos pos, int tintIndex) {
+ return switch (tintIndex) {
+ case 0 -> level.getBlockEntity(pos) instanceof UnboundCompactMachineEntity unbound ? unbound.getColor() : 0xFFFFFFFF;
+ default -> 0xFFFFFFFF;
+ };
+ }
+
+ @SubscribeEvent
+ public static void onKeybindRegistration(final RegisterKeyMappingsEvent evt) {
+ evt.register(RoomExitKeyMapping.MAPPING);
+ }
+
+ @SubscribeEvent
+ public static void onClientSetup(final FMLClientSetupEvent client) {
+ MenuScreens.register(RoomUserInterfaceRegistration.MACHINE_MENU.get(), MachineRoomScreen::new);
+ }
+
+ @SubscribeEvent
+ public static void onTextureStitch(final TextureStitchEvent.Pre stitch) {
+ if (ModList.get().isLoaded("curios"))
+ CuriosCompat.addTextures(stitch);
+ }
+}
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/client/RoomExitKeyMapping.java b/forge-main/src/main/java/dev/compactmods/machines/forge/client/RoomExitKeyMapping.java
new file mode 100644
index 00000000..f0b232a7
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/client/RoomExitKeyMapping.java
@@ -0,0 +1,39 @@
+package dev.compactmods.machines.forge.client;
+
+import com.mojang.blaze3d.platform.InputConstants;
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.dimension.CompactDimension;
+import dev.compactmods.machines.forge.network.CompactMachinesNet;
+import dev.compactmods.machines.forge.network.PlayerRequestedLeavePacket;
+import net.minecraft.Util;
+import net.minecraft.client.KeyMapping;
+import net.minecraft.client.Minecraft;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraftforge.client.settings.IKeyConflictContext;
+
+public class RoomExitKeyMapping {
+
+ public static final String CATEGORY = Util.makeDescriptionId("key.category", new ResourceLocation(Constants.MOD_ID, "general"));
+ public static final String NAME = Util.makeDescriptionId("key.mapping", new ResourceLocation(Constants.MOD_ID, "exit_room"));
+
+ public static final IKeyConflictContext CONFLICT_CONTEXT = new IKeyConflictContext() {
+ @Override
+ public boolean isActive() {
+ final var level = Minecraft.getInstance().level;
+ return level != null && level.dimension().equals(CompactDimension.LEVEL_KEY);
+ }
+
+ @Override
+ public boolean conflicts(IKeyConflictContext other) {
+ return this == other;
+ }
+ };
+
+ public static final KeyMapping MAPPING = new KeyMapping(NAME, CONFLICT_CONTEXT, InputConstants.UNKNOWN, CATEGORY);
+
+ public static void handle() {
+ final var level = Minecraft.getInstance().level;
+ if(level != null && level.dimension().equals(CompactDimension.LEVEL_KEY))
+ CompactMachinesNet.CHANNEL.sendToServer(new PlayerRequestedLeavePacket());
+ }
+}
diff --git a/src/main/java/dev/compactmods/machines/client/level/RenderingLevel.java b/forge-main/src/main/java/dev/compactmods/machines/forge/client/level/RenderingLevel.java
similarity index 93%
rename from src/main/java/dev/compactmods/machines/client/level/RenderingLevel.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/client/level/RenderingLevel.java
index f542184d..9732d097 100644
--- a/src/main/java/dev/compactmods/machines/client/level/RenderingLevel.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/client/level/RenderingLevel.java
@@ -1,7 +1,13 @@
-package dev.compactmods.machines.client.level;
+package dev.compactmods.machines.forge.client.level;
+import dev.compactmods.machines.client.level.EmptyLevelEntityGetter;
+import dev.compactmods.machines.client.level.FakeSpawnInfo;
import net.minecraft.client.Minecraft;
-import net.minecraft.core.*;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.Direction;
+import net.minecraft.core.Holder;
+import net.minecraft.core.Registry;
+import net.minecraft.core.RegistryAccess;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundSource;
@@ -27,8 +33,8 @@
import net.minecraft.world.scores.Scoreboard;
import net.minecraft.world.ticks.BlackholeTickAccess;
import net.minecraft.world.ticks.LevelTickAccess;
+import org.jetbrains.annotations.Nullable;
-import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
diff --git a/src/main/java/dev/compactmods/machines/client/level/TemplateChunk.java b/forge-main/src/main/java/dev/compactmods/machines/forge/client/level/TemplateChunk.java
similarity index 79%
rename from src/main/java/dev/compactmods/machines/client/level/TemplateChunk.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/client/level/TemplateChunk.java
index b96442fc..57b94fa1 100644
--- a/src/main/java/dev/compactmods/machines/client/level/TemplateChunk.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/client/level/TemplateChunk.java
@@ -1,28 +1,19 @@
-package dev.compactmods.machines.client.level;
+package dev.compactmods.machines.forge.client.level;
-import dev.compactmods.machines.CompactMachines;
-import dev.compactmods.machines.advancement.GenericAdvancementTriggerListener;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.ChunkPos;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
-import net.minecraft.world.level.block.entity.TickingBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.EmptyLevelChunk;
-import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraft.world.level.material.FluidState;
-import net.minecraft.world.ticks.TickContainerAccess;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
@@ -75,9 +66,9 @@ public void tick() {
this.tickers.forEach((pos, ticker) -> ticker.tick(this.getLevel(), pos, getBlockState(pos), tiles.get(pos)));
}
- @Nonnull
+ @NotNull
@Override
- public BlockState getBlockState(@Nonnull BlockPos pos) {
+ public BlockState getBlockState(@NotNull BlockPos pos) {
if (shouldShow.test(pos)) {
var state = blocksInChunk.get(pos);
if (state != null)
@@ -87,16 +78,16 @@ public BlockState getBlockState(@Nonnull BlockPos pos) {
return Blocks.VOID_AIR.defaultBlockState();
}
- @Nonnull
+ @NotNull
@Override
- public FluidState getFluidState(@Nonnull BlockPos pos) {
+ public FluidState getFluidState(@NotNull BlockPos pos) {
return getBlockState(pos).getFluidState();
}
@Nullable
@Override
- public BlockEntity getBlockEntity(@Nonnull BlockPos pos, @Nonnull EntityCreationType creationMode) {
+ public BlockEntity getBlockEntity(@NotNull BlockPos pos, @NotNull EntityCreationType creationMode) {
if (!shouldShow.test(pos))
return null;
return tiles.get(pos);
diff --git a/src/main/java/dev/compactmods/machines/client/level/TemplateChunkProvider.java b/forge-main/src/main/java/dev/compactmods/machines/forge/client/level/TemplateChunkProvider.java
similarity index 92%
rename from src/main/java/dev/compactmods/machines/client/level/TemplateChunkProvider.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/client/level/TemplateChunkProvider.java
index e7492524..71516ecc 100644
--- a/src/main/java/dev/compactmods/machines/client/level/TemplateChunkProvider.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/client/level/TemplateChunkProvider.java
@@ -1,10 +1,9 @@
-package dev.compactmods.machines.client.level;
+package dev.compactmods.machines.forge.client.level;
import com.mojang.datafixers.util.Pair;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.ChunkPos;
-import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.world.level.chunk.ChunkStatus;
@@ -12,9 +11,8 @@
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraft.world.level.lighting.LevelLightEngine;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -65,7 +63,7 @@ public Stream chunks() {
@Nullable
@Override
- public ChunkAccess getChunk(int chunkX, int chunkZ, @Nonnull ChunkStatus requiredStatus, boolean load)
+ public ChunkAccess getChunk(int chunkX, int chunkZ, @NotNull ChunkStatus requiredStatus, boolean load)
{
return chunks.computeIfAbsent(new ChunkPos(chunkX, chunkZ), p -> {
return new EmptyLevelChunk(world, p, world.getUncachedNoiseBiome(0, 0, 0));
@@ -77,7 +75,7 @@ public void tick(BooleanSupplier p_202162_, boolean p_202163_) {
}
- @Nonnull
+ @NotNull
@Override
public String gatherStats()
{
@@ -90,14 +88,14 @@ public int getLoadedChunksCount()
return 0;
}
- @Nonnull
+ @NotNull
@Override
public LevelLightEngine getLightEngine()
{
return lightManager;
}
- @Nonnull
+ @NotNull
@Override
public BlockGetter getLevel()
{
diff --git a/src/main/java/dev/compactmods/machines/client/render/RenderTypes.java b/forge-main/src/main/java/dev/compactmods/machines/forge/client/render/RenderTypes.java
similarity index 93%
rename from src/main/java/dev/compactmods/machines/client/render/RenderTypes.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/client/render/RenderTypes.java
index ead7c6a7..0c96b041 100644
--- a/src/main/java/dev/compactmods/machines/client/render/RenderTypes.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/client/render/RenderTypes.java
@@ -1,10 +1,10 @@
-package dev.compactmods.machines.client.render;
+package dev.compactmods.machines.forge.client.render;
import com.google.common.collect.ImmutableMap;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.blaze3d.vertex.VertexFormatElement;
import dev.compactmods.machines.api.core.Constants;
-import dev.compactmods.machines.client.shader.CM4Shaders;
+import dev.compactmods.machines.forge.client.CM4Shaders;
import net.minecraft.client.renderer.RenderStateShard;
import net.minecraft.client.renderer.RenderType;
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/command/ForgeCommands.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/ForgeCommands.java
new file mode 100644
index 00000000..48c15a55
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/ForgeCommands.java
@@ -0,0 +1,48 @@
+package dev.compactmods.machines.forge.command;
+
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.command.Commands;
+import dev.compactmods.machines.forge.Registries;
+import dev.compactmods.machines.forge.command.argument.RoomUpgradeArgument;
+import dev.compactmods.machines.forge.command.subcommand.CMEjectSubcommand;
+import dev.compactmods.machines.forge.command.subcommand.CMGiveMachineSubcommand;
+import dev.compactmods.machines.forge.command.subcommand.CMReaddDimensionSubcommand;
+import dev.compactmods.machines.forge.command.subcommand.CMRebindSubcommand;
+import dev.compactmods.machines.forge.command.subcommand.CMRoomUpgradeCommand;
+import dev.compactmods.machines.forge.command.subcommand.CMRoomsSubcommand;
+import dev.compactmods.machines.forge.command.subcommand.CMSummarySubcommand;
+import dev.compactmods.machines.forge.command.subcommand.CMTeleportSubcommand;
+import dev.compactmods.machines.forge.command.subcommand.CMUnbindSubcommand;
+import dev.compactmods.machines.forge.command.subcommand.SpawnSubcommand;
+import net.minecraft.commands.synchronization.ArgumentTypeInfos;
+import net.minecraft.commands.synchronization.SingletonArgumentInfo;
+import net.minecraftforge.event.RegisterCommandsEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.common.Mod;
+
+@Mod.EventBusSubscriber(modid = Constants.MOD_ID)
+public class ForgeCommands {
+
+ static {
+ Registries.COMMAND_ARGUMENT_TYPES.register("room_upgrade",
+ () -> ArgumentTypeInfos.registerByClass(RoomUpgradeArgument.class, SingletonArgumentInfo.contextFree(RoomUpgradeArgument::upgrade)));
+
+ var cm = Commands.getRoot();
+
+ cm.then(CMTeleportSubcommand.make());
+ cm.then(CMEjectSubcommand.make());
+ cm.then(CMSummarySubcommand.make());
+ cm.then(CMRebindSubcommand.make());
+ cm.then(CMUnbindSubcommand.make());
+ cm.then(CMReaddDimensionSubcommand.make());
+ cm.then(CMRoomsSubcommand.make());
+ cm.then(CMGiveMachineSubcommand.make());
+ cm.then(SpawnSubcommand.make());
+ cm.then(CMRoomUpgradeCommand.make());
+ }
+
+ @SubscribeEvent
+ public static void onCommandsRegister(final RegisterCommandsEvent event) {
+ event.getDispatcher().register(Commands.getRoot());
+ }
+}
diff --git a/src/main/java/dev/compactmods/machines/upgrade/command/RoomUpgradeArgument.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/argument/RoomUpgradeArgument.java
similarity index 64%
rename from src/main/java/dev/compactmods/machines/upgrade/command/RoomUpgradeArgument.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/command/argument/RoomUpgradeArgument.java
index c3ddfff1..621aa947 100644
--- a/src/main/java/dev/compactmods/machines/upgrade/command/RoomUpgradeArgument.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/argument/RoomUpgradeArgument.java
@@ -1,16 +1,14 @@
-package dev.compactmods.machines.upgrade.command;
+package dev.compactmods.machines.forge.command.argument;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
-import com.mojang.brigadier.suggestion.SuggestionProvider;
import dev.compactmods.machines.api.core.CMCommands;
-import dev.compactmods.machines.api.room.upgrade.RoomUpgrade;
-import dev.compactmods.machines.core.Registries;
+import dev.compactmods.machines.api.core.CMRegistryKeys;
+import dev.compactmods.machines.api.upgrade.RoomUpgrade;
+import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades;
import dev.compactmods.machines.i18n.TranslationUtil;
-import dev.compactmods.machines.upgrade.MachineRoomUpgrades;
import net.minecraft.commands.CommandSourceStack;
-import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.commands.arguments.ResourceKeyArgument;
import net.minecraft.resources.ResourceKey;
@@ -18,19 +16,16 @@
public class RoomUpgradeArgument extends ResourceKeyArgument {
- public static final SuggestionProvider SUGGESTOR = (ctx, builder) ->
- SharedSuggestionProvider.suggestResource(MachineRoomUpgrades.REGISTRY.get().getKeys(), builder);
-
private static final DynamicCommandExceptionType ERROR_INVALID_UPGRADE = new DynamicCommandExceptionType((a) ->
TranslationUtil.command(CMCommands.WRONG_DIMENSION));
private RoomUpgradeArgument() {
- super(MachineRoomUpgrades.REGISTRY.get().getRegistryKey());
+ super(CMRegistryKeys.ROOM_UPGRADES);
}
public static Optional getUpgrade(CommandContext stack, String argName) throws CommandSyntaxException {
final var UPGRADES = MachineRoomUpgrades.REGISTRY.get();
- ResourceKey resourcekey = getRegistryType(stack, argName, Registries.ROOM_UPGRADES_REG_KEY, ERROR_INVALID_UPGRADE);
+ ResourceKey resourcekey = getRegistryType(stack, argName, CMRegistryKeys.ROOM_UPGRADES, ERROR_INVALID_UPGRADE);
return Optional.ofNullable(UPGRADES.getValue(resourcekey.location()));
}
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/command/argument/Suggestors.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/argument/Suggestors.java
new file mode 100644
index 00000000..1644e068
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/argument/Suggestors.java
@@ -0,0 +1,29 @@
+package dev.compactmods.machines.forge.command.argument;
+
+import com.mojang.brigadier.suggestion.SuggestionProvider;
+import dev.compactmods.machines.api.room.registration.IRoomRegistration;
+import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades;
+import dev.compactmods.machines.room.graph.CompactRoomProvider;
+import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.commands.SharedSuggestionProvider;
+
+public class Suggestors {
+
+ public static final SuggestionProvider ROOM_UPGRADES = (ctx, builder) ->
+ SharedSuggestionProvider.suggestResource(MachineRoomUpgrades.REGISTRY.get().getKeys(), builder);
+
+ public static final SuggestionProvider OWNED_ROOM_CODES = (ctx, builder) -> {
+ final var server = ctx.getSource().getServer();
+ final var owner = ctx.getSource().getPlayerOrException();
+ final var roomProvider = CompactRoomProvider.instance(server);
+ final var codes = roomProvider.findByOwner(owner.getUUID()).map(IRoomRegistration::code);
+ return SharedSuggestionProvider.suggest(codes, builder);
+ };
+
+ public static final SuggestionProvider ROOM_CODES = (ctx, builder) -> {
+ final var server = ctx.getSource().getServer();
+ final var roomProvider = CompactRoomProvider.instance(server);
+ final var codes = roomProvider.allRooms().map(IRoomRegistration::code);
+ return SharedSuggestionProvider.suggest(codes, builder);
+ };
+}
diff --git a/src/main/java/dev/compactmods/machines/command/subcommand/CMEjectSubcommand.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMEjectSubcommand.java
similarity index 80%
rename from src/main/java/dev/compactmods/machines/command/subcommand/CMEjectSubcommand.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMEjectSubcommand.java
index 53abb877..d34766eb 100644
--- a/src/main/java/dev/compactmods/machines/command/subcommand/CMEjectSubcommand.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMEjectSubcommand.java
@@ -1,12 +1,12 @@
-package dev.compactmods.machines.command.subcommand;
+package dev.compactmods.machines.forge.command.subcommand;
import java.util.Collection;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
-import dev.compactmods.machines.room.RoomCapabilities;
+import dev.compactmods.machines.forge.util.ForgePlayerUtil;
+import dev.compactmods.machines.forge.room.capability.RoomCapabilities;
import dev.compactmods.machines.api.room.IRoomHistory;
-import dev.compactmods.machines.util.PlayerUtil;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
@@ -25,7 +25,7 @@ private static int execSpecificPlayer(CommandContext ctx) th
Collection ent = EntityArgument.getPlayers(ctx, "player");
ent.forEach(player -> {
player.getCapability(RoomCapabilities.ROOM_HISTORY).ifPresent(IRoomHistory::clear);
- PlayerUtil.teleportPlayerToRespawnOrOverworld(ctx.getSource().getServer(), player);
+ ForgePlayerUtil.teleportPlayerToRespawnOrOverworld(ctx.getSource().getServer(), player);
});
return 0;
@@ -35,7 +35,7 @@ private static int execExecutingPlayer(CommandContext ctx) t
final ServerPlayer player = ctx.getSource().getPlayerOrException();
player.getCapability(RoomCapabilities.ROOM_HISTORY).ifPresent(IRoomHistory::clear);
- PlayerUtil.teleportPlayerToRespawnOrOverworld(ctx.getSource().getServer(), player);
+ ForgePlayerUtil.teleportPlayerToRespawnOrOverworld(ctx.getSource().getServer(), player);
return 0;
}
diff --git a/src/main/java/dev/compactmods/machines/command/subcommand/CMGiveMachineSubcommand.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMGiveMachineSubcommand.java
similarity index 51%
rename from src/main/java/dev/compactmods/machines/command/subcommand/CMGiveMachineSubcommand.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMGiveMachineSubcommand.java
index 4e6cbe82..92a36e1a 100644
--- a/src/main/java/dev/compactmods/machines/command/subcommand/CMGiveMachineSubcommand.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMGiveMachineSubcommand.java
@@ -1,63 +1,56 @@
-package dev.compactmods.machines.command.subcommand;
+package dev.compactmods.machines.forge.command.subcommand;
+import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
-import dev.compactmods.machines.CompactMachines;
+import dev.compactmods.machines.forge.command.argument.Suggestors;
+import dev.compactmods.machines.forge.config.ServerConfig;
+import dev.compactmods.machines.forge.machine.item.BoundCompactMachineItem;
import dev.compactmods.machines.api.core.CMCommands;
import dev.compactmods.machines.api.core.Messages;
-import dev.compactmods.machines.command.argument.RoomPositionArgument;
-import dev.compactmods.machines.config.ServerConfig;
+import dev.compactmods.machines.LoggingUtil;
import dev.compactmods.machines.i18n.TranslationUtil;
-import dev.compactmods.machines.machine.CompactMachineItem;
-import dev.compactmods.machines.api.room.RoomSize;
-import dev.compactmods.machines.room.Rooms;
-import dev.compactmods.machines.room.exceptions.NonexistentRoomException;
+import dev.compactmods.machines.room.graph.CompactRoomProvider;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.world.item.ItemStack;
+import org.apache.logging.log4j.Logger;
public class CMGiveMachineSubcommand {
+ private static final Logger LOGGER = LoggingUtil.modLog();
+
public static LiteralArgumentBuilder make() {
final var subRoot = Commands.literal("give")
.requires(cs -> cs.hasPermission(ServerConfig.giveMachineLevel()));
subRoot.then(Commands.argument("player", EntityArgument.player())
- .then(Commands.argument("room", RoomPositionArgument.room())
- .executes(CMGiveMachineSubcommand::giveMachine)));
+ .then(Commands.argument("room", StringArgumentType.string())
+ .suggests(Suggestors.ROOM_CODES)
+ .executes(CMGiveMachineSubcommand::giveMachine)));
return subRoot;
}
private static int giveMachine(CommandContext ctx) throws CommandSyntaxException {
final var src = ctx.getSource();
- final var server = src.getServer();
-
final var player = EntityArgument.getPlayer(ctx, "player");
- final var roomPos = RoomPositionArgument.get(ctx, "room");
-
- if(!Rooms.exists(server, roomPos)) {
- CompactMachines.LOGGER.error("Error giving player a new machine block: room not found.");
- src.sendFailure(TranslationUtil.message(Messages.UNKNOWN_ROOM_CHUNK, "%s, %s".formatted(roomPos.x, roomPos.z)));
- return -1;
- }
-
- try {
- final RoomSize size = Rooms.sizeOf(server, roomPos);
-
- ItemStack newItem = new ItemStack(CompactMachineItem.getItemBySize(size));
- CompactMachineItem.setRoom(newItem, roomPos);
+ final var roomCode = StringArgumentType.getString(ctx, "room");
- if(!player.addItem(newItem)) {
+ var roomProvider = CompactRoomProvider.instance(src.getServer());
+ roomProvider.forRoom(roomCode).ifPresentOrElse(room -> {
+ ItemStack newItem = BoundCompactMachineItem.createForRoom(room);
+ if (!player.addItem(newItem)) {
src.sendFailure(TranslationUtil.command(CMCommands.CANNOT_GIVE_MACHINE));
} else {
src.sendSuccess(TranslationUtil.command(CMCommands.MACHINE_GIVEN, player.getDisplayName()), true);
}
- } catch (NonexistentRoomException e) {
- CompactMachines.LOGGER.fatal(e);
- }
+ }, () -> {
+ LOGGER.error("Error giving player a new machine block: room not found.");
+ src.sendFailure(TranslationUtil.message(Messages.UNKNOWN_ROOM_CHUNK, roomCode));
+ });
return 0;
}
diff --git a/src/main/java/dev/compactmods/machines/command/subcommand/CMReaddDimensionSubcommand.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMReaddDimensionSubcommand.java
similarity index 96%
rename from src/main/java/dev/compactmods/machines/command/subcommand/CMReaddDimensionSubcommand.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMReaddDimensionSubcommand.java
index 2e41b7c2..2579dba4 100644
--- a/src/main/java/dev/compactmods/machines/command/subcommand/CMReaddDimensionSubcommand.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMReaddDimensionSubcommand.java
@@ -1,4 +1,4 @@
-package dev.compactmods.machines.command.subcommand;
+package dev.compactmods.machines.forge.command.subcommand;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMRebindSubcommand.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMRebindSubcommand.java
new file mode 100644
index 00000000..6b62ee77
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMRebindSubcommand.java
@@ -0,0 +1,74 @@
+package dev.compactmods.machines.forge.command.subcommand;
+
+import com.mojang.brigadier.arguments.StringArgumentType;
+import com.mojang.brigadier.builder.LiteralArgumentBuilder;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import dev.compactmods.machines.api.core.CMCommands;
+import dev.compactmods.machines.api.dimension.CompactDimension;
+import dev.compactmods.machines.api.dimension.MissingDimensionException;
+import dev.compactmods.machines.forge.CompactMachines;
+import dev.compactmods.machines.forge.config.ServerConfig;
+import dev.compactmods.machines.forge.machine.entity.BoundCompactMachineBlockEntity;
+import dev.compactmods.machines.i18n.TranslationUtil;
+import dev.compactmods.machines.room.graph.CompactRoomProvider;
+import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph;
+import dev.compactmods.machines.tunnel.graph.traversal.TunnelMachineFilters;
+import net.minecraft.commands.CommandRuntimeException;
+import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.commands.Commands;
+import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
+import net.minecraft.server.level.ServerLevel;
+
+public class CMRebindSubcommand {
+
+ public static LiteralArgumentBuilder make() {
+ final var subRoot = Commands.literal("rebind")
+ .requires(cs -> cs.hasPermission(ServerConfig.rebindLevel()));
+
+ subRoot.then(Commands.argument("pos", BlockPosArgument.blockPos())
+ .then(Commands.argument("bindTo", StringArgumentType.string())
+ .executes(CMRebindSubcommand::doRebind)));
+
+ return subRoot;
+ }
+
+ private static int doRebind(CommandContext ctx) throws CommandSyntaxException {
+ final var server = ctx.getSource().getServer();
+ final var level = ctx.getSource().getLevel();
+ final ServerLevel compactDim;
+ try {
+ compactDim = CompactDimension.forServer(server);
+ } catch (MissingDimensionException e) {
+ throw new CommandRuntimeException(TranslationUtil.command(CMCommands.LEVEL_NOT_FOUND));
+ }
+
+ final var roomProvider = CompactRoomProvider.instance(compactDim);
+ final var rebindingMachine = BlockPosArgument.getLoadedBlockPos(ctx, "pos");
+ final var roomCode = StringArgumentType.getString(ctx, "bindTo");
+ roomProvider.forRoom(roomCode).ifPresentOrElse(targetRoom -> {
+ CompactMachines.LOGGER.debug("Binding machine at {} to room {}", rebindingMachine, targetRoom.code());
+
+ if (!(level.getBlockEntity(rebindingMachine) instanceof BoundCompactMachineBlockEntity machine)) {
+ CompactMachines.LOGGER.error("Refusing to rebind block at {}; block has invalid machine data.", rebindingMachine);
+ throw new CommandRuntimeException(TranslationUtil.command(CMCommands.NOT_A_MACHINE_BLOCK));
+ }
+
+ machine.connectedRoom().ifPresentOrElse(currentRoom -> {
+ final var currentRoomTunnels = TunnelConnectionGraph.forRoom(compactDim, currentRoom);
+ currentRoomTunnels.positions(TunnelMachineFilters.all(machine.getLevelPosition()))
+ .findFirst()
+ .ifPresent(match -> {
+ throw new CommandRuntimeException(TranslationUtil.command(CMCommands.NO_REBIND_TUNNEL_PRESENT, match));
+ });
+
+ // No tunnels - clear to rebind
+ machine.setConnectedRoom(roomCode);
+ }, () -> machine.setConnectedRoom(roomCode));
+ }, () -> {
+ CompactMachines.LOGGER.error("Cannot rebind to room {}; not registered.", roomCode);
+ });
+
+ return 0;
+ }
+}
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMRoomUpgradeCommand.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMRoomUpgradeCommand.java
new file mode 100644
index 00000000..1edd23cc
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMRoomUpgradeCommand.java
@@ -0,0 +1,150 @@
+package dev.compactmods.machines.forge.command.subcommand;
+
+import com.mojang.brigadier.builder.ArgumentBuilder;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import dev.compactmods.machines.forge.command.argument.Suggestors;
+import dev.compactmods.machines.forge.config.ServerConfig;
+import dev.compactmods.machines.forge.room.upgrade.RoomUpgradeManager;
+import dev.compactmods.machines.api.core.CMCommands;
+import dev.compactmods.machines.api.core.Messages;
+import dev.compactmods.machines.api.dimension.CompactDimension;
+import dev.compactmods.machines.api.upgrade.IUpgradeAppliedListener;
+import dev.compactmods.machines.api.upgrade.IUpgradeRemovedListener;
+import dev.compactmods.machines.forge.command.argument.RoomUpgradeArgument;
+import dev.compactmods.machines.i18n.TranslationUtil;
+import dev.compactmods.machines.room.graph.CompactRoomProvider;
+import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.commands.Commands;
+import net.minecraft.core.BlockPos;
+import net.minecraft.world.level.ChunkPos;
+
+public class CMRoomUpgradeCommand {
+
+ public static ArgumentBuilder make() {
+ final var root = Commands.literal("upgrades")
+ .requires(cs -> cs.hasPermission(ServerConfig.changeUpgrades()));
+
+ final var addRoot = Commands.literal("add");
+ final var addUpgRoot = Commands.argument("upgrade", RoomUpgradeArgument.upgrade())
+ .suggests(Suggestors.ROOM_UPGRADES)
+ .executes(CMRoomUpgradeCommand::addToCurrentRoom);
+
+ addUpgRoot.then(Commands.literal("current").executes(CMRoomUpgradeCommand::addToCurrentRoom));
+ // addUpgRoot.then(Commands.argument("room", RoomPositionArgument.room()).executes(CMUpgradeRoomCommand::addToSpecificRoom));
+ addRoot.then(addUpgRoot);
+ root.then(addRoot);
+
+ final var remRoot = Commands.literal("remove");
+ final var remUpgRoot = Commands.argument("upgrade", RoomUpgradeArgument.upgrade())
+ .suggests(Suggestors.ROOM_UPGRADES)
+ .executes(CMRoomUpgradeCommand::removeFromCurrentRoom);
+
+ remUpgRoot.then(Commands.literal("current").executes(CMRoomUpgradeCommand::removeFromCurrentRoom));
+ // remUpgRoot.then(Commands.argument("room", RoomPositionArgument.room()).executes(CMUpgradeRoomCommand::removeFromSpecificRoom));
+ remRoot.then(remUpgRoot);
+ root.then(remRoot);
+
+ return root;
+ }
+
+ private static int addToCurrentRoom(CommandContext ctx) throws CommandSyntaxException {
+ final var src = ctx.getSource();
+ final var compactDim = ctx.getSource().getLevel();
+ final var serv = ctx.getSource().getServer();
+
+ if (!compactDim.dimension().equals(CompactDimension.LEVEL_KEY))
+ return -1;
+
+ final var upg = RoomUpgradeArgument.getUpgrade(ctx, "upgrade");
+
+ if (upg.isEmpty())
+ return -1;
+
+ final var upgrade = upg.get();
+
+ final var execdAt = src.getPosition();
+ final var currChunk = new ChunkPos(new BlockPos((int) execdAt.x, (int) execdAt.y, (int) execdAt.z));
+
+ final var roomProvider = CompactRoomProvider.instance(compactDim);
+ final var manager = RoomUpgradeManager.get(compactDim);
+
+ if (!roomProvider.isRoomChunk(currChunk)) {
+ src.sendFailure(TranslationUtil.command(CMCommands.NOT_IN_COMPACT_DIMENSION));
+ return -1;
+ }
+
+ roomProvider.findByChunk(currChunk).ifPresentOrElse(room -> {
+ if (manager.hasUpgrade(room.code(), upgrade)) {
+ src.sendFailure(TranslationUtil.message(Messages.ALREADY_HAS_UPGRADE));
+ } else {
+ final var added = manager.addUpgrade(upgrade, room.code());
+
+ if (added) {
+ if(upgrade instanceof IUpgradeAppliedListener applied)
+ applied.onAdded(compactDim, room);
+
+ src.sendSuccess(TranslationUtil.message(Messages.UPGRADE_APPLIED), true);
+ } else {
+ src.sendFailure(TranslationUtil.message(Messages.UPGRADE_ADD_FAILED));
+ }
+ }
+ }, () -> src.sendFailure(TranslationUtil.command(CMCommands.NOT_IN_COMPACT_DIMENSION)));
+
+
+ return 0;
+ }
+
+ private static int addToSpecificRoom(CommandContext ctx) {
+ return 0;
+ }
+
+ private static int removeFromCurrentRoom(CommandContext ctx) throws CommandSyntaxException {
+ final var src = ctx.getSource();
+ final var compactDim = ctx.getSource().getLevel();
+
+ if (!compactDim.dimension().equals(CompactDimension.LEVEL_KEY))
+ return -1;
+
+ final var upg = RoomUpgradeArgument.getUpgrade(ctx, "upgrade");
+
+ if (upg.isEmpty())
+ return -1;
+
+ final var upgrade = upg.get();
+
+ final var execdAt = src.getPosition();
+ final var currChunk = new ChunkPos(new BlockPos((int) execdAt.x, (int) execdAt.y, (int) execdAt.z));
+
+ final var roomProvider = CompactRoomProvider.instance(compactDim);
+ final var manager = RoomUpgradeManager.get(compactDim);
+
+ if (!roomProvider.isRoomChunk(currChunk)) {
+ src.sendFailure(TranslationUtil.command(CMCommands.NOT_IN_COMPACT_DIMENSION));
+ return -1;
+ }
+
+ roomProvider.findByChunk(currChunk).ifPresentOrElse(room -> {
+ if (!manager.hasUpgrade(room.code(), upgrade)) {
+ src.sendFailure(TranslationUtil.message(Messages.UPGRADE_NOT_PRESENT));
+ } else {
+ final var removed = manager.removeUpgrade(upgrade, room.code());
+
+ if (removed) {
+ if(upgrade instanceof IUpgradeRemovedListener rem)
+ rem.onRemoved(compactDim, room);
+
+ src.sendSuccess(TranslationUtil.message(Messages.UPGRADE_REMOVED), true);
+ } else {
+ src.sendFailure(TranslationUtil.message(Messages.UPGRADE_REM_FAILED));
+ }
+ }
+ }, () -> src.sendFailure(TranslationUtil.command(CMCommands.NOT_IN_COMPACT_DIMENSION)));
+
+ return 0;
+ }
+
+ private static int removeFromSpecificRoom(CommandContext ctx) {
+ return 0;
+ }
+}
diff --git a/src/main/java/dev/compactmods/machines/command/subcommand/CMRoomsSubcommand.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMRoomsSubcommand.java
similarity index 56%
rename from src/main/java/dev/compactmods/machines/command/subcommand/CMRoomsSubcommand.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMRoomsSubcommand.java
index 425f386a..d721d7b1 100644
--- a/src/main/java/dev/compactmods/machines/command/subcommand/CMRoomsSubcommand.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMRoomsSubcommand.java
@@ -1,26 +1,23 @@
-package dev.compactmods.machines.command.subcommand;
+package dev.compactmods.machines.forge.command.subcommand;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
-import dev.compactmods.machines.CompactMachines;
+import dev.compactmods.machines.forge.machine.entity.BoundCompactMachineBlockEntity;
import dev.compactmods.machines.api.core.CMCommands;
import dev.compactmods.machines.api.core.Messages;
import dev.compactmods.machines.api.dimension.CompactDimension;
+import dev.compactmods.machines.api.machine.MachineTags;
import dev.compactmods.machines.i18n.TranslationUtil;
-import dev.compactmods.machines.machine.CompactMachineBlock;
-import dev.compactmods.machines.machine.CompactMachineBlockEntity;
-import dev.compactmods.machines.room.Rooms;
-import dev.compactmods.machines.room.data.CompactRoomData;
-import dev.compactmods.machines.room.exceptions.NonexistentRoomException;
-import net.minecraft.ChatFormatting;
+import dev.compactmods.machines.room.graph.CompactRoomProvider;
import net.minecraft.commands.CommandRuntimeException;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import net.minecraft.network.chat.Component;
-import net.minecraft.world.level.ChunkPos;
+
+import java.util.stream.Collectors;
public class CMRoomsSubcommand {
@@ -49,13 +46,17 @@ private static int fetchByMachineBlock(CommandContext ctx) t
final var block = BlockPosArgument.getLoadedBlockPos(ctx, "pos");
final var level = ctx.getSource().getLevel();
- if(!(level.getBlockState(block).getBlock() instanceof CompactMachineBlock b))
+ if (!level.getBlockState(block).is(MachineTags.BLOCK))
throw new CommandRuntimeException(TranslationUtil.command(CMCommands.NOT_A_MACHINE_BLOCK));
- if(level.getBlockEntity(block) instanceof CompactMachineBlockEntity be) {
- be.getConnectedRoom().ifPresent(room -> {
- final var m = TranslationUtil.message(Messages.MACHINE_ROOM_INFO, block, b.getSize(), room);
- ctx.getSource().sendSuccess(m, false);
+ if (level.getBlockEntity(block) instanceof BoundCompactMachineBlockEntity be) {
+ be.connectedRoom().ifPresent(roomCode -> {
+ CompactRoomProvider.instance(ctx.getSource().getServer())
+ .forRoom(roomCode)
+ .ifPresent(roomInfo -> {
+ final var m = TranslationUtil.message(Messages.MACHINE_ROOM_INFO, block, roomInfo.dimensions(), roomCode);
+ ctx.getSource().sendSuccess(m, false);
+ });
});
}
@@ -64,7 +65,6 @@ private static int fetchByMachineBlock(CommandContext ctx) t
private static int findByContainingPlayer(CommandContext ctx) throws CommandSyntaxException {
final var player = EntityArgument.getPlayer(ctx, "player");
- final var server = ctx.getSource().getServer();
final var playerChunk = player.chunkPosition();
final var playerLevel = player.getLevel();
@@ -73,32 +73,25 @@ private static int findByContainingPlayer(CommandContext ctx
throw new CommandRuntimeException(TranslationUtil.command(CMCommands.WRONG_DIMENSION));
}
- try {
- final var roomSize = Rooms.sizeOf(server, playerChunk);
- final var m = TranslationUtil.message(Messages.PLAYER_ROOM_INFO, player.getDisplayName(), playerChunk.toString(), roomSize);
- ctx.getSource().sendSuccess(m, false);
- } catch (NonexistentRoomException e) {
- CompactMachines.LOGGER.error("Player is inside an unregistered chunk ({}) in the compact world.", playerChunk, e);
- final var tc = Component.literal("%s, %s".formatted(playerChunk.x, playerChunk.z))
- .withStyle(ChatFormatting.RED);
-
- throw new CommandRuntimeException(TranslationUtil.message(Messages.UNKNOWN_ROOM_CHUNK, tc));
- }
+ final var m = TranslationUtil.message(Messages.PLAYER_ROOM_INFO, player.getDisplayName(), playerChunk.toString());
+ ctx.getSource().sendSuccess(m, false);
return 0;
}
public static int findByOwner(CommandContext ctx) throws CommandSyntaxException {
final var owner = EntityArgument.getPlayer(ctx, "owner");
- final var server = ctx.getSource().getServer();
- final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY);
-
- final var rooms = CompactRoomData.get(compactDim);
- rooms.streamRooms()
- .filter(r -> r.getOwner().equals(owner.getUUID()))
- .forEach(data -> {
- ctx.getSource().sendSuccess(Component.literal("Room: " + new ChunkPos(data.getCenter())), false);
- });
+ final var source = ctx.getSource();
+ final var graph = CompactRoomProvider.instance(source.getServer());
+
+ // TODO Localization
+ final var owned = graph.findByOwner(owner.getUUID()).collect(Collectors.toSet());
+ if (owned.isEmpty()) {
+ source.sendSuccess(Component.literal("No rooms found."), false);
+ } else {
+ owned.forEach(roomInfo -> source.sendSuccess(Component.literal("Room: " + roomInfo.code()), false));
+ }
+
return 0;
}
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMSummarySubcommand.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMSummarySubcommand.java
new file mode 100644
index 00000000..017caf48
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMSummarySubcommand.java
@@ -0,0 +1,55 @@
+package dev.compactmods.machines.forge.command.subcommand;
+
+import com.mojang.brigadier.builder.ArgumentBuilder;
+import com.mojang.brigadier.context.CommandContext;
+import dev.compactmods.machines.api.core.CMCommands;
+import dev.compactmods.machines.api.dimension.CompactDimension;
+import dev.compactmods.machines.api.dimension.MissingDimensionException;
+import dev.compactmods.machines.i18n.TranslationUtil;
+import dev.compactmods.machines.machine.graph.DimensionMachineGraph;
+import dev.compactmods.machines.room.graph.CompactRoomProvider;
+import net.minecraft.ChatFormatting;
+import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.commands.Commands;
+import net.minecraft.server.level.ServerLevel;
+
+import java.util.stream.LongStream;
+
+public class CMSummarySubcommand {
+ public static ArgumentBuilder make() {
+ return Commands.literal("summary")
+ .executes(CMSummarySubcommand::exec);
+ }
+
+ private static int exec(CommandContext ctx) {
+ var src = ctx.getSource();
+ var serv = src.getServer();
+
+ try {
+ ServerLevel compactLevel = CompactDimension.forServer(serv);
+ src.sendSuccess(TranslationUtil.command(CMCommands.LEVEL_REGISTERED).withStyle(ChatFormatting.DARK_GREEN), false);
+
+ final var ls = LongStream.builder();
+ serv.getAllLevels().forEach(sl -> {
+ final var machineData = DimensionMachineGraph.forDimension(sl);
+ long numRegistered = machineData.machines().count();
+
+ if(numRegistered > 0) {
+ src.sendSuccess(TranslationUtil.command(CMCommands.MACHINE_REG_DIM, sl.dimension().location().toString(), numRegistered), false);
+ ls.add(numRegistered);
+ }
+ });
+
+ long grandTotal = ls.build().sum();
+ src.sendSuccess(TranslationUtil.command(CMCommands.MACHINE_REG_TOTAL, grandTotal).withStyle(ChatFormatting.GOLD), false);
+
+ final var roomInfo = CompactRoomProvider.instance(compactLevel);
+ src.sendSuccess(TranslationUtil.command(CMCommands.ROOM_REG_COUNT, roomInfo.count()), false);
+ } catch (MissingDimensionException e) {
+ src.sendSuccess(TranslationUtil.command(CMCommands.LEVEL_NOT_FOUND).withStyle(ChatFormatting.RED), false);
+ }
+
+
+ return 0;
+ }
+}
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMTeleportSubcommand.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMTeleportSubcommand.java
new file mode 100644
index 00000000..61c55920
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMTeleportSubcommand.java
@@ -0,0 +1,76 @@
+package dev.compactmods.machines.forge.command.subcommand;
+
+import com.mojang.brigadier.arguments.StringArgumentType;
+import com.mojang.brigadier.builder.LiteralArgumentBuilder;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import dev.compactmods.machines.LoggingUtil;
+import dev.compactmods.machines.api.core.Messages;
+import dev.compactmods.machines.api.dimension.MissingDimensionException;
+import dev.compactmods.machines.forge.command.argument.Suggestors;
+import dev.compactmods.machines.forge.config.ServerConfig;
+import dev.compactmods.machines.forge.room.RoomHelper;
+import dev.compactmods.machines.i18n.TranslationUtil;
+import dev.compactmods.machines.room.exceptions.NonexistentRoomException;
+import dev.compactmods.machines.room.graph.CompactRoomProvider;
+import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.commands.Commands;
+import net.minecraft.commands.arguments.EntityArgument;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerPlayer;
+import org.apache.logging.log4j.Logger;
+
+public class CMTeleportSubcommand {
+
+ private static final Logger LOGGER = LoggingUtil.modLog();
+
+ public static LiteralArgumentBuilder make() {
+ final var subRoot = Commands.literal("tp")
+ .requires(cs -> cs.hasPermission(ServerConfig.giveMachineLevel()));
+
+ subRoot.then(Commands.argument("room", StringArgumentType.string())
+ .suggests(Suggestors.ROOM_CODES)
+ .executes(CMTeleportSubcommand::teleportExecutor));
+
+ subRoot.then(Commands.argument("player", EntityArgument.player())
+ .then(Commands.argument("room", StringArgumentType.string())
+ .suggests(Suggestors.ROOM_CODES)
+ .executes(CMTeleportSubcommand::teleportSpecificPlayer)));
+
+ return subRoot;
+ }
+
+ private static void teleportToRoom(CommandSourceStack src, MinecraftServer server, ServerPlayer player, String roomCode) {
+ var roomProvider = CompactRoomProvider.instance(src.getServer());
+ roomProvider.forRoom(roomCode).ifPresentOrElse(room -> {
+ try {
+ RoomHelper.teleportPlayerIntoRoom(server, player, room);
+ } catch (MissingDimensionException | NonexistentRoomException e) {
+ throw new RuntimeException(e);
+ }
+ }, () -> {
+ LOGGER.error("Error teleporting player into room: room not found.");
+ src.sendFailure(TranslationUtil.message(Messages.UNKNOWN_ROOM_CHUNK, roomCode));
+ });
+ }
+
+ private static int teleportExecutor(CommandContext ctx) throws CommandSyntaxException {
+ final var src = ctx.getSource();
+ final var server = src.getServer();
+ final var player = src.getPlayerOrException();
+ final var roomCode = StringArgumentType.getString(ctx, "room");
+
+ teleportToRoom(src, server, player, roomCode);
+ return 0;
+ }
+
+ private static int teleportSpecificPlayer(CommandContext ctx) throws CommandSyntaxException {
+ final var src = ctx.getSource();
+ final var server = src.getServer();
+ final var player = EntityArgument.getPlayer(ctx, "player");
+ final var roomCode = StringArgumentType.getString(ctx, "room");
+
+ teleportToRoom(src, server, player, roomCode);
+ return 0;
+ }
+}
diff --git a/src/main/java/dev/compactmods/machines/command/subcommand/CMUnbindSubcommand.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMUnbindSubcommand.java
similarity index 72%
rename from src/main/java/dev/compactmods/machines/command/subcommand/CMUnbindSubcommand.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMUnbindSubcommand.java
index 033c91f8..9db52e91 100644
--- a/src/main/java/dev/compactmods/machines/command/subcommand/CMUnbindSubcommand.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/CMUnbindSubcommand.java
@@ -1,15 +1,16 @@
-package dev.compactmods.machines.command.subcommand;
+package dev.compactmods.machines.forge.command.subcommand;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
-import dev.compactmods.machines.CompactMachines;
+import dev.compactmods.machines.forge.CompactMachines;
+import dev.compactmods.machines.forge.config.ServerConfig;
+import dev.compactmods.machines.forge.machine.entity.BoundCompactMachineBlockEntity;
+import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph;
import dev.compactmods.machines.api.core.CMCommands;
import dev.compactmods.machines.api.dimension.CompactDimension;
-import dev.compactmods.machines.config.ServerConfig;
+import dev.compactmods.machines.tunnel.graph.traversal.TunnelMachineFilters;
import dev.compactmods.machines.i18n.TranslationUtil;
-import dev.compactmods.machines.machine.CompactMachineBlockEntity;
-import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph;
import net.minecraft.commands.CommandRuntimeException;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
@@ -37,17 +38,18 @@ private static int doUnbind(CommandContext ctx) throws Comma
final var rebindingMachine = BlockPosArgument.getLoadedBlockPos(ctx, "pos");
- if(!(level.getBlockEntity(rebindingMachine) instanceof CompactMachineBlockEntity machine)) {
+ if (!(level.getBlockEntity(rebindingMachine) instanceof BoundCompactMachineBlockEntity machine)) {
CompactMachines.LOGGER.error("Refusing to rebind block at {}; block has invalid machine data.", rebindingMachine);
throw new CommandRuntimeException(TranslationUtil.command(CMCommands.NOT_A_MACHINE_BLOCK));
}
- machine.getConnectedRoom().ifPresentOrElse(currentRoom -> {
+ machine.connectedRoom().ifPresentOrElse(currentRoom -> {
final var currentRoomTunnels = TunnelConnectionGraph.forRoom(compactDim, currentRoom);
- final var firstTunnel = currentRoomTunnels.getConnections(machine.getLevelPosition()).findFirst();
- firstTunnel.ifPresent(ft -> {
- throw new CommandRuntimeException(TranslationUtil.command(CMCommands.NO_REBIND_TUNNEL_PRESENT, ft));
- });
+ currentRoomTunnels.positions(TunnelMachineFilters.all(machine.getLevelPosition()))
+ .findFirst()
+ .ifPresent(ft -> {
+ throw new CommandRuntimeException(TranslationUtil.command(CMCommands.NO_REBIND_TUNNEL_PRESENT, ft));
+ });
machine.disconnect();
}, () -> {
diff --git a/src/main/java/dev/compactmods/machines/command/subcommand/SpawnSubcommand.java b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/SpawnSubcommand.java
similarity index 51%
rename from src/main/java/dev/compactmods/machines/command/subcommand/SpawnSubcommand.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/SpawnSubcommand.java
index 271d662b..c2ffc53d 100644
--- a/src/main/java/dev/compactmods/machines/command/subcommand/SpawnSubcommand.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/command/subcommand/SpawnSubcommand.java
@@ -1,13 +1,16 @@
-package dev.compactmods.machines.command.subcommand;
+package dev.compactmods.machines.forge.command.subcommand;
+import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
+import dev.compactmods.machines.forge.config.ServerConfig;
import dev.compactmods.machines.api.core.CMCommands;
-import dev.compactmods.machines.command.argument.RoomPositionArgument;
-import dev.compactmods.machines.config.ServerConfig;
+import dev.compactmods.machines.api.core.Messages;
+import dev.compactmods.machines.api.dimension.CompactDimension;
+import dev.compactmods.machines.api.dimension.MissingDimensionException;
import dev.compactmods.machines.i18n.TranslationUtil;
-import dev.compactmods.machines.room.Rooms;
import dev.compactmods.machines.room.exceptions.NonexistentRoomException;
+import dev.compactmods.machines.room.graph.CompactRoomProvider;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
@@ -18,8 +21,8 @@ public class SpawnSubcommand {
final var resetSpawn = Commands.literal("reset")
.requires(cs -> cs.hasPermission(ServerConfig.changeRoomSpawn()))
- .then(Commands.argument("room", RoomPositionArgument.room())
- .executes(SpawnSubcommand::resetRoomSpawn));
+ .then(Commands.argument("room", StringArgumentType.string())
+ .executes(SpawnSubcommand::resetRoomSpawn));
spawnRoot.then(resetSpawn);
@@ -29,16 +32,21 @@ public class SpawnSubcommand {
private static int resetRoomSpawn(CommandContext ctx) {
final var src = ctx.getSource();
final var serv = src.getServer();
- final var roomPos = RoomPositionArgument.get(ctx, "room");
+ final var roomCode = StringArgumentType.getString(ctx, "room");
try {
- Rooms.resetSpawn(serv, roomPos);
- src.sendSuccess(TranslationUtil.command(CMCommands.SPAWN_CHANGED_SUCCESSFULLY, "%s, %s".formatted(roomPos.x, roomPos.z)), true);
+ final var compactDim = CompactDimension.forServer(serv);
+ final var roomProvider = CompactRoomProvider.instance(compactDim);
+
+ roomProvider.resetSpawn(roomCode);
+ src.sendSuccess(TranslationUtil.command(CMCommands.SPAWN_CHANGED_SUCCESSFULLY, "%s".formatted(roomCode)), true);
return 0;
+ } catch (MissingDimensionException e) {
+ src.sendFailure(TranslationUtil.command(Messages.UNREGISTERED_CM_DIM));
+ return -1;
} catch (NonexistentRoomException e) {
- src.sendFailure(TranslationUtil.command(CMCommands.ROOM_NOT_FOUND, "%s, %s".formatted(roomPos.x, roomPos.z)));
+ src.sendFailure(TranslationUtil.command(CMCommands.ROOM_NOT_FOUND, roomCode));
return -1;
}
}
-
}
diff --git a/src/main/java/dev/compactmods/machines/compat/InterModCompat.java b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/InterModCompat.java
similarity index 66%
rename from src/main/java/dev/compactmods/machines/compat/InterModCompat.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/compat/InterModCompat.java
index b7764014..6595725b 100644
--- a/src/main/java/dev/compactmods/machines/compat/InterModCompat.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/InterModCompat.java
@@ -1,8 +1,9 @@
-package dev.compactmods.machines.compat;
+package dev.compactmods.machines.forge.compat;
import dev.compactmods.machines.api.core.Constants;
-import dev.compactmods.machines.compat.carryon.CarryOnCompat;
-import dev.compactmods.machines.compat.theoneprobe.TheOneProbeCompat;
+import dev.compactmods.machines.forge.compat.carryon.CarryOnCompat;
+import dev.compactmods.machines.forge.compat.curios.CuriosCompat;
+import dev.compactmods.machines.forge.compat.theoneprobe.TheOneProbeCompat;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.common.Mod;
@@ -18,5 +19,8 @@ public static void enqueueCompatMessages(final InterModEnqueueEvent evt) {
if(ModList.get().isLoaded("carryon"))
CarryOnCompat.sendIMC();
+
+ if(ModList.get().isLoaded("curios"))
+ CuriosCompat.sendIMC();
}
}
diff --git a/src/main/java/dev/compactmods/machines/compat/carryon/CarryOnCompat.java b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/carryon/CarryOnCompat.java
similarity index 54%
rename from src/main/java/dev/compactmods/machines/compat/carryon/CarryOnCompat.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/compat/carryon/CarryOnCompat.java
index 118abe62..b0965937 100644
--- a/src/main/java/dev/compactmods/machines/compat/carryon/CarryOnCompat.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/carryon/CarryOnCompat.java
@@ -1,6 +1,7 @@
-package dev.compactmods.machines.compat.carryon;
+package dev.compactmods.machines.forge.compat.carryon;
-import dev.compactmods.machines.machine.CompactMachineBlock;
+import dev.compactmods.machines.forge.machine.Machines;
+import dev.compactmods.machines.forge.machine.block.LegacySizedCompactMachineBlock;
import dev.compactmods.machines.api.room.RoomSize;
import net.minecraftforge.fml.InterModComms;
import net.minecraftforge.registries.ForgeRegistries;
@@ -9,14 +10,19 @@ public class CarryOnCompat {
private static final String MOD_ID = "carryon";
+ @SuppressWarnings("removal")
public static void sendIMC() {
// Denies the machine blocks from being picked up by CarryOn users.
// Prevents duplication of data on block movement.
final var blockReg = ForgeRegistries.BLOCKS;
for(var size : RoomSize.values()) {
- final var regName = blockReg.getKey(CompactMachineBlock.getBySize(size));
+ final var regName = blockReg.getKey(LegacySizedCompactMachineBlock.getBySize(size));
if(regName != null)
InterModComms.sendTo(MOD_ID, "blacklistBlock", regName::toString);
}
+
+ final var machineBlockNew = blockReg.getKey(Machines.MACHINE_BLOCK.get());
+ if(machineBlockNew != null)
+ InterModComms.sendTo(MOD_ID, "blacklistBlock", machineBlockNew::toString);
}
}
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/compat/curios/CuriosCompat.java b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/curios/CuriosCompat.java
new file mode 100644
index 00000000..27df3757
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/curios/CuriosCompat.java
@@ -0,0 +1,40 @@
+package dev.compactmods.machines.forge.compat.curios;
+
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.shrinking.PSDTags;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.entity.LivingEntity;
+import net.minecraft.world.item.ItemStack;
+import net.minecraftforge.client.event.TextureStitchEvent;
+import net.minecraftforge.fml.InterModComms;
+import top.theillusivec4.curios.api.CuriosApi;
+import top.theillusivec4.curios.api.SlotTypeMessage;
+
+import javax.annotation.Nonnull;
+
+public class CuriosCompat {
+
+ private static final ResourceLocation CURIO_TEXTURE = new ResourceLocation(Constants.MOD_ID, "curios/empty_psd");
+
+
+ public static void sendIMC() {
+ InterModComms.sendTo(CuriosApi.MODID, SlotTypeMessage.REGISTER_TYPE, () -> new SlotTypeMessage.Builder("psd")
+ .size(1)
+ .icon(CURIO_TEXTURE)
+ .build());
+ }
+
+ private static boolean isPsd(ItemStack stack) {
+ return stack.is(PSDTags.ITEM);
+ }
+
+ public static void addTextures(final TextureStitchEvent.Pre stitch) {
+ stitch.addSprite(CURIO_TEXTURE);
+ }
+
+ public static boolean hasPsdCurio(@Nonnull LivingEntity ent) {
+ return CuriosApi.getCuriosHelper()
+ .findFirstCurio(ent, CuriosCompat::isPsd)
+ .isPresent();
+ }
+}
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/compat/jei/CompactMachinesJeiPlugin.java b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/jei/CompactMachinesJeiPlugin.java
new file mode 100644
index 00000000..33c77703
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/jei/CompactMachinesJeiPlugin.java
@@ -0,0 +1,69 @@
+package dev.compactmods.machines.forge.compat.jei;
+
+import dev.compactmods.machines.api.core.Constants;
+import dev.compactmods.machines.api.core.JeiInfo;
+import dev.compactmods.machines.api.room.Rooms;
+import dev.compactmods.machines.forge.machine.Machines;
+import dev.compactmods.machines.forge.machine.item.LegacyCompactMachineItem;
+import dev.compactmods.machines.forge.machine.item.MachineItemUtil;
+import dev.compactmods.machines.forge.machine.item.UnboundCompactMachineItem;
+import dev.compactmods.machines.forge.shrinking.Shrinking;
+import dev.compactmods.machines.forge.tunnel.Tunnels;
+import dev.compactmods.machines.i18n.TranslationUtil;
+import mezz.jei.api.IModPlugin;
+import mezz.jei.api.JeiPlugin;
+import mezz.jei.api.constants.VanillaTypes;
+import mezz.jei.api.registration.IRecipeRegistration;
+import mezz.jei.api.registration.ISubtypeRegistration;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.item.ItemStack;
+import net.minecraftforge.registries.ForgeRegistries;
+import net.minecraftforge.server.ServerLifecycleHooks;
+
+import java.util.stream.Collectors;
+
+@JeiPlugin
+public class CompactMachinesJeiPlugin implements IModPlugin {
+ @Override
+ public ResourceLocation getPluginUid() {
+ return new ResourceLocation(Constants.MOD_ID, "main");
+ }
+
+ @Override
+ public void registerRecipes(IRecipeRegistration registration) {
+ final var ingManager = registration.getIngredientManager();
+
+ registration.addIngredientInfo(
+ UnboundCompactMachineItem.unbound(),
+ VanillaTypes.ITEM_STACK,
+ TranslationUtil.jeiInfo(JeiInfo.MACHINE));
+
+ // Add all known template JEI infos
+ Rooms.getTemplates(ServerLifecycleHooks.getCurrentServer())
+ .entrySet()
+ .stream()
+ .map(t -> UnboundCompactMachineItem.forTemplate(t.getKey().location(), t.getValue()))
+ .forEach(t -> registration.addIngredientInfo(t, VanillaTypes.ITEM_STACK, TranslationUtil.jeiInfo(JeiInfo.MACHINE)));
+
+ registration.addIngredientInfo(
+ new ItemStack(Shrinking.PERSONAL_SHRINKING_DEVICE.get()),
+ VanillaTypes.ITEM_STACK,
+ TranslationUtil.jeiInfo(JeiInfo.SHRINKING_DEVICE));
+
+ //noinspection removal Will be removing once 5.3 or 6.0 drops
+ final var allLegacyMachines = ForgeRegistries.ITEMS.tags()
+ .getTag(LegacyCompactMachineItem.TAG)
+ .stream()
+ .map(ItemStack::new)
+ .collect(Collectors.toSet());
+
+ ingManager.removeIngredientsAtRuntime(VanillaTypes.ITEM_STACK, allLegacyMachines);
+ }
+
+ @Override
+ public void registerItemSubtypes(ISubtypeRegistration registration) {
+ registration.useNbtForSubtypes(Tunnels.ITEM_TUNNEL.get());
+ registration.registerSubtypeInterpreter(Machines.UNBOUND_MACHINE_BLOCK_ITEM.get(),
+ (ingredient, context) -> MachineItemUtil.getTemplateId(ingredient).toString());
+ }
+}
diff --git a/src/main/java/dev/compactmods/machines/compat/theoneprobe/TheOneProbeCompat.java b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/TheOneProbeCompat.java
similarity index 77%
rename from src/main/java/dev/compactmods/machines/compat/theoneprobe/TheOneProbeCompat.java
rename to forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/TheOneProbeCompat.java
index 841c3ed7..327747c3 100644
--- a/src/main/java/dev/compactmods/machines/compat/theoneprobe/TheOneProbeCompat.java
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/TheOneProbeCompat.java
@@ -1,4 +1,4 @@
-package dev.compactmods.machines.compat.theoneprobe;
+package dev.compactmods.machines.forge.compat.theoneprobe;
import net.minecraftforge.fml.InterModComms;
diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/TheOneProbeMain.java b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/TheOneProbeMain.java
new file mode 100644
index 00000000..0876b0f5
--- /dev/null
+++ b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/TheOneProbeMain.java
@@ -0,0 +1,40 @@
+package dev.compactmods.machines.forge.compat.theoneprobe;
+
+import dev.compactmods.machines.forge.compat.theoneprobe.elements.PlayerFaceElement;
+import dev.compactmods.machines.forge.compat.theoneprobe.overrides.CompactMachineNameOverride;
+import dev.compactmods.machines.forge.compat.theoneprobe.providers.CompactMachineProvider;
+import dev.compactmods.machines.forge.compat.theoneprobe.providers.TunnelProvider;
+import mcjty.theoneprobe.api.IElement;
+import mcjty.theoneprobe.api.IElementFactory;
+import mcjty.theoneprobe.api.ITheOneProbe;
+import net.minecraft.network.FriendlyByteBuf;
+import net.minecraft.resources.ResourceLocation;
+
+import java.util.function.Function;
+
+public class TheOneProbeMain implements Function