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 +Discord -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 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 { + static ITheOneProbe PROBE; + + @Override + public Void apply(Object o) { + PROBE = (ITheOneProbe) o; + PROBE.registerBlockDisplayOverride(new CompactMachineNameOverride()); + PROBE.registerProvider(new CompactMachineProvider()); + PROBE.registerProvider(new TunnelProvider()); + + PROBE.registerElementFactory(new IElementFactory() { + @Override + public IElement createElement(FriendlyByteBuf buffer) { + return new PlayerFaceElement(buffer.readGameProfile()); + } + + @Override + public ResourceLocation getId() { + return PlayerFaceElement.ID; + } + }); + + return null; + } + +} diff --git a/src/main/java/dev/compactmods/machines/compat/theoneprobe/elements/MachineTunnelElement.java b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/elements/MachineTunnelElement.java similarity index 90% rename from src/main/java/dev/compactmods/machines/compat/theoneprobe/elements/MachineTunnelElement.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/elements/MachineTunnelElement.java index 395e951c..8da5eed6 100644 --- a/src/main/java/dev/compactmods/machines/compat/theoneprobe/elements/MachineTunnelElement.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/elements/MachineTunnelElement.java @@ -1,4 +1,4 @@ -package dev.compactmods.machines.compat.theoneprobe.elements; +package dev.compactmods.machines.forge.compat.theoneprobe.elements; import com.mojang.blaze3d.vertex.PoseStack; import mcjty.theoneprobe.api.IElement; diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/elements/PlayerFaceElement.java b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/elements/PlayerFaceElement.java new file mode 100644 index 00000000..c62a2cdc --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/elements/PlayerFaceElement.java @@ -0,0 +1,47 @@ +package dev.compactmods.machines.forge.compat.theoneprobe.elements; + +import com.mojang.authlib.GameProfile; +import com.mojang.blaze3d.vertex.PoseStack; +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.client.PlayerFaceRenderer; +import mcjty.theoneprobe.api.IElement; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; + +public class PlayerFaceElement implements IElement { + public static final ResourceLocation ID = new ResourceLocation(Constants.MOD_ID, "player_face"); + private final GameProfile player; + + public PlayerFaceElement(GameProfile player) { + this.player = player; + } + + @Override + public void render(PoseStack poseStack, int x, int y) { + PlayerFaceRenderer.render(player, poseStack, x, y); + } + + @Override + public int getWidth() { + return 16; + } + + @Override + public int getHeight() { + return 16; + } + + @Override + public void toBytes(FriendlyByteBuf friendlyByteBuf) { + friendlyByteBuf.writeGameProfile(player); + } + + @Override + public ResourceLocation getID() { + return ID; + } + + public GameProfile player() { + return player; + } +} diff --git a/src/main/java/dev/compactmods/machines/compat/theoneprobe/overrides/CompactMachineNameOverride.java b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/overrides/CompactMachineNameOverride.java similarity index 69% rename from src/main/java/dev/compactmods/machines/compat/theoneprobe/overrides/CompactMachineNameOverride.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/overrides/CompactMachineNameOverride.java index 39418d28..6797488a 100644 --- a/src/main/java/dev/compactmods/machines/compat/theoneprobe/overrides/CompactMachineNameOverride.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/overrides/CompactMachineNameOverride.java @@ -1,14 +1,20 @@ -package dev.compactmods.machines.compat.theoneprobe.overrides; +package dev.compactmods.machines.forge.compat.theoneprobe.overrides; -import dev.compactmods.machines.machine.CompactMachineBlock; -import dev.compactmods.machines.machine.CompactMachineBlockEntity; -import dev.compactmods.machines.room.Rooms; +import dev.compactmods.machines.api.core.CMTags; +import dev.compactmods.machines.forge.machine.entity.BoundCompactMachineBlockEntity; +import dev.compactmods.machines.forge.machine.item.BoundCompactMachineItem; +import dev.compactmods.machines.forge.room.Rooms; import dev.compactmods.machines.room.exceptions.NonexistentRoomException; import mcjty.theoneprobe.Tools; -import mcjty.theoneprobe.api.*; +import mcjty.theoneprobe.api.CompoundText; +import mcjty.theoneprobe.api.ElementAlignment; +import mcjty.theoneprobe.api.IBlockDisplayOverride; +import mcjty.theoneprobe.api.IProbeHitData; +import mcjty.theoneprobe.api.IProbeInfo; +import mcjty.theoneprobe.api.ProbeMode; +import mcjty.theoneprobe.api.TextStyleClass; import mcjty.theoneprobe.config.Config; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; @@ -16,13 +22,13 @@ public class CompactMachineNameOverride implements IBlockDisplayOverride { @Override public boolean overrideStandardInfo(ProbeMode mode, IProbeInfo probeInfo, Player player, Level level, BlockState blockState, IProbeHitData hitData) { - if(blockState.getBlock() instanceof CompactMachineBlock) { - if (level.getBlockEntity(hitData.getPos()) instanceof CompactMachineBlockEntity mach) { - final var cr = mach.getConnectedRoom(); + if(blockState.is(CMTags.MACHINE_BLOCK)) { + if (level.getBlockEntity(hitData.getPos()) instanceof BoundCompactMachineBlockEntity mach) { + final var cr = mach.connectedRoom(); if(cr.isEmpty()) return false; - cr.ifPresent(room -> { + cr.ifPresent(roomCode -> { final var pickBlock = hitData.getPickBlock(); if (!pickBlock.isEmpty()) { final var config = Config.getRealConfig(); @@ -31,9 +37,9 @@ public boolean overrideStandardInfo(ProbeMode mode, IProbeInfo probeInfo, Player Component roomName; try { - roomName = Rooms.getRoomName(level.getServer(), room) + roomName = Rooms.getRoomName(level.getServer(), roomCode) .map(Component::literal) - .orElse((MutableComponent) pickBlock.getHoverName()); + .orElse(BoundCompactMachineItem.name(pickBlock).copy()); } catch (NonexistentRoomException e) { roomName = pickBlock.getHoverName(); } diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/providers/CompactMachineProvider.java b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/providers/CompactMachineProvider.java new file mode 100644 index 00000000..9b135b79 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/providers/CompactMachineProvider.java @@ -0,0 +1,118 @@ +package dev.compactmods.machines.forge.compat.theoneprobe.providers; + +import dev.compactmods.machines.api.core.CMTags; +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.api.core.Tooltips; +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.forge.compat.theoneprobe.elements.PlayerFaceElement; +import dev.compactmods.machines.forge.machine.entity.BoundCompactMachineBlockEntity; +import dev.compactmods.machines.forge.tunnel.TunnelItem; +import dev.compactmods.machines.i18n.TranslationUtil; +import dev.compactmods.machines.room.graph.CompactRoomProvider; +import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; +import dev.compactmods.machines.util.PlayerUtil; +import mcjty.theoneprobe.api.ElementAlignment; +import mcjty.theoneprobe.api.IProbeHitData; +import mcjty.theoneprobe.api.IProbeInfo; +import mcjty.theoneprobe.api.IProbeInfoProvider; +import mcjty.theoneprobe.api.ProbeMode; +import mcjty.theoneprobe.apiimpl.styles.ItemStyle; +import mcjty.theoneprobe.apiimpl.styles.LayoutStyle; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +import java.util.stream.Collectors; + +public class CompactMachineProvider implements IProbeInfoProvider { + + @Override + public ResourceLocation getID() { + return new ResourceLocation(Constants.MOD_ID, "machine"); + } + + @Override + public void addProbeInfo(ProbeMode probeMode, IProbeInfo info, Player player, Level level, BlockState blockState, IProbeHitData hitData) { + if (!blockState.is(CMTags.MACHINE_BLOCK)) + return; + + final var server = level.getServer(); + if (server == null) + return; + + final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); + if (compactDim == null) + return; + + if (level.getBlockEntity(hitData.getPos()) instanceof BoundCompactMachineBlockEntity machine) { + machine.connectedRoom().ifPresentOrElse(roomCode -> { + final var boundTo = TranslationUtil.tooltip(Tooltips.Machines.BOUND_TO, roomCode); + info.text(boundTo); + + final var roomGraph = CompactRoomProvider.instance(compactDim); + roomGraph.getRoomOwner(roomCode) + .flatMap(owner -> PlayerUtil.getProfileByUUID(server, owner)) + .ifPresent(p -> { + MutableComponent ownerText = TranslationUtil + .tooltip(Tooltips.Machines.OWNER, p.getName()) + .withStyle(ChatFormatting.GRAY); + + info.horizontal(new LayoutStyle() + .alignment(ElementAlignment.ALIGN_CENTER) + .padding(0).spacing(0)) + .element(new PlayerFaceElement(p)) + .text(ownerText); + }); + + addTunnelInfo(probeMode, info, hitData, compactDim, machine, roomCode); + }, () -> { + MutableComponent newMachine = TranslationUtil + .message(new ResourceLocation(Constants.MOD_ID, "new_machine")) + .withStyle(ChatFormatting.GREEN); + + info.text(newMachine); + }); + } + } + + private static void addTunnelInfo(ProbeMode probeMode, IProbeInfo info, IProbeHitData hitData, ServerLevel compactDim, BoundCompactMachineBlockEntity machine, String roomCode) { + if (compactDim == null) + return; + + final var graph = TunnelConnectionGraph.forRoom(compactDim, roomCode); + + final var applied = graph.types(machine.getLevelPosition(), hitData.getSideHit()) + .collect(Collectors.toSet()); + + switch (probeMode) { + case NORMAL -> { + final var group = info.horizontal(new LayoutStyle() + .alignment(ElementAlignment.ALIGN_TOPLEFT) + .padding(0) + .spacing(0)); + applied.forEach(tn -> { + ItemStack item = TunnelItem.createStack(tn); + group.item(item, new ItemStyle().bounds(8, 8)); + }); + } + case EXTENDED -> { + final var tgg = info.vertical(new LayoutStyle().alignment(ElementAlignment.ALIGN_TOPLEFT)); + applied.forEach(tn -> { + final var tg = tgg.horizontal(new LayoutStyle() + .alignment(ElementAlignment.ALIGN_CENTER) + .hPadding(2).vPadding(2) + .spacing(0)); + + ItemStack item = TunnelItem.createStack(tn); + tg.item(item, new ItemStyle().bounds(8, 8)); + tg.itemLabel(item); + }); + } + } + } +} diff --git a/src/main/java/dev/compactmods/machines/compat/theoneprobe/providers/TunnelProvider.java b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/providers/TunnelProvider.java similarity index 62% rename from src/main/java/dev/compactmods/machines/compat/theoneprobe/providers/TunnelProvider.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/providers/TunnelProvider.java index 602a094c..d13eb92c 100644 --- a/src/main/java/dev/compactmods/machines/compat/theoneprobe/providers/TunnelProvider.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/compat/theoneprobe/providers/TunnelProvider.java @@ -1,10 +1,10 @@ -package dev.compactmods.machines.compat.theoneprobe.providers; +package dev.compactmods.machines.forge.compat.theoneprobe.providers; +import dev.compactmods.machines.forge.tunnel.TunnelWallBlock; +import dev.compactmods.machines.forge.tunnel.TunnelWallEntity; +import dev.compactmods.machines.forge.tunnel.Tunnels; import dev.compactmods.machines.api.core.Constants; import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import dev.compactmods.machines.tunnel.TunnelWallBlock; -import dev.compactmods.machines.tunnel.TunnelWallEntity; -import dev.compactmods.machines.tunnel.Tunnels; import mcjty.theoneprobe.api.*; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; @@ -40,10 +40,6 @@ public void addProbeInfo(ProbeMode probeMode, IProbeInfo info, Player playerEnti IProbeInfo v = info.vertical(info.defaultLayoutStyle().spacing(-1)); if (level.getBlockEntity(hitData.getPos()) instanceof TunnelWallEntity tile) { - - - - if (probeMode == ProbeMode.EXTENDED) { TunnelDefinition definition = tile.getTunnelType(); final var tunnelReg = Tunnels.TUNNEL_DEF_REGISTRY.get(); @@ -65,32 +61,32 @@ public void addProbeInfo(ProbeMode probeMode, IProbeInfo info, Player playerEnti .item(new ItemStack(Items.COMPASS)) .text(Component.translatable(sideTranslated)); - final var connectedTo = tile.getConnectedPosition(); - if(connectedTo != null) { - ServerLevel connectedWorld = (ServerLevel) level; - BlockPos outPosBlock = connectedTo.getBlockPosition(); - - try { - final var state = connectedTo.state(level.getServer()); - - // If connected block isn't air, show a connected block line - if (!state.isAir()) { - String blockName = IProbeInfo.STARTLOC + state.getBlock().getDescriptionId() + IProbeInfo.ENDLOC; - HitResult trace = new BlockHitResult( - hitData.getHitVec(), hitData.getSideHit(), - outPosBlock, false); - - ItemStack pick = state - .getBlock() - .getCloneItemStack(state, trace, connectedWorld, outPosBlock, playerEntity); - - v.horizontal(center) - .item(pick) - .text(Component.translatable(Constants.MOD_ID.concat(".connected_block"), blockName)); - } - } catch (Exception ex) { - // no-op: we don't want to spam the log here + final var connectedMachinePos = tile.connectedMachine(); + final var connectedPos = connectedMachinePos.pos().relative(tile.getConnectedSide()); + + ServerLevel connectedWorld = (ServerLevel) level; + BlockPos outPosBlock = connectedMachinePos.pos(); + + try { + final var state = connectedWorld.getBlockState(connectedPos); + + // If connected block isn't air, show a connected block line + if (!state.isAir()) { + String blockName = IProbeInfo.STARTLOC + state.getBlock().getDescriptionId() + IProbeInfo.ENDLOC; + HitResult trace = new BlockHitResult( + hitData.getHitVec(), hitData.getSideHit(), + outPosBlock, false); + + ItemStack pick = state + .getBlock() + .getCloneItemStack(state, trace, connectedWorld, outPosBlock, playerEntity); + + v.horizontal(center) + .item(pick) + .text(Component.translatable(Constants.MOD_ID.concat(".connected_block"), blockName)); } + } catch (Exception ex) { + // no-op: we don't want to spam the log here } } } diff --git a/src/main/java/dev/compactmods/machines/config/CommonConfig.java b/forge-main/src/main/java/dev/compactmods/machines/forge/config/CommonConfig.java similarity index 91% rename from src/main/java/dev/compactmods/machines/config/CommonConfig.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/config/CommonConfig.java index 630ed26e..4c3733c4 100644 --- a/src/main/java/dev/compactmods/machines/config/CommonConfig.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/config/CommonConfig.java @@ -1,6 +1,6 @@ -package dev.compactmods.machines.config; +package dev.compactmods.machines.forge.config; -import dev.compactmods.machines.CompactMachines; +import dev.compactmods.machines.forge.CompactMachines; import dev.compactmods.machines.api.core.Constants; import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.eventbus.api.SubscribeEvent; diff --git a/src/main/java/dev/compactmods/machines/config/ServerConfig.java b/forge-main/src/main/java/dev/compactmods/machines/forge/config/ServerConfig.java similarity index 93% rename from src/main/java/dev/compactmods/machines/config/ServerConfig.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/config/ServerConfig.java index 8623d19c..e2ffcb73 100644 --- a/src/main/java/dev/compactmods/machines/config/ServerConfig.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/config/ServerConfig.java @@ -1,4 +1,4 @@ -package dev.compactmods.machines.config; +package dev.compactmods.machines.forge.config; import com.electronwill.nightconfig.core.EnumGetMethod; import dev.compactmods.machines.machine.EnumMachinePlayersBreakHandling; @@ -14,8 +14,6 @@ public class ServerConfig { public static ForgeConfigSpec.EnumValue MACHINE_PLAYER_BREAK_HANDLING; - public static ForgeConfigSpec.IntValue MACHINE_FLOOR_Y; - private static ForgeConfigSpec.IntValue REBIND_LEVEL; private static ForgeConfigSpec.IntValue GIVE_MACHINE; private static ForgeConfigSpec.IntValue CHANGE_SPAWN_LEVEL; @@ -49,10 +47,6 @@ private static void generateConfig() { EnumMachinePlayersBreakHandling.UNBREAKABLE, EnumGetMethod.NAME_IGNORECASE); - MACHINE_FLOOR_Y = builder - .comment("The Y-dimension to spawn machine floors at.") - .defineInRange("floor", 40, 10, 200); - ALLOWED_OUTSIDE_MACHINE = builder .comment("Specify if we want to damage player's that managed to escape the boundries") .comment("default: false") diff --git a/src/main/java/dev/compactmods/machines/room/data/CopyRoomBindingFunction.java b/forge-main/src/main/java/dev/compactmods/machines/forge/data/functions/CopyRoomBindingFunction.java similarity index 65% rename from src/main/java/dev/compactmods/machines/room/data/CopyRoomBindingFunction.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/data/functions/CopyRoomBindingFunction.java index 97527bc6..ae9251aa 100644 --- a/src/main/java/dev/compactmods/machines/room/data/CopyRoomBindingFunction.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/data/functions/CopyRoomBindingFunction.java @@ -1,10 +1,12 @@ -package dev.compactmods.machines.room.data; +package dev.compactmods.machines.forge.data.functions; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; -import dev.compactmods.machines.machine.CompactMachineBlockEntity; -import dev.compactmods.machines.machine.CompactMachineItem; +import dev.compactmods.machines.forge.machine.entity.BoundCompactMachineBlockEntity; +import dev.compactmods.machines.forge.machine.item.BoundCompactMachineItem; +import dev.compactmods.machines.api.core.CMTags; +import dev.compactmods.machines.machine.item.ICompactMachineItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.functions.LootItemConditionalFunction; @@ -24,11 +26,15 @@ public static Builder binding() { @Override protected ItemStack run(ItemStack stack, LootContext ctx) { - var data = ctx.getParam(LootContextParams.BLOCK_ENTITY); - if(data instanceof CompactMachineBlockEntity machine) { - machine.getConnectedRoom().ifPresent(room -> { - CompactMachineItem.setRoom(stack, room); - }); + var state = ctx.getParam(LootContextParams.BLOCK_STATE); + if(state.is(CMTags.MACHINE_BLOCK)) { + var data = ctx.getParam(LootContextParams.BLOCK_ENTITY); + if (data instanceof BoundCompactMachineBlockEntity machine) { + machine.connectedRoom().ifPresent(roomCode -> { + ICompactMachineItem.setColor(stack, machine.getColor()); + BoundCompactMachineItem.setRoom(stack, roomCode); + }); + } } return stack; diff --git a/src/main/java/dev/compactmods/machines/room/data/LootFunctions.java b/forge-main/src/main/java/dev/compactmods/machines/forge/data/functions/LootFunctions.java similarity index 80% rename from src/main/java/dev/compactmods/machines/room/data/LootFunctions.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/data/functions/LootFunctions.java index 49fdb15a..0257714e 100644 --- a/src/main/java/dev/compactmods/machines/room/data/LootFunctions.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/data/functions/LootFunctions.java @@ -1,6 +1,6 @@ -package dev.compactmods.machines.room.data; +package dev.compactmods.machines.forge.data.functions; -import dev.compactmods.machines.core.Registries; +import dev.compactmods.machines.forge.Registries; import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType; import net.minecraftforge.registries.RegistryObject; diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/data/migration/EarlyLevelDataFileReader.java b/forge-main/src/main/java/dev/compactmods/machines/forge/data/migration/EarlyLevelDataFileReader.java new file mode 100644 index 00000000..41a6f11f --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/data/migration/EarlyLevelDataFileReader.java @@ -0,0 +1,80 @@ +package dev.compactmods.machines.forge.data.migration; + +import com.google.common.collect.ImmutableSet; +import com.mojang.serialization.Dynamic; +import dev.compactmods.machines.api.dimension.CompactDimension; +import net.minecraft.SharedConstants; +import net.minecraft.Util; +import net.minecraft.nbt.NbtIo; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceKey; +import net.minecraft.util.datafix.DataFixTypes; +import net.minecraft.util.datafix.DataFixers; +import net.minecraft.util.datafix.fixes.References; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.levelgen.WorldGenSettings; +import net.minecraft.world.level.storage.LevelStorageSource; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Set; + +public class EarlyLevelDataFileReader { + private final Logger LOG = LogManager.getLogger(); + private final LevelStorageSource.LevelDirectory directory; + private static final ImmutableSet> DEFAULT_LEVELS = ImmutableSet.of(Level.OVERWORLD, Level.NETHER, Level.END, CompactDimension.LEVEL_KEY); + public EarlyLevelDataFileReader(LevelStorageSource.LevelDirectory directory) { + this.directory = directory; + } + + /** + * Clones a file to do work upon, keeping the original in a safe state + * @return + */ + private Path makeSafeFile(String backupName) throws IOException { + if(Files.exists(directory.dataFile())) { + final var copied = directory.path().resolve(backupName); + Files.copy(directory.dataFile(), copied, StandardCopyOption.REPLACE_EXISTING); + return copied; + } + + if(Files.exists(directory.oldDataFile())) { + final var copied = directory.path().resolve(backupName); + Files.copy(directory.oldDataFile(), copied, StandardCopyOption.REPLACE_EXISTING); + return copied; + } + + throw new IOException("No source file could be found."); + } + + public Set> dimensions() { + LOG.info("Starting dimension read from level files."); + try { + final var tempFile = makeSafeFile("cm5_early_dimensions.dat"); + final var dataFixer = DataFixers.getDataFixer(); + final var rootTag = NbtIo.readCompressed(tempFile.toFile()).getCompound("Data"); + + int savedLevelVersion = rootTag.contains("DataVersion", 99) ? rootTag.getInt("DataVersion") : -1; + Dynamic dynamic = dataFixer.update(DataFixTypes.LEVEL.getType(), new Dynamic<>(NbtOps.INSTANCE, rootTag), savedLevelVersion, + SharedConstants.getCurrentVersion().getWorldVersion()); + + final var updatedData = dataFixer.update(References.WORLD_GEN_SETTINGS, dynamic, savedLevelVersion, SharedConstants.getCurrentVersion().getWorldVersion()); + final var levels = WorldGenSettings.CODEC.parse(updatedData) + .resultOrPartial(Util.prefix("CM5-EarlyLevelReader: ", LOG::error)) + .map(WorldGenSettings::levels) + .orElse(DEFAULT_LEVELS); + + Files.deleteIfExists(tempFile); + LOG.info("Completed dimension read from level files."); + return levels; + } catch (IOException e) { + LOG.fatal("Failed to make a safe level file backup to read dimension info!"); + return DEFAULT_LEVELS; + } + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/data/migration/Pre520RoomDataMigrator.java b/forge-main/src/main/java/dev/compactmods/machines/forge/data/migration/Pre520RoomDataMigrator.java new file mode 100644 index 00000000..f194a40e --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/data/migration/Pre520RoomDataMigrator.java @@ -0,0 +1,200 @@ +package dev.compactmods.machines.forge.data.migration; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.room.RoomSize; +import dev.compactmods.machines.codec.CodecExtensions; +import dev.compactmods.machines.forge.machine.block.LegacySizedCompactMachineBlock; +import dev.compactmods.machines.machine.graph.DimensionMachineGraph; +import dev.compactmods.machines.room.RoomCodeGenerator; +import dev.compactmods.machines.room.graph.CompactRoomProvider; +import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; +import dev.compactmods.machines.util.DimensionUtil; +import dev.compactmods.machines.util.SavedDataHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtIo; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.dimension.DimensionType; +import net.minecraft.world.level.storage.DimensionDataStorage; +import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.phys.Vec2; +import net.minecraft.world.phys.Vec3; +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 java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; + +@SuppressWarnings({"removal", "deprecation"}) +public class Pre520RoomDataMigrator { + + public static final String ROOM_DATA_NAME = Constants.MOD_ID + "_rooms"; + private static final Logger UPDATER_LOGGER = LogManager.getLogger(Constants.MOD_ID); + private static final Marker UPDATER = MarkerManager.getMarker("room_data_updater"); + + public record RoomDataPre520(UUID owner, BlockPos center, Vec3 spawn, RoomSize size, Optional name) { + + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + CodecExtensions.UUID_STRING.fieldOf("owner").forGetter(RoomDataPre520::owner), + BlockPos.CODEC.fieldOf("center").forGetter(RoomDataPre520::center), + CodecExtensions.VECTOR3D.fieldOf("spawn").forGetter(RoomDataPre520::spawn), + RoomSize.CODEC.fieldOf("size").forGetter(RoomDataPre520::size), + Codec.STRING.optionalFieldOf("name").forGetter(RoomDataPre520::name) + ).apply(i, RoomDataPre520::new)); + + public static RoomDataPre520 of(CompoundTag data) { + return CODEC.parse(NbtOps.INSTANCE, data).getOrThrow(false, UPDATER_LOGGER::error); + } + } + + public record MachineRoomConnection(ChunkPos room, List machines) { + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + CodecExtensions.CHUNKPOS.fieldOf("room") + .forGetter(MachineRoomConnection::room), + + BlockPos.CODEC.listOf().fieldOf("machines") + .forGetter(MachineRoomConnection::machines) + ).apply(i, MachineRoomConnection::new)); + } + + public record RoomDataLoadResult(HashMap oldRoomData, HashMap roomChunkLookup) { + } + + public static String getOldTunnelFilename(ChunkPos oldRoom) { + return "tunnels_%s_%s".formatted(oldRoom.x, oldRoom.z); + } + + public static RoomDataLoadResult loadOldRoomData(DimensionDataStorage dataStore) throws IOException { + AtomicReference result = new AtomicReference<>(); + SavedDataHelper.processFile(dataStore, ROOM_DATA_NAME, nbt -> result.set(loadOldRoomData(nbt))); + return result.get(); + } + + public static RoomDataLoadResult loadOldRoomData(CompoundTag nbt) { + final HashMap oldRoomData = new HashMap<>(); + final HashMap roomChunkLookup = new HashMap<>(); + + final var data = RoomDataPre520.CODEC.listOf() + .parse(NbtOps.INSTANCE, nbt.getList("machines", Tag.TAG_COMPOUND)) + .resultOrPartial(UPDATER_LOGGER::error) + .orElse(Collections.emptyList()); + + data.forEach(d -> { + ChunkPos chunk = new ChunkPos(d.center()); + String newId = RoomCodeGenerator.generateRoomId(); + roomChunkLookup.put(chunk, newId); + oldRoomData.put(newId, d); + }); + + return new RoomDataLoadResult(oldRoomData, roomChunkLookup); + } + + public static void addMissingRoomEntries(DimensionDataStorage dataStore, CompactRoomProvider provider, RoomDataLoadResult oldData) { + oldData.oldRoomData().forEach((code, roomInfo) -> { + final var roomChunk = new ChunkPos(roomInfo.center); + if (!provider.isRoomChunk(roomChunk)) { + // Room hasn't been registered yet, map to migrated code + var legTemplate = LegacySizedCompactMachineBlock.getLegacyTemplate(roomInfo.size); + provider.registerNew(code, builder -> builder + .setColor(legTemplate.color()) + .setDimensions(roomInfo.size.toVec3()) + .setCenter(roomInfo.center) + .setSpawn(roomInfo.spawn, Vec2.ZERO) + .setOwner(roomInfo.owner)); + } + }); + + SavedDataHelper.saveFile(dataStore, CompactRoomProvider.DATA_NAME, provider); + } + + public static void migrateConnectionInfo(LevelStorageSource.LevelDirectory levelDirectory, HashMap roomChunkLookup, + Set> levels, Path backupDir) throws IOException { + + for (var level : levels) { + final var dimDataStore = DimensionUtil.getDataStorage(levelDirectory, level); + final var connFile = dimDataStore.getDataFile(DimensionMachineGraph.DATA_KEY); + if (connFile.exists()) { + final var thisDimDir = DimensionUtil.getDataFolder(backupDir, level); + Files.createDirectories(thisDimDir); + + UPDATER_LOGGER.debug(UPDATER, "Updating connection info for dimension: {}", level.location()); + Files.copy(connFile.toPath(), thisDimDir.resolve(connFile.getName() + ".backup")); + + /** + * data/ CompoundTag + * graph: CompoundTag + * connections: ListTag (CompoundTag/MachineRoomConnectionRecord) + * + * MachineRoomConnectionRecord: + * machines: ListTag (integer) - BlockPos + * room: array [x, z] + */ + final var machineGraphNbt = DimensionUtil.readSavedFile(dimDataStore, "machine_connections"); + machineGraphNbt.getCompound("graph") + .getList("connections", Tag.TAG_COMPOUND) + .forEach(machConnTag -> { + // Loop machine-room connection info, replace room pos with room code + if (machConnTag instanceof CompoundTag ct) { + var record = MachineRoomConnection.CODEC.parse(NbtOps.INSTANCE, ct) + .getOrThrow(false, UPDATER_LOGGER::error); + + // Change the room reference from a chunkpos to a room code + if (roomChunkLookup.containsKey(record.room)) { + final var newCode = roomChunkLookup.get(record.room); + ct.remove("room"); + ct.putString("room", newCode); + UPDATER_LOGGER.debug(UPDATER, "Assigning new code to room {}; code: {}", record.room.toString(), newCode); + } + + // note: machines are read here but not needed; the dim graph still reads those fine + } + }); + + final var dimPath = DimensionType.getStorageFolder(level, levelDirectory.path()); + NbtIo.writeCompressed(machineGraphNbt, dimPath.resolve("data").resolve(DimensionMachineGraph.DATA_KEY + ".dat").toFile()); + } + } + } + + public static void migrateTunnelFiles(LevelStorageSource.LevelDirectory levelDirectory, HashMap roomChunkLookup, Path backupDir) + throws IOException { + Files.createDirectories(backupDir.resolve("tunnels")); + + final var dataStore = CompactDimension.getDataStorage(levelDirectory); + for(final var room : roomChunkLookup.entrySet()) { + final var prevFilename = getOldTunnelFilename(room.getKey()); + final var oldFile = dataStore.getDataFile(prevFilename); + final var newFile = dataStore.getDataFile(TunnelConnectionGraph.getDataFilename(room.getValue())); + if(oldFile.exists()) { + final var oldFilePath = oldFile.toPath(); + Files.copy(oldFilePath, backupDir.resolve("tunnels").resolve(prevFilename + ".dat.backup")); + Files.copy(oldFilePath, newFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + Files.delete(oldFilePath); + } + } + } + + public static void makeRoomDataBackup(DimensionDataStorage dataStore, Path backupDir) throws IOException { + final var moveTo = DimensionUtil.getDataFolder(backupDir, CompactDimension.LEVEL_KEY); + Files.createDirectories(moveTo); + Files.copy(dataStore.getDataFile(ROOM_DATA_NAME).toPath(), moveTo.resolve(ROOM_DATA_NAME.concat(".dat"))); + } +} diff --git a/src/main/java/dev/compactmods/machines/dimension/Dimension.java b/forge-main/src/main/java/dev/compactmods/machines/forge/dimension/Dimension.java similarity index 85% rename from src/main/java/dev/compactmods/machines/dimension/Dimension.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/dimension/Dimension.java index 8f915e9a..6c456944 100644 --- a/src/main/java/dev/compactmods/machines/dimension/Dimension.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/dimension/Dimension.java @@ -1,6 +1,6 @@ -package dev.compactmods.machines.dimension; +package dev.compactmods.machines.forge.dimension; -import dev.compactmods.machines.core.Registries; +import dev.compactmods.machines.forge.Registries; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; @@ -18,11 +18,11 @@ public class Dimension { // ================================================================================================================ // DIMENSION // ================================================================================================================ - @Deprecated(forRemoval = true) + @Deprecated(forRemoval = true, since = "5.2.0") public static final ResourceKey COMPACT_DIMENSION = ResourceKey .create(Registry.DIMENSION_REGISTRY, new ResourceLocation(MOD_ID, "compact_world")); - @Deprecated(forRemoval = true) + @Deprecated(forRemoval = true, since = "5.2.0") public static final ResourceKey COMPACT_DIMENSION_DIM_TYPE = ResourceKey .create(Registry.DIMENSION_TYPE_REGISTRY, new ResourceLocation(MOD_ID, "compact_world")); diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/dimension/SimpleTeleporter.java b/forge-main/src/main/java/dev/compactmods/machines/forge/dimension/SimpleTeleporter.java new file mode 100644 index 00000000..bf14f572 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/dimension/SimpleTeleporter.java @@ -0,0 +1,87 @@ +package dev.compactmods.machines.forge.dimension; + +import net.minecraft.commands.arguments.EntityAnchorArgument; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec2; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.util.ITeleporter; + +import java.util.Objects; +import java.util.function.Function; + +public final class SimpleTeleporter implements ITeleporter { + private final Vec3 pos; + private final Vec2 rotation; + + private final BlockPos postTeleLookAt; + + private SimpleTeleporter(Vec3 pos, Vec2 rotation) { + this.pos = pos; + this.rotation = rotation; + this.postTeleLookAt = null; + } + + private SimpleTeleporter(Vec3 pos, Vec2 rotation, BlockPos postTeleLookAt) { + this.pos = pos; + this.rotation = rotation; + this.postTeleLookAt = postTeleLookAt; + } + + public static SimpleTeleporter to(Vec3 pos) { + return new SimpleTeleporter(pos, Vec2.ZERO); + } + + public static SimpleTeleporter to(Vec3 pos, Vec2 rotation) { + return new SimpleTeleporter(pos, rotation); + } + + public static ITeleporter lookingAt(Vec3 position, BlockPos lookAt) { + return new SimpleTeleporter(position, Vec2.ZERO, lookAt); + } + + @Override + public Entity placeEntity(Entity entity, ServerLevel currentWorld, ServerLevel destWorld, float yaw, Function repositionEntity) { + entity = repositionEntity.apply(false); + entity.teleportTo(pos.x, pos.y, pos.z); + entity.setXRot(rotation.x); + entity.setYRot(rotation.y); + entity.setYHeadRot(rotation.y); + + if(postTeleLookAt != null) + entity.lookAt(EntityAnchorArgument.Anchor.EYES, Vec3.atCenterOf(postTeleLookAt)); + + return entity; + } + + public Vec3 pos() { + return pos; + } + + public Vec2 rotation() { + return rotation; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (SimpleTeleporter) obj; + return Objects.equals(this.pos, that.pos) && + Objects.equals(this.rotation, that.rotation); + } + + @Override + public int hashCode() { + return Objects.hash(pos, rotation); + } + + @Override + public String toString() { + return "SimpleTeleporter[" + + "pos=" + pos + ", " + + "rotation=" + rotation + ']'; + } + +} diff --git a/src/main/java/dev/compactmods/machines/dimension/VoidAirBlock.java b/forge-main/src/main/java/dev/compactmods/machines/forge/dimension/VoidAirBlock.java similarity index 81% rename from src/main/java/dev/compactmods/machines/dimension/VoidAirBlock.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/dimension/VoidAirBlock.java index 04fcac69..7d959950 100644 --- a/src/main/java/dev/compactmods/machines/dimension/VoidAirBlock.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/dimension/VoidAirBlock.java @@ -1,8 +1,9 @@ -package dev.compactmods.machines.dimension; +package dev.compactmods.machines.forge.dimension; import dev.compactmods.machines.api.room.IRoomHistory; -import dev.compactmods.machines.config.ServerConfig; -import dev.compactmods.machines.room.RoomCapabilities; +import dev.compactmods.machines.forge.config.ServerConfig; +import dev.compactmods.machines.forge.room.capability.RoomCapabilities; +import dev.compactmods.machines.forge.util.ForgePlayerUtil; import dev.compactmods.machines.util.PlayerUtil; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; @@ -32,6 +33,7 @@ public void entityInside(BlockState pState, Level pLevel, BlockPos pPos, Entity if (ServerConfig.isAllowedOutsideOfMachine()) return; if (pLevel.isClientSide) return; + // TODO: Configurable behavior if (pEntity instanceof ServerPlayer player) { if (player.isCreative()) return; @@ -41,7 +43,7 @@ public void entityInside(BlockState pState, Level pLevel, BlockPos pPos, Entity PlayerUtil.howDidYouGetThere(player); player.getCapability(RoomCapabilities.ROOM_HISTORY).ifPresent(IRoomHistory::clear); - PlayerUtil.teleportPlayerToRespawnOrOverworld(player.server, player); + ForgePlayerUtil.teleportPlayerToRespawnOrOverworld(player.server, player); } } } diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/Machines.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/Machines.java new file mode 100644 index 00000000..82dc9add --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/Machines.java @@ -0,0 +1,114 @@ +package dev.compactmods.machines.forge.machine; + +import dev.compactmods.machines.api.machine.MachineIds; +import dev.compactmods.machines.api.room.RoomSize; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.Registries; +import dev.compactmods.machines.forge.machine.block.BoundCompactMachineBlock; +import dev.compactmods.machines.forge.machine.block.LegacySizedCompactMachineBlock; +import dev.compactmods.machines.forge.machine.block.UnboundCompactMachineBlock; +import dev.compactmods.machines.forge.machine.entity.BoundCompactMachineBlockEntity; +import dev.compactmods.machines.forge.machine.entity.UnboundCompactMachineEntity; +import dev.compactmods.machines.forge.machine.item.BoundCompactMachineItem; +import dev.compactmods.machines.forge.machine.item.LegacyCompactMachineItem; +import dev.compactmods.machines.forge.machine.item.UnboundCompactMachineItem; +import dev.compactmods.machines.forge.machine.entity.LegacyCompactMachineBlockEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.material.Material; +import net.minecraftforge.registries.RegistryObject; + +import java.util.function.Supplier; + +@SuppressWarnings("removal") +public class Machines { + static final BlockBehaviour.Properties MACHINE_BLOCK_PROPS = BlockBehaviour.Properties + .of(Material.METAL) + .strength(8.0F, 20.0F) + .requiresCorrectToolForDrops(); + + static final Supplier MACHINE_ITEM_PROPS = () -> new Item.Properties() + .tab(CompactMachines.COMPACT_MACHINES_ITEMS); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject MACHINE_BLOCK_TINY = Registries.BLOCKS.register("machine_tiny", () -> + new LegacySizedCompactMachineBlock(RoomSize.TINY, MACHINE_BLOCK_PROPS)); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject MACHINE_BLOCK_SMALL = Registries.BLOCKS.register("machine_small", () -> + new LegacySizedCompactMachineBlock(RoomSize.SMALL, MACHINE_BLOCK_PROPS)); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject MACHINE_BLOCK_NORMAL = Registries.BLOCKS.register("machine_normal", () -> + new LegacySizedCompactMachineBlock(RoomSize.NORMAL, MACHINE_BLOCK_PROPS)); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject MACHINE_BLOCK_LARGE = Registries.BLOCKS.register("machine_large", () -> + new LegacySizedCompactMachineBlock(RoomSize.LARGE, MACHINE_BLOCK_PROPS)); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject MACHINE_BLOCK_GIANT = Registries.BLOCKS.register("machine_giant", () -> + new LegacySizedCompactMachineBlock(RoomSize.GIANT, MACHINE_BLOCK_PROPS)); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject MACHINE_BLOCK_MAXIMUM = Registries.BLOCKS.register("machine_maximum", () -> + new LegacySizedCompactMachineBlock(RoomSize.MAXIMUM, MACHINE_BLOCK_PROPS)); + + public static final RegistryObject UNBOUND_MACHINE_BLOCK = Registries.BLOCKS.register("new_machine", () -> + new UnboundCompactMachineBlock(MACHINE_BLOCK_PROPS)); + + public static final RegistryObject MACHINE_BLOCK = Registries.BLOCKS.register("machine", () -> + new BoundCompactMachineBlock(MACHINE_BLOCK_PROPS)); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject MACHINE_BLOCK_ITEM_TINY = Registries.ITEMS.register("machine_tiny", + () -> new LegacyCompactMachineItem(MACHINE_BLOCK_TINY.get(), MACHINE_ITEM_PROPS.get())); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject MACHINE_BLOCK_ITEM_SMALL = Registries.ITEMS.register("machine_small", + () -> new LegacyCompactMachineItem(MACHINE_BLOCK_SMALL.get(), MACHINE_ITEM_PROPS.get())); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject MACHINE_BLOCK_ITEM_NORMAL = Registries.ITEMS.register("machine_normal", + () -> new LegacyCompactMachineItem(MACHINE_BLOCK_NORMAL.get(), MACHINE_ITEM_PROPS.get())); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject MACHINE_BLOCK_ITEM_LARGE = Registries.ITEMS.register("machine_large", + () -> new LegacyCompactMachineItem(MACHINE_BLOCK_LARGE.get(), MACHINE_ITEM_PROPS.get())); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject MACHINE_BLOCK_ITEM_GIANT = Registries.ITEMS.register("machine_giant", + () -> new LegacyCompactMachineItem(MACHINE_BLOCK_GIANT.get(), MACHINE_ITEM_PROPS.get())); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject MACHINE_BLOCK_ITEM_MAXIMUM = Registries.ITEMS.register("machine_maximum", + () -> new LegacyCompactMachineItem(MACHINE_BLOCK_MAXIMUM.get(), MACHINE_ITEM_PROPS.get())); + + public static final RegistryObject BOUND_MACHINE_BLOCK_ITEM = Registries.ITEMS.register("machine", + () -> new BoundCompactMachineItem(MACHINE_ITEM_PROPS.get().tab(CompactMachines.COMPACT_MACHINES_ITEMS))); + + + public static final RegistryObject UNBOUND_MACHINE_BLOCK_ITEM = Registries.ITEMS.register("new_machine", + () -> new UnboundCompactMachineItem(MACHINE_ITEM_PROPS.get().tab(CompactMachines.COMPACT_MACHINES_ITEMS))); + + @Deprecated(forRemoval = true, since = "5.2.0") + public static final RegistryObject> LEGACY_MACHINE_ENTITY = Registries.BLOCK_ENTITIES.register(MachineIds.OLD_MACHINE_ENTITY.getPath(), () -> + BlockEntityType.Builder.of(LegacyCompactMachineBlockEntity::new, + MACHINE_BLOCK_TINY.get(), MACHINE_BLOCK_SMALL.get(), MACHINE_BLOCK_NORMAL.get(), + MACHINE_BLOCK_LARGE.get(), MACHINE_BLOCK_GIANT.get(), MACHINE_BLOCK_MAXIMUM.get()) + .build(null)); + + public static final RegistryObject> UNBOUND_MACHINE_ENTITY = Registries.BLOCK_ENTITIES.register(MachineIds.UNBOUND_MACHINE_ENTITY.getPath(), () -> + BlockEntityType.Builder.of(UnboundCompactMachineEntity::new, UNBOUND_MACHINE_BLOCK.get()) + .build(null)); + + public static final RegistryObject> MACHINE_ENTITY = Registries.BLOCK_ENTITIES.register(MachineIds.BOUND_MACHINE_ENTITY.getPath(), () -> + BlockEntityType.Builder.of(BoundCompactMachineBlockEntity::new, MACHINE_BLOCK.get()) + .build(null)); + + public static void prepare() { + + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/BoundCompactMachineBlock.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/BoundCompactMachineBlock.java new file mode 100644 index 00000000..97389415 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/BoundCompactMachineBlock.java @@ -0,0 +1,108 @@ +package dev.compactmods.machines.forge.machine.block; + +import dev.compactmods.machines.LoggingUtil; +import dev.compactmods.machines.api.shrinking.PSDTags; +import dev.compactmods.machines.forge.machine.Machines; +import dev.compactmods.machines.forge.machine.entity.BoundCompactMachineBlockEntity; +import dev.compactmods.machines.forge.machine.item.BoundCompactMachineItem; +import dev.compactmods.machines.forge.machine.item.UnboundCompactMachineItem; +import dev.compactmods.machines.machine.item.ICompactMachineItem; +import dev.compactmods.machines.room.BasicRoomInfo; +import net.minecraft.core.BlockPos; +import net.minecraft.core.NonNullList; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class BoundCompactMachineBlock extends CompactMachineBlock implements EntityBlock { + public BoundCompactMachineBlock(Properties props) { + super(props); + } + + @Override + public ItemStack getCloneItemStack(BlockGetter level, BlockPos pos, BlockState state) { + if (level.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity be) { + return be.connectedRoom().map(roomCode -> { + final var roomInfo = new BasicRoomInfo(roomCode, be.getColor()); + return BoundCompactMachineItem.createForRoom(roomInfo); + }).orElse(UnboundCompactMachineItem.unbound()); + } + + LoggingUtil.modLog().warn("Warning: tried to pick block on a machine that does not have an associated block entity."); + return null; + } + + @Override + public float getDestroyProgress(BlockState state, Player player, BlockGetter level, BlockPos pos) { + return MachineBlockUtil.destroyProgress(state, player, level, pos); + } + + @Override + public void fillItemCategory(CreativeModeTab pTab, NonNullList pItems) { + // Do not add additional items to Creative + } + + @Override + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { + if (!level.isClientSide) { + level.getBlockEntity(pos, Machines.MACHINE_ENTITY.get()).ifPresent(tile -> { + // force client redraw + final int color = ICompactMachineItem.getMachineColor(stack); + tile.setColor(color); + + BoundCompactMachineItem.getRoom(stack).ifPresent(tile::setConnectedRoom); + }); + } + } + + @SuppressWarnings("deprecation") + public void onRemove(BlockState oldState, Level level, BlockPos pos, BlockState newState, boolean a) { + if (level.isClientSide) { + super.onRemove(oldState, level, pos, newState, a); + return; + } + + MachineBlockUtil.cleanupTunnelsPostMachineRemove(level, pos); + + super.onRemove(oldState, level, pos, newState, a); + } + + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new BoundCompactMachineBlockEntity(pos, state); + } + + @NotNull + @Override + @SuppressWarnings("deprecation") + public InteractionResult use(@NotNull BlockState state, Level level, @NotNull BlockPos pos, Player player, @NotNull InteractionHand hand, @NotNull BlockHitResult hitResult) { + MinecraftServer server = level.getServer(); + ItemStack mainItem = player.getMainHandItem(); + if (mainItem.is(PSDTags.ITEM) && player instanceof ServerPlayer sp) { + return MachineBlockUtil.tryRoomTeleport(level, pos, sp, server); + } + + // All other items, open preview screen + if(!level.isClientSide) { + level.getBlockEntity(pos, Machines.MACHINE_ENTITY.get()).ifPresent(machine -> { + MachineBlockUtil.roomPreviewScreen(pos, (ServerPlayer) player, server, machine); + }); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/CompactMachineBlock.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/CompactMachineBlock.java new file mode 100644 index 00000000..de57ddac --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/CompactMachineBlock.java @@ -0,0 +1,40 @@ +package dev.compactmods.machines.forge.machine.block; + +import dev.compactmods.machines.api.shrinking.PSDTags; +import net.minecraft.core.BlockPos; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import org.jetbrains.annotations.NotNull; + +/** + * Primary block. + * + * @since 5.2.0 + */ +public class CompactMachineBlock extends Block { + + CompactMachineBlock(Properties props) { + super(props); + } + + @NotNull + @Override + @SuppressWarnings("deprecation") + public InteractionResult use(@NotNull BlockState state, Level level, @NotNull BlockPos pos, Player player, @NotNull InteractionHand hand, @NotNull BlockHitResult hitResult) { + MinecraftServer server = level.getServer(); + ItemStack mainItem = player.getMainHandItem(); + if (mainItem.is(PSDTags.ITEM) && player instanceof ServerPlayer sp) { + return MachineBlockUtil.tryRoomTeleport(level, pos, sp, server); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/LegacySizedCompactMachineBlock.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/LegacySizedCompactMachineBlock.java new file mode 100644 index 00000000..11bfcb76 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/LegacySizedCompactMachineBlock.java @@ -0,0 +1,280 @@ +package dev.compactmods.machines.forge.machine.block; + +import dev.compactmods.machines.api.core.CMTags; +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.dimension.MissingDimensionException; +import dev.compactmods.machines.api.room.RoomSize; +import dev.compactmods.machines.api.room.RoomTemplate; +import dev.compactmods.machines.api.shrinking.PSDTags; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.Registries; +import dev.compactmods.machines.forge.client.ClientConfig; +import dev.compactmods.machines.forge.machine.Machines; +import dev.compactmods.machines.forge.machine.entity.BoundCompactMachineBlockEntity; +import dev.compactmods.machines.forge.machine.entity.LegacyCompactMachineBlockEntity; +import dev.compactmods.machines.forge.machine.item.BoundCompactMachineItem; +import dev.compactmods.machines.forge.machine.item.LegacyCompactMachineItem; +import dev.compactmods.machines.forge.machine.item.UnboundCompactMachineItem; +import dev.compactmods.machines.forge.room.RoomHelper; +import dev.compactmods.machines.forge.tunnel.Tunnels; +import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades; +import dev.compactmods.machines.forge.upgrade.RoomUpgradeItem; +import dev.compactmods.machines.machine.LegacySizedTemplates; +import dev.compactmods.machines.machine.graph.DimensionMachineGraph; +import dev.compactmods.machines.room.exceptions.NonexistentRoomException; +import dev.compactmods.machines.tunnel.graph.traversal.TunnelMachineFilters; +import dev.compactmods.machines.tunnel.graph.traversal.TunnelTypeFilters; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.NonNullList; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.tags.TagKey; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.ParametersAreNonnullByDefault; + +@SuppressWarnings("removal") +@Deprecated(forRemoval = true, since = "5.2.0") +public class LegacySizedCompactMachineBlock extends CompactMachineBlock implements EntityBlock { + + public static final TagKey LEGACY_MACHINES_TAG = TagKey.create(Registries.BLOCKS.getRegistryKey(), + new ResourceLocation(Constants.MOD_ID, "legacy_machines")); + + private final RoomSize size; + + public LegacySizedCompactMachineBlock(RoomSize size, BlockBehaviour.Properties props) { + super(props); + this.size = size; + } + + @Override + public void fillItemCategory(CreativeModeTab pTab, NonNullList pItems) { + if (ClientConfig.showLegacyItems()) { + pItems.add(new ItemStack(LegacyCompactMachineItem.getItemBySize(this.size))); + } + } + + @Override + @SuppressWarnings("deprecation") + public float getDestroyProgress(BlockState state, Player player, BlockGetter worldIn, BlockPos pos) { + return MachineBlockUtil.destroyProgress(state, player, worldIn, pos); + } + + @Override + public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, @Nullable Direction side) { + return false; + } + + @Override + @SuppressWarnings("deprecation") + public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { + // TODO Redstone out tunnels + return 0; + } + + @Override + @SuppressWarnings("deprecation") + @ParametersAreNonnullByDefault + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block changedBlock, BlockPos changedPos, boolean isMoving) { + if (world.isClientSide) + return; + + ServerLevel serverWorld = (ServerLevel) world; + if (serverWorld.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity machine) { + ServerLevel compactWorld = serverWorld.getServer().getLevel(CompactDimension.LEVEL_KEY); + if (compactWorld == null) { + CompactMachines.LOGGER.warn("Warning: Compact Dimension was null! Cannot fetch internal state for machine neighbor change listener."); + } else { + for (final var dir : Direction.Plane.HORIZONTAL) { + if (!pos.relative(dir).equals(changedPos)) continue; + + // Horizontal neighbor changed + machine.getTunnelGraph().ifPresent(graph -> { + // Update redstone tunnel signals + graph.positions(TunnelMachineFilters.sided(machine.getLevelPosition(), dir), TunnelTypeFilters.redstone(Tunnels::getDefinition)).forEach(tunnelPos -> { + compactWorld.updateNeighbourForOutputSignal(tunnelPos, Tunnels.BLOCK_TUNNEL_WALL.get()); + }); + }); + } + } + } + } + + public static Block getBySize(RoomSize size) { + return switch (size) { + case TINY -> Machines.MACHINE_BLOCK_TINY.get(); + case SMALL -> Machines.MACHINE_BLOCK_SMALL.get(); + case NORMAL -> Machines.MACHINE_BLOCK_NORMAL.get(); + case LARGE -> Machines.MACHINE_BLOCK_LARGE.get(); + case GIANT -> Machines.MACHINE_BLOCK_GIANT.get(); + case MAXIMUM -> Machines.MACHINE_BLOCK_MAXIMUM.get(); + }; + + } + + @Override + public ItemStack getCloneItemStack(BlockGetter level, BlockPos pos, BlockState state) { + if (state.getBlock() instanceof LegacySizedCompactMachineBlock leg) { + final var item = LegacyCompactMachineItem.getItemBySize(leg.getSize()); + return new ItemStack(item); + } + + return UnboundCompactMachineItem.unbound(); + } + + @Override + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { + level.getBlockEntity(pos, Machines.LEGACY_MACHINE_ENTITY.get()).ifPresent(machine -> { + + // TODO - Custom machine names + if (!level.isClientSide && level instanceof ServerLevel serverLevel) { + // Custom machine name override +// if(stack.hasCustomHoverName()) { +// tile.setCustomName(stack.getHoverName()); +// } +// +// MachineItemUtil.getMachineName(stack).ifPresent(customName -> { +// tile.setCustomName(Component.literal(customName)); +// }); + + + // Machine was previously bound to a room - make a new binding post-place + BoundCompactMachineItem.getRoom(stack).ifPresent(room -> { + final var g = DimensionMachineGraph.forDimension(serverLevel); + g.register(pos, room); + machine.setConnectedRoom(room); + }); + } + }); + } + + @Override + @SuppressWarnings("deprecation") + public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) { + if (level.isClientSide()) + return InteractionResult.SUCCESS; + + MinecraftServer server = level.getServer(); + ItemStack mainItem = player.getMainHandItem(); + if (mainItem.is(PSDTags.ITEM) && player instanceof ServerPlayer sp) { + level.getBlockEntity(pos, Machines.LEGACY_MACHINE_ENTITY.get()).ifPresentOrElse(machine -> { + machine.roomInfo().ifPresentOrElse(room -> { + try { + + RoomHelper.teleportPlayerIntoRoom(server, sp, room, machine.getLevelPosition()); + } catch (MissingDimensionException | NonexistentRoomException e) { + throw new RuntimeException(e); + } + }, () -> { + player.displayClientMessage(Component.literal("Please break and replace this block to create a new room."), true); + }); + }, () -> { + player.displayClientMessage(Component.literal("Error in block entry: not a legacy machine block entity"), true); + }); + } + + // Try and pull the name off the nametag and apply it to the room + InteractionResult applyNametag = MachineBlockUtil.tryApplyNametag(level, pos, player); + if (applyNametag != null) return applyNametag; + + // Upgrade Item + if (mainItem.is(CMTags.ROOM_UPGRADE_ITEM)) { + final var reg = MachineRoomUpgrades.REGISTRY.get(); + if (mainItem.getItem() instanceof RoomUpgradeItem upItem) { + if (level.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity tile) { + // TODO - Upgrades for legacy machine blocks + /* + tile.roomInfo().ifPresent(room -> { + final var ownerId = room.owner(roomData); + if (!player.getUUID().equals(ownerId)) { + final var ownerName = server.getPlayerList().getPlayer(ownerId).getName(); + player.displayClientMessage(TranslationUtil.message(Messages.NOT_ROOM_OWNER, ownerName), true); + return; + } + + final var upg = RoomUpgradeHelper.getUpgradeId(mainItem); + final var manager = RoomUpgradeManager.get(compactDim); + + if (manager.hasUpgrade(room.code(), upg)) { + player.displayClientMessage(TranslationUtil.message(Messages.ALREADY_HAS_UPGRADE), true); + } else { + final var added = manager.addUpgrade(upg, room.code()); + + if (added) { + player.displayClientMessage(TranslationUtil.message(Messages.UPGRADE_APPLIED) + .withStyle(ChatFormatting.DARK_GREEN), true); + } else { + player.displayClientMessage(TranslationUtil.message(Messages.UPGRADE_ADD_FAILED) + .withStyle(ChatFormatting.DARK_RED), true); + } + } + }); +*/ + } + } + } + + // All other items, open preview screen + if (level.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity machine) { + MachineBlockUtil.roomPreviewScreen(pos, (ServerPlayer) player, server, machine); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } + + public static RoomTemplate getLegacyTemplate(RoomSize size) { + final var temp = switch (size) { + case TINY -> LegacySizedTemplates.EMPTY_TINY; + case SMALL -> LegacySizedTemplates.EMPTY_SMALL; + case NORMAL -> LegacySizedTemplates.EMPTY_NORMAL; + case LARGE -> LegacySizedTemplates.EMPTY_LARGE; + case GIANT -> LegacySizedTemplates.EMPTY_GIANT; + case MAXIMUM -> LegacySizedTemplates.EMPTY_COLOSSAL; + }; + + return temp.template(); + } + + public RoomSize getSize() { + return this.size; + } + + @Override + @SuppressWarnings("deprecation") + public void onRemove(BlockState oldState, Level level, BlockPos pos, BlockState newState, boolean a) { + MinecraftServer server = level.getServer(); + if (level.isClientSide || server == null) { + super.onRemove(oldState, level, pos, newState, a); + return; + } + + MachineBlockUtil.cleanupTunnelsPostMachineRemove(level, pos); + + super.onRemove(oldState, level, pos, newState, a); + } + + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos pPos, BlockState state) { + return new LegacyCompactMachineBlockEntity(pPos, state); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/MachineBlockUtil.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/MachineBlockUtil.java new file mode 100644 index 00000000..621f51b6 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/MachineBlockUtil.java @@ -0,0 +1,190 @@ +package dev.compactmods.machines.forge.machine.block; + +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.forge.config.ServerConfig; +import dev.compactmods.machines.forge.machine.entity.BoundCompactMachineBlockEntity; +import dev.compactmods.machines.forge.room.RoomHelper; +import dev.compactmods.machines.forge.room.Rooms; +import dev.compactmods.machines.forge.room.ui.MachineRoomMenu; +import dev.compactmods.machines.forge.wall.Walls; +import dev.compactmods.machines.i18n.TranslationUtil; +import dev.compactmods.machines.machine.EnumMachinePlayersBreakHandling; +import dev.compactmods.machines.machine.graph.DimensionMachineGraph; +import dev.compactmods.machines.room.exceptions.NonexistentRoomException; +import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; +import dev.compactmods.machines.tunnel.graph.traversal.TunnelMachineFilters; +import dev.compactmods.machines.util.PlayerUtil; +import net.minecraft.commands.Commands; +import net.minecraft.core.BlockPos; +import net.minecraft.core.GlobalPos; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.NameTagItem; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.network.NetworkHooks; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.Nonnull; +import java.util.Optional; +import java.util.UUID; + +@SuppressWarnings("removal") +public class MachineBlockUtil { + + static void cleanupTunnelsPostMachineRemove(Level level, BlockPos pos) { + if (level instanceof ServerLevel sl) { + final var serv = sl.getServer(); + final var compactDim = serv.getLevel(CompactDimension.LEVEL_KEY); + + if (level.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity entity) { + entity.connectedRoom().ifPresent(roomCode -> { + final var dimGraph = DimensionMachineGraph.forDimension(sl); + dimGraph.unregisterMachine(pos); + + if (compactDim == null) + return; + + final var tunnels = TunnelConnectionGraph.forRoom(compactDim, roomCode); + tunnels.positions(TunnelMachineFilters.all(entity.getLevelPosition())) + .forEach(pos1 -> { + tunnels.unregister(pos1); + compactDim.setBlock(pos1, Walls.BLOCK_SOLID_WALL.get().defaultBlockState(), Block.UPDATE_ALL); + }); + }); + } + } + } + + @Nonnull + static InteractionResult tryRoomTeleport(Level level, BlockPos pos, ServerPlayer player, MinecraftServer server) { + // Try teleport to compact machine dimension + if (level.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity tile) { + tile.connectedRoom().ifPresentOrElse(roomCode -> { + try { + RoomHelper.teleportPlayerIntoMachine(level, player, tile.getLevelPosition(), roomCode); + } catch (MissingDimensionException e) { + e.printStackTrace(); + } + }, () -> { + + // AdvancementTriggers.getTriggerForMachineClaim(size).trigger(sp); + }); + + return InteractionResult.SUCCESS; + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } + + /** + * Gets destroy progress, without any lookups on owner, internal players, etcetera. + * + * @param state + * @param player + * @param worldIn + * @param pos + * @return + */ + public static float destroyProgressUnchecked(BlockState state, Player player, BlockGetter worldIn, BlockPos pos) { + int baseSpeedForge = ForgeHooks.isCorrectToolForDrops(state, player) ? 30 : 100; + return player.getDigSpeed(state, pos) / (float) baseSpeedForge; + } + + public static float destroyProgress(BlockState state, Player player, BlockGetter worldIn, BlockPos pos) { + float normalHardness = destroyProgressUnchecked(state, player, worldIn, pos); + + BoundCompactMachineBlockEntity tile = (BoundCompactMachineBlockEntity) worldIn.getBlockEntity(pos); + if (tile == null) + return normalHardness; + + boolean hasPlayers = tile.hasPlayersInside(); + + // If there are players inside, check config for break handling + if (hasPlayers) { + EnumMachinePlayersBreakHandling hand = ServerConfig.MACHINE_PLAYER_BREAK_HANDLING.get(); + switch (hand) { + case UNBREAKABLE: + return 0; + + case OWNER: + Optional ownerUUID = tile.getOwnerUUID(); + return ownerUUID + .map(uuid -> player.getUUID() == uuid ? normalHardness : 0) + .orElse(normalHardness); + + case ANYONE: + return normalHardness; + } + } + + // No players inside - let anyone break it + return normalHardness; + } + + public static void roomPreviewScreen(BlockPos pos, ServerPlayer player, MinecraftServer server, BoundCompactMachineBlockEntity machine) { + machine.connectedRoom().ifPresent(roomCode -> { + try { + final var roomName = Rooms.getRoomName(server, roomCode); + NetworkHooks.openScreen(player, MachineRoomMenu.makeProvider(server, roomCode, machine.getLevelPosition()), (buf) -> { + buf.writeBlockPos(pos); + buf.writeWithCodec(GlobalPos.CODEC, machine.getLevelPosition()); + buf.writeUtf(roomCode); + roomName.ifPresentOrElse(name -> { + buf.writeBoolean(true); + buf.writeUtf(name); + }, () -> { + buf.writeBoolean(false); + buf.writeUtf(""); + }); + }); + } catch (NonexistentRoomException e) { + e.printStackTrace(); + } + }); + } + + @Nullable + public static InteractionResult tryApplyNametag(Level level, BlockPos pos, Player player) { + ItemStack mainItem = player.getMainHandItem(); + if (mainItem.getItem() instanceof NameTagItem && mainItem.hasCustomHoverName()) { + if (level.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity tile) { + final var ownerProfile = tile.getOwnerUUID().flatMap(id -> PlayerUtil.getProfileByUUID(level, id)); + boolean isOwner = ownerProfile.map(p -> p.getId().equals(player.getUUID())).orElse(false); + boolean isOp = player.hasPermissions(Commands.LEVEL_MODERATORS); + + if (ownerProfile.isEmpty()) { + return InteractionResult.FAIL; + } + + if (!isOp || !isOwner) + return InteractionResult.FAIL; + else { + ownerProfile.ifPresent(owner -> { + player.displayClientMessage(TranslationUtil.message(Messages.CANNOT_RENAME_NOT_OWNER, + owner.getName()), true); + }); + } + + tile.connectedRoom().ifPresent(roomCode -> { + try { + final var newName = mainItem.getHoverName().getString(120); + Rooms.updateName(level.getServer(), roomCode, newName); + } catch (NonexistentRoomException e) { + throw new RuntimeException(e); + } + }); + } + } + return null; + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/UnboundCompactMachineBlock.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/UnboundCompactMachineBlock.java new file mode 100644 index 00000000..5648e258 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/block/UnboundCompactMachineBlock.java @@ -0,0 +1,133 @@ +package dev.compactmods.machines.forge.machine.block; + +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.dimension.MissingDimensionException; +import dev.compactmods.machines.api.room.RoomTemplate; +import dev.compactmods.machines.api.shrinking.PSDTags; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.machine.Machines; +import dev.compactmods.machines.forge.machine.entity.UnboundCompactMachineEntity; +import dev.compactmods.machines.forge.machine.item.MachineItemUtil; +import dev.compactmods.machines.forge.machine.item.UnboundCompactMachineItem; +import dev.compactmods.machines.forge.room.RoomHelper; +import dev.compactmods.machines.forge.wall.Walls; +import dev.compactmods.machines.room.exceptions.NonexistentRoomException; +import dev.compactmods.machines.room.graph.CompactRoomProvider; +import dev.compactmods.machines.util.CompactStructureGenerator; +import net.minecraft.core.BlockPos; +import net.minecraft.core.NonNullList; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.stream.Collectors; + +public class UnboundCompactMachineBlock extends CompactMachineBlock implements EntityBlock { + public UnboundCompactMachineBlock(Properties props) { + super(props); + } + + @Override + public ItemStack getCloneItemStack(BlockGetter level, BlockPos pos, BlockState state) { + if (level.getBlockEntity(pos) instanceof UnboundCompactMachineEntity be) { + return UnboundCompactMachineItem.forTemplate(be.templateId().location(), be.template().get()); + } + + return UnboundCompactMachineItem.unbound(); + } + + @Override + public @Nullable BlockEntity newBlockEntity(@NotNull BlockPos pos, @NotNull BlockState state) { + return new UnboundCompactMachineEntity(pos, state); + } + + @Override + public float getDestroyProgress(BlockState state, Player player, BlockGetter level, BlockPos pos) { + return MachineBlockUtil.destroyProgressUnchecked(state, player, level, pos); + } + + @Override + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { + level.getBlockEntity(pos, Machines.UNBOUND_MACHINE_ENTITY.get()).ifPresent(tile -> { + final var template = MachineItemUtil.getTemplateId(stack); + tile.setTemplate(template); + }); + } + + @Override + public void fillItemCategory(@NotNull CreativeModeTab tab, @NotNull NonNullList tabItems) { + var reg = RoomHelper.getTemplates(); + // TODO - fix ordering + tabItems.addAll(reg.entrySet() + .stream() + .map((template) -> UnboundCompactMachineItem.forTemplate(template.getKey().location(), template.getValue())) + .collect(Collectors.toSet())); + } + + @Override + public @NotNull InteractionResult use(@NotNull BlockState state, Level level, @NotNull BlockPos pos, Player player, @NotNull InteractionHand hand, @NotNull BlockHitResult hitResult) { + MinecraftServer server = level.getServer(); + ItemStack mainItem = player.getMainHandItem(); + + if (mainItem.is(PSDTags.ITEM) && player instanceof ServerPlayer sp) { + level.getBlockEntity(pos, Machines.UNBOUND_MACHINE_ENTITY.get()).ifPresent(unboundEntity -> { + RoomTemplate template = unboundEntity.template().orElse(RoomTemplate.INVALID_TEMPLATE); + if(!template.equals(RoomTemplate.INVALID_TEMPLATE)) + { + try { + final var compactDim = CompactDimension.forServer(server); + if (template.equals(RoomTemplate.INVALID_TEMPLATE)) { + CompactMachines.LOGGER.fatal("Tried to create and enter an invalidly-registered room. Something went very wrong!"); + return; + } + + final var roomInfo = CompactRoomProvider.instance(compactDim); + final var newRoom = roomInfo.registerNew(builder -> builder + .setColor(template.color()) + .setDimensions(template.dimensions()) + .setOwner(player.getUUID())); + + // Generate a new machine room + final var unbreakableWall = Walls.BLOCK_SOLID_WALL.get().defaultBlockState(); + CompactStructureGenerator.generateRoom(compactDim, template.dimensions(), newRoom.center(), unbreakableWall); + + // If template specified, prefill new room + if (!template.prefillTemplate().equals(RoomTemplate.NO_TEMPLATE)) { + CompactStructureGenerator.fillWithTemplate(compactDim, template.prefillTemplate(), template.dimensions(), newRoom.center()); + } + + level.setBlock(pos, Machines.MACHINE_BLOCK.get().defaultBlockState(), Block.UPDATE_ALL); + + level.getBlockEntity(pos, Machines.MACHINE_ENTITY.get()).ifPresent(ent -> { + ent.setConnectedRoom(newRoom.code()); + try { + RoomHelper.teleportPlayerIntoRoom(server, sp, newRoom, ent.getLevelPosition()); + } catch (MissingDimensionException | NonexistentRoomException e) { + throw new RuntimeException(e); + } + }); + + } catch (MissingDimensionException e) { + CompactMachines.LOGGER.error("Error occurred while generating new room and machine info for first player entry.", e); + } + } + }); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/entity/BoundCompactMachineBlockEntity.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/entity/BoundCompactMachineBlockEntity.java new file mode 100644 index 00000000..21cfd530 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/entity/BoundCompactMachineBlockEntity.java @@ -0,0 +1,269 @@ +package dev.compactmods.machines.forge.machine.entity; + +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.dimension.MissingDimensionException; +import dev.compactmods.machines.api.machine.IMachineBlockEntity; +import dev.compactmods.machines.api.machine.MachineEntityNbt; +import dev.compactmods.machines.api.machine.MachineNbt; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.machine.Machines; +import dev.compactmods.machines.forge.tunnel.TunnelWallEntity; +import dev.compactmods.machines.forge.tunnel.graph.traversal.ForgeTunnelTypeFilters; +import dev.compactmods.machines.machine.graph.DimensionMachineGraph; +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.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.GlobalPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; +import java.util.UUID; + +@SuppressWarnings("removal") +public class BoundCompactMachineBlockEntity extends BlockEntity implements IMachineBlockEntity { + + protected UUID owner; + private String roomCode; + + private boolean hasMachineColorOverride = false; + private int machineColor; + private int roomColor; + + @Nullable + private Component customName; + + public BoundCompactMachineBlockEntity(BlockPos pos, BlockState state) { + super(Machines.MACHINE_ENTITY.get(), pos, state); + } + + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (level instanceof ServerLevel sl) { + return getConnectedRoom().map(roomId -> { + try { + final var serv = sl.getServer(); + final var compactDim = CompactDimension.forServer(serv); + + final var graph = TunnelConnectionGraph.forRoom(compactDim, roomId); + + final var firstSupported = graph.positions( + TunnelMachineFilters.sided(getLevelPosition(), side), + ForgeTunnelTypeFilters.capability(cap) + ).findFirst(); + + if (firstSupported.isEmpty()) + return super.getCapability(cap, side); + + if (compactDim.getBlockEntity(firstSupported.get()) instanceof TunnelWallEntity tunnel) { + return tunnel.getTunnelCapability(cap, side); + } else { + return super.getCapability(cap, side); + } + } catch (MissingDimensionException e) { + CompactMachines.LOGGER.fatal(e); + return super.getCapability(cap, side); + } + }).orElse(super.getCapability(cap, side)); + } + + return super.getCapability(cap, side); + } + + @Override + public void load(@NotNull CompoundTag nbt) { + super.load(nbt); + + if (nbt.contains(MachineEntityNbt.NBT_ROOM_CODE)) { + this.roomCode = nbt.getString(MachineEntityNbt.NBT_ROOM_CODE); + } + + if (nbt.contains(MachineNbt.OWNER)) { + owner = nbt.getUUID(MachineNbt.OWNER); + } else { + owner = null; + } + + if (nbt.contains(MachineEntityNbt.NBT_CUSTOM_COLOR)) { + machineColor = nbt.getInt(MachineNbt.NBT_COLOR); + hasMachineColorOverride = true; + } + + if (level != null && !level.isClientSide) + this.level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), Block.UPDATE_ALL); + } + + @Override + protected void saveAdditional(@NotNull CompoundTag nbt) { + if (owner != null) { + nbt.putUUID(MachineNbt.OWNER, this.owner); + } + + if (hasMachineColorOverride) { + nbt.putInt(MachineEntityNbt.NBT_CUSTOM_COLOR, machineColor); + } + + if (roomCode != null) + nbt.putString(MachineEntityNbt.NBT_ROOM_CODE, roomCode); + } + + @Override + public CompoundTag getUpdateTag() { + CompoundTag data = super.getUpdateTag(); + + if (this.roomCode != null) { + // data.putString(ROOM_POS_NBT, room); + data.putString(MachineEntityNbt.NBT_ROOM_CODE, roomCode); + } + + if (level instanceof ServerLevel) { + // TODO - Internal player list + if (this.owner != null) + data.putUUID("owner", this.owner); + } + + if (hasMachineColorOverride) + data.putInt(MachineEntityNbt.NBT_CUSTOM_COLOR, machineColor); + else + data.putInt(MachineEntityNbt.NBT_ROOM_COLOR, getColor()); + + return data; + } + + private Optional getConnectedRoom() { + if (level instanceof ServerLevel sl) { + if (roomCode != null) + return Optional.of(roomCode); + + final var graph = DimensionMachineGraph.forDimension(sl); + + var chunk = graph.connectedRoom(worldPosition); + chunk.ifPresent(c -> this.roomCode = c); + return chunk; + } + + return Optional.ofNullable(roomCode); + } + + @Override + public void handleUpdateTag(CompoundTag tag) { + super.handleUpdateTag(tag); + + if (tag.contains("players")) { + CompoundTag players = tag.getCompound("players"); + // playerData = CompactMachinePlayerData.fromNBT(players); + + } + + if (tag.contains(MachineEntityNbt.NBT_ROOM_CODE)) { + this.roomCode = tag.getString(MachineEntityNbt.NBT_ROOM_CODE); + } + + if (tag.contains(MachineEntityNbt.NBT_CUSTOM_COLOR)) { + hasMachineColorOverride = true; + machineColor = tag.getInt(MachineNbt.NBT_COLOR); + } + + if (tag.contains(MachineEntityNbt.NBT_ROOM_COLOR)) { + roomColor = tag.getInt(MachineEntityNbt.NBT_ROOM_COLOR); + } + + if (tag.contains("owner")) + owner = tag.getUUID("owner"); + } + + public Optional getOwnerUUID() { + return Optional.ofNullable(this.owner); + } + + public void setOwner(UUID owner) { + this.owner = owner; + } + + public boolean hasPlayersInside() { + // TODO + return false; + } + + public GlobalPos getLevelPosition() { + return GlobalPos.of(level.dimension(), worldPosition); + } + + public void setConnectedRoom(String roomCode) { + if (level instanceof ServerLevel sl) { + final var dimMachines = DimensionMachineGraph.forDimension(sl); + if (this.roomCode != null) { + dimMachines.unregisterMachine(worldPosition); + } + + dimMachines.register(worldPosition, roomCode); + this.roomCode = roomCode; + + // FIXME - Rooms do not have colors on first creation; this should be pulled from the template! + CompactRoomProvider.instance(sl.getServer()).forRoom(roomCode).ifPresent(roomInfo -> { + this.roomColor = roomInfo.color(); + }); + + this.setChanged(); + } + } + + public void disconnect() { + if (level instanceof ServerLevel sl) { + final var dimMachines = DimensionMachineGraph.forDimension(sl); + dimMachines.unregisterMachine(worldPosition); + + this.roomCode = null; + setChanged(); + } + } + + public Optional getTunnelGraph() { + if (level == null || roomCode == null) return Optional.empty(); + + if (level instanceof ServerLevel sl) { + try { + final var compactDim = CompactDimension.forServer(sl.getServer()); + final var tunnelGraph = TunnelConnectionGraph.forRoom(compactDim, roomCode); + return Optional.of(tunnelGraph); + } catch (MissingDimensionException e) { + return Optional.empty(); + } + } + + return Optional.empty(); + } + + public int getColor() { + return hasMachineColorOverride ? machineColor : roomColor; + } + + public void setColor(int color) { + this.machineColor = color; + this.hasMachineColorOverride = true; + } + + public Optional connectedRoom() { + return Optional.ofNullable(roomCode); + } + + public Optional getCustomName() { + return Optional.ofNullable(customName); + } + + public void setCustomName(Component customName) { + this.customName = customName; + this.setChanged(); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/entity/LegacyCompactMachineBlockEntity.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/entity/LegacyCompactMachineBlockEntity.java new file mode 100644 index 00000000..98ab09ea --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/entity/LegacyCompactMachineBlockEntity.java @@ -0,0 +1,226 @@ +package dev.compactmods.machines.forge.machine.entity; + +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.dimension.MissingDimensionException; +import dev.compactmods.machines.api.machine.MachineEntityNbt; +import dev.compactmods.machines.api.machine.MachineNbt; +import dev.compactmods.machines.api.room.registration.IRoomRegistration; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.machine.Machines; +import dev.compactmods.machines.forge.tunnel.TunnelWallEntity; +import dev.compactmods.machines.forge.tunnel.graph.traversal.ForgeTunnelTypeFilters; +import dev.compactmods.machines.machine.graph.DimensionMachineGraph; +import dev.compactmods.machines.room.graph.CompactRoomProvider; +import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; +import dev.compactmods.machines.tunnel.graph.traversal.TunnelMachineFilters; +import dev.compactmods.machines.util.NbtUtil; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.GlobalPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; +import java.util.Optional; +import java.util.UUID; + +@SuppressWarnings("removal") +@Deprecated(forRemoval = true, since = "5.2.0") +public class LegacyCompactMachineBlockEntity extends BlockEntity { + @Deprecated(forRemoval = true, since = "5.2.0") + public static final String NBT_ROOM_POS = "room_pos"; + private static final String NBT_ROOM_CODE = MachineEntityNbt.NBT_ROOM_CODE; + + protected UUID owner; + private String roomCode; + private int legacyMachineId = -1; + private WeakReference roomInfo; + + public LegacyCompactMachineBlockEntity(BlockPos pos, BlockState state) { + super(Machines.LEGACY_MACHINE_ENTITY.get(), pos, state); + } + + @Nonnull + @Override + public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { + if (level instanceof ServerLevel sl) { + return getConnectedRoom().map(roomId -> { + final var serv = sl.getServer(); + try { + final ServerLevel compactDim = CompactDimension.forServer(serv); + return TunnelConnectionGraph.forRoom(compactDim, roomId) + .tunnels( + TunnelMachineFilters.sided(getLevelPosition(), side), + ForgeTunnelTypeFilters.capability(cap) + ) + .findFirst() + .map(tmi -> { + if (compactDim.getBlockEntity(tmi.location()) instanceof TunnelWallEntity tunnel) { + return tunnel.getTunnelCapability(cap, side); + } else { + return super.getCapability(cap, side); + } + }).orElse(super.getCapability(cap, side)); + } catch (MissingDimensionException e) { + return super.getCapability(cap, side); + } + }).orElse(super.getCapability(cap, side)); + } + + return super.getCapability(cap, side); + } + + @Override + public void onLoad() { + super.onLoad(); + if (this.roomCode == null || this.legacyMachineId == -1) + this.updateLegacyData(); + + roomInfo().ifPresent(r -> this.roomInfo = new WeakReference<>(r)); + } + + @Override + public void load(@NotNull CompoundTag nbt) { + super.load(nbt); + + if (nbt.contains(NBT_ROOM_POS)) { + final var originalRoomPos = NbtUtil.readChunkPos(nbt.get(NBT_ROOM_POS)); + CompactMachines.LOGGER.debug("Machine block has a chunk position specified, it will be rewritten to the new room code system." + + "The block at {} was originally connected to position {}", worldPosition, originalRoomPos); + } + + if (nbt.contains(NBT_ROOM_CODE)) { + this.roomCode = nbt.getString(NBT_ROOM_CODE); + } + + if (nbt.contains(MachineNbt.OWNER)) { + owner = nbt.getUUID(MachineNbt.OWNER); + } else { + owner = null; + } + +// if (level != null && !level.isClientSide) +// this.level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), Block.UPDATE_ALL); + } + + @Override + protected void saveAdditional(CompoundTag nbt) { + // nbt.putString("CustomName", customName.getString()); + + if (owner != null) { + nbt.putUUID(MachineNbt.OWNER, this.owner); + } + + if (roomCode != null) + nbt.putString(NBT_ROOM_CODE, roomCode); + } + + @Override + public CompoundTag getUpdateTag() { + CompoundTag data = super.getUpdateTag(); + + getConnectedRoom().ifPresent(room -> { + data.putString(MachineEntityNbt.NBT_ROOM_CODE, roomCode); + }); + + if (level instanceof ServerLevel) { + // TODO - Internal player list + if (this.owner != null) + data.putUUID(MachineNbt.OWNER, this.owner); + } + + return data; + } + + private void updateLegacyData() { + if (level instanceof ServerLevel sl) { + DimensionMachineGraph graph = DimensionMachineGraph.forDimension(sl); + graph.connectedRoom(worldPosition).ifPresent(roomCode -> { + CompactMachines.LOGGER.info("Rebinding machine {} ({}/{}) to room {}", legacyMachineId, worldPosition, level.dimension(), roomCode); + this.roomCode = roomCode; + this.legacyMachineId = -1; + this.setChanged(); + }); + } + } + + private Optional getConnectedRoom() { + if (level instanceof ServerLevel sl) { + if (roomCode != null) + return Optional.of(roomCode); + + final var graph = DimensionMachineGraph.forDimension(sl); + + var chunk = graph.connectedRoom(worldPosition); + chunk.ifPresent(c -> this.roomCode = c); + return chunk; + } + + return Optional.ofNullable(roomCode); + } + + @Override + public void handleUpdateTag(CompoundTag tag) { + super.handleUpdateTag(tag); + + if (tag.contains("players")) { + CompoundTag players = tag.getCompound("players"); + // playerData = CompactMachinePlayerData.fromNBT(players); + } + + if (tag.contains(MachineEntityNbt.NBT_ROOM_CODE)) { + this.roomCode = tag.getString(MachineEntityNbt.NBT_ROOM_CODE); + } + + if (tag.contains("owner")) + owner = tag.getUUID("owner"); + } + + public Optional getOwnerUUID() { + return Optional.ofNullable(this.owner); + } + + public void setOwner(UUID owner) { + this.owner = owner; + } + + public boolean hasPlayersInside() { + // TODO + return false; + } + + public GlobalPos getLevelPosition() { + return GlobalPos.of(level.dimension(), worldPosition); + } + + public void setConnectedRoom(String room) { + if (level instanceof ServerLevel sl) { + final var dimMachines = DimensionMachineGraph.forDimension(sl); + dimMachines.register(worldPosition, room); + this.roomCode = room; + setChanged(); + } + } + + public void disconnect() { + if (level instanceof ServerLevel sl) { + final var dimMachines = DimensionMachineGraph.forDimension(sl); + dimMachines.unregisterMachine(worldPosition); + this.roomCode = null; + setChanged(); + } + } + + public Optional roomInfo() { + if(level == null || level.isClientSide) return Optional.empty(); + return getConnectedRoom() + .flatMap(code -> CompactRoomProvider.instance(level.getServer()).forRoom(code)); + } +} \ No newline at end of file diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/entity/UnboundCompactMachineEntity.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/entity/UnboundCompactMachineEntity.java new file mode 100644 index 00000000..a63f8a5e --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/entity/UnboundCompactMachineEntity.java @@ -0,0 +1,85 @@ +package dev.compactmods.machines.forge.machine.entity; + +import dev.compactmods.machines.api.core.CMRegistryKeys; +import dev.compactmods.machines.api.machine.IMachineBlockEntity; +import dev.compactmods.machines.api.machine.MachineNbt; +import dev.compactmods.machines.api.room.RoomTemplate; +import dev.compactmods.machines.forge.machine.Machines; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +public class UnboundCompactMachineEntity extends BlockEntity implements IMachineBlockEntity { + + private static final String NBT_TEMPLATE_ID = MachineNbt.NBT_TEMPLATE_ID; + + private ResourceLocation roomTemplateId; + + public UnboundCompactMachineEntity(BlockPos pos, BlockState state) { + super(Machines.UNBOUND_MACHINE_ENTITY.get(), pos, state); + this.roomTemplateId = RoomTemplate.NO_TEMPLATE; + } + + @Override + public void load(@NotNull CompoundTag nbt) { + super.load(nbt); + + if (nbt.contains(NBT_TEMPLATE_ID)) { + roomTemplateId = new ResourceLocation(nbt.getString(NBT_TEMPLATE_ID)); + } + } + + @Override + protected void saveAdditional(@NotNull CompoundTag nbt) { + if (roomTemplateId != null) + nbt.putString(NBT_TEMPLATE_ID, roomTemplateId.toString()); + } + + @Override + public CompoundTag getUpdateTag() { + CompoundTag data = super.getUpdateTag(); + + if (!this.roomTemplateId.equals(RoomTemplate.NO_TEMPLATE)) + data.putString(NBT_TEMPLATE_ID, this.roomTemplateId.toString()); + + return data; + } + + @Override + public void handleUpdateTag(CompoundTag tag) { + super.handleUpdateTag(tag); + + if (tag.contains(NBT_TEMPLATE_ID)) + roomTemplateId = new ResourceLocation(tag.getString(NBT_TEMPLATE_ID)); + } + + public ResourceKey templateId() { + return ResourceKey.create(CMRegistryKeys.ROOM_TEMPLATES, roomTemplateId); + } + + public void setTemplate(ResourceLocation template) { + this.roomTemplateId = template; + this.setChanged(); + } + + public Optional template() { + if (level != null) { + return level.registryAccess() + .registry(CMRegistryKeys.ROOM_TEMPLATES) + .map(reg -> reg.get(roomTemplateId)); + } + + return Optional.empty(); + } + + @Override + public int getColor() { + return this.template().map(RoomTemplate::color).orElse(0xFFFFFFFF); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/item/BoundCompactMachineItem.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/item/BoundCompactMachineItem.java new file mode 100644 index 00000000..a573e538 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/item/BoundCompactMachineItem.java @@ -0,0 +1,119 @@ +package dev.compactmods.machines.forge.machine.item; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.api.core.Tooltips; +import dev.compactmods.machines.api.machine.MachineNbt; +import dev.compactmods.machines.api.room.registration.IBasicRoomInfo; +import dev.compactmods.machines.forge.machine.Machines; +import dev.compactmods.machines.i18n.TranslationUtil; +import dev.compactmods.machines.machine.item.ICompactMachineItem; +import net.minecraft.Util; +import net.minecraft.core.Vec3i; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Optional; + +public class BoundCompactMachineItem extends BlockItem implements ICompactMachineItem { + public static final String ROOM_NBT = "room_pos"; + public static final String ROOM_DIMENSIONS_NBT = "room_dimensions"; + + private static final String FALLBACK_ID = Util.makeDescriptionId("block", new ResourceLocation(Constants.MOD_ID, "bound_machine_fallback")); + + public BoundCompactMachineItem(Properties builder) { + super(Machines.MACHINE_BLOCK.get(), builder); + } + + public static Component name(ItemStack stack) { + return MachineItemUtil.getMachineName(stack) + .map(Component::literal) + .orElse(Component.translatable(FALLBACK_ID)); + } + @Override + public Component getName(ItemStack stack) { + return name(stack); + } + + @NotNull + @Override + public String getDescriptionId(ItemStack stack) { + return FALLBACK_ID; + } + + @Deprecated(forRemoval = true, since = "5.2.0") + public static Optional getMachineId(ItemStack stack) { + if (!stack.hasTag()) + return Optional.empty(); + + CompoundTag machineData = stack.getOrCreateTag(); + if (machineData.contains(MachineNbt.ID)) { + int c = machineData.getInt(MachineNbt.ID); + return c > -1 ? Optional.of(c) : Optional.empty(); + } + + return Optional.empty(); + } + + public static Optional getRoom(ItemStack stack) { + if (!stack.hasTag()) + return Optional.empty(); + + var tag = stack.getTag(); + if (tag == null || !tag.contains(ROOM_NBT)) + return Optional.empty(); + + return Optional.of(tag.getString(ROOM_NBT)); + } + + public static void setRoom(ItemStack stack, String room) { + var tag = stack.getOrCreateTag(); + tag.putString(ROOM_NBT, room); + } + + public static ItemStack createForRoom(IBasicRoomInfo room) { + ItemStack item = new ItemStack(Machines.BOUND_MACHINE_BLOCK_ITEM.get()); + setRoom(item, room.code()); + ICompactMachineItem.setColor(item, room.color()); + return item; + } + + public static Vec3i getRoomSize(ItemStack stack) { + if (!stack.hasTag()) return Vec3i.ZERO; + final var tag = stack.getTag(); + if (tag == null || tag.isEmpty() || !tag.contains(ROOM_DIMENSIONS_NBT)) return Vec3i.ZERO; + final var dimNbt = tag.getIntArray(ROOM_DIMENSIONS_NBT); + return new Vec3i(dimNbt[0], dimNbt[1], dimNbt[2]); + } + + public static ItemStack setRoomSize(ItemStack stack, Vec3i innerBounds) { + var tag = stack.getOrCreateTag(); + tag.putIntArray(ROOM_DIMENSIONS_NBT, new int[]{ + innerBounds.getX(), + innerBounds.getY(), + innerBounds.getZ() + }); + + return stack; + } + + @Override + public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List tooltip, TooltipFlag flagIn) { + // Try room binding; if failed, try old machine ID binding + getRoom(stack).ifPresentOrElse(room -> { + // TODO - Server-synced room name list + tooltip.add(TranslationUtil.tooltip(Tooltips.ROOM_NAME, room)); + }, () -> { + getMachineId(stack).ifPresent(id -> { + tooltip.add(TranslationUtil.tooltip(Tooltips.Machines.ID, id)); + }); + }); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/item/LegacyCompactMachineItem.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/item/LegacyCompactMachineItem.java new file mode 100644 index 00000000..3beaea24 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/item/LegacyCompactMachineItem.java @@ -0,0 +1,73 @@ +package dev.compactmods.machines.forge.machine.item; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.forge.Registries; +import dev.compactmods.machines.forge.machine.block.LegacySizedCompactMachineBlock; +import dev.compactmods.machines.api.core.Tooltips; +import dev.compactmods.machines.api.room.RoomSize; +import dev.compactmods.machines.i18n.TranslationUtil; +import dev.compactmods.machines.forge.machine.Machines; +import dev.compactmods.machines.machine.item.ICompactMachineItem; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +@SuppressWarnings("removal") +@Deprecated(forRemoval = true, since = "5.2.0") +public class LegacyCompactMachineItem extends BlockItem implements ICompactMachineItem { + public static final TagKey TAG = TagKey.create(Registries.ITEMS.getRegistryKey(), + new ResourceLocation(Constants.MOD_ID, "legacy_machines"));; + + public LegacyCompactMachineItem(Block blockIn, Properties builder) { + super(blockIn, builder); + } + + public static Item getItemBySize(RoomSize size) { + return switch (size) { + case TINY -> Machines.MACHINE_BLOCK_ITEM_TINY.get(); + case SMALL -> Machines.MACHINE_BLOCK_ITEM_SMALL.get(); + case NORMAL -> Machines.MACHINE_BLOCK_ITEM_NORMAL.get(); + case LARGE -> Machines.MACHINE_BLOCK_ITEM_LARGE.get(); + case GIANT -> Machines.MACHINE_BLOCK_ITEM_GIANT.get(); + case MAXIMUM -> Machines.MACHINE_BLOCK_ITEM_MAXIMUM.get(); + }; + } + + @Override + public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List tooltip, TooltipFlag flagIn) { + tooltip.add(TranslationUtil.tooltip(Tooltips.CRAFT_TO_UPGRADE).withStyle(ChatFormatting.YELLOW)); + + boolean sneaking = Screen.hasShiftDown(); + + if (sneaking) { + Block b = Block.byItem(stack.getItem()); + if (b instanceof LegacySizedCompactMachineBlock cmb) { + RoomSize size = cmb.getSize(); + int internalSize = size.getInternalSize(); + + MutableComponent text = TranslationUtil.tooltip(Tooltips.Machines.SIZE, internalSize) + .withStyle(ChatFormatting.YELLOW); + + tooltip.add(text); + } + } else { + MutableComponent text = TranslationUtil.tooltip(Tooltips.HINT_HOLD_SHIFT) + .withStyle(ChatFormatting.DARK_GRAY) + .withStyle(ChatFormatting.ITALIC); + + tooltip.add(text); + } + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/item/MachineItemUtil.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/item/MachineItemUtil.java new file mode 100644 index 00000000..f8232353 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/item/MachineItemUtil.java @@ -0,0 +1,54 @@ +package dev.compactmods.machines.forge.machine.item; + +import dev.compactmods.machines.api.machine.MachineNbt; +import dev.compactmods.machines.api.room.RoomTemplate; +import dev.compactmods.machines.forge.room.RoomHelper; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +public class MachineItemUtil { + public static final String NBT_TEMPLATE_ID = MachineNbt.NBT_TEMPLATE_ID; + public static final String NBT_CUSTOM_NAME = "custom_name"; + + public static ItemStack setTemplate(ItemStack stack, ResourceLocation templateId) { + var tag = stack.getOrCreateTag(); + tag.putString(NBT_TEMPLATE_ID, templateId.toString()); + return stack; + } + + @NotNull + public static ResourceLocation getTemplateId(ItemStack stack) { + if (!stack.hasTag()) return RoomTemplate.NO_TEMPLATE; + + final var tag = stack.getTag(); + if (tag == null || tag.isEmpty() || !tag.contains(NBT_TEMPLATE_ID)) + return RoomTemplate.NO_TEMPLATE; + + return new ResourceLocation(tag.getString(NBT_TEMPLATE_ID)); + } + + @NotNull + public static Optional getTemplate(ItemStack stack) { + var template = getTemplateId(stack); + if (!template.equals(RoomTemplate.NO_TEMPLATE)) { + final var actualTemplate = RoomHelper.getTemplates().get(template); + return Optional.ofNullable(actualTemplate); + } + + return Optional.empty(); + } + + public static Optional getMachineName(ItemStack stack) { + if(!stack.hasTag()) return Optional.empty(); + + final var tag = stack.getTag(); + if(!tag.contains(NBT_CUSTOM_NAME, Tag.TAG_STRING)) + return Optional.empty(); + + return Optional.of(tag.getString(NBT_CUSTOM_NAME)); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/machine/item/UnboundCompactMachineItem.java b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/item/UnboundCompactMachineItem.java new file mode 100644 index 00000000..c8c2baad --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/machine/item/UnboundCompactMachineItem.java @@ -0,0 +1,89 @@ +package dev.compactmods.machines.forge.machine.item; + +import dev.compactmods.machines.api.core.Tooltips; +import dev.compactmods.machines.api.machine.MachineEntityNbt; +import dev.compactmods.machines.api.machine.MachineIds; +import dev.compactmods.machines.api.room.RoomTemplate; +import dev.compactmods.machines.forge.machine.Machines; +import dev.compactmods.machines.i18n.TranslationUtil; +import dev.compactmods.machines.machine.item.ICompactMachineItem; +import net.minecraft.ChatFormatting; +import net.minecraft.Util; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.Level; +import net.minecraftforge.registries.ForgeRegistries; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * Represents a machine item that has not been bound to a room yet, + * but has an assigned template to use. + */ +public class UnboundCompactMachineItem extends BlockItem implements ICompactMachineItem { + + public UnboundCompactMachineItem(Properties builder) { + super(Machines.UNBOUND_MACHINE_BLOCK.get(), builder); + } + + @NotNull + @Override + public String getDescriptionId(ItemStack stack) { + return Util.makeDescriptionId("machine", MachineItemUtil.getTemplateId(stack)); + } + + @Override + public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List tooltip, TooltipFlag flagIn) { + // We need NBT data for the rest of this + boolean sneaking = Screen.hasShiftDown(); + + if (sneaking) { + MachineItemUtil.getTemplate(stack).ifPresent(actualTemplate -> { + final var roomDimensions = actualTemplate.dimensions(); + tooltip.add(Component.literal("Size: " + roomDimensions.toShortString()).withStyle(ChatFormatting.YELLOW)); + + final var templateId = MachineItemUtil.getTemplateId(stack); + tooltip.add(Component.literal("Template: " + templateId).withStyle(ChatFormatting.DARK_GRAY)); + + if (!actualTemplate.prefillTemplate().equals(RoomTemplate.NO_TEMPLATE)) { + tooltip.add(Component.literal("Prefill: " + actualTemplate.prefillTemplate()).withStyle(ChatFormatting.DARK_GRAY)); + } + }); + } else { + MutableComponent text = TranslationUtil.tooltip(Tooltips.HINT_HOLD_SHIFT) + .withStyle(ChatFormatting.DARK_GRAY) + .withStyle(ChatFormatting.ITALIC); + + tooltip.add(text); + } + } + + private static ItemLike fromRegistry() { + return ForgeRegistries.ITEMS.getValue(MachineIds.UNBOUND_MACHINE_ITEM_ID); + } + + public static ItemStack unbound() { + final var stack = new ItemStack(fromRegistry(), 1); + MachineItemUtil.setTemplate(stack, RoomTemplate.NO_TEMPLATE); + ICompactMachineItem.setColor(stack, 0xFFFFFFFF); + return stack; + } + + public static ItemStack forTemplate(ResourceLocation templateId, RoomTemplate template) { + final var stack = new ItemStack(fromRegistry(), 1); + MachineItemUtil.setTemplate(stack, templateId); + ICompactMachineItem.setColor(stack, template.color()); + + final var tag = stack.getOrCreateTag(); + tag.putString(MachineEntityNbt.NBT_TEMPLATE_ID, templateId.toString()); + return stack; + } +} diff --git a/src/main/java/dev/compactmods/machines/core/CompactMachinesNet.java b/forge-main/src/main/java/dev/compactmods/machines/forge/network/CompactMachinesNet.java similarity index 55% rename from src/main/java/dev/compactmods/machines/core/CompactMachinesNet.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/network/CompactMachinesNet.java index dcc09de9..ac34bc78 100644 --- a/src/main/java/dev/compactmods/machines/core/CompactMachinesNet.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/network/CompactMachinesNet.java @@ -1,12 +1,9 @@ -package dev.compactmods.machines.core; +package dev.compactmods.machines.forge.network; import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.room.network.PlayerRequestedTeleportPacket; -import dev.compactmods.machines.tunnel.network.TunnelAddedPacket; -import dev.compactmods.machines.util.VersionUtil; +import dev.compactmods.machines.forge.tunnel.network.TunnelAddedPacket; +import dev.compactmods.machines.forge.util.VersionUtil; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.loading.FMLEnvironment; import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.simple.SimpleChannel; @@ -14,16 +11,7 @@ import org.apache.maven.artifact.versioning.DefaultArtifactVersion; public class CompactMachinesNet { - private static final ArtifactVersion PROTOCOL_VERSION; - - - static { - if(FMLEnvironment.production) { - PROTOCOL_VERSION = new DefaultArtifactVersion(ModList.get().getModFileById(Constants.MOD_ID).versionString()); - } else { - PROTOCOL_VERSION = new DefaultArtifactVersion("9.99.999"); - } - } + private static final ArtifactVersion PROTOCOL_VERSION = new DefaultArtifactVersion("5.2.0"); public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( new ResourceLocation(Constants.MOD_ID, "main"), @@ -37,13 +25,25 @@ public static void setupMessages() { CHANNEL.messageBuilder(TunnelAddedPacket.class, 1, NetworkDirection.PLAY_TO_CLIENT) .encoder(TunnelAddedPacket::encode) .decoder(TunnelAddedPacket::new) - .consumer(TunnelAddedPacket::handle) + .consumerMainThread(TunnelAddedPacket::handle) .add(); CHANNEL.messageBuilder(PlayerRequestedTeleportPacket.class, 2, NetworkDirection.PLAY_TO_SERVER) .encoder(PlayerRequestedTeleportPacket::encode) .decoder(PlayerRequestedTeleportPacket::new) - .consumer(PlayerRequestedTeleportPacket::handle) + .consumerMainThread(PlayerRequestedTeleportPacket::handle) + .add(); + + CHANNEL.messageBuilder(SyncRoomMetadataPacket.class, 3, NetworkDirection.PLAY_TO_CLIENT) + .encoder(SyncRoomMetadataPacket::encode) + .decoder(SyncRoomMetadataPacket::new) + .consumerMainThread(SyncRoomMetadataPacket::handle) + .add(); + + CHANNEL.messageBuilder(PlayerRequestedLeavePacket.class, 4, NetworkDirection.PLAY_TO_SERVER) + .encoder(PlayerRequestedLeavePacket::encode) + .decoder(PlayerRequestedLeavePacket::new) + .consumerMainThread(PlayerRequestedLeavePacket::handle) .add(); } } diff --git a/src/main/java/dev/compactmods/machines/room/network/InitialRoomBlockDataPacket.java b/forge-main/src/main/java/dev/compactmods/machines/forge/network/InitialRoomBlockDataPacket.java similarity index 79% rename from src/main/java/dev/compactmods/machines/room/network/InitialRoomBlockDataPacket.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/network/InitialRoomBlockDataPacket.java index 51106c81..3d8eb848 100644 --- a/src/main/java/dev/compactmods/machines/room/network/InitialRoomBlockDataPacket.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/network/InitialRoomBlockDataPacket.java @@ -1,5 +1,6 @@ -package dev.compactmods.machines.room.network; +package dev.compactmods.machines.forge.network; +import dev.compactmods.machines.forge.room.client.ClientRoomPacketHandler; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; @@ -23,7 +24,7 @@ public void toNetwork(FriendlyByteBuf buf) { } public boolean handle(Supplier ctx) { - ctx.get().enqueueWork(() -> ClientRoomNetworkHandler.handleBlockData(this)); + ctx.get().enqueueWork(() -> ClientRoomPacketHandler.handleBlockData(this.blocks)); return true; } } diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/network/PlayerRequestedLeavePacket.java b/forge-main/src/main/java/dev/compactmods/machines/forge/network/PlayerRequestedLeavePacket.java new file mode 100644 index 00000000..c1082f22 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/network/PlayerRequestedLeavePacket.java @@ -0,0 +1,24 @@ +package dev.compactmods.machines.forge.network; + +import dev.compactmods.machines.forge.room.RoomHelper; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +import java.util.function.Supplier; + +public record PlayerRequestedLeavePacket() { + public PlayerRequestedLeavePacket(FriendlyByteBuf friendlyByteBuf) { + this(); + } + + public void handle(Supplier context) { + final var ctx = context.get(); + final var sender = ctx.getSender(); + + RoomHelper.teleportPlayerOutOfRoom(sender); + } + + public void encode(FriendlyByteBuf buffer) { + + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/network/PlayerRequestedTeleportPacket.java b/forge-main/src/main/java/dev/compactmods/machines/forge/network/PlayerRequestedTeleportPacket.java new file mode 100644 index 00000000..05c33ad9 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/network/PlayerRequestedTeleportPacket.java @@ -0,0 +1,37 @@ +package dev.compactmods.machines.forge.network; + +import dev.compactmods.machines.api.dimension.MissingDimensionException; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.room.RoomHelper; +import net.minecraft.core.GlobalPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +import java.util.function.Supplier; + +public record PlayerRequestedTeleportPacket(GlobalPos machine, String room) { + + public PlayerRequestedTeleportPacket(FriendlyByteBuf buf) { + this(buf.readWithCodec(GlobalPos.CODEC), buf.readUtf()); + } + + public void encode(FriendlyByteBuf buf) { + buf.writeWithCodec(GlobalPos.CODEC, machine); + buf.writeUtf(room); + } + + public boolean handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + final var player = ctx.get().getSender(); + if (player != null) { + try { + RoomHelper.teleportPlayerIntoMachine(player.level, player, machine, room); + } catch (MissingDimensionException e) { + CompactMachines.LOGGER.error("Failed to teleport player into machine.", e); + } + } + }); + + return true; + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/network/PlayerStartedRoomTrackingPacket.java b/forge-main/src/main/java/dev/compactmods/machines/forge/network/PlayerStartedRoomTrackingPacket.java new file mode 100644 index 00000000..7b636071 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/network/PlayerStartedRoomTrackingPacket.java @@ -0,0 +1,40 @@ +package dev.compactmods.machines.forge.network; + +import dev.compactmods.machines.forge.room.Rooms; +import dev.compactmods.machines.api.dimension.MissingDimensionException; +import dev.compactmods.machines.room.exceptions.NonexistentRoomException; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.network.PacketDistributor; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Supplier; + +public record PlayerStartedRoomTrackingPacket(String room) { + + public PlayerStartedRoomTrackingPacket(FriendlyByteBuf buf) { + this(buf.readUtf()); + } + + public void encode(FriendlyByteBuf buf) { + buf.writeUtf(room); + } + + public boolean handle(Supplier ctx) { + var sender = ctx.get().getSender(); + ctx.get().enqueueWork(() -> { + StructureTemplate blocks; + try { + blocks = Rooms.getInternalBlocks(sender.server, room).get(5, TimeUnit.SECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException | MissingDimensionException | NonexistentRoomException e) { + throw new RuntimeException(e); + } + RoomNetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> sender), new InitialRoomBlockDataPacket(blocks)); + }); + + return true; + } +} diff --git a/src/main/java/dev/compactmods/machines/room/network/RoomNetworkHandler.java b/forge-main/src/main/java/dev/compactmods/machines/forge/network/RoomNetworkHandler.java similarity index 83% rename from src/main/java/dev/compactmods/machines/room/network/RoomNetworkHandler.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/network/RoomNetworkHandler.java index 8f5de386..6dd2bfdc 100644 --- a/src/main/java/dev/compactmods/machines/room/network/RoomNetworkHandler.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/network/RoomNetworkHandler.java @@ -1,7 +1,7 @@ -package dev.compactmods.machines.room.network; +package dev.compactmods.machines.forge.network; +import dev.compactmods.machines.forge.util.VersionUtil; import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.util.VersionUtil; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkRegistry; @@ -11,7 +11,7 @@ public class RoomNetworkHandler { - private static final ArtifactVersion ROOM_TRACK_VERSION = new DefaultArtifactVersion("1.0.0"); + private static final ArtifactVersion ROOM_TRACK_VERSION = new DefaultArtifactVersion("2.0.0"); public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( new ResourceLocation(Constants.MOD_ID, "room_tracking"), @@ -24,13 +24,13 @@ public static void setupMessages() { CHANNEL.messageBuilder(PlayerStartedRoomTrackingPacket.class, 1, NetworkDirection.PLAY_TO_SERVER) .encoder(PlayerStartedRoomTrackingPacket::encode) .decoder(PlayerStartedRoomTrackingPacket::new) - .consumer(PlayerStartedRoomTrackingPacket::handle) + .consumerMainThread(PlayerStartedRoomTrackingPacket::handle) .add(); CHANNEL.messageBuilder(InitialRoomBlockDataPacket.class, 2, NetworkDirection.PLAY_TO_CLIENT) .encoder(InitialRoomBlockDataPacket::toNetwork) .decoder(InitialRoomBlockDataPacket::fromNetwork) - .consumer(InitialRoomBlockDataPacket::handle) + .consumerMainThread(InitialRoomBlockDataPacket::handle) .add(); } } diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/network/SyncRoomMetadataPacket.java b/forge-main/src/main/java/dev/compactmods/machines/forge/network/SyncRoomMetadataPacket.java new file mode 100644 index 00000000..6c903ad4 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/network/SyncRoomMetadataPacket.java @@ -0,0 +1,24 @@ +package dev.compactmods.machines.forge.network; + +import dev.compactmods.machines.forge.room.client.ClientRoomPacketHandler; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +import java.util.UUID; +import java.util.function.Supplier; + +public record SyncRoomMetadataPacket(String roomCode, UUID owner) { + public SyncRoomMetadataPacket(FriendlyByteBuf buffer) { + this(buffer.readUtf(), buffer.readUUID()); + } + + public void encode(FriendlyByteBuf buffer) { + buffer.writeUtf(roomCode); + buffer.writeUUID(owner); + } + + public void handle(Supplier contextSupplier) { + ClientRoomPacketHandler.handleRoomSync(this.roomCode, this.owner); + contextSupplier.get().setPacketHandled(true); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/ForgeCompactRoomProvider.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ForgeCompactRoomProvider.java new file mode 100644 index 00000000..1f592fe3 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ForgeCompactRoomProvider.java @@ -0,0 +1,24 @@ +package dev.compactmods.machines.forge.room; + +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.dimension.MissingDimensionException; +import dev.compactmods.machines.room.graph.CompactRoomProvider; +import net.minecraft.server.level.ServerLevel; +import net.minecraftforge.server.ServerLifecycleHooks; +import org.jetbrains.annotations.Nullable; + +import static dev.compactmods.machines.room.graph.CompactRoomProvider.DATA_NAME; + +public class ForgeCompactRoomProvider { + @Nullable + public static CompactRoomProvider instance() { + try { + final ServerLevel level = CompactDimension.forServer(ServerLifecycleHooks.getCurrentServer()); + return level.getDataStorage() + .computeIfAbsent(CompactRoomProvider::fromDisk, CompactRoomProvider::empty, DATA_NAME); + } catch (MissingDimensionException e) { + CompactRoomProvider.LOGS.fatal(e); + return null; + } + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/ForgeRoomServerHelper.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ForgeRoomServerHelper.java new file mode 100644 index 00000000..bb428d4a --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ForgeRoomServerHelper.java @@ -0,0 +1,14 @@ +package dev.compactmods.machines.forge.room; + +import dev.compactmods.machines.api.room.RoomTemplate; +import dev.compactmods.machines.room.server.RoomServerHelper; +import net.minecraft.core.Registry; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class ForgeRoomServerHelper extends RoomServerHelper { + + public static Registry getTemplates() { + final var serv = ServerLifecycleHooks.getCurrentServer(); + return getTemplates(serv); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/PlayerRoomMetadataProvider.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/PlayerRoomMetadataProvider.java new file mode 100644 index 00000000..cdb77319 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/PlayerRoomMetadataProvider.java @@ -0,0 +1,65 @@ +package dev.compactmods.machines.forge.room; + +import dev.compactmods.machines.api.room.IPlayerRoomMetadata; +import dev.compactmods.machines.api.room.IPlayerRoomMetadataProvider; +import net.minecraftforge.common.util.LazyOptional; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; +import java.util.UUID; + +public class PlayerRoomMetadataProvider implements IPlayerRoomMetadataProvider { + + @Nullable + private IPlayerRoomMetadata currentRoom; + + private final LazyOptional lazy; + + public PlayerRoomMetadataProvider() { + this.lazy = LazyOptional.of(this::lazyRoom).cast(); + } + + private IPlayerRoomMetadata lazyRoom() { + return currentRoom; + } + + public LazyOptional getRoomLazy() { + if(currentRoom == null) + return LazyOptional.empty(); + + return lazy; + } + + @Override + public Optional currentRoom() { + return Optional.ofNullable(currentRoom); + } + + @Override + public Optional roomCode() { + if(currentRoom == null) + return Optional.empty(); + + return Optional.of(currentRoom.roomCode()); + } + + @Override + public Optional owner() { + if(currentRoom == null) return Optional.empty(); + return Optional.of(currentRoom.owner()); + } + + @Override + public void clearCurrent() { + this.currentRoom = null; + this.lazy.invalidate(); + } + + @Override + public void setCurrent(IPlayerRoomMetadata current) { + this.currentRoom = current; + this.lazy.invalidate(); + } + + public record CurrentRoomData(String roomCode, UUID owner) implements IPlayerRoomMetadata {} +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/RoomClientEventHandler.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/RoomClientEventHandler.java new file mode 100644 index 00000000..d60d936d --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/RoomClientEventHandler.java @@ -0,0 +1,18 @@ +package dev.compactmods.machines.forge.room; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.forge.room.ui.overlay.RoomMetadataDebugOverlay; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.RegisterGuiOverlaysEvent; +import net.minecraftforge.client.gui.overlay.VanillaGuiOverlay; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(modid = Constants.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD) +public class RoomClientEventHandler { + + @SubscribeEvent + public static void onOverlayRegistration(final RegisterGuiOverlaysEvent overlays) { + overlays.registerAbove(VanillaGuiOverlay.DEBUG_TEXT.id(), "room_meta_debug", new RoomMetadataDebugOverlay()); + } +} diff --git a/src/main/java/dev/compactmods/machines/room/RoomEventHandler.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/RoomEventHandler.java similarity index 61% rename from src/main/java/dev/compactmods/machines/room/RoomEventHandler.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/room/RoomEventHandler.java index 768f9840..4e585f9b 100644 --- a/src/main/java/dev/compactmods/machines/room/RoomEventHandler.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/RoomEventHandler.java @@ -1,11 +1,13 @@ -package dev.compactmods.machines.room; +package dev.compactmods.machines.forge.room; import dev.compactmods.machines.api.core.Constants; import dev.compactmods.machines.api.core.Messages; import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.room.registration.IRoomRegistration; +import dev.compactmods.machines.forge.network.CompactMachinesNet; import dev.compactmods.machines.i18n.TranslationUtil; -import dev.compactmods.machines.room.data.CompactRoomData; -import dev.compactmods.machines.room.exceptions.NonexistentRoomException; +import dev.compactmods.machines.forge.network.SyncRoomMetadataPacket; +import dev.compactmods.machines.room.graph.CompactRoomProvider; import net.minecraft.ChatFormatting; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -20,6 +22,7 @@ import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.network.PacketDistributor; @Mod.EventBusSubscriber(modid = Constants.MOD_ID) public class RoomEventHandler { @@ -28,14 +31,27 @@ public class RoomEventHandler { public static void entityJoined(final EntityJoinLevelEvent evt) { Entity ent = evt.getEntity(); - // Early exit if spawning in non-CM dimensions - if ((ent instanceof Player) || !ent.level.dimension().equals(CompactDimension.LEVEL_KEY)) return; - - // no-op clients, we only care about blocking server spawns - if(ent.level.isClientSide) return; - - if (!positionInsideRoom(ent, ent.position())) { - evt.setCanceled(true); + boolean isPlayer = ent instanceof Player; + boolean isCompact = CompactDimension.isLevelCompact(ent.level); + + // no-op clients and non-compact dimensions, we only care about server spawns + if (!isCompact || ent.level.isClientSide) + return; + + // Handle players + if (isPlayer && ent instanceof ServerPlayer serverPlayer) { + // sync current room info to client player + final var roomProvider = CompactRoomProvider.instance(serverPlayer.getLevel()); + roomProvider.findByChunk(serverPlayer.chunkPosition()).ifPresent(roomInfo -> { + CompactMachinesNet.CHANNEL.send( + PacketDistributor.PLAYER.with(() -> serverPlayer), + new SyncRoomMetadataPacket(roomInfo.code(), roomInfo.owner(roomProvider)) + ); + }); + } else { + if (!positionInsideRoom(ent, ent.position())) { + evt.setCanceled(true); + } } } @@ -55,7 +71,7 @@ public static void onCheckSpawn(final LivingSpawnEvent.CheckSpawn evt) { public static void onEntityTeleport(final EntityTeleportEvent evt) { // Allow teleport commands, we don't want to trap people anywhere if (evt instanceof EntityTeleportEvent.TeleportCommand) return; - if(!evt.getEntity().level.dimension().equals(CompactDimension.LEVEL_KEY)) return; + if (!evt.getEntity().level.dimension().equals(CompactDimension.LEVEL_KEY)) return; Entity ent = evt.getEntity(); doEntityTeleportHandle(evt, evt.getTarget(), ent); @@ -75,14 +91,14 @@ private static boolean positionInsideRoom(Entity entity, Vec3 target) { if (!level.dimension().equals(CompactDimension.LEVEL_KEY)) return false; if (level instanceof ServerLevel compactDim) { - ChunkPos machineChunk = new ChunkPos(entity.chunkPosition().x, entity.chunkPosition().z); - - try { - final CompactRoomData intern = CompactRoomData.get(compactDim); - return intern.getBounds(machineChunk).contains(target); - } catch (NonexistentRoomException e) { - return false; - } + ChunkPos playerChunk = entity.chunkPosition(); + final var roomInfo = CompactRoomProvider.instance(compactDim); + return roomInfo.isRoomChunk(playerChunk) + ? roomInfo.findByChunk(playerChunk) + .map(IRoomRegistration::innerBounds) + .map(ib -> ib.contains(target)) + .orElse(false) + : false; } return false; diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/RoomHelper.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/RoomHelper.java new file mode 100644 index 00000000..a759f5fe --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/RoomHelper.java @@ -0,0 +1,157 @@ +package dev.compactmods.machines.forge.room; + +import dev.compactmods.machines.advancement.AdvancementTriggers; +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.dimension.MissingDimensionException; +import dev.compactmods.machines.api.room.IPlayerRoomMetadataProvider; +import dev.compactmods.machines.api.room.RoomTemplate; +import dev.compactmods.machines.api.room.history.IRoomHistoryItem; +import dev.compactmods.machines.api.room.registration.IRoomRegistration; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.dimension.SimpleTeleporter; +import dev.compactmods.machines.forge.network.CompactMachinesNet; +import dev.compactmods.machines.forge.network.SyncRoomMetadataPacket; +import dev.compactmods.machines.forge.room.capability.RoomCapabilities; +import dev.compactmods.machines.forge.util.ForgePlayerUtil; +import dev.compactmods.machines.location.PreciseDimensionalPosition; +import dev.compactmods.machines.room.client.RoomClientHelper; +import dev.compactmods.machines.room.exceptions.NonexistentRoomException; +import dev.compactmods.machines.room.graph.CompactRoomProvider; +import dev.compactmods.machines.room.history.PlayerRoomHistoryItem; +import dev.compactmods.machines.util.PlayerUtil; +import net.minecraft.core.GlobalPos; +import net.minecraft.core.Registry; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.PacketDistributor; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.Nonnull; + +public class RoomHelper { + + public static final Capability CURRENT_ROOM_META = CapabilityManager.get(new CapabilityToken<>() { + }); + + public static Registry getTemplates() { + return DistExecutor.safeRunForDist(() -> RoomClientHelper::getTemplates, () -> ForgeRoomServerHelper::getTemplates); + } + + public static void teleportPlayerIntoMachine(Level machineLevel, ServerPlayer player, GlobalPos machinePos, String roomCode) throws MissingDimensionException { + MinecraftServer serv = machineLevel.getServer(); + + CompactRoomProvider.instance(serv) + .forRoom(roomCode) + .ifPresent(roomInfo -> { + // Recursion check. Player tried to enter the room they're already in. + if (player.level.dimension().equals(CompactDimension.LEVEL_KEY)) { + final boolean recursion = player.getCapability(RoomCapabilities.ROOM_HISTORY).map(hist -> { + if (roomInfo.chunks().anyMatch(chunk -> player.chunkPosition().equals(chunk))) { + AdvancementTriggers.RECURSIVE_ROOMS.trigger(player); + return true; + } + + return false; + }).orElse(false); + + if (recursion) return; + } + + try { + final var entry = PreciseDimensionalPosition.fromPlayer(player); + + teleportPlayerIntoRoom(serv, player, roomInfo); + + // Mark the player as inside the machine, set external spawn, and yeet + player.getCapability(RoomCapabilities.ROOM_HISTORY).ifPresent(hist -> { + hist.addHistory(new PlayerRoomHistoryItem(entry, machinePos)); + }); + } catch (MissingDimensionException | NonexistentRoomException e) { + CompactMachines.LOGGER.fatal("Critical error; could not enter a freshly-created room instance.", e); + } + }); + } + + public static void setCurrentRoom(MinecraftServer server, ServerPlayer player, IRoomRegistration room) { + // Mark current room, invalidates any listeners + debug screen + final var roomProvider = CompactRoomProvider.instance(server); + final var roomOwner = room.owner(roomProvider); + player.getCapability(CURRENT_ROOM_META).ifPresent(provider -> { + provider.setCurrent(new PlayerRoomMetadataProvider.CurrentRoomData(room.code(), roomOwner)); + }); + + final var sync = new SyncRoomMetadataPacket(room.code(), roomOwner); + CompactMachinesNet.CHANNEL.send(PacketDistributor.PLAYER.with(() -> player), sync); + } + + public static void teleportPlayerIntoRoom(MinecraftServer serv, ServerPlayer player, IRoomRegistration room) throws MissingDimensionException, NonexistentRoomException { + teleportPlayerIntoRoom(serv, player, room, null); + } + + public static void teleportPlayerIntoRoom(MinecraftServer serv, ServerPlayer player, IRoomRegistration room, @Nullable GlobalPos from) + throws MissingDimensionException, NonexistentRoomException { + final var compactDim = CompactDimension.forServer(serv); + final var roomProvider = CompactRoomProvider.instance(compactDim); + + serv.submitAsync(() -> { + player.changeDimension(compactDim, SimpleTeleporter.to(room.spawnPosition(roomProvider), room.spawnRotation(roomProvider))); + }); + + if (from != null) { + // Mark the player as inside the machine, set external spawn + player.getCapability(RoomCapabilities.ROOM_HISTORY).ifPresent(hist -> { + var entry = PreciseDimensionalPosition.fromPlayer(player); + hist.addHistory(new PlayerRoomHistoryItem(entry, from)); + }); + } + + // Mark current room, invalidates any listeners + debug screen + RoomHelper.setCurrentRoom(serv, player, room); + } + + public static void teleportPlayerOutOfRoom(@Nonnull ServerPlayer serverPlayer) { + + MinecraftServer serv = serverPlayer.getServer(); + if (!serverPlayer.level.dimension().equals(CompactDimension.LEVEL_KEY)) + return; + + serverPlayer.getCapability(RoomCapabilities.ROOM_HISTORY) + .resolve() + .ifPresentOrElse(hist -> { + if (hist.hasHistory()) { + final var roomProvider = CompactRoomProvider.instance(serv); + final IRoomHistoryItem prevArea = hist.pop(); + // Mark current room, invalidates any listeners + debug screen + serverPlayer.getCapability(CURRENT_ROOM_META).ifPresent(provider -> { + // Check entry dimension - if it isn't a machine room, clear room info + if (!prevArea.getEntryLocation().dimension().equals(CompactDimension.LEVEL_KEY)) + provider.clearCurrent(); + else { + roomProvider.findByChunk(prevArea.getEntryLocation().chunkPos()).ifPresent(roomMeta -> { + provider.setCurrent(new PlayerRoomMetadataProvider.CurrentRoomData(roomMeta.code(), roomMeta.owner(roomProvider))); + }); + } + }); + + var spawnPoint = prevArea.getEntryLocation(); + final var enteredMachine = prevArea.getMachine().pos(); + + final var level = spawnPoint.level(serv); + serverPlayer.changeDimension(level, SimpleTeleporter.lookingAt(spawnPoint.position(), enteredMachine)); + } else { + PlayerUtil.howDidYouGetThere(serverPlayer); + + hist.clear(); + ForgePlayerUtil.teleportPlayerToRespawnOrOverworld(serv, serverPlayer); + } + }, () -> { + PlayerUtil.howDidYouGetThere(serverPlayer); + ForgePlayerUtil.teleportPlayerToRespawnOrOverworld(serv, serverPlayer); + }); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/Rooms.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/Rooms.java new file mode 100644 index 00000000..e9f213d2 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/Rooms.java @@ -0,0 +1,152 @@ +package dev.compactmods.machines.forge.room; + +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.dimension.MissingDimensionException; +import dev.compactmods.machines.api.room.RoomTemplate; +import dev.compactmods.machines.forge.Registries; +import dev.compactmods.machines.room.exceptions.NonexistentRoomException; +import dev.compactmods.machines.room.graph.CompactRoomProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.chunk.ChunkStatus; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraftforge.registries.IForgeRegistry; +import net.minecraftforge.registries.RegistryBuilder; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; + +public class Rooms { + + public static Supplier> TEMPLATES = Registries.ROOM_TEMPLATES + .makeRegistry(() -> new RegistryBuilder() + .dataPackRegistry(RoomTemplate.CODEC, RoomTemplate.CODEC)); + + public static void prepare() { + } + + /* + TODO - Revisit with furnace recipe + public static boolean destroy(MinecraftServer server, ChunkPos room) throws MissingDimensionException, NonexistentRoomException { + final var compactDim = server.getLevel(Registration.COMPACT_DIMENSION); + if (compactDim == null) + throw new MissingDimensionException(); + + var roomData = CompactRoomData.get(compactDim); + if (!roomData.isRegistered(room)) { + throw new NonexistentRoomException(room); + } + + final var roomBounds = roomData.getBounds(room); + final var innerBounds = roomBounds.deflate(1); + + final var states = compactDim.getBlockStates(innerBounds) + .collect(Collectors.toSet()); + + final var nonAir = states.stream() + .filter(state -> !state.isAir()) + .findAny(); + + if (nonAir.isPresent()) { + CompactMachines.LOGGER.error("Refusing to delete room at {}; non-air blocks exist inside the room. First match: {}", room, nonAir.get()); + return false; + } + + // clear tunnel connection info + final var tunnels = RoomTunnelData.getFile(server, room); + final var filename = RoomTunnelData.getDataFilename(room); + if (!tunnels.delete()) { + CompactMachines.LOGGER.warn("Could not delete tunnel data for room {}; clearing the connection graph as an alternative.", room); + CompactMachines.LOGGER.warn("Data file to delete: {}", filename); + + var td = RoomTunnelData.forRoom(server, room); + td.getGraph().clear(); + td.setDirty(); + } else { + // File deletion successful, delete cached data + final var compactDataCache = compactDim.getDataStorage().cache; + compactDataCache.remove(filename); + } + + // reset everything for the room boundary + BlockPos.betweenClosedStream(roomBounds.inflate(1)) + .forEach(p -> compactDim.setBlock(p, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL)); + + // Remove room registration + roomData.remove(room); + + // Disconnect all machines + var conns = MachineToRoomConnections.forDimension(server); + var d = CompactMachineData.get(server); + + var connected = conns.getMachinesFor(room); + for (int mid : connected) { + var location = d.getMachineLocation(mid); + location.ifPresent(p -> { + var pos = p.getBlockPosition(); + var l = p.level(server); + if (l.getBlockEntity(pos) instanceof TunnelWallEntity tunn) { + tunn.disconnect(); + } + }); + } + + conns.unregisterRoom(room); + return true; + } +*/ + + public static CompletableFuture getInternalBlocks(MinecraftServer server, String room) throws MissingDimensionException, NonexistentRoomException { + final var tem = new StructureTemplate(); + + final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); + final var provider = CompactRoomProvider.instance(compactDim); + + final var chunkSource = compactDim.getChunkSource(); + return provider.forRoom(room).map(reg -> { + final var chunkLoading = reg.chunks() + .map(cp -> chunkSource.getChunkFuture(cp.x, cp.z, ChunkStatus.FULL, true)) + .toList(); + + final var awaitAllChunks = CompletableFuture.allOf(chunkLoading.toArray(new CompletableFuture[chunkLoading.size()])); + + return awaitAllChunks.thenApply(ignored -> { + final var bounds = reg.outerBounds(); + tem.fillFromWorld(compactDim, + new BlockPos(bounds.minX, bounds.minY - 1, bounds.minZ), + new Vec3i(bounds.getXsize(), bounds.getYsize() + 1, bounds.getZsize()), + false, Blocks.AIR + ); + + return tem; + }); + }).orElse(CompletableFuture.completedFuture(tem)); + } + + public static Optional getRoomName(MinecraftServer server, String room) throws NonexistentRoomException { +// if (!exists(server, room)) +// throw new NonexistentRoomException(room); +// +// final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); +// +// final var data = RoomData.get(compactDim); +// final var roomInfo = data.getData(room); +// return roomInfo.getName(); + return Optional.empty(); + } + + public static void updateName(MinecraftServer server, String room, String newName) throws NonexistentRoomException { +// if (!exists(server, room)) +// throw new NonexistentRoomException(room); +// +// final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); +// +// final var data = RoomData.get(compactDim); +// final var roomInfo = data.getData(room); +// roomInfo.setName(newName); +// data.setDirty(); + } +} diff --git a/src/main/java/dev/compactmods/machines/room/capability/CMRoomHistory.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/CMRoomHistory.java similarity index 89% rename from src/main/java/dev/compactmods/machines/room/capability/CMRoomHistory.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/CMRoomHistory.java index 50f6371a..618b674b 100644 --- a/src/main/java/dev/compactmods/machines/room/capability/CMRoomHistory.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/CMRoomHistory.java @@ -1,16 +1,16 @@ -package dev.compactmods.machines.room.capability; +package dev.compactmods.machines.forge.room.capability; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.Optional; import com.mojang.serialization.DataResult; import dev.compactmods.machines.api.room.IRoomHistory; -import dev.compactmods.machines.api.codec.NbtListCollector; -import dev.compactmods.machines.api.room.history.IRoomHistoryItem; +import dev.compactmods.machines.codec.NbtListCollector; import dev.compactmods.machines.room.history.PlayerRoomHistoryItem; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtOps; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Optional; + public class CMRoomHistory implements IRoomHistory { private final Deque history; @@ -44,7 +44,6 @@ public void addHistory(PlayerRoomHistoryItem item) { history.add(item); } - @Override public ListTag serializeNBT() { return history.stream() .map(hi -> PlayerRoomHistoryItem.CODEC.encodeStart(NbtOps.INSTANCE, hi)) @@ -55,7 +54,6 @@ public ListTag serializeNBT() { .collect(NbtListCollector.toNbtList()); } - @Override public void deserializeNBT(ListTag nbt) { nbt.stream() .map(it -> PlayerRoomHistoryItem.CODEC.parse(NbtOps.INSTANCE, it)) diff --git a/src/main/java/dev/compactmods/machines/room/capability/PlayerRoomHistoryCapProvider.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/PlayerRoomHistoryProvider.java similarity index 76% rename from src/main/java/dev/compactmods/machines/room/capability/PlayerRoomHistoryCapProvider.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/PlayerRoomHistoryProvider.java index 27ae8414..c340f0b1 100644 --- a/src/main/java/dev/compactmods/machines/room/capability/PlayerRoomHistoryCapProvider.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/PlayerRoomHistoryProvider.java @@ -1,25 +1,23 @@ -package dev.compactmods.machines.room.capability; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +package dev.compactmods.machines.forge.room.capability; import dev.compactmods.machines.api.room.IRoomHistory; -import dev.compactmods.machines.room.RoomCapabilities; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; -import net.minecraft.world.entity.player.Player; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.common.util.LazyOptional; -public class PlayerRoomHistoryCapProvider implements ICapabilityProvider, INBTSerializable { +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class PlayerRoomHistoryProvider implements ICapabilityProvider, INBTSerializable { private final CMRoomHistory history; - private LazyOptional opt = LazyOptional.empty(); + private final LazyOptional opt; - public PlayerRoomHistoryCapProvider(Player player) { + public PlayerRoomHistoryProvider() { this.history = new CMRoomHistory(); this.opt = LazyOptional.of(() -> this.history); } diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/PlayerRoomMetadataProviderProvider.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/PlayerRoomMetadataProviderProvider.java new file mode 100644 index 00000000..836b28ea --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/PlayerRoomMetadataProviderProvider.java @@ -0,0 +1,58 @@ +package dev.compactmods.machines.forge.room.capability; + +import dev.compactmods.machines.forge.room.PlayerRoomMetadataProvider; +import dev.compactmods.machines.api.room.IPlayerRoomMetadataProvider; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.common.util.LazyOptional; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +// Provider provider. Because Java. +public class PlayerRoomMetadataProviderProvider implements ICapabilityProvider, INBTSerializable { + private static final Capability CURRENT_ROOM_META = CapabilityManager.get(new CapabilityToken<>() { + }); + + private final IPlayerRoomMetadataProvider provider; + + private final LazyOptional lazy; + + public PlayerRoomMetadataProviderProvider() { + provider = new PlayerRoomMetadataProvider(); + lazy = LazyOptional.of(this::getCurrentRoomMetadataProvider); + } + + private IPlayerRoomMetadataProvider getCurrentRoomMetadataProvider() { + return this.provider; + } + + @Override + public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if(cap == CURRENT_ROOM_META) + return lazy.cast(); + + return LazyOptional.empty(); + } + + @Override + public CompoundTag serializeNBT() { + final var tag = new CompoundTag(); + provider.currentRoom().ifPresent(meta -> { + tag.putString("room", meta.roomCode()); + tag.putUUID("owner", meta.owner()); + }); + + return tag; + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + if(nbt.isEmpty()) return; + provider.setCurrent(new PlayerRoomMetadataProvider.CurrentRoomData(nbt.getString("room"), nbt.getUUID("owner"))); + } +} diff --git a/src/main/java/dev/compactmods/machines/room/capability/RoomCapEventHandler.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/RoomCapEventHandler.java similarity index 74% rename from src/main/java/dev/compactmods/machines/room/capability/RoomCapEventHandler.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/RoomCapEventHandler.java index 38e31b29..997a8665 100644 --- a/src/main/java/dev/compactmods/machines/room/capability/RoomCapEventHandler.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/RoomCapEventHandler.java @@ -1,4 +1,4 @@ -package dev.compactmods.machines.room.capability; +package dev.compactmods.machines.forge.room.capability; import dev.compactmods.machines.api.core.Constants; import net.minecraft.resources.ResourceLocation; @@ -18,6 +18,9 @@ static void onCapPlayerAttach(final AttachCapabilitiesEvent event) { event.addCapability( new ResourceLocation(Constants.MOD_ID, "room_history"), - new PlayerRoomHistoryCapProvider(player)); + new PlayerRoomHistoryProvider()); + + final var meta = new PlayerRoomMetadataProviderProvider(); + event.addCapability(new ResourceLocation(Constants.MOD_ID, "room_metadata"), meta); } } diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/RoomCapabilities.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/RoomCapabilities.java new file mode 100644 index 00000000..e8cc1a66 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/capability/RoomCapabilities.java @@ -0,0 +1,14 @@ +package dev.compactmods.machines.forge.room.capability; + +import dev.compactmods.machines.api.room.IRoomHistory; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; + +public class RoomCapabilities { + + public static final Capability ROOM_HISTORY = CapabilityManager.get(new CapabilityToken<>() { + }); + + +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/client/ClientRoomPacketHandler.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/client/ClientRoomPacketHandler.java new file mode 100644 index 00000000..4a1c7461 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/client/ClientRoomPacketHandler.java @@ -0,0 +1,30 @@ +package dev.compactmods.machines.forge.room.client; + +import dev.compactmods.machines.forge.room.RoomHelper; +import dev.compactmods.machines.forge.room.ui.MachineRoomScreen; +import dev.compactmods.machines.room.client.ClientRoomMetadata; +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; + +import java.util.UUID; + +public class ClientRoomPacketHandler { + public static void handleBlockData(StructureTemplate blocks) { + final var mc = Minecraft.getInstance(); + if(mc.screen instanceof MachineRoomScreen mrs) { + mrs.getMenu().setBlocks(blocks); + mrs.updateBlockRender(); + } + } + + public static void handleRoomSync(String roomCode, UUID owner) { + final var mc = Minecraft.getInstance(); + mc.player.getCapability(RoomHelper.CURRENT_ROOM_META).ifPresent(meta -> { + if(owner.equals(Util.NIL_UUID)) + meta.clearCurrent(); + else + meta.setCurrent(new ClientRoomMetadata(roomCode, owner)); + }); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/data/AllRoomsDataFile.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/data/AllRoomsDataFile.java new file mode 100644 index 00000000..f787c880 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/data/AllRoomsDataFile.java @@ -0,0 +1,314 @@ +package dev.compactmods.machines.forge.room.data; + +import com.google.common.graph.MutableValueGraph; +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.dimension.MissingDimensionException; +import dev.compactmods.machines.codec.NbtListCollector; +import dev.compactmods.machines.graph.GraphTraversalHelper; +import dev.compactmods.machines.graph.edge.IGraphEdge; +import dev.compactmods.machines.graph.node.IGraphNode; +import dev.compactmods.machines.room.RoomCodeGenerator; +import dev.compactmods.machines.room.graph.NewRoomBuilder; +import dev.compactmods.machines.room.graph.edge.RoomChunkEdge; +import dev.compactmods.machines.room.graph.edge.RoomOwnerEdge; +import dev.compactmods.machines.room.graph.node.RoomChunkNode; +import dev.compactmods.machines.room.graph.node.RoomOwnerNode; +import dev.compactmods.machines.room.graph.node.RoomRegistrationNode; +import dev.compactmods.machines.util.MathUtil; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.saveddata.SavedData; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Stream; + +@SuppressWarnings("UnstableApiUsage") +public class AllRoomsDataFile extends SavedData { + + public static final Logger LOGS = LogManager.getLogger(); + + public static final String DATA_NAME = Constants.MOD_ID + "_rooms"; + public static final String NBT_NODE_ID_KEY = "node_id"; + + private final Map registrationNodes; + + private final Map owners; + + + private AllRoomsDataFile() { + this.registrationNodes = new HashMap<>(); + this.owners = new HashMap<>(); + } + + public static AllRoomsDataFile empty() { + return new AllRoomsDataFile(); + } + + @Nullable + public static AllRoomsDataFile instance(MinecraftServer server) { + try { + final ServerLevel level = CompactDimension.forServer(server); + return level.getDataStorage() + .computeIfAbsent(AllRoomsDataFile::fromDisk, AllRoomsDataFile::empty, DATA_NAME); + } catch (MissingDimensionException e) { + LOGS.fatal(e); + return null; + } + } + + public static AllRoomsDataFile instance(ServerLevel compactDim) { + return compactDim.getDataStorage() + .computeIfAbsent(AllRoomsDataFile::fromDisk, AllRoomsDataFile::empty, DATA_NAME); + } + + public static AllRoomsDataFile fromDisk(CompoundTag compoundTag) { + final var graph = new AllRoomsDataFile(); + + final HashMap metaNodeIdMap = new HashMap<>(); + if (compoundTag.contains("rooms")) { + compoundTag.getList("rooms", ListTag.TAG_COMPOUND) + .stream() + .map(CompoundTag.class::cast) + .forEach(roomNode -> { + UUID id = roomNode.getUUID(NBT_NODE_ID_KEY); + final var node = RoomRegistrationNode.CODEC.parse(NbtOps.INSTANCE, roomNode) + .getOrThrow(false, LOGS::fatal); + + metaNodeIdMap.put(id, node); + graph.registrationNodes.put(node.code(), node); + + node.chunks().forEach(chunk -> { + RoomChunkNode chunkNode = new RoomChunkNode(chunk); + graph.graph.putEdgeValue(node, chunkNode, new RoomChunkEdge()); + graph.chunks.put(chunk, chunkNode); + }); + }); + } + + final HashMap roomOwnerNodeMap = new HashMap<>(); + if (compoundTag.contains("owners")) { + compoundTag.getList("owners", ListTag.TAG_COMPOUND) + .stream() + .map(CompoundTag.class::cast) + .forEach(ownerNode -> { + UUID id = ownerNode.getUUID(NBT_NODE_ID_KEY); + final var node = RoomOwnerNode.CODEC.parse(NbtOps.INSTANCE, ownerNode) + .getOrThrow(false, LOGS::fatal); + + roomOwnerNodeMap.put(id, node); + graph.owners.put(node.owner(), node); + }); + } + + if (compoundTag.contains("roomOwners")) { + compoundTag.getList("roomOwners", ListTag.TAG_COMPOUND) + .stream() + .map(CompoundTag.class::cast) + .forEach(roomOwnerConn -> { + RoomRegistrationNode meta = metaNodeIdMap.get(roomOwnerConn.getUUID("room")); + RoomOwnerNode owner = roomOwnerNodeMap.get(roomOwnerConn.getUUID("owner")); + graph.graph.putEdgeValue(meta, owner, new RoomOwnerEdge()); + }); + } + + LOGS.debug("Number of rooms loaded from disk: {}", metaNodeIdMap.size()); + return graph; + } + + @NotNull + @Override + public CompoundTag save(@NotNull CompoundTag tag) { + //region Room Metadata Nodes + final HashMap metaNodeIdMap = new HashMap<>(); + registrationNodes.values().forEach(metaNode -> metaNodeIdMap.put(metaNode.code(), UUID.randomUUID())); + ListTag meta = (ListTag) RoomRegistrationNode.CODEC.listOf() + .encodeStart(NbtOps.INSTANCE, List.copyOf(registrationNodes.values())) + .getOrThrow(false, LOGS::fatal); + + meta.stream() + .filter(CompoundTag.class::isInstance) + .map(CompoundTag.class::cast) + .forEach(mct -> mct.putUUID(NBT_NODE_ID_KEY, metaNodeIdMap.get(mct.getString("code")))); + + tag.put("rooms", meta); + //endregion + + //region Room Owner nodes + final HashMap ownerByUuidMap = new HashMap<>(); + owners.values().forEach(ownerNode -> ownerByUuidMap.put(ownerNode.owner(), UUID.randomUUID())); + ListTag ownerList = (ListTag) RoomOwnerNode.CODEC.listOf() + .encodeStart(NbtOps.INSTANCE, List.copyOf(owners.values())) + .getOrThrow(false, LOGS::fatal); + + ownerList.stream().map(CompoundTag.class::cast) + .forEach(oct -> oct.putUUID(NBT_NODE_ID_KEY, ownerByUuidMap.get(oct.getUUID("owner")))); + + tag.put("owners", ownerList); + //endregion + + //region Room-Owner connections + if (!registrationNodes.isEmpty() && !owners.isEmpty()) { + final ListTag roomOwnerConnections = registrationNodes.values() + .stream() + .map(roomNode -> graph.adjacentNodes(roomNode) + .stream() + .filter(RoomOwnerNode.class::isInstance) + .map(RoomOwnerNode.class::cast) + .findFirst() + .map(roomOwner -> { + UUID roomId = metaNodeIdMap.get(roomNode.code()); + UUID ownerId = ownerByUuidMap.get(roomOwner.owner()); + CompoundTag connection = new CompoundTag(); + connection.putUUID("room", roomId); + connection.putUUID("owner", ownerId); + return connection; + })) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(NbtListCollector.toNbtList()); + + tag.put("roomOwners", roomOwnerConnections); + } + //endregion + + return tag; + } + + @Override + public Stream allRooms() { + return registrationNodes.values().stream() + .map(mn -> mn); + } + + @Override + public boolean isRegistered(String room) { + return false; + } + + @Override + public Stream findByOwner(UUID owner) { + if (!owners.containsKey(owner)) + return Stream.empty(); + + return graph.adjacentNodes(owners.get(owner)).stream() + .filter(RoomRegistrationNode.class::isInstance) + .map(RoomRegistrationNode.class::cast); + } + + @Override + public Optional get(String room) { + return Optional.ofNullable(registrationNodes.get(room)); + } + + @Override + public Optional findByChunk(ChunkPos chunk) { + + } + + @Override + public boolean isRoomChunk(ChunkPos chunk) { + return chunks.containsKey(chunk); + } + + @Override + public long count() { + return registrationNodes.size(); + } + + private IRoomRegistration finalizeNew(String code, RoomRegistrationNode roomNode, UUID owner) { + this.registrationNodes.put(code, roomNode); + this.owners.computeIfAbsent(owner, RoomOwnerNode::new); + final var ownerNode = owners.get(owner); + + graph.putEdgeValue(roomNode, ownerNode, new RoomOwnerEdge()); + + // calculate chunks + roomNode.chunks().forEach(c -> { + final var roomChunkNode = new RoomChunkNode(c); + chunks.put(c, roomChunkNode); + graph.putEdgeValue(roomNode, roomChunkNode, new RoomChunkEdge()); + }); + + setDirty(); + + return roomNode; + } + + /** + * Registers a new room with a specified room code and data from the builder. + * This assumes that data is coming from a previous source such as a migrator, and + * will take all values from the returned builder. + * + * @param code + * @param newRoom + * @return + */ + public IRoomRegistration registerNew(String code, Function newRoom) { + final var builder = newRoom.apply(new NewRoomBuilder(code)); + + final var roomNode = builder.build(); + return finalizeNew(code, roomNode, builder.owner); + } + + public IRoomRegistration registerNew(Function newRoom) { + final var newRoomCode = RoomCodeGenerator.generateRoomId(); + + Vec3i location = MathUtil.getRegionPositionByIndex(registrationNodes.size()); + + final var builder = newRoom.apply(new NewRoomBuilder(newRoomCode)); + BlockPos newCenter = MathUtil.getCenterWithY(location, 40).above(builder.yOffset()); + + builder.setCenter(newCenter); + + final var roomNode = builder.build(); + return finalizeNew(newRoomCode, roomNode, builder.owner); + } + + /** + * @deprecated Fetch an instance of {@link dev.compactmods.machines.api.room.spawn.IRoomSpawnManager} and use the method there. + * @param room + * @throws NonexistentRoomException + */ + @Deprecated(forRemoval = true) + public void resetSpawn(String room) throws NonexistentRoomException { + + } + + @Override + public UUID getRoomOwner(String roomCode) throws NonexistentRoomException { + if (!registrationNodes.containsKey(roomCode)) + throw new NonexistentRoomException(roomCode); + + final var roomNode = registrationNodes.get(roomCode); + return GraphTraversalHelper.predecessors(graph, roomNode, RoomOwnerNode.class) + .map(RoomOwnerNode::owner) + .findFirst() + .orElseThrow(() -> new NonexistentRoomException(roomCode)); + } + + @ApiStatus.Internal + public MutableValueGraph, IGraphEdge> getGraph() { + return graph; + } + + public Optional roomNode(String roomCode) { + return Optional.ofNullable(registrationNodes.get(roomCode)); + } +} diff --git a/src/main/java/dev/compactmods/machines/room/data/RoomPreview.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/data/RoomPreview.java similarity index 53% rename from src/main/java/dev/compactmods/machines/room/data/RoomPreview.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/room/data/RoomPreview.java index 28b10d47..69e3dac9 100644 --- a/src/main/java/dev/compactmods/machines/room/data/RoomPreview.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/data/RoomPreview.java @@ -1,14 +1,14 @@ -package dev.compactmods.machines.room.data; +package dev.compactmods.machines.forge.room.data; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.codec.CodecExtensions; -import dev.compactmods.machines.api.room.RoomSize; +import dev.compactmods.machines.codec.CodecExtensions; import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.levelgen.structure.BoundingBox; -public record RoomPreview(ChunkPos chunk, RoomSize size) { +public record RoomPreview(ChunkPos chunk, BoundingBox area) { public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( CodecExtensions.CHUNKPOS.fieldOf("pos").forGetter(RoomPreview::chunk), - RoomSize.CODEC.fieldOf("size").forGetter(RoomPreview::size) + BoundingBox.CODEC.fieldOf("area").forGetter(RoomPreview::area) ).apply(i, RoomPreview::new)); } diff --git a/src/main/java/dev/compactmods/machines/room/menu/MachineRoomMenu.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/MachineRoomMenu.java similarity index 61% rename from src/main/java/dev/compactmods/machines/room/menu/MachineRoomMenu.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/MachineRoomMenu.java index 67b53776..e55e176b 100644 --- a/src/main/java/dev/compactmods/machines/room/menu/MachineRoomMenu.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/MachineRoomMenu.java @@ -1,11 +1,11 @@ -package dev.compactmods.machines.room.menu; +package dev.compactmods.machines.forge.room.ui; import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.core.UIRegistration; -import dev.compactmods.machines.dimension.MissingDimensionException; -import dev.compactmods.machines.location.LevelBlockPosition; -import dev.compactmods.machines.room.Rooms; +import dev.compactmods.machines.api.dimension.MissingDimensionException; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.room.Rooms; import dev.compactmods.machines.room.exceptions.NonexistentRoomException; +import net.minecraft.core.GlobalPos; import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; import net.minecraft.world.MenuProvider; @@ -13,35 +13,39 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; public class MachineRoomMenu extends AbstractContainerMenu { - private final ChunkPos room; + private final String room; private String roomName; - private final LevelBlockPosition machine; + private final GlobalPos machine; private StructureTemplate roomBlocks; + public boolean loadingBlocks; - public MachineRoomMenu(int win, ChunkPos room, LevelBlockPosition machine, String roomName) { - super(UIRegistration.MACHINE_MENU.get(), win); + public MachineRoomMenu(int win, String room, GlobalPos machine, String roomName) { + super(RoomUserInterfaceRegistration.MACHINE_MENU.get(), win); this.room = room; this.roomName = roomName; this.roomBlocks = new StructureTemplate(); this.machine = machine; + this.loadingBlocks = true; } - public ChunkPos getRoom() { + public String getRoom() { return room; } - public LevelBlockPosition getMachine() { + public GlobalPos getMachine() { return machine; } - public static MenuProvider makeProvider(MinecraftServer server, ChunkPos roomId, LevelBlockPosition machinePos) { + public static MenuProvider makeProvider(MinecraftServer server, String roomCode, GlobalPos machinePos) { return new MenuProvider() { @Override public Component getDisplayName() { @@ -52,14 +56,17 @@ public Component getDisplayName() { @Override public AbstractContainerMenu createMenu(int winId, Inventory inv, Player player2) { try { - final var title = Rooms.getRoomName(server, roomId); + final var title = Rooms.getRoomName(server, roomCode); - var menu = new MachineRoomMenu(winId, roomId, machinePos, title.orElse("Room Preview")); - menu.roomBlocks = Rooms.getInternalBlocks(server, roomId); + var menu = new MachineRoomMenu(winId, roomCode, machinePos, title.orElse("Room Preview")); + menu.roomBlocks = Rooms.getInternalBlocks(server, roomCode).get(5, TimeUnit.SECONDS); return menu; - } catch (MissingDimensionException | NonexistentRoomException e) { + } catch (NonexistentRoomException | MissingDimensionException e) { + CompactMachines.LOGGER.fatal("Error creating machine preview for {}.", machinePos, e); return null; + } catch (ExecutionException | InterruptedException | TimeoutException e) { + throw new RuntimeException(e); } } }; @@ -83,6 +90,7 @@ public StructureTemplate getBlocks() { public void setBlocks(StructureTemplate blocks) { this.roomBlocks = blocks; + this.loadingBlocks = false; } public String getRoomName() { diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/MachineRoomScreen.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/MachineRoomScreen.java new file mode 100644 index 00000000..09f8c171 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/MachineRoomScreen.java @@ -0,0 +1,235 @@ +package dev.compactmods.machines.forge.room.ui; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix4f; +import com.mojang.math.Vector3f; +import dev.compactmods.machines.forge.client.level.RenderingLevel; +import dev.compactmods.machines.forge.client.render.RenderTypes; +import dev.compactmods.machines.forge.compat.curios.CuriosCompat; +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.client.render.SuperRenderTypeBuffer; +import dev.compactmods.machines.client.util.TransformingVertexBuilder; +import dev.compactmods.machines.forge.network.PlayerStartedRoomTrackingPacket; +import dev.compactmods.machines.forge.network.RoomNetworkHandler; +import dev.compactmods.machines.forge.shrinking.Shrinking; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.core.BlockPos; +import net.minecraft.core.GlobalPos; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import net.minecraftforge.client.model.data.ModelData; +import net.minecraftforge.fml.ModList; + +public class MachineRoomScreen extends AbstractContainerScreen { + + private final Inventory inv; + protected double rotateX = 45.0f; + protected double rotateY = 20.0f; + private PSDIconButton psdButton; + private RenderingLevel renderer; + + public MachineRoomScreen(MachineRoomMenu menu, Inventory inv, Component title) { + super(menu, inv, title); + this.imageWidth = 248; + this.imageHeight = 239; + this.titleLabelY = 5; + this.inv = inv; + + // Send packet to server for block data + RoomNetworkHandler.CHANNEL.sendToServer(new PlayerStartedRoomTrackingPacket(menu.getRoom())); + updateBlockRender(); + } + + @Override + protected void init() { + super.init(); + + this.psdButton = addRenderableWidget(new PSDIconButton(this, leftPos + 220, topPos + 210)); + if (hasPsdItem()) + this.psdButton.setEnabled(true); + } + + public void updateBlockRender() { + var struct = menu.getBlocks(); + this.renderer = new RenderingLevel(struct); + } + + private boolean hasPsdItem() { + final var is = inv.contains(new ItemStack(Shrinking.psd)); + final var inInv = inv.contains(new ItemStack(Shrinking.PERSONAL_SHRINKING_DEVICE.get())); + if (ModList.get().isLoaded("curios") && CuriosCompat.hasPsdCurio(inv.player)) + return true; + + return inInv; + } + + @Override + protected void containerTick() { + super.containerTick(); + psdButton.setEnabled(this.inv.player.isCreative() || hasPsdItem()); + renderer.tbe(); + } + + @Override + public boolean mouseDragged(double mx, double my, int mButton, double dx, double dy) { + var s = super.mouseDragged(mx, my, mButton, dx, dy); + if (!s) return false; + + rotateX += dx; + rotateY += dy; + return true; + } + + @Override + protected void renderLabels(PoseStack pose, int mouseX, int mouseY) { + pose.pushPose(); + pose.translate(0, 0, 500); + + pose.translate(this.imageWidth / 2f, 0, 0); + + var p = Component.literal(menu.getRoomName()); + Screen.drawCenteredString(pose, font, p, 0, this.titleLabelY, 0xFFFFFFFF); + + var room = menu.getRoom(); + var rt = Component.literal(room); + pose.scale(0.7f, 0.7f, 0.7f); + Screen.drawCenteredString(pose, font, rt, 0, this.titleLabelY + font.lineHeight + 2, 0xFFCCCCCC); + pose.popPose(); + } + + @Override + public void render(PoseStack pose, int mouseX, int mouseY, float partial) { + this.renderBackground(pose); + super.render(pose, mouseX, mouseY, partial); + + var buffer = SuperRenderTypeBuffer.getInstance(); + + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + RenderSystem.backupProjectionMatrix(); + + // has to be outside of MS transforms, important for vertex sorting + Matrix4f matrix4f = new Matrix4f(RenderSystem.getProjectionMatrix()); + matrix4f.multiplyWithTranslation(0, 0, 800); + RenderSystem.setProjectionMatrix(matrix4f); + + PoseStack.Pose lastEntryBeforeTry = pose.last(); + + var cam = minecraft.cameraEntity; + + if (this.menu.loadingBlocks) { + pose.pushPose(); + Screen.drawCenteredString(pose, font, "Loading preview...", 0, this.titleLabelY + font.lineHeight + 2, 0xFFCCCCCC); + pose.popPose(); + } else { + try { + pose.pushPose(); + pose.translate(0, 0, -800); + + final var blockRenderer = Minecraft.getInstance().getBlockRenderer(); + final var beRenderer = Minecraft.getInstance().getBlockEntityRenderDispatcher(); + + var struct = menu.getBlocks(); + + pose.pushPose(); + { + // pose.translate(s, s, s); + + pose.translate(getGuiLeft() + (getXSize() / 2d), getGuiTop() + 135, 150); + + float zoom = switch (struct.getSize().getX()) { + case 3 -> 23.5f; + case 5 -> 19.5f; + case 7 -> 15.5f; + case 9 -> 14.5f; + case 11 -> 11.5f; + case 13 -> 10.5f; + default -> 10.5f; + }; + + pose.scale(zoom, -zoom, zoom); + + pose.mulPose(Vector3f.XP.rotationDegrees((float) rotateY)); + pose.mulPose(Vector3f.YP.rotationDegrees((float) rotateX)); + + final var tSize = struct.getSize(); + final float s = tSize.getX() / 2f; + pose.translate(-s, -s + 1, -s); + + final var transformer = new TransformingVertexBuilder(buffer, RenderTypes.WALLS); + + var bb = struct.getBoundingBox(new StructurePlaceSettings(), BlockPos.ZERO); + + var as = new ArmorStand(renderer, 0, 0, 0); + minecraft.cameraEntity = as; + + BlockPos.betweenClosedStream(bb).forEach(pos -> { + pose.pushPose(); + { + pose.translate(pos.getX(), pos.getY(), pos.getZ()); + + final var state = renderer.getBlockState(pos); + transformer.setOverlay(OverlayTexture.RED_OVERLAY_V); + + ModelData modelData = ModelData.EMPTY; + if (state.hasBlockEntity()) { + final var be = renderer.getBlockEntity(pos); + if (be != null) { + modelData = be.getModelData(); + final var ber = beRenderer.getRenderer(be); + if (ber != null) { + ber.render(be, 1f, pose, buffer, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY); + } + } + } + + try { + pose.pushPose(); + + for (var type : blockRenderer.getBlockModel(state).getRenderTypes(state, minecraft.level.random, modelData)) { + blockRenderer.renderBatched(state, pos, renderer, pose, buffer.getBuffer(type), true, renderer.random, modelData, type); + } + + pose.popPose(); + } catch (Exception e) { + } + } + pose.popPose(); + }); + } + pose.popPose(); + pose.popPose(); + } catch (Exception e) { + while (lastEntryBeforeTry != pose.last()) + pose.popPose(); + } + + minecraft.cameraEntity = cam; + + buffer.draw(); + RenderSystem.restoreProjectionMatrix(); + } + } + + @Override + protected void renderBg(PoseStack pose, float p_97788_, int p_97789_, int p_97790_) { + RenderSystem.setShaderTexture(0, new ResourceLocation(Constants.MOD_ID, "textures/gui/room_menu.png")); + + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + // this.blit(pose, leftPos, topPos, 0, 0, this.imageWidth, this.imageHeight); + } + + public GlobalPos getMachine() { + return menu.getMachine(); + } +} diff --git a/src/main/java/dev/compactmods/machines/client/gui/widget/PSDIconButton.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/PSDIconButton.java similarity index 82% rename from src/main/java/dev/compactmods/machines/client/gui/widget/PSDIconButton.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/PSDIconButton.java index 0d0f4fb4..ef081aa6 100644 --- a/src/main/java/dev/compactmods/machines/client/gui/widget/PSDIconButton.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/PSDIconButton.java @@ -1,10 +1,9 @@ -package dev.compactmods.machines.client.gui.widget; +package dev.compactmods.machines.forge.room.ui; import com.mojang.blaze3d.vertex.PoseStack; -import dev.compactmods.machines.core.CompactMachinesNet; -import dev.compactmods.machines.room.client.MachineRoomScreen; -import dev.compactmods.machines.room.network.PlayerRequestedTeleportPacket; -import dev.compactmods.machines.shrinking.Shrinking; +import dev.compactmods.machines.forge.network.CompactMachinesNet; +import dev.compactmods.machines.forge.network.PlayerRequestedTeleportPacket; +import dev.compactmods.machines.forge.shrinking.Shrinking; import net.minecraft.client.gui.components.Button; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; diff --git a/src/main/java/dev/compactmods/machines/core/UIRegistration.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/RoomUserInterfaceRegistration.java similarity index 67% rename from src/main/java/dev/compactmods/machines/core/UIRegistration.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/RoomUserInterfaceRegistration.java index 32269272..58b0feb8 100644 --- a/src/main/java/dev/compactmods/machines/core/UIRegistration.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/RoomUserInterfaceRegistration.java @@ -1,18 +1,18 @@ -package dev.compactmods.machines.core; +package dev.compactmods.machines.forge.room.ui; -import dev.compactmods.machines.location.LevelBlockPosition; -import dev.compactmods.machines.room.menu.MachineRoomMenu; +import dev.compactmods.machines.forge.Registries; +import net.minecraft.core.GlobalPos; import net.minecraft.world.inventory.MenuType; import net.minecraftforge.common.extensions.IForgeMenuType; import net.minecraftforge.registries.RegistryObject; -public class UIRegistration { +public class RoomUserInterfaceRegistration { public static final RegistryObject> MACHINE_MENU = Registries.CONTAINERS.register("machine", () -> IForgeMenuType.create( ((windowId, inv, data) -> { data.readBlockPos(); - final var mach = data.readWithCodec(LevelBlockPosition.CODEC); - final var room = data.readChunkPos(); + final var mach = data.readWithCodec(GlobalPos.CODEC); + final var room = data.readUtf(); final boolean hasName = data.readBoolean(); final var roomName = hasName ? data.readUtf() : "Room Preview"; diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/overlay/RoomMetadataDebugOverlay.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/overlay/RoomMetadataDebugOverlay.java new file mode 100644 index 00000000..1247ad89 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/ui/overlay/RoomMetadataDebugOverlay.java @@ -0,0 +1,55 @@ +package dev.compactmods.machines.forge.room.ui.overlay; + +import com.mojang.blaze3d.vertex.PoseStack; +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.room.IPlayerRoomMetadataProvider; +import dev.compactmods.machines.client.PlayerFaceRenderer; +import dev.compactmods.machines.util.PlayerUtil; +import net.minecraft.client.Minecraft; +import net.minecraftforge.client.gui.overlay.ForgeGui; +import net.minecraftforge.client.gui.overlay.IGuiOverlay; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; + +public class RoomMetadataDebugOverlay implements IGuiOverlay { + private static final Capability CURRENT_ROOM_META = CapabilityManager.get(new CapabilityToken<>() { + }); + + @Override + public void render(ForgeGui gui, PoseStack poseStack, float partialTick, int screenWidth, int screenHeight) { + final var player = Minecraft.getInstance().player; + if (player == null || !player.level.dimension().equals(CompactDimension.LEVEL_KEY)) + return; + + if (!gui.getMinecraft().options.renderDebug) + return; + + final var font = gui.getFont(); + final var center = screenWidth / 2f; + + + player.getCapability(CURRENT_ROOM_META) + .resolve() + .flatMap(IPlayerRoomMetadataProvider::currentRoom) + .ifPresent(room -> { + poseStack.pushPose(); + poseStack.translate(center, screenHeight - 75, 0); + + PlayerUtil.getProfileByUUID(player.level, room.owner()).ifPresent(ownerInfo -> { + final int ownerWidth = font.width(ownerInfo.getName()); + + PlayerFaceRenderer.render(ownerInfo, poseStack, -6, -14); + + font.drawShadow(poseStack, ownerInfo.getName(), -(ownerWidth / 2f), 0, 0xFFFFFFFF, false); + poseStack.translate(0, 12, 0); + }); + + final int codeWidth = font.width(room.roomCode()); + font.drawShadow(poseStack, room.roomCode(), -(codeWidth / 2f), 0, 0xFFFFFFFF, false); + + poseStack.popPose(); + + }); + } +} diff --git a/src/main/java/dev/compactmods/machines/upgrade/RoomUpgradeManager.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/upgrade/RoomUpgradeManager.java similarity index 73% rename from src/main/java/dev/compactmods/machines/upgrade/RoomUpgradeManager.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/room/upgrade/RoomUpgradeManager.java index 3674d390..1d8c2b84 100644 --- a/src/main/java/dev/compactmods/machines/upgrade/RoomUpgradeManager.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/upgrade/RoomUpgradeManager.java @@ -1,41 +1,45 @@ -package dev.compactmods.machines.upgrade; +package dev.compactmods.machines.forge.room.upgrade; import com.google.common.graph.MutableValueGraph; import com.google.common.graph.ValueGraphBuilder; import com.mojang.serialization.Codec; -import dev.compactmods.machines.CompactMachines; import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.api.room.upgrade.RoomUpgrade; -import dev.compactmods.machines.api.room.upgrade.RoomUpgradeInstance; -import dev.compactmods.machines.graph.IGraphEdge; -import dev.compactmods.machines.graph.IGraphNode; -import dev.compactmods.machines.room.graph.CompactMachineRoomNode; -import dev.compactmods.machines.upgrade.graph.RoomUpgradeConnection; -import dev.compactmods.machines.upgrade.graph.RoomUpgradeGraphNode; -import dev.compactmods.machines.upgrade.graph.UpgradeConnectionEntry; +import dev.compactmods.machines.api.upgrade.RoomUpgrade; +import dev.compactmods.machines.api.upgrade.RoomUpgradeInstance; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades; +import dev.compactmods.machines.forge.upgrade.graph.RoomUpgradeConnection; +import dev.compactmods.machines.forge.upgrade.graph.UpgradeConnectionEntry; +import dev.compactmods.machines.graph.GraphTraversalHelper; +import dev.compactmods.machines.graph.edge.IGraphEdge; +import dev.compactmods.machines.graph.node.IGraphNode; +import dev.compactmods.machines.room.graph.node.RoomReferenceNode; +import dev.compactmods.machines.room.upgrade.graph.RoomUpgradeGraphNode; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.saveddata.SavedData; import net.minecraft.world.level.storage.DimensionDataStorage; import javax.annotation.Nonnull; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; +@SuppressWarnings("UnstableApiUsage") public class RoomUpgradeManager extends SavedData { public static final String DATA_NAME = Constants.MOD_ID + "_upgrades"; private final HashMap upgradeNodes; - private final HashMap roomNodes; - - private final MutableValueGraph graph; + private final HashMap roomNodes; + private final MutableValueGraph, IGraphEdge> graph; private static final Codec> UPGRADE_CONNECTIONS_CODEC = UpgradeConnectionEntry.CODEC.listOf(); @@ -102,7 +106,7 @@ public CompoundTag save(CompoundTag tag) { return tag; } - public boolean addUpgrade(T upgrade, ChunkPos room) { + public boolean addUpgrade(T upgrade, String room) { final var upgRegistry = MachineRoomUpgrades.REGISTRY.get(); final var upgradeNode = upgradeNodes.computeIfAbsent(upgRegistry.getKey(upgrade), rl -> { @@ -111,7 +115,7 @@ public boolean addUpgrade(T upgrade, ChunkPos room) { }); final var roomNode = roomNodes.computeIfAbsent(room, p -> { - final var nn = new CompactMachineRoomNode(p); + final var nn = new RoomReferenceNode(p); return graph.addNode(nn) ? nn : null; }); @@ -124,34 +128,34 @@ public boolean addUpgrade(T upgrade, ChunkPos room) { return true; } - public boolean removeUpgrade(T upgrade, ChunkPos room) { + public boolean removeUpgrade(T upgrade, String room) { final var upgRegistry = MachineRoomUpgrades.REGISTRY.get(); - if(!upgRegistry.containsValue(upgrade)) return false; + if (!upgRegistry.containsValue(upgrade)) return false; final var upgId = upgRegistry.getKey(upgrade); - if(!upgradeNodes.containsKey(upgId)) + if (!upgradeNodes.containsKey(upgId)) return true; - if(!roomNodes.containsKey(room)) + if (!roomNodes.containsKey(room)) return true; final var uNode = upgradeNodes.get(upgId); final var rNode = roomNodes.get(room); - graph.removeEdge(rNode, uNode); + graph.removeEdge(rNode, uNode); setDirty(); return true; } - public Stream roomsWith(ResourceKey upgradeKey) { + public Stream roomsWith(ResourceKey upgradeKey) { if (!upgradeNodes.containsKey(upgradeKey.location())) return Stream.empty(); return upgradeNodes.values().stream() .filter(upg -> upg.key().equals(upgradeKey.location())) .flatMap(upg -> graph.adjacentNodes(upg).stream()) - .filter(CompactMachineRoomNode.class::isInstance) - .map(CompactMachineRoomNode.class::cast) - .map(CompactMachineRoomNode::pos); + .filter(RoomReferenceNode.class::isInstance) + .map(RoomReferenceNode.class::cast) + .map(RoomReferenceNode::code); } public Stream> implementing(Class inter) { @@ -171,32 +175,30 @@ public Stream> implementing(Class // Build a set of matched upgrade instance nodes HashSet> instances = new HashSet<>(); - final var roomNodes = new HashSet<>(); for (RoomUpgradeGraphNode upgNode : matchedUpgradeNodes) { - for (IGraphNode adjNode : graph.adjacentNodes(upgNode)) { - if (adjNode instanceof CompactMachineRoomNode roomNode) { - graph.edgeValue(roomNode, upgNode).ifPresent(edv -> { - if (edv instanceof RoomUpgradeConnection conn && inter.isInstance(conn.instance())) - instances.add(new RoomUpgradeInstance<>(inter.cast(conn.instance()), roomNode.pos())); + GraphTraversalHelper.predecessors(graph, upgNode, RoomReferenceNode.class) + .forEach(roomNode -> { + var edge = graph.edgeValue(roomNode, upgNode).orElseThrow(); + if (edge instanceof RoomUpgradeConnection upgEdge) { + instances.add(new RoomUpgradeInstance<>(inter.cast(upgEdge.instance()), roomNode.code())); + } }); - } - } } // Stream the instances off the set built above return instances.stream(); } - public boolean hasUpgrade(ChunkPos room, RoomUpgrade upgrade) { + public boolean hasUpgrade(String room, RoomUpgrade upgrade) { final var upgRegistry = MachineRoomUpgrades.REGISTRY.get(); - if(!upgRegistry.containsValue(upgrade)) + if (!upgRegistry.containsValue(upgrade)) return false; final var upgId = upgRegistry.getKey(upgrade); - if(!upgradeNodes.containsKey(upgId)) + if (!upgradeNodes.containsKey(upgId)) return false; - if(!roomNodes.containsKey(room)) + if (!roomNodes.containsKey(room)) return false; final var upgNode = upgradeNodes.get(upgId); diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/upgrade/RoomUpgradeWorkbench.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/upgrade/RoomUpgradeWorkbench.java new file mode 100644 index 00000000..dfc14a4e --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/upgrade/RoomUpgradeWorkbench.java @@ -0,0 +1,34 @@ +package dev.compactmods.machines.forge.room.upgrade; + +import dev.compactmods.machines.api.core.Tooltips; +import dev.compactmods.machines.i18n.TranslationUtil; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class RoomUpgradeWorkbench extends Block implements EntityBlock { + public RoomUpgradeWorkbench(Properties props) { + super(props); + } + + @Override + public void appendHoverText(ItemStack stack, @Nullable BlockGetter level, List tooltip, TooltipFlag flag) { + tooltip.add(TranslationUtil.tooltip(Tooltips.NOT_YET_IMPLEMENTED).withStyle(ChatFormatting.DARK_RED)); + } + + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { + return new RoomUpgradeWorkbenchEntity(pPos, pState); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/room/upgrade/RoomUpgradeWorkbenchEntity.java b/forge-main/src/main/java/dev/compactmods/machines/forge/room/upgrade/RoomUpgradeWorkbenchEntity.java new file mode 100644 index 00000000..60107611 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/room/upgrade/RoomUpgradeWorkbenchEntity.java @@ -0,0 +1,23 @@ +package dev.compactmods.machines.forge.room.upgrade; + +import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class RoomUpgradeWorkbenchEntity extends BlockEntity { + public RoomUpgradeWorkbenchEntity(BlockPos pPos, BlockState pBlockState) { + super(MachineRoomUpgrades.ROOM_UPDATE_ENTITY.get(), pPos, pBlockState); + } + + @Override + protected void saveAdditional(CompoundTag tag) { + super.saveAdditional(tag); + } + + @Override + public void load(CompoundTag tag) { + super.load(tag); + } +} diff --git a/src/main/java/dev/compactmods/machines/shrinking/PersonalShrinkingDevice.java b/forge-main/src/main/java/dev/compactmods/machines/forge/shrinking/PersonalShrinkingDevice.java similarity index 78% rename from src/main/java/dev/compactmods/machines/shrinking/PersonalShrinkingDevice.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/shrinking/PersonalShrinkingDevice.java index 2047cc7a..ba3a81ab 100644 --- a/src/main/java/dev/compactmods/machines/shrinking/PersonalShrinkingDevice.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/shrinking/PersonalShrinkingDevice.java @@ -1,11 +1,13 @@ -package dev.compactmods.machines.shrinking; +package dev.compactmods.machines.forge.shrinking; +import dev.compactmods.machines.forge.room.RoomHelper; import dev.compactmods.machines.api.core.Messages; import dev.compactmods.machines.api.core.Tooltips; import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.room.registration.IMutableRoomRegistration; import dev.compactmods.machines.client.gui.PersonalShrinkingDeviceScreen; import dev.compactmods.machines.i18n.TranslationUtil; -import dev.compactmods.machines.room.data.CompactRoomData; +import dev.compactmods.machines.room.graph.CompactRoomProvider; import dev.compactmods.machines.util.PlayerUtil; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.screens.Screen; @@ -19,10 +21,9 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.List; public class PersonalShrinkingDevice extends Item { @@ -64,12 +65,14 @@ public InteractionResultHolder use(Level world, Player player, Intera ServerLevel playerDim = serverPlayer.getLevel(); if (playerDim.dimension().equals(CompactDimension.LEVEL_KEY)) { if (player.isShiftKeyDown()) { - ChunkPos machineChunk = new ChunkPos(player.blockPosition()); - final CompactRoomData intern = CompactRoomData.get(playerDim); - - // Use internal data to set new spawn point - intern.setSpawn(machineChunk, player.position()); + final var roomInfo = CompactRoomProvider.instance(playerDim); + roomInfo.findByChunk(player.chunkPosition()).ifPresent(room -> { + if(room instanceof IMutableRoomRegistration mutableRoom) { + mutableRoom.setSpawnPosition(player.position()); + mutableRoom.setSpawnRotation(PlayerUtil.getLookDirection(player)); + } + }); MutableComponent tc = TranslationUtil.message(Messages.ROOM_SPAWNPOINT_SET) .withStyle(ChatFormatting.GREEN); @@ -77,7 +80,7 @@ public InteractionResultHolder use(Level world, Player player, Intera player.displayClientMessage(tc, true); } else { - PlayerUtil.teleportPlayerOutOfMachine(playerDim, serverPlayer); + RoomHelper.teleportPlayerOutOfRoom(serverPlayer); } } } diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/shrinking/Shrinking.java b/forge-main/src/main/java/dev/compactmods/machines/forge/shrinking/Shrinking.java new file mode 100644 index 00000000..c7e6d904 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/shrinking/Shrinking.java @@ -0,0 +1,27 @@ +package dev.compactmods.machines.forge.shrinking; + +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.Registries; +import dev.compactmods.machines.api.core.Constants; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraftforge.registries.RegistryObject; + +public class Shrinking { + + public static final Holder psd = Holder.Reference.createStandAlone(Registry.ITEM, ResourceKey.create( + Registry.ITEM_REGISTRY, new ResourceLocation(Constants.MOD_ID, "personal_shrinking_device") + )); + + public static final RegistryObject PERSONAL_SHRINKING_DEVICE = Registries.ITEMS.register("personal_shrinking_device", + () -> new PersonalShrinkingDevice(new Item.Properties() + .tab(CompactMachines.COMPACT_MACHINES_ITEMS) + .stacksTo(1))); + + public static void prepare() { + + } +} diff --git a/src/main/java/dev/compactmods/machines/tunnel/TunnelItem.java b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/TunnelItem.java similarity index 59% rename from src/main/java/dev/compactmods/machines/tunnel/TunnelItem.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/TunnelItem.java index 2d554e7d..7f456789 100644 --- a/src/main/java/dev/compactmods/machines/tunnel/TunnelItem.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/TunnelItem.java @@ -1,21 +1,24 @@ -package dev.compactmods.machines.tunnel; +package dev.compactmods.machines.forge.tunnel; -import dev.compactmods.machines.CompactMachines; 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.dimension.CompactDimension; +import dev.compactmods.machines.api.dimension.MissingDimensionException; import dev.compactmods.machines.api.room.history.IRoomHistoryItem; import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import dev.compactmods.machines.api.tunnels.redstone.IRedstoneTunnel; -import dev.compactmods.machines.core.*; -import dev.compactmods.machines.dimension.MissingDimensionException; +import dev.compactmods.machines.api.tunnels.redstone.RedstoneTunnel; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.room.capability.RoomCapabilities; +import dev.compactmods.machines.forge.wall.SolidWallBlock; import dev.compactmods.machines.i18n.TranslationUtil; -import dev.compactmods.machines.room.RoomCapabilities; +import dev.compactmods.machines.room.graph.CompactRoomProvider; +import dev.compactmods.machines.tunnel.ITunnelItem; +import dev.compactmods.machines.tunnel.TunnelHelper; import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; -import dev.compactmods.machines.tunnel.network.TunnelAddedPacket; +import dev.compactmods.machines.tunnel.graph.traversal.TunnelMachineFilters; +import dev.compactmods.machines.tunnel.graph.traversal.TunnelTypeFilters; import dev.compactmods.machines.util.PlayerUtil; -import dev.compactmods.machines.wall.SolidWallBlock; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.screens.Screen; import net.minecraft.core.BlockPos; @@ -24,6 +27,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -37,7 +41,6 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.registries.IForgeRegistry; import javax.annotation.Nonnull; @@ -46,17 +49,31 @@ import java.util.Optional; import java.util.stream.Collectors; -public class TunnelItem extends Item { +public class TunnelItem extends Item implements ITunnelItem { public TunnelItem(Properties properties) { super(properties); } + @Deprecated(forRemoval = true, since = "5.2.0") public static void setTunnelType(ItemStack stack, TunnelDefinition definition) { CompoundTag defTag = stack.getOrCreateTagElement("definition"); defTag.putString("id", Tunnels.getRegistryId(definition).toString()); } + private static void setTunnelType(ItemStack stack, ResourceKey definition) { + CompoundTag defTag = stack.getOrCreateTagElement("definition"); + defTag.putString("id", definition.location().toString()); + } + @Nonnull + public static ItemStack createStack(ResourceKey definition) { + var stack = new ItemStack(Tunnels.ITEM_TUNNEL.get(), 1); + setTunnelType(stack, definition); + return stack; + } + + @Nonnull + @Deprecated(forRemoval = true, since = "5.2.0") public static ItemStack createStack(TunnelDefinition definition) { var stack = new ItemStack(Tunnels.ITEM_TUNNEL.get(), 1); setTunnelType(stack, definition); @@ -65,59 +82,58 @@ public static ItemStack createStack(TunnelDefinition definition) { @Override public Component getName(ItemStack stack) { - String key = getDefinition(stack) - .map(def -> { - ResourceLocation id = Tunnels.getRegistryId(def); - return TranslationUtil.tunnelId(id); - }) - .orElse("item." + Constants.MOD_ID + ".tunnels.unnamed"); - - return Component.translatable(key); + try { + String key = ITunnelItem.getDefinition(stack) + .map(id -> TranslationUtil.tunnelId(id.location())) + .orElse(TranslationUtil.tunnelId(Tunnels.UNKNOWN_KEY.location())); + + return Component.translatable(key); + } + + catch(Exception e) { + return Component.translatable(TranslationUtil.tunnelId(Tunnels.UNKNOWN_KEY.location())); + } } @Override public void appendHoverText(@Nonnull ItemStack stack, @Nullable Level worldIn, List tooltip, TooltipFlag flagIn) { - getDefinition(stack).ifPresent(tunnelDef -> { - if (Screen.hasShiftDown()) { - MutableComponent type = Component.translatable("tooltip." + Constants.MOD_ID + ".tunnel_type", Tunnels.getRegistryId(tunnelDef)) - .withStyle(ChatFormatting.GRAY) - .withStyle(ChatFormatting.ITALIC); - - tooltip.add(type); - } else { - tooltip.add(TranslationUtil.tooltip(Tooltips.HINT_HOLD_SHIFT) - .withStyle(ChatFormatting.DARK_GRAY) - .withStyle(ChatFormatting.ITALIC)); - } - }); + try { + ITunnelItem.getDefinition(stack).ifPresent(tunnelDef -> { + if (Screen.hasShiftDown()) { + MutableComponent type = Component.translatable("tooltip." + Constants.MOD_ID + ".tunnel_type", tunnelDef.location()) + .withStyle(ChatFormatting.GRAY) + .withStyle(ChatFormatting.ITALIC); + + tooltip.add(type); + } else { + tooltip.add(TranslationUtil.tooltip(Tooltips.HINT_HOLD_SHIFT) + .withStyle(ChatFormatting.DARK_GRAY) + .withStyle(ChatFormatting.ITALIC)); + } + }); + } + + catch(Exception e) { + tooltip.add(TranslationUtil.tooltip(new ResourceLocation(Constants.MOD_ID, "error_tunnel_tooltip")) + .withStyle(ChatFormatting.DARK_RED)); + } } @Override public void fillItemCategory(CreativeModeTab group, NonNullList items) { if (this.allowedIn(group)) { IForgeRegistry definitions = Tunnels.TUNNEL_DEF_REGISTRY.get(); - definitions.getValues().forEach(def -> { - if (def == Tunnels.UNKNOWN.get()) + definitions.getKeys().forEach(def -> { + if (def.equals(Tunnels.UNKNOWN_KEY.location())) return; - ItemStack withDef = createStack(def); + ItemStack withDef = createStack(ResourceKey.create(TunnelDefinition.REGISTRY_KEY, def)); items.add(withDef); }); } } - public static Optional getDefinition(ItemStack stack) { - CompoundTag defTag = stack.getOrCreateTagElement("definition"); - if (defTag.isEmpty() || !defTag.contains("id")) - return Optional.empty(); - - ResourceLocation defId = new ResourceLocation(defTag.getString("id")); - if (!Tunnels.isRegistered(defId)) - return Optional.empty(); - TunnelDefinition tunnelReg = Tunnels.getDefinition(defId); - return Optional.ofNullable(tunnelReg); - } @Override public InteractionResult useOn(UseOnContext context) { @@ -130,9 +146,9 @@ public InteractionResult useOn(UseOnContext context) { if(level instanceof ServerLevel sl && sl.dimension().equals(CompactDimension.LEVEL_KEY)) { if (state.getBlock() instanceof SolidWallBlock && player != null) { - getDefinition(context.getItemInHand()).ifPresent(def -> { + ITunnelItem.getDefinition(context.getItemInHand()).ifPresent(def -> { try { - boolean success = setupTunnelWall(sl, position, context.getClickedFace(), player, def); + boolean success = setupTunnelWall(sl, position, context.getClickedFace(), player, Tunnels.getDefinition(def)); if (success && !player.isCreative()) context.getItemInHand().shrink(1); } catch (Exception | MissingDimensionException e) { @@ -163,9 +179,16 @@ public static Optional getMachineBindingInfo(Player player) { } private static boolean setupTunnelWall(ServerLevel compactDim, BlockPos position, Direction innerFace, Player player, TunnelDefinition def) throws Exception, MissingDimensionException { - boolean redstone = def instanceof IRedstoneTunnel; + boolean redstone = def instanceof RedstoneTunnel; + final var tunnelId = Tunnels.getRegistryKey(def); - final var roomTunnels = TunnelConnectionGraph.forRoom(compactDim, player.chunkPosition()); + final var provider = CompactRoomProvider.instance(compactDim); + final var roomInfo = provider.findByChunk(player.chunkPosition()); + if(roomInfo.isEmpty()) + return false; + + final var roomInstance = roomInfo.get(); + final var roomTunnels = TunnelConnectionGraph.forRoom(compactDim, roomInstance.code()); var lastEnteredMachine = getMachineBindingInfo(player); if (lastEnteredMachine.isEmpty()) { @@ -176,12 +199,14 @@ private static boolean setupTunnelWall(ServerLevel compactDim, BlockPos position var hist = lastEnteredMachine.get(); var placedSides = roomTunnels - .getTunnelSides(def) + .sides(TunnelMachineFilters.all(hist.getMachine()), TunnelTypeFilters.key(tunnelId)) .collect(Collectors.toSet()); // all tunnels already placed for type - if (placedSides.size() == 6) + if (placedSides.size() == 6) { + player.displayClientMessage(TranslationUtil.message(Messages.NO_TUNNEL_SIDE).withStyle(ChatFormatting.DARK_RED), true); return false; + } var newlyPlacedSide = TunnelHelper.getOrderedSides() .filter(s -> !placedSides.contains(s)) @@ -199,25 +224,22 @@ private static boolean setupTunnelWall(ServerLevel compactDim, BlockPos position .setValue(TunnelWallBlock.CONNECTED_SIDE, first) .setValue(TunnelWallBlock.REDSTONE, redstone); - boolean connected = roomTunnels.registerTunnel(position, def, hist.getMachine(), first); + boolean connected = roomTunnels.register(position, tunnelId, hist.getMachine(), first); if (!connected) { player.displayClientMessage(TranslationUtil.message(Messages.NO_TUNNEL_SIDE), true); return false; } - final var oldState = compactDim.getBlockState(position); - compactDim.setBlock(position, tunnelState, Block.UPDATE_NEIGHBORS); - - if (compactDim.getBlockEntity(position) instanceof TunnelWallEntity twe) { - twe.setTunnelType(def); + compactDim.setBlock(position, tunnelState, Block.UPDATE_ALL); + compactDim.getBlockEntity(position, Tunnels.TUNNEL_BLOCK_ENTITY.get()).ifPresent(twe -> { + twe.setTunnelType(tunnelId); twe.setConnectedTo(hist.getMachine(), first); - CompactMachinesNet.CHANNEL.send( - PacketDistributor.TRACKING_CHUNK.with(() -> compactDim.getChunkAt(position)), - new TunnelAddedPacket(position, def)); - } +// CompactMachinesNet.CHANNEL.send( +// PacketDistributor.TRACKING_CHUNK.with(() -> compactDim.getChunkAt(position)), +// new TunnelAddedPacket(position, tunnelId)); + }); - compactDim.sendBlockUpdated(position, oldState, tunnelState, Block.UPDATE_ALL); return true; } } diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/TunnelWallBlock.java b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/TunnelWallBlock.java new file mode 100644 index 00000000..f1756de2 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/TunnelWallBlock.java @@ -0,0 +1,219 @@ +package dev.compactmods.machines.forge.tunnel; + +import dev.compactmods.machines.api.core.Messages; +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.tunnels.TunnelPosition; +import dev.compactmods.machines.api.tunnels.lifecycle.TunnelTeardownHandler; +import dev.compactmods.machines.api.tunnels.lifecycle.removal.ITunnelRemoveEventListener; +import dev.compactmods.machines.api.tunnels.lifecycle.rotation.ITunnelRotationEventListener; +import dev.compactmods.machines.api.tunnels.redstone.RedstoneReaderTunnel; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.tunnel.removal.ServerPlayerRemovedReason; +import dev.compactmods.machines.forge.tunnel.rotation.ServerPlayerRotatedReason; +import dev.compactmods.machines.forge.wall.ProtectedWallBlock; +import dev.compactmods.machines.forge.wall.Walls; +import dev.compactmods.machines.i18n.TranslationUtil; +import dev.compactmods.machines.room.graph.CompactRoomProvider; +import dev.compactmods.machines.tunnel.TunnelHelper; +import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; +import dev.compactmods.machines.tunnel.graph.traversal.TunnelMachineFilters; +import dev.compactmods.machines.tunnel.graph.traversal.TunnelTypeFilters; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.GlobalPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +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.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.phys.BlockHitResult; + +import javax.annotation.Nullable; +import java.util.stream.Collectors; + +@SuppressWarnings("deprecation") +public class TunnelWallBlock extends ProtectedWallBlock implements EntityBlock { + public static final DirectionProperty TUNNEL_SIDE = DirectionProperty.create("tunnel_side", Direction.values()); + public static final DirectionProperty CONNECTED_SIDE = DirectionProperty.create("connected_side", Direction.values()); + + public static final BooleanProperty REDSTONE = BooleanProperty.create("redstone"); + + public TunnelWallBlock(BlockBehaviour.Properties props) { + super(props); + registerDefaultState(getStateDefinition().any() + .setValue(CONNECTED_SIDE, Direction.UP) + .setValue(TUNNEL_SIDE, Direction.UP) + .setValue(REDSTONE, false) + ); + } + + @Override + public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos position, @Nullable Direction side) { + return state.getValue(REDSTONE); + } + + @Override + public boolean isSignalSource(BlockState state) { + return state.getValue(REDSTONE); + } + + @Override + public int getDirectSignal(BlockState state, BlockGetter world, BlockPos position, Direction side) { + return 0; + } + + @Override + public int getSignal(BlockState state, BlockGetter world, BlockPos position, Direction side) { + if (!state.getValue(REDSTONE)) return 0; + if (world instanceof ServerLevel sl && world.getBlockEntity(position) instanceof TunnelWallEntity tunnelWall) { + final var serv = sl.getServer(); + final var def = tunnelWall.getTunnelType(); + final var machPos = tunnelWall.connectedMachine(); + final var tunnPos = tunnelWall.getTunnelPosition(); + final var connectedLevel = serv.getLevel(machPos.dimension()); + + if (!connectedLevel.isLoaded(machPos.pos())) return 0; + + if (def instanceof RedstoneReaderTunnel rrt) { + return rrt.powerLevel(serv, GlobalPos.of(machPos.dimension(), machPos.pos()), tunnPos); + } else { + return 0; + } + } else { + return 0; + } + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(TUNNEL_SIDE).add(CONNECTED_SIDE).add(REDSTONE); + super.createBlockStateDefinition(builder); + } + + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new TunnelWallEntity(pos, state); + } + + @Override + public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { + if (level.isClientSide) + return InteractionResult.SUCCESS; + + final var server = level.getServer(); + if (!(player instanceof ServerPlayer serverPlayer)) + return InteractionResult.FAIL; + + if (!(level.getBlockEntity(pos) instanceof TunnelWallEntity tunnel)) + return InteractionResult.FAIL; + + if (level.dimension().equals(CompactDimension.LEVEL_KEY) && level instanceof ServerLevel compactDim) { + final var def = tunnel.getTunnelType(); + final var tunnelWallSide = hitResult.getDirection(); + final var tunnelConnectedSide = tunnel.getConnectedSide(); + final var tunnelId = Tunnels.getRegistryKey(def); + final var roomProvider = CompactRoomProvider.instance(compactDim); + final var tunnelOriginalPosition = new TunnelPosition(pos, tunnelWallSide, tunnelConnectedSide); + + if (player.isShiftKeyDown()) { + final var removalReason = new ServerPlayerRemovedReason(serverPlayer); + if (def instanceof ITunnelRemoveEventListener removeListener) { + var handler = removeListener.createBeforeRemoveHandler(tunnel.getTunnel()); + if (handler != null && !handler.beforeRemove(server, tunnelOriginalPosition, removalReason)) { + // Cancel removal + return InteractionResult.FAIL; + } + } + } + + return roomProvider.findByChunk(new ChunkPos(pos)).map(roomInfo -> { + final var tunnels = TunnelConnectionGraph.forRoom(compactDim, roomInfo.code()); + if (player.isShiftKeyDown()) { + BlockState solidWall = Walls.BLOCK_SOLID_WALL.get().defaultBlockState(); + + level.setBlockAndUpdate(pos, solidWall); + + ItemStack stack = TunnelItem.createStack(tunnelId); + + ItemEntity ie = new ItemEntity(level, player.getX(), player.getY(), player.getZ(), stack); + level.addFreshEntity(ie); + + if (def instanceof TunnelTeardownHandler teardown) { + //noinspection removal + teardown.onRemoved(tunnelOriginalPosition, tunnel.getTunnel()); + } + + tunnels.unregister(pos); + } else { + // Rotate tunnel + Direction dir = state.getValue(CONNECTED_SIDE); + + final var existingDirs = tunnels + .sides(TunnelMachineFilters.all(tunnel.connectedMachine()), TunnelTypeFilters.key(tunnelId)) + .collect(Collectors.toSet()); + + if (existingDirs.size() == 6) { + // WARN PLAYER - NO OTHER SIDES REMAIN + player.displayClientMessage( + TranslationUtil.message(Messages.NO_TUNNEL_SIDE).withStyle(ChatFormatting.DARK_RED), true); + + return InteractionResult.FAIL; + } + + final var next = TunnelHelper.getNextDirection(dir, existingDirs); + next.ifPresent(newSide -> { + final var rotationReason = new ServerPlayerRotatedReason(serverPlayer); + final var newRotation = new TunnelPosition(pos, tunnelWallSide, newSide); + + if(def instanceof ITunnelRotationEventListener rotationListener) { + var handler = rotationListener.createBeforeRotateHandler(tunnel.getTunnel()); + if(handler != null && !handler.beforeRotate(server, tunnelOriginalPosition, newRotation, rotationReason)) { + return; + } + } + + level.setBlockAndUpdate(pos, state.setValue(CONNECTED_SIDE, newSide)); + + // TODO Remove in 5.3/next + if (def instanceof TunnelTeardownHandler teardown) { + //noinspection removal + teardown.onRotated(new TunnelPosition(pos, tunnelWallSide, tunnelConnectedSide), tunnel.getTunnel(), dir, newSide); + } + + tunnels.rotate(pos, newSide); + tunnels.setDirty(); + + if(def instanceof ITunnelRotationEventListener rotationListener) { + var handler = rotationListener.createAfterRotateHandler(tunnel.getTunnel()); + if(handler != null) + handler.afterRotate(server, tunnelOriginalPosition, newRotation, rotationReason); + } + }); + } + + return InteractionResult.SUCCESS; + }).orElseGet(() -> { + CompactMachines.LOGGER.fatal("Failed to interact with tunnel: not assigned to a room"); + return InteractionResult.FAIL; + }); + } + + return InteractionResult.SUCCESS; + } + // todo - breaking block unregisters tunnel info +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/TunnelWallEntity.java b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/TunnelWallEntity.java new file mode 100644 index 00000000..9a6dc979 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/TunnelWallEntity.java @@ -0,0 +1,308 @@ +package dev.compactmods.machines.forge.tunnel; + +import dev.compactmods.machines.api.tunnels.ITunnelHolder; +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.InstancedTunnel; +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 dev.compactmods.machines.api.tunnels.lifecycle.removal.ITunnelRemoveReason; +import dev.compactmods.machines.codec.CodecExtensions; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.wall.Walls; +import dev.compactmods.machines.room.graph.CompactRoomProvider; +import dev.compactmods.machines.tunnel.BaseTunnelWallData; +import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; +import dev.compactmods.machines.tunnel.graph.node.TunnelNode; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.GlobalPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.common.util.LazyOptional; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.WeakReference; + +public class TunnelWallEntity extends BlockEntity implements ITunnelHolder { + + private static final String NBT_LEGACY_MACHINE_KEY = "machine"; + + private GlobalPos connectedMachine; + + private ResourceKey tunnelTypeKey; + private TunnelDefinition tunnelType; + + @Nullable + private TunnelInstance tunnel; + + private WeakReference node; + + public TunnelWallEntity(BlockPos pos, BlockState state) { + super(Tunnels.TUNNEL_BLOCK_ENTITY.get(), pos, state); + } + + @Override + @SuppressWarnings("unchecked") + public void load(@NotNull CompoundTag nbt) { + super.load(nbt); + + final var baseData = BaseTunnelWallData.CODEC.parse(NbtOps.INSTANCE, nbt) + .getOrThrow(true, CompactMachines.LOGGER::fatal); + + this.connectedMachine = baseData.connection(); + this.tunnelTypeKey = ResourceKey.create(TunnelDefinition.REGISTRY_KEY, baseData.tunnelType()); + this.tunnelType = Tunnels.getDefinition(this.tunnelTypeKey); + + try { + if (tunnelType instanceof InstancedTunnel it) + this.tunnel = it.newInstance(worldPosition, getTunnelSide()); + + if (tunnel instanceof INBTSerializable persist && nbt.contains("tunnel_data")) { + var data = nbt.get("tunnel_data"); + persist.deserializeNBT(data); + } + } catch (Exception ex) { + CompactMachines.LOGGER.error("Error loading tunnel persistent data at {}; this is likely a cross-mod issue!", worldPosition, ex); + } + } + + @Override + public void onLoad() { + super.onLoad(); + + if (level instanceof ServerLevel sl) { + // If tunnel type is unknown, remove the tunnel entirely + // Null tunnel types here mean it's being loaded into the world + if (this.tunnelType != null && tunnelType.equals(Tunnels.UNKNOWN.get())) { + CompactMachines.LOGGER.warn("Removing unknown tunnel type at {}", worldPosition.toShortString()); + sl.setBlock(worldPosition, Walls.BLOCK_SOLID_WALL.get().defaultBlockState(), Block.UPDATE_ALL); + } else { + // todo Load tunnel data + node = new WeakReference<>(null); + } + } + } + + @Override + public void saveAdditional(@NotNull CompoundTag compound) { + CodecExtensions.writeIntoTag(BaseTunnelWallData.CODEC, + new BaseTunnelWallData(connectedMachine, tunnelTypeKey.location()), + compound); + + if (tunnel instanceof INBTSerializable persist) { + var data = persist.serializeNBT(); + compound.put("tunnel_data", data); + } + } + + @Nullable + @Override + public Packet getUpdatePacket() { + return super.getUpdatePacket(); + } + + @Override + @NotNull + public CompoundTag getUpdateTag() { + CompoundTag nbt = super.getUpdateTag(); + return CodecExtensions.writeIntoTag(BaseTunnelWallData.CODEC, + new BaseTunnelWallData(connectedMachine, tunnelTypeKey.location()), + nbt); + } + + @Override + public void handleUpdateTag(CompoundTag tag) { + super.handleUpdateTag(tag); + final var data = BaseTunnelWallData.CODEC.parse(NbtOps.INSTANCE, tag) + .getOrThrow(false, CompactMachines.LOGGER::error); + + this.tunnelTypeKey = ResourceKey.create(TunnelDefinition.REGISTRY_KEY, data.tunnelType()); + this.tunnelType = Tunnels.getDefinition(tunnelTypeKey); + this.connectedMachine = data.connection(); + + setChanged(); + } + + @NotNull + public LazyOptional getTunnelCapability(@NotNull Capability cap, @Nullable Direction outerSide) { + if (level == null || level.isClientSide) + return LazyOptional.empty(); + + if (outerSide != null && outerSide != getConnectedSide()) + return LazyOptional.empty(); + + if (tunnelType instanceof CapabilityTunnel c) { + return c.getCapability(cap, tunnel); + } + + return LazyOptional.empty(); + } + + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (level == null || level.isClientSide) + return super.getCapability(cap, side); + + if (side != null && side != getTunnelSide()) + return super.getCapability(cap, side); + + if (tunnelType instanceof CapabilityTunnel c) { + return c.getCapability(cap, tunnel); + } + + return super.getCapability(cap, side); + } + + @NotNull + public GlobalPos connectedMachine() { + return this.connectedMachine; + } + + /** + * Gets the side the tunnel is placed on (the wall inside the machine) + */ + public Direction getTunnelSide() { + BlockState state = getBlockState(); + return state.getValue(TunnelWallBlock.TUNNEL_SIDE); + } + + /** + * Gets the side the tunnel connects to externally (the machine side) + */ + public Direction getConnectedSide() { + BlockState blockState = getBlockState(); + return blockState.getValue(TunnelWallBlock.CONNECTED_SIDE); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private void serverPreRemoval(@Nullable ITunnelRemoveReason reason) { + final var p = new TunnelPosition(worldPosition, getTunnelSide(), getConnectedSide()); + if (tunnelType instanceof TunnelTeardownHandler teardown) { + //noinspection removal + teardown.onRemoved(p, tunnel); + } + + if (tunnelType instanceof ITunnelRemoveEventListener removeListener) { + final var handler = removeListener.createBeforeRemoveHandler(tunnel); + if (handler != null) + handler.beforeRemove(level.getServer(), p, reason); + } + } + + private void serverPostRemoval(@Nullable ITunnelRemoveReason reason) { + final var p = new TunnelPosition(worldPosition, getTunnelSide(), getConnectedSide()); + if (this.tunnelType instanceof InstancedTunnel it) + this.tunnel = it.newInstance(p.pos(), p.wallSide()); + + if (this.tunnelType instanceof ITunnelRemoveEventListener removeListener) { + removeListener.createAfterRemoveHandler(tunnel) + .afterRemove(level.getServer(), p, reason); + } + } + + // TODO : Fix tunnel removal and placement coloration + + private void setTunnelTypeInternal(ResourceKey key, TunnelDefinition definition) { + if (level == null || level.isClientSide || !(level instanceof ServerLevel)) { + this.tunnelTypeKey = key; + this.tunnelType = definition; + return; + } + + // TODO Clean all this up properly with a real removal reason + serverPreRemoval(null); + + this.tunnelTypeKey = key; + this.tunnelType = definition; + + serverPostRemoval(null); + + final var state = getBlockState(); + level.sendBlockUpdated(worldPosition, state, state, Block.UPDATE_ALL); + + setChanged(); + } + + @Override + public void setTunnelType(ResourceKey type) { + if(type == null) { + CompactMachines.LOGGER.warn("Removing tunnel at {} due to it being set null", worldPosition.toShortString()); + level.setBlock(worldPosition, Walls.BLOCK_SOLID_WALL.get().defaultBlockState(), Block.UPDATE_ALL); + return; + } + + if (type.equals(this.tunnelTypeKey)) + return; + + final var def = Tunnels.getDefinition(type); + setTunnelTypeInternal(type, def); + } + + @Override + @Deprecated(forRemoval = true, since = "5.2.0") + @SuppressWarnings("removal") + public void setTunnelType(TunnelDefinition definition) { + final var key = Tunnels.getRegistryKey(definition); + if (this.tunnelTypeKey.equals(key)) + return; + + setTunnelTypeInternal(key, definition); + } + + public TunnelDefinition getTunnelType() { + return tunnelType; + } + + /** + * Server only. Changes where the tunnel is connected to. + * + * @param machine Machine to connect tunnel to. + */ + public void setConnectedTo(GlobalPos machine, Direction side) { + if (level == null || level.isClientSide) return; + this.connectedMachine = machine; + if (level instanceof ServerLevel sl) { + + // TODO - Weak references to room data so we don't have to do this + final var roomProvider = CompactRoomProvider.instance(sl); + roomProvider.findByChunk(new ChunkPos(this.worldPosition)).ifPresent(room -> { + final var graph = TunnelConnectionGraph.forRoom(sl, room.code()); + graph.rebind(worldPosition, machine, side); + }); + } + } + + @Nullable + @SuppressWarnings("unchecked") + public U getTunnel() { + try { + return (U) tunnel; + } catch (ClassCastException ignored) { + return null; + } + } + + public void setInstance(TunnelInstance newTunn) { + this.tunnel = newTunn; + setChanged(); + } + + public TunnelPosition getTunnelPosition() { + return new TunnelPosition(worldPosition, getTunnelSide(), getConnectedSide()); + } +} diff --git a/src/main/java/dev/compactmods/machines/tunnel/Tunnels.java b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/Tunnels.java similarity index 69% rename from src/main/java/dev/compactmods/machines/tunnel/Tunnels.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/Tunnels.java index b464efd2..8301d3d3 100644 --- a/src/main/java/dev/compactmods/machines/tunnel/Tunnels.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/Tunnels.java @@ -1,12 +1,10 @@ -package dev.compactmods.machines.tunnel; +package dev.compactmods.machines.forge.tunnel; -import dev.compactmods.machines.CompactMachines; import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import dev.compactmods.machines.core.Registries; -import dev.compactmods.machines.tunnel.definitions.FluidTunnel; -import dev.compactmods.machines.tunnel.definitions.ForgeEnergyTunnel; -import dev.compactmods.machines.tunnel.definitions.ItemTunnel; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.Registries; import dev.compactmods.machines.tunnel.definitions.UnknownTunnel; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; @@ -25,12 +23,19 @@ public class Tunnels { - public static final Supplier> TUNNEL_DEF_REGISTRY = Registries.TUNNEL_DEFINITIONS.makeRegistry(RegistryBuilder::new); + public static final Supplier> TUNNEL_DEF_REGISTRY = Registries.TUNNEL_DEFINITIONS + .makeRegistry(RegistryBuilder::new); public static boolean isRegistered(ResourceLocation id) { return TUNNEL_DEF_REGISTRY.get().containsKey(id); } + public static TunnelDefinition getDefinition(ResourceKey id) { + if (isRegistered(id.location())) return TUNNEL_DEF_REGISTRY.get().getValue(id.location()); + CompactMachines.LOGGER.warn("Unknown tunnel requested: {}", id); + return Tunnels.UNKNOWN.get(); + } + public static TunnelDefinition getDefinition(ResourceLocation id) { if (isRegistered(id)) return TUNNEL_DEF_REGISTRY.get().getValue(id); CompactMachines.LOGGER.warn("Unknown tunnel requested: {}", id); @@ -40,20 +45,15 @@ public static TunnelDefinition getDefinition(ResourceLocation id) { // ================================================================================================================ // TUNNELS // ================================================================================================================ - public static final RegistryObject UNKNOWN = Registries.TUNNEL_DEFINITIONS.register("unknown", UnknownTunnel::new); + public static final ResourceKey UNKNOWN_KEY = ResourceKey.create(TunnelDefinition.REGISTRY_KEY, + new ResourceLocation(MOD_ID, "unknown")); + + public static final RegistryObject UNKNOWN = Registries.TUNNEL_DEFINITIONS + .register("unknown", UnknownTunnel::new); public static final RegistryObject ITEM_TUNNEL = Registries.ITEMS.register("tunnel", () -> new TunnelItem(new Item.Properties().tab(CompactMachines.COMPACT_MACHINES_ITEMS))); - // ================================================================================================================ - // TUNNEL TYPE DEFINITIONS - // ================================================================================================================ - public static final RegistryObject ITEM_TUNNEL_DEF = Registries.TUNNEL_DEFINITIONS.register("item", ItemTunnel::new); - - public static final RegistryObject FLUID_TUNNEL_DEF = Registries.TUNNEL_DEFINITIONS.register("fluid", FluidTunnel::new); - - public static final RegistryObject FORGE_ENERGY = Registries.TUNNEL_DEFINITIONS.register("energy", ForgeEnergyTunnel::new); - // ================================================================================================================ // TUNNEL BLOCKS / TILES // ================================================================================================================ @@ -64,7 +64,13 @@ public static TunnelDefinition getDefinition(ResourceLocation id) { .lightLevel((state) -> 15))); public static final RegistryObject> TUNNEL_BLOCK_ENTITY = Registries.BLOCK_ENTITIES - .register("tunnel_wall", () -> BlockEntityType.Builder.of(TunnelWallEntity::new, BLOCK_TUNNEL_WALL.get()).build(null)); + .register("tunnel_wall", () -> BlockEntityType.Builder.of(TunnelWallEntity::new, BLOCK_TUNNEL_WALL.get()) + .build(null)); + + public static ResourceKey getRegistryKey(TunnelDefinition definition) { + final var reg = TUNNEL_DEF_REGISTRY.get(); + return reg.getResourceKey(definition).orElse(UNKNOWN_KEY); + } public static ResourceLocation getRegistryId(TunnelDefinition definition) { final var reg = TUNNEL_DEF_REGISTRY.get(); diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/client/TunnelColors.java b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/client/TunnelColors.java new file mode 100644 index 00000000..3262bbdb --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/client/TunnelColors.java @@ -0,0 +1,56 @@ +package dev.compactmods.machines.forge.tunnel.client; + +import dev.compactmods.machines.forge.tunnel.Tunnels; +import dev.compactmods.machines.api.tunnels.ITunnelHolder; +import dev.compactmods.machines.api.tunnels.TunnelDefinition; +import dev.compactmods.machines.tunnel.ITunnelItem; +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.color.item.ItemColor; +import net.minecraft.world.level.block.entity.BlockEntity; + +public class TunnelColors { + + public static final BlockColor BLOCK = (state, reader, position, tintIndex) -> { + try { + if(reader == null || position == null) + return TunnelDefinition.NO_INDICATOR_COLOR; + + BlockEntity tile = reader.getBlockEntity(position); + if (tile instanceof ITunnelHolder tunnel) { + TunnelDefinition type = tunnel.getTunnelType(); + switch(tintIndex) { + case 0: + return type.ringColor(); + + case 1: + return type.indicatorColor(); + } + } + + return TunnelDefinition.NO_INDICATOR_COLOR; + } + + catch(Exception ex) { + return TunnelDefinition.NO_INDICATOR_COLOR; + } + }; + + public static final ItemColor ITEM = (stack, tintIndex) -> { + try { + var definition = ITunnelItem.getDefinition(stack); + if (definition.isEmpty()) + return 0; + + TunnelDefinition actualDef = Tunnels.getDefinition(definition.get()); + if (tintIndex == 0) { + return actualDef.ringColor(); + } + + return actualDef.indicatorColor(); + } + + catch(Exception e) { + return 0; + } + }; +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/graph/traversal/ForgeTunnelTypeFilters.java b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/graph/traversal/ForgeTunnelTypeFilters.java new file mode 100644 index 00000000..339df9b8 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/graph/traversal/ForgeTunnelTypeFilters.java @@ -0,0 +1,19 @@ +package dev.compactmods.machines.forge.tunnel.graph.traversal; + +import dev.compactmods.machines.api.tunnels.capability.CapabilityTunnel; +import dev.compactmods.machines.forge.tunnel.Tunnels; +import dev.compactmods.machines.tunnel.graph.traversal.ITunnelFilter; +import dev.compactmods.machines.tunnel.graph.traversal.TunnelTypeFilters; +import net.minecraftforge.common.capabilities.Capability; + +public class ForgeTunnelTypeFilters { + + public static ITunnelFilter capability(Capability capability) { + return TunnelTypeFilters.definition(def -> { + if (!(def instanceof CapabilityTunnel tcp)) + return false; + + return tcp.getSupportedCapabilities().contains(capability); + }, Tunnels::getDefinition); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/migration/CM510to520RoomTunnelsMigrator.java b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/migration/CM510to520RoomTunnelsMigrator.java new file mode 100644 index 00000000..78da82ef --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/migration/CM510to520RoomTunnelsMigrator.java @@ -0,0 +1,4 @@ +package dev.compactmods.machines.forge.tunnel.migration; + +public class CM510to520RoomTunnelsMigrator { +} diff --git a/src/main/java/dev/compactmods/machines/tunnel/network/TunnelAddedPacket.java b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/network/TunnelAddedPacket.java similarity index 51% rename from src/main/java/dev/compactmods/machines/tunnel/network/TunnelAddedPacket.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/network/TunnelAddedPacket.java index 32e14c48..878b70ff 100644 --- a/src/main/java/dev/compactmods/machines/tunnel/network/TunnelAddedPacket.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/tunnel/network/TunnelAddedPacket.java @@ -1,38 +1,26 @@ -package dev.compactmods.machines.tunnel.network; +package dev.compactmods.machines.forge.tunnel.network; import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import dev.compactmods.machines.tunnel.Tunnels; import dev.compactmods.machines.tunnel.client.ClientTunnelHandler; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceKey; import net.minecraftforge.network.NetworkEvent; import javax.annotation.Nonnull; -import java.util.Objects; import java.util.function.Supplier; -public class TunnelAddedPacket { - - @Nonnull - private final BlockPos position; - - @Nonnull - private final TunnelDefinition type; - - public TunnelAddedPacket(@Nonnull BlockPos tunnelPos, @Nonnull TunnelDefinition tunnelType) { - this.position = tunnelPos; - this.type = tunnelType; - } +public record TunnelAddedPacket(BlockPos position, ResourceKey type) { public TunnelAddedPacket(FriendlyByteBuf buf) { - position = buf.readBlockPos(); - type = Tunnels.getDefinition(buf.readResourceLocation()); + this(buf.readBlockPos(), buf.readResourceKey(TunnelDefinition.REGISTRY_KEY)); } public static void handle(TunnelAddedPacket message, Supplier context) { NetworkEvent.Context ctx = context.get(); ctx.enqueueWork(() -> { - ClientTunnelHandler.setTunnel(message.position, message.type); + final var holder = ClientTunnelHandler.getTunnelHolder(message.position); + holder.setTunnelType(message.type); }); ctx.setPacketHandled(true); @@ -40,6 +28,6 @@ public static void handle(TunnelAddedPacket message, Supplier> REGISTRY = Registries.UPGRADES.makeRegistry(RegistryBuilder::new); + + // ================================================================================================================ + + public static final RegistryObject ROOM_UPGRADE = Registries.ITEMS.register("room_upgrade", () -> new RoomUpgradeItem(new Item.Properties() + .tab(CompactMachines.COMPACT_MACHINES_ITEMS) + .stacksTo(1))); + + public static final RegistryObject WORKBENCH_BLOCK = Registries.BLOCKS.register("workbench", () -> + new RoomUpgradeWorkbench(BlockBehaviour.Properties.of(Material.METAL) + .requiresCorrectToolForDrops() + .lightLevel(state -> 3))); + + public static final RegistryObject WORKBENCH_ITEM = Registries.ITEMS.register("workbench", () -> + new BlockItem(WORKBENCH_BLOCK.get(), new Item.Properties().tab(CompactMachines.COMPACT_MACHINES_ITEMS))); + + public static final RegistryObject> ROOM_UPDATE_ENTITY = Registries.BLOCK_ENTITIES.register( + "workbench", () -> BlockEntityType.Builder.of(RoomUpgradeWorkbenchEntity::new, WORKBENCH_BLOCK.get()) + .build(null)); + + public static void prepare() { + + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/upgrade/RoomUpgradeItem.java b/forge-main/src/main/java/dev/compactmods/machines/forge/upgrade/RoomUpgradeItem.java new file mode 100644 index 00000000..8f19ac05 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/upgrade/RoomUpgradeItem.java @@ -0,0 +1,38 @@ +package dev.compactmods.machines.forge.upgrade; + +import dev.compactmods.machines.api.core.Tooltips; +import dev.compactmods.machines.api.upgrade.RoomUpgradeHelper; +import dev.compactmods.machines.i18n.TranslationUtil; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class RoomUpgradeItem extends Item { + + public RoomUpgradeItem(Properties props) { + super(props); + } + + @Override + public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltips, TooltipFlag flag) { + if (Screen.hasShiftDown()) { + tooltips.add(TranslationUtil.tooltip(Tooltips.TUTORIAL_APPLY_ROOM_UPGRADE).withStyle(ChatFormatting.ITALIC)); + } else { + tooltips.add(TranslationUtil.tooltip(Tooltips.HINT_HOLD_SHIFT).withStyle(ChatFormatting.DARK_GRAY)); + } + + // Show upgrade type while sneaking, or if advanced tooltips are on + if (Screen.hasShiftDown() || flag.isAdvanced()) { + RoomUpgradeHelper.getUpgradeId(stack).ifPresent(upgType -> { + tooltips.add(TranslationUtil.tooltip(Tooltips.ROOM_UPGRADE_TYPE, upgType).withStyle(ChatFormatting.DARK_GRAY)); + }); + } + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/upgrade/graph/RoomUpgradeConnection.java b/forge-main/src/main/java/dev/compactmods/machines/forge/upgrade/graph/RoomUpgradeConnection.java new file mode 100644 index 00000000..dd1ec736 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/upgrade/graph/RoomUpgradeConnection.java @@ -0,0 +1,19 @@ +package dev.compactmods.machines.forge.upgrade.graph; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.compactmods.machines.api.upgrade.RoomUpgrade; +import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades; +import dev.compactmods.machines.graph.edge.IGraphEdge; +import org.jetbrains.annotations.NotNull; + +public record RoomUpgradeConnection(T instance) implements IGraphEdge> { + public static final Codec> CODEC = RecordCodecBuilder.create(i -> i.group( + MachineRoomUpgrades.REGISTRY.get().getCodec().fieldOf("data").forGetter(RoomUpgradeConnection::instance) + ).apply(i, RoomUpgradeConnection::new)); + + @Override + public @NotNull Codec> codec() { + return CODEC; + } +} diff --git a/src/main/java/dev/compactmods/machines/upgrade/graph/UpgradeConnectionEntry.java b/forge-main/src/main/java/dev/compactmods/machines/forge/upgrade/graph/UpgradeConnectionEntry.java similarity index 61% rename from src/main/java/dev/compactmods/machines/upgrade/graph/UpgradeConnectionEntry.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/upgrade/graph/UpgradeConnectionEntry.java index bf402b1f..7ef489d0 100644 --- a/src/main/java/dev/compactmods/machines/upgrade/graph/UpgradeConnectionEntry.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/upgrade/graph/UpgradeConnectionEntry.java @@ -1,17 +1,15 @@ -package dev.compactmods.machines.upgrade.graph; +package dev.compactmods.machines.forge.upgrade.graph; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.codec.CodecExtensions; -import dev.compactmods.machines.api.room.upgrade.RoomUpgrade; -import dev.compactmods.machines.upgrade.MachineRoomUpgrades; +import dev.compactmods.machines.api.upgrade.RoomUpgrade; +import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades; import net.minecraft.resources.ResourceKey; -import net.minecraft.world.level.ChunkPos; -public record UpgradeConnectionEntry(ChunkPos room, ResourceKey upgradeKey, T instance) { +public record UpgradeConnectionEntry(String room, ResourceKey upgradeKey, T instance) { public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - CodecExtensions.CHUNKPOS + Codec.STRING .fieldOf("room") .forGetter(UpgradeConnectionEntry::room), diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/util/AnnotationScanner.java b/forge-main/src/main/java/dev/compactmods/machines/forge/util/AnnotationScanner.java new file mode 100644 index 00000000..6f57eca8 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/util/AnnotationScanner.java @@ -0,0 +1,55 @@ +package dev.compactmods.machines.forge.util; + +import net.minecraftforge.fml.ModList; +import net.minecraftforge.forgespi.language.ModFileScanData; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.objectweb.asm.Type; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Stream; + +// thanks to JEI's ForgePluginFinder for a baseline +public class AnnotationScanner { + + private static final Logger SCANNER_LOG = LogManager.getLogger(); + + public static Stream scanModList(Class type) { + return ModList.get() + .getAllScanData() + .stream() + .flatMap(scans -> scans.getAnnotations() + .stream() + .filter(ad -> ad.annotationType().equals(Type.getType(type))) + ); + } + + public static Stream scanFields(T instance, Class annotationType) { + var parent = instance.getClass(); + return Arrays.stream(parent.getDeclaredFields()) + .filter(field -> field.isAnnotationPresent(annotationType)); + } + + public static Stream scanMethods(T instance, Class annotationType) { + var parent = instance.getClass(); + return Arrays.stream(parent.getDeclaredMethods()) + .filter(meth -> meth.isAnnotationPresent(annotationType)); + } + + public static void injectFields(Target target, Value val, Set injectableFields) { + injectableFields.stream() + .filter(field -> field.getType().isAssignableFrom(val.getClass())) + .forEach(field -> { + try { + field.set(target, val); + } catch (IllegalAccessException e) { + SCANNER_LOG.error("Failed to inject lookup data {} into addon {}", field.getName(), target.getClass().getName()); + SCANNER_LOG.error(e); + } + }); + } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/util/ForgePlayerUtil.java b/forge-main/src/main/java/dev/compactmods/machines/forge/util/ForgePlayerUtil.java new file mode 100644 index 00000000..6531a8cd --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/util/ForgePlayerUtil.java @@ -0,0 +1,33 @@ +package dev.compactmods.machines.forge.util; + +import dev.compactmods.machines.forge.dimension.SimpleTeleporter; +import dev.compactmods.machines.forge.network.CompactMachinesNet; +import dev.compactmods.machines.forge.network.SyncRoomMetadataPacket; +import dev.compactmods.machines.forge.room.RoomHelper; +import net.minecraft.Util; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.PacketDistributor; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +public class ForgePlayerUtil { + public static void teleportPlayerToRespawnOrOverworld(MinecraftServer serv, @NotNull ServerPlayer player) { + ServerLevel level = Optional.ofNullable(serv.getLevel(player.getRespawnDimension())).orElse(serv.overworld()); + Vec3 worldPos = Vec3.atCenterOf(level.getSharedSpawnPos()); + + if (player.getRespawnPosition() != null) + worldPos = Vec3.atCenterOf(player.getRespawnPosition()); + + player.changeDimension(level, SimpleTeleporter.to(worldPos)); + + player.getCapability(RoomHelper.CURRENT_ROOM_META).ifPresent(provider -> { + provider.clearCurrent(); + CompactMachinesNet.CHANNEL.send(PacketDistributor.PLAYER.with(() -> player), + new SyncRoomMetadataPacket("", Util.NIL_UUID)); + }); + } +} diff --git a/src/main/java/dev/compactmods/machines/util/VersionUtil.java b/forge-main/src/main/java/dev/compactmods/machines/forge/util/VersionUtil.java similarity index 91% rename from src/main/java/dev/compactmods/machines/util/VersionUtil.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/util/VersionUtil.java index 75b83266..6e9bb355 100644 --- a/src/main/java/dev/compactmods/machines/util/VersionUtil.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/util/VersionUtil.java @@ -1,4 +1,4 @@ -package dev.compactmods.machines.util; +package dev.compactmods.machines.forge.util; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/villager/VillagerTradesEventHandler.java b/forge-main/src/main/java/dev/compactmods/machines/forge/villager/VillagerTradesEventHandler.java new file mode 100644 index 00000000..c9aaeef1 --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/villager/VillagerTradesEventHandler.java @@ -0,0 +1,18 @@ +package dev.compactmods.machines.forge.villager; + +import dev.compactmods.machines.api.core.Constants; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(modid = Constants.MOD_ID) +public class VillagerTradesEventHandler { + +// @SubscribeEvent +// public static void onVillagerTrades(final VillagerTradesEvent trades) { +// final var tinkerer = Villagers.TINKERER.get(); +// if(!trades.getType().equals(tinkerer)) +// return; +// +// final var tradeList = trades.getTrades(); +// tradeList.get(1).add(Villagers.TEST_TRADE.get()); +// } +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/villager/VillagerUpgradeTrade.java b/forge-main/src/main/java/dev/compactmods/machines/forge/villager/VillagerUpgradeTrade.java new file mode 100644 index 00000000..c4d8956e --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/villager/VillagerUpgradeTrade.java @@ -0,0 +1,4 @@ +package dev.compactmods.machines.forge.villager; + +public class VillagerUpgradeTrade { +} diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/villager/Villagers.java b/forge-main/src/main/java/dev/compactmods/machines/forge/villager/Villagers.java new file mode 100644 index 00000000..031dda7c --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/villager/Villagers.java @@ -0,0 +1,51 @@ +package dev.compactmods.machines.forge.villager; + +import com.google.common.collect.ImmutableSet; +import dev.compactmods.machines.forge.Registries; +import dev.compactmods.machines.forge.upgrade.MachineRoomUpgrades; +import dev.compactmods.machines.api.core.Constants; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.entity.ai.village.poi.PoiType; +import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +public class Villagers { + public static final ResourceLocation TINKERER_ID = new ResourceLocation(Constants.MOD_ID, "tinkerer"); + + public static final ResourceKey TINKERER_WORKBENCH_KEY = ResourceKey + .create(ForgeRegistries.POI_TYPES.getRegistryKey(), TINKERER_ID); + + public static final RegistryObject TINKERER = Registries.VILLAGERS.register("tinkerer", + () -> new VillagerProfession( + TINKERER_ID.toString(), + holder -> holder.is(TINKERER_WORKBENCH_KEY), //jobSite + holder -> holder.is(TINKERER_WORKBENCH_KEY), //acquirable jobSite + ImmutableSet.of(), + ImmutableSet.of(), + SoundEvents.VILLAGER_WORK_TOOLSMITH + )); + +// public static final DeferredRegister TRADES = DeferredRegister.create( +// new ResourceLocation(Constants.MOD_ID, "tinkerer_trades"), +// Constants.MOD_ID +// ); + +// public static final Supplier> TRADES_REG = TRADES +// .makeRegistry(RegistryBuilder::new); + +// public static final RegistryObject TEST_TRADE = TRADES.register("test", +// () -> new BasicItemListing(1, new ItemStack(Machines.MACHINE_BLOCK_ITEM_TINY.get()), 5, 100)); + + static { + Registries.POINTS_OF_INTEREST.register("tinkerer", () -> new PoiType( + ImmutableSet.of(MachineRoomUpgrades.WORKBENCH_BLOCK.get().defaultBlockState()), 1, 1) + ); + } + + public static void prepare() { + + } +} diff --git a/src/main/java/dev/compactmods/machines/core/CommonEventHandler.java b/forge-main/src/main/java/dev/compactmods/machines/forge/wall/ProtectedBlockHandler.java similarity index 84% rename from src/main/java/dev/compactmods/machines/core/CommonEventHandler.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/wall/ProtectedBlockHandler.java index 1ed5d81f..c8950b61 100644 --- a/src/main/java/dev/compactmods/machines/core/CommonEventHandler.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/wall/ProtectedBlockHandler.java @@ -1,13 +1,12 @@ -package dev.compactmods.machines.core; +package dev.compactmods.machines.forge.wall; import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.wall.ProtectedWallBlock; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; @Mod.EventBusSubscriber(modid = Constants.MOD_ID) -public class CommonEventHandler { +public class ProtectedBlockHandler { @SubscribeEvent public static void onLeftClickBlock(final PlayerInteractEvent.LeftClickBlock evt) { diff --git a/src/main/java/dev/compactmods/machines/wall/ProtectedWallBlock.java b/forge-main/src/main/java/dev/compactmods/machines/forge/wall/ProtectedWallBlock.java similarity index 97% rename from src/main/java/dev/compactmods/machines/wall/ProtectedWallBlock.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/wall/ProtectedWallBlock.java index 083e2482..a6a94b2e 100644 --- a/src/main/java/dev/compactmods/machines/wall/ProtectedWallBlock.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/wall/ProtectedWallBlock.java @@ -1,4 +1,4 @@ -package dev.compactmods.machines.wall; +package dev.compactmods.machines.forge.wall; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; diff --git a/forge-main/src/main/java/dev/compactmods/machines/forge/wall/SolidWallBlock.java b/forge-main/src/main/java/dev/compactmods/machines/forge/wall/SolidWallBlock.java new file mode 100644 index 00000000..470eea8c --- /dev/null +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/wall/SolidWallBlock.java @@ -0,0 +1,12 @@ +package dev.compactmods.machines.forge.wall; + +public class SolidWallBlock extends ProtectedWallBlock { + public SolidWallBlock(Properties props) { + super(props); + } + +// @Override +// public boolean isValidSpawn(BlockState state, BlockGetter world, BlockPos pos, SpawnPlacements.Type type, EntityType entityType) { +// return pos.getY() == 40; +// } +} diff --git a/src/main/java/dev/compactmods/machines/wall/Walls.java b/forge-main/src/main/java/dev/compactmods/machines/forge/wall/Walls.java similarity index 86% rename from src/main/java/dev/compactmods/machines/wall/Walls.java rename to forge-main/src/main/java/dev/compactmods/machines/forge/wall/Walls.java index 045670f9..76dc385a 100644 --- a/src/main/java/dev/compactmods/machines/wall/Walls.java +++ b/forge-main/src/main/java/dev/compactmods/machines/forge/wall/Walls.java @@ -1,7 +1,9 @@ -package dev.compactmods.machines.wall; +package dev.compactmods.machines.forge.wall; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.core.Registries; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.forge.Registries; +import dev.compactmods.machines.wall.BreakableWallBlock; +import dev.compactmods.machines.wall.ItemBlockWall; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.SoundType; diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/forge-main/src/main/resources/META-INF/accesstransformer.cfg similarity index 100% rename from src/main/resources/META-INF/accesstransformer.cfg rename to forge-main/src/main/resources/META-INF/accesstransformer.cfg diff --git a/forge-main/src/main/resources/META-INF/mods.toml b/forge-main/src/main/resources/META-INF/mods.toml new file mode 100644 index 00000000..376aa724 --- /dev/null +++ b/forge-main/src/main/resources/META-INF/mods.toml @@ -0,0 +1,33 @@ +modLoader="javafml" #mandatory +loaderVersion="[42,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +license="MIT" + +[[mods]] #mandatory + modId="compactmachines" + version="${file.jarVersion}" + displayName="Compact Machines 5" + authors="Davenonymous, RobotGryphon" #optional + description="It's all so tiny!" + + issueTrackerURL="https://github.com/CompactMods/CompactMachines/issues" + + #updateJSONURL="http://myurl.me/" #optional + displayURL="https://compactmods.dev" + + # A file name (in the root of the mod JAR) containing a logo for display + # logoFile="examplemod.png" #optional + +# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. +[[dependencies.compactmachines]] #optional + modId="forge" + mandatory=true + versionRange="[42,)" + ordering="NONE" + side="BOTH" + +[[dependencies.compactmachines]] + modId="minecraft" + mandatory=true + versionRange="[1.19.1,)" + ordering="NONE" + side="BOTH" \ No newline at end of file diff --git a/src/main/resources/assets/compactmachines/shaders/core/block_fullbright.fsh b/forge-main/src/main/resources/assets/compactmachines/shaders/core/block_fullbright.fsh similarity index 100% rename from src/main/resources/assets/compactmachines/shaders/core/block_fullbright.fsh rename to forge-main/src/main/resources/assets/compactmachines/shaders/core/block_fullbright.fsh diff --git a/src/main/resources/assets/compactmachines/shaders/core/block_fullbright.json b/forge-main/src/main/resources/assets/compactmachines/shaders/core/block_fullbright.json similarity index 100% rename from src/main/resources/assets/compactmachines/shaders/core/block_fullbright.json rename to forge-main/src/main/resources/assets/compactmachines/shaders/core/block_fullbright.json diff --git a/src/main/resources/assets/compactmachines/shaders/core/block_fullbright.vsh b/forge-main/src/main/resources/assets/compactmachines/shaders/core/block_fullbright.vsh similarity index 100% rename from src/main/resources/assets/compactmachines/shaders/core/block_fullbright.vsh rename to forge-main/src/main/resources/assets/compactmachines/shaders/core/block_fullbright.vsh diff --git a/src/main/resources/assets/compactmachines/shaders/core/wall.fsh b/forge-main/src/main/resources/assets/compactmachines/shaders/core/wall.fsh similarity index 100% rename from src/main/resources/assets/compactmachines/shaders/core/wall.fsh rename to forge-main/src/main/resources/assets/compactmachines/shaders/core/wall.fsh diff --git a/src/main/resources/assets/compactmachines/shaders/core/wall.json b/forge-main/src/main/resources/assets/compactmachines/shaders/core/wall.json similarity index 100% rename from src/main/resources/assets/compactmachines/shaders/core/wall.json rename to forge-main/src/main/resources/assets/compactmachines/shaders/core/wall.json diff --git a/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/border.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/border.png new file mode 100644 index 00000000..aa3cda37 Binary files /dev/null and b/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/border.png differ diff --git a/src/main/resources/assets/compactmachines/textures/block/machine/machine_giant.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/machine_giant.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/machine/machine_giant.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/machine/machine_giant.png diff --git a/src/main/resources/assets/compactmachines/textures/block/machine/machine_large.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/machine_large.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/machine/machine_large.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/machine/machine_large.png diff --git a/src/main/resources/assets/compactmachines/textures/block/machine/machine_maximum.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/machine_maximum.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/machine/machine_maximum.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/machine/machine_maximum.png diff --git a/src/main/resources/assets/compactmachines/textures/block/machine/machine_normal.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/machine_normal.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/machine/machine_normal.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/machine/machine_normal.png diff --git a/src/main/resources/assets/compactmachines/textures/block/machine/machine_small.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/machine_small.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/machine/machine_small.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/machine/machine_small.png diff --git a/src/main/resources/assets/compactmachines/textures/block/machine/machine_tiny.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/machine_tiny.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/machine/machine_tiny.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/machine/machine_tiny.png diff --git a/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/overlay.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/overlay.png new file mode 100644 index 00000000..d505c643 Binary files /dev/null and b/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/overlay.png differ diff --git a/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/tint.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/tint.png new file mode 100644 index 00000000..6b2a1290 Binary files /dev/null and b/forge-main/src/main/resources/assets/compactmachines/textures/block/machine/tint.png differ diff --git a/src/main/resources/assets/compactmachines/textures/block/tunnels/down.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/down.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/tunnels/down.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/down.png diff --git a/src/main/resources/assets/compactmachines/textures/block/tunnels/east.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/east.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/tunnels/east.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/east.png diff --git a/src/main/resources/assets/compactmachines/textures/block/tunnels/indicator.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/indicator.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/tunnels/indicator.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/indicator.png diff --git a/src/main/resources/assets/compactmachines/textures/block/tunnels/none.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/none.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/tunnels/none.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/none.png diff --git a/src/main/resources/assets/compactmachines/textures/block/tunnels/north.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/north.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/tunnels/north.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/north.png diff --git a/src/main/resources/assets/compactmachines/textures/block/tunnels/south.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/south.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/tunnels/south.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/south.png diff --git a/src/main/resources/assets/compactmachines/textures/block/tunnels/tunnel.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/tunnel.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/tunnels/tunnel.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/tunnel.png diff --git a/src/main/resources/assets/compactmachines/textures/block/tunnels/up.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/up.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/tunnels/up.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/up.png diff --git a/src/main/resources/assets/compactmachines/textures/block/tunnels/west.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/west.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/tunnels/west.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/tunnels/west.png diff --git a/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_giant.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_giant.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_giant.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_giant.png diff --git a/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_large.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_large.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_large.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_large.png diff --git a/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_maximum.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_maximum.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_maximum.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_maximum.png diff --git a/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_normal.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_normal.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_normal.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_normal.png diff --git a/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_small.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_small.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_small.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_small.png diff --git a/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_tiny.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_tiny.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_tiny.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/upgrades/upgrade_tiny.png diff --git a/src/main/resources/assets/compactmachines/textures/block/wall.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/wall.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/block/wall.png rename to forge-main/src/main/resources/assets/compactmachines/textures/block/wall.png diff --git a/forge-main/src/main/resources/assets/compactmachines/textures/block/workbench/sides.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/workbench/sides.png new file mode 100644 index 00000000..7f276fcb Binary files /dev/null and b/forge-main/src/main/resources/assets/compactmachines/textures/block/workbench/sides.png differ diff --git a/forge-main/src/main/resources/assets/compactmachines/textures/block/workbench/top.png b/forge-main/src/main/resources/assets/compactmachines/textures/block/workbench/top.png new file mode 100644 index 00000000..7d5de200 Binary files /dev/null and b/forge-main/src/main/resources/assets/compactmachines/textures/block/workbench/top.png differ diff --git a/forge-main/src/main/resources/assets/compactmachines/textures/curios/empty_psd.png b/forge-main/src/main/resources/assets/compactmachines/textures/curios/empty_psd.png new file mode 100644 index 00000000..0ce2374c Binary files /dev/null and b/forge-main/src/main/resources/assets/compactmachines/textures/curios/empty_psd.png differ diff --git a/src/main/resources/assets/compactmachines/textures/entities/villager.png b/forge-main/src/main/resources/assets/compactmachines/textures/entities/villager.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/entities/villager.png rename to forge-main/src/main/resources/assets/compactmachines/textures/entities/villager.png diff --git a/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_large.png b/forge-main/src/main/resources/assets/compactmachines/textures/entity/villager/profession/tinkerer-old.png similarity index 66% rename from src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_large.png rename to forge-main/src/main/resources/assets/compactmachines/textures/entity/villager/profession/tinkerer-old.png index d80b50f0..822df393 100644 Binary files a/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_large.png and b/forge-main/src/main/resources/assets/compactmachines/textures/entity/villager/profession/tinkerer-old.png differ diff --git a/forge-main/src/main/resources/assets/compactmachines/textures/entity/villager/profession/tinkerer.aseprite b/forge-main/src/main/resources/assets/compactmachines/textures/entity/villager/profession/tinkerer.aseprite new file mode 100644 index 00000000..4152208d Binary files /dev/null and b/forge-main/src/main/resources/assets/compactmachines/textures/entity/villager/profession/tinkerer.aseprite differ diff --git a/forge-main/src/main/resources/assets/compactmachines/textures/entity/villager/profession/tinkerer.png b/forge-main/src/main/resources/assets/compactmachines/textures/entity/villager/profession/tinkerer.png new file mode 100644 index 00000000..7c89c99d Binary files /dev/null and b/forge-main/src/main/resources/assets/compactmachines/textures/entity/villager/profession/tinkerer.png differ diff --git a/forge-main/src/main/resources/assets/compactmachines/textures/entity/villager/profession/tinkerer.png.mcmeta b/forge-main/src/main/resources/assets/compactmachines/textures/entity/villager/profession/tinkerer.png.mcmeta new file mode 100644 index 00000000..f24387e7 --- /dev/null +++ b/forge-main/src/main/resources/assets/compactmachines/textures/entity/villager/profession/tinkerer.png.mcmeta @@ -0,0 +1,5 @@ +{ + "villager": { + "hat": "full" + } +} diff --git a/src/main/resources/assets/compactmachines/textures/gui/field_example.png b/forge-main/src/main/resources/assets/compactmachines/textures/gui/field_example.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/gui/field_example.png rename to forge-main/src/main/resources/assets/compactmachines/textures/gui/field_example.png diff --git a/src/main/resources/assets/compactmachines/textures/gui/psd_screen.png b/forge-main/src/main/resources/assets/compactmachines/textures/gui/psd_screen.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/gui/psd_screen.png rename to forge-main/src/main/resources/assets/compactmachines/textures/gui/psd_screen.png diff --git a/src/main/resources/assets/compactmachines/textures/gui/room_menu.png b/forge-main/src/main/resources/assets/compactmachines/textures/gui/room_menu.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/gui/room_menu.png rename to forge-main/src/main/resources/assets/compactmachines/textures/gui/room_menu.png diff --git a/src/main/resources/assets/compactmachines/textures/gui/tabicons.png b/forge-main/src/main/resources/assets/compactmachines/textures/gui/tabicons.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/gui/tabicons.png rename to forge-main/src/main/resources/assets/compactmachines/textures/gui/tabicons.png diff --git a/src/main/resources/assets/compactmachines/textures/item/minifluiddrop.png b/forge-main/src/main/resources/assets/compactmachines/textures/item/minifluiddrop.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/item/minifluiddrop.png rename to forge-main/src/main/resources/assets/compactmachines/textures/item/minifluiddrop.png diff --git a/src/main/resources/assets/compactmachines/textures/item/personal_shrinking_device.png b/forge-main/src/main/resources/assets/compactmachines/textures/item/personal_shrinking_device.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/item/personal_shrinking_device.png rename to forge-main/src/main/resources/assets/compactmachines/textures/item/personal_shrinking_device.png diff --git a/forge-main/src/main/resources/assets/compactmachines/textures/item/room_core.png b/forge-main/src/main/resources/assets/compactmachines/textures/item/room_core.png new file mode 100644 index 00000000..237639cd Binary files /dev/null and b/forge-main/src/main/resources/assets/compactmachines/textures/item/room_core.png differ diff --git a/src/main/resources/assets/compactmachines/textures/item/tunnel.png b/forge-main/src/main/resources/assets/compactmachines/textures/item/tunnel.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/item/tunnel.png rename to forge-main/src/main/resources/assets/compactmachines/textures/item/tunnel.png diff --git a/src/main/resources/assets/compactmachines/textures/particles/blockmarker.png b/forge-main/src/main/resources/assets/compactmachines/textures/particles/blockmarker.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/particles/blockmarker.png rename to forge-main/src/main/resources/assets/compactmachines/textures/particles/blockmarker.png diff --git a/src/main/resources/assets/compactmachines/textures/upgrades/chunkloader.png b/forge-main/src/main/resources/assets/compactmachines/textures/upgrades/chunkloader.png similarity index 100% rename from src/main/resources/assets/compactmachines/textures/upgrades/chunkloader.png rename to forge-main/src/main/resources/assets/compactmachines/textures/upgrades/chunkloader.png diff --git a/src/main/resources/pack.mcmeta b/forge-main/src/main/resources/pack.mcmeta similarity index 100% rename from src/main/resources/pack.mcmeta rename to forge-main/src/main/resources/pack.mcmeta diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/GameTestEventHandler.java b/forge-main/src/test/java/dev/compactmods/machines/test/GameTestEventHandler.java new file mode 100644 index 00000000..c5fdb3df --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/GameTestEventHandler.java @@ -0,0 +1,18 @@ +package dev.compactmods.machines.test; + +import dev.compactmods.machines.api.core.Constants; +import net.minecraftforge.event.RegisterGameTestsEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(modid = Constants.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) +public class GameTestEventHandler { + + @SubscribeEvent + public static void registerCrossmodGametests(final RegisterGameTestsEvent gametests) { + final var mods = ModList.get(); + + // if(mods.isLoaded("mekanism")) gametests.register(Mekanism.class); + } +} diff --git a/src/test/java/dev/compactmods/machines/test/MathTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/MathTests.java similarity index 95% rename from src/test/java/dev/compactmods/machines/test/MathTests.java rename to forge-main/src/test/java/dev/compactmods/machines/test/MathTests.java index 66cc6fb2..f031bc0f 100644 --- a/src/test/java/dev/compactmods/machines/test/MathTests.java +++ b/forge-main/src/test/java/dev/compactmods/machines/test/MathTests.java @@ -1,7 +1,6 @@ package dev.compactmods.machines.test; -import java.util.HashMap; -import dev.compactmods.machines.CompactMachines; +import dev.compactmods.machines.api.core.Constants; import dev.compactmods.machines.util.MathUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; @@ -11,8 +10,10 @@ import net.minecraftforge.gametest.GameTestHolder; import net.minecraftforge.gametest.PrefixGameTestTemplate; +import java.util.HashMap; + @PrefixGameTestTemplate(false) -@GameTestHolder(CompactMachines.MOD_ID) +@GameTestHolder(Constants.MOD_ID) public class MathTests { @GameTest(template = "empty_1x1", batch = TestBatches.MATH) diff --git a/src/test/java/dev/compactmods/machines/test/ServerEvents.java b/forge-main/src/test/java/dev/compactmods/machines/test/ServerEvents.java similarity index 83% rename from src/test/java/dev/compactmods/machines/test/ServerEvents.java rename to forge-main/src/test/java/dev/compactmods/machines/test/ServerEvents.java index d30c7e8a..0f77c31b 100644 --- a/src/test/java/dev/compactmods/machines/test/ServerEvents.java +++ b/forge-main/src/test/java/dev/compactmods/machines/test/ServerEvents.java @@ -1,6 +1,7 @@ package dev.compactmods.machines.test; -import dev.compactmods.machines.CompactMachines; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.api.core.Constants; import dev.compactmods.machines.api.dimension.CompactDimension; import dev.compactmods.machines.util.DimensionUtil; import net.minecraft.server.MinecraftServer; @@ -8,7 +9,7 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -@Mod.EventBusSubscriber(modid = CompactMachines.MOD_ID) +@Mod.EventBusSubscriber(modid = Constants.MOD_ID) public class ServerEvents { @SubscribeEvent diff --git a/src/test/java/dev/compactmods/machines/test/TestBatches.java b/forge-main/src/test/java/dev/compactmods/machines/test/TestBatches.java similarity index 90% rename from src/test/java/dev/compactmods/machines/test/TestBatches.java rename to forge-main/src/test/java/dev/compactmods/machines/test/TestBatches.java index db6923de..acb23aaa 100644 --- a/src/test/java/dev/compactmods/machines/test/TestBatches.java +++ b/forge-main/src/test/java/dev/compactmods/machines/test/TestBatches.java @@ -12,4 +12,5 @@ public final class TestBatches { public static final String MATH = "math"; public static final String MACHINE_DATA = "machine_data"; public static final String DIMENSION = "dimension"; + public static final String MIGRATION = "migration"; } diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/TestRegistration.java b/forge-main/src/test/java/dev/compactmods/machines/test/TestRegistration.java new file mode 100644 index 00000000..c7c1e18a --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/TestRegistration.java @@ -0,0 +1,22 @@ +package dev.compactmods.machines.test; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.api.tunnels.TunnelDefinition; +import dev.compactmods.machines.test.tunnel.FakeTunnelDefinition; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.registries.RegisterEvent; + +@Mod.EventBusSubscriber(modid = Constants.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) +public class TestRegistration { + + @SubscribeEvent + public static void onRegisterEvent(final RegisterEvent e) { + if (e.getRegistryKey().equals(TunnelDefinition.REGISTRY_KEY)) { + e.register(TunnelDefinition.REGISTRY_KEY, (helper) -> { + final var inst = new FakeTunnelDefinition(); + helper.register(FakeTunnelDefinition.ID, inst); + }); + } + } +} diff --git a/src/test/java/dev/compactmods/machines/test/core/CompactMachinesTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/core/CompactMachinesTests.java similarity index 85% rename from src/test/java/dev/compactmods/machines/test/core/CompactMachinesTests.java rename to forge-main/src/test/java/dev/compactmods/machines/test/core/CompactMachinesTests.java index f7f8ac66..944a47cb 100644 --- a/src/test/java/dev/compactmods/machines/test/core/CompactMachinesTests.java +++ b/forge-main/src/test/java/dev/compactmods/machines/test/core/CompactMachinesTests.java @@ -1,6 +1,7 @@ package dev.compactmods.machines.test.core; -import dev.compactmods.machines.CompactMachines; +import dev.compactmods.machines.forge.CompactMachines; +import dev.compactmods.machines.api.core.Constants; import dev.compactmods.machines.test.TestBatches; import net.minecraft.gametest.framework.GameTest; import net.minecraft.gametest.framework.GameTestHelper; @@ -8,7 +9,7 @@ import net.minecraftforge.gametest.PrefixGameTestTemplate; @PrefixGameTestTemplate(false) -@GameTestHolder(CompactMachines.MOD_ID) +@GameTestHolder(Constants.MOD_ID) public class CompactMachinesTests { @GameTest(template = "empty_1x1", batch = TestBatches.CODEC_TESTS) diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/crossmod/Mekanism.java b/forge-main/src/test/java/dev/compactmods/machines/test/crossmod/Mekanism.java new file mode 100644 index 00000000..32c52ea1 --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/crossmod/Mekanism.java @@ -0,0 +1,18 @@ +package dev.compactmods.machines.test.crossmod; + +import dev.compactmods.machines.forge.CompactMachines; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraftforge.gametest.PrefixGameTestTemplate; + +@PrefixGameTestTemplate(false) +public class Mekanism { + + public static final String MEKANISM_BATCH = "mekanism"; + + @GameTest(templateNamespace = "compactmachines", template = "empty_1x1", batch = MEKANISM_BATCH) + public static void testMekanism(final GameTestHelper test) { + CompactMachines.LOGGER.debug("Testing mekanism interactions!"); + test.succeed(); + } +} diff --git a/src/test/java/dev/compactmods/machines/test/data/CodecTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/data/CodecTests.java similarity index 92% rename from src/test/java/dev/compactmods/machines/test/data/CodecTests.java rename to forge-main/src/test/java/dev/compactmods/machines/test/data/CodecTests.java index aa7bbd7e..81ae806a 100644 --- a/src/test/java/dev/compactmods/machines/test/data/CodecTests.java +++ b/forge-main/src/test/java/dev/compactmods/machines/test/data/CodecTests.java @@ -1,8 +1,8 @@ package dev.compactmods.machines.test.data; import com.mojang.serialization.DataResult; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.codec.CodecExtensions; +import dev.compactmods.machines.codec.CodecExtensions; +import dev.compactmods.machines.api.core.Constants; import dev.compactmods.machines.api.room.RoomSize; import dev.compactmods.machines.test.TestBatches; import net.minecraft.gametest.framework.GameTest; @@ -16,7 +16,7 @@ import net.minecraftforge.gametest.PrefixGameTestTemplate; @PrefixGameTestTemplate(false) -@GameTestHolder(CompactMachines.MOD_ID) +@GameTestHolder(Constants.MOD_ID) public class CodecTests { @GameTest(template = "empty_1x1", batch = TestBatches.CODEC_TESTS) @@ -41,6 +41,7 @@ public static void canSerializeVector3d(final GameTestHelper test) { test.succeed(); } + @Deprecated(forRemoval = true, since = "5.2.0") @GameTest(template = "empty_1x1", batch = TestBatches.CODEC_TESTS) public static void canSerializeMachineSize(final GameTestHelper test) { DataResult result = RoomSize.CODEC.encodeStart(NbtOps.INSTANCE, RoomSize.LARGE); diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/migration/EarlyFileLoaderTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/migration/EarlyFileLoaderTests.java new file mode 100644 index 00000000..69d8ff9e --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/migration/EarlyFileLoaderTests.java @@ -0,0 +1,37 @@ +package dev.compactmods.machines.test.migration; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.forge.data.migration.EarlyLevelDataFileReader; +import dev.compactmods.machines.test.TestBatches; +import dev.compactmods.machines.test.util.FileHelper; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.gametest.PrefixGameTestTemplate; + +@PrefixGameTestTemplate(false) +@GameTestHolder(Constants.MOD_ID) +public class EarlyFileLoaderTests { + + @GameTest(template = "empty_1x1", batch = TestBatches.MIGRATION) + public static void canGetDimensions(final GameTestHelper test) { + final var resRoot = FileHelper.resourcesDir(); + if(resRoot == null) { + test.fail("No resource path defined; cannot complete test."); + return; + } + + final var resLoc = resRoot.resolve("migrate").resolve("pre520"); + final var save = new LevelStorageSource.LevelDirectory(resLoc); + final var loader = new EarlyLevelDataFileReader(save); + + final var dims = loader.dimensions(); + if(dims.isEmpty()) { + test.fail("Did not read any dimension info from level files; this should be impossible."); + return; + } + + test.succeed(); + } +} diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/migration/RoomInfoPre520MigratorTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/migration/RoomInfoPre520MigratorTests.java new file mode 100644 index 00000000..facc9719 --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/migration/RoomInfoPre520MigratorTests.java @@ -0,0 +1,77 @@ +package dev.compactmods.machines.test.migration; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.api.room.RoomSize; +import dev.compactmods.machines.forge.data.migration.Pre520RoomDataMigrator; +import dev.compactmods.machines.test.TestBatches; +import dev.compactmods.machines.test.util.FileHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.gametest.PrefixGameTestTemplate; + +import java.io.IOException; +import java.util.UUID; + +@PrefixGameTestTemplate(false) +@GameTestHolder(Constants.MOD_ID) +public class RoomInfoPre520MigratorTests { + + @GameTest(template = "empty_1x1", batch = TestBatches.MIGRATION) + public static void canReadPre520RoomFiles(final GameTestHelper test) { + + try { + final var oldRoomData = FileHelper.getNbtFromSavedDataFile("migrate/pre520/room_data.dat"); + final var oldData = Pre520RoomDataMigrator.loadOldRoomData(oldRoomData); + + if(oldData.oldRoomData().isEmpty()) { + test.fail("No data loaded."); + return; + } + + if(oldData.oldRoomData().size() != 3) { + test.fail("Expected 3 entries from old data; got %s".formatted(oldData.oldRoomData().size())); + return; + } + + if(!oldData.roomChunkLookup().containsKey(new ChunkPos(0, -64))) { + test.fail("Expected chunk [0,-64] in chunk lookup, but it was not found."); + return; + } + + test.succeed(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @GameTest(template = "empty_1x1", batch = TestBatches.MIGRATION) + public static void canReadSingleRoom(final GameTestHelper test) { + + try { + final var nbtData = FileHelper.getNbtFromFile("migrate/pre520/single_room.dat"); + final var oldData = Pre520RoomDataMigrator.RoomDataPre520.of(nbtData); + + if(!oldData.center().equals(new BlockPos(8, 45, -1016))) + test.fail("Room center did not match expected value."); + + if(!oldData.size().equals(RoomSize.GIANT)) + test.fail("Expected room size to be 'giant'."); + + if(!oldData.spawn().equals(new Vec3(8, 40, -1016))) + test.fail("Room spawn did not match expected value."); + + if(!oldData.owner().equals(UUID.fromString("6878c888-1219-4639-9c1a-de524a628dcb"))) + test.fail("Owner did not match expected value."); + } + + catch(Exception e) { + test.fail(e.getMessage()); + } + + test.succeed(); + } +} diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/migration/TunnelMigrationTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/migration/TunnelMigrationTests.java new file mode 100644 index 00000000..e1e56791 --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/migration/TunnelMigrationTests.java @@ -0,0 +1,18 @@ +package dev.compactmods.machines.test.migration; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.test.TestBatches; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.gametest.PrefixGameTestTemplate; + +@PrefixGameTestTemplate(false) +@GameTestHolder(Constants.MOD_ID) +public class TunnelMigrationTests { + + @GameTest(template = "empty_1x1", batch = TestBatches.MIGRATION) + public static void canReadCM51RoomTunnelsFile(final GameTestHelper test) { + test.succeed(); + } +} diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/FakeTunnelDefinition.java b/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/FakeTunnelDefinition.java new file mode 100644 index 00000000..682434b8 --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/FakeTunnelDefinition.java @@ -0,0 +1,17 @@ +package dev.compactmods.machines.test.tunnel; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.api.tunnels.TunnelDefinition; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.FastColor; + +public class FakeTunnelDefinition implements TunnelDefinition { + + public static final ResourceKey ID = ResourceKey.create(TunnelDefinition.REGISTRY_KEY, new ResourceLocation(Constants.MOD_ID, "fake")); + + @Override + public int ringColor() { + return FastColor.ARGB32.color(255, 255, 0, 0); + } +} diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphCleanupTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphCleanupTests.java new file mode 100644 index 00000000..647efa12 --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphCleanupTests.java @@ -0,0 +1,35 @@ +package dev.compactmods.machines.test.tunnel; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; +import dev.compactmods.machines.test.TestBatches; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.GlobalPos; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.gametest.PrefixGameTestTemplate; + +import java.util.stream.Collectors; + +@PrefixGameTestTemplate(false) +@GameTestHolder(Constants.MOD_ID) +public class TunnelGraphCleanupTests { + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void canCleanupOrphanedMachines(final GameTestHelper test) { + final var graph = new TunnelConnectionGraph(); + final var MACHINE_POS = GlobalPos.of(test.getLevel().dimension(), BlockPos.ZERO); + + graph.register(BlockPos.ZERO, FakeTunnelDefinition.ID, MACHINE_POS, Direction.UP); + + graph.unregister(BlockPos.ZERO); + + final var machines = graph.machines().collect(Collectors.toSet()); + if(!machines.isEmpty()) + test.fail("Expected no machines to remain registered; got %s".formatted(machines.size())); + + test.succeed(); + } +} diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphMachineTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphMachineTests.java new file mode 100644 index 00000000..2cb41747 --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphMachineTests.java @@ -0,0 +1,74 @@ +package dev.compactmods.machines.test.tunnel; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; +import dev.compactmods.machines.tunnel.graph.traversal.TunnelMachineFilters; +import dev.compactmods.machines.test.TestBatches; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.GlobalPos; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.gametest.PrefixGameTestTemplate; + +import java.util.stream.Collectors; + +@PrefixGameTestTemplate(false) +@GameTestHolder(Constants.MOD_ID) +public class TunnelGraphMachineTests { + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void unregisteredMachineConnectionCheck(final GameTestHelper test) { + final var graph = new TunnelConnectionGraph(); + final var MACHINE_POS = GlobalPos.of(test.getLevel().dimension(), BlockPos.ZERO); + + final var connections = graph.positions(TunnelMachineFilters.all(MACHINE_POS)) + .collect(Collectors.toUnmodifiableSet()); + + if(!connections.isEmpty()) { + test.fail("There should be no connections registered."); + } + + test.succeed(); + } + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void tunnelToMachineRelationship(final GameTestHelper test) { + final var graph = new TunnelConnectionGraph(); + final var MACHINE_POS = GlobalPos.of(test.getLevel().dimension(), BlockPos.ZERO); + + graph.register(BlockPos.ZERO, FakeTunnelDefinition.ID, MACHINE_POS, Direction.UP); + + // Check connected machine + graph.machine(BlockPos.ZERO).ifPresentOrElse(mp -> { + if(!mp.equals(MACHINE_POS)) + test.fail("Connected machine position did not match."); + }, () -> { + test.fail("Expected the tunnel to be connected to a machine. It was not."); + }); + + test.succeed(); + } + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void machineToTunnelRelationship(final GameTestHelper test) { + final var graph = new TunnelConnectionGraph(); + final var MACHINE_POS = GlobalPos.of(test.getLevel().dimension(), BlockPos.ZERO); + + graph.register(BlockPos.ZERO, FakeTunnelDefinition.ID, MACHINE_POS, Direction.UP); + + final var connectedToMachine = graph.positions(TunnelMachineFilters.sided(MACHINE_POS, Direction.UP)) + .collect(Collectors.toUnmodifiableSet()); + + if(connectedToMachine.size() != 1) { + test.fail("Expected machine to have 1 connection."); + } + + if(!connectedToMachine.contains(BlockPos.ZERO)) { + test.fail("Expected machine to be connected to the tunnel."); + } + + test.succeed(); + } +} diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphSerializationTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphSerializationTests.java new file mode 100644 index 00000000..3b0720ff --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphSerializationTests.java @@ -0,0 +1,138 @@ +package dev.compactmods.machines.test.tunnel; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.forge.tunnel.Tunnels; +import dev.compactmods.machines.graph.GraphTraversalHelper; +import dev.compactmods.machines.test.TestBatches; +import dev.compactmods.machines.test.util.NbtTestUtils; +import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; +import dev.compactmods.machines.tunnel.graph.nbt.TunnelGraphNbtKeys; +import dev.compactmods.machines.tunnel.graph.nbt.TunnelGraphNbtSerializer; +import dev.compactmods.machines.tunnel.graph.node.TunnelNode; +import dev.compactmods.machines.tunnel.graph.node.TunnelTypeNode; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.GlobalPos; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.level.Level; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.gametest.PrefixGameTestTemplate; + +@PrefixGameTestTemplate(false) +@GameTestHolder(Constants.MOD_ID) +public class TunnelGraphSerializationTests { + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void canSerializeEmptyTunnelGraph(final GameTestHelper test) { + final var graph = new TunnelConnectionGraph(); + final var nbt = TunnelGraphNbtSerializer.serialize(graph); + + if(!nbt.contains(TunnelGraphNbtKeys.NODE_GROUP, Tag.TAG_COMPOUND)) { + test.fail("Expected an graph node compound in the dataset."); + return; + } + + if(!nbt.contains(TunnelGraphNbtKeys.EDGE_GROUP, Tag.TAG_COMPOUND)) { + test.fail("Expected an graph edge compound in the dataset."); + return; + } + + final var nodesNbt = nbt.getCompound(TunnelGraphNbtKeys.NODE_GROUP); + if(nodesNbt.isEmpty()) { + test.fail("Expected graph node group to be populated."); + return; + } + + final var edgesNbt = nbt.getCompound(TunnelGraphNbtKeys.EDGE_GROUP); + if(edgesNbt.isEmpty()) { + test.fail("Expected graph edge group to be populated."); + return; + } + + test.succeed(); + } + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void canSerializeSingleTunnel(final GameTestHelper test) { + final var graph = new TunnelConnectionGraph(); + + final var MACHINE_POS = GlobalPos.of(Level.OVERWORLD, BlockPos.ZERO); + graph.register(BlockPos.ZERO, Tunnels.UNKNOWN_KEY, MACHINE_POS, Direction.UP); + + final var nbt = TunnelGraphNbtSerializer.serialize(graph); + + final var nodesNbt = nbt.getCompound(TunnelGraphNbtKeys.NODE_GROUP); + final var edgesNbt = nbt.getCompound(TunnelGraphNbtKeys.EDGE_GROUP); + + if(nodesNbt.size() != 4) { + test.fail("Did not get expected number of nodes for a single tunnel registration."); + return; + } + + if(nodesNbt.getInt(TunnelGraphNbtKeys.NODE_COUNT) != 3) { + test.fail("Expected 3 nodes accounted for; got a different result."); + } + + NbtTestUtils.checkListSize(nodesNbt, TunnelGraphNbtKeys.NODE_GROUP_TUNNEL_LIST, 1); + NbtTestUtils.checkListSize(nodesNbt, TunnelGraphNbtKeys.NODE_GROUP_TUNNEL_TYPE_LIST, 1); + NbtTestUtils.checkListSize(nodesNbt, TunnelGraphNbtKeys.NODE_GROUP_MACHINE_LIST, 1); + + if(edgesNbt.size() != 3) { + test.fail("Did not get expected number of edges for a single tunnel registration."); + return; + } + + if(edgesNbt.getInt(TunnelGraphNbtKeys.EDGE_COUNT) != 2) { + test.fail("Expected 2 edges accounted for; got a different result."); + } + + NbtTestUtils.checkListSize(edgesNbt, TunnelGraphNbtKeys.EDGE_GROUP_MACHINE_LIST, 1); + NbtTestUtils.checkListSize(edgesNbt, TunnelGraphNbtKeys.NODE_GROUP_TUNNEL_LIST, 1); + + test.succeed(); + } + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void deserializeEarlyExitsEmptyTag(final GameTestHelper test) { + final var tag = new CompoundTag(); + + test.succeedIf(() -> { + final var graph = TunnelGraphNbtSerializer.fromNbt(tag); + if(graph.size() != 0) + test.fail("Expected an empty graph."); + }); + } + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void canDeserializeTunnels(final GameTestHelper test) { + final var graph = new TunnelConnectionGraph(); + + final var MACHINE_POS = GlobalPos.of(Level.OVERWORLD, BlockPos.ZERO); + graph.register(BlockPos.ZERO.above(), Tunnels.UNKNOWN_KEY, MACHINE_POS, Direction.UP); + graph.register(BlockPos.ZERO, Tunnels.UNKNOWN_KEY, MACHINE_POS, Direction.DOWN); + + final var nbt = TunnelGraphNbtSerializer.serialize(graph); + + final var newGraph = TunnelGraphNbtSerializer.fromNbt(nbt); + + long machineCount = newGraph.machines().count(); + if(machineCount != 1) { + test.fail("Expected one machine node; got %s.".formatted(machineCount)); + } + + long tunnelCount = GraphTraversalHelper.nodes(graph.graph(), TunnelNode.class).count(); + if(tunnelCount != 2) { + test.fail("Expected 2 tunnel nodes; got %s.".formatted(tunnelCount)); + } + + long tunnelTypeCount = GraphTraversalHelper.nodes(graph.graph(), TunnelTypeNode.class).count(); + if(tunnelTypeCount != 1) { + test.fail("Expected 1 tunnel type node; got %s.".formatted(tunnelTypeCount)); + } + + test.succeed(); + } +} diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphSideTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphSideTests.java new file mode 100644 index 00000000..689309a5 --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphSideTests.java @@ -0,0 +1,76 @@ +package dev.compactmods.machines.test.tunnel; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.test.TestBatches; +import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; +import dev.compactmods.machines.tunnel.graph.traversal.TunnelMachineFilters; +import dev.compactmods.machines.tunnel.graph.traversal.TunnelTypeFilters; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.GlobalPos; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.gametest.PrefixGameTestTemplate; + +import java.util.stream.Collectors; + +@PrefixGameTestTemplate(false) +@GameTestHolder(Constants.MOD_ID) +public class TunnelGraphSideTests { + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void directionalTypeLookup(final GameTestHelper test) { + final var graph = new TunnelConnectionGraph(); + final var MACHINE_POS = GlobalPos.of(test.getLevel().dimension(), BlockPos.ZERO); + + graph.register(BlockPos.ZERO, FakeTunnelDefinition.ID, MACHINE_POS, Direction.UP); + + final var typesForUp = graph.types(MACHINE_POS, Direction.UP) + .collect(Collectors.toUnmodifiableSet()); + + if(typesForUp.size() != 1) { + test.fail("Expected the machine to have one tunnel registered for UP; got %s".formatted(typesForUp.size())); + } + + if(!typesForUp.contains(FakeTunnelDefinition.ID)) { + test.fail("Expected the fake tunnel definition to be registered for UP"); + } + + // Check side of tunnel + graph.side(BlockPos.ZERO).ifPresentOrElse(side -> { + if(side != Direction.UP) + test.fail("Expected tunnel side to be UP"); + }, () -> { + test.fail("Expected tunnel side to be set."); + }); + + test.succeed(); + } + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void canLookupSidesByDefinition(final GameTestHelper test) { + final var graph = new TunnelConnectionGraph(); + final var MACHINE_POS = GlobalPos.of(test.getLevel().dimension(), BlockPos.ZERO); + + graph.register(BlockPos.ZERO, FakeTunnelDefinition.ID, MACHINE_POS, Direction.UP); + + final var sides = graph + .sides(TunnelMachineFilters.all(MACHINE_POS), TunnelTypeFilters.key(FakeTunnelDefinition.ID)) + .collect(Collectors.toSet()); + + if(sides.size() != 1) { + test.fail("Expected one side matched; got %s".formatted(sides.size())); + } + + if(!sides.contains(Direction.UP)) { + var sidesString = sides.stream() + .map(Direction::getName) + .collect(Collectors.joining(",")); + + test.fail("Expected fake tunnel side lookup to include UP; it did not. Contents: %s".formatted(sidesString)); + } + + test.succeed(); + } +} diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphTunnelTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphTunnelTests.java new file mode 100644 index 00000000..3eb41f06 --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/tunnel/TunnelGraphTunnelTests.java @@ -0,0 +1,69 @@ +package dev.compactmods.machines.test.tunnel; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.test.TestBatches; +import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.GlobalPos; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.gametest.PrefixGameTestTemplate; + +@PrefixGameTestTemplate(false) +@GameTestHolder(Constants.MOD_ID) +public class TunnelGraphTunnelTests { + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void unboundTunnelPositionReturnsNoResult(final GameTestHelper test) { + final var graph = new TunnelConnectionGraph(); + + final var connectedTo = graph.machine(BlockPos.ZERO); + if (connectedTo.isPresent()) { + test.fail("There should not be a connection."); + } + + test.succeed(); + } + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void returnsNothingForUnregisteredLocations(final GameTestHelper test) { + final var graph = new TunnelConnectionGraph(); + + graph.info(BlockPos.ZERO).ifPresent(info -> { + test.fail("Got registration info for an unregistered position: %s".formatted(info.type())); + }); + + test.succeed(); + } + + @GameTest(template = "empty_1x1", batch = TestBatches.TUNNEL_DATA) + public static void canRegisterSingleTunnel(final GameTestHelper test) { + final var graph = new TunnelConnectionGraph(); + final var MACHINE_POS = GlobalPos.of(test.getLevel().dimension(), BlockPos.ZERO); + + graph.register(BlockPos.ZERO, FakeTunnelDefinition.ID, MACHINE_POS, Direction.UP); + + if (!graph.has(BlockPos.ZERO)) + test.fail("Graph is reporting tunnel is not registered."); + + graph.info(BlockPos.ZERO).ifPresentOrElse(info -> { + if (!info.location().equals(BlockPos.ZERO)) + test.fail("Tunnel location is not correct."); + + if (!info.machine().equals(MACHINE_POS)) + test.fail("Tunnel machine is not correct."); + + if (!info.side().equals(Direction.UP)) + test.fail("Tunnel side is not correct."); + + if (!info.type().equals(FakeTunnelDefinition.ID)) + test.fail("Tunnel type is not correct."); + }, () -> { + test.fail("Tunnel was not registered correctly."); + }); + + test.succeed(); + } +} diff --git a/src/test/java/dev/compactmods/machines/test/util/FileHelper.java b/forge-main/src/test/java/dev/compactmods/machines/test/util/FileHelper.java similarity index 60% rename from src/test/java/dev/compactmods/machines/test/util/FileHelper.java rename to forge-main/src/test/java/dev/compactmods/machines/test/util/FileHelper.java index ddcdec78..cc33d82e 100644 --- a/src/test/java/dev/compactmods/machines/test/util/FileHelper.java +++ b/forge-main/src/test/java/dev/compactmods/machines/test/util/FileHelper.java @@ -1,23 +1,30 @@ package dev.compactmods.machines.test.util; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtIo; +import net.minecraft.nbt.Tag; +import org.jetbrains.annotations.Nullable; + import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.nio.file.Path; -import java.nio.file.Paths; -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtIo; public final class FileHelper { public static final FileHelper INSTANCE = new FileHelper(); - public static Path RESOURCES_DIR = Paths.get("src","test","resources"); private FileHelper() { } + @Nullable + public static Path resourcesDir() { + final var rd = System.getenv("CM5_TEST_RESOURCES"); + return rd == null ? null : Path.of(rd); + } + public InputStream getFileStream(String filename) { return getClass().getClassLoader().getResourceAsStream(filename); } @@ -44,4 +51,20 @@ public static CompoundTag getNbtFromFile(String filename) throws IOException { InputStream isr = INSTANCE.getFileStream(filename); return NbtIo.readCompressed(isr); } + + public static CompoundTag getNbtFromSavedDataFile(String filename) throws IOException { + InputStream isr = INSTANCE.getFileStream(filename); + final var nbtRoot = NbtIo.readCompressed(isr); + return nbtRoot.getCompound("data"); + } + + public static T getNbtFromSavedDataFile(String filename, Class tagClass) throws IOException { + InputStream isr = INSTANCE.getFileStream(filename); + final var nbtRoot = NbtIo.readCompressed(isr); + final var tag = nbtRoot.get("data"); + if(tagClass.isInstance(tag)) + return tagClass.cast(tag); + + return null; + } } diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/util/NbtTestUtils.java b/forge-main/src/test/java/dev/compactmods/machines/test/util/NbtTestUtils.java new file mode 100644 index 00000000..bd7f9474 --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/util/NbtTestUtils.java @@ -0,0 +1,22 @@ +package dev.compactmods.machines.test.util; + +import net.minecraft.gametest.framework.GameTestAssertException; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; + +public class NbtTestUtils { + public static boolean checkListSize(CompoundTag tag, String list, int expectedSize) { + return checkListSize(tag, list, Tag.TAG_COMPOUND, expectedSize); + } + + public static boolean checkListSize(CompoundTag tag, String list, int listType, int expectedSize) { + if(!tag.contains(list, Tag.TAG_LIST)) + return false; + + int actualSize = tag.getList(list, listType).size(); + if(actualSize != expectedSize) + throw new GameTestAssertException("Expected NBT list %s to have %s elements; got %s".formatted(list, expectedSize, actualSize)); + + return true; + } +} diff --git a/src/test/java/dev/compactmods/machines/test/util/TestUtil.java b/forge-main/src/test/java/dev/compactmods/machines/test/util/TestUtil.java similarity index 100% rename from src/test/java/dev/compactmods/machines/test/util/TestUtil.java rename to forge-main/src/test/java/dev/compactmods/machines/test/util/TestUtil.java diff --git a/src/test/java/dev/compactmods/machines/test/worldgen/DimensionTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/worldgen/DimensionTests.java similarity index 90% rename from src/test/java/dev/compactmods/machines/test/worldgen/DimensionTests.java rename to forge-main/src/test/java/dev/compactmods/machines/test/worldgen/DimensionTests.java index 6a8ff237..570a2992 100644 --- a/src/test/java/dev/compactmods/machines/test/worldgen/DimensionTests.java +++ b/forge-main/src/test/java/dev/compactmods/machines/test/worldgen/DimensionTests.java @@ -1,6 +1,6 @@ package dev.compactmods.machines.test.worldgen; -import dev.compactmods.machines.CompactMachines; +import dev.compactmods.machines.api.core.Constants; import dev.compactmods.machines.api.dimension.CompactDimension; import dev.compactmods.machines.test.TestBatches; import net.minecraft.gametest.framework.GameTest; @@ -9,7 +9,7 @@ import net.minecraftforge.gametest.PrefixGameTestTemplate; @PrefixGameTestTemplate(false) -@GameTestHolder(CompactMachines.MOD_ID) +@GameTestHolder(Constants.MOD_ID) public class DimensionTests { @GameTest(template = "empty_5x5", batch = TestBatches.DIMENSION) diff --git a/forge-main/src/test/java/dev/compactmods/machines/test/worldgen/RoomGenerationTests.java b/forge-main/src/test/java/dev/compactmods/machines/test/worldgen/RoomGenerationTests.java new file mode 100644 index 00000000..479292c3 --- /dev/null +++ b/forge-main/src/test/java/dev/compactmods/machines/test/worldgen/RoomGenerationTests.java @@ -0,0 +1,82 @@ +package dev.compactmods.machines.test.worldgen; + +import dev.compactmods.machines.api.core.Constants; +import dev.compactmods.machines.api.room.RoomTemplate; +import dev.compactmods.machines.test.TestBatches; +import dev.compactmods.machines.util.CompactStructureGenerator; +import dev.compactmods.machines.forge.wall.Walls; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.gametest.PrefixGameTestTemplate; + +@PrefixGameTestTemplate(false) +@GameTestHolder(Constants.MOD_ID) +public class RoomGenerationTests { + + @GameTest(template = "empty_15x15", batch = TestBatches.ROOM_GENERATION) + public static void checkRoomGeneratorColossal(final GameTestHelper test) { + final var roomDims = new Vec3i(13, 13, 13); + final var roomCenter = Vec3.atCenterOf(test.absolutePos(new BlockPos(7, 1, 7))); + + final var unbreakableWall = Walls.BLOCK_SOLID_WALL.get().defaultBlockState(); + CompactStructureGenerator.generateRoom(test.getLevel(), roomDims, roomCenter, unbreakableWall); + + test.setBlock(new BlockPos(7, 8, 7), Blocks.GOLD_BLOCK.defaultBlockState()); + CompactStructureGenerator.fillWithTemplate(test.getLevel(), + new ResourceLocation(Constants.MOD_ID, "template_max"), + roomDims, roomCenter); + + test.succeed(); + } + + @GameTest(template = "empty_15x15", batch = TestBatches.ROOM_GENERATION) + public static void checkRoomGeneratorNormal(final GameTestHelper test) { + final var roomDims = new Vec3i(9, 9, 9); + final var roomCenter = Vec3.atCenterOf(test.absolutePos(new BlockPos(7, 1, 7))); + + final var unbreakableWall = Walls.BLOCK_SOLID_WALL.get().defaultBlockState(); + CompactStructureGenerator.generateRoom(test.getLevel(), roomDims, roomCenter, unbreakableWall); + + test.setBlock(new BlockPos(7, 5, 7), Blocks.GOLD_BLOCK.defaultBlockState()); + CompactStructureGenerator.fillWithTemplate(test.getLevel(), + RoomTemplate.NO_TEMPLATE, + roomDims, roomCenter); + + test.succeed(); + } + + @GameTest(template = "empty_15x15", batch = TestBatches.ROOM_GENERATION) + public static void checkRoomGeneratorSmall(final GameTestHelper test) { + final var roomDims = new Vec3i(5, 5, 5); + final var roomCenter = Vec3.atCenterOf(test.absolutePos(new BlockPos(7, 1, 7))); + + final var unbreakableWall = Walls.BLOCK_SOLID_WALL.get().defaultBlockState(); + CompactStructureGenerator.generateRoom(test.getLevel(), roomDims, roomCenter, unbreakableWall); + + test.setBlock(new BlockPos(7, 4, 7), Blocks.GOLD_BLOCK.defaultBlockState()); + CompactStructureGenerator.fillWithTemplate(test.getLevel(), + RoomTemplate.NO_TEMPLATE, + roomDims, roomCenter); + + test.succeed(); + } + + @GameTest(template = "empty_15x15", batch = TestBatches.ROOM_GENERATION) + public static void checkRoomGeneratorWeirdShape(final GameTestHelper test) { + final var roomDims = new Vec3i(11, 2, 7); + final var roomCenter = Vec3.atCenterOf(test.absolutePos(new BlockPos(7, 1, 7))); + + final var unbreakableWall = Walls.BLOCK_SOLID_WALL.get().defaultBlockState(); + CompactStructureGenerator.generateRoom(test.getLevel(), roomDims, roomCenter, unbreakableWall); + + // test.setBlock(new BlockPos(7, 3, 7), Blocks.GOLD_BLOCK.defaultBlockState()); + + test.succeed(); + } +} diff --git a/src/test/resources/data/compactmachines/structures/empty_15x15.nbt b/forge-main/src/test/resources/data/compactmachines/structures/empty_15x15.nbt similarity index 100% rename from src/test/resources/data/compactmachines/structures/empty_15x15.nbt rename to forge-main/src/test/resources/data/compactmachines/structures/empty_15x15.nbt diff --git a/src/test/resources/data/compactmachines/structures/empty_15x31.nbt b/forge-main/src/test/resources/data/compactmachines/structures/empty_15x31.nbt similarity index 100% rename from src/test/resources/data/compactmachines/structures/empty_15x31.nbt rename to forge-main/src/test/resources/data/compactmachines/structures/empty_15x31.nbt diff --git a/src/test/resources/data/compactmachines/structures/empty_1x1.nbt b/forge-main/src/test/resources/data/compactmachines/structures/empty_1x1.nbt similarity index 100% rename from src/test/resources/data/compactmachines/structures/empty_1x1.nbt rename to forge-main/src/test/resources/data/compactmachines/structures/empty_1x1.nbt diff --git a/src/test/resources/data/compactmachines/structures/empty_5x5.nbt b/forge-main/src/test/resources/data/compactmachines/structures/empty_5x5.nbt similarity index 100% rename from src/test/resources/data/compactmachines/structures/empty_5x5.nbt rename to forge-main/src/test/resources/data/compactmachines/structures/empty_5x5.nbt diff --git a/src/test/resources/data/compactmachines/structures/giant.nbt b/forge-main/src/test/resources/data/compactmachines/structures/giant.nbt similarity index 100% rename from src/test/resources/data/compactmachines/structures/giant.nbt rename to forge-main/src/test/resources/data/compactmachines/structures/giant.nbt diff --git a/src/test/resources/data/compactmachines/structures/large.nbt b/forge-main/src/test/resources/data/compactmachines/structures/large.nbt similarity index 100% rename from src/test/resources/data/compactmachines/structures/large.nbt rename to forge-main/src/test/resources/data/compactmachines/structures/large.nbt diff --git a/src/test/resources/data/compactmachines/structures/maximum.nbt b/forge-main/src/test/resources/data/compactmachines/structures/maximum.nbt similarity index 100% rename from src/test/resources/data/compactmachines/structures/maximum.nbt rename to forge-main/src/test/resources/data/compactmachines/structures/maximum.nbt diff --git a/forge-main/src/test/resources/data/compactmachines/structures/mekanism/empty_1x1.nbt b/forge-main/src/test/resources/data/compactmachines/structures/mekanism/empty_1x1.nbt new file mode 100644 index 00000000..10ba26a4 Binary files /dev/null and b/forge-main/src/test/resources/data/compactmachines/structures/mekanism/empty_1x1.nbt differ diff --git a/src/test/resources/data/compactmachines/structures/normal.nbt b/forge-main/src/test/resources/data/compactmachines/structures/normal.nbt similarity index 100% rename from src/test/resources/data/compactmachines/structures/normal.nbt rename to forge-main/src/test/resources/data/compactmachines/structures/normal.nbt diff --git a/src/test/resources/data/compactmachines/structures/small.nbt b/forge-main/src/test/resources/data/compactmachines/structures/small.nbt similarity index 100% rename from src/test/resources/data/compactmachines/structures/small.nbt rename to forge-main/src/test/resources/data/compactmachines/structures/small.nbt diff --git a/forge-main/src/test/resources/data/compactmachines/structures/template_max.nbt b/forge-main/src/test/resources/data/compactmachines/structures/template_max.nbt new file mode 100644 index 00000000..eca07ef7 Binary files /dev/null and b/forge-main/src/test/resources/data/compactmachines/structures/template_max.nbt differ diff --git a/src/test/resources/data/compactmachines/structures/tiny.nbt b/forge-main/src/test/resources/data/compactmachines/structures/tiny.nbt similarity index 100% rename from src/test/resources/data/compactmachines/structures/tiny.nbt rename to forge-main/src/test/resources/data/compactmachines/structures/tiny.nbt diff --git a/src/test/resources/data/compactmachines/structures/tunneltests.solid_wall_3x3.nbt b/forge-main/src/test/resources/data/compactmachines/structures/tunneltests.solid_wall_3x3.nbt similarity index 100% rename from src/test/resources/data/compactmachines/structures/tunneltests.solid_wall_3x3.nbt rename to forge-main/src/test/resources/data/compactmachines/structures/tunneltests.solid_wall_3x3.nbt diff --git a/forge-main/src/test/resources/migrate/pre520/connections.dat b/forge-main/src/test/resources/migrate/pre520/connections.dat new file mode 100644 index 00000000..81a30fe7 Binary files /dev/null and b/forge-main/src/test/resources/migrate/pre520/connections.dat differ diff --git a/forge-main/src/test/resources/migrate/pre520/level.dat b/forge-main/src/test/resources/migrate/pre520/level.dat new file mode 100644 index 00000000..f0a8d3f6 Binary files /dev/null and b/forge-main/src/test/resources/migrate/pre520/level.dat differ diff --git a/forge-main/src/test/resources/migrate/pre520/level.dat_old b/forge-main/src/test/resources/migrate/pre520/level.dat_old new file mode 100644 index 00000000..ae8f90ab Binary files /dev/null and b/forge-main/src/test/resources/migrate/pre520/level.dat_old differ diff --git a/forge-main/src/test/resources/migrate/pre520/machines.dat b/forge-main/src/test/resources/migrate/pre520/machines.dat new file mode 100644 index 00000000..f07b56af Binary files /dev/null and b/forge-main/src/test/resources/migrate/pre520/machines.dat differ diff --git a/forge-main/src/test/resources/migrate/pre520/room_data.dat b/forge-main/src/test/resources/migrate/pre520/room_data.dat new file mode 100644 index 00000000..7d8323e9 Binary files /dev/null and b/forge-main/src/test/resources/migrate/pre520/room_data.dat differ diff --git a/forge-main/src/test/resources/migrate/pre520/single_room.dat b/forge-main/src/test/resources/migrate/pre520/single_room.dat new file mode 100644 index 00000000..2246f74d Binary files /dev/null and b/forge-main/src/test/resources/migrate/pre520/single_room.dat differ diff --git a/forge-main/src/test/resources/migrate/pre520/tunnels_-64_-64.dat b/forge-main/src/test/resources/migrate/pre520/tunnels_-64_-64.dat new file mode 100644 index 00000000..a209cebf Binary files /dev/null and b/forge-main/src/test/resources/migrate/pre520/tunnels_-64_-64.dat differ diff --git a/forge-main/src/test/resources/migrate/pre520/tunnels_0_-64.dat b/forge-main/src/test/resources/migrate/pre520/tunnels_0_-64.dat new file mode 100644 index 00000000..8763e630 Binary files /dev/null and b/forge-main/src/test/resources/migrate/pre520/tunnels_0_-64.dat differ diff --git a/src/test/resources/scenario/simple-connection/compactmachines_connections.nbt b/forge-main/src/test/resources/scenario/simple-connection/compactmachines_connections.nbt similarity index 100% rename from src/test/resources/scenario/simple-connection/compactmachines_connections.nbt rename to forge-main/src/test/resources/scenario/simple-connection/compactmachines_connections.nbt diff --git a/src/test/resources/scenario/simple-connection/compactmachines_machines.nbt b/forge-main/src/test/resources/scenario/simple-connection/compactmachines_machines.nbt similarity index 100% rename from src/test/resources/scenario/simple-connection/compactmachines_machines.nbt rename to forge-main/src/test/resources/scenario/simple-connection/compactmachines_machines.nbt diff --git a/src/test/resources/scenario/simple-connection/compactmachines_rooms.nbt b/forge-main/src/test/resources/scenario/simple-connection/compactmachines_rooms.nbt similarity index 100% rename from src/test/resources/scenario/simple-connection/compactmachines_rooms.nbt rename to forge-main/src/test/resources/scenario/simple-connection/compactmachines_rooms.nbt diff --git a/src/test/resources/scenario/single-machine-player-inside/machines_external.nbt b/forge-main/src/test/resources/scenario/single-machine-player-inside/machines_external.nbt similarity index 100% rename from src/test/resources/scenario/single-machine-player-inside/machines_external.nbt rename to forge-main/src/test/resources/scenario/single-machine-player-inside/machines_external.nbt diff --git a/src/test/resources/scenario/single-machine-player-inside/machines_internal.dat b/forge-main/src/test/resources/scenario/single-machine-player-inside/machines_internal.dat similarity index 100% rename from src/test/resources/scenario/single-machine-player-inside/machines_internal.dat rename to forge-main/src/test/resources/scenario/single-machine-player-inside/machines_internal.dat diff --git a/src/test/resources/scenario/single-machine-player-inside/players.dat b/forge-main/src/test/resources/scenario/single-machine-player-inside/players.dat similarity index 100% rename from src/test/resources/scenario/single-machine-player-inside/players.dat rename to forge-main/src/test/resources/scenario/single-machine-player-inside/players.dat diff --git a/forge-tunnels-api/.gitignore b/forge-tunnels-api/.gitignore new file mode 100644 index 00000000..5dd0b448 --- /dev/null +++ b/forge-tunnels-api/.gitignore @@ -0,0 +1,2 @@ +build/ +run/ \ No newline at end of file diff --git a/forge-tunnels-api/build.gradle.kts b/forge-tunnels-api/build.gradle.kts new file mode 100644 index 00000000..e579580f --- /dev/null +++ b/forge-tunnels-api/build.gradle.kts @@ -0,0 +1,120 @@ + +import net.minecraftforge.gradle.userdev.UserDevExtension +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 + +plugins { + id("idea") + id("eclipse") + 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)) + withSourcesJar() +} + +var minecraft_version: String by extra +var forge_version: String by extra +var parchment_version: String by extra + +sourceSets { + named("main") { + resources { + //The API has no resources + setSrcDirs(emptyList()) + } + } + + named("test") { + resources { + //The test module has no resources + setSrcDirs(emptyList()) + } + } +} + +configure { + mappings("parchment", "${parchment_version}-${minecraft_version}") + accessTransformer(file("../forge-main/src/main/resources/META-INF/accesstransformer.cfg")) +} + +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 ("net.minecraftforge", "forge", version = "${minecraft_version}-${forge_version}") + + implementation("dev.compactmods.compactmachines", "core-api", coreVersion) { + isTransitive = false + } + + implementation("dev.compactmods.compactmachines", "tunnels-api", tunnelsApiVersion) { + isTransitive = false + } +} + +tasks.withType { + manifest { + val now = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(Date()) + attributes(mapOf( + "Specification-Title" to "Compact Machines API", + "Specification-Vendor" to "", + "Specification-Version" to "1", // We are version 1 of ourselves + "Implementation-Title" to "Compact Machines API", + "Implementation-Version" to archiveVersion, + "Implementation-Vendor" to "", + "Implementation-Timestamp" to now + )) + } +} + +tasks.jar { + archiveClassifier.set("") + finalizedBy("reobfJar") +} + +tasks.named("sourcesJar") { + archiveClassifier.set("api-sources") +} + +artifacts { + archives(tasks.jar.get()) + archives(tasks.named("sourcesJar").get()) +} + +val PACKAGES_URL = System.getenv("GH_PKG_URL") ?: "https://maven.pkg.github.com/compactmods/compactmachines" +publishing { + publications.register("forge-tunnels-api") { + from(components.findByName("java")) + } + + 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-tunnels-api/src/main/java/dev/compactmods/machines/api/tunnels/capability/CapabilityLookupTunnel.java b/forge-tunnels-api/src/main/java/dev/compactmods/machines/api/tunnels/capability/CapabilityLookupTunnel.java new file mode 100644 index 00000000..a7fc881b --- /dev/null +++ b/forge-tunnels-api/src/main/java/dev/compactmods/machines/api/tunnels/capability/CapabilityLookupTunnel.java @@ -0,0 +1,17 @@ +package dev.compactmods.machines.api.tunnels.capability; + +import com.google.common.collect.ImmutableSet; +import dev.compactmods.machines.api.tunnels.TunnelPosition; +import net.minecraft.core.GlobalPos; +import net.minecraft.server.MinecraftServer; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Experimental +public interface CapabilityLookupTunnel { + + ImmutableSet> getSupportedCapabilities(); + + > LazyOptional findCapability(MinecraftServer server, TunnelPosition tunnelPosition, GlobalPos connectedPosition); +} diff --git a/src/api/java/dev/compactmods/machines/api/tunnels/capability/CapabilityTunnel.java b/forge-tunnels-api/src/main/java/dev/compactmods/machines/api/tunnels/capability/CapabilityTunnel.java similarity index 100% rename from src/api/java/dev/compactmods/machines/api/tunnels/capability/CapabilityTunnel.java rename to forge-tunnels-api/src/main/java/dev/compactmods/machines/api/tunnels/capability/CapabilityTunnel.java index c6803c31..b034cb17 100644 --- a/src/api/java/dev/compactmods/machines/api/tunnels/capability/CapabilityTunnel.java +++ b/forge-tunnels-api/src/main/java/dev/compactmods/machines/api/tunnels/capability/CapabilityTunnel.java @@ -1,8 +1,8 @@ package dev.compactmods.machines.api.tunnels.capability; import com.google.common.collect.ImmutableSet; -import dev.compactmods.machines.api.tunnels.lifecycle.TunnelInstance; import dev.compactmods.machines.api.tunnels.lifecycle.InstancedTunnel; +import dev.compactmods.machines.api.tunnels.lifecycle.TunnelInstance; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; diff --git a/gradle.properties b/gradle.properties index 59e7ce0c..f5f7ac49 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,23 +3,17 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -minecraft_version=1.19.1 -forge_version=42.0.1 -parchment_version=1.18.2-2022.07.17-1.19.1 +minecraft_version=1.19.2 +loom_version = 1.0-SNAPSHOT +forge_version=43.2.0 +parchment_version=2022.10.16 mod_id=compactmachines - -# Dependencies and Libs -jei_mc_version=1.19.1 -jei_version=11.2.0.241 -#top_version=1.16-3.1.4-22 +core_version=2.2.12 +tunnels_version=2.2.12 # Curseforge cf_project=224218 cf_release_type=release -# Plugins that shall not be named -mixin_version = 0.8.5 -mixingradle_version = 0.7-SNAPSHOT - -include_test_mods = false \ No newline at end of file +include_test_mods = true \ No newline at end of file diff --git a/gradlew.bat b/gradlew.bat old mode 100644 new mode 100755 diff --git a/raw-assets/field-projector-setup-example.png b/raw-assets/field-projector-setup-example.png deleted file mode 100644 index b0f86517..00000000 Binary files a/raw-assets/field-projector-setup-example.png and /dev/null differ diff --git a/raw-assets/personal_shrinking_device.aseprite b/raw-assets/personal_shrinking_device.aseprite deleted file mode 100644 index 1c5752f9..00000000 Binary files a/raw-assets/personal_shrinking_device.aseprite and /dev/null differ diff --git a/raw-assets/projector-texture.psd b/raw-assets/projector-texture.psd deleted file mode 100644 index a45626ac..00000000 Binary files a/raw-assets/projector-texture.psd and /dev/null differ diff --git a/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/giant_machine.json b/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/giant_machine.json deleted file mode 100644 index 2aa94e78..00000000 --- a/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/giant_machine.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "version": 1, - "recipeSize": 5, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "W" - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:mixed", - "pattern": [ - ["W", "W", "W", "W", "W"], - ["W", "-", "-", "-", "W"], - ["W", "-", "D", "-", "W"], - ["W", "-", "-", "-", "W"], - ["W", "W", "W", "W", "W"] - ] - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:filled", - "component": "W" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "W": { - "Name": "compactmachines:wall" - }, - "D": { - "Name": "minecraft:diamond_block" - } - }, - - "outputs": [ - { - "id": "compactmachines:machine_giant", - "Count": 1 - } - ] -} \ No newline at end of file diff --git a/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/large_machine.json b/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/large_machine.json deleted file mode 100644 index 8e20fa9e..00000000 --- a/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/large_machine.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "version": 1, - "recipeSize": 5, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "W" - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:filled", - "component": "W" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "W": { - "Name": "compactmachines:wall" - } - }, - - "outputs": [ - { - "id": "compactmachines:machine_large", - "Count": 1 - } - ] -} \ No newline at end of file diff --git a/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/maximum_machine.json b/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/maximum_machine.json deleted file mode 100644 index 0cf06b94..00000000 --- a/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/maximum_machine.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "version": 1, - "recipeSize": 5, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "W" - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:mixed", - "pattern": [ - ["W", "W", "W", "W", "W"], - ["W", "-", "-", "-", "W"], - ["W", "-", "E", "-", "W"], - ["W", "-", "-", "-", "W"], - ["W", "W", "W", "W", "W"] - ] - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:filled", - "component": "W" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "W": { - "Name": "compactmachines:wall" - }, - - "E": { - "Name": "minecraft:emerald_block" - } - }, - - "outputs": [ - { - "id": "compactmachines:machine_maximum", - "Count": 1 - } - ] -} \ No newline at end of file diff --git a/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/normal_machine.json b/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/normal_machine.json deleted file mode 100644 index 2f637249..00000000 --- a/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/normal_machine.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": 1, - "recipeSize": 3, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "W" - }, - { - "type": "compactcrafting:mixed", - "pattern": [ - ["W", "W", "W"], - ["W", "G", "W"], - ["W", "W", "W"] - ] - }, - { - "type": "compactcrafting:filled", - "component": "W" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "W": { - "Name": "compactmachines:wall" - }, - "G": { - "Name": "minecraft:gold_block" - } - }, - - "outputs": [ - { - "id": "compactmachines:machine_normal", - "Count": 1 - } - ] -} \ No newline at end of file diff --git a/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/small_machine.json b/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/small_machine.json deleted file mode 100644 index 60d4bce2..00000000 --- a/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/small_machine.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": 1, - "recipeSize": 3, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "W" - }, - { - "type": "compactcrafting:mixed", - "pattern": [ - ["W", "W", "W"], - ["W", "I", "W"], - ["W", "W", "W"] - ] - }, - { - "type": "compactcrafting:filled", - "component": "W" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "W": { - "Name": "compactmachines:wall" - }, - "I": { - "Name": "minecraft:iron_block" - } - }, - - "outputs": [ - { - "id": "compactmachines:machine_small", - "Count": 1 - } - ] -} \ No newline at end of file diff --git a/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/tiny_machine.json b/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/tiny_machine.json deleted file mode 100644 index d6800816..00000000 --- a/recipepacks/compact-crafting-alpha2/data/compactmachines/recipes/tiny_machine.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "version": 1, - "recipeSize": 3, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "W" - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:filled", - "component": "W" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "W": { - "Name": "compactmachines:wall" - } - }, - - "outputs": [ - { - "id": "compactmachines:machine_tiny", - "Count": 1 - } - ] -} \ No newline at end of file diff --git a/recipepacks/compact-crafting-alpha2/pack.mcmeta b/recipepacks/compact-crafting-alpha2/pack.mcmeta deleted file mode 100644 index 04b45ab6..00000000 --- a/recipepacks/compact-crafting-alpha2/pack.mcmeta +++ /dev/null @@ -1,6 +0,0 @@ -{ - "pack": { - "pack_format": 6, - "description": "Integration of Compact Machines and Compact Crafting." - } -} \ No newline at end of file diff --git a/recipepacks/compact-crafting/data/compactmachines/recipes/giant_machine.json b/recipepacks/compact-crafting/data/compactmachines/recipes/giant_machine.json deleted file mode 100644 index 4316719c..00000000 --- a/recipepacks/compact-crafting/data/compactmachines/recipes/giant_machine.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "type": "compactcrafting:miniaturization", - "recipeSize": 5, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "W" - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:mixed", - "pattern": [ - ["W", "W", "W", "W", "W"], - ["W", "-", "-", "-", "W"], - ["W", "-", "D", "-", "W"], - ["W", "-", "-", "-", "W"], - ["W", "W", "W", "W", "W"] - ] - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:filled", - "component": "W" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "W": { - "type": "compactcrafting:block", - "block": "compactmachines:wall" - }, - "D": { - "type": "compactcrafting:block", - "block": "minecraft:diamond_block" - } - }, - - "outputs": [ - { - "id": "compactmachines:machine_giant", - "Count": 1 - } - ] -} \ No newline at end of file diff --git a/recipepacks/compact-crafting/data/compactmachines/recipes/large_machine.json b/recipepacks/compact-crafting/data/compactmachines/recipes/large_machine.json deleted file mode 100644 index c1aab734..00000000 --- a/recipepacks/compact-crafting/data/compactmachines/recipes/large_machine.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "type": "compactcrafting:miniaturization", - "recipeSize": 5, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "W" - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:filled", - "component": "W" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "W": { - "type": "compactcrafting:block", - "block": "compactmachines:wall" - } - }, - - "outputs": [ - { - "id": "compactmachines:machine_large", - "Count": 1 - } - ] -} \ No newline at end of file diff --git a/recipepacks/compact-crafting/data/compactmachines/recipes/maximum_machine.json b/recipepacks/compact-crafting/data/compactmachines/recipes/maximum_machine.json deleted file mode 100644 index 83bf0f9b..00000000 --- a/recipepacks/compact-crafting/data/compactmachines/recipes/maximum_machine.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "type": "compactcrafting:miniaturization", - "recipeSize": 5, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "W" - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:mixed", - "pattern": [ - ["W", "W", "W", "W", "W"], - ["W", "-", "-", "-", "W"], - ["W", "-", "E", "-", "W"], - ["W", "-", "-", "-", "W"], - ["W", "W", "W", "W", "W"] - ] - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:filled", - "component": "W" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "W": { - "type": "compactcrafting:block", - "block": "compactmachines:wall" - }, - - "E": { - "type": "compactcrafting:block", - "block": "minecraft:emerald_block" - } - }, - - "outputs": [ - { - "id": "compactmachines:machine_maximum", - "Count": 1 - } - ] -} \ No newline at end of file diff --git a/recipepacks/compact-crafting/data/compactmachines/recipes/normal_machine.json b/recipepacks/compact-crafting/data/compactmachines/recipes/normal_machine.json deleted file mode 100644 index d6d397ea..00000000 --- a/recipepacks/compact-crafting/data/compactmachines/recipes/normal_machine.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "type": "compactcrafting:miniaturization", - "recipeSize": 3, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "W" - }, - { - "type": "compactcrafting:mixed", - "pattern": [ - ["W", "W", "W"], - ["W", "G", "W"], - ["W", "W", "W"] - ] - }, - { - "type": "compactcrafting:filled", - "component": "W" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "W": { - "type": "compactcrafting:block", - "block": "compactmachines:wall" - }, - "G": { - "type": "compactcrafting:block", - "block": "minecraft:gold_block" - } - }, - - "outputs": [ - { - "id": "compactmachines:machine_normal", - "Count": 1 - } - ] -} \ No newline at end of file diff --git a/recipepacks/compact-crafting/data/compactmachines/recipes/small_machine.json b/recipepacks/compact-crafting/data/compactmachines/recipes/small_machine.json deleted file mode 100644 index 05c7accc..00000000 --- a/recipepacks/compact-crafting/data/compactmachines/recipes/small_machine.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "type": "compactcrafting:miniaturization", - "recipeSize": 3, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "W" - }, - { - "type": "compactcrafting:mixed", - "pattern": [ - ["W", "W", "W"], - ["W", "I", "W"], - ["W", "W", "W"] - ] - }, - { - "type": "compactcrafting:filled", - "component": "W" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "W": { - "type": "compactcrafting:block", - "block": "compactmachines:wall" - }, - "I": { - "type": "compactcrafting:block", - "block": "minecraft:iron_block" - } - }, - - "outputs": [ - { - "id": "compactmachines:machine_small", - "Count": 1 - } - ] -} \ No newline at end of file diff --git a/recipepacks/compact-crafting/data/compactmachines/recipes/tiny_machine.json b/recipepacks/compact-crafting/data/compactmachines/recipes/tiny_machine.json deleted file mode 100644 index d38c1fbb..00000000 --- a/recipepacks/compact-crafting/data/compactmachines/recipes/tiny_machine.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "type": "compactcrafting:miniaturization", - "recipeSize": 3, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "W" - }, - { - "type": "compactcrafting:hollow", - "wall": "W" - }, - { - "type": "compactcrafting:filled", - "component": "W" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "W": { - "type": "compactcrafting:block", - "block": "compactmachines:wall" - } - }, - - "outputs": [ - { - "id": "compactmachines:machine_tiny", - "Count": 1 - } - ] -} \ No newline at end of file diff --git a/recipepacks/compact-crafting/data/compactmachines/recipes/wall.json b/recipepacks/compact-crafting/data/compactmachines/recipes/wall.json deleted file mode 100644 index 7c3bc21e..00000000 --- a/recipepacks/compact-crafting/data/compactmachines/recipes/wall.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "type": "compactcrafting:miniaturization", - "recipeSize": 1, - "layers": [ - { - "type": "compactcrafting:filled", - "component": "R" - }, - { - "type": "compactcrafting:filled", - "component": "I" - } - ], - - "catalyst": { - "id": "minecraft:ender_pearl", - "Count": 1 - }, - - "components": { - "R": { - "type": "compactcrafting:block", - "block": "minecraft:redstone_wire" - }, - "I": { - "type": "compactcrafting:block", - "block": "minecraft:iron_block" - } - }, - - "outputs": [ - { - "id": "compactmachines:wall", - "Count": 16 - } - ] - } \ No newline at end of file diff --git a/recipepacks/compact-crafting/pack.mcmeta b/recipepacks/compact-crafting/pack.mcmeta deleted file mode 100644 index 04b45ab6..00000000 --- a/recipepacks/compact-crafting/pack.mcmeta +++ /dev/null @@ -1,6 +0,0 @@ -{ - "pack": { - "pack_format": 6, - "description": "Integration of Compact Machines and Compact Crafting." - } -} \ No newline at end of file diff --git a/recipepacks/vanilla/data/compactmachines/recipes/giant_machine.json b/recipepacks/vanilla/data/compactmachines/recipes/giant_machine.json deleted file mode 100644 index 149cf0ba..00000000 --- a/recipepacks/vanilla/data/compactmachines/recipes/giant_machine.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "result": { - "item": "compactmachines:machine_giant", - "count": 1 - }, - "pattern": [ - "www", - "wdw", - "www" - ], - "key": { - "w": { - "item": "compactmachines:wall" - }, - "d": { - "item": "minecraft:diamond_block" - } - } -} \ No newline at end of file diff --git a/recipepacks/vanilla/data/compactmachines/recipes/large_machine.json b/recipepacks/vanilla/data/compactmachines/recipes/large_machine.json deleted file mode 100644 index ff8602f5..00000000 --- a/recipepacks/vanilla/data/compactmachines/recipes/large_machine.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "result": { - "item": "compactmachines:machine_large", - "count": 1 - }, - "pattern": [ - "www", - "wow", - "www" - ], - "key": { - "w": { - "item": "compactmachines:wall" - }, - "o": { - "item": "minecraft:obsidian" - } - } -} \ No newline at end of file diff --git a/recipepacks/vanilla/data/compactmachines/recipes/machine_wall.json b/recipepacks/vanilla/data/compactmachines/recipes/machine_wall.json deleted file mode 100644 index 5103a05f..00000000 --- a/recipepacks/vanilla/data/compactmachines/recipes/machine_wall.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "result": { - "item": "compactmachines:wall", - "count": 16 - }, - "pattern": [ - " ", - " r ", - " i " - ], - "key": { - "r": { - "item": "minecraft:redstone" - }, - "i": { - "item": "minecraft:iron_block" - } - } -} \ No newline at end of file diff --git a/recipepacks/vanilla/data/compactmachines/recipes/maximum_machine.json b/recipepacks/vanilla/data/compactmachines/recipes/maximum_machine.json deleted file mode 100644 index 2f9d2daa..00000000 --- a/recipepacks/vanilla/data/compactmachines/recipes/maximum_machine.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "result": { - "item": "compactmachines:machine_maximum", - "count": 1 - }, - "pattern": [ - "www", - "wew", - "www" - ], - "key": { - "w": { - "item": "compactmachines:wall" - }, - "e": { - "item": "minecraft:emerald_block" - } - } -} \ No newline at end of file diff --git a/recipepacks/vanilla/data/compactmachines/recipes/normal_machine.json b/recipepacks/vanilla/data/compactmachines/recipes/normal_machine.json deleted file mode 100644 index cc4471b2..00000000 --- a/recipepacks/vanilla/data/compactmachines/recipes/normal_machine.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "result": { - "item": "compactmachines:machine_normal", - "count": 1 - }, - "pattern": [ - "www", - "wgw", - "www" - ], - "key": { - "w": { - "item": "compactmachines:wall" - }, - "g": { - "item": "minecraft:gold_block" - } - } -} \ No newline at end of file diff --git a/recipepacks/vanilla/data/compactmachines/recipes/small_machine.json b/recipepacks/vanilla/data/compactmachines/recipes/small_machine.json deleted file mode 100644 index 2835b2da..00000000 --- a/recipepacks/vanilla/data/compactmachines/recipes/small_machine.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "result": { - "item": "compactmachines:machine_small", - "count": 1 - }, - "pattern": [ - "www", - "wiw", - "www" - ], - "key": { - "w": { - "item": "compactmachines:wall" - }, - "i": { - "item": "minecraft:iron_block" - } - } -} \ No newline at end of file diff --git a/recipepacks/vanilla/data/compactmachines/recipes/tiny_machine.json b/recipepacks/vanilla/data/compactmachines/recipes/tiny_machine.json deleted file mode 100644 index f30ace4c..00000000 --- a/recipepacks/vanilla/data/compactmachines/recipes/tiny_machine.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "result": { - "item": "compactmachines:machine_tiny", - "count": 1 - }, - "pattern": [ - "www", - "wpw", - "www" - ], - "key": { - "w": { - "item": "compactmachines:wall" - }, - "p": { - "tag": "minecraft:planks" - } - } -} \ No newline at end of file diff --git a/recipepacks/vanilla/pack.mcmeta b/recipepacks/vanilla/pack.mcmeta deleted file mode 100644 index 2b78c1d0..00000000 --- a/recipepacks/vanilla/pack.mcmeta +++ /dev/null @@ -1,6 +0,0 @@ -{ - "pack": { - "pack_format": 6, - "description": "Provides recipes for vanilla Compact Machines integration." - } -} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 69c30d59..00000000 --- a/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = "Compact Machines" \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000..3318b49e --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,27 @@ +pluginManagement { + repositories { + mavenCentral() + mavenLocal() + maven("https://maven.minecraftforge.net") { + name = "Minecraft Forge" + } + + maven("https://maven.parchmentmc.org") { + name = "ParchmentMC" + } + } + + resolutionStrategy { + eachPlugin { + if (requested.id.id == "net.minecraftforge.gradle") { + useModule("${requested.id}:ForgeGradle:${requested.version}") + } + } + } +} + +rootProject.name = "Compact Machines" +include("forge-tunnels-api") +include("forge-main") +include("forge-builtin") +include("forge-datagen") diff --git a/src/api/java/dev/compactmods/machines/api/codec/CodecExtensions.java b/src/api/java/dev/compactmods/machines/api/codec/CodecExtensions.java deleted file mode 100644 index 10fea87f..00000000 --- a/src/api/java/dev/compactmods/machines/api/codec/CodecExtensions.java +++ /dev/null @@ -1,31 +0,0 @@ -package dev.compactmods.machines.api.codec; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; -import net.minecraft.Util; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.phys.Vec3; - -import java.util.UUID; -import java.util.stream.DoubleStream; -import java.util.stream.IntStream; - -public abstract class CodecExtensions { - public static final Codec UUID_CODEC = Codec.STRING - .comapFlatMap((s) -> { - try { - return DataResult.success(UUID.fromString(s)); - } catch (Exception ex) { - return DataResult.error("Not a valid UUID: " + s + " (" + ex.getMessage() + ")"); - } - }, UUID::toString).stable(); - - public static final Codec VECTOR3D = DoubleStreamExtensions.CODEC - .comapFlatMap(i -> DoubleStreamExtensions.fixedDoubleSize(i, 3) - .map(out -> new Vec3(out[0], out[1], out[2])), vec -> DoubleStream.of(vec.x, vec.y, vec.z)); - - public static final Codec CHUNKPOS = Codec.INT_STREAM - .comapFlatMap(i -> Util.fixedSize(i, 2) - .map(arr -> new ChunkPos(arr[0], arr[1])), pos -> IntStream.of(pos.x, pos.z)); - -} diff --git a/src/api/java/dev/compactmods/machines/api/codec/DoubleStreamExtensions.java b/src/api/java/dev/compactmods/machines/api/codec/DoubleStreamExtensions.java deleted file mode 100644 index c00465cb..00000000 --- a/src/api/java/dev/compactmods/machines/api/codec/DoubleStreamExtensions.java +++ /dev/null @@ -1,50 +0,0 @@ -package dev.compactmods.machines.api.codec; - -import com.mojang.serialization.DataResult; -import com.mojang.serialization.DynamicOps; -import com.mojang.serialization.codecs.PrimitiveCodec; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.DoubleStream; - -public class DoubleStreamExtensions { - - public static final PrimitiveCodec CODEC = new PrimitiveCodec() { - @Override - public DataResult read(final DynamicOps ops, final T input) { - return getDoubleStream(ops, input); - } - - @Override - public T write(final DynamicOps ops, final DoubleStream value) { - return ops.createList(value.mapToObj(ops::createDouble)); - } - - @Override - public String toString() { - return "DoubleStream"; - } - }; - - public static DataResult fixedDoubleSize(DoubleStream stream, int limit) { - double[] limited = stream.limit(limit + 1).toArray(); - if (limited.length != limit) { - String s = "Input is not a list of " + limit + " doubles"; - return limited.length >= limit ? DataResult.error(s, Arrays.copyOf(limited, limit)) : DataResult.error(s); - } else { - return DataResult.success(limited); - } - } - - public static DataResult getDoubleStream(final DynamicOps ops, final T input) { - return ops.getStream(input).flatMap(stream -> { - final List list = stream.collect(Collectors.toList()); - if (list.stream().allMatch(element -> ops.getNumberValue(element).result().isPresent())) { - return DataResult.success(list.stream().mapToDouble(element -> ops.getNumberValue(element).result().get().doubleValue())); - } - return DataResult.error("Some elements are not doubles: " + input); - }); - } -} diff --git a/src/api/java/dev/compactmods/machines/api/codec/NbtListCollector.java b/src/api/java/dev/compactmods/machines/api/codec/NbtListCollector.java deleted file mode 100644 index 078a40b6..00000000 --- a/src/api/java/dev/compactmods/machines/api/codec/NbtListCollector.java +++ /dev/null @@ -1,54 +0,0 @@ -package dev.compactmods.machines.api.codec; - -import com.google.common.collect.ImmutableSet; -import net.minecraft.nbt.Tag; -import net.minecraft.nbt.ListTag; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collector; - -public class NbtListCollector implements Collector, ListTag> { - - @Override - public Supplier> supplier() { - return ArrayList::new; - } - - @Override - public BiConsumer, Tag> accumulator() { - return List::add; - } - - @Override - public BinaryOperator> combiner() { - return (res1, res2) -> { - res1.addAll(res2); - return res1; - }; - } - - @Override - public Function, ListTag> finisher() { - return (items) -> { - ListTag list = new ListTag(); - list.addAll(items); - return list; - }; - } - - @Override - public Set characteristics() { - return ImmutableSet.of(Collector.Characteristics.CONCURRENT, - Collector.Characteristics.UNORDERED); - } - - public static NbtListCollector toNbtList() { - return new NbtListCollector(); - } -} diff --git a/src/api/java/dev/compactmods/machines/api/core/Advancements.java b/src/api/java/dev/compactmods/machines/api/core/Advancements.java deleted file mode 100644 index 3adc0cf1..00000000 --- a/src/api/java/dev/compactmods/machines/api/core/Advancements.java +++ /dev/null @@ -1,20 +0,0 @@ -package dev.compactmods.machines.api.core; - -import net.minecraft.resources.ResourceLocation; - -public abstract class Advancements { - public static final ResourceLocation HOW_DID_YOU_GET_HERE = new ResourceLocation(Constants.MOD_ID, "how_did_you_get_here"); - public static final ResourceLocation ROOT = new ResourceLocation(Constants.MOD_ID, "root"); - public static final ResourceLocation FOUNDATIONS = new ResourceLocation(Constants.MOD_ID, "foundations"); - - public static final ResourceLocation GOT_SHRINKING_DEVICE = new ResourceLocation(Constants.MOD_ID, "got_shrinking_device"); - - public static final ResourceLocation CLAIMED_TINY_MACHINE = new ResourceLocation(Constants.MOD_ID, "claimed_machine_tiny"); - public static final ResourceLocation CLAIMED_SMALL_MACHINE = new ResourceLocation(Constants.MOD_ID, "claimed_machine_small"); - public static final ResourceLocation CLAIMED_NORMAL_MACHINE = new ResourceLocation(Constants.MOD_ID, "claimed_machine_normal"); - public static final ResourceLocation CLAIMED_LARGE_MACHINE = new ResourceLocation(Constants.MOD_ID, "claimed_machine_large"); - public static final ResourceLocation CLAIMED_GIANT_MACHINE = new ResourceLocation(Constants.MOD_ID, "claimed_machine_giant"); - public static final ResourceLocation CLAIMED_MAX_MACHINE = new ResourceLocation(Constants.MOD_ID, "claimed_machine_max"); - - public static final ResourceLocation RECURSIVE_ROOMS = new ResourceLocation(Constants.MOD_ID, "recursion"); -} diff --git a/src/api/java/dev/compactmods/machines/api/core/CMCommands.java b/src/api/java/dev/compactmods/machines/api/core/CMCommands.java deleted file mode 100644 index 3f365a38..00000000 --- a/src/api/java/dev/compactmods/machines/api/core/CMCommands.java +++ /dev/null @@ -1,38 +0,0 @@ -package dev.compactmods.machines.api.core; - -import net.minecraft.resources.ResourceLocation; - -import static dev.compactmods.machines.api.core.Constants.MOD_ID; - -public abstract class CMCommands { - public static final ResourceLocation LEVEL_REGISTERED = new ResourceLocation(MOD_ID, "level_registered"); - public static final ResourceLocation LEVEL_NOT_FOUND = new ResourceLocation(MOD_ID, "level_not_found"); - - public static final ResourceLocation ROOM_NOT_FOUND = new ResourceLocation(MOD_ID, "room_not_found"); - - /** - * Used for displaying the number of registered machines via summary commands. - */ - public static final ResourceLocation MACHINE_REG_DIM = new ResourceLocation(MOD_ID, "summary.machines.dimension"); - public static final ResourceLocation MACHINE_REG_TOTAL = new ResourceLocation(MOD_ID, "summary.machines.total"); - - /** - * Used for displaying the number of registered rooms via summary commands. - */ - public static final ResourceLocation ROOM_REG_COUNT = new ResourceLocation(MOD_ID, "room_reg_count"); - public static final ResourceLocation NOT_A_MACHINE_BLOCK = new ResourceLocation(MOD_ID, "not_a_machine_block"); - - /** - * Shows a machine is not bound. Takes in a single param, the machine position in world. - */ - public static final ResourceLocation MACHINE_NOT_BOUND = new ResourceLocation(MOD_ID, "machine_not_bound"); - - public static final ResourceLocation WRONG_DIMENSION = new ResourceLocation(MOD_ID, "not_in_compact_dimension"); - public static final ResourceLocation NOT_IN_COMPACT_DIMENSION = new ResourceLocation(MOD_ID, "not_in_compact_dim"); - public static final ResourceLocation FAILED_CMD_FILE_ERROR = new ResourceLocation(MOD_ID, "failed_command_file_error"); - - public static final ResourceLocation CANNOT_GIVE_MACHINE = new ResourceLocation(MOD_ID, "cannot_give_machine_item"); - public static final ResourceLocation MACHINE_GIVEN = new ResourceLocation(MOD_ID, "machine_given_successfully"); - public static final ResourceLocation NO_REBIND_TUNNEL_PRESENT = new ResourceLocation(MOD_ID, "cannot_rebind_tunnel_present"); - public static final ResourceLocation SPAWN_CHANGED_SUCCESSFULLY = new ResourceLocation(MOD_ID, "spawn_changed_successfully"); -} diff --git a/src/api/java/dev/compactmods/machines/api/core/CMTags.java b/src/api/java/dev/compactmods/machines/api/core/CMTags.java deleted file mode 100644 index 95800750..00000000 --- a/src/api/java/dev/compactmods/machines/api/core/CMTags.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.compactmods.machines.api.core; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.ItemTags; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; - -public abstract class CMTags { - - public static final TagKey ROOM_UPGRADE_ITEM = ItemTags.create(new ResourceLocation(Constants.MOD_ID, "room_upgrade")); -} diff --git a/src/api/java/dev/compactmods/machines/api/core/Constants.java b/src/api/java/dev/compactmods/machines/api/core/Constants.java deleted file mode 100644 index 19bf6647..00000000 --- a/src/api/java/dev/compactmods/machines/api/core/Constants.java +++ /dev/null @@ -1,6 +0,0 @@ -package dev.compactmods.machines.api.core; - -public abstract class Constants { - public static final String MOD_ID = "compactmachines"; - -} diff --git a/src/api/java/dev/compactmods/machines/api/core/JeiInfo.java b/src/api/java/dev/compactmods/machines/api/core/JeiInfo.java deleted file mode 100644 index b2032f33..00000000 --- a/src/api/java/dev/compactmods/machines/api/core/JeiInfo.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.compactmods.machines.api.core; - -import net.minecraft.resources.ResourceLocation; - -public abstract class JeiInfo { - public static final ResourceLocation MACHINE = new ResourceLocation(Constants.MOD_ID, "machines"); - - public static final ResourceLocation SHRINKING_DEVICE = new ResourceLocation(Constants.MOD_ID, "shrinking_device"); -} diff --git a/src/api/java/dev/compactmods/machines/api/core/Messages.java b/src/api/java/dev/compactmods/machines/api/core/Messages.java deleted file mode 100644 index c6d74540..00000000 --- a/src/api/java/dev/compactmods/machines/api/core/Messages.java +++ /dev/null @@ -1,42 +0,0 @@ -package dev.compactmods.machines.api.core; - -import net.minecraft.resources.ResourceLocation; - -public abstract class Messages { - public static final ResourceLocation CANNOT_ENTER_MACHINE = new ResourceLocation(Constants.MOD_ID, "cannot_enter"); - public static final ResourceLocation NO_MACHINE_DATA = new ResourceLocation(Constants.MOD_ID, "no_machine_data"); - public static final ResourceLocation ROOM_SPAWNPOINT_SET = new ResourceLocation(Constants.MOD_ID, "spawnpoint_set"); - public static final ResourceLocation TELEPORT_OUT_OF_BOUNDS = new ResourceLocation(Constants.MOD_ID, "teleport_oob"); - public static final ResourceLocation HOW_DID_YOU_GET_HERE = new ResourceLocation(Constants.MOD_ID, "how_did_you_get_here"); - public static final ResourceLocation UNKNOWN_TUNNEL = new ResourceLocation(Constants.MOD_ID, "unknown_tunnel_type"); - public static final ResourceLocation NO_TUNNEL_SIDE = new ResourceLocation(Constants.MOD_ID, "no_available_sides"); - public static final ResourceLocation UNKNOWN_ROOM_CHUNK = new ResourceLocation(Constants.MOD_ID, "unknown_room_chunk"); - public static final ResourceLocation UNREGISTERED_CM_DIM = new ResourceLocation(Constants.MOD_ID, "dimension_not_registered"); - public static final ResourceLocation NEW_MACHINE = new ResourceLocation(Constants.MOD_ID, "new_machine"); - - /** - * Used to show information about a player inside a Compact room. - */ - public static final ResourceLocation PLAYER_ROOM_INFO = new ResourceLocation(Constants.MOD_ID, "player_room_info"); - - /** - * Used to show information about a room, accessed via a bound machine. - */ - public static final ResourceLocation MACHINE_ROOM_INFO = new ResourceLocation(Constants.MOD_ID, "machine_room_info"); - - /** - * Shown when a non-owner tries to rename a room. Takes the owner's display name. - */ - public static final ResourceLocation CANNOT_RENAME_NOT_OWNER = new ResourceLocation(Constants.MOD_ID, "cannot_rename_not_owner"); - - /** - * Shown to players when they try to interact with a room they do not own. Provides the owner's display name. - */ - public static final ResourceLocation NOT_ROOM_OWNER = new ResourceLocation(Constants.MOD_ID, "not_the_room_owner"); - public static final ResourceLocation UPGRADE_APPLIED = new ResourceLocation(Constants.MOD_ID, "upgrade_applied"); - public static final ResourceLocation UPGRADE_ADD_FAILED = new ResourceLocation(Constants.MOD_ID, "upgrade_add_failed"); - public static final ResourceLocation UPGRADE_REMOVED = new ResourceLocation(Constants.MOD_ID, "upgrade_removed"); - public static final ResourceLocation UPGRADE_REM_FAILED = new ResourceLocation(Constants.MOD_ID, "upgrade_remove_failed"); - public static final ResourceLocation ALREADY_HAS_UPGRADE = new ResourceLocation(Constants.MOD_ID, "upgrade_already_present"); - public static final ResourceLocation UPGRADE_NOT_PRESENT = new ResourceLocation(Constants.MOD_ID, "upgrade_not_present"); -} diff --git a/src/api/java/dev/compactmods/machines/api/core/Tooltips.java b/src/api/java/dev/compactmods/machines/api/core/Tooltips.java deleted file mode 100644 index b18233c6..00000000 --- a/src/api/java/dev/compactmods/machines/api/core/Tooltips.java +++ /dev/null @@ -1,29 +0,0 @@ -package dev.compactmods.machines.api.core; - -import net.minecraft.resources.ResourceLocation; - -public abstract class Tooltips { - - public static final ResourceLocation UNKNOWN_PLAYER_NAME = new ResourceLocation(Constants.MOD_ID, "unknown_player"); - public static final ResourceLocation TUNNEL_TYPE = new ResourceLocation(Constants.MOD_ID, "tunnel_type"); - public static final ResourceLocation UNKNOWN_TUNNEL_TYPE = new ResourceLocation(Constants.MOD_ID, "unknown_tunnel_type"); - public static final ResourceLocation ROOM_NAME = new ResourceLocation(Constants.MOD_ID, "room_name"); - public static final ResourceLocation ROOM_UPGRADE_TYPE = new ResourceLocation(Constants.MOD_ID, "room_upgrade_type"); - public static final ResourceLocation TUTORIAL_APPLY_ROOM_UPGRADE = new ResourceLocation(Constants.MOD_ID, "tutorial_apply_room_upgrade"); - - public static abstract class Machines { - public static final ResourceLocation ID = new ResourceLocation(Constants.MOD_ID, "machine.id"); - public static final ResourceLocation OWNER = new ResourceLocation(Constants.MOD_ID, "machine.owner"); - public static final ResourceLocation SIZE = new ResourceLocation(Constants.MOD_ID, "machine.size"); - public static final ResourceLocation BOUND_TO = new ResourceLocation(Constants.MOD_ID, "machine.bound_to"); - } - - //#region Hints and Details - public static final ResourceLocation HINT_HOLD_SHIFT = new ResourceLocation(Constants.MOD_ID, "hint.hold_shift"); - - public static abstract class Details { - public static final ResourceLocation PERSONAL_SHRINKING_DEVICE = new ResourceLocation(Constants.MOD_ID, "details.psd"); - public static final ResourceLocation SOLID_WALL = new ResourceLocation(Constants.MOD_ID, "details.solid_wall"); - } - //#endregion -} diff --git a/src/api/java/dev/compactmods/machines/api/dimension/CompactDimension.java b/src/api/java/dev/compactmods/machines/api/dimension/CompactDimension.java deleted file mode 100644 index a29f6eea..00000000 --- a/src/api/java/dev/compactmods/machines/api/dimension/CompactDimension.java +++ /dev/null @@ -1,19 +0,0 @@ -package dev.compactmods.machines.api.dimension; - -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.dimension.DimensionType; - -import static dev.compactmods.machines.api.core.Constants.MOD_ID; - -public abstract class CompactDimension { - public static final ResourceKey LEVEL_KEY = ResourceKey - .create(Registry.DIMENSION_REGISTRY, new ResourceLocation(MOD_ID, "compact_world")); - - public static final ResourceKey DIM_TYPE_KEY = ResourceKey - .create(Registry.DIMENSION_TYPE_REGISTRY, new ResourceLocation(MOD_ID, "compact_world")); - - private CompactDimension() {} -} diff --git a/src/api/java/dev/compactmods/machines/api/location/IDimensionalBlockPosition.java b/src/api/java/dev/compactmods/machines/api/location/IDimensionalBlockPosition.java deleted file mode 100644 index a8a94436..00000000 --- a/src/api/java/dev/compactmods/machines/api/location/IDimensionalBlockPosition.java +++ /dev/null @@ -1,8 +0,0 @@ -package dev.compactmods.machines.api.location; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.level.block.state.BlockState; - -public interface IDimensionalBlockPosition extends IDimensionalPosition { - BlockState state(MinecraftServer server); -} diff --git a/src/api/java/dev/compactmods/machines/api/location/IDimensionalPosition.java b/src/api/java/dev/compactmods/machines/api/location/IDimensionalPosition.java deleted file mode 100644 index db7b4e3c..00000000 --- a/src/api/java/dev/compactmods/machines/api/location/IDimensionalPosition.java +++ /dev/null @@ -1,25 +0,0 @@ -package dev.compactmods.machines.api.location; - -import java.util.Optional; - -import com.mojang.serialization.Codec; -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.Vec3; - -public interface IDimensionalPosition { - - BlockPos getBlockPosition(); - Vec3 getExactPosition(); - - ResourceKey dimensionKey(); - ServerLevel level(MinecraftServer server); - - IDimensionalPosition relative(Direction direction); - - Optional getRotation(); -} diff --git a/src/api/java/dev/compactmods/machines/api/machine/MachineNbt.java b/src/api/java/dev/compactmods/machines/api/machine/MachineNbt.java deleted file mode 100644 index c33d8eb6..00000000 --- a/src/api/java/dev/compactmods/machines/api/machine/MachineNbt.java +++ /dev/null @@ -1,6 +0,0 @@ -package dev.compactmods.machines.api.machine; - -public abstract class MachineNbt { - public static final String OWNER = "owner"; - public final static String ID = "machine_id"; -} diff --git a/src/api/java/dev/compactmods/machines/api/room/IRoomHistory.java b/src/api/java/dev/compactmods/machines/api/room/IRoomHistory.java deleted file mode 100644 index efaf6f73..00000000 --- a/src/api/java/dev/compactmods/machines/api/room/IRoomHistory.java +++ /dev/null @@ -1,15 +0,0 @@ -package dev.compactmods.machines.api.room; - -import dev.compactmods.machines.api.room.history.IRoomHistoryItem; -import net.minecraft.nbt.ListTag; -import net.minecraftforge.common.util.INBTSerializable; - -public interface IRoomHistory extends INBTSerializable { - - void clear(); - boolean hasHistory(); - T peek(); - T pop(); - - void addHistory(T item); -} diff --git a/src/api/java/dev/compactmods/machines/api/room/RoomSize.java b/src/api/java/dev/compactmods/machines/api/room/RoomSize.java deleted file mode 100644 index 3d2366d0..00000000 --- a/src/api/java/dev/compactmods/machines/api/room/RoomSize.java +++ /dev/null @@ -1,60 +0,0 @@ -package dev.compactmods.machines.api.room; - -import com.mojang.serialization.Codec; -import net.minecraft.util.StringRepresentable; -import net.minecraft.world.phys.AABB; -import net.minecraft.core.BlockPos; - -public enum RoomSize implements StringRepresentable { - TINY ("tiny", 3), - SMALL ("small", 5), - NORMAL ("normal", 7), - LARGE ("large", 9), - GIANT ("giant", 11), - MAXIMUM ("maximum", 13); - - private final String name; - private final int internalSize; - - public static final Codec CODEC = StringRepresentable.fromEnum(RoomSize::values); - - RoomSize(String name, int internalSize) { - this.name = name; - this.internalSize = internalSize; - } - - public static RoomSize maximum() { - return MAXIMUM; - } - - public String getName() { - return this.name; - } - - public AABB getBounds(BlockPos center) { - AABB bounds = new AABB(center); - return bounds.inflate(Math.floorDiv(internalSize, 2)); - } - - public int getInternalSize() { - return this.internalSize; - } - - public static RoomSize getFromSize(String size) { - switch (size.toLowerCase()) { - case "tiny": return TINY; - case "small": return SMALL; - case "normal": return NORMAL; - case "large": return LARGE; - case "giant": return GIANT; - case "maximum": return MAXIMUM; - } - - return TINY; - } - - @Override - public String getSerializedName() { - return this.name; - } -} diff --git a/src/api/java/dev/compactmods/machines/api/room/history/IRoomHistoryItem.java b/src/api/java/dev/compactmods/machines/api/room/history/IRoomHistoryItem.java deleted file mode 100644 index 57b536ae..00000000 --- a/src/api/java/dev/compactmods/machines/api/room/history/IRoomHistoryItem.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.compactmods.machines.api.room.history; - -import dev.compactmods.machines.api.location.IDimensionalBlockPosition; -import dev.compactmods.machines.api.location.IDimensionalPosition; - -public interface IRoomHistoryItem { - - IDimensionalPosition getEntryLocation(); - - IDimensionalBlockPosition getMachine(); -} diff --git a/src/api/java/dev/compactmods/machines/api/room/upgrade/ILevelLoadedUpgradeListener.java b/src/api/java/dev/compactmods/machines/api/room/upgrade/ILevelLoadedUpgradeListener.java deleted file mode 100644 index ded9f8b6..00000000 --- a/src/api/java/dev/compactmods/machines/api/room/upgrade/ILevelLoadedUpgradeListener.java +++ /dev/null @@ -1,18 +0,0 @@ -package dev.compactmods.machines.api.room.upgrade; - -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.ChunkPos; - -public interface ILevelLoadedUpgradeListener extends RoomUpgrade { - - /** - * Called when a level is loaded, typically when the server first boots up. - */ - default void onLevelLoaded(ServerLevel level, ChunkPos room) {} - - /** - * Called when a level is unloaded. - */ - default void onLevelUnloaded(ServerLevel level, ChunkPos room) {} - -} diff --git a/src/api/java/dev/compactmods/machines/api/room/upgrade/RoomUpgrade.java b/src/api/java/dev/compactmods/machines/api/room/upgrade/RoomUpgrade.java deleted file mode 100644 index 1180fa5e..00000000 --- a/src/api/java/dev/compactmods/machines/api/room/upgrade/RoomUpgrade.java +++ /dev/null @@ -1,35 +0,0 @@ -package dev.compactmods.machines.api.room.upgrade; - -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.ChunkPos; - -import static dev.compactmods.machines.api.core.Constants.MOD_ID; - -public interface RoomUpgrade { - - ResourceKey> REG_KEY = ResourceKey.createRegistryKey(new ResourceLocation(MOD_ID, "room_upgrade")); - - String UNNAMED_TRANS_KEY = "item." + MOD_ID + ".upgrades.unnamed"; - - default String getTranslationKey() { - return UNNAMED_TRANS_KEY; - } - - default String getTranslationKey(ItemStack stack) { - return getTranslationKey(); - } - - /** - * Called when an upgrade is first applied to a room. - */ - default void onAdded(ServerLevel level, ChunkPos room) {} - - /** - * Called when an update is removed from a room. - */ - default void onRemoved(ServerLevel level, ChunkPos room) {} -} diff --git a/src/api/java/dev/compactmods/machines/api/room/upgrade/RoomUpgradeInstance.java b/src/api/java/dev/compactmods/machines/api/room/upgrade/RoomUpgradeInstance.java deleted file mode 100644 index cad3bcca..00000000 --- a/src/api/java/dev/compactmods/machines/api/room/upgrade/RoomUpgradeInstance.java +++ /dev/null @@ -1,6 +0,0 @@ -package dev.compactmods.machines.api.room.upgrade; - -import net.minecraft.world.level.ChunkPos; - -public record RoomUpgradeInstance(T upgrade, ChunkPos room) { -} diff --git a/src/api/java/dev/compactmods/machines/api/tunnels/TunnelDefinition.java b/src/api/java/dev/compactmods/machines/api/tunnels/TunnelDefinition.java deleted file mode 100644 index 06acee32..00000000 --- a/src/api/java/dev/compactmods/machines/api/tunnels/TunnelDefinition.java +++ /dev/null @@ -1,42 +0,0 @@ -package dev.compactmods.machines.api.tunnels; - -import dev.compactmods.machines.api.core.Constants; -import net.minecraft.resources.ResourceLocation; - -public interface TunnelDefinition { - /** - * The color of a non-indicator (the same color as the wall) - */ - int NO_INDICATOR_COLOR = 3751749; - - /** - * Constant value used to indicate that a tunnel is receiving a resource from - * outside a machine room. - */ - int IMPORT_COLOR = 0xff2462cd; - - /** - * Constant value used to indicate that a tunnel is pushing a resource out of - * a machine room. - */ - int EXPORT_COLOR = 0xffe6a709; - ResourceLocation TUNNEL_ID = new ResourceLocation(Constants.MOD_ID, "tunnel"); - - /** - * The central ring color of the tunnel. Shown in the tunnel item and on blocks. - * - * @return An AARRGGBB-formatted integer indicating color. - */ - int ringColor(); - - /** - * Gets the color for the indicator at the top-right of the block texture. - * For import- and export-style tunnels, see {@link #IMPORT_COLOR} and {@link #EXPORT_COLOR}. - * - * @return An AARRGGBB-formatted integer indicating color. - */ - default int indicatorColor() { - return NO_INDICATOR_COLOR; - } - -} diff --git a/src/api/java/dev/compactmods/machines/api/tunnels/TunnelPosition.java b/src/api/java/dev/compactmods/machines/api/tunnels/TunnelPosition.java deleted file mode 100644 index 55164c52..00000000 --- a/src/api/java/dev/compactmods/machines/api/tunnels/TunnelPosition.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.compactmods.machines.api.tunnels; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; - -import javax.annotation.Nullable; - -public record TunnelPosition(@Nullable ServerLevel level, BlockPos pos, Direction side) { - -} diff --git a/src/api/java/dev/compactmods/machines/api/tunnels/lifecycle/InstancedTunnel.java b/src/api/java/dev/compactmods/machines/api/tunnels/lifecycle/InstancedTunnel.java deleted file mode 100644 index c6e6c45b..00000000 --- a/src/api/java/dev/compactmods/machines/api/tunnels/lifecycle/InstancedTunnel.java +++ /dev/null @@ -1,15 +0,0 @@ -package dev.compactmods.machines.api.tunnels.lifecycle; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; - -public interface InstancedTunnel { - - /** - * Handle initialization tasks for the tunnel's data here. - * - * @param position The location of the new tunnel being created. - * @param side The side of the wall the tunnel is being added to. - */ - T newInstance(BlockPos position, Direction side); -} diff --git a/src/api/java/dev/compactmods/machines/api/tunnels/lifecycle/TunnelInstance.java b/src/api/java/dev/compactmods/machines/api/tunnels/lifecycle/TunnelInstance.java deleted file mode 100644 index a7c9d1a3..00000000 --- a/src/api/java/dev/compactmods/machines/api/tunnels/lifecycle/TunnelInstance.java +++ /dev/null @@ -1,7 +0,0 @@ -package dev.compactmods.machines.api.tunnels.lifecycle; - -/** - * Marker interface for signaling that the class is a tunnel instance. - */ -public interface TunnelInstance { -} diff --git a/src/api/java/dev/compactmods/machines/api/tunnels/lifecycle/TunnelTeardownHandler.java b/src/api/java/dev/compactmods/machines/api/tunnels/lifecycle/TunnelTeardownHandler.java deleted file mode 100644 index 40d56f81..00000000 --- a/src/api/java/dev/compactmods/machines/api/tunnels/lifecycle/TunnelTeardownHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -package dev.compactmods.machines.api.tunnels.lifecycle; - -import dev.compactmods.machines.api.tunnels.TunnelPosition; -import net.minecraft.core.Direction; - -/** - * Indicates that a tunnel has teardown tasks that are performed whenever a tunnel - * is removed from a machine room's wall, or rotated in-place. - */ -public interface TunnelTeardownHandler extends InstancedTunnel { - - /** - * Handle tasks when a tunnel is being rotated on a machine room wall. - * - * @param instance The tunnel instance being rotated. - * @param oldSide The previous side of the machine the tunnel was connected to. - * @param newSide The upcoming side of the machine the tunnel will connect to. - */ - default void onRotated(TunnelPosition position, Instance instance, Direction oldSide, Direction newSide) { - } - - /** - * Handle tasks when a tunnel is fully removed from a machine room wall. - * - * @param instance The tunnel instance being removed. - */ - default void onRemoved(TunnelPosition position, Instance instance) { - } -} diff --git a/src/api/java/dev/compactmods/machines/api/tunnels/recipe/TunnelRecipeBuilder.java b/src/api/java/dev/compactmods/machines/api/tunnels/recipe/TunnelRecipeBuilder.java deleted file mode 100644 index 30939171..00000000 --- a/src/api/java/dev/compactmods/machines/api/tunnels/recipe/TunnelRecipeBuilder.java +++ /dev/null @@ -1,160 +0,0 @@ -package dev.compactmods.machines.api.tunnels.recipe; - -import com.google.common.collect.Lists; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import net.minecraft.advancements.Advancement; -import net.minecraft.advancements.AdvancementRewards; -import net.minecraft.advancements.CriterionTriggerInstance; -import net.minecraft.advancements.RequirementsStrategy; -import net.minecraft.advancements.critereon.RecipeUnlockedTrigger; -import net.minecraft.data.recipes.FinishedRecipe; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.level.ItemLike; -import net.minecraftforge.registries.RegistryObject; - -import javax.annotation.Nullable; -import java.util.List; -import java.util.function.Consumer; - -public class TunnelRecipeBuilder { - - private final List ingredients = Lists.newArrayList(); - private final Advancement.Builder advancement = Advancement.Builder.advancement(); - private String group; - private int count; - private ResourceLocation tunnelType; - - private TunnelRecipeBuilder(RegistryObject definition, int count) { - this.tunnelType = definition.getId(); - this.count = count; - } - - public static TunnelRecipeBuilder tunnel(RegistryObject definition) { - return new TunnelRecipeBuilder(definition, 1); - } - - public static TunnelRecipeBuilder tunnel(RegistryObject definition, int count) { - return new TunnelRecipeBuilder(definition, count); - } - - public TunnelRecipeBuilder setType(ResourceLocation id) { - this.tunnelType = id; - return this; - } - - public TunnelRecipeBuilder requires(ItemLike item) { - return this.requires(Ingredient.of(item)); - } - - public TunnelRecipeBuilder requires(Ingredient ingredient) { - this.ingredients.add(ingredient); - return this; - } - - public TunnelRecipeBuilder unlockedBy(String criterionName, CriterionTriggerInstance crit) { - this.advancement.addCriterion(criterionName, crit); - return this; - } - - public TunnelRecipeBuilder group(String groupName) { - this.group = groupName; - return this; - } - - public void save(Consumer consumer) { - this.ensureValid(tunnelType); - this.advancement - .parent(new ResourceLocation("recipes/root")) - .addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(TunnelRecipeHelper.getRecipeId(tunnelType))) - .rewards(AdvancementRewards.Builder.recipe(tunnelType)) - .requirements(RequirementsStrategy.OR); - - consumer.accept(new TunnelRecipeBuilder.Result( - this.tunnelType, - this.count, - this.group == null ? "" : this.group, this.ingredients, - this.advancement, - new ResourceLocation(tunnelType.getNamespace(), "recipes/" + tunnelType.getPath()) - )); - } - - private void ensureValid(ResourceLocation recipeId) { - if (this.advancement.getCriteria().isEmpty()) { - throw new IllegalStateException("No way of obtaining recipe " + recipeId); - } - } - - public static class Result implements FinishedRecipe { - private final ResourceLocation tunnelType; - private final int count; - private final String group; - private final List ingredients; - private final Advancement.Builder advancement; - private final ResourceLocation advancementId; - - public Result(ResourceLocation tunnelType, int count, String group, List ingredients, Advancement.Builder adv, ResourceLocation advId) { - this.tunnelType = tunnelType; - this.count = count; - this.group = group; - this.ingredients = ingredients; - this.advancement = adv; - this.advancementId = advId; - } - - @Override - public void serializeRecipeData(JsonObject output) { - if (!this.group.isEmpty()) { - output.addProperty("group", this.group); - } - - JsonArray jsonarray = new JsonArray(); - - for(Ingredient ingredient : this.ingredients) { - jsonarray.add(ingredient.toJson()); - } - - output.add("ingredients", jsonarray); - - JsonObject result = new JsonObject(); - result.addProperty("item", TunnelDefinition.TUNNEL_ID.toString()); - if (this.count > 1) { - result.addProperty("count", this.count); - } - - JsonObject definition = new JsonObject(); - definition.addProperty("id", this.tunnelType.toString()); - JsonObject nbt = new JsonObject(); - nbt.add("definition", definition); - - result.add("nbt", nbt); - - output.add("result", result); - } - - @Override - public ResourceLocation getId() { - return TunnelRecipeHelper.getRecipeId(tunnelType); - } - - @Override - public RecipeSerializer getType() { - return RecipeSerializer.SHAPELESS_RECIPE; - } - - @Nullable - @Override - public JsonObject serializeAdvancement() { - return this.advancement.serializeToJson(); - } - - @Nullable - @Override - public ResourceLocation getAdvancementId() { - return this.advancementId; - } - } -} \ No newline at end of file diff --git a/src/api/java/dev/compactmods/machines/api/tunnels/recipe/TunnelRecipeHelper.java b/src/api/java/dev/compactmods/machines/api/tunnels/recipe/TunnelRecipeHelper.java deleted file mode 100644 index ff79a287..00000000 --- a/src/api/java/dev/compactmods/machines/api/tunnels/recipe/TunnelRecipeHelper.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.compactmods.machines.api.tunnels.recipe; - -import net.minecraft.resources.ResourceLocation; - -import javax.annotation.Nonnull; - -public abstract class TunnelRecipeHelper { - public static ResourceLocation getRecipeId(@Nonnull ResourceLocation tunnelType) { - return new ResourceLocation(tunnelType.getNamespace(), "tunnels/" + tunnelType.getPath()); - } -} \ No newline at end of file diff --git a/src/api/java/dev/compactmods/machines/api/tunnels/redstone/IRedstoneTunnel.java b/src/api/java/dev/compactmods/machines/api/tunnels/redstone/IRedstoneTunnel.java deleted file mode 100644 index bfd4a713..00000000 --- a/src/api/java/dev/compactmods/machines/api/tunnels/redstone/IRedstoneTunnel.java +++ /dev/null @@ -1,4 +0,0 @@ -package dev.compactmods.machines.api.tunnels.redstone; - -public interface IRedstoneTunnel { -} diff --git a/src/api/java/dev/compactmods/machines/api/upgrade/RoomUpgradeHelper.java b/src/api/java/dev/compactmods/machines/api/upgrade/RoomUpgradeHelper.java deleted file mode 100644 index c76115f0..00000000 --- a/src/api/java/dev/compactmods/machines/api/upgrade/RoomUpgradeHelper.java +++ /dev/null @@ -1,25 +0,0 @@ -package dev.compactmods.machines.api.upgrade; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.NotNull; - -import java.util.Optional; - -public abstract class RoomUpgradeHelper { - - public static final String NBT_UPGRADE_NODE = "upgrade_info"; - public static final String NBT_UPGRADE_ID = "key"; - - public static Optional getTypeFrom(@NotNull ItemStack stack) { - if(!stack.hasTag()) return Optional.empty(); - final var tag = stack.getTag(); - if(!tag.contains(NBT_UPGRADE_NODE)) return Optional.empty(); - - final var upg = tag.getCompound(NBT_UPGRADE_NODE); - if(!upg.contains(NBT_UPGRADE_ID)) return Optional.empty(); - - final var upg2 = new ResourceLocation(upg.getString(NBT_UPGRADE_ID)); - return Optional.of(upg2); - } -} diff --git a/src/datagen/java/dev/compactmods/machines/datagen/DataGeneration.java b/src/datagen/java/dev/compactmods/machines/datagen/DataGeneration.java deleted file mode 100644 index 5b01302f..00000000 --- a/src/datagen/java/dev/compactmods/machines/datagen/DataGeneration.java +++ /dev/null @@ -1,38 +0,0 @@ -package dev.compactmods.machines.datagen; - -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.datagen.lang.EnglishLangGenerator; -import dev.compactmods.machines.datagen.lang.RussianLangGenerator; -import dev.compactmods.machines.datagen.tags.BlockTagGenerator; -import dev.compactmods.machines.datagen.tags.ItemTagGenerator; -import net.minecraftforge.data.event.GatherDataEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; - -@Mod.EventBusSubscriber(modid = CompactMachines.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 - generator.addProvider(event.includeServer(), new LevelBiomeGenerator(generator)); - generator.addProvider(event.includeServer(), new BlockLootGenerator(generator)); - generator.addProvider(event.includeServer(), new RecipeGenerator(generator)); - generator.addProvider(event.includeServer(), new AdvancementGenerator(generator)); - - final var blocks = new BlockTagGenerator(generator, helper); - generator.addProvider(event.includeServer(), blocks); - generator.addProvider(event.includeServer(), new ItemTagGenerator(generator, blocks, helper)); - - // Client - generator.addProvider(event.includeClient(), new StateGenerator(generator, helper)); - generator.addProvider(event.includeClient(), new TunnelWallStateGenerator(generator, helper)); - generator.addProvider(event.includeClient(), new ItemModelGenerator(generator, helper)); - - generator.addProvider(event.includeClient(), new EnglishLangGenerator(generator)); - generator.addProvider(event.includeClient(), new RussianLangGenerator(generator)); - } -} diff --git a/src/datagen/java/dev/compactmods/machines/datagen/RecipeGenerator.java b/src/datagen/java/dev/compactmods/machines/datagen/RecipeGenerator.java deleted file mode 100644 index 1baa86c5..00000000 --- a/src/datagen/java/dev/compactmods/machines/datagen/RecipeGenerator.java +++ /dev/null @@ -1,109 +0,0 @@ -package dev.compactmods.machines.datagen; - -import dev.compactmods.machines.api.tunnels.recipe.TunnelRecipeBuilder; -import dev.compactmods.machines.config.EnableVanillaRecipesConfigCondition; -import dev.compactmods.machines.machine.Machines; -import dev.compactmods.machines.shrinking.Shrinking; -import dev.compactmods.machines.tunnel.Tunnels; -import dev.compactmods.machines.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.tags.TagKey; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.level.ItemLike; -import net.minecraftforge.common.Tags; -import net.minecraftforge.common.crafting.ConditionalRecipe; -import net.minecraftforge.registries.ForgeRegistries; -import org.jetbrains.annotations.NotNull; - -import java.util.Objects; -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", RecipeProvider.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", RecipeProvider.has(Items.ENDER_EYE)) - .save(consumer); - - TunnelRecipeBuilder.tunnel(Tunnels.ITEM_TUNNEL_DEF, 2) - .requires(Ingredient.of(Tags.Items.CHESTS)) - .requires(Items.ENDER_PEARL) - .requires(Items.REDSTONE) - .requires(Items.OBSERVER) - .unlockedBy("observer", RecipeProvider.has(Items.OBSERVER)) - .save(consumer); - - TunnelRecipeBuilder.tunnel(Tunnels.FLUID_TUNNEL_DEF, 2) - .requires(Items.BUCKET) - .requires(Items.ENDER_PEARL) - .requires(Items.REDSTONE) - .requires(Items.OBSERVER) - .unlockedBy("observer", RecipeProvider.has(Items.OBSERVER)) - .save(consumer); - - TunnelRecipeBuilder.tunnel(Tunnels.FORGE_ENERGY, 2) - .requires(Items.GLOWSTONE_DUST) - .requires(Items.ENDER_PEARL) - .requires(Items.REDSTONE) - .requires(Items.OBSERVER) - .unlockedBy("observer", RecipeProvider.has(Items.OBSERVER)) - .save(consumer); - - addMachineRecipes(consumer); - } - - private void addMachineRecipes(Consumer consumer) { - registerMachineRecipe(consumer, Machines.MACHINE_BLOCK_ITEM_TINY.get(), Tags.Items.STORAGE_BLOCKS_COPPER); - registerMachineRecipe(consumer, Machines.MACHINE_BLOCK_ITEM_SMALL.get(), Tags.Items.STORAGE_BLOCKS_IRON); - registerMachineRecipe(consumer, Machines.MACHINE_BLOCK_ITEM_NORMAL.get(), Tags.Items.STORAGE_BLOCKS_GOLD); - registerMachineRecipe(consumer, Machines.MACHINE_BLOCK_ITEM_GIANT.get(), Tags.Items.STORAGE_BLOCKS_DIAMOND); - registerMachineRecipe(consumer, Machines.MACHINE_BLOCK_ITEM_LARGE.get(), Tags.Items.OBSIDIAN); - registerMachineRecipe(consumer, Machines.MACHINE_BLOCK_ITEM_MAXIMUM.get(), Tags.Items.STORAGE_BLOCKS_NETHERITE); - } - - protected void registerMachineRecipe(Consumer consumer, ItemLike out, TagKey center) { - Item wall = Walls.ITEM_BREAKABLE_WALL.get(); - ShapedRecipeBuilder recipe = ShapedRecipeBuilder.shaped(out) - .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", RecipeProvider.has(wall)); - - ConditionalRecipe.builder() - .addCondition(new EnableVanillaRecipesConfigCondition()) - .addRecipe(recipe::save) - .build(consumer, Objects.requireNonNull(ForgeRegistries.ITEMS.getKey(out.asItem()))); - } -} diff --git a/src/datagen/java/dev/compactmods/machines/datagen/StateGenerator.java b/src/datagen/java/dev/compactmods/machines/datagen/StateGenerator.java deleted file mode 100644 index 29f13e02..00000000 --- a/src/datagen/java/dev/compactmods/machines/datagen/StateGenerator.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.compactmods.machines.datagen; - -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.machine.CompactMachineBlock; -import dev.compactmods.machines.api.room.RoomSize; -import dev.compactmods.machines.wall.Walls; -import net.minecraft.data.DataGenerator; -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, CompactMachines.MOD_ID, exFileHelper); - } - - @Override - protected void registerStatesAndModels() { - // Wall block model - var wall = models().cubeAll("block/wall", modLoc("block/wall")); - simpleBlock(Walls.BLOCK_SOLID_WALL.get(), wall); - simpleBlock(Walls.BLOCK_BREAKABLE_WALL.get(), wall); - - // Machine models - for(RoomSize size : RoomSize.values()) { - String sizeName = size.getName(); - - var mod = models() - .cubeAll("block/machine/machine_" + sizeName, modLoc("block/machine/machine_" + sizeName)); - - simpleBlock(CompactMachineBlock.getBySize(size), ConfiguredModel.builder() - .modelFile(mod) - .build()); - } - } -} diff --git a/src/datagen/java/dev/compactmods/machines/datagen/tags/BlockTagGenerator.java b/src/datagen/java/dev/compactmods/machines/datagen/tags/BlockTagGenerator.java deleted file mode 100644 index e620783a..00000000 --- a/src/datagen/java/dev/compactmods/machines/datagen/tags/BlockTagGenerator.java +++ /dev/null @@ -1,39 +0,0 @@ -package dev.compactmods.machines.datagen.tags; - -import java.util.Set; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.machine.Machines; -import dev.compactmods.machines.wall.Walls; -import net.minecraft.data.DataGenerator; -import net.minecraft.data.tags.BlockTagsProvider; -import net.minecraft.tags.BlockTags; -import net.minecraftforge.common.data.ExistingFileHelper; - -public class BlockTagGenerator extends BlockTagsProvider { - - public BlockTagGenerator(DataGenerator generator, ExistingFileHelper files) { - super(generator, CompactMachines.MOD_ID, files); - } - - @Override - public void addTags() { - var machines = 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 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); - - machines.forEach(mach -> { - pickaxe.add(mach); - ironTool.add(mach); - }); - } -} diff --git a/src/datagen/java/dev/compactmods/machines/datagen/tags/ItemTagGenerator.java b/src/datagen/java/dev/compactmods/machines/datagen/tags/ItemTagGenerator.java deleted file mode 100644 index d9ecdf37..00000000 --- a/src/datagen/java/dev/compactmods/machines/datagen/tags/ItemTagGenerator.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.compactmods.machines.datagen.tags; - -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.core.CMTags; -import dev.compactmods.machines.upgrade.MachineRoomUpgrades; -import net.minecraft.data.DataGenerator; -import net.minecraft.data.tags.BlockTagsProvider; -import net.minecraft.data.tags.ItemTagsProvider; -import net.minecraftforge.common.data.ExistingFileHelper; -import org.jetbrains.annotations.Nullable; - -public class ItemTagGenerator extends ItemTagsProvider { - public ItemTagGenerator(DataGenerator gen, BlockTagsProvider blockTags, @Nullable ExistingFileHelper files) { - super(gen, blockTags, CompactMachines.MOD_ID, files); - } - - @Override - protected void addTags() { - var upgradeTag = tag(CMTags.ROOM_UPGRADE_ITEM); - - upgradeTag.add(MachineRoomUpgrades.CHUNKLOADER.get()); - } -} diff --git a/src/main/java/dev/compactmods/machines/CompactMachines.java b/src/main/java/dev/compactmods/machines/CompactMachines.java deleted file mode 100644 index 7ff5f395..00000000 --- a/src/main/java/dev/compactmods/machines/CompactMachines.java +++ /dev/null @@ -1,96 +0,0 @@ -package dev.compactmods.machines; - -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.command.Commands; -import dev.compactmods.machines.config.CommonConfig; -import dev.compactmods.machines.config.EnableVanillaRecipesConfigCondition; -import dev.compactmods.machines.config.ServerConfig; -import dev.compactmods.machines.core.Registries; -import dev.compactmods.machines.core.UIRegistration; -import dev.compactmods.machines.dimension.Dimension; -import dev.compactmods.machines.graph.Graph; -import dev.compactmods.machines.machine.Machines; -import dev.compactmods.machines.room.data.LootFunctions; -import dev.compactmods.machines.shrinking.Shrinking; -import dev.compactmods.machines.tunnel.Tunnels; -import dev.compactmods.machines.upgrade.MachineRoomUpgrades; -import dev.compactmods.machines.wall.Walls; -import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.crafting.CraftingHelper; -import net.minecraftforge.fml.ModLoadingContext; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.config.ModConfig; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -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 javax.annotation.Nonnull; - -@Mod(Constants.MOD_ID) -public class CompactMachines { - /** - * @deprecated Switch usages to use api Constants in 1.20, eliminate it here - */ - @Deprecated(forRemoval = true) - public static final String MOD_ID = Constants.MOD_ID; - - public static final Logger LOGGER = LogManager.getLogger(); - public static final Marker CONN_MARKER = MarkerManager.getMarker("cm_connections"); - - public static final CreativeModeTab COMPACT_MACHINES_ITEMS = new CreativeModeTab(MOD_ID) { - @Override - public @Nonnull - ItemStack makeIcon() { - return new ItemStack(Machines.MACHINE_BLOCK_ITEM_NORMAL.get()); - } - }; - - public CompactMachines() { - Registries.setup(); - preparePackages(); - doRegistration(); - - // Configuration - ModLoadingContext mlCtx = ModLoadingContext.get(); - mlCtx.registerConfig(ModConfig.Type.COMMON, CommonConfig.CONFIG); - mlCtx.registerConfig(ModConfig.Type.SERVER, ServerConfig.CONFIG); - - CraftingHelper.register(EnableVanillaRecipesConfigCondition.Serializer.INSTANCE); - } - - /** - * 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.UPGRADES.register(bus); - Registries.NODE_TYPES.register(bus); - Registries.EDGE_TYPES.register(bus); - Registries.COMMAND_ARGUMENT_TYPES.register(bus); - Registries.LOOT_FUNCS.register(bus); - } - - private static void preparePackages() { - // Package initialization here, this kickstarts the rest of the DR code (classloading) - Machines.prepare(); - Walls.prepare(); - Tunnels.prepare(); - Shrinking.prepare(); - - UIRegistration.prepare(); - Dimension.prepare(); - MachineRoomUpgrades.prepare(); - Graph.prepare(); - Commands.prepare(); - LootFunctions.prepare(); - } -} diff --git a/src/main/java/dev/compactmods/machines/advancement/AdvancementTriggers.java b/src/main/java/dev/compactmods/machines/advancement/AdvancementTriggers.java deleted file mode 100644 index 1384fa36..00000000 --- a/src/main/java/dev/compactmods/machines/advancement/AdvancementTriggers.java +++ /dev/null @@ -1,39 +0,0 @@ -package dev.compactmods.machines.advancement; - -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.room.RoomSize; -import net.minecraft.advancements.CriteriaTriggers; - -public class AdvancementTriggers { - - public static final BasicPlayerAdvTrigger RECURSIVE_ROOMS = CriteriaTriggers.register(new BasicPlayerAdvTrigger(Advancements.RECURSIVE_ROOMS)); - - public static final HowDidYouGetHereTrigger HOW_DID_YOU_GET_HERE = CriteriaTriggers.register(new HowDidYouGetHereTrigger()); - - public static final BasicPlayerAdvTrigger CLAIMED_TINY = CriteriaTriggers.register(new BasicPlayerAdvTrigger(Advancements.CLAIMED_TINY_MACHINE)); - public static final BasicPlayerAdvTrigger CLAIMED_SMALL = CriteriaTriggers.register(new BasicPlayerAdvTrigger(Advancements.CLAIMED_SMALL_MACHINE)); - public static final BasicPlayerAdvTrigger CLAIMED_NORMAL = CriteriaTriggers.register(new BasicPlayerAdvTrigger(Advancements.CLAIMED_NORMAL_MACHINE)); - public static final BasicPlayerAdvTrigger CLAIMED_LARGE = CriteriaTriggers.register(new BasicPlayerAdvTrigger(Advancements.CLAIMED_LARGE_MACHINE)); - public static final BasicPlayerAdvTrigger CLAIMED_GIANT = CriteriaTriggers.register(new BasicPlayerAdvTrigger(Advancements.CLAIMED_GIANT_MACHINE)); - public static final BasicPlayerAdvTrigger CLAIMED_MAX = CriteriaTriggers.register(new BasicPlayerAdvTrigger(Advancements.CLAIMED_MAX_MACHINE)); - - public static void init() { - CompactMachines.LOGGER.trace("Registering advancement triggers."); - } - - public static BasicPlayerAdvTrigger getTriggerForMachineClaim(RoomSize machineSize) { - switch (machineSize) { - case TINY: return CLAIMED_TINY; - case SMALL: return CLAIMED_SMALL; - case NORMAL: return CLAIMED_NORMAL; - case LARGE: return CLAIMED_LARGE; - case GIANT: return CLAIMED_GIANT; - case MAXIMUM: return CLAIMED_MAX; - } - - return CLAIMED_TINY; - } -} diff --git a/src/main/java/dev/compactmods/machines/advancement/GenericAdvancementTriggerListener.java b/src/main/java/dev/compactmods/machines/advancement/GenericAdvancementTriggerListener.java deleted file mode 100644 index c36b04a5..00000000 --- a/src/main/java/dev/compactmods/machines/advancement/GenericAdvancementTriggerListener.java +++ /dev/null @@ -1,33 +0,0 @@ -package dev.compactmods.machines.advancement; - -import java.util.Set; -import com.google.common.collect.Sets; -import net.minecraft.advancements.CriterionTriggerInstance; -import net.minecraft.advancements.CriterionTrigger; -import net.minecraft.server.PlayerAdvancements; - -public class GenericAdvancementTriggerListener { - - private final PlayerAdvancements advancements; - private final Set> listeners = Sets.newHashSet(); - - public GenericAdvancementTriggerListener(PlayerAdvancements advancements) { - this.advancements = advancements; - } - - public void add(CriterionTrigger.Listener listener) { - listeners.add(listener); - } - - public void remove(CriterionTrigger.Listener listener) { - listeners.remove(listener); - } - - public boolean empty() { - return listeners.isEmpty(); - } - - public void trigger() { - listeners.forEach(a -> a.run(advancements)); - } -} diff --git a/src/main/java/dev/compactmods/machines/advancement/GenericAdvancementTriggerListenerList.java b/src/main/java/dev/compactmods/machines/advancement/GenericAdvancementTriggerListenerList.java deleted file mode 100644 index d66abdc7..00000000 --- a/src/main/java/dev/compactmods/machines/advancement/GenericAdvancementTriggerListenerList.java +++ /dev/null @@ -1,38 +0,0 @@ -package dev.compactmods.machines.advancement; - -import javax.annotation.Nullable; -import java.util.Map; -import com.google.common.collect.Maps; -import net.minecraft.advancements.CriterionTriggerInstance; -import net.minecraft.advancements.CriterionTrigger; -import net.minecraft.server.PlayerAdvancements; -import net.minecraft.server.level.ServerPlayer; - -public class GenericAdvancementTriggerListenerList { - private final Map> listeners = Maps.newHashMap(); - - - public void addPlayerListener(PlayerAdvancements advancements, CriterionTrigger.Listener listener) { - GenericAdvancementTriggerListener listeners = this.listeners.computeIfAbsent(advancements, GenericAdvancementTriggerListener::new); - listeners.add(listener); - } - - public void removePlayerListener(PlayerAdvancements advancements, CriterionTrigger.Listener listener) { - GenericAdvancementTriggerListener listeners = this.listeners.get(advancements); - if (listeners != null) { - listeners.remove(listener); - if (listeners.empty()) { - this.listeners.remove(advancements); - } - } - } - - public void removePlayerListeners(PlayerAdvancements advancements) { - this.listeners.remove(advancements); - } - - @Nullable - public GenericAdvancementTriggerListener getListeners(ServerPlayer player) { - return listeners.get(player.getAdvancements()); - } -} diff --git a/src/main/java/dev/compactmods/machines/advancement/trigger/BaseAdvancementTrigger.java b/src/main/java/dev/compactmods/machines/advancement/trigger/BaseAdvancementTrigger.java deleted file mode 100644 index b0e51063..00000000 --- a/src/main/java/dev/compactmods/machines/advancement/trigger/BaseAdvancementTrigger.java +++ /dev/null @@ -1,33 +0,0 @@ -package dev.compactmods.machines.advancement.trigger; - -import dev.compactmods.machines.advancement.GenericAdvancementTriggerListenerList; -import net.minecraft.advancements.CriterionTrigger; -import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance; -import net.minecraft.server.PlayerAdvancements; -import net.minecraft.server.level.ServerPlayer; - -public abstract class BaseAdvancementTrigger implements CriterionTrigger { - - private final GenericAdvancementTriggerListenerList listeners = new GenericAdvancementTriggerListenerList<>(); - - @Override - public void addPlayerListener(PlayerAdvancements advancements, Listener list) { - listeners.addPlayerListener(advancements, list); - } - - @Override - public void removePlayerListener(PlayerAdvancements advancements, Listener list) { - listeners.removePlayerListener(advancements, list); - } - - @Override - public void removePlayerListeners(PlayerAdvancements advancements) { - listeners.removePlayerListeners(advancements); - } - - public void trigger(ServerPlayer player) { - final var listeners = this.listeners.getListeners(player); - if(listeners != null) - listeners.trigger(); - } -} diff --git a/src/main/java/dev/compactmods/machines/advancement/trigger/BasicPlayerAdvTrigger.java b/src/main/java/dev/compactmods/machines/advancement/trigger/BasicPlayerAdvTrigger.java deleted file mode 100644 index 34a8ef2b..00000000 --- a/src/main/java/dev/compactmods/machines/advancement/trigger/BasicPlayerAdvTrigger.java +++ /dev/null @@ -1,37 +0,0 @@ -package dev.compactmods.machines.advancement.trigger; - -import com.google.gson.JsonObject; -import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance; -import net.minecraft.advancements.critereon.DeserializationContext; -import net.minecraft.advancements.critereon.EntityPredicate; -import net.minecraft.resources.ResourceLocation; - -public class BasicPlayerAdvTrigger extends BaseAdvancementTrigger { - - private final ResourceLocation advancementId; - - public BasicPlayerAdvTrigger(ResourceLocation advancementId) { - this.advancementId = advancementId; - } - - @Override - public ResourceLocation getId() { - return advancementId; - } - - @Override - public Instance createInstance(JsonObject json, DeserializationContext conditions) { - return new Instance(this.advancementId, EntityPredicate.Composite.fromJson(json, "player", conditions)); - } - - public static class Instance extends AbstractCriterionTriggerInstance { - - public Instance(ResourceLocation advId, EntityPredicate.Composite player) { - super(advId, player); - } - - public static Instance create(ResourceLocation advancement) { - return new Instance(advancement, EntityPredicate.Composite.ANY); - } - } -} diff --git a/src/main/java/dev/compactmods/machines/advancement/trigger/HowDidYouGetHereTrigger.java b/src/main/java/dev/compactmods/machines/advancement/trigger/HowDidYouGetHereTrigger.java deleted file mode 100644 index 6407bcf7..00000000 --- a/src/main/java/dev/compactmods/machines/advancement/trigger/HowDidYouGetHereTrigger.java +++ /dev/null @@ -1,32 +0,0 @@ -package dev.compactmods.machines.advancement.trigger; - -import com.google.gson.JsonObject; -import dev.compactmods.machines.api.core.Advancements; -import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance; -import net.minecraft.advancements.critereon.EntityPredicate; -import net.minecraft.advancements.critereon.DeserializationContext; -import net.minecraft.resources.ResourceLocation; - -public class HowDidYouGetHereTrigger extends BaseAdvancementTrigger { - - @Override - public ResourceLocation getId() { - return Advancements.HOW_DID_YOU_GET_HERE; - } - - @Override - public Instance createInstance(JsonObject json, DeserializationContext conditions) { - return new Instance(EntityPredicate.Composite.fromJson(json, "player", conditions)); - } - - public static class Instance extends AbstractCriterionTriggerInstance { - - public Instance(EntityPredicate.Composite player) { - super(Advancements.HOW_DID_YOU_GET_HERE, player); - } - - public static Instance create() { - return new Instance(EntityPredicate.Composite.ANY); - } - } -} diff --git a/src/main/java/dev/compactmods/machines/client/ClientEventHandler.java b/src/main/java/dev/compactmods/machines/client/ClientEventHandler.java deleted file mode 100644 index 659077d2..00000000 --- a/src/main/java/dev/compactmods/machines/client/ClientEventHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -package dev.compactmods.machines.client; - -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.tunnel.Tunnels; -import dev.compactmods.machines.core.UIRegistration; -import dev.compactmods.machines.room.client.MachineRoomScreen; -import dev.compactmods.machines.tunnel.client.TunnelColors; -import dev.compactmods.machines.tunnel.client.TunnelItemColor; -import net.minecraft.client.gui.screens.MenuScreens; -import net.minecraft.client.renderer.ItemBlockRenderTypes; -import net.minecraft.client.renderer.RenderType; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.RegisterColorHandlersEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -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 ClientEventHandler { - - @SubscribeEvent - public static void onItemColors(final RegisterColorHandlersEvent.Item colors) { - colors.register(new TunnelItemColor(), Tunnels.ITEM_TUNNEL.get()); - } - - @SubscribeEvent - public static void onBlockColors(final RegisterColorHandlersEvent.Block colors) { - colors.register(new TunnelColors(), Tunnels.BLOCK_TUNNEL_WALL.get()); - } - - @SubscribeEvent - public static void onClientSetup(final FMLClientSetupEvent client) { - RenderType cutout = RenderType.cutoutMipped(); - ItemBlockRenderTypes.setRenderLayer(Tunnels.BLOCK_TUNNEL_WALL.get(), cutout); - - MenuScreens.register(UIRegistration.MACHINE_MENU.get(), MachineRoomScreen::new); - } -} diff --git a/src/main/java/dev/compactmods/machines/client/Resources.java b/src/main/java/dev/compactmods/machines/client/Resources.java deleted file mode 100644 index 149d77d9..00000000 --- a/src/main/java/dev/compactmods/machines/client/Resources.java +++ /dev/null @@ -1,12 +0,0 @@ -package dev.compactmods.machines.client; - -import dev.compactmods.machines.api.core.Constants; -import net.minecraft.resources.ResourceLocation; - -public class Resources { - public static final class Gui { - private static final String path = "textures/gui/"; - - public static final ResourceLocation PSD_SCREEN = new ResourceLocation(Constants.MOD_ID, path + "psd_screen.png"); - } -} diff --git a/src/main/java/dev/compactmods/machines/client/gui/GuiIds.java b/src/main/java/dev/compactmods/machines/client/gui/GuiIds.java deleted file mode 100644 index dd100634..00000000 --- a/src/main/java/dev/compactmods/machines/client/gui/GuiIds.java +++ /dev/null @@ -1,7 +0,0 @@ -package dev.compactmods.machines.client.gui; - -public enum GuiIds { - PSD_GUIDE, - MACHINE_VIEW, - MACHINE_ADMIN -} diff --git a/src/main/java/dev/compactmods/machines/client/gui/PersonalShrinkingDeviceScreen.java b/src/main/java/dev/compactmods/machines/client/gui/PersonalShrinkingDeviceScreen.java deleted file mode 100644 index d54120ff..00000000 --- a/src/main/java/dev/compactmods/machines/client/gui/PersonalShrinkingDeviceScreen.java +++ /dev/null @@ -1,107 +0,0 @@ -package dev.compactmods.machines.client.gui; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.client.gui.guide.GuideSection; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; - -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.Map; - -public class PersonalShrinkingDeviceScreen extends Screen { - private final ResourceLocation GUI = new ResourceLocation(Constants.MOD_ID, "textures/gui/psd_screen.png"); - private static final int WIDTH = 256; - private static final int HEIGHT = 201; - - private final Map sections; - private final ResourceLocation emptySection = new ResourceLocation(Constants.MOD_ID, "empty"); - - @Nullable - private final GuideSection currentSection; - - protected PersonalShrinkingDeviceScreen() { - super(Component.translatable(Constants.MOD_ID + ".gui.psd.title")); - this.sections = new HashMap<>(); - - GuideSection root = new GuideSection(); - sections.put(new ResourceLocation(Constants.MOD_ID, "root"), root); - this.currentSection = root; - } - - @Override - public void mouseMoved(double mouseX, double mouseY) { - if(currentSection != null) - currentSection.mouseMoved(mouseX, mouseY); - } - - @Override - public boolean mouseScrolled(double mouseX, double mouseY, double delta) { - int relX = (this.width - WIDTH) / 2; - - // relY = relative position, places screen against bottom edge of screen - int relY = (this.height - HEIGHT); - - if(currentSection != null) - return currentSection.mouseScrolled(mouseX - relX - 15, mouseY - relY - 14, delta); - - return false; - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - super.mouseClicked(mouseX, mouseY, button); - - int relX = (this.width - WIDTH) / 2; - - // relY = relative position, places screen against bottom edge of screen - int relY = (this.height - HEIGHT); - - if(currentSection != null) - return currentSection.mouseClicked(mouseX - relX - 15, mouseY - relY - 14, button); - - return false; - } - - @Override - public void render(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { - this.renderBackground(matrixStack); - - RenderSystem.clearColor(1, 1, 1, 1); - int relX = (this.width - WIDTH) / 2; - - // relY = relative position, places screen against bottom edge of screen - int relY = (this.height - HEIGHT); - - matrixStack.pushPose(); - matrixStack.translate(relX, relY, 0); - - RenderSystem.setShaderTexture(0, GUI); - this.blit(matrixStack, 0, 0, 0, 0, WIDTH, HEIGHT); - matrixStack.popPose(); - - matrixStack.pushPose(); - matrixStack.translate(relX + 15, relY + 14, 10); - - if(currentSection != null) { - currentSection.render(matrixStack, mouseX - relX - 15, mouseY - relY - 14, partialTicks); - } - - matrixStack.popPose(); - - super.render(matrixStack, mouseX, mouseY, partialTicks); - } - - @Override - public boolean isPauseScreen() { - return false; - } - - public static void show() { - Minecraft.getInstance().setScreen(new PersonalShrinkingDeviceScreen()); - } -} diff --git a/src/main/java/dev/compactmods/machines/client/gui/guide/GuidePage.java b/src/main/java/dev/compactmods/machines/client/gui/guide/GuidePage.java deleted file mode 100644 index 16819d5b..00000000 --- a/src/main/java/dev/compactmods/machines/client/gui/guide/GuidePage.java +++ /dev/null @@ -1,70 +0,0 @@ -package dev.compactmods.machines.client.gui.guide; - -import com.mojang.blaze3d.vertex.PoseStack; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.client.gui.widget.AbstractCMGuiWidget; -import dev.compactmods.machines.client.gui.widget.ScrollableWrappedTextWidget; -import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiComponent; -import net.minecraft.client.gui.components.Widget; -import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.network.chat.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -public class GuidePage implements Widget, GuiEventListener { - - protected final List widgets; - - public GuidePage() { - widgets = new ArrayList<>(); - - ScrollableWrappedTextWidget sc = new ScrollableWrappedTextWidget(Constants.MOD_ID + ".psd.pages.machines", 2, 18, 222, 160); - widgets.add(sc); - } - - @Override - public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) { - Font fr = Minecraft.getInstance().font; - GuiComponent.drawString(ms, fr, - Component.translatable(Constants.MOD_ID + ".psd.pages.machines.title") - .withStyle(ChatFormatting.GOLD), - 2, 2, 0); - - for(Widget comp : widgets) - comp.render(ms, mouseX, mouseY, partialTicks); - } - - public Optional getWidgetByPosition(double mouseX, double mouseY) { - for(AbstractCMGuiWidget wid : widgets) { - if(wid.isMouseOver(mouseX, mouseY)) - return Optional.of(wid); - } - - return Optional.empty(); - } - - @Override - public void mouseMoved(double mouseX, double mouseY) { - getWidgetByPosition(mouseX, mouseY) - .ifPresent(c -> c.mouseMoved(mouseX, mouseY)); - } - - @Override - public boolean mouseScrolled(double mouseX, double mouseY, double delta) { - return getWidgetByPosition(mouseX, mouseY) - .map(c -> c.mouseScrolled(mouseX, mouseY, delta)) - .orElse(false); - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - return getWidgetByPosition(mouseX, mouseY) - .map(c -> c.mouseClicked(mouseX, mouseY, button)) - .orElse(false); - } -} diff --git a/src/main/java/dev/compactmods/machines/client/gui/guide/GuideSection.java b/src/main/java/dev/compactmods/machines/client/gui/guide/GuideSection.java deleted file mode 100644 index dab2ea68..00000000 --- a/src/main/java/dev/compactmods/machines/client/gui/guide/GuideSection.java +++ /dev/null @@ -1,48 +0,0 @@ -package dev.compactmods.machines.client.gui.guide; - -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.client.gui.components.Widget; - -import java.util.ArrayList; -import java.util.List; - -public class GuideSection implements Widget, GuiEventListener { - private final List pages; - private final int currentPageIndex = 0; - private final GuidePage currentPage; - - public GuideSection() { - this.pages = new ArrayList<>(); - this.currentPage = new GuidePage(); - this.pages.add(currentPage); - } - - @Override - public void render(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { - if(this.currentPage != null) - currentPage.render(matrixStack, mouseX, mouseY, partialTicks); - } - - @Override - public void mouseMoved(double mouseX, double mouseY) { - if(this.currentPage != null) - currentPage.mouseMoved(mouseX, mouseY); - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if(this.currentPage != null) - return currentPage.mouseClicked(mouseX, mouseY, button); - - return false; - } - - @Override - public boolean mouseScrolled(double mouseX, double mouseY, double delta) { - if(this.currentPage != null) - return currentPage.mouseScrolled(mouseX, mouseY, delta); - - return false; - } -} diff --git a/src/main/java/dev/compactmods/machines/client/gui/widget/AbstractCMGuiWidget.java b/src/main/java/dev/compactmods/machines/client/gui/widget/AbstractCMGuiWidget.java deleted file mode 100644 index 344e1492..00000000 --- a/src/main/java/dev/compactmods/machines/client/gui/widget/AbstractCMGuiWidget.java +++ /dev/null @@ -1,27 +0,0 @@ -package dev.compactmods.machines.client.gui.widget; - -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.gui.components.events.GuiEventListener; -import net.minecraft.client.gui.components.Widget; - -public class AbstractCMGuiWidget implements Widget, GuiEventListener { - - protected final int x, y, width, height; - - protected AbstractCMGuiWidget(int x, int y, int width, int height) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - } - - @Override - public void render(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { - - } - - @Override - public boolean isMouseOver(double mouseX, double mouseY) { - return mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; - } -} diff --git a/src/main/java/dev/compactmods/machines/client/gui/widget/ScrollableWrappedTextWidget.java b/src/main/java/dev/compactmods/machines/client/gui/widget/ScrollableWrappedTextWidget.java deleted file mode 100644 index 22f9a197..00000000 --- a/src/main/java/dev/compactmods/machines/client/gui/widget/ScrollableWrappedTextWidget.java +++ /dev/null @@ -1,71 +0,0 @@ -package dev.compactmods.machines.client.gui.widget; - -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; -import net.minecraft.client.resources.language.I18n; -import net.minecraft.network.chat.Component; -import net.minecraft.util.FormattedCharSequence; -import net.minecraft.util.Mth; - -import java.util.List; - -public class ScrollableWrappedTextWidget extends AbstractCMGuiWidget { - - private final String localeKey; - private double yScroll = 0; - private final Font fontRenderer; - - private int maxLinesToShow; - private int lineIndexStart; - private List lines; - private int charSize; - - public ScrollableWrappedTextWidget(String key, int x, int y, int width, int height) { - super(x, y, width, height); - this.localeKey = key; - this.fontRenderer = Minecraft.getInstance().font; - - this.recalculate(); - } - - @Override - public boolean mouseScrolled(double mouseX, double mouseY, double delta) { - double temp = yScroll - delta; - yScroll = Mth.clamp(temp, 0, lines.size() - maxLinesToShow - 1); - recalculate(); - return true; - } - - private void recalculate() { - String t = I18n.get(localeKey); - lines = fontRenderer.split(Component.literal(t), width); - - charSize = fontRenderer.width("M"); - int maxOnScreen = height / (charSize + 4); - maxLinesToShow = Math.min(lines.size(), maxOnScreen); - - // startClamp - either the current line scroll, or the max allowed line - int startClamp = Math.min((int) Math.floor(yScroll), lines.size()); - lineIndexStart = Mth.clamp(0, startClamp, lines.size() - 1); - } - - @Override - public void render(PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { - matrixStack.pushPose(); - matrixStack.translate(x, y, 10); - - Font fr = Minecraft.getInstance().font; - - try { - for (int y = lineIndexStart; y <= lineIndexStart + maxLinesToShow; y++) { - FormattedCharSequence s = lines.get(y); - fr.drawShadow(matrixStack, s, 0, (y - lineIndexStart) * (charSize + 4), 0xFFFFFF); - } - } - - catch(Exception ex1) {} - - matrixStack.popPose(); - } -} diff --git a/src/main/java/dev/compactmods/machines/client/level/EmptyLevelEntityGetter.java b/src/main/java/dev/compactmods/machines/client/level/EmptyLevelEntityGetter.java deleted file mode 100644 index 1c42fa2b..00000000 --- a/src/main/java/dev/compactmods/machines/client/level/EmptyLevelEntityGetter.java +++ /dev/null @@ -1,45 +0,0 @@ -package dev.compactmods.machines.client.level; - -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.entity.EntityTypeTest; -import net.minecraft.world.level.entity.LevelEntityGetter; -import net.minecraft.world.phys.AABB; - -import javax.annotation.Nullable; -import java.util.Collections; -import java.util.UUID; -import java.util.function.Consumer; - -public class EmptyLevelEntityGetter implements LevelEntityGetter { - @Nullable - @Override - public Entity get(int p_156931_) { - return null; - } - - @Nullable - @Override - public Entity get(UUID p_156939_) { - return null; - } - - @Override - public Iterable getAll() { - return Collections.emptySet(); - } - - @Override - public void get(EntityTypeTest p_156935_, Consumer p_156936_) { - - } - - @Override - public void get(AABB p_156937_, Consumer p_156938_) { - - } - - @Override - public void get(EntityTypeTest p_156932_, AABB p_156933_, Consumer p_156934_) { - - } -} diff --git a/src/main/java/dev/compactmods/machines/client/level/FakeSpawnInfo.java b/src/main/java/dev/compactmods/machines/client/level/FakeSpawnInfo.java deleted file mode 100644 index f7ad3847..00000000 --- a/src/main/java/dev/compactmods/machines/client/level/FakeSpawnInfo.java +++ /dev/null @@ -1,120 +0,0 @@ -package dev.compactmods.machines.client.level; - -import net.minecraft.world.Difficulty; -import net.minecraft.world.level.GameRules; -import net.minecraft.world.level.storage.WritableLevelData; - -/** - * Credits to Immersive Engineering manual code for a baseline in 1.18.x. - * Source: https://github.com/BluSunrize/ImmersiveEngineering/blob/1.18.2/src/main/java/blusunrize/immersiveengineering/common/util/fakeworld/FakeSpawnInfo.java - */ -public class FakeSpawnInfo implements WritableLevelData { - private static final GameRules RULES = new GameRules(); - - private int spawnX; - private int spawnY; - private int spawnZ; - private float spawnAngle; - - @Override - public void setXSpawn(int x) - { - spawnX = x; - } - - @Override - public void setYSpawn(int y) - { - spawnY = y; - } - - @Override - public void setZSpawn(int z) - { - spawnZ = z; - } - - @Override - public void setSpawnAngle(float angle) - { - spawnAngle = angle; - } - - @Override - public int getXSpawn() - { - return spawnX; - } - - @Override - public int getYSpawn() - { - return spawnY; - } - - @Override - public int getZSpawn() - { - return spawnZ; - } - - @Override - public float getSpawnAngle() - { - return spawnAngle; - } - - @Override - public long getGameTime() - { - return 0; - } - - @Override - public long getDayTime() - { - return 0; - } - - @Override - public boolean isThundering() - { - return false; - } - - @Override - public boolean isRaining() - { - return false; - } - - @Override - public void setRaining(boolean isRaining) - { - - } - - @Override - public boolean isHardcore() - { - return false; - } - - @Override - public GameRules getGameRules() - { - return RULES; - } - - @Override - public Difficulty getDifficulty() - { - return Difficulty.PEACEFUL; - } - - @Override - public boolean isDifficultyLocked() - { - return false; - } -} diff --git a/src/main/java/dev/compactmods/machines/client/render/SuperRenderTypeBuffer.java b/src/main/java/dev/compactmods/machines/client/render/SuperRenderTypeBuffer.java deleted file mode 100644 index 5b9e42d2..00000000 --- a/src/main/java/dev/compactmods/machines/client/render/SuperRenderTypeBuffer.java +++ /dev/null @@ -1,98 +0,0 @@ -package dev.compactmods.machines.client.render; - -import java.util.SortedMap; - -import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.VertexConsumer; - -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import net.minecraft.Util; -import net.minecraft.client.renderer.ChunkBufferBuilderPack; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.Sheets; -import net.minecraft.client.resources.model.ModelBakery; - -/** - * Copied from Create's ponder rendering code. Stripping this down for now, WIP - */ -public class SuperRenderTypeBuffer implements MultiBufferSource { - - private static final SuperRenderTypeBuffer INSTANCE = new SuperRenderTypeBuffer(); - - public static SuperRenderTypeBuffer getInstance() { - return INSTANCE; - } - - private SuperRenderTypeBufferPhase earlyBuffer; - private SuperRenderTypeBufferPhase defaultBuffer; - private SuperRenderTypeBufferPhase lateBuffer; - - public SuperRenderTypeBuffer() { - earlyBuffer = new SuperRenderTypeBufferPhase(); - defaultBuffer = new SuperRenderTypeBufferPhase(); - lateBuffer = new SuperRenderTypeBufferPhase(); - } - - public VertexConsumer getEarlyBuffer(RenderType type) { - return earlyBuffer.bufferSource.getBuffer(type); - } - - @Override - public VertexConsumer getBuffer(RenderType type) { - return defaultBuffer.bufferSource.getBuffer(type); - } - - public VertexConsumer getLateBuffer(RenderType type) { - return lateBuffer.bufferSource.getBuffer(type); - } - - public void draw() { - earlyBuffer.bufferSource.endBatch(); - defaultBuffer.bufferSource.endBatch(); - lateBuffer.bufferSource.endBatch(); - } - - public void draw(RenderType type) { - earlyBuffer.bufferSource.endBatch(type); - defaultBuffer.bufferSource.endBatch(type); - lateBuffer.bufferSource.endBatch(type); - } - - private static class SuperRenderTypeBufferPhase { - - // Visible clones from RenderBuffers - private final ChunkBufferBuilderPack fixedBufferPack = new ChunkBufferBuilderPack(); - private final SortedMap fixedBuffers = Util.make(new Object2ObjectLinkedOpenHashMap<>(), map -> { - map.put(Sheets.solidBlockSheet(), fixedBufferPack.builder(RenderType.solid())); - map.put(Sheets.cutoutBlockSheet(), fixedBufferPack.builder(RenderType.cutout())); - map.put(Sheets.bannerSheet(), fixedBufferPack.builder(RenderType.cutoutMipped())); - map.put(Sheets.translucentCullBlockSheet(), fixedBufferPack.builder(RenderType.translucent())); - put(map, Sheets.shieldSheet()); - put(map, Sheets.bedSheet()); - put(map, Sheets.shulkerBoxSheet()); - put(map, Sheets.signSheet()); - put(map, Sheets.chestSheet()); - put(map, RenderType.translucentNoCrumbling()); - put(map, RenderType.armorGlint()); - put(map, RenderType.armorEntityGlint()); - put(map, RenderType.glint()); - put(map, RenderType.glintDirect()); - put(map, RenderType.glintTranslucent()); - put(map, RenderType.entityGlint()); - put(map, RenderType.entityGlintDirect()); - put(map, RenderType.waterMask()); - ModelBakery.DESTROY_TYPES.forEach((p_173062_) -> { - put(map, p_173062_); - }); - }); - private final MultiBufferSource.BufferSource bufferSource = MultiBufferSource.immediateWithBuffers(fixedBuffers, new BufferBuilder(256)); - - private static void put(Object2ObjectLinkedOpenHashMap map, RenderType type) { - map.put(type, new BufferBuilder(type.bufferSize())); - } - - } - -} - diff --git a/src/main/java/dev/compactmods/machines/client/util/TransformingVertexBuilder.java b/src/main/java/dev/compactmods/machines/client/util/TransformingVertexBuilder.java deleted file mode 100644 index 58592063..00000000 --- a/src/main/java/dev/compactmods/machines/client/util/TransformingVertexBuilder.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * BluSunrize - * Copyright (c) 2020 - * - * This code is licensed under "Blu's License of Common Sense" - * - * Source: https://github.com/BluSunrize/ImmersiveEngineering/blob/1.18.2/src/main/java/blusunrize/immersiveengineering/client/utils/TransformingVertexBuilder.java - */ - -package dev.compactmods.machines.client.util; - -import com.google.common.base.Preconditions; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.blaze3d.vertex.VertexFormat; -import com.mojang.blaze3d.vertex.VertexFormatElement; -import com.mojang.math.Vector3f; -import com.mojang.math.Vector4f; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.world.phys.Vec2; -import net.minecraft.world.phys.Vec3; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import static com.mojang.blaze3d.vertex.DefaultVertexFormat.*; - -public class TransformingVertexBuilder implements VertexConsumer -{ - private final VertexConsumer base; - private final PoseStack transform; - private final List> allObjects = new ArrayList<>(); - private final ObjectWithGlobal uv = new ObjectWithGlobal<>(this); - private final ObjectWithGlobal pos = new ObjectWithGlobal<>(this); - private final ObjectWithGlobal overlay = new ObjectWithGlobal<>(this); - private final ObjectWithGlobal lightmap = new ObjectWithGlobal<>(this); - private final ObjectWithGlobal normal = new ObjectWithGlobal<>(this); - private final ObjectWithGlobal color = new ObjectWithGlobal<>(this); - private final VertexFormat format; - - public TransformingVertexBuilder(VertexConsumer base, PoseStack transform, VertexFormat format) - { - this.base = base; - this.transform = transform; - this.format = format; - } - - public TransformingVertexBuilder(VertexConsumer base, VertexFormat format) - { - this(base, new PoseStack(), format); - } - - public TransformingVertexBuilder(MultiBufferSource buffer, RenderType type, PoseStack transform) - { - this(buffer.getBuffer(type), transform, type.format()); - } - - public TransformingVertexBuilder(MultiBufferSource buffer, RenderType type) - { - this(buffer, type, new PoseStack()); - } - - @Nonnull - @Override - public VertexConsumer vertex(double x, double y, double z) - { - pos.putData(new Vec3(x, y, z)); - return this; - } - - @Nonnull - @Override - public VertexConsumer color(int red, int green, int blue, int alpha) - { - color.putData(new Vector4f(red/255f, green/255f, blue/255f, alpha/255f)); - return this; - } - - @Nonnull - @Override - public VertexConsumer uv(float u, float v) - { - uv.putData(new Vec2(u, v)); - return this; - } - - @Nonnull - @Override - public VertexConsumer overlayCoords(int u, int v) - { - overlay.putData(new Vec2i(u, v)); - return this; - } - - @Nonnull - @Override - public VertexConsumer uv2(int u, int v) - { - lightmap.putData(new Vec2i(u, v)); - return this; - } - - @Nonnull - @Override - public VertexConsumer normal(float x, float y, float z) - { - normal.putData(new Vector3f(x, y, z)); - return this; - } - - @Override - public void endVertex() - { - for(VertexFormatElement element : format.getElements()) - { - if(element==ELEMENT_POSITION) - pos.ifPresent(pos -> base.vertex(transform.last().pose(), (float)pos.x, (float)pos.y, (float)pos.z)); - else if(element==ELEMENT_COLOR) - color.ifPresent(c -> base.color(c.x(), c.y(), c.z(), c.w())); - else if(element==ELEMENT_UV0) - uv.ifPresent(uv -> base.uv(uv.x, uv.y)); - else if(element==ELEMENT_UV1) - overlay.ifPresent(overlay -> base.overlayCoords(overlay.x, overlay.y)); - else if(element==ELEMENT_UV2) - lightmap.ifPresent(lightmap -> base.uv2(lightmap.x, lightmap.y)); - else if(element==ELEMENT_NORMAL) - normal.ifPresent( - normal -> base.normal(transform.last().normal(), normal.x(), normal.y(), normal.z()) - ); - } - base.endVertex(); - allObjects.forEach(ObjectWithGlobal::clear); - } - - public void defaultColor(float r, float g, float b, float a) - { - color.setGlobal(new Vector4f(r, g, b, a)); - } - - @Override - public void defaultColor(int r, int g, int b, int a) - { - defaultColor(r/255f, g/255f, b/255f, a/255f); - } - - @Override - public void unsetDefaultColor() - { - color.setGlobal(null); - } - - public void setLight(int light) - { - lightmap.setGlobal(new Vec2i(light&255, light >> 16)); - } - - public void setNormal(float x, float y, float z) - { - Vector3f vec = new Vector3f(x, y, z); - vec.normalize(); - normal.setGlobal(vec); - } - - public void setOverlay(int packedOverlayIn) - { - overlay.setGlobal(new Vec2i(packedOverlayIn&0xffff, packedOverlayIn >> 16)); - } - - private record Vec2i(int x, int y) - { - } - - private static class ObjectWithGlobal - { - @Nullable - private T obj; - private boolean isGlobal; - - public ObjectWithGlobal(TransformingVertexBuilder builder) - { - builder.allObjects.add(this); - } - - public void putData(T newVal) - { - Preconditions.checkState(obj==null||(isGlobal&&obj.equals(newVal))); - obj = newVal; - } - - public void setGlobal(@Nullable T obj) - { - this.obj = obj; - isGlobal = obj!=null; - } - - public T read() - { - T ret = Preconditions.checkNotNull(obj); - if(!isGlobal) - obj = null; - return ret; - } - - public boolean hasValue() - { - return obj!=null; - } - - public void ifPresent(Consumer out) - { - if(hasValue()) - out.accept(read()); - } - - public void clear() - { - if(!isGlobal) - obj = null; - } - } -} \ No newline at end of file diff --git a/src/main/java/dev/compactmods/machines/command/Commands.java b/src/main/java/dev/compactmods/machines/command/Commands.java deleted file mode 100644 index 32aa2f5f..00000000 --- a/src/main/java/dev/compactmods/machines/command/Commands.java +++ /dev/null @@ -1,52 +0,0 @@ -package dev.compactmods.machines.command; - -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.command.argument.RoomPositionArgument; -import dev.compactmods.machines.command.data.CMDataSubcommand; -import dev.compactmods.machines.command.subcommand.*; -import dev.compactmods.machines.core.Registries; -import dev.compactmods.machines.upgrade.command.CMUpgradeRoomCommand; -import dev.compactmods.machines.upgrade.command.RoomUpgradeArgument; -import net.minecraft.commands.CommandSourceStack; -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 Commands { - - // TODO: /cm create - // TODO: /cm spawn set - - static { - Registries.COMMAND_ARGUMENT_TYPES.register("room_pos", - () -> ArgumentTypeInfos.registerByClass(RoomPositionArgument.class, SingletonArgumentInfo.contextFree(RoomPositionArgument::room))); - - Registries.COMMAND_ARGUMENT_TYPES.register("room_upgrade", - () -> ArgumentTypeInfos.registerByClass(RoomUpgradeArgument.class, SingletonArgumentInfo.contextFree(RoomUpgradeArgument::upgrade))); - } - - @SubscribeEvent - public static void onCommandsRegister(final RegisterCommandsEvent event) { - final LiteralArgumentBuilder root = LiteralArgumentBuilder.literal(Constants.MOD_ID); - root.then(CMEjectSubcommand.make()); - root.then(CMSummarySubcommand.make()); - root.then(CMRebindSubcommand.make()); - root.then(CMUnbindSubcommand.make()); - root.then(CMReaddDimensionSubcommand.make()); - root.then(CMRoomsSubcommand.make()); - root.then(CMDataSubcommand.make()); - root.then(CMGiveMachineSubcommand.make()); - root.then(SpawnSubcommand.make()); - root.then(CMUpgradeRoomCommand.make()); - - event.getDispatcher().register(root); - } - - public static void prepare() { - - } -} diff --git a/src/main/java/dev/compactmods/machines/command/argument/RoomCoordinates.java b/src/main/java/dev/compactmods/machines/command/argument/RoomCoordinates.java deleted file mode 100644 index edeee10d..00000000 --- a/src/main/java/dev/compactmods/machines/command/argument/RoomCoordinates.java +++ /dev/null @@ -1,21 +0,0 @@ -package dev.compactmods.machines.command.argument; - -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.coordinates.WorldCoordinate; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.phys.Vec3; - -public class RoomCoordinates { - private final WorldCoordinate x; - private final WorldCoordinate z; - - public RoomCoordinates(WorldCoordinate x, WorldCoordinate z) { - this.x = x; - this.z = z; - } - - public ChunkPos get(CommandSourceStack stack) { - Vec3 vec3 = stack.getPosition(); - return new ChunkPos((int) this.x.get(vec3.x), (int) this.z.get(vec3.z)); - } -} diff --git a/src/main/java/dev/compactmods/machines/command/argument/RoomPositionArgument.java b/src/main/java/dev/compactmods/machines/command/argument/RoomPositionArgument.java deleted file mode 100644 index fc1c6510..00000000 --- a/src/main/java/dev/compactmods/machines/command/argument/RoomPositionArgument.java +++ /dev/null @@ -1,51 +0,0 @@ -package dev.compactmods.machines.command.argument; - -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.coordinates.WorldCoordinate; -import net.minecraft.network.chat.Component; -import net.minecraft.world.level.ChunkPos; - -import java.util.concurrent.CompletableFuture; - -public class RoomPositionArgument implements ArgumentType { - public static final SimpleCommandExceptionType ERROR_NOT_COMPLETE = new SimpleCommandExceptionType(Component.translatable("argument.pos2d.incomplete")); - - public static RoomPositionArgument room() { - return new RoomPositionArgument(); - } - - public static ChunkPos get(CommandContext ctx, String room) { - var arg = ctx.getArgument(room, RoomCoordinates.class); - return arg.get(ctx.getSource()); - } - - @Override - public RoomCoordinates parse(StringReader reader) throws CommandSyntaxException { - int i = reader.getCursor(); - if (!reader.canRead()) { - throw ERROR_NOT_COMPLETE.createWithContext(reader); - } else { - WorldCoordinate chunkX = WorldCoordinate.parseInt(reader); - if (reader.canRead() && reader.peek() == ' ') { - reader.skip(); - WorldCoordinate chunkZ = WorldCoordinate.parseInt(reader); - return new RoomCoordinates(chunkX, chunkZ); - } else { - reader.setCursor(i); - throw ERROR_NOT_COMPLETE.createWithContext(reader); - } - } - } - - @Override - public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { - return Suggestions.empty(); - } -} diff --git a/src/main/java/dev/compactmods/machines/command/data/CMDataSubcommand.java b/src/main/java/dev/compactmods/machines/command/data/CMDataSubcommand.java deleted file mode 100644 index 2aaef861..00000000 --- a/src/main/java/dev/compactmods/machines/command/data/CMDataSubcommand.java +++ /dev/null @@ -1,21 +0,0 @@ -package dev.compactmods.machines.command.data; - -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; - -public class CMDataSubcommand { - public static LiteralArgumentBuilder make() { - final LiteralArgumentBuilder root = LiteralArgumentBuilder.literal("data"); - - var export = Commands.literal("export"); - export.then(CMMachineDataExportCommand.makeMachineCsv()); - export.then(CMTunnelDataExportCommand.makeTunnelCsv()); - export.then(CMRoomDataExportCommand.makeRoomCsv()); - root.then(export); - - return root; - } - - -} diff --git a/src/main/java/dev/compactmods/machines/command/data/CMMachineDataExportCommand.java b/src/main/java/dev/compactmods/machines/command/data/CMMachineDataExportCommand.java deleted file mode 100644 index b37bb0c3..00000000 --- a/src/main/java/dev/compactmods/machines/command/data/CMMachineDataExportCommand.java +++ /dev/null @@ -1,94 +0,0 @@ -package dev.compactmods.machines.command.data; - -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import dev.compactmods.machines.api.room.MachineRoomConnections; -import dev.compactmods.machines.api.core.Constants; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.util.CsvOutput; - -import javax.annotation.Nonnull; -import java.io.BufferedWriter; -import java.io.IOException; - -// TODO -public class CMMachineDataExportCommand { - - public static ArgumentBuilder makeMachineCsv() { - return Commands.literal("machines") - .requires(cs -> cs.hasPermission(2)) - .executes(CMMachineDataExportCommand::execAll); - } - - private static int execAll(CommandContext ctx) { - var src = ctx.getSource(); - var serv = src.getServer(); - -// final CompactMachineGraph machines; -// final MachineToRoomConnections connections; -// try { -// machines = CompactMachineGraph.forDimension(serv); -// connections = MachineToRoomConnections.get(serv); -// } catch (MissingDimensionException e) { -// CompactMachines.LOGGER.fatal(e); -// return -1; -// } -// -// var outdir = src.getServer().getFile(CompactMachines.MOD_ID); -// var out = outdir.toPath() -// .resolve("machines.csv") -// .toAbsolutePath(); -// -// try { -// Files.createDirectories(outdir.toPath()); -// -// var writer = Files.newBufferedWriter(out); -// CsvOutput builder = makeCsv(writer); -// -// machines.getMachines().forEach(node -> writeMachine(connections, node, builder)); -// -// writer.close(); -// } catch (IOException e) { -// CompactMachines.LOGGER.error(e); -// src.sendFailure(TranslationUtil.command(CMCommands.FAILED_CMD_FILE_ERROR)); -// return -1; -// } - - return 0; - } - - @Nonnull - private static CsvOutput makeCsv(BufferedWriter writer) throws IOException { - return CsvOutput.builder() - .addColumn("id") - .addColumn("dim") - .addColumn("machine_x") - .addColumn("machine_y") - .addColumn("machine_z") - .addColumn("room_x") - .addColumn("room_z") - .build(writer); - } - - private static void writeMachine(MachineRoomConnections connections, CsvOutput builder) { -// try { -// int id = mach.getMachineId(); -// var loc = mach.getLocation(); -// var placedAt = loc.getBlockPosition(); -// -// var room = connections.getConnectedRoom(id).orElse(new ChunkPos(-1, -1)); -// builder.writeRow( -// id, -// loc.getDimension().location().toString(), -// placedAt.getX(), -// placedAt.getY(), -// placedAt.getZ(), -// room.x, -// room.z -// ); -// } catch (IOException e) { -// CompactMachines.LOGGER.error(e); -// } - } -} diff --git a/src/main/java/dev/compactmods/machines/command/data/CMRoomDataExportCommand.java b/src/main/java/dev/compactmods/machines/command/data/CMRoomDataExportCommand.java deleted file mode 100644 index 391afe2e..00000000 --- a/src/main/java/dev/compactmods/machines/command/data/CMRoomDataExportCommand.java +++ /dev/null @@ -1,88 +0,0 @@ -package dev.compactmods.machines.command.data; - -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.core.CMCommands; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.i18n.TranslationUtil; -import dev.compactmods.machines.room.data.CompactRoomData; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.util.CsvOutput; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.phys.Vec3; - -import javax.annotation.Nonnull; -import java.io.BufferedWriter; -import java.io.IOException; -import java.nio.file.Files; - -public class CMRoomDataExportCommand { - - public static ArgumentBuilder makeRoomCsv() { - return Commands.literal("rooms") - .requires(cs -> cs.hasPermission(2)) - .executes(CMRoomDataExportCommand::execAll); - } - - private static int execAll(CommandContext ctx) { - var src = ctx.getSource(); - var serv = src.getServer(); - var compact = serv.getLevel(CompactDimension.LEVEL_KEY); - - final CompactRoomData rooms = CompactRoomData.get(compact); - - var outdir = src.getServer().getFile(Constants.MOD_ID); - var out = outdir.toPath() - .resolve("rooms.csv") - .toAbsolutePath(); - - try { - Files.createDirectories(outdir.toPath()); - - var writer = Files.newBufferedWriter(out); - CsvOutput builder = makeCsv(writer); - - rooms.streamRooms().forEach(room -> writeRoom(room, builder)); - - writer.close(); - } catch (IOException e) { - CompactMachines.LOGGER.error(e); - src.sendFailure(TranslationUtil.command(CMCommands.FAILED_CMD_FILE_ERROR)); - return -1; - } - - return 0; - } - - @Nonnull - private static CsvOutput makeCsv(BufferedWriter writer) throws IOException { - return CsvOutput.builder() - .addColumn("room_x") - .addColumn("room_z") - .addColumn("size") - .addColumn("owner_uuid") - .addColumn("spawn_x") - .addColumn("spawn_y") - .addColumn("spawn_z") - .build(writer); - } - - private static void writeRoom(CompactRoomData.RoomData room, CsvOutput builder) { - try { - ChunkPos chunk = new ChunkPos(room.getCenter()); - final Vec3 spawn = room.getSpawn(); - - builder.writeRow( - chunk.x, chunk.z, - room.getSize().getSerializedName(), - room.getOwner().toString(), - spawn.x, spawn.y, spawn.z - ); - } catch (IOException e) { - CompactMachines.LOGGER.error(e); - } - } -} diff --git a/src/main/java/dev/compactmods/machines/command/data/CMTunnelDataExportCommand.java b/src/main/java/dev/compactmods/machines/command/data/CMTunnelDataExportCommand.java deleted file mode 100644 index 2f4bb781..00000000 --- a/src/main/java/dev/compactmods/machines/command/data/CMTunnelDataExportCommand.java +++ /dev/null @@ -1,133 +0,0 @@ -package dev.compactmods.machines.command.data; - -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.core.CMCommands; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.command.argument.RoomPositionArgument; -import dev.compactmods.machines.dimension.MissingDimensionException; -import dev.compactmods.machines.i18n.TranslationUtil; -import dev.compactmods.machines.room.data.CompactRoomData; -import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.CsvOutput; -import net.minecraft.world.level.ChunkPos; - -import javax.annotation.Nonnull; -import java.io.BufferedWriter; -import java.io.IOException; -import java.nio.file.Files; - -public class CMTunnelDataExportCommand { - - public static ArgumentBuilder makeTunnelCsv() { - var chunk = Commands - .argument("room", RoomPositionArgument.room()) - .executes(CMTunnelDataExportCommand::exec); - - return Commands.literal("tunnels") - .requires(cs -> cs.hasPermission(Commands.LEVEL_GAMEMASTERS)) - .executes(CMTunnelDataExportCommand::execAll) - .then(chunk); - } - - private static int execAll(CommandContext ctx) { - var src = ctx.getSource(); - var serv = src.getServer(); - var compact = serv.getLevel(CompactDimension.LEVEL_KEY); - - final CompactRoomData rooms = CompactRoomData.get(compact); - - var outdir = src.getServer().getFile(Constants.MOD_ID); - var out = outdir.toPath() - .resolve("tunnels.csv") - .toAbsolutePath(); - - try { - Files.createDirectories(outdir.toPath()); - - var writer = Files.newBufferedWriter(out); - CsvOutput builder = makeTunnelCsvOut(writer); - - rooms.stream().forEach(roomChunk -> { - try { - writeRoomTunnels(compact, roomChunk, builder); - } catch (MissingDimensionException e) { - CompactMachines.LOGGER.error(e); - } - }); - - writer.close(); - } catch (IOException e) { - CompactMachines.LOGGER.error(e); - src.sendFailure(TranslationUtil.command(CMCommands.FAILED_CMD_FILE_ERROR)); - return -1; - } - - return 0; - } - - public static int exec(CommandContext ctx) throws CommandSyntaxException { - var src = ctx.getSource(); - ServerPlayer player = src.getPlayerOrException(); - - final var room = RoomPositionArgument.get(ctx, "room"); - final var compactDim = src.getServer().getLevel(CompactDimension.LEVEL_KEY); - - var outdir = src.getServer().getFile(Constants.MOD_ID); - var out = outdir.toPath() - .resolve(String.format("tunnels_%s_%s.csv", room.x, room.z)) - .toAbsolutePath(); - - try { - Files.createDirectories(outdir.toPath()); - - var writer = Files.newBufferedWriter(out); - CsvOutput builder = makeTunnelCsvOut(writer); - writeRoomTunnels(compactDim, room, builder); - - writer.close(); - } catch (IOException e) { - CompactMachines.LOGGER.error(e); - src.sendFailure(TranslationUtil.command(CMCommands.FAILED_CMD_FILE_ERROR)); - return -1; - } catch (MissingDimensionException e) { - CompactMachines.LOGGER.error(e); - } - - return 0; - } - - @Nonnull - private static CsvOutput makeTunnelCsvOut(BufferedWriter writer) throws IOException { - return CsvOutput.builder() - .addColumn("type") - .addColumn("side") - .addColumn("pos_x").addColumn("pos_y").addColumn("pos_z") - .addColumn("machine_id") - .build(writer); - } - - private static void writeRoomTunnels(ServerLevel compactDim, ChunkPos room, CsvOutput builder) throws MissingDimensionException { - final var graph = TunnelConnectionGraph.forRoom(compactDim, room); - graph.tunnels().forEach(info -> { - var pos = info.location(); - try { - builder.writeRow( - info.type().toString(), - info.side().getSerializedName(), - pos.getX(), pos.getY(), pos.getZ(), - info.machine() - ); - } catch (IOException e) { - CompactMachines.LOGGER.warn("Error writing tunnel record.", e); - } - }); - } -} diff --git a/src/main/java/dev/compactmods/machines/command/subcommand/CMRebindSubcommand.java b/src/main/java/dev/compactmods/machines/command/subcommand/CMRebindSubcommand.java deleted file mode 100644 index a65476c9..00000000 --- a/src/main/java/dev/compactmods/machines/command/subcommand/CMRebindSubcommand.java +++ /dev/null @@ -1,63 +0,0 @@ -package dev.compactmods.machines.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.api.core.CMCommands; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.command.argument.RoomPositionArgument; -import dev.compactmods.machines.config.ServerConfig; -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; -import net.minecraft.commands.arguments.coordinates.BlockPosArgument; - -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", RoomPositionArgument.room()) - .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 var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); - if(compactDim == null) { - throw new CommandRuntimeException(TranslationUtil.command(CMCommands.LEVEL_NOT_FOUND)); - } - - final var rebindingMachine = BlockPosArgument.getLoadedBlockPos(ctx, "pos"); - final var roomPos = RoomPositionArgument.get(ctx, "bindTo"); - - CompactMachines.LOGGER.debug("Binding machine at {} to room chunk {}", rebindingMachine, roomPos); - - if(!(level.getBlockEntity(rebindingMachine) instanceof CompactMachineBlockEntity 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 -> { - 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)); - }); - - // No tunnels - clear to rebind - machine.setConnectedRoom(roomPos); - }, () -> machine.setConnectedRoom(roomPos)); - - return 0; - } -} diff --git a/src/main/java/dev/compactmods/machines/command/subcommand/CMSummarySubcommand.java b/src/main/java/dev/compactmods/machines/command/subcommand/CMSummarySubcommand.java deleted file mode 100644 index 7bea8f7d..00000000 --- a/src/main/java/dev/compactmods/machines/command/subcommand/CMSummarySubcommand.java +++ /dev/null @@ -1,56 +0,0 @@ -package dev.compactmods.machines.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.i18n.TranslationUtil; -import dev.compactmods.machines.machine.graph.DimensionMachineGraph; -import dev.compactmods.machines.room.data.CompactRoomData; -import net.minecraft.ChatFormatting; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.level.Level; - -import java.util.HashMap; - -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(); - - var compactLevel = serv.getLevel(CompactDimension.LEVEL_KEY); - if (compactLevel != null) { - src.sendSuccess(TranslationUtil.command(CMCommands.LEVEL_REGISTERED).withStyle(ChatFormatting.DARK_GREEN), false); - } else { - src.sendSuccess(TranslationUtil.command(CMCommands.LEVEL_NOT_FOUND).withStyle(ChatFormatting.RED), false); - } - - HashMap, Long> levelCounts = new HashMap<>(); - serv.getAllLevels().forEach(sl -> { - final var machineData = DimensionMachineGraph.forDimension(sl); - long numRegistered = machineData.getMachines().count(); - - if(numRegistered > 0) { - src.sendSuccess(TranslationUtil.command(CMCommands.MACHINE_REG_DIM, sl.dimension().toString(), numRegistered), false); - levelCounts.put(sl.dimension(), numRegistered); - } - }); - - long grandTotal = levelCounts.values().stream().reduce(0L, Long::sum); - src.sendSuccess(TranslationUtil.command(CMCommands.MACHINE_REG_TOTAL, grandTotal).withStyle(ChatFormatting.GOLD), false); - - final var roomData = CompactRoomData.get(compactLevel); - - long numRegistered = roomData.stream().count(); - src.sendSuccess(TranslationUtil.command(CMCommands.ROOM_REG_COUNT, numRegistered), false); - - return 0; - } -} diff --git a/src/main/java/dev/compactmods/machines/compat/jei/CompactMachinesJeiPlugin.java b/src/main/java/dev/compactmods/machines/compat/jei/CompactMachinesJeiPlugin.java deleted file mode 100644 index 8defeaa4..00000000 --- a/src/main/java/dev/compactmods/machines/compat/jei/CompactMachinesJeiPlugin.java +++ /dev/null @@ -1,47 +0,0 @@ -package dev.compactmods.machines.compat.jei; - -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.api.core.JeiInfo; -import dev.compactmods.machines.api.room.RoomSize; -import dev.compactmods.machines.i18n.TranslationUtil; -import dev.compactmods.machines.machine.CompactMachineItem; -import dev.compactmods.machines.shrinking.Shrinking; -import dev.compactmods.machines.tunnel.Tunnels; -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 java.util.Arrays; - -@JeiPlugin -public class CompactMachinesJeiPlugin implements IModPlugin { - @Override - public ResourceLocation getPluginUid() { - return new ResourceLocation(Constants.MOD_ID, "main"); - } - - @Override - public void registerRecipes(IRecipeRegistration registration) { - Arrays.stream(RoomSize.values()) - .map(CompactMachineItem::getItemBySize) - .forEach(i -> registration.addIngredientInfo( - new ItemStack(i), - VanillaTypes.ITEM_STACK, - TranslationUtil.jeiInfo(JeiInfo.MACHINE))); - - - registration.addIngredientInfo( - new ItemStack(Shrinking.PERSONAL_SHRINKING_DEVICE.get()), - VanillaTypes.ITEM_STACK, - TranslationUtil.jeiInfo(JeiInfo.SHRINKING_DEVICE)); - } - - @Override - public void registerItemSubtypes(ISubtypeRegistration registration) { - registration.useNbtForSubtypes(Tunnels.ITEM_TUNNEL.get()); - } -} diff --git a/src/main/java/dev/compactmods/machines/compat/theoneprobe/TheOneProbeMain.java b/src/main/java/dev/compactmods/machines/compat/theoneprobe/TheOneProbeMain.java deleted file mode 100644 index 41e275b9..00000000 --- a/src/main/java/dev/compactmods/machines/compat/theoneprobe/TheOneProbeMain.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.compactmods.machines.compat.theoneprobe; - -import dev.compactmods.machines.compat.theoneprobe.overrides.CompactMachineNameOverride; -import dev.compactmods.machines.compat.theoneprobe.providers.CompactMachineProvider; -import dev.compactmods.machines.compat.theoneprobe.providers.TunnelProvider; -import mcjty.theoneprobe.api.ITheOneProbe; - -import java.util.function.Function; - -public class TheOneProbeMain implements Function { - static ITheOneProbe PROBE; - - @Override - public Void apply(Object o) { - PROBE = (ITheOneProbe) o; - PROBE.registerBlockDisplayOverride(new CompactMachineNameOverride()); - PROBE.registerProvider(new CompactMachineProvider()); - PROBE.registerProvider(new TunnelProvider()); - - return null; - } - -} diff --git a/src/main/java/dev/compactmods/machines/compat/theoneprobe/providers/CompactMachineProvider.java b/src/main/java/dev/compactmods/machines/compat/theoneprobe/providers/CompactMachineProvider.java deleted file mode 100644 index a870163c..00000000 --- a/src/main/java/dev/compactmods/machines/compat/theoneprobe/providers/CompactMachineProvider.java +++ /dev/null @@ -1,118 +0,0 @@ -package dev.compactmods.machines.compat.theoneprobe.providers; - -import com.mojang.authlib.GameProfile; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.api.core.Tooltips; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.i18n.TranslationUtil; -import dev.compactmods.machines.machine.CompactMachineBlock; -import dev.compactmods.machines.machine.CompactMachineBlockEntity; -import dev.compactmods.machines.room.data.CompactRoomData; -import dev.compactmods.machines.tunnel.TunnelItem; -import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; -import mcjty.theoneprobe.api.*; -import mcjty.theoneprobe.apiimpl.styles.ItemStyle; -import mcjty.theoneprobe.apiimpl.styles.LayoutStyle; -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; - -import java.util.stream.Collectors; - -public class CompactMachineProvider implements IProbeInfoProvider { - - @Override - public ResourceLocation getID() { - return new ResourceLocation(Constants.MOD_ID, "machine"); - } - - @Override - public void addProbeInfo(ProbeMode probeMode, IProbeInfo info, Player player, Level level, BlockState blockState, IProbeHitData hitData) { - if (!(blockState.getBlock() instanceof CompactMachineBlock mach)) - return; - - final var server = level.getServer(); - if (server == null) - return; - - final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); - - final var te = level.getBlockEntity(hitData.getPos()); - - if (te instanceof CompactMachineBlockEntity machine) { - machine.getConnectedRoom().ifPresentOrElse(room -> { - final var boundTo = TranslationUtil.tooltip(Tooltips.Machines.BOUND_TO, room); - info.text(boundTo); - }, () -> { - MutableComponent newMachine = TranslationUtil - .message(new ResourceLocation(Constants.MOD_ID, "new_machine")) - .withStyle(ChatFormatting.GREEN); - - info.text(newMachine); - }); - - machine.getOwnerUUID().ifPresent(ownerID -> { - // Owner Name - Player owner = level.getPlayerByUUID(ownerID); - if (owner != null) { - GameProfile ownerProfile = owner.getGameProfile(); - MutableComponent ownerText = TranslationUtil - .tooltip(Tooltips.Machines.OWNER, ownerProfile.getName()) - .withStyle(ChatFormatting.GRAY); - - info.text(ownerText); - } - }); - - machine.getConnectedRoom().ifPresent(room -> { - if (compactDim == null) - return; - - final var roomData = CompactRoomData.get(compactDim); - final var graph = TunnelConnectionGraph.forRoom(compactDim, room); - - final var applied = graph.getTypesForSide(machine.getLevelPosition(), hitData.getSideHit()) - .collect(Collectors.toSet()); - - switch (probeMode) { - case NORMAL: - final var group = info.horizontal(new LayoutStyle() - .alignment(ElementAlignment.ALIGN_TOPLEFT) - .padding(0) - .spacing(0)); - - applied.forEach(tn -> { - ItemStack item = TunnelItem.createStack(tn); - group.item(item, new ItemStyle().bounds(8, 8)); - }); - break; - - case EXTENDED: - final var tgg = info.vertical(new LayoutStyle().alignment(ElementAlignment.ALIGN_TOPLEFT)); - applied.forEach(tn -> { - final var tg = tgg.horizontal(new LayoutStyle() - .alignment(ElementAlignment.ALIGN_CENTER) - .hPadding(2).vPadding(2) - .spacing(0)); - - ItemStack item = TunnelItem.createStack(tn); - tg.item(item, new ItemStyle().bounds(8, 8)); - tg.itemLabel(item); - }); - break; - } - - final var rd = roomData.forRoom(room); - rd.ifPresent(r -> { -// final var el = new RoomPreviewElement(new RoomPreview(room, r.getSize())); -// el.loadBlocks(server, r); -// info.element(el); - }); - }); - } - } -} diff --git a/src/main/java/dev/compactmods/machines/config/EnableVanillaRecipesConfigCondition.java b/src/main/java/dev/compactmods/machines/config/EnableVanillaRecipesConfigCondition.java deleted file mode 100644 index 6e922b7c..00000000 --- a/src/main/java/dev/compactmods/machines/config/EnableVanillaRecipesConfigCondition.java +++ /dev/null @@ -1,41 +0,0 @@ -package dev.compactmods.machines.config; - -import com.google.gson.JsonObject; -import dev.compactmods.machines.api.core.Constants; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.common.crafting.conditions.ICondition; -import net.minecraftforge.common.crafting.conditions.IConditionSerializer; - -public class EnableVanillaRecipesConfigCondition implements ICondition { - - public static final ResourceLocation ID = new ResourceLocation(Constants.MOD_ID, "config_enable_vanilla_recipes"); - - @Override - public ResourceLocation getID() { - return ID; - } - - @Override - public boolean test(IContext ctx) { - return CommonConfig.ENABLE_VANILLA_RECIPES.get(); - } - - public static class Serializer implements IConditionSerializer { - - public static final Serializer INSTANCE = new Serializer(); - - @Override - public void write(JsonObject json, EnableVanillaRecipesConfigCondition value) { - } - - @Override - public EnableVanillaRecipesConfigCondition read(JsonObject json) { - return new EnableVanillaRecipesConfigCondition(); - } - - @Override - public ResourceLocation getID() { - return EnableVanillaRecipesConfigCondition.ID; - } - } -} diff --git a/src/main/java/dev/compactmods/machines/dimension/MissingDimensionException.java b/src/main/java/dev/compactmods/machines/dimension/MissingDimensionException.java deleted file mode 100644 index 606d2189..00000000 --- a/src/main/java/dev/compactmods/machines/dimension/MissingDimensionException.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.compactmods.machines.dimension; - -public class MissingDimensionException extends Throwable { - public MissingDimensionException() { - super("Could not find compact machine dimension. This is likely a bug; please report it."); - } - - public MissingDimensionException(String msg) { - super(msg); - } -} diff --git a/src/main/java/dev/compactmods/machines/graph/DimensionGraphNode.java b/src/main/java/dev/compactmods/machines/graph/DimensionGraphNode.java deleted file mode 100644 index 0d222409..00000000 --- a/src/main/java/dev/compactmods/machines/graph/DimensionGraphNode.java +++ /dev/null @@ -1,25 +0,0 @@ -package dev.compactmods.machines.graph; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.level.Level; - -public record DimensionGraphNode(ResourceKey dimension) implements IGraphNode { - - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - ResourceKey.codec(Registry.DIMENSION_REGISTRY).fieldOf("dim").forGetter(DimensionGraphNode::dimension) - ).apply(i, DimensionGraphNode::new)); - - @Override - public String toString() { - return "DimensionGraphNode[" + - "dimension=" + dimension + ']'; - } - - @Override - public IGraphNodeType getType() { - return Graph.DIM_NODE.get(); - } -} diff --git a/src/main/java/dev/compactmods/machines/graph/Graph.java b/src/main/java/dev/compactmods/machines/graph/Graph.java deleted file mode 100644 index 710d314b..00000000 --- a/src/main/java/dev/compactmods/machines/graph/Graph.java +++ /dev/null @@ -1,34 +0,0 @@ -package dev.compactmods.machines.graph; - -import dev.compactmods.machines.core.Registries; -import net.minecraftforge.registries.IForgeRegistry; -import net.minecraftforge.registries.RegistryBuilder; -import net.minecraftforge.registries.RegistryObject; - -import java.util.function.Supplier; - -public class Graph { - - public static final Supplier> NODE_TYPE_REG = Registries.NODE_TYPES.makeRegistry(RegistryBuilder::new); - public static final Supplier> EDGE_TYPE_REG = Registries.EDGE_TYPES.makeRegistry(RegistryBuilder::new); - - - public static final RegistryObject MACH_NODE = Registries.NODE_TYPES.register("machine", () -> GraphNodeType.MACHINE); - public static final RegistryObject DIM_NODE = Registries.NODE_TYPES.register("dimension", () -> GraphNodeType.DIMENSION); - public static final RegistryObject ROOM_NODE = Registries.NODE_TYPES.register("room", () -> GraphNodeType.ROOM); - - public static final RegistryObject TUNNEL_NODE = Registries.NODE_TYPES.register("tunnel", () -> GraphNodeType.TUNNEL); - public static final RegistryObject TUNNEL_TYPE_NODE = Registries.NODE_TYPES.register("tunnel_type", () -> GraphNodeType.TUNNEL_TYPE); - - public static final RegistryObject ROOM_UPGRADE_NODE = Registries.NODE_TYPES.register("room_upgrade", () -> GraphNodeType.ROOM_UPGRADE); - - public static final RegistryObject MACHINE_LINK = Registries.EDGE_TYPES.register("machine_link", () -> GraphEdgeType.MACHINE_LINK); - - // Tunnel edges - public static final RegistryObject TUNNEL_TYPE = Registries.EDGE_TYPES.register("tunnel_type", () -> GraphEdgeType.TUNNEL_TYPE); - public static final RegistryObject TUNNEL_MACHINE_LINK = Registries.EDGE_TYPES.register("tunnel_machine", () -> GraphEdgeType.TUNNEL_MACHINE); - - public static void prepare() { - - } -} diff --git a/src/main/java/dev/compactmods/machines/graph/GraphEdgeType.java b/src/main/java/dev/compactmods/machines/graph/GraphEdgeType.java deleted file mode 100644 index 1f19c1b8..00000000 --- a/src/main/java/dev/compactmods/machines/graph/GraphEdgeType.java +++ /dev/null @@ -1,26 +0,0 @@ -package dev.compactmods.machines.graph; - -import com.mojang.serialization.Codec; -import dev.compactmods.machines.machine.graph.MachineRoomEdge; -import dev.compactmods.machines.tunnel.graph.TunnelMachineEdge; -import dev.compactmods.machines.tunnel.graph.TunnelTypeEdge; -import dev.compactmods.machines.upgrade.graph.RoomUpgradeConnection; - -public enum GraphEdgeType implements IGraphEdgeType { - TUNNEL_TYPE(TunnelTypeEdge.CODEC), - MACHINE_LINK(MachineRoomEdge.CODEC), - TUNNEL_MACHINE(TunnelMachineEdge.CODEC), - ROOM_UPGRADE(RoomUpgradeConnection.CODEC); - - private final Codec codec; - - @SuppressWarnings("unchecked") - GraphEdgeType(Codec codec) { - this.codec = (Codec) codec; - } - - @Override - public Codec codec() { - return codec; - } -} diff --git a/src/main/java/dev/compactmods/machines/graph/GraphNodeBase.java b/src/main/java/dev/compactmods/machines/graph/GraphNodeBase.java deleted file mode 100644 index 391e29ba..00000000 --- a/src/main/java/dev/compactmods/machines/graph/GraphNodeBase.java +++ /dev/null @@ -1,4 +0,0 @@ -package dev.compactmods.machines.graph; - -public abstract class GraphNodeBase implements IGraphNode { -} diff --git a/src/main/java/dev/compactmods/machines/graph/GraphNodeType.java b/src/main/java/dev/compactmods/machines/graph/GraphNodeType.java deleted file mode 100644 index 34b780bc..00000000 --- a/src/main/java/dev/compactmods/machines/graph/GraphNodeType.java +++ /dev/null @@ -1,30 +0,0 @@ -package dev.compactmods.machines.graph; - -import com.mojang.serialization.Codec; -import dev.compactmods.machines.machine.graph.CompactMachineNode; -import dev.compactmods.machines.room.graph.CompactMachineRoomNode; -import dev.compactmods.machines.tunnel.graph.TunnelNode; -import dev.compactmods.machines.tunnel.graph.TunnelTypeNode; -import dev.compactmods.machines.upgrade.graph.RoomUpgradeGraphNode; - -public enum GraphNodeType implements IGraphNodeType { - MACHINE(CompactMachineNode.CODEC), - TUNNEL(TunnelNode.CODEC), - ROOM(CompactMachineRoomNode.CODEC), - TUNNEL_TYPE(TunnelTypeNode.CODEC), - DIMENSION(DimensionGraphNode.CODEC), - ROOM_UPGRADE(RoomUpgradeGraphNode.CODEC); - - private final Codec codec; - - @SuppressWarnings("unchecked") - GraphNodeType(Codec codec) { - this.codec = (Codec) codec; - } - - @Override - @SuppressWarnings("unchecked") - public Codec codec() { - return codec; - } -} diff --git a/src/main/java/dev/compactmods/machines/graph/IGraphEdge.java b/src/main/java/dev/compactmods/machines/graph/IGraphEdge.java deleted file mode 100644 index 0ede60fb..00000000 --- a/src/main/java/dev/compactmods/machines/graph/IGraphEdge.java +++ /dev/null @@ -1,7 +0,0 @@ -package dev.compactmods.machines.graph; - -import org.jetbrains.annotations.NotNull; - -public interface IGraphEdge { - @NotNull IGraphEdgeType getEdgeType(); -} diff --git a/src/main/java/dev/compactmods/machines/graph/IGraphEdgeType.java b/src/main/java/dev/compactmods/machines/graph/IGraphEdgeType.java deleted file mode 100644 index a89d1864..00000000 --- a/src/main/java/dev/compactmods/machines/graph/IGraphEdgeType.java +++ /dev/null @@ -1,7 +0,0 @@ -package dev.compactmods.machines.graph; - -import com.mojang.serialization.Codec; - -public interface IGraphEdgeType { - Codec codec(); -} diff --git a/src/main/java/dev/compactmods/machines/graph/IGraphNode.java b/src/main/java/dev/compactmods/machines/graph/IGraphNode.java deleted file mode 100644 index 09c25cd2..00000000 --- a/src/main/java/dev/compactmods/machines/graph/IGraphNode.java +++ /dev/null @@ -1,5 +0,0 @@ -package dev.compactmods.machines.graph; - -public interface IGraphNode { - IGraphNodeType getType(); -} diff --git a/src/main/java/dev/compactmods/machines/graph/IGraphNodeType.java b/src/main/java/dev/compactmods/machines/graph/IGraphNodeType.java deleted file mode 100644 index 65f137ba..00000000 --- a/src/main/java/dev/compactmods/machines/graph/IGraphNodeType.java +++ /dev/null @@ -1,8 +0,0 @@ -package dev.compactmods.machines.graph; - -import com.mojang.serialization.Codec; - -public interface IGraphNodeType { - - Codec codec(); -} diff --git a/src/main/java/dev/compactmods/machines/i18n/TranslationUtil.java b/src/main/java/dev/compactmods/machines/i18n/TranslationUtil.java deleted file mode 100644 index fd41b1e0..00000000 --- a/src/main/java/dev/compactmods/machines/i18n/TranslationUtil.java +++ /dev/null @@ -1,69 +0,0 @@ -package dev.compactmods.machines.i18n; - -import net.minecraft.Util; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.resources.ResourceLocation; - -public abstract class TranslationUtil { - - public static String messageId(ResourceLocation message) { - return Util.makeDescriptionId("message", message); - } - - public static MutableComponent message(ResourceLocation message) { - return Component.translatable(messageId(message)); - } - - public static MutableComponent message(ResourceLocation message, Object... params) { - return Component.translatable(messageId(message), params); - } - - public static String tooltipId(ResourceLocation tooltip) { - return Util.makeDescriptionId("tooltip", tooltip); - } - - public static MutableComponent tooltip(ResourceLocation tooltip) { - return Component.translatable(tooltipId(tooltip)); - } - - public static MutableComponent tooltip(ResourceLocation tooltip, Object... params) { - return Component.translatable(tooltipId(tooltip), params); - } - - public static String advId(ResourceLocation tooltip) { - return Util.makeDescriptionId("advancement", tooltip); - } - - public static MutableComponent advancement(ResourceLocation advancement) { - return Component.translatable(advId(advancement)); - } - - public static MutableComponent advancementTitle(ResourceLocation advancement) { - return advancement(advancement); - } - - public static MutableComponent advancementDesc(ResourceLocation advancement) { - return Component.translatable(Util.makeDescriptionId("advancement", advancement) + ".desc"); - } - - public static MutableComponent jeiInfo(ResourceLocation jei) { - return Component.translatable(Util.makeDescriptionId("jei", jei)); - } - - public static String commandId(ResourceLocation s) { - return Util.makeDescriptionId("command", s); - } - - public static MutableComponent command(ResourceLocation s) { - return Component.translatable(commandId(s)); - } - - public static MutableComponent command(ResourceLocation s, Object... params) { - return Component.translatable(commandId(s), params); - } - - public static String tunnelId(ResourceLocation id) { - return "item." + id.getNamespace() + ".tunnels." + id.getPath().replace('/', '.'); - } -} diff --git a/src/main/java/dev/compactmods/machines/location/LevelBlockPosition.java b/src/main/java/dev/compactmods/machines/location/LevelBlockPosition.java deleted file mode 100644 index 9f38c34e..00000000 --- a/src/main/java/dev/compactmods/machines/location/LevelBlockPosition.java +++ /dev/null @@ -1,172 +0,0 @@ -package dev.compactmods.machines.location; - -import javax.annotation.Nonnull; -import java.util.Objects; -import java.util.Optional; -import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.location.IDimensionalBlockPosition; -import dev.compactmods.machines.api.codec.CodecExtensions; -import dev.compactmods.machines.util.LocationUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Registry; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.nbt.Tag; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.util.INBTSerializable; - -public class LevelBlockPosition implements INBTSerializable, IDimensionalBlockPosition { - - private ResourceKey dimension; - private Vec3 position; - private Vec3 rotation; - - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - ResourceKey.codec(Registry.DIMENSION_REGISTRY).fieldOf("dim").forGetter(LevelBlockPosition::getDimension), - CodecExtensions.VECTOR3D.fieldOf("pos").forGetter(LevelBlockPosition::getExactPosition), - CodecExtensions.VECTOR3D.optionalFieldOf("rot", Vec3.ZERO).forGetter(x -> x.rotation) - ).apply(i, LevelBlockPosition::new)); - - private LevelBlockPosition() { - } - - public LevelBlockPosition(IDimensionalBlockPosition base) { - this.dimension = base.dimensionKey(); - this.position = base.getExactPosition(); - this.rotation = Vec3.ZERO; - } - - public LevelBlockPosition(ResourceKey world, BlockPos positionBlock) { - this(world, Vec3.ZERO, Vec3.ZERO); - this.position = new Vec3(positionBlock.getX(), positionBlock.getY(), positionBlock.getZ()); - this.rotation = Vec3.ZERO; - } - - public LevelBlockPosition(ResourceKey world, Vec3 positionBlock) { - this(world, positionBlock, Vec3.ZERO); - this.dimension = world; - this.rotation = Vec3.ZERO; - } - - public LevelBlockPosition(ResourceKey dim, Vec3 pos, Vec3 rotation) { - this.dimension = dim; - this.position = pos; - this.rotation = rotation; - } - - public static LevelBlockPosition fromEntity(LivingEntity entity) { - return new LevelBlockPosition(entity.level.dimension(), entity.position()); - } - - public ServerLevel level(@Nonnull MinecraftServer server) { - return server.getLevel(this.dimension); - } - - public BlockState state(MinecraftServer server) { - final var level = level(server); - return level.getBlockState(getBlockPosition()); - } - - @Override - public IDimensionalBlockPosition relative(Direction direction) { - return new LevelBlockPosition(this.dimension, this.position.add(direction.getStepX(), direction.getStepY(), direction.getStepZ())); - } - - public boolean isLoaded(MinecraftServer server) { - final var level = level(server); - return level.isLoaded(LocationUtil.vectorToBlockPos(position)); - } - - public static LevelBlockPosition fromNBT(CompoundTag nbt) { - LevelBlockPosition dp = new LevelBlockPosition(); - dp.deserializeNBT(nbt); - - return dp; - } - - @Override - public CompoundTag serializeNBT() { - if(this.rotation == null) - this.rotation = Vec3.ZERO; - - DataResult nbt = CODEC.encodeStart(NbtOps.INSTANCE, this); - return (CompoundTag) nbt.result().orElse(null); - } - - @Override - public void deserializeNBT(CompoundTag nbt) { - Optional dimensionalPosition = CODEC - .parse(NbtOps.INSTANCE, nbt) - .resultOrPartial(CompactMachines.LOGGER::error); - - dimensionalPosition.ifPresent(dp -> { - this.dimension = dp.dimension; - this.position = dp.position; - this.rotation = dp.rotation; - }); - } - - public ResourceKey getDimension() { - return this.dimension; - } - - public Optional getRotation() { - return Optional.of(this.rotation); - } - - public BlockPos getBlockPosition() { - return new BlockPos(position.x, position.y, position.z); - } - - @Override - public Vec3 getExactPosition() { - return this.position; - } - - @Override - public ResourceKey dimensionKey() { - return dimension; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - - if (o == null || getClass() != o.getClass()) - return false; - - LevelBlockPosition that = (LevelBlockPosition) o; - if (!dimension.equals(that.dimension)) - return false; - - if (!position.equals(that.position)) - return false; - - return rotation.equals(that.rotation); - } - - @Override - public int hashCode() { - return Objects.hash(dimension, position, rotation); - } - - @Override - public String toString() { - return "DimensionalPosition{" + - "d=" + dimension + - ", p=" + position + - ", r=" + rotation + - '}'; - } -} diff --git a/src/main/java/dev/compactmods/machines/location/PreciseDimensionalPosition.java b/src/main/java/dev/compactmods/machines/location/PreciseDimensionalPosition.java deleted file mode 100644 index fb04c2a8..00000000 --- a/src/main/java/dev/compactmods/machines/location/PreciseDimensionalPosition.java +++ /dev/null @@ -1,113 +0,0 @@ -package dev.compactmods.machines.location; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.codec.CodecExtensions; -import dev.compactmods.machines.api.location.IDimensionalPosition; -import dev.compactmods.machines.util.MathUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.Vec3; - -import java.util.Objects; -import java.util.Optional; - -public final class PreciseDimensionalPosition implements IDimensionalPosition { - - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - ResourceKey.codec(Registry.DIMENSION_REGISTRY).fieldOf("dim").forGetter(PreciseDimensionalPosition::dimension), - CodecExtensions.VECTOR3D.fieldOf("pos").forGetter(PreciseDimensionalPosition::position), - CodecExtensions.VECTOR3D.optionalFieldOf("rot", Vec3.ZERO).forGetter(x -> x.rotation) - ).apply(i, PreciseDimensionalPosition::new)); - - private final ResourceKey dimension; - private final Vec3 position; - private final Vec3 rotation; - - public PreciseDimensionalPosition(ResourceKey dimension, Vec3 position) { - this.dimension = dimension; - this.position = position; - this.rotation = Vec3.ZERO; - } - - public PreciseDimensionalPosition(ResourceKey dimension, Vec3 position, Vec3 rotation) { - this.dimension = dimension; - this.position = position; - this.rotation = rotation; - } - - public static PreciseDimensionalPosition fromPlayer(Player player) { - return new PreciseDimensionalPosition(player.level.dimension(), player.position(), player.getLookAngle()); - } - - @Override - public BlockPos getBlockPosition() { - return new BlockPos(position.x, position.y, position.z); - } - - @Override - public Vec3 getExactPosition() { - return position; - } - - public Optional rotation() { - return Optional.ofNullable(rotation); - } - - @Override - public ResourceKey dimensionKey() { - return dimension; - } - - @Override - public ServerLevel level(MinecraftServer server) { - return server.getLevel(dimension); - } - - @Override - public IDimensionalPosition relative(Direction direction) { - final var newPos = position.add(direction.getStepX(), direction.getStepY(), direction.getStepZ()); - return new PreciseDimensionalPosition(dimension, newPos); - } - - @Override - public Optional getRotation() { - return Optional.empty(); - } - - public ResourceKey dimension() { - return dimension; - } - - public Vec3 position() { - return position; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - var that = (PreciseDimensionalPosition) obj; - return Objects.equals(this.dimension, that.dimension) && - Objects.equals(this.position, that.position); - } - - @Override - public int hashCode() { - return Objects.hash(dimension, position); - } - - @Override - public String toString() { - return "PreciseDimensionalPosition[" + - "dimension=" + dimension + ", " + - "position=" + position + ']'; - } - -} diff --git a/src/main/java/dev/compactmods/machines/location/SimpleTeleporter.java b/src/main/java/dev/compactmods/machines/location/SimpleTeleporter.java deleted file mode 100644 index 9b74d92b..00000000 --- a/src/main/java/dev/compactmods/machines/location/SimpleTeleporter.java +++ /dev/null @@ -1,22 +0,0 @@ -package dev.compactmods.machines.location; - -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.util.ITeleporter; - -import java.util.function.Function; - -public record SimpleTeleporter(Vec3 pos) implements ITeleporter { - - public static SimpleTeleporter to(Vec3 pos) { - return new SimpleTeleporter(pos); - } - - @Override - public Entity placeEntity(Entity entity, ServerLevel currentWorld, ServerLevel destWorld, float yaw, Function repositionEntity) { - entity = repositionEntity.apply(false); - entity.teleportTo(pos.x, pos.y, pos.z); - return entity; - } -} diff --git a/src/main/java/dev/compactmods/machines/machine/CompactMachineBlock.java b/src/main/java/dev/compactmods/machines/machine/CompactMachineBlock.java deleted file mode 100644 index a776364b..00000000 --- a/src/main/java/dev/compactmods/machines/machine/CompactMachineBlock.java +++ /dev/null @@ -1,348 +0,0 @@ -package dev.compactmods.machines.machine; - -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.core.CMTags; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.api.core.Messages; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.api.room.RoomSize; -import dev.compactmods.machines.config.ServerConfig; -import dev.compactmods.machines.dimension.MissingDimensionException; -import dev.compactmods.machines.i18n.TranslationUtil; -import dev.compactmods.machines.location.LevelBlockPosition; -import dev.compactmods.machines.location.PreciseDimensionalPosition; -import dev.compactmods.machines.machine.graph.DimensionMachineGraph; -import dev.compactmods.machines.room.RoomCapabilities; -import dev.compactmods.machines.room.Rooms; -import dev.compactmods.machines.room.exceptions.NonexistentRoomException; -import dev.compactmods.machines.room.history.PlayerRoomHistoryItem; -import dev.compactmods.machines.room.menu.MachineRoomMenu; -import dev.compactmods.machines.shrinking.Shrinking; -import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; -import dev.compactmods.machines.upgrade.MachineRoomUpgrades; -import dev.compactmods.machines.upgrade.RoomUpgradeItem; -import dev.compactmods.machines.upgrade.RoomUpgradeManager; -import dev.compactmods.machines.util.PlayerUtil; -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Registry; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.tags.TagKey; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.NameTagItem; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.HitResult; -import net.minecraftforge.network.NetworkHooks; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.Optional; -import java.util.UUID; - -public class CompactMachineBlock extends Block implements EntityBlock { - - public static final TagKey TAG = TagKey.create(Registry.BLOCK_REGISTRY, new ResourceLocation(Constants.MOD_ID, "machine")); - - private final RoomSize size; - - public CompactMachineBlock(RoomSize size, BlockBehaviour.Properties props) { - super(props); - this.size = size; - } - - @Override - @SuppressWarnings("deprecation") - public float getDestroyProgress(BlockState state, Player player, BlockGetter worldIn, BlockPos pos) { - CompactMachineBlockEntity tile = (CompactMachineBlockEntity) worldIn.getBlockEntity(pos); - float normalHardness = super.getDestroyProgress(state, player, worldIn, pos); - - if (tile == null) - return normalHardness; - - boolean hasPlayers = tile.hasPlayersInside(); - - - // If there are players inside, check config for break handling - if (hasPlayers) { - EnumMachinePlayersBreakHandling hand = ServerConfig.MACHINE_PLAYER_BREAK_HANDLING.get(); - switch (hand) { - case UNBREAKABLE: - return 0; - - case OWNER: - Optional ownerUUID = tile.getOwnerUUID(); - return ownerUUID - .map(uuid -> player.getUUID() == uuid ? normalHardness : 0) - .orElse(normalHardness); - - case ANYONE: - return normalHardness; - } - } - - // No players inside - let anyone break it - return normalHardness; - } - - @Override - public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, @Nullable Direction side) { - return false; - } - - @Override - @SuppressWarnings("deprecation") - public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { - // TODO Redstone out tunnels - return 0; - } - - @Override - @SuppressWarnings("deprecation") - @ParametersAreNonnullByDefault - public void neighborChanged(BlockState state, Level world, BlockPos pos, Block changedBlock, BlockPos changedPos, boolean isMoving) { - super.neighborChanged(state, world, pos, changedBlock, changedPos, isMoving); - - if (world.isClientSide) - return; - - ServerLevel serverWorld = (ServerLevel) world; - - if (serverWorld.getBlockEntity(pos) instanceof CompactMachineBlockEntity machine) { - ServerLevel compactWorld = serverWorld.getServer().getLevel(CompactDimension.LEVEL_KEY); - if (compactWorld == null) { - CompactMachines.LOGGER.warn("Warning: Compact Dimension was null! Cannot fetch internal state for machine neighbor change listener."); - } - - // TODO - Send notification to dimension tunnel listeners (API) - } - } - - public static Block getBySize(RoomSize size) { - return switch (size) { - case TINY -> Machines.MACHINE_BLOCK_TINY.get(); - case SMALL -> Machines.MACHINE_BLOCK_SMALL.get(); - case NORMAL -> Machines.MACHINE_BLOCK_NORMAL.get(); - case LARGE -> Machines.MACHINE_BLOCK_LARGE.get(); - case GIANT -> Machines.MACHINE_BLOCK_GIANT.get(); - case MAXIMUM -> Machines.MACHINE_BLOCK_MAXIMUM.get(); - }; - - } - - @Override - public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) { - Block given = getBySize(this.size); - ItemStack stack = new ItemStack(given, 1); - - if (world.getBlockEntity(pos) instanceof CompactMachineBlockEntity tile) { - tile.getConnectedRoom().ifPresent(room -> { - CompactMachineItem.setRoom(stack, room); - }); - } - - return stack; - } - - @Override - public void setPlacedBy(Level worldIn, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { - - if (worldIn.isClientSide()) - return; - - if (worldIn.getBlockEntity(pos) instanceof CompactMachineBlockEntity tile && worldIn instanceof ServerLevel sl) { - // TODO - Custom machine names - if (!stack.hasTag()) - return; - - CompoundTag nbt = stack.getTag(); - if (nbt == null) - return; - - // Machine was previously bound to a room - make a new binding post-place - CompactMachineItem.getRoom(stack).ifPresent(room -> { - final var g = DimensionMachineGraph.forDimension(sl); - g.connectMachineToRoom(pos, room); - tile.syncConnectedRoom(); - }); - } - } - - @Override - @SuppressWarnings("deprecation") - public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) { - if (level.isClientSide()) - return InteractionResult.SUCCESS; - - MinecraftServer server = level.getServer(); - ItemStack mainItem = player.getMainHandItem(); - - if (mainItem.isEmpty() && level.getBlockEntity(pos) instanceof CompactMachineBlockEntity machine) { - if (state.getBlock() instanceof CompactMachineBlock cmBlock) { - machine.getConnectedRoom().ifPresent(room -> { - var size = cmBlock.getSize(); - try { - final var roomName = Rooms.getRoomName(server, room); - NetworkHooks.openScreen((ServerPlayer) player, MachineRoomMenu.makeProvider(server, room, machine.getLevelPosition()), (buf) -> { - buf.writeBlockPos(pos); - buf.writeWithCodec(LevelBlockPosition.CODEC, machine.getLevelPosition()); - buf.writeChunkPos(room); - roomName.ifPresentOrElse(name -> { - buf.writeBoolean(true); - buf.writeUtf(name); - }, () -> { - buf.writeBoolean(false); - }); - }); - } catch (NonexistentRoomException e) { - e.printStackTrace(); - } - }); - } - } - - // TODO - Item tags instead of direct item reference here - if (mainItem.getItem() == Shrinking.PERSONAL_SHRINKING_DEVICE.get()) { - // Try teleport to compact machine dimension - if (level.getBlockEntity(pos) instanceof CompactMachineBlockEntity tile) { - tile.getConnectedRoom().ifPresentOrElse(room -> { - try { - PlayerUtil.teleportPlayerIntoMachine(level, player, pos); - } catch (MissingDimensionException e) { - e.printStackTrace(); - } - }, () -> createAndEnterRoom(player, server, tile)); - } - } - - // Try and pull the name off the nametag and apply it to the room - if (mainItem.getItem() instanceof NameTagItem && mainItem.hasCustomHoverName()) { - if (level.getBlockEntity(pos) instanceof CompactMachineBlockEntity tile) { - tile.getConnectedRoom().ifPresentOrElse(room -> { - Rooms.getOwner(server, room).ifPresent(profile -> { - try { - if (player.getUUID().equals(profile.getId())) { - final var newName = mainItem.getHoverName().getString(120); - Rooms.updateName(server, room, newName); - } else { - player.displayClientMessage(TranslationUtil.message(Messages.CANNOT_RENAME_NOT_OWNER, profile.getName()), true); - } - } catch (NonexistentRoomException e) { - throw new RuntimeException(e); - } - }); - }, () -> { - CompactMachines.LOGGER.warn("Tried to apply upgrade to a 'claimed' machine, but there was no owner data attached."); - }); - } - } - - // Upgrade Item - if (mainItem.is(CMTags.ROOM_UPGRADE_ITEM)) { - final var reg = MachineRoomUpgrades.REGISTRY.get(); - if(mainItem.getItem() instanceof RoomUpgradeItem upItem) { - if (level.getBlockEntity(pos) instanceof CompactMachineBlockEntity tile) { - tile.getConnectedRoom().ifPresent(room -> { - Rooms.getOwner(server, room).ifPresent(prof -> { - if (!player.getUUID().equals(prof.getId())) { - player.displayClientMessage(TranslationUtil.message(Messages.NOT_ROOM_OWNER, prof.getName()), true); - return; - } - - final var upg = upItem.getUpgradeType(); - final var manager = RoomUpgradeManager.get(server.getLevel(CompactDimension.LEVEL_KEY)); - - if (manager.hasUpgrade(room, upg)) { - player.displayClientMessage(TranslationUtil.message(Messages.ALREADY_HAS_UPGRADE), true); - } else { - final var added = manager.addUpgrade(upg, room); - - if (added) { - player.displayClientMessage(TranslationUtil.message(Messages.UPGRADE_APPLIED) - .withStyle(ChatFormatting.DARK_GREEN), true); - } else { - player.displayClientMessage(TranslationUtil.message(Messages.UPGRADE_ADD_FAILED) - .withStyle(ChatFormatting.DARK_RED), true); - } - } - }); - }); - } - } - } - - return InteractionResult.SUCCESS; - } - - private void createAndEnterRoom(Player player, MinecraftServer server, CompactMachineBlockEntity tile) { - try { - final var newRoomPos = Rooms.createNew(server, size, player.getUUID()); - tile.setConnectedRoom(newRoomPos); - - PlayerUtil.teleportPlayerIntoRoom(server, player, newRoomPos, true); - - // Mark the player as inside the machine, set external spawn, and yeet - player.getCapability(RoomCapabilities.ROOM_HISTORY).ifPresent(hist -> { - var entry = PreciseDimensionalPosition.fromPlayer(player); - hist.addHistory(new PlayerRoomHistoryItem(entry, tile.getLevelPosition())); - }); - } catch (MissingDimensionException | NonexistentRoomException e) { - CompactMachines.LOGGER.error("Error occurred while generating new room and machine info for first player entry.", e); - } - } - - public RoomSize getSize() { - return this.size; - } - - @Nullable - @Override - public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { - return new CompactMachineBlockEntity(pos, state); - } - - @Override - @SuppressWarnings("deprecation") - public void onRemove(BlockState oldState, Level level, BlockPos pos, BlockState newState, boolean a) { - MinecraftServer server = level.getServer(); - if (level.isClientSide || server == null) { - super.onRemove(oldState, level, pos, newState, a); - return; - } - - if (level instanceof ServerLevel sl) { - final var serv = sl.getServer(); - final var compactDim = serv.getLevel(CompactDimension.LEVEL_KEY); - - if (level.getBlockEntity(pos) instanceof CompactMachineBlockEntity entity) { - entity.getConnectedRoom().ifPresent(room -> { - final var dimGraph = DimensionMachineGraph.forDimension(sl); - dimGraph.disconnect(pos); - - if (compactDim == null) - return; - - final var tunnels = TunnelConnectionGraph.forRoom(compactDim, room); - tunnels.unregister(pos); - }); - } - } - - super.onRemove(oldState, level, pos, newState, a); - } -} diff --git a/src/main/java/dev/compactmods/machines/machine/CompactMachineBlockEntity.java b/src/main/java/dev/compactmods/machines/machine/CompactMachineBlockEntity.java deleted file mode 100644 index 0353e947..00000000 --- a/src/main/java/dev/compactmods/machines/machine/CompactMachineBlockEntity.java +++ /dev/null @@ -1,259 +0,0 @@ -package dev.compactmods.machines.machine; - -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.api.machine.MachineNbt; -import dev.compactmods.machines.location.LevelBlockPosition; -import dev.compactmods.machines.dimension.MissingDimensionException; -import dev.compactmods.machines.machine.graph.DimensionMachineGraph; -import dev.compactmods.machines.machine.graph.CompactMachineNode; -import dev.compactmods.machines.machine.graph.legacy.LegacyMachineConnections; -import dev.compactmods.machines.room.graph.CompactMachineRoomNode; -import dev.compactmods.machines.tunnel.TunnelWallEntity; -import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.lang.ref.WeakReference; -import java.util.Optional; -import java.util.UUID; - -public class CompactMachineBlockEntity extends BlockEntity { - private static final String ROOM_NBT = "room_pos"; - private static final String LEGACY_MACH_ID = "machine_id"; - - public long nextSpawnTick = 0; - - protected UUID owner; - protected String schema; - protected boolean locked = false; - private ChunkPos roomChunk; - private int legacyMachineId = -1; - - private WeakReference graphNode; - private WeakReference roomNode; - - public CompactMachineBlockEntity(BlockPos pos, BlockState state) { - super(Machines.MACHINE_TILE_ENTITY.get(), pos, state); - } - - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { - if (level instanceof ServerLevel sl) { - return getConnectedRoom().map(roomId -> { - try { - final var serv = sl.getServer(); - final var compactDim = serv.getLevel(CompactDimension.LEVEL_KEY); - - final var graph = TunnelConnectionGraph.forRoom(compactDim, roomId); - - final var supportingTunnels = graph.getTunnelsSupporting(getLevelPosition(), side, cap); - final var firstSupported = supportingTunnels.findFirst(); - if (firstSupported.isEmpty()) - return super.getCapability(cap, side); - - if (compactDim == null) - throw new MissingDimensionException(); - - if (compactDim.getBlockEntity(firstSupported.get()) instanceof TunnelWallEntity tunnel) { - return tunnel.getTunnelCapability(cap, side); - } else { - return super.getCapability(cap, side); - } - } catch (MissingDimensionException e) { - CompactMachines.LOGGER.fatal(e); - return super.getCapability(cap, side); - } - }).orElse(super.getCapability(cap, side)); - } - - return super.getCapability(cap, side); - } - - @Override - public void onLoad() { - super.onLoad(); - if (this.legacyMachineId != -1) - this.updateLegacyData(); - - this.syncConnectedRoom(); - } - - @Override - public void load(@Nonnull CompoundTag nbt) { - super.load(nbt); - - // TODO customName = nbt.getString("CustomName"); - if (nbt.contains(MachineNbt.OWNER)) { - owner = nbt.getUUID(MachineNbt.OWNER); - } else { - owner = null; - } - - if (nbt.contains(LEGACY_MACH_ID)) { - this.legacyMachineId = nbt.getInt(LEGACY_MACH_ID); - } - - nextSpawnTick = nbt.getLong("spawntick"); - if (nbt.contains("schema")) { - schema = nbt.getString("schema"); - } else { - schema = null; - } - - if (nbt.contains("locked")) { - locked = nbt.getBoolean("locked"); - } else { - locked = false; - } - } - - private void updateLegacyData() { - if (level instanceof ServerLevel sl) { - try { - final var legacy = LegacyMachineConnections.get(sl.getServer()); - - DimensionMachineGraph graph = DimensionMachineGraph.forDimension(sl); - graph.addMachine(worldPosition); - - final ChunkPos oldRoom = legacy.getConnectedRoom(this.legacyMachineId); - CompactMachines.LOGGER.info(CompactMachines.CONN_MARKER, "Rebinding machine {} ({}/{}) to room {}", legacyMachineId, worldPosition, level.dimension(), roomChunk); - - this.roomChunk = oldRoom; - graph.connectMachineToRoom(worldPosition, roomChunk); - } catch (MissingDimensionException e) { - CompactMachines.LOGGER.fatal(CompactMachines.CONN_MARKER, "Could not load connection info from legacy data; machine at {} in dimension {} will be unmapped.", worldPosition, level.dimension()); - } - } - } - - @Override - protected void saveAdditional(CompoundTag nbt) { - // nbt.putString("CustomName", customName.getString()); - - if (owner != null) { - nbt.putUUID(MachineNbt.OWNER, this.owner); - } - - nbt.putLong("spawntick", nextSpawnTick); - if (schema != null) { - nbt.putString("schema", schema); - } - - nbt.putBoolean("locked", locked); - } - - @Override - public CompoundTag getUpdateTag() { - CompoundTag data = super.getUpdateTag(); - - getConnectedRoom().ifPresent(room -> { - data.putIntArray(ROOM_NBT, new int[]{room.x, room.z}); - }); - - if (level instanceof ServerLevel) { - // TODO - Internal player list - if (this.owner != null) - data.putUUID("owner", this.owner); - } - - return data; - } - - public Optional getConnectedRoom() { - if (level instanceof ServerLevel sl) { - if (roomChunk != null) - return Optional.of(roomChunk); - - final var graph = DimensionMachineGraph.forDimension(sl); - - var chunk = graph.getConnectedRoom(worldPosition); - chunk.ifPresent(c -> this.roomChunk = c); - return chunk; - } - - return Optional.ofNullable(roomChunk); - } - - @Override - public void handleUpdateTag(CompoundTag tag) { - super.handleUpdateTag(tag); - - if (tag.contains("players")) { - CompoundTag players = tag.getCompound("players"); - // playerData = CompactMachinePlayerData.fromNBT(players); - - } - - if (tag.contains(ROOM_NBT)) { - int[] room = tag.getIntArray(ROOM_NBT); - this.roomChunk = new ChunkPos(room[0], room[1]); - } - - if (tag.contains("owner")) - owner = tag.getUUID("owner"); - } - - public Optional getOwnerUUID() { - return Optional.ofNullable(this.owner); - } - - public void setOwner(UUID owner) { - this.owner = owner; - } - - public boolean hasPlayersInside() { - // TODO - return false; - } - - public LevelBlockPosition getLevelPosition() { - return new LevelBlockPosition(level.dimension(), worldPosition); - } - - public void syncConnectedRoom() { - if (this.level == null || this.level.isClientSide) return; - - if (level instanceof ServerLevel sl) { - final var graph = DimensionMachineGraph.forDimension(sl); - graph.getMachineNode(worldPosition).ifPresent(node -> { - this.graphNode = new WeakReference<>(node); - }); - - this.getConnectedRoom() - .flatMap(room -> graph.getRoomNode(this.roomChunk)) - .ifPresent(roomNode -> this.roomNode = new WeakReference<>(roomNode)); - - this.setChanged(); - } - } - - public void setConnectedRoom(ChunkPos room) { - if(level instanceof ServerLevel sl) { - final var dimMachines = DimensionMachineGraph.forDimension(sl); - dimMachines.connectMachineToRoom(worldPosition, room); - syncConnectedRoom(); - } - } - - public void disconnect() { - if(level instanceof ServerLevel sl) { - final var dimMachines = DimensionMachineGraph.forDimension(sl); - dimMachines.disconnect(worldPosition); - - this.roomChunk = null; - this.graphNode.clear(); - setChanged(); - } - } -} diff --git a/src/main/java/dev/compactmods/machines/machine/CompactMachineItem.java b/src/main/java/dev/compactmods/machines/machine/CompactMachineItem.java deleted file mode 100644 index d0d068cb..00000000 --- a/src/main/java/dev/compactmods/machines/machine/CompactMachineItem.java +++ /dev/null @@ -1,115 +0,0 @@ -package dev.compactmods.machines.machine; - -import dev.compactmods.machines.api.core.Tooltips; -import dev.compactmods.machines.api.machine.MachineNbt; -import dev.compactmods.machines.i18n.TranslationUtil; -import dev.compactmods.machines.api.room.RoomSize; -import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; - -import javax.annotation.Nullable; -import java.util.List; -import java.util.Optional; - -public class CompactMachineItem extends BlockItem { - - private static final String ROOM_NBT = "room_pos"; - - public CompactMachineItem(Block blockIn, Properties builder) { - super(blockIn, builder); - } - - @Deprecated(forRemoval = true) - public static Optional getMachineId(ItemStack stack) { - if (!stack.hasTag()) - return Optional.empty(); - - CompoundTag machineData = stack.getOrCreateTag(); - if (machineData.contains(MachineNbt.ID)) { - int c = machineData.getInt(MachineNbt.ID); - return c > -1 ? Optional.of(c) : Optional.empty(); - } - - return Optional.empty(); - } - - public static Item getItemBySize(RoomSize size) { - return switch (size) { - case TINY -> Machines.MACHINE_BLOCK_ITEM_TINY.get(); - case SMALL -> Machines.MACHINE_BLOCK_ITEM_SMALL.get(); - case NORMAL -> Machines.MACHINE_BLOCK_ITEM_NORMAL.get(); - case LARGE -> Machines.MACHINE_BLOCK_ITEM_LARGE.get(); - case GIANT -> Machines.MACHINE_BLOCK_ITEM_GIANT.get(); - case MAXIMUM -> Machines.MACHINE_BLOCK_ITEM_MAXIMUM.get(); - }; - } - - public static Optional getRoom(ItemStack stack) { - if (!stack.hasTag()) - return Optional.empty(); - - var tag = stack.getTag(); - if(!tag.contains(ROOM_NBT)) { - return Optional.empty(); - } - - var roomNbt = tag.getIntArray(ROOM_NBT); - return Optional.of(new ChunkPos(roomNbt[0], roomNbt[1])); - } - - public static void setRoom(ItemStack stack, ChunkPos room) { - var tag = stack.getOrCreateTag(); - tag.putIntArray(ROOM_NBT, new int[] { room.x, room.z }); - } - - @Override - public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List tooltip, TooltipFlag flagIn) { - super.appendHoverText(stack, worldIn, tooltip, flagIn); - - // We need NBT data for the rest of this - if (stack.hasTag()) { - CompoundTag nbt = stack.getTag(); - if(nbt == null) - return; - - // Try room binding; if failed, try old machine ID binding - getRoom(stack).ifPresentOrElse(room -> { - // TODO - Server-synced room name list - tooltip.add(TranslationUtil.tooltip(Tooltips.ROOM_NAME, room)); - }, () -> { - getMachineId(stack).ifPresent(id -> { - tooltip.add(TranslationUtil.tooltip(Tooltips.Machines.ID, id)); - }); - }); - } - - if (Screen.hasShiftDown()) { - Block b = Block.byItem(stack.getItem()); - if (b instanceof CompactMachineBlock cmb) { - RoomSize size = cmb.getSize(); - int internalSize = size.getInternalSize(); - - MutableComponent text = TranslationUtil.tooltip(Tooltips.Machines.SIZE, internalSize) - .withStyle(ChatFormatting.YELLOW); - - tooltip.add(text); - } - } else { - MutableComponent text = TranslationUtil.tooltip(Tooltips.HINT_HOLD_SHIFT) - .withStyle(ChatFormatting.DARK_GRAY) - .withStyle(ChatFormatting.ITALIC); - - tooltip.add(text); - } - } -} diff --git a/src/main/java/dev/compactmods/machines/machine/EnumMachinePlayersBreakHandling.java b/src/main/java/dev/compactmods/machines/machine/EnumMachinePlayersBreakHandling.java deleted file mode 100644 index 9df6cee9..00000000 --- a/src/main/java/dev/compactmods/machines/machine/EnumMachinePlayersBreakHandling.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.compactmods.machines.machine; - -public enum EnumMachinePlayersBreakHandling { - UNBREAKABLE("unbreakable", "Nobody can break while players are inside."), - OWNER("owner", "Only the owner can break while players are inside."), - ANYONE("anyone", "Anyone can break while players are inside."); - - private final String configValue; - private final String configDesc; - - EnumMachinePlayersBreakHandling(String configValue, String configDesc) { - this.configValue = configValue; - this.configDesc = configDesc; - } - - public String configName() { - return configValue; - } - - public String configDesc() { - return configDesc; - } -} diff --git a/src/main/java/dev/compactmods/machines/machine/Machines.java b/src/main/java/dev/compactmods/machines/machine/Machines.java deleted file mode 100644 index 76d25be8..00000000 --- a/src/main/java/dev/compactmods/machines/machine/Machines.java +++ /dev/null @@ -1,74 +0,0 @@ -package dev.compactmods.machines.machine; - -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.core.Registries; -import dev.compactmods.machines.api.room.RoomSize; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.material.Material; -import net.minecraftforge.registries.RegistryObject; - -import java.util.function.Supplier; - -public class Machines { - static final BlockBehaviour.Properties MACHINE_BLOCK_PROPS = BlockBehaviour.Properties - .of(Material.METAL) - .strength(8.0F, 20.0F) - .requiresCorrectToolForDrops(); - - static final Supplier MACHINE_ITEM_PROPS = () -> new Item.Properties() - .tab(CompactMachines.COMPACT_MACHINES_ITEMS); - - public static final RegistryObject MACHINE_BLOCK_TINY = Registries.BLOCKS.register("machine_tiny", () -> - new CompactMachineBlock(RoomSize.TINY, MACHINE_BLOCK_PROPS)); - - public static final RegistryObject MACHINE_BLOCK_SMALL = Registries.BLOCKS.register("machine_small", () -> - new CompactMachineBlock(RoomSize.SMALL, MACHINE_BLOCK_PROPS)); - - public static final RegistryObject MACHINE_BLOCK_NORMAL = Registries.BLOCKS.register("machine_normal", () -> - new CompactMachineBlock(RoomSize.NORMAL, MACHINE_BLOCK_PROPS)); - - public static final RegistryObject MACHINE_BLOCK_LARGE = Registries.BLOCKS.register("machine_large", () -> - new CompactMachineBlock(RoomSize.LARGE, MACHINE_BLOCK_PROPS)); - - public static final RegistryObject MACHINE_BLOCK_GIANT = Registries.BLOCKS.register("machine_giant", () -> - new CompactMachineBlock(RoomSize.GIANT, MACHINE_BLOCK_PROPS)); - - public static final RegistryObject MACHINE_BLOCK_MAXIMUM = Registries.BLOCKS.register("machine_maximum", () -> - new CompactMachineBlock(RoomSize.MAXIMUM, MACHINE_BLOCK_PROPS)); - - - - - public static final RegistryObject MACHINE_BLOCK_ITEM_TINY = Registries.ITEMS.register("machine_tiny", - () -> new CompactMachineItem(MACHINE_BLOCK_TINY.get(), MACHINE_ITEM_PROPS.get())); - - public static final RegistryObject MACHINE_BLOCK_ITEM_SMALL = Registries.ITEMS.register("machine_small", - () -> new CompactMachineItem(MACHINE_BLOCK_SMALL.get(), MACHINE_ITEM_PROPS.get())); - - public static final RegistryObject MACHINE_BLOCK_ITEM_NORMAL = Registries.ITEMS.register("machine_normal", - () -> new CompactMachineItem(MACHINE_BLOCK_NORMAL.get(), MACHINE_ITEM_PROPS.get())); - - public static final RegistryObject MACHINE_BLOCK_ITEM_LARGE = Registries.ITEMS.register("machine_large", - () -> new CompactMachineItem(MACHINE_BLOCK_LARGE.get(), MACHINE_ITEM_PROPS.get())); - - public static final RegistryObject MACHINE_BLOCK_ITEM_GIANT = Registries.ITEMS.register("machine_giant", - () -> new CompactMachineItem(MACHINE_BLOCK_GIANT.get(), MACHINE_ITEM_PROPS.get())); - - public static final RegistryObject MACHINE_BLOCK_ITEM_MAXIMUM = Registries.ITEMS.register("machine_maximum", - () -> new CompactMachineItem(MACHINE_BLOCK_MAXIMUM.get(), MACHINE_ITEM_PROPS.get())); - - - - public static final RegistryObject> MACHINE_TILE_ENTITY = Registries.BLOCK_ENTITIES.register("compact_machine", () -> - BlockEntityType.Builder.of(CompactMachineBlockEntity::new, - MACHINE_BLOCK_TINY.get(), MACHINE_BLOCK_SMALL.get(), MACHINE_BLOCK_NORMAL.get(), - MACHINE_BLOCK_LARGE.get(), MACHINE_BLOCK_GIANT.get(), MACHINE_BLOCK_MAXIMUM.get()) - .build(null)); - - public static void prepare() { - - } -} diff --git a/src/main/java/dev/compactmods/machines/machine/exceptions/InvalidMachineStateException.java b/src/main/java/dev/compactmods/machines/machine/exceptions/InvalidMachineStateException.java deleted file mode 100644 index 11ba4e09..00000000 --- a/src/main/java/dev/compactmods/machines/machine/exceptions/InvalidMachineStateException.java +++ /dev/null @@ -1,30 +0,0 @@ -package dev.compactmods.machines.machine.exceptions; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.state.BlockState; -import org.antlr.v4.runtime.atn.BlockStartState; - -public class InvalidMachineStateException extends Throwable { - private final BlockPos machinePosition; - private final BlockState state; - - public InvalidMachineStateException(BlockPos machinePos, BlockState state) { - super("Invalid machine state."); - this.machinePosition = machinePos; - this.state = state; - } - - public InvalidMachineStateException(BlockPos machinePos, BlockState state, String s) { - super(s); - this.machinePosition = machinePos; - this.state = state; - } - - public BlockPos getMachinePosition() { - return machinePosition; - } - - public BlockState getState() { - return state; - } -} diff --git a/src/main/java/dev/compactmods/machines/machine/exceptions/NonexistentMachineException.java b/src/main/java/dev/compactmods/machines/machine/exceptions/NonexistentMachineException.java deleted file mode 100644 index 7e41a6dd..00000000 --- a/src/main/java/dev/compactmods/machines/machine/exceptions/NonexistentMachineException.java +++ /dev/null @@ -1,13 +0,0 @@ -package dev.compactmods.machines.machine.exceptions; - -public class NonexistentMachineException extends Throwable { - private final int machine; - - public NonexistentMachineException(int machine) { - this.machine = machine; - } - - public int getMachine() { - return machine; - } -} diff --git a/src/main/java/dev/compactmods/machines/machine/graph/CompactMachineNode.java b/src/main/java/dev/compactmods/machines/machine/graph/CompactMachineNode.java deleted file mode 100644 index 5113512a..00000000 --- a/src/main/java/dev/compactmods/machines/machine/graph/CompactMachineNode.java +++ /dev/null @@ -1,41 +0,0 @@ -package dev.compactmods.machines.machine.graph; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.graph.Graph; -import dev.compactmods.machines.graph.IGraphNode; -import dev.compactmods.machines.graph.IGraphNodeType; -import dev.compactmods.machines.location.LevelBlockPosition; -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.Level; - -/** - * Represents a machine's external point. This can be either inside a machine or in a dimension somewhere. - */ -public record CompactMachineNode(ResourceKey dimension, BlockPos position) - implements IGraphNode { - - public static final ResourceLocation TYPE = new ResourceLocation(Constants.MOD_ID, "machine"); - - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - Level.RESOURCE_KEY_CODEC.fieldOf("dimension").forGetter(CompactMachineNode::dimension), - BlockPos.CODEC.fieldOf("position").forGetter(CompactMachineNode::position), - ResourceLocation.CODEC.fieldOf("type").forGetter(x -> TYPE) - ).apply(i, (dim, pos, type) -> new CompactMachineNode(dim, pos))); - - public String toString() { - return "Compact Machine {%s}".formatted(position); - } - - public LevelBlockPosition dimpos() { - return new LevelBlockPosition(dimension, position); - } - - @Override - public IGraphNodeType getType() { - return Graph.MACH_NODE.get(); - } -} diff --git a/src/main/java/dev/compactmods/machines/machine/graph/DimensionMachineGraph.java b/src/main/java/dev/compactmods/machines/machine/graph/DimensionMachineGraph.java deleted file mode 100644 index f8e13cda..00000000 --- a/src/main/java/dev/compactmods/machines/machine/graph/DimensionMachineGraph.java +++ /dev/null @@ -1,243 +0,0 @@ -package dev.compactmods.machines.machine.graph; - -import com.google.common.collect.ImmutableList; -import com.google.common.graph.MutableValueGraph; -import com.google.common.graph.ValueGraphBuilder; -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.codec.CodecExtensions; -import dev.compactmods.machines.graph.IGraphEdge; -import dev.compactmods.machines.graph.IGraphNode; -import dev.compactmods.machines.graph.IGraphNodeType; -import dev.compactmods.machines.room.graph.CompactMachineRoomNode; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.saveddata.SavedData; - -import javax.annotation.Nonnull; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Stores information on how external machines connect to the rooms in the compact machine - * dimension. Per-dimension since 4.3.0. - */ -public class DimensionMachineGraph extends SavedData { - - private final ResourceKey level; - private final MutableValueGraph graph; - private final Map machines; - private final Map rooms; - - public static final String DATA_KEY = "machine_connections"; - private final Codec> CONN_CODEC = CompactMachineConnectionInfo.CODEC - .listOf() - .fieldOf("connections") - .codec(); - - private DimensionMachineGraph(ResourceKey level) { - this.level = level; - graph = ValueGraphBuilder - .directed() - .build(); - - machines = new HashMap<>(); - rooms = new HashMap<>(); - } - - private DimensionMachineGraph(ResourceKey level, @Nonnull CompoundTag nbt) { - this(level); - - if (nbt.contains("graph")) { - CompoundTag graphNbt = nbt.getCompound("graph"); - - final var connectionData = CONN_CODEC.parse(NbtOps.INSTANCE, graphNbt) - .resultOrPartial(CompactMachines.LOGGER::error) - .orElseThrow(); - - loadConnections(connectionData); - } - } - - private void loadConnections(List connectionInfo) { - for (CompactMachineConnectionInfo i : connectionInfo) { - addRoom(i.roomChunk); - for (var connectedMachine : i.machines()) { - addMachine(connectedMachine); - connectMachineToRoom(connectedMachine, i.roomChunk); - } - } - } - - public static DimensionMachineGraph forDimension(ServerLevel dimension) { - final var dimStore = dimension.getDataStorage(); - return dimStore.computeIfAbsent(tag -> new DimensionMachineGraph(dimension.dimension(), tag), - () -> new DimensionMachineGraph(dimension.dimension()), DATA_KEY); - } - - private List buildConnections() { - List result = new ArrayList<>(); - this.rooms.forEach((chunk, node) -> { - Collection machines = this.getMachinesFor(chunk); - CompactMachineConnectionInfo roomInfo = new CompactMachineConnectionInfo(chunk, machines); - result.add(roomInfo); - }); - - return result; - } - - public void addMachine(BlockPos machine) { - if (this.machines.containsKey(machine)) - return; - - CompactMachineNode node = new CompactMachineNode(this.level, machine); - graph.addNode(node); - machines.put(machine, node); - - this.setDirty(); - } - - public void addRoom(ChunkPos roomChunk) { - if (this.rooms.containsKey(roomChunk)) - return; - - CompactMachineRoomNode node = new CompactMachineRoomNode(roomChunk); - graph.addNode(node); - rooms.put(roomChunk, node); - - this.setDirty(); - } - - public void connectMachineToRoom(BlockPos machine, ChunkPos room) { - if (!machines.containsKey(machine)) - addMachine(machine); - - if (!rooms.containsKey(room)) - addRoom(room); - - CompactMachineNode machineNode = machines.get(machine); - CompactMachineRoomNode roomNode = rooms.get(room); - - graph.putEdgeValue(machineNode, roomNode, new MachineRoomEdge()); - - this.setDirty(); - } - - public Collection getMachinesFor(ChunkPos room) { - if(!rooms.containsKey(room)) - return Collections.emptySet(); - - var node = this.rooms.get(room); - var inbound = graph.predecessors(node); - - return inbound.stream() - .filter(CompactMachineNode.class::isInstance) - .map(CompactMachineNode.class::cast) - .map(CompactMachineNode::position) - .collect(Collectors.toSet()); - } - - public Optional getConnectedRoom(BlockPos machinePos) { - if (!this.machines.containsKey(machinePos)) - return Optional.empty(); - - var node = this.machines.get(machinePos); - var connected = this.graph.successors(node); - return connected.stream() - .filter(n -> n instanceof CompactMachineRoomNode) - .map(n -> (CompactMachineRoomNode) n) - .map(CompactMachineRoomNode::pos) - .findFirst(); - } - - public Stream getMachines() { - return this.machines.values().stream(); - } - - public void disconnectAndUnregister(int machine) { - if (!machines.containsKey(machine)) - return; - - final var node = machines.get(machine); - graph.removeNode(node); - machines.remove(machine); - } - - public void removeRoom(ChunkPos room) { - if (!this.rooms.containsKey(room)) - return; - - graph.removeNode(rooms.get(room)); - rooms.remove(room); - } - - public void disconnect(BlockPos machine) { - if (!machines.containsKey(machine)) - return; - - final var node = machines.get(machine); - graph.successors(node).stream() - .filter(cn -> cn instanceof CompactMachineRoomNode) - .forEach(room -> graph.removeEdge(node, room)); - - setDirty(); - } - - public Optional getMachineNode(BlockPos worldPosition) { - return Optional.ofNullable(machines.get(worldPosition)); - } - - public Optional getRoomNode(ChunkPos room) { - return Optional.ofNullable(rooms.get(room)); - } - - @Nonnull - @Override - public CompoundTag save(@Nonnull CompoundTag nbt) { - final var connData = buildConnections(); - - CONN_CODEC.encodeStart(NbtOps.INSTANCE, connData) - .resultOrPartial(CompactMachines.LOGGER::error) - .ifPresent(gNbt -> nbt.put("graph", gNbt)); - - return nbt; - } - - /** - * Data structure for serialization. Do not use directly. - */ - private static class CompactMachineConnectionInfo { - private final ChunkPos roomChunk; - private final List connectedMachines; - - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - CodecExtensions.CHUNKPOS - .fieldOf("room") - .forGetter(CompactMachineConnectionInfo::room), - - BlockPos.CODEC.listOf() - .fieldOf("machines") - .forGetter(CompactMachineConnectionInfo::machines) - ).apply(i, CompactMachineConnectionInfo::new)); - - public CompactMachineConnectionInfo(ChunkPos roomChunk, Collection connections) { - this.roomChunk = roomChunk; - this.connectedMachines = ImmutableList.copyOf(connections); - } - - public ChunkPos room() { - return this.roomChunk; - } - - public List machines() { - return this.connectedMachines; - } - } -} diff --git a/src/main/java/dev/compactmods/machines/machine/graph/MachineRoomEdge.java b/src/main/java/dev/compactmods/machines/machine/graph/MachineRoomEdge.java deleted file mode 100644 index 5e66dca9..00000000 --- a/src/main/java/dev/compactmods/machines/machine/graph/MachineRoomEdge.java +++ /dev/null @@ -1,32 +0,0 @@ -package dev.compactmods.machines.machine.graph; - -import com.mojang.serialization.Codec; -import dev.compactmods.machines.graph.GraphEdgeType; -import dev.compactmods.machines.graph.IGraphEdge; -import dev.compactmods.machines.graph.IGraphEdgeType; -import org.jetbrains.annotations.NotNull; - -public record MachineRoomEdge() implements IGraphEdge { - - public static final Codec CODEC = Codec.unit(MachineRoomEdge::new); - - @Override - public boolean equals(Object obj) { - return obj == this || obj != null && obj.getClass() == this.getClass(); - } - - @Override - public int hashCode() { - return 1; - } - - @Override - public String toString() { - return "MachineRoomEdge[]"; - } - - @Override - public @NotNull IGraphEdgeType getEdgeType() { - return GraphEdgeType.MACHINE_LINK; - } -} diff --git a/src/main/java/dev/compactmods/machines/machine/graph/legacy/LegacyMachineConnections.java b/src/main/java/dev/compactmods/machines/machine/graph/legacy/LegacyMachineConnections.java deleted file mode 100644 index bd97899e..00000000 --- a/src/main/java/dev/compactmods/machines/machine/graph/legacy/LegacyMachineConnections.java +++ /dev/null @@ -1,81 +0,0 @@ -package dev.compactmods.machines.machine.graph.legacy; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.codec.CodecExtensions; -import dev.compactmods.machines.dimension.MissingDimensionException; -import dev.compactmods.machines.dimension.Dimension; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.saveddata.SavedData; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class LegacyMachineConnections extends SavedData { - - private static final String DATA_KEY = "compactmachines_connections"; - - private final Map machineMapping; - - private LegacyMachineConnections() { - this.machineMapping = new HashMap<>(); - } - - public static LegacyMachineConnections get(MinecraftServer server) throws MissingDimensionException { - var compactDim = server.getLevel(Dimension.COMPACT_DIMENSION); - if(compactDim == null) - throw new MissingDimensionException(); - - return compactDim.getDataStorage().get(LegacyMachineConnections::load, DATA_KEY); - } - - private static LegacyMachineConnections load(CompoundTag tag) { - if(!tag.contains("graph")) - return null; - - var graphTag = tag.getCompound("graph"); - if(!graphTag.contains("connections")) - return null; - - LegacyMachineConnections tmp = new LegacyMachineConnections(); - final var connections = ConnectionInfoTag.CODEC.listOf() - .fieldOf("connections") - .codec() - .parse(NbtOps.INSTANCE, graphTag) - .getOrThrow(false, CompactMachines.LOGGER::error); - - // load all connections into result - connections.forEach(conn -> conn.machines.forEach(mid -> tmp.machineMapping.putIfAbsent(mid, conn.room))); - - return tmp; - } - - @Override - public CompoundTag save(CompoundTag tag) { - return tag; - } - - public ChunkPos getConnectedRoom(int legacyMachineId) { - if(!machineMapping.containsKey(legacyMachineId)) - return ChunkPos.ZERO; - - return machineMapping.get(legacyMachineId); - } - - private record ConnectionInfoTag(ChunkPos room, List machines) { - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - CodecExtensions.CHUNKPOS - .fieldOf("machine") - .forGetter(ConnectionInfoTag::room), - - Codec.INT.listOf() - .fieldOf("connections") - .forGetter(ConnectionInfoTag::machines) - ).apply(i, ConnectionInfoTag::new)); - } -} diff --git a/src/main/java/dev/compactmods/machines/machine/graph/legacy/LegacyMachineLocationsGraph.java b/src/main/java/dev/compactmods/machines/machine/graph/legacy/LegacyMachineLocationsGraph.java deleted file mode 100644 index 54ecd6f7..00000000 --- a/src/main/java/dev/compactmods/machines/machine/graph/legacy/LegacyMachineLocationsGraph.java +++ /dev/null @@ -1,69 +0,0 @@ -package dev.compactmods.machines.machine.graph.legacy; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.dimension.MissingDimensionException; -import dev.compactmods.machines.dimension.Dimension; -import dev.compactmods.machines.location.LevelBlockPosition; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.level.saveddata.SavedData; - -import java.util.HashMap; -import java.util.Map; - -public class LegacyMachineLocationsGraph extends SavedData { - - private static final String DATA_KEY = "compactmachines_machines"; - - private final Map machineMapping; - - private LegacyMachineLocationsGraph() { - this.machineMapping = new HashMap<>(); - } - - public static LegacyMachineLocationsGraph get(MinecraftServer server) throws MissingDimensionException { - var compactDim = server.getLevel(Dimension.COMPACT_DIMENSION); - if(compactDim == null) - throw new MissingDimensionException(); - - return compactDim.getDataStorage().get(LegacyMachineLocationsGraph::load, DATA_KEY); - } - - private static LegacyMachineLocationsGraph load(CompoundTag tag) { - LegacyMachineLocationsGraph tmp = new LegacyMachineLocationsGraph(); - - if(tag.contains("locations")) { - final var locations = MachineData.CODEC.listOf() - .fieldOf("locations") - .codec() - .parse(NbtOps.INSTANCE, tag) - .getOrThrow(false, CompactMachines.LOGGER::error); - - locations.forEach(md -> tmp.machineMapping.putIfAbsent(md.machine, md.location)); - } - - return tmp; - } - - @Override - public CompoundTag save(CompoundTag tag) { - return tag; - } - - public LevelBlockPosition getLocation(int legacyMachineId) { - if(!machineMapping.containsKey(legacyMachineId)) - return null; - - return this.machineMapping.get(legacyMachineId); - } - - private record MachineData(LevelBlockPosition location, int machine) { - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - LevelBlockPosition.CODEC.fieldOf("location").forGetter(MachineData::location), - Codec.INT.fieldOf("machine").forGetter(MachineData::machine) - ).apply(i, MachineData::new)); - } -} diff --git a/src/main/java/dev/compactmods/machines/room/RoomCapabilities.java b/src/main/java/dev/compactmods/machines/room/RoomCapabilities.java deleted file mode 100644 index 7eb8f8b9..00000000 --- a/src/main/java/dev/compactmods/machines/room/RoomCapabilities.java +++ /dev/null @@ -1,22 +0,0 @@ -package dev.compactmods.machines.room; - -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.api.room.IRoomHistory; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.CapabilityManager; -import net.minecraftforge.common.capabilities.CapabilityToken; -import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; - -@Mod.EventBusSubscriber(modid = Constants.MOD_ID) -public class RoomCapabilities { - - public static final Capability ROOM_HISTORY = CapabilityManager.get(new CapabilityToken<>() { - }); - - @SubscribeEvent - void onCapRegistration(final RegisterCapabilitiesEvent evt) { - evt.register(IRoomHistory.class); - } -} diff --git a/src/main/java/dev/compactmods/machines/room/Rooms.java b/src/main/java/dev/compactmods/machines/room/Rooms.java deleted file mode 100644 index dd5130af..00000000 --- a/src/main/java/dev/compactmods/machines/room/Rooms.java +++ /dev/null @@ -1,231 +0,0 @@ -package dev.compactmods.machines.room; - -import com.mojang.authlib.GameProfile; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.api.location.IDimensionalBlockPosition; -import dev.compactmods.machines.api.location.IDimensionalPosition; -import dev.compactmods.machines.api.room.RoomSize; -import dev.compactmods.machines.config.ServerConfig; -import dev.compactmods.machines.dimension.MissingDimensionException; -import dev.compactmods.machines.location.LevelBlockPosition; -import dev.compactmods.machines.machine.graph.DimensionMachineGraph; -import dev.compactmods.machines.room.data.CompactRoomData; -import dev.compactmods.machines.room.exceptions.NonexistentRoomException; -import dev.compactmods.machines.util.CompactStructureGenerator; -import dev.compactmods.machines.util.MathUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraft.world.phys.Vec3; - -import javax.naming.OperationNotSupportedException; -import java.util.Objects; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Stream; - -public class Rooms { - public static ChunkPos createNew(MinecraftServer serv, RoomSize size, UUID owner) throws MissingDimensionException { - final var compactWorld = serv.getLevel(CompactDimension.LEVEL_KEY); - - if (compactWorld == null) - throw new MissingDimensionException(); - - CompactRoomData rooms = CompactRoomData.get(compactWorld); - - int nextPosition = rooms.getNextSpiralPosition(); - Vec3i location = MathUtil.getRegionPositionByIndex(nextPosition); - - int centerY = ServerConfig.MACHINE_FLOOR_Y.get() + (size.getInternalSize() / 2); - BlockPos newCenter = MathUtil.getCenterWithY(location, centerY); - - // Generate a new machine room - CompactStructureGenerator.generateCompactStructure(compactWorld, size, newCenter); - - ChunkPos machineChunk = new ChunkPos(newCenter); - try { - rooms.createNew() - .owner(owner) - .size(size) - .chunk(machineChunk) - .register(); - } catch (OperationNotSupportedException e) { - // room already registered somehow - CompactMachines.LOGGER.warn(e); - } - - return machineChunk; - } - - // TODO - Revisit with furnace recipe -// public static boolean destroy(MinecraftServer server, ChunkPos room) throws MissingDimensionException, NonexistentRoomException { -// final var compactDim = server.getLevel(Registration.COMPACT_DIMENSION); -// if (compactDim == null) -// throw new MissingDimensionException(); -// -// var roomData = CompactRoomData.get(compactDim); -// if (!roomData.isRegistered(room)) { -// throw new NonexistentRoomException(room); -// } -// -// final var roomBounds = roomData.getBounds(room); -// final var innerBounds = roomBounds.deflate(1); -// -// final var states = compactDim.getBlockStates(innerBounds) -// .collect(Collectors.toSet()); -// -// final var nonAir = states.stream() -// .filter(state -> !state.isAir()) -// .findAny(); -// -// if (nonAir.isPresent()) { -// CompactMachines.LOGGER.error("Refusing to delete room at {}; non-air blocks exist inside the room. First match: {}", room, nonAir.get()); -// return false; -// } -// -// // clear tunnel connection info -// final var tunnels = RoomTunnelData.getFile(server, room); -// final var filename = RoomTunnelData.getDataFilename(room); -// if (!tunnels.delete()) { -// CompactMachines.LOGGER.warn("Could not delete tunnel data for room {}; clearing the connection graph as an alternative.", room); -// CompactMachines.LOGGER.warn("Data file to delete: {}", filename); -// -// var td = RoomTunnelData.forRoom(server, room); -// td.getGraph().clear(); -// td.setDirty(); -// } else { -// // File deletion successful, delete cached data -// final var compactDataCache = compactDim.getDataStorage().cache; -// compactDataCache.remove(filename); -// } -// -// // reset everything for the room boundary -// BlockPos.betweenClosedStream(roomBounds.inflate(1)) -// .forEach(p -> compactDim.setBlock(p, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL)); -// -// // Remove room registration -// roomData.remove(room); -// -// // Disconnect all machines -// var conns = MachineToRoomConnections.forDimension(server); -// var d = CompactMachineData.get(server); -// -// var connected = conns.getMachinesFor(room); -// for (int mid : connected) { -// var location = d.getMachineLocation(mid); -// location.ifPresent(p -> { -// var pos = p.getBlockPosition(); -// var l = p.level(server); -// if (l.getBlockEntity(pos) instanceof TunnelWallEntity tunn) { -// tunn.disconnect(); -// } -// }); -// } -// -// conns.unregisterRoom(room); -// return true; -// } - - public static Stream getConnectedMachines(MinecraftServer server, ChunkPos room) { - return server.levelKeys().stream() - .map(server::getLevel) - .filter(Objects::nonNull) - .filter(sl -> sl.getDataStorage().cache.containsKey(DimensionMachineGraph.DATA_KEY)) - .flatMap(sl -> { - final var graph = DimensionMachineGraph.forDimension(sl); - return graph.getMachinesFor(room).stream() - .map(bp -> new LevelBlockPosition(sl.dimension(), bp)); - }); - } - - public static RoomSize sizeOf(MinecraftServer server, ChunkPos room) throws NonexistentRoomException { - final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); - return CompactRoomData.get(compactDim) - .getData(room) - .getSize(); - } - - public static IDimensionalPosition getSpawn(MinecraftServer server, ChunkPos room) { - final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); - return CompactRoomData.get(compactDim).getSpawn(room); - } - - public static boolean exists(MinecraftServer server, ChunkPos room) { - final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); - return CompactRoomData.get(compactDim).isRegistered(room); - } - - public static StructureTemplate getInternalBlocks(MinecraftServer server, ChunkPos room) throws MissingDimensionException, NonexistentRoomException { - final var tem = new StructureTemplate(); - - final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); - - final var data = CompactRoomData.get(compactDim); - final var roomInfo = data.getData(room); - - final var bounds = roomInfo.getRoomBounds(); - final int inside = roomInfo.getSize().getInternalSize(); - tem.fillFromWorld(compactDim, new BlockPos(bounds.minX, bounds.minY - 1, bounds.minZ), - new Vec3i(inside, inside + 1, inside), false, null); - - return tem; - } - - public static void resetSpawn(MinecraftServer server, ChunkPos room) throws NonexistentRoomException { - if(!exists(server, room)) - throw new NonexistentRoomException(room); - - final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); - - final var data = CompactRoomData.get(compactDim); - final var roomInfo = data.getData(room); - - final var centerPoint = Vec3.atCenterOf(roomInfo.getCenter()); - final var newSpawn = centerPoint.subtract(0, (roomInfo.getSize().getInternalSize() / 2f), 0); - - data.setSpawn(room, newSpawn); - } - - public static Optional getRoomName(MinecraftServer server, ChunkPos room) throws NonexistentRoomException { - if(!exists(server, room)) - throw new NonexistentRoomException(room); - - final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); - - final var data = CompactRoomData.get(compactDim); - final var roomInfo = data.getData(room); - return roomInfo.getName(); - } - - public static Optional getOwner(MinecraftServer server, ChunkPos room) { - if(!exists(server, room)) - return Optional.empty(); - - final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); - final var data = CompactRoomData.get(compactDim); - - try { - final CompactRoomData.RoomData roomInfo = data.getData(room); - final var ownerUUID = roomInfo.getOwner(); - - return server.getProfileCache().get(ownerUUID); - } catch (NonexistentRoomException e) { - return Optional.empty(); - } - } - - public static void updateName(MinecraftServer server, ChunkPos room, String newName) throws NonexistentRoomException { - if(!exists(server, room)) - throw new NonexistentRoomException(room); - - final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); - - final var data = CompactRoomData.get(compactDim); - final var roomInfo = data.getData(room); - roomInfo.setName(newName); - data.setDirty(); - } -} diff --git a/src/main/java/dev/compactmods/machines/room/client/MachineRoomScreen.java b/src/main/java/dev/compactmods/machines/room/client/MachineRoomScreen.java deleted file mode 100644 index 52feacf7..00000000 --- a/src/main/java/dev/compactmods/machines/room/client/MachineRoomScreen.java +++ /dev/null @@ -1,225 +0,0 @@ -package dev.compactmods.machines.room.client; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Matrix4f; -import com.mojang.math.Vector3f; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.client.gui.widget.PSDIconButton; -import dev.compactmods.machines.client.level.RenderingLevel; -import dev.compactmods.machines.client.render.RenderTypes; -import dev.compactmods.machines.client.render.SuperRenderTypeBuffer; -import dev.compactmods.machines.client.util.TransformingVertexBuilder; -import dev.compactmods.machines.location.LevelBlockPosition; -import dev.compactmods.machines.room.menu.MachineRoomMenu; -import dev.compactmods.machines.room.network.PlayerStartedRoomTrackingPacket; -import dev.compactmods.machines.room.network.RoomNetworkHandler; -import dev.compactmods.machines.shrinking.Shrinking; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.decoration.ArmorStand; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; -import net.minecraftforge.client.model.data.ModelData; - -public class MachineRoomScreen extends AbstractContainerScreen { - - private final Inventory inv; - protected double rotateX = 45.0f; - protected double rotateY = 20.0f; - private PSDIconButton psdButton; - private RenderingLevel renderer; - - public MachineRoomScreen(MachineRoomMenu menu, Inventory inv, Component title) { - super(menu, inv, title); - this.imageWidth = 248; - this.imageHeight = 239; - this.titleLabelY = 5; - this.inv = inv; - - // Send packet to server for block data - RoomNetworkHandler.CHANNEL.sendToServer(new PlayerStartedRoomTrackingPacket(menu.getRoom())); - updateBlockRender(); - } - - @Override - protected void init() { - super.init(); - - this.psdButton = addRenderableWidget(new PSDIconButton(this, leftPos + 220, topPos + 210)); - if (hasPsdItem()) - this.psdButton.setEnabled(true); - } - - public void updateBlockRender() { - var struct = menu.getBlocks(); - this.renderer = new RenderingLevel(struct); - } - - private boolean hasPsdItem() { - return inv.contains(new ItemStack(Shrinking.PERSONAL_SHRINKING_DEVICE.get())); - } - - @Override - protected void containerTick() { - super.containerTick(); - psdButton.setEnabled(this.inv.player.isCreative() || hasPsdItem()); - renderer.tbe(); - } - - @Override - public boolean mouseDragged(double mx, double my, int mButton, double dx, double dy) { - var s = super.mouseDragged(mx, my, mButton, dx, dy); - if (!s) return false; - - rotateX += dx; - rotateY += dy; - return true; - } - - @Override - protected void renderLabels(PoseStack pose, int mouseX, int mouseY) { - pose.pushPose(); - pose.translate(0, 0, 500); - - pose.translate(this.imageWidth / 2f, 0, 0); - - var p = Component.literal(menu.getRoomName()); - Screen.drawCenteredString(pose, font, p, 0, this.titleLabelY, 0xFFFFFFFF); - - var room = menu.getRoom(); - var rt = Component.literal("(%s, %s)".formatted(room.x, room.z)); - pose.scale(0.8f, 0.8f, 0.8f); - Screen.drawCenteredString(pose, font, rt, 0,this.titleLabelY + font.lineHeight + 2, 0xFFCCCCCC); - pose.popPose(); - } - - @Override - public void render(PoseStack pose, int mouseX, int mouseY, float partial) { - this.renderBackground(pose); - super.render(pose, mouseX, mouseY, partial); - - var buffer = SuperRenderTypeBuffer.getInstance(); - - RenderSystem.enableBlend(); - RenderSystem.enableDepthTest(); - RenderSystem.backupProjectionMatrix(); - - // has to be outside of MS transforms, important for vertex sorting - Matrix4f matrix4f = new Matrix4f(RenderSystem.getProjectionMatrix()); - matrix4f.multiplyWithTranslation(0, 0, 800); - RenderSystem.setProjectionMatrix(matrix4f); - - PoseStack.Pose lastEntryBeforeTry = pose.last(); - - var cam = minecraft.cameraEntity; - - - try { - pose.pushPose(); - pose.translate(0, 0, -800); - - final var blockRenderer = Minecraft.getInstance().getBlockRenderer(); - final var beRenderer = Minecraft.getInstance().getBlockEntityRenderDispatcher(); - - var struct = menu.getBlocks(); - - pose.pushPose(); - { - // pose.translate(s, s, s); - - pose.translate(getGuiLeft() + (getXSize() / 2d), getGuiTop() + 135, 150); - - float zoom = switch (struct.getSize().getX()) { - case 3 -> 23.5f; - case 5 -> 19.5f; - case 7 -> 15.5f; - case 9 -> 14.5f; - case 11 -> 11.5f; - case 13 -> 10.5f; - default -> 10.5f; - }; - - pose.scale(zoom, -zoom, zoom); - - pose.mulPose(Vector3f.XP.rotationDegrees((float) rotateY)); - pose.mulPose(Vector3f.YP.rotationDegrees((float) rotateX)); - - final var tSize = struct.getSize(); - final float s = tSize.getX() / 2f; - pose.translate(-s, -s + 1, -s); - - final var transformer = new TransformingVertexBuilder(buffer, RenderTypes.WALLS); - - var bb = struct.getBoundingBox(new StructurePlaceSettings(), BlockPos.ZERO); - - var as = new ArmorStand(renderer, 0, 0, 0); - minecraft.cameraEntity = as; - - BlockPos.betweenClosedStream(bb).forEach(pos -> { - pose.pushPose(); - { - pose.translate(pos.getX(), pos.getY(), pos.getZ()); - - final var state = renderer.getBlockState(pos); - transformer.setOverlay(OverlayTexture.RED_OVERLAY_V); - - ModelData modelData = ModelData.EMPTY; - if (state.hasBlockEntity()) { - final var be = renderer.getBlockEntity(pos); - if (be != null) { - modelData = be.getModelData(); - final var ber = beRenderer.getRenderer(be); - if (ber != null) { - ber.render(be, 1f, pose, buffer, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY); - } - } - } - - try { - pose.pushPose(); - - for(var type : blockRenderer.getBlockModel(state).getRenderTypes(state, minecraft.level.random, modelData)) { - blockRenderer.renderBatched(state, pos, renderer, pose, buffer.getBuffer(type), true, renderer.random, modelData, type); - } - - pose.popPose(); - } catch (Exception e) { - } - } - pose.popPose(); - }); - } - pose.popPose(); - pose.popPose(); - } catch (Exception e) { - while (lastEntryBeforeTry != pose.last()) - pose.popPose(); - } - - minecraft.cameraEntity = cam; - - buffer.draw(); - RenderSystem.restoreProjectionMatrix(); - } - - @Override - protected void renderBg(PoseStack pose, float p_97788_, int p_97789_, int p_97790_) { - RenderSystem.setShaderTexture(0, new ResourceLocation(Constants.MOD_ID, "textures/gui/room_menu.png")); - - int i = (this.width - this.imageWidth) / 2; - int j = (this.height - this.imageHeight) / 2; - // this.blit(pose, leftPos, topPos, 0, 0, this.imageWidth, this.imageHeight); - } - - public LevelBlockPosition getMachine() { - return menu.getMachine(); - } -} diff --git a/src/main/java/dev/compactmods/machines/room/data/CompactRoomData.java b/src/main/java/dev/compactmods/machines/room/data/CompactRoomData.java deleted file mode 100644 index 656d0bb7..00000000 --- a/src/main/java/dev/compactmods/machines/room/data/CompactRoomData.java +++ /dev/null @@ -1,306 +0,0 @@ -package dev.compactmods.machines.room.data; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.codec.CodecExtensions; -import dev.compactmods.machines.api.codec.NbtListCollector; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.api.room.RoomSize; -import dev.compactmods.machines.config.ServerConfig; -import dev.compactmods.machines.location.LevelBlockPosition; -import dev.compactmods.machines.room.exceptions.NonexistentRoomException; -import dev.compactmods.machines.util.MathUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.nbt.Tag; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.saveddata.SavedData; -import net.minecraft.world.level.storage.DimensionDataStorage; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.naming.OperationNotSupportedException; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Stream; - -public class CompactRoomData extends SavedData { - public static final String DATA_NAME = Constants.MOD_ID + "_rooms"; - - private final Map roomData; - - public CompactRoomData() { - roomData = new HashMap<>(); - } - - @Nonnull - public static CompactRoomData get(ServerLevel compactDim) { - DimensionDataStorage sd = compactDim.getDataStorage(); - return sd.computeIfAbsent(CompactRoomData::fromNbt, CompactRoomData::new, DATA_NAME); - } - - public static CompactRoomData fromNbt(CompoundTag nbt) { - CompactRoomData data = new CompactRoomData(); - if (nbt.contains("machines")) { - ListTag machines = nbt.getList("machines", Tag.TAG_COMPOUND); - machines.forEach(machNbt -> { - DataResult result = - RoomData.CODEC.parse(NbtOps.INSTANCE, machNbt); - - result - .resultOrPartial((err) -> CompactMachines.LOGGER.error("Error loading machine data from file: {}", err)) - .ifPresent(imd -> { - ChunkPos chunk = new ChunkPos(imd.getCenter()); - data.roomData.put(chunk, imd); - }); - }); - } - - return data; - } - - @Override - @Nonnull - public CompoundTag save(@Nonnull CompoundTag nbt) { - if (!roomData.isEmpty()) { - ListTag collect = roomData.values() - .stream() - .map(data -> { - DataResult n = RoomData.CODEC.encodeStart(NbtOps.INSTANCE, data); - return n.result(); - }) - .filter(Optional::isPresent) - .map(Optional::get) - .collect(NbtListCollector.toNbtList()); - - nbt.put("machines", collect); - } - - return nbt; - } - - public Stream stream() { - return roomData.keySet().stream(); - } - - public boolean isRegistered(ChunkPos chunkPos) { - return roomData.containsKey(chunkPos); - } - - private void register(ChunkPos pos, RoomData data) throws OperationNotSupportedException { - if (isRegistered(pos)) - throw new OperationNotSupportedException("Machine already registered."); - - roomData.put(pos, data); - setDirty(); - } - - public Optional forRoom(ChunkPos room) { - if (roomData.containsKey(room)) - return Optional.ofNullable(roomData.get(room)); - - return Optional.empty(); - } - - public Stream streamRooms() { - return roomData.values().stream(); - } - - @Nullable - public LevelBlockPosition getSpawn(ChunkPos roomChunk) { - RoomData roomData = this.roomData.get(roomChunk); - if (roomData == null) - return null; - - return new LevelBlockPosition( - CompactDimension.LEVEL_KEY, - roomData.getSpawn() - ); - } - - public int getNextSpiralPosition() { - return this.roomData.size() + 1; - } - - public void setSpawn(ChunkPos roomChunk, Vec3 position) { - if (!roomData.containsKey(roomChunk)) - return; - - RoomData roomData = this.roomData.get(roomChunk); - roomData.setSpawn(position); - - setDirty(); - } - - public AABB getBounds(ChunkPos roomChunk) throws NonexistentRoomException { - if (!roomData.containsKey(roomChunk)) - throw new NonexistentRoomException(roomChunk); - - return roomData.get(roomChunk).getRoomBounds(); - } - - public NewRoomRegistration createNew() { - return new NewRoomRegistration(this); - } - - public boolean isMachineRoomChunk(ChunkPos pos) { - return roomData.containsKey(pos); - } - - public void remove(ChunkPos room) { - roomData.remove(room); - setDirty(); - } - - public RoomData getData(ChunkPos room) throws NonexistentRoomException { - if (!roomData.containsKey(room)) - throw new NonexistentRoomException(room); - - return roomData.get(room); - } - - public static class NewRoomRegistration { - - private final CompactRoomData storage; - private Vec3 spawn; - private ChunkPos chunk = new ChunkPos(0, 0); - private RoomSize size = RoomSize.TINY; - private BlockPos center = BlockPos.ZERO; - private UUID owner; - - public NewRoomRegistration(CompactRoomData storage) { - this.storage = storage; - } - - private void recalculateSize() { - BlockPos centerAtFloor = MathUtil.getCenterWithY(chunk, ServerConfig.MACHINE_FLOOR_Y.get()); - BlockPos centerSized = centerAtFloor.above(size.getInternalSize() / 2); - - this.spawn = new Vec3(centerAtFloor.getX(), centerAtFloor.getY(), centerAtFloor.getZ()); - this.center = centerSized; - } - - public NewRoomRegistration owner(UUID owner) { - this.owner = owner; - return this; - } - - public NewRoomRegistration size(RoomSize size) { - this.size = size; - recalculateSize(); - return this; - } - - public NewRoomRegistration spawn(BlockPos spawn) { - Vec3 spawnTest = new Vec3(spawn.getX(), spawn.getY(), spawn.getZ()); - - // Make sure the spawn is inside the new room bounds - if (size.getBounds(this.center).contains(spawnTest)) - this.spawn = spawnTest; - - return this; - } - - public NewRoomRegistration chunk(ChunkPos chunk) { - this.chunk = chunk; - recalculateSize(); - return this; - } - - public void register() throws OperationNotSupportedException { - RoomData data = new RoomData(owner, center, spawn, size, Optional.empty()); - storage.register(chunk, data); - } - } - - public static class RoomData { - - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - CodecExtensions.UUID_CODEC.fieldOf("owner").forGetter(RoomData::getOwner), - BlockPos.CODEC.fieldOf("center").forGetter(RoomData::getCenter), - CodecExtensions.VECTOR3D.fieldOf("spawn").forGetter(RoomData::getSpawn), - RoomSize.CODEC.fieldOf("size").forGetter(RoomData::getSize), - Codec.STRING.optionalFieldOf("name").forGetter(RoomData::getName) - ).apply(i, RoomData::new)); - - private final UUID owner; - private final BlockPos center; - private Vec3 spawn; - private final RoomSize size; - private boolean hasCustomName; - private String name; - - public RoomData(UUID owner, BlockPos center, Vec3 spawn, RoomSize size, Optional name) { - this.owner = owner; - this.center = center; - this.spawn = spawn; - this.size = size; - - name.ifPresentOrElse(n -> { - this.name = n; - this.hasCustomName = true; - }, () -> { - this.hasCustomName = false; - }); - } - - public RoomSize getSize() { - return this.size; - } - - public UUID getOwner() { - return this.owner; - } - - public Vec3 getSpawn() { - if (this.spawn != null) - return this.spawn; - - Vec3 newSpawn = new Vec3( - center.getX(), - center.getY(), - center.getZ() - ); - - double offset = size.getInternalSize() / 2.0d; - - this.spawn = newSpawn.subtract(0, offset, 0); - return this.spawn; - } - - public BlockPos getCenter() { - return this.center; - } - - public void setSpawn(Vec3 newSpawn) { - this.spawn = newSpawn; - } - - public AABB getRoomBounds() { - return size.getBounds(this.center); - } - - public boolean hasName() { - return this.hasCustomName; - } - - public void setName(String newName) { - this.hasCustomName = true; - this.name = newName; - } - - public Optional getName() { - return hasCustomName ? Optional.ofNullable(name) : Optional.empty(); - } - } -} diff --git a/src/main/java/dev/compactmods/machines/room/exceptions/NonexistentRoomException.java b/src/main/java/dev/compactmods/machines/room/exceptions/NonexistentRoomException.java deleted file mode 100644 index 29165334..00000000 --- a/src/main/java/dev/compactmods/machines/room/exceptions/NonexistentRoomException.java +++ /dev/null @@ -1,16 +0,0 @@ -package dev.compactmods.machines.room.exceptions; - -import net.minecraft.world.level.ChunkPos; - -public class NonexistentRoomException extends Throwable { - private final ChunkPos room; - - public NonexistentRoomException(ChunkPos room) { - super("The requested room could not be found."); - this.room = room; - } - - public ChunkPos getRoom() { - return room; - } -} diff --git a/src/main/java/dev/compactmods/machines/room/graph/CompactMachineRoomNode.java b/src/main/java/dev/compactmods/machines/room/graph/CompactMachineRoomNode.java deleted file mode 100644 index ed42f446..00000000 --- a/src/main/java/dev/compactmods/machines/room/graph/CompactMachineRoomNode.java +++ /dev/null @@ -1,35 +0,0 @@ -package dev.compactmods.machines.room.graph; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.codec.CodecExtensions; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.graph.Graph; -import dev.compactmods.machines.graph.IGraphNode; -import dev.compactmods.machines.graph.IGraphNodeType; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.ChunkPos; - -/** - * Represents the inside of a Compact Machine. - */ -public record CompactMachineRoomNode(ChunkPos pos) implements IGraphNode { - - private static final ResourceLocation TYPE = new ResourceLocation(Constants.MOD_ID, "room"); - - public static final Codec CODEC = RecordCodecBuilder.create((i) -> i.group( - CodecExtensions.CHUNKPOS.fieldOf("chunk").forGetter(CompactMachineRoomNode::pos), - ResourceLocation.CODEC.fieldOf("type").forGetter(x -> TYPE) - ).apply(i, (pos, type) -> new CompactMachineRoomNode(pos))); - - @Override - public String toString() { - return "CompactMachineRoomNode[" + - "pos=" + pos + ']'; - } - - @Override - public IGraphNodeType getType() { - return Graph.ROOM_NODE.get(); - } -} diff --git a/src/main/java/dev/compactmods/machines/room/history/PlayerRoomHistoryItem.java b/src/main/java/dev/compactmods/machines/room/history/PlayerRoomHistoryItem.java deleted file mode 100644 index 86141107..00000000 --- a/src/main/java/dev/compactmods/machines/room/history/PlayerRoomHistoryItem.java +++ /dev/null @@ -1,27 +0,0 @@ -package dev.compactmods.machines.room.history; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.location.IDimensionalBlockPosition; -import dev.compactmods.machines.api.location.IDimensionalPosition; -import dev.compactmods.machines.api.room.history.IRoomHistoryItem; -import dev.compactmods.machines.location.LevelBlockPosition; -import dev.compactmods.machines.location.PreciseDimensionalPosition; - -public record PlayerRoomHistoryItem(PreciseDimensionalPosition entry, LevelBlockPosition machine) implements IRoomHistoryItem { - - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - PreciseDimensionalPosition.CODEC.fieldOf("position").forGetter(PlayerRoomHistoryItem::entry), - LevelBlockPosition.CODEC.fieldOf("machine").forGetter(PlayerRoomHistoryItem::machine) - ).apply(i, PlayerRoomHistoryItem::new)); - - @Override - public IDimensionalPosition getEntryLocation() { - return entry; - } - - @Override - public IDimensionalBlockPosition getMachine() { - return machine; - } -} diff --git a/src/main/java/dev/compactmods/machines/room/network/ClientRoomNetworkHandler.java b/src/main/java/dev/compactmods/machines/room/network/ClientRoomNetworkHandler.java deleted file mode 100644 index 2dcc7532..00000000 --- a/src/main/java/dev/compactmods/machines/room/network/ClientRoomNetworkHandler.java +++ /dev/null @@ -1,15 +0,0 @@ -package dev.compactmods.machines.room.network; - -import dev.compactmods.machines.room.client.MachineRoomScreen; -import dev.compactmods.machines.room.menu.MachineRoomMenu; -import net.minecraft.client.Minecraft; - -public class ClientRoomNetworkHandler { - public static void handleBlockData(InitialRoomBlockDataPacket blockData) { - final var mc = Minecraft.getInstance(); - if(mc.screen instanceof MachineRoomScreen mrs) { - mrs.getMenu().setBlocks(blockData.blocks()); - mrs.updateBlockRender(); - } - } -} diff --git a/src/main/java/dev/compactmods/machines/room/network/PlayerRequestedTeleportPacket.java b/src/main/java/dev/compactmods/machines/room/network/PlayerRequestedTeleportPacket.java deleted file mode 100644 index 45ebf790..00000000 --- a/src/main/java/dev/compactmods/machines/room/network/PlayerRequestedTeleportPacket.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.compactmods.machines.room.network; - -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.location.LevelBlockPosition; -import dev.compactmods.machines.dimension.MissingDimensionException; -import dev.compactmods.machines.util.PlayerUtil; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.level.ChunkPos; -import net.minecraftforge.network.NetworkEvent; - -import java.util.function.Supplier; - -public record PlayerRequestedTeleportPacket(LevelBlockPosition machine, ChunkPos room) { - - public PlayerRequestedTeleportPacket(FriendlyByteBuf buf) { - this(buf.readWithCodec(LevelBlockPosition.CODEC), buf.readChunkPos()); - } - - public void encode(FriendlyByteBuf buf) { - buf.writeWithCodec(LevelBlockPosition.CODEC, machine); - buf.writeChunkPos(room); - } - - public boolean handle(Supplier ctx) { - ctx.get().enqueueWork(() -> { - final var player = ctx.get().getSender(); - try { - PlayerUtil.teleportPlayerIntoMachine(player.level, player, machine.getBlockPosition()); - } catch (MissingDimensionException e) { - CompactMachines.LOGGER.error("Failed to teleport player into machine.", e); - } - }); - - return true; - } -} diff --git a/src/main/java/dev/compactmods/machines/room/network/PlayerStartedRoomTrackingPacket.java b/src/main/java/dev/compactmods/machines/room/network/PlayerStartedRoomTrackingPacket.java deleted file mode 100644 index c06e2b71..00000000 --- a/src/main/java/dev/compactmods/machines/room/network/PlayerStartedRoomTrackingPacket.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.compactmods.machines.room.network; - -import dev.compactmods.machines.dimension.MissingDimensionException; -import dev.compactmods.machines.room.Rooms; -import dev.compactmods.machines.room.exceptions.NonexistentRoomException; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.level.ChunkPos; -import net.minecraftforge.network.NetworkEvent; -import net.minecraftforge.network.PacketDistributor; - -import java.util.function.Supplier; - -public record PlayerStartedRoomTrackingPacket(ChunkPos room) { - - public PlayerStartedRoomTrackingPacket(FriendlyByteBuf buf) { - this(buf.readChunkPos()); - } - - public void encode(FriendlyByteBuf buf) { - buf.writeChunkPos(room); - } - - public boolean handle(Supplier ctx) { - var sender = ctx.get().getSender(); - ctx.get().enqueueWork(() -> { - try { - var blocks = Rooms.getInternalBlocks(sender.server, room); - RoomNetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> sender), new InitialRoomBlockDataPacket(blocks)); - } catch (MissingDimensionException | NonexistentRoomException e) { - e.printStackTrace(); - } - }); - - return true; - } -} diff --git a/src/main/java/dev/compactmods/machines/shrinking/Shrinking.java b/src/main/java/dev/compactmods/machines/shrinking/Shrinking.java deleted file mode 100644 index 99b2db8b..00000000 --- a/src/main/java/dev/compactmods/machines/shrinking/Shrinking.java +++ /dev/null @@ -1,18 +0,0 @@ -package dev.compactmods.machines.shrinking; - -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.core.Registries; -import net.minecraft.world.item.Item; -import net.minecraftforge.registries.RegistryObject; - -public class Shrinking { - - public static final RegistryObject PERSONAL_SHRINKING_DEVICE = Registries.ITEMS.register("personal_shrinking_device", - () -> new PersonalShrinkingDevice(new Item.Properties() - .tab(CompactMachines.COMPACT_MACHINES_ITEMS) - .stacksTo(1))); - - public static void prepare() { - - } -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/BaseTunnelWallData.java b/src/main/java/dev/compactmods/machines/tunnel/BaseTunnelWallData.java deleted file mode 100644 index 6c07ae7a..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/BaseTunnelWallData.java +++ /dev/null @@ -1,21 +0,0 @@ -package dev.compactmods.machines.tunnel; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import dev.compactmods.machines.location.LevelBlockPosition; -import net.minecraft.resources.ResourceLocation; - -public record BaseTunnelWallData(LevelBlockPosition connection, ResourceLocation tunnelType) { - public static final String KEY_CONNECTION = "connection"; - public static final String KEY_TUNNEL_TYPE = "tunnel_type"; - - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - LevelBlockPosition.CODEC.fieldOf(KEY_CONNECTION).forGetter(BaseTunnelWallData::connection), - ResourceLocation.CODEC.fieldOf(KEY_TUNNEL_TYPE).forGetter(BaseTunnelWallData::tunnelType) - ).apply(i, BaseTunnelWallData::new)); - - public TunnelDefinition tunnel() { - return Tunnels.getDefinition(tunnelType); - } -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/SidedPosition.java b/src/main/java/dev/compactmods/machines/tunnel/SidedPosition.java deleted file mode 100644 index 37fddfc5..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/SidedPosition.java +++ /dev/null @@ -1,7 +0,0 @@ -package dev.compactmods.machines.tunnel; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; - -public record SidedPosition(BlockPos pos, Direction side) { -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/TunnelHelper.java b/src/main/java/dev/compactmods/machines/tunnel/TunnelHelper.java deleted file mode 100644 index f64b1895..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/TunnelHelper.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.compactmods.machines.tunnel; - -import net.minecraft.core.Direction; - -import javax.annotation.Nonnull; -import java.util.Collection; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Stream; - -public class TunnelHelper { - - @Nonnull - public static Direction getNextDirection(Direction in) { - return switch (in) { - case UP -> Direction.DOWN; - case DOWN -> Direction.NORTH; - case NORTH -> Direction.SOUTH; - case SOUTH -> Direction.WEST; - case WEST -> Direction.EAST; - case EAST -> Direction.UP; - }; - } - - public static Stream getOrderedSides() { - return Stream.of(Direction.UP, Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST); - } - - public static Optional getNextDirection(Direction current, Set used) { - final var ordered = getOrderedSides().toList(); - final var found = ordered.indexOf(current); - final var stream = Stream.generate(() -> ordered).flatMap(Collection::stream); - - return stream.skip(found + 1).filter(dir -> !used.contains(dir)).findFirst(); - } -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/TunnelWallBlock.java b/src/main/java/dev/compactmods/machines/tunnel/TunnelWallBlock.java deleted file mode 100644 index c1ecce79..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/TunnelWallBlock.java +++ /dev/null @@ -1,161 +0,0 @@ -package dev.compactmods.machines.tunnel; - -import dev.compactmods.machines.api.core.Messages; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import dev.compactmods.machines.api.tunnels.TunnelPosition; -import dev.compactmods.machines.api.tunnels.lifecycle.TunnelTeardownHandler; -import dev.compactmods.machines.i18n.TranslationUtil; -import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; -import dev.compactmods.machines.wall.ProtectedWallBlock; -import dev.compactmods.machines.wall.Walls; -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -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.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.phys.BlockHitResult; - -import javax.annotation.Nullable; -import java.util.Optional; -import java.util.stream.Collectors; - -@SuppressWarnings("deprecation") -public class TunnelWallBlock extends ProtectedWallBlock implements EntityBlock { - public static final DirectionProperty TUNNEL_SIDE = DirectionProperty.create("tunnel_side", Direction.values()); - public static final DirectionProperty CONNECTED_SIDE = DirectionProperty.create("connected_side", Direction.values()); - - public static final BooleanProperty REDSTONE = BooleanProperty.create("redstone"); - - public TunnelWallBlock(Properties props) { - super(props); - registerDefaultState(getStateDefinition().any() - .setValue(CONNECTED_SIDE, Direction.UP) - .setValue(TUNNEL_SIDE, Direction.UP) - .setValue(REDSTONE, false) - ); - } - - public static Optional getTunnelInfo(BlockGetter world, BlockPos position) { - TunnelWallEntity tile = (TunnelWallEntity) world.getBlockEntity(position); - if (tile == null) - return Optional.empty(); - - return Optional.ofNullable(tile.getTunnelType()); - } - - @Override - public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos position, @Nullable Direction side) { - return state.getValue(REDSTONE); - } - - @Override - public boolean isSignalSource(BlockState state) { - return state.getValue(REDSTONE); - } - - @Override - public int getDirectSignal(BlockState state, BlockGetter world, BlockPos position, Direction side) { - return 0; - } - - @Override - public int getSignal(BlockState state, BlockGetter world, BlockPos position, Direction side) { - // TODO - Redstone tunnels - // Optional tunnelInfo = getTunnelInfo(world, position); - return 0; - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(TUNNEL_SIDE).add(CONNECTED_SIDE).add(REDSTONE); - super.createBlockStateDefinition(builder); - } - - @Nullable - @Override - public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { - return new TunnelWallEntity(pos, state); - } - - @Override - public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { - if (level.isClientSide) - return InteractionResult.SUCCESS; - - if (!(level.getBlockEntity(pos) instanceof TunnelWallEntity tunnel)) - return InteractionResult.FAIL; - - if(level.dimension().equals(CompactDimension.LEVEL_KEY) && level instanceof ServerLevel compactDim) { - var def = tunnel.getTunnelType(); - final Direction tunnelWallSide = hitResult.getDirection(); - - if (player.isShiftKeyDown()) { - BlockState solidWall = Walls.BLOCK_SOLID_WALL.get().defaultBlockState(); - - level.setBlockAndUpdate(pos, solidWall); - - ItemStack stack = new ItemStack(Tunnels.ITEM_TUNNEL.get(), 1); - CompoundTag defTag = stack.getOrCreateTagElement("definition"); - defTag.putString("id", Tunnels.getRegistryId(def).toString()); - - ItemEntity ie = new ItemEntity(level, player.getX(), player.getY(), player.getZ(), stack); - level.addFreshEntity(ie); - - if (def instanceof TunnelTeardownHandler teardown) { - teardown.onRemoved(new TunnelPosition(compactDim, pos, tunnelWallSide), tunnel.getTunnel()); - } - - final var tunnels = TunnelConnectionGraph.forRoom(compactDim, new ChunkPos(pos)); - tunnels.unregister(pos); - } else { - // Rotate tunnel - Direction dir = state.getValue(CONNECTED_SIDE); - - final var tunnelGraph = TunnelConnectionGraph.forRoom(compactDim, new ChunkPos(pos)); - final var existingDirs = tunnelGraph - .getTunnelSides(def) - .collect(Collectors.toSet()); - - if (existingDirs.size() == 6) { - // WARN PLAYER - NO OTHER SIDES REMAIN - player.displayClientMessage( - TranslationUtil.message(Messages.NO_TUNNEL_SIDE).withStyle(ChatFormatting.DARK_RED), true); - - return InteractionResult.FAIL; - } - - final var next = TunnelHelper.getNextDirection(dir, existingDirs); - next.ifPresent(newSide -> { - level.setBlockAndUpdate(pos, state.setValue(CONNECTED_SIDE, newSide)); - - if (def instanceof TunnelTeardownHandler teardown) { - teardown.onRotated(new TunnelPosition(compactDim, pos, tunnelWallSide), tunnel.getTunnel(), dir, newSide); - } - - tunnelGraph.rotateTunnel(pos, newSide); - tunnelGraph.setDirty(); - }); - } - } - - return InteractionResult.SUCCESS; - } - - // todo - breaking block unregisters tunnel info -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/TunnelWallEntity.java b/src/main/java/dev/compactmods/machines/tunnel/TunnelWallEntity.java deleted file mode 100644 index c993ed80..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/TunnelWallEntity.java +++ /dev/null @@ -1,284 +0,0 @@ -package dev.compactmods.machines.tunnel; - -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.api.location.IDimensionalBlockPosition; -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.InstancedTunnel; -import dev.compactmods.machines.api.tunnels.lifecycle.TunnelInstance; -import dev.compactmods.machines.api.tunnels.lifecycle.TunnelTeardownHandler; -import dev.compactmods.machines.dimension.MissingDimensionException; -import dev.compactmods.machines.location.LevelBlockPosition; -import dev.compactmods.machines.machine.graph.legacy.LegacyMachineLocationsGraph; -import dev.compactmods.machines.tunnel.graph.TunnelConnectionGraph; -import dev.compactmods.machines.wall.Walls; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.common.util.LazyOptional; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class TunnelWallEntity extends BlockEntity { - - private static final String NBT_LEGACY_MACHINE_KEY = "machine"; - - @Deprecated(forRemoval = true) - private int legacyMachineId = -1; - - private LevelBlockPosition connectedMachine; - private TunnelDefinition tunnelType; - - @Nullable - private TunnelInstance tunnel; - - public TunnelWallEntity(BlockPos pos, BlockState state) { - super(Tunnels.TUNNEL_BLOCK_ENTITY.get(), pos, state); - } - - @Override - @SuppressWarnings("unchecked") - public void load(@Nonnull CompoundTag nbt) { - super.load(nbt); - - try { - // TODO - Remove in 5.0 - if(nbt.contains(NBT_LEGACY_MACHINE_KEY)) { - // 4.2 and below - this.legacyMachineId = nbt.getInt(NBT_LEGACY_MACHINE_KEY); - this.tunnelType = Tunnels.getDefinition(new ResourceLocation(nbt.getString(BaseTunnelWallData.KEY_TUNNEL_TYPE))); - } else { - // 4.3 and above - final var baseData = BaseTunnelWallData.CODEC.parse(NbtOps.INSTANCE, nbt) - .getOrThrow(true, CompactMachines.LOGGER::fatal); - - this.connectedMachine = baseData.connection(); - this.tunnelType = baseData.tunnel(); - } - } catch (Exception e) { - this.tunnelType = Tunnels.UNKNOWN.get(); - this.connectedMachine = null; - } - - try { - if (tunnelType instanceof InstancedTunnel it) - this.tunnel = it.newInstance(worldPosition, getTunnelSide()); - - if (tunnel instanceof INBTSerializable persist && nbt.contains("tunnel_data")) { - var data = nbt.get("tunnel_data"); - persist.deserializeNBT(data); - } - } catch (Exception ex) { - CompactMachines.LOGGER.error("Error loading tunnel persistent data at {}; this is likely a cross-mod issue!", worldPosition, ex); - } - } - - @Override - public void onLoad() { - super.onLoad(); - - if (level instanceof ServerLevel sl) { - if(legacyMachineId > -1) { - try { - this.upgradeLegacyData(); - } catch (MissingDimensionException e) { - CompactMachines.LOGGER.error(CompactMachines.CONN_MARKER, "Failed to load legacy location info for tunnel conversion at: {}; removing the tunnel instance.", worldPosition); - this.tunnelType = Tunnels.UNKNOWN.get(); - } - } - - // If tunnel type is unknown, remove the tunnel entirely - // Null tunnel types here mean it's being loaded into the world - if (this.tunnelType != null && tunnelType.equals(Tunnels.UNKNOWN.get())) { - CompactMachines.LOGGER.warn("Removing unknown tunnel type at {}", worldPosition.toShortString()); - sl.setBlock(worldPosition, Walls.BLOCK_SOLID_WALL.get().defaultBlockState(), Block.UPDATE_ALL); - } - } - } - - private void upgradeLegacyData() throws MissingDimensionException { - if(level != null && level.isClientSide) return; - if(this.legacyMachineId == -1) return; - - if(level instanceof ServerLevel sl) { - var leg = LegacyMachineLocationsGraph.get(sl.getServer()); - if(leg != null) - this.connectedMachine = leg.getLocation(this.legacyMachineId); - else { - CompactMachines.LOGGER.error(CompactMachines.CONN_MARKER, "Failed to load legacy location info for tunnel conversion at: {}; removing the tunnel instance.", worldPosition); - this.tunnelType = Tunnels.UNKNOWN.get(); - } - } - } - - @Override - public void saveAdditional(@Nonnull CompoundTag compound) { - if (tunnelType != null) - compound.putString(BaseTunnelWallData.KEY_TUNNEL_TYPE, Tunnels.getRegistryId(tunnelType).toString()); - else - compound.putString(BaseTunnelWallData.KEY_TUNNEL_TYPE, Tunnels.UNKNOWN.getId().toString()); - - if (connectedMachine != null) - compound.put(BaseTunnelWallData.KEY_CONNECTION, connectedMachine.serializeNBT()); - - if (tunnel instanceof INBTSerializable persist) { - var data = persist.serializeNBT(); - compound.put("tunnel_data", data); - } - } - - @Override - @Nonnull - public CompoundTag getUpdateTag() { - CompoundTag nbt = super.getUpdateTag(); - nbt.putString(BaseTunnelWallData.KEY_TUNNEL_TYPE, Tunnels.getRegistryId(tunnelType).toString()); - nbt.put(BaseTunnelWallData.KEY_CONNECTION, connectedMachine.serializeNBT()); - return nbt; - } - - @Override - public void handleUpdateTag(CompoundTag tag) { - super.handleUpdateTag(tag); - if (tag.contains(BaseTunnelWallData.KEY_TUNNEL_TYPE)) { - var id = new ResourceLocation(tag.getString(BaseTunnelWallData.KEY_TUNNEL_TYPE)); - this.tunnelType = Tunnels.getDefinition(id); - } - - if (tag.contains(BaseTunnelWallData.KEY_CONNECTION)) { - this.connectedMachine = LevelBlockPosition.fromNBT(tag.getCompound(BaseTunnelWallData.KEY_CONNECTION)); - } - - setChanged(); - } - - @Nonnull - public LazyOptional getTunnelCapability(@Nonnull Capability cap, @Nullable Direction outerSide) { - if (level == null || level.isClientSide) - return LazyOptional.empty(); - - if (outerSide != null && outerSide != getConnectedSide()) - return LazyOptional.empty(); - - if (tunnelType instanceof CapabilityTunnel c) { - return c.getCapability(cap, tunnel); - } - - return LazyOptional.empty(); - } - - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { - if (level == null || level.isClientSide) - return super.getCapability(cap, side); - - if (side != null && side != getTunnelSide()) - return super.getCapability(cap, side); - - if (tunnelType instanceof CapabilityTunnel c) { - return c.getCapability(cap, tunnel); - } - - return super.getCapability(cap, side); - } - - public IDimensionalBlockPosition getConnectedPosition() { - if (this.connectedMachine == null) - return null; - - return this.connectedMachine.relative(getConnectedSide()); - } - - /** - * Gets the side the tunnel is placed on (the wall inside the machine) - */ - public Direction getTunnelSide() { - BlockState state = getBlockState(); - return state.getValue(TunnelWallBlock.TUNNEL_SIDE); - } - - /** - * Gets the side the tunnel connects to externally (the machine side) - */ - public Direction getConnectedSide() { - BlockState blockState = getBlockState(); - return blockState.getValue(TunnelWallBlock.CONNECTED_SIDE); - } - - public void setTunnelType(TunnelDefinition type) { - if (type == tunnelType) - return; - - if (level == null || level.isClientSide || !(level instanceof ServerLevel sl)) { - tunnelType = type; - return; - } - - final var p = new TunnelPosition(sl, worldPosition, getTunnelSide()); - if (tunnelType instanceof TunnelTeardownHandler teardown) { - teardown.onRemoved(p, tunnel); - } - - this.tunnelType = type; - if (type instanceof InstancedTunnel it) - this.tunnel = it.newInstance(p.pos(), p.side()); - - setChanged(); - } - - public TunnelDefinition getTunnelType() { - return tunnelType; - } - - /** - * Server only. Changes where the tunnel is connected to. - * - * @param machine Machine to connect tunnel to. - */ - public void setConnectedTo(IDimensionalBlockPosition machine, Direction side) { - if (level == null || level.isClientSide) return; - this.connectedMachine = new LevelBlockPosition(machine); - - if (level instanceof ServerLevel sl) { - final var graph = TunnelConnectionGraph.forRoom(sl, new ChunkPos(worldPosition)); - graph.rebind(worldPosition, machine, side); - } - } - - @Nullable - public TunnelInstance getTunnel() { - return tunnel; - } - - public void setInstance(TunnelInstance newTunn) { - this.tunnel = newTunn; - setChanged(); - } - - public void disconnect() { - if (level == null || level.isClientSide) { - this.connectedMachine = null; - return; - } - - if (level instanceof ServerLevel compactDim && compactDim.dimension().equals(CompactDimension.LEVEL_KEY)) { - final var tunnelData = TunnelConnectionGraph.forRoom(compactDim, new ChunkPos(worldPosition)); - tunnelData.unregister(worldPosition); - - this.connectedMachine = null; - compactDim.setBlock(worldPosition, Walls.BLOCK_SOLID_WALL.get().defaultBlockState(), Block.UPDATE_ALL); - } - } -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/client/ClientTunnelHandler.java b/src/main/java/dev/compactmods/machines/tunnel/client/ClientTunnelHandler.java deleted file mode 100644 index b247e796..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/client/ClientTunnelHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.compactmods.machines.tunnel.client; - -import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import dev.compactmods.machines.tunnel.TunnelWallEntity; -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; - -public class ClientTunnelHandler { - public static void setTunnel(BlockPos position, TunnelDefinition type) { - var level = Minecraft.getInstance().level; - if(level == null) return; - - Minecraft.getInstance().tell(() -> { - if (level.getBlockEntity(position) instanceof TunnelWallEntity tun) { - try { - tun.setTunnelType(type); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/client/TunnelColors.java b/src/main/java/dev/compactmods/machines/tunnel/client/TunnelColors.java deleted file mode 100644 index 2a5b2b03..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/client/TunnelColors.java +++ /dev/null @@ -1,40 +0,0 @@ -package dev.compactmods.machines.tunnel.client; - -import javax.annotation.Nullable; -import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import dev.compactmods.machines.tunnel.TunnelWallEntity; -import net.minecraft.client.color.block.BlockColor; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; - -public class TunnelColors implements BlockColor { - - @Override - public int getColor(BlockState state, @Nullable BlockAndTintGetter reader, @Nullable BlockPos position, int tintIndex) { - try { - if(reader == null || position == null) - return TunnelDefinition.NO_INDICATOR_COLOR; - - BlockEntity tile = reader.getBlockEntity(position); - if (tile instanceof TunnelWallEntity tunnel) { - TunnelDefinition type = tunnel.getTunnelType(); - - switch(tintIndex) { - case 0: - return type.ringColor(); - - case 1: - return type.indicatorColor(); - } - } - - return TunnelDefinition.NO_INDICATOR_COLOR; - } - - catch(Exception ex) { - return TunnelDefinition.NO_INDICATOR_COLOR; - } - } -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/client/TunnelItemColor.java b/src/main/java/dev/compactmods/machines/tunnel/client/TunnelItemColor.java deleted file mode 100644 index b66b256e..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/client/TunnelItemColor.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.compactmods.machines.tunnel.client; - -import java.util.Optional; -import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import dev.compactmods.machines.tunnel.TunnelItem; -import net.minecraft.client.color.item.ItemColor; -import net.minecraft.world.item.ItemStack; - -public class TunnelItemColor implements ItemColor { - @Override - public int getColor(ItemStack stack, int tintIndex) { - Optional definition = TunnelItem.getDefinition(stack); - if(!definition.isPresent()) - return 0; - - TunnelDefinition actualDef = definition.get(); - if (tintIndex == 0) { - return actualDef.ringColor(); - } - - return actualDef.indicatorColor(); - } -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelConnectionGraph.java b/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelConnectionGraph.java deleted file mode 100644 index f9c2dedd..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelConnectionGraph.java +++ /dev/null @@ -1,621 +0,0 @@ -package dev.compactmods.machines.tunnel.graph; - -import com.google.common.graph.EndpointPair; -import com.google.common.graph.MutableValueGraph; -import com.google.common.graph.ValueGraphBuilder; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.codec.NbtListCollector; -import dev.compactmods.machines.api.location.IDimensionalBlockPosition; -import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import dev.compactmods.machines.api.tunnels.capability.CapabilityTunnel; -import dev.compactmods.machines.tunnel.Tunnels; -import dev.compactmods.machines.graph.*; -import dev.compactmods.machines.location.LevelBlockPosition; -import dev.compactmods.machines.machine.graph.CompactMachineNode; -import dev.compactmods.machines.machine.graph.MachineRoomEdge; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.nbt.Tag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.saveddata.SavedData; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.INBTSerializable; - -import javax.annotation.Nonnull; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Represents a room's tunnel connections in a graph-style format. - * This should be accessed through the saved data for specific machine room chunks. - */ -public class TunnelConnectionGraph extends SavedData implements INBTSerializable { - - /** - * The full data graph. Contains tunnel nodes, machine ids, and tunnel type information. - */ - private final MutableValueGraph graph; - - /** - * Quick access to tunnel information for specific locations. - */ - private final Map tunnels; - - /** - * Quick access to machine information nodes. - */ - private final Map machines; - - /** - * Quick access to tunnel definition nodes. - */ - private final Map tunnelTypes; - - private TunnelConnectionGraph() { - graph = ValueGraphBuilder - .directed() - .build(); - - tunnels = new HashMap<>(); - machines = new HashMap<>(); - tunnelTypes = new HashMap<>(); - } - - private TunnelConnectionGraph(CompoundTag nbt) { - this(); - this.deserializeNBT(nbt); - } - - public static TunnelConnectionGraph forRoom(ServerLevel compactDim, ChunkPos room) { - final var key = getDataFilename(room); - return compactDim.getDataStorage().computeIfAbsent( - TunnelConnectionGraph::new, - TunnelConnectionGraph::new, - key - ); - } - - @Nonnull - @Override - public CompoundTag save(CompoundTag tag) { - var gData = this.serializeNBT(); - tag.put("graph", gData); - return tag; - } - - public static String getDataFilename(ChunkPos room) { - return "tunnels_" + room.x + "_" + room.z; - } - - /** - * Finds which machine a tunnel is connected to. - * - * @param tunnel The tunnel to find a connection for. - * @return The id of the connected machine. - */ - public Optional connectedMachine(BlockPos tunnel) { - if (!tunnels.containsKey(tunnel)) - return Optional.empty(); - - var tNode = tunnels.get(tunnel); - return graph.successors(tNode) - .stream() - .filter(CompactMachineNode.class::isInstance) - .map(CompactMachineNode.class::cast) - .findFirst() - .map(CompactMachineNode::dimpos); - } - - /** - * Registers a tunnel as being connected to a machine on a particular side. - * If the tunnel already is registered, this will report a failure. - * - * @param tunnelPos The position of the tunnel inside the room. - * @param type The type of tunnel being registered. - * @param machine The machine the tunnel is to be connected to. - * @param side The side of the machine the tunnel is connecting to. - * @return True if the connection could be established; false if the tunnel type is already registered for the given side. - */ - public boolean registerTunnel(BlockPos tunnelPos, TunnelDefinition type, IDimensionalBlockPosition machine, Direction side) { - // First we need to get the machine the tunnel is trying to connect to - var machineNode = getOrCreateMachineNode(machine); - var tunnelNode = getOrCreateTunnelNode(tunnelPos); - if (graph.hasEdgeConnecting(tunnelNode, machineNode)) { - // connection already formed between the tunnel at pos and the machine - CompactMachines.LOGGER.info("Tunnel already registered for machine {} at position {}.", - machine, - tunnelPos); - - return false; - } - - var tunnelTypeNode = getOrCreateTunnelTypeNode(type); - - // no tunnels registered for side yet - free to make new tunnel node - var newTM = graph.putEdgeValue(tunnelNode, machineNode, new TunnelMachineEdge(side)); - var newTT = graph.putEdgeValue(tunnelNode, tunnelTypeNode, new TunnelTypeEdge()); - - setDirty(); - return true; - } - - private void createTunnelAndLink(TunnelNode newTunnel, Direction side, CompactMachineNode machNode, TunnelTypeNode typeNode) { - - } - - @Nonnull - public TunnelNode getOrCreateTunnelNode(BlockPos tunnelPos) { - if (tunnels.containsKey(tunnelPos)) - return tunnels.get(tunnelPos); - - var newTunnel = new TunnelNode(tunnelPos); - tunnels.put(tunnelPos, newTunnel); - graph.addNode(newTunnel); - setDirty(); - - return newTunnel; - } - - public CompactMachineNode getOrCreateMachineNode(IDimensionalBlockPosition machine) { - var machineRegistered = machines.containsKey(machine); - CompactMachineNode node; - if (!machineRegistered) { - node = new CompactMachineNode(machine.dimensionKey(), machine.getBlockPosition()); - machines.put(machine, node); - graph.addNode(node); - setDirty(); - } else { - node = machines.get(machine); - } - - return node; - } - - public TunnelTypeNode getOrCreateTunnelTypeNode(TunnelDefinition definition) { - final ResourceLocation id = Tunnels.getRegistryId(definition); - - if (tunnelTypes.containsKey(id)) - return tunnelTypes.get(id); - - TunnelTypeNode newType = new TunnelTypeNode(id); - tunnelTypes.put(id, newType); - graph.addNode(newType); - setDirty(); - return newType; - } - - /** - * Gets the number of registered nodes in the graph. - */ - public int size() { - return graph.nodes().size(); - } - - @Deprecated(forRemoval = true, since = "5.0.0") - public Stream getTunnelNodesByType(TunnelDefinition type) { - final var id = Tunnels.getRegistryId(type); - return getTunnelNodesByType(id); - } - - public Stream getTunnelNodesByType(ResourceLocation type) { - var defNode = tunnelTypes.get(type); - if (defNode == null) - return Stream.empty(); - - return graph.adjacentNodes(defNode) - .stream() - .filter(TunnelNode.class::isInstance) - .map(TunnelNode.class::cast); - } - - @Deprecated(forRemoval = true, since = "5.0.0") - public Set getTunnelsByType(TunnelDefinition type) { - return getTunnelNodesByType(type) - .map(TunnelNode::position) - .map(BlockPos::immutable) - .collect(Collectors.toSet()); - } - - public Optional getTunnelSide(TunnelNode node) { - return graph.adjacentNodes(node).stream() - .filter(CompactMachineNode.class::isInstance) - .map(mn -> graph.edgeValue(node, mn)) - .filter(Optional::isPresent) - .map(Optional::get) - .map(TunnelMachineEdge.class::cast) - .map(TunnelMachineEdge::side) - .findFirst(); - } - - public Optional getTunnelSide(BlockPos pos) { - if (!tunnels.containsKey(pos)) - return Optional.empty(); - - var node = tunnels.get(pos); - return graph.adjacentNodes(node).stream() - .filter(CompactMachineNode.class::isInstance) - .map(mn -> graph.edgeValue(node, mn)) - .filter(Optional::isPresent) - .map(Optional::get) - .map(TunnelMachineEdge.class::cast) - .map(TunnelMachineEdge::side) - .findFirst(); - } - - public Optional getTunnelInfo(BlockPos tunnel) { - if (!tunnels.containsKey(tunnel)) - return Optional.empty(); - - var node = tunnels.get(tunnel); - var typeNode = graph.successors(node).stream() - .filter(TunnelTypeNode.class::isInstance) - .map(TunnelTypeNode.class::cast) - .findFirst() - .orElseThrow(); - - var mach = connectedMachine(tunnel).orElseThrow(); - var side = getTunnelSide(tunnel).orElseThrow(); - var type = typeNode.id(); - - return Optional.of(new TunnelMachineInfo(tunnel, type, new LevelBlockPosition(mach), side)); - } - - public Stream tunnels() { - return tunnels.keySet().stream() - .map(this::getTunnelInfo) - .filter(Optional::isPresent) - .map(Optional::get); - } - - public Stream nodes() { - return graph.nodes().stream(); - } - - @Override - public CompoundTag serializeNBT() { - cleanupOrphans(); - - CompoundTag tag = new CompoundTag(); - - HashMap nodeIds = new HashMap<>(); - - final var nodeReg = Graph.NODE_TYPE_REG.get(); - final var nodeRegCodec = nodeReg.getCodec() - .dispatchStable(IGraphNode::getType, IGraphNodeType::codec); - - var nodeList = nodes().map(node -> { - CompoundTag nodeInfo = new CompoundTag(); - - var encoded = nodeRegCodec.encodeStart(NbtOps.INSTANCE, node); - var nodeEncoded = encoded.getOrThrow(false, CompactMachines.LOGGER::error); - - var id = UUID.randomUUID(); - nodeInfo.putUUID("id", id); - nodeInfo.put("data", nodeEncoded); - nodeIds.put(node, id); - return nodeInfo; - }).collect(NbtListCollector.toNbtList()); - - tag.put("nodes", nodeList); - - ListTag edges = new ListTag(); - for (var edge : graph.edges()) { - CompoundTag edgeInfo = new CompoundTag(); - - //noinspection OptionalGetWithoutIsPresent - var realEdge = graph.edgeValue(edge).get(); - var codec = realEdge.getEdgeType().codec(); - - var encoded = codec.encodeStart(NbtOps.INSTANCE, realEdge); - var edgeEnc = encoded.getOrThrow(false, CompactMachines.LOGGER::error); - - edgeInfo.putUUID("from", nodeIds.get(edge.nodeU())); - edgeInfo.putUUID("to", nodeIds.get(edge.nodeV())); - edgeInfo.put("data", edgeEnc); - - edges.add(edgeInfo); - } - - tag.put("edges", edges); - - return tag; - } - - @Override - public void deserializeNBT(CompoundTag tag) { - if (!tag.contains("graph")) return; - - final var graphRoot = tag.getCompound("graph"); - - final var nodeReg = Graph.NODE_TYPE_REG.get(); - final var nodeRegCodec = nodeReg.getCodec() - .dispatchStable(IGraphNode::getType, IGraphNodeType::codec); - - final var edgeRegCodec = Graph.EDGE_TYPE_REG.get().getCodec() - .dispatchStable(IGraphEdge::getEdgeType, IGraphEdgeType::codec); - - final var nodes = graphRoot.getList("nodes", Tag.TAG_COMPOUND); - HashMap nodeMap = new HashMap<>(nodes.size()); - - if (graphRoot.contains("nodes", Tag.TAG_LIST)) { - for (var nodeNbt : nodes) { - if (!(nodeNbt instanceof CompoundTag nt)) - continue; - - if (!nt.contains("data") || !nt.hasUUID("id")) - continue; - - UUID nodeId = nt.getUUID("id"); - CompoundTag nodeData = nt.getCompound("data"); - - var result = nodeRegCodec.parse(NbtOps.INSTANCE, nodeData) - .getOrThrow(false, CompactMachines.LOGGER::error); - - if (result == null) continue; - - try { - if (result instanceof CompactMachineNode m) { - graph.addNode(m); - machines.put(m.dimpos(), m); - nodeMap.putIfAbsent(nodeId, m); - } - - if (result instanceof TunnelNode t) { - graph.addNode(t); - tunnels.put(t.position(), t); - nodeMap.putIfAbsent(nodeId, t); - } - - if (result instanceof TunnelTypeNode tt) { - graph.addNode(tt); - tunnelTypes.put(tt.id(), tt); - nodeMap.putIfAbsent(nodeId, tt); - } - - } catch (RuntimeException ignored) { - } - } - } - - // No edges - skip rest of processing - if (graphRoot.contains("edges", Tag.TAG_LIST)) { - final var edgeTags = graphRoot.getList("edges", Tag.TAG_COMPOUND); - for (var edgeTag : edgeTags) { - if (!(edgeTag instanceof CompoundTag edge)) - continue; - - // invalid edge data - if (!edge.contains("data") || !edge.hasUUID("from") || !edge.hasUUID("to")) - continue; - - var nodeFrom = nodeMap.get(edge.getUUID("from")); - var nodeTo = nodeMap.get(edge.getUUID("to")); - - if (nodeFrom == null || nodeTo == null) - continue; - - var edgeData = edgeRegCodec.parse(NbtOps.INSTANCE, edge.getCompound("data")) - .getOrThrow(false, CompactMachines.LOGGER::error); - - graph.putEdgeValue(nodeFrom, nodeTo, edgeData); - } - } - } - - public boolean hasTunnel(BlockPos location) { - return tunnels.containsKey(location); - } - - public Stream getTunnelsSupporting(LevelBlockPosition machine, Direction side, Capability capability) { - final var node = machines.get(machine); - if (node == null) return Stream.empty(); - - return getTunnelsForSide(machine, side) - .filter(sided -> graph.successors(sided).stream() - .filter(TunnelTypeNode.class::isInstance) - .map(TunnelTypeNode.class::cast) - .anyMatch(ttn -> { - var def = Tunnels.getDefinition(ttn.id()); - if (!(def instanceof CapabilityTunnel tcp)) - return false; - - return tcp.getSupportedCapabilities().contains(capability); - })).map(TunnelNode::position); - } - - public Stream getTypesForSide(LevelBlockPosition machine, Direction side) { - final var node = machines.get(machine); - if (node == null) return Stream.empty(); - - return getTunnelsForSide(machine, side) - .flatMap(tn -> graph.successors(tn).stream()) - .filter(TunnelTypeNode.class::isInstance) - .map(TunnelTypeNode.class::cast) - .map(type -> Tunnels.getDefinition(type.id())) - .distinct(); - } - - public Stream getTunnelsForSide(IDimensionalBlockPosition machine, Direction side) { - final var node = machines.get(machine); - if (node == null) return Stream.empty(); - - return graph.incidentEdges(node).stream() - .filter(e -> graph.edgeValue(e) - .map(ed -> ed instanceof TunnelMachineEdge tme && tme.side() == side) - .orElse(false) - ) - .map(EndpointPair::nodeU) - .filter(TunnelNode.class::isInstance) - .map(TunnelNode.class::cast); - } - - @Deprecated(forRemoval = true, since = "5.0.0") - public Stream getTunnelSides(TunnelDefinition type) { - final var id = Tunnels.getRegistryId(type); - return getTunnelSides(id); - } - - public Stream getTunnelSides(ResourceLocation type) { - if (!tunnelTypes.containsKey(type)) - return Stream.empty(); - - return getTunnelNodesByType(type) - .map(this::getTunnelSide) - .filter(Optional::isPresent) - .map(Optional::get); - } - - public void clear() { - for (var machine : machines.values()) - graph.removeNode(machine); - machines.clear(); - - for (var t : tunnelTypes.values()) - graph.removeNode(t); - tunnelTypes.clear(); - - for (var tun : tunnels.values()) - graph.removeNode(tun); - tunnels.clear(); - } - - @Deprecated(forRemoval = true, since = "5.0.0") - public Stream getMachineTunnels(IDimensionalBlockPosition machine, TunnelDefinition type) { - return getTunnelNodesByType(type) - .map(TunnelNode::position) - .filter(position -> connectedMachine(position).map(machine::equals).orElse(false)) - .map(BlockPos::immutable); - } - - /** - * Unlinks a tunnel at a specified point inside the machine room. - * - * @param pos Tunnel position inside the room. - */ - public void unregister(BlockPos pos) { - if (!hasTunnel(pos)) - return; - - CompactMachines.LOGGER.debug("Unregistering tunnel at {}", pos); - - final var existing = tunnels.get(pos); - graph.removeNode(existing); - tunnels.remove(pos); - - cleanupOrphanedTypes(); - cleanupOrphanedMachines(); - - setDirty(); - } - - private void cleanupOrphans() { - cleanupOrphanedTunnels(); - cleanupOrphanedTypes(); - cleanupOrphanedMachines(); - } - - private void cleanupOrphanedTypes() { - HashSet removedTypes = new HashSet<>(); - tunnelTypes.forEach((type, node) -> { - if (graph.degree(node) == 0) { - graph.removeNode(node); - removedTypes.add(type); - } - }); - - if (!removedTypes.isEmpty()) { - CompactMachines.LOGGER.debug("Removed {} tunnel type nodes during cleanup.", removedTypes.size()); - removedTypes.forEach(tunnelTypes::remove); - setDirty(); - } - - } - - private void cleanupOrphanedTunnels() { - HashSet removed = new HashSet<>(); - tunnels.forEach((pos, node) -> { - if (graph.degree(node) == 0) { - graph.removeNode(node); - removed.add(pos); - } - }); - - if (!removed.isEmpty()) { - CompactMachines.LOGGER.debug("Removed {} tunnel nodes during cleanup.", removed.size()); - removed.forEach(tunnels::remove); - setDirty(); - } - } - - private void cleanupOrphanedMachines() { - HashSet removed = new HashSet<>(); - machines.forEach((machine, node) -> { - if (graph.degree(node) == 0) { - graph.removeNode(node); - removed.add(machine); - } - }); - - if (!removed.isEmpty()) { - CompactMachines.LOGGER.debug("Removed {} machine nodes during cleanup.", removed.size()); - removed.forEach(machines::remove); - setDirty(); - } - } - - public void rotateTunnel(BlockPos tunnel, Direction newSide) { - if (!tunnels.containsKey(tunnel)) - return; - - final var connected = connectedMachine(tunnel); - connected.ifPresent(machine -> { - if (!machines.containsKey(machine)) - return; - - final var t = tunnels.get(tunnel); - final var m = machines.get(machine); - graph.removeEdge(t, m); - graph.putEdgeValue(t, m, new TunnelMachineEdge(newSide)); - - setDirty(); - }); - } - - public Stream getMachines() { - return this.machines.keySet().stream(); - } - - public Stream getConnections(IDimensionalBlockPosition machine) { - if (!machines.containsKey(machine)) - return Stream.empty(); - - final var mNode = machines.get(machine); - return graph.incidentEdges(mNode).stream() - .filter(e -> graph.edgeValue(e).orElseThrow() instanceof MachineRoomEdge) - .map(edge -> { - if (edge.nodeU() instanceof TunnelNode cmn) return cmn; - if (edge.nodeV() instanceof TunnelNode cmn2) return cmn2; - return null; - }).filter(Objects::nonNull).map(TunnelNode::position); - - } - - public boolean hasAnyConnectedTo(IDimensionalBlockPosition machine) { - return getConnections(machine).findAny().isPresent(); - } - - public void rebind(BlockPos tunnel, IDimensionalBlockPosition newMachine, Direction side) { - CompactMachines.LOGGER.debug("Rebinding tunnel at {} to machine {}", tunnel, newMachine); - - final var tunnelNode = getOrCreateTunnelNode(tunnel); - final var newMachineNode = getOrCreateMachineNode(newMachine); - graph.putEdgeValue(tunnelNode, newMachineNode, new TunnelMachineEdge(side)); - setDirty(); - } -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelMachineEdge.java b/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelMachineEdge.java deleted file mode 100644 index b3767c22..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelMachineEdge.java +++ /dev/null @@ -1,33 +0,0 @@ -package dev.compactmods.machines.tunnel.graph; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.graph.GraphEdgeType; -import dev.compactmods.machines.graph.IGraphEdge; -import dev.compactmods.machines.graph.IGraphEdgeType; -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; - -/** - * Bridges connection between a tunnel and a given machine side. - */ -public record TunnelMachineEdge(Direction side) implements IGraphEdge { - private static final ResourceLocation TYPE = new ResourceLocation(Constants.MOD_ID, "tunnel_machine"); - - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - Direction.CODEC.fieldOf("side").forGetter(TunnelMachineEdge::side), - ResourceLocation.CODEC.fieldOf("type").forGetter(x -> TYPE) - ).apply(i, (side, t) -> new TunnelMachineEdge(side))); - - @Override - public String toString() { - return "TunnelMachineEdge[" + - "side=" + side + ']'; - } - - @Override - public IGraphEdgeType getEdgeType() { - return GraphEdgeType.TUNNEL_MACHINE; - } -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelMachineInfo.java b/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelMachineInfo.java deleted file mode 100644 index 636d111c..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelMachineInfo.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.compactmods.machines.tunnel.graph; - -import dev.compactmods.machines.location.LevelBlockPosition; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; - -public record TunnelMachineInfo(BlockPos location, ResourceLocation type, LevelBlockPosition machine, Direction side) { -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelNode.java b/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelNode.java deleted file mode 100644 index 5320e0c4..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelNode.java +++ /dev/null @@ -1,63 +0,0 @@ -package dev.compactmods.machines.tunnel.graph; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.graph.Graph; -import dev.compactmods.machines.graph.GraphNodeBase; -import dev.compactmods.machines.graph.IGraphNodeType; -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; - -import java.util.Objects; - -public final class TunnelNode extends GraphNodeBase implements IGraphNodeType { - private static final ResourceLocation TYPE = new ResourceLocation(Constants.MOD_ID, "tunnel"); - - public static final Codec CODEC = RecordCodecBuilder.create((i) -> i.group( - BlockPos.CODEC.fieldOf("pos").forGetter(TunnelNode::position), - ResourceLocation.CODEC.fieldOf("type").forGetter(x -> TYPE) - ).apply(i, (bpos, type) -> new TunnelNode(bpos))); - private final BlockPos position; - - public TunnelNode() { - this.position = BlockPos.ZERO; - } - - public TunnelNode(BlockPos position) { - this.position = position; - } - - @Override - public Codec codec() { - return CODEC; - } - - public BlockPos position() { - return position; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - var that = (TunnelNode) obj; - return Objects.equals(this.position, that.position); - } - - @Override - public int hashCode() { - return Objects.hash(position); - } - - @Override - public String toString() { - return "TunnelNode[" + - "position=" + position + ']'; - } - - @Override - public IGraphNodeType getType() { - return Graph.TUNNEL_NODE.get(); - } -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelTypeEdge.java b/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelTypeEdge.java deleted file mode 100644 index 27504be8..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelTypeEdge.java +++ /dev/null @@ -1,41 +0,0 @@ -package dev.compactmods.machines.tunnel.graph; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.graph.GraphEdgeType; -import dev.compactmods.machines.graph.IGraphEdge; -import dev.compactmods.machines.graph.IGraphEdgeType; -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.NotNull; - -public final class TunnelTypeEdge implements IGraphEdge { - private static final ResourceLocation TYPE = new ResourceLocation(Constants.MOD_ID, "tunnel_type"); - - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - ResourceLocation.CODEC.fieldOf("type").forGetter(x -> TYPE) - ).apply(i, (t) -> new TunnelTypeEdge())); - - public TunnelTypeEdge() { - } - - @Override - public boolean equals(Object obj) { - return obj == this || obj != null && obj.getClass() == this.getClass(); - } - - @Override - public int hashCode() { - return 1; - } - - @Override - public String toString() { - return "TunnelTypeEdge[]"; - } - - @Override - public @NotNull IGraphEdgeType getEdgeType() { - return GraphEdgeType.TUNNEL_TYPE; - } -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelTypeNode.java b/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelTypeNode.java deleted file mode 100644 index 7ad9c24a..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/graph/TunnelTypeNode.java +++ /dev/null @@ -1,62 +0,0 @@ -package dev.compactmods.machines.tunnel.graph; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.graph.Graph; -import dev.compactmods.machines.graph.GraphNodeBase; -import dev.compactmods.machines.graph.IGraphNodeType; -import net.minecraft.resources.ResourceLocation; - -import java.util.Objects; - -public final class TunnelTypeNode extends GraphNodeBase implements IGraphNodeType { - private static final ResourceLocation TYPE = new ResourceLocation(Constants.MOD_ID, "tunnel_type"); - - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - ResourceLocation.CODEC.fieldOf("tunnel_type").forGetter(TunnelTypeNode::id), - ResourceLocation.CODEC.fieldOf("type").forGetter(x -> TYPE) - ).apply(i, (tunn, type) -> new TunnelTypeNode(tunn))); - private final ResourceLocation id; - - public TunnelTypeNode() { - this.id = null; - } - - public TunnelTypeNode(ResourceLocation id) { - this.id = id; - } - - @Override - public Codec codec() { - return CODEC; - } - - public ResourceLocation id() { - return id; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - var that = (TunnelTypeNode) obj; - return Objects.equals(this.id, that.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } - - @Override - public String toString() { - return "TunnelTypeNode[" + - "id=" + id + ']'; - } - - @Override - public IGraphNodeType getType() { - return Graph.TUNNEL_TYPE_NODE.get(); - } -} diff --git a/src/main/java/dev/compactmods/machines/tunnel/graph/readme.md b/src/main/java/dev/compactmods/machines/tunnel/graph/readme.md deleted file mode 100644 index 36b6f6c4..00000000 --- a/src/main/java/dev/compactmods/machines/tunnel/graph/readme.md +++ /dev/null @@ -1,35 +0,0 @@ -# Tunnel Connection Graph - -## Structure - -File: `tunnel_graph_0_0.nbt` (inside `data` block) -```json5 -{ - "nodes": [ - { - "type": "compactmachines:tunnel", - "pos": [0, 0, 0] - }, - { - "type": "compactmachines:tunnel_type", - "tunnel_type": "compactmachines:unknown" - }, - { - "type": "compactmachines:machine", - "machine": 1 - } - ], - "edges": [ - { - "type": "compactmachines:tunnel_type", - "from": "[[tunnel]]", - "to": "[[tunnel type]]" - }, - { - "type": "compactmachines:tunnel_machine_link", - "from": "[[tunnel]]", - "to": "[[machine]]" - } - ] -} -``` \ No newline at end of file diff --git a/src/main/java/dev/compactmods/machines/upgrade/ChunkloadUpgrade.java b/src/main/java/dev/compactmods/machines/upgrade/ChunkloadUpgrade.java deleted file mode 100644 index def3e304..00000000 --- a/src/main/java/dev/compactmods/machines/upgrade/ChunkloadUpgrade.java +++ /dev/null @@ -1,63 +0,0 @@ -package dev.compactmods.machines.upgrade; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.core.Constants; -import dev.compactmods.machines.api.room.upgrade.ILevelLoadedUpgradeListener; -import dev.compactmods.machines.api.room.upgrade.RoomUpgrade; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.TicketType; -import net.minecraft.world.level.ChunkPos; - -import java.util.Comparator; - -public class ChunkloadUpgrade implements RoomUpgrade, ILevelLoadedUpgradeListener { - - public static final ResourceLocation REG_ID = new ResourceLocation(Constants.MOD_ID, "chunkloader"); - private static final TicketType CM4_LOAD_TYPE = TicketType.create(Constants.MOD_ID + ":rooms", Comparator.comparingLong(ChunkPos::toLong)); - - private static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - ResourceLocation.CODEC.fieldOf("type").forGetter(x -> REG_ID) - ).apply(i, t -> new ChunkloadUpgrade())); - - @Override - public String getTranslationKey() { - return "item." + REG_ID.getNamespace() + ".upgrades." + REG_ID.getPath(); - } - - @Override - public void onAdded(ServerLevel level, ChunkPos room) { - forceLoad(level, room); - } - - @Override - public void onRemoved(ServerLevel level, ChunkPos room) { - normalLoad(level, room); - } - - @Override - public void onLevelLoaded(ServerLevel level, ChunkPos room) { - forceLoad(level, room); - } - - @Override - public void onLevelUnloaded(ServerLevel level, ChunkPos room) { - normalLoad(level, room); - } - - private void forceLoad(ServerLevel level, ChunkPos room) { - final var chunks = level.getChunkSource(); - level.setChunkForced(room.x, room.z, true); - chunks.addRegionTicket(CM4_LOAD_TYPE, room, 2, room); - chunks.save(false); - } - - private void normalLoad(ServerLevel level, ChunkPos room) { - final var chunks = level.getChunkSource(); - level.setChunkForced(room.x, room.z, false); - chunks.removeRegionTicket(CM4_LOAD_TYPE, room, 2, room); - chunks.save(false); - } -} - diff --git a/src/main/java/dev/compactmods/machines/upgrade/ChunkloadUpgradeItem.java b/src/main/java/dev/compactmods/machines/upgrade/ChunkloadUpgradeItem.java deleted file mode 100644 index e06800f5..00000000 --- a/src/main/java/dev/compactmods/machines/upgrade/ChunkloadUpgradeItem.java +++ /dev/null @@ -1,27 +0,0 @@ -package dev.compactmods.machines.upgrade; - -import dev.compactmods.machines.api.room.upgrade.RoomUpgrade; -import dev.compactmods.machines.api.upgrade.RoomUpgradeHelper; -import net.minecraft.core.NonNullList; -import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.ItemStack; - -public class ChunkloadUpgradeItem extends RoomUpgradeItem { - public ChunkloadUpgradeItem(Properties props) { - super(props); - } - @Override - public void fillItemCategory(CreativeModeTab tab, NonNullList stacks) { - if(!allowedIn(tab)) return; - - final var stack = new ItemStack(MachineRoomUpgrades.CHUNKLOADER.get(), 1); - final var info = stack.getOrCreateTagElement(RoomUpgradeHelper.NBT_UPGRADE_NODE); - info.putString(RoomUpgradeHelper.NBT_UPGRADE_ID, ChunkloadUpgrade.REG_ID.toString()); - - stacks.add(stack); - } - @Override - public RoomUpgrade getUpgradeType() { - return MachineRoomUpgrades.CHUNKLOAD.get(); - } -} diff --git a/src/main/java/dev/compactmods/machines/upgrade/MachineRoomUpgrades.java b/src/main/java/dev/compactmods/machines/upgrade/MachineRoomUpgrades.java deleted file mode 100644 index 3cbe1bb4..00000000 --- a/src/main/java/dev/compactmods/machines/upgrade/MachineRoomUpgrades.java +++ /dev/null @@ -1,27 +0,0 @@ -package dev.compactmods.machines.upgrade; - -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.room.upgrade.RoomUpgrade; -import dev.compactmods.machines.core.Registries; -import net.minecraft.world.item.Item; -import net.minecraftforge.registries.IForgeRegistry; -import net.minecraftforge.registries.RegistryBuilder; -import net.minecraftforge.registries.RegistryObject; - -import java.util.function.Supplier; - -public class MachineRoomUpgrades { - - public static final Supplier> REGISTRY = Registries.UPGRADES.makeRegistry(RegistryBuilder::new); - - // ================================================================================================================ - public static final RegistryObject CHUNKLOAD = Registries.UPGRADES.register(ChunkloadUpgrade.REG_ID.getPath(), ChunkloadUpgrade::new); - - public static final RegistryObject CHUNKLOADER = Registries.ITEMS.register("chunkloader_upgrade", () -> new ChunkloadUpgradeItem(new Item.Properties() - .tab(CompactMachines.COMPACT_MACHINES_ITEMS) - .stacksTo(1))); - - public static void prepare() { - - } -} diff --git a/src/main/java/dev/compactmods/machines/upgrade/RoomUpgradeItem.java b/src/main/java/dev/compactmods/machines/upgrade/RoomUpgradeItem.java deleted file mode 100644 index 73a3fb59..00000000 --- a/src/main/java/dev/compactmods/machines/upgrade/RoomUpgradeItem.java +++ /dev/null @@ -1,51 +0,0 @@ -package dev.compactmods.machines.upgrade; - -import dev.compactmods.machines.api.core.Tooltips; -import dev.compactmods.machines.api.room.upgrade.RoomUpgrade; -import dev.compactmods.machines.api.upgrade.RoomUpgradeHelper; -import dev.compactmods.machines.i18n.TranslationUtil; -import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.Level; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public abstract class RoomUpgradeItem extends Item { - - public RoomUpgradeItem(Properties props) { - super(props); - } - - public abstract RoomUpgrade getUpgradeType(); - - @Override - public Component getName(ItemStack stack) { - String key = RoomUpgradeHelper.getTypeFrom(stack) - .map(rl -> MachineRoomUpgrades.REGISTRY.get().getValue(rl)) - .map(def -> def.getTranslationKey(stack)) - .orElse(RoomUpgrade.UNNAMED_TRANS_KEY); - - return Component.translatable(key); - } - - @Override - public void appendHoverText(ItemStack stack, @Nullable Level level, List info, TooltipFlag flag) { - if (Screen.hasShiftDown()) { - info.add(TranslationUtil.tooltip(Tooltips.TUTORIAL_APPLY_ROOM_UPGRADE).withStyle(ChatFormatting.ITALIC)); - } else { - info.add(TranslationUtil.tooltip(Tooltips.HINT_HOLD_SHIFT).withStyle(ChatFormatting.DARK_GRAY)); - } - - // Show upgrade type while sneaking, or if advanced tooltips are on - if (Screen.hasShiftDown() || flag.isAdvanced()) { - RoomUpgradeHelper.getTypeFrom(stack).ifPresent(upgType -> { - info.add(TranslationUtil.tooltip(Tooltips.ROOM_UPGRADE_TYPE, upgType).withStyle(ChatFormatting.DARK_GRAY)); - }); - } - } -} diff --git a/src/main/java/dev/compactmods/machines/upgrade/command/CMUpgradeRoomCommand.java b/src/main/java/dev/compactmods/machines/upgrade/command/CMUpgradeRoomCommand.java deleted file mode 100644 index 1964a789..00000000 --- a/src/main/java/dev/compactmods/machines/upgrade/command/CMUpgradeRoomCommand.java +++ /dev/null @@ -1,130 +0,0 @@ -package dev.compactmods.machines.upgrade.command; - -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import dev.compactmods.machines.api.core.Messages; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.config.ServerConfig; -import dev.compactmods.machines.i18n.TranslationUtil; -import dev.compactmods.machines.room.Rooms; -import dev.compactmods.machines.upgrade.RoomUpgradeManager; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ChunkPos; - -public class CMUpgradeRoomCommand { - 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(RoomUpgradeArgument.SUGGESTOR) - .executes(CMUpgradeRoomCommand::addToCurrentRoom); - - addUpgRoot.then(Commands.literal("current").executes(CMUpgradeRoomCommand::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(RoomUpgradeArgument.SUGGESTOR) - .executes(CMUpgradeRoomCommand::removeFromCurrentRoom); - - remUpgRoot.then(Commands.literal("current").executes(CMUpgradeRoomCommand::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 level = ctx.getSource().getLevel(); - final var serv = ctx.getSource().getServer(); - - if (!level.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)); - - if (!Rooms.exists(serv, currChunk)) - return -1; - - final var manager = RoomUpgradeManager.get(level); - if(manager.hasUpgrade(currChunk, upgrade)) { - src.sendFailure(TranslationUtil.message(Messages.ALREADY_HAS_UPGRADE)); - } else { - final var added = manager.addUpgrade(upgrade, currChunk); - - if (added) { - upgrade.onAdded(level, currChunk); - src.sendSuccess(TranslationUtil.message(Messages.UPGRADE_APPLIED), true); - } else { - src.sendFailure(TranslationUtil.message(Messages.UPGRADE_ADD_FAILED)); - } - } - - 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 level = ctx.getSource().getLevel(); - final var serv = ctx.getSource().getServer(); - - if (!level.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)); - - if (!Rooms.exists(serv, currChunk)) - return -1; - - final var manager = RoomUpgradeManager.get(level); - if(!manager.hasUpgrade(currChunk, upgrade)) { - src.sendFailure(TranslationUtil.message(Messages.UPGRADE_NOT_PRESENT)); - } else { - final var removed = manager.removeUpgrade(upgrade, currChunk); - - if (removed) { - upgrade.onRemoved(level, currChunk); - src.sendSuccess(TranslationUtil.message(Messages.UPGRADE_REMOVED), true); - } else { - src.sendFailure(TranslationUtil.message(Messages.UPGRADE_REM_FAILED)); - } - } - - return 0; - } - - private static int removeFromSpecificRoom(CommandContext ctx) { - return 0; - } - - -} diff --git a/src/main/java/dev/compactmods/machines/upgrade/graph/RoomUpgradeConnection.java b/src/main/java/dev/compactmods/machines/upgrade/graph/RoomUpgradeConnection.java deleted file mode 100644 index 8f8e3b4d..00000000 --- a/src/main/java/dev/compactmods/machines/upgrade/graph/RoomUpgradeConnection.java +++ /dev/null @@ -1,31 +0,0 @@ -package dev.compactmods.machines.upgrade.graph; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.api.room.upgrade.RoomUpgrade; -import dev.compactmods.machines.graph.GraphEdgeType; -import dev.compactmods.machines.graph.IGraphEdge; -import dev.compactmods.machines.graph.IGraphEdgeType; -import dev.compactmods.machines.upgrade.MachineRoomUpgrades; -import org.jetbrains.annotations.NotNull; - -public class RoomUpgradeConnection implements IGraphEdge { - public static final Codec> CODEC = RecordCodecBuilder.create(i -> i.group( - MachineRoomUpgrades.REGISTRY.get().getCodec().fieldOf("data").forGetter(RoomUpgradeConnection::instance) - ).apply(i, RoomUpgradeConnection::new)); - - private final T upgradeData; - - public RoomUpgradeConnection(final T instance) { - this.upgradeData = instance; - } - - public T instance() { - return upgradeData; - } - - @Override - public @NotNull IGraphEdgeType getEdgeType() { - return GraphEdgeType.ROOM_UPGRADE; - } -} diff --git a/src/main/java/dev/compactmods/machines/upgrade/graph/RoomUpgradeGraphNode.java b/src/main/java/dev/compactmods/machines/upgrade/graph/RoomUpgradeGraphNode.java deleted file mode 100644 index 16fe89fe..00000000 --- a/src/main/java/dev/compactmods/machines/upgrade/graph/RoomUpgradeGraphNode.java +++ /dev/null @@ -1,20 +0,0 @@ -package dev.compactmods.machines.upgrade.graph; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.compactmods.machines.graph.Graph; -import dev.compactmods.machines.graph.IGraphNode; -import dev.compactmods.machines.graph.IGraphNodeType; -import net.minecraft.resources.ResourceLocation; - -public record RoomUpgradeGraphNode(ResourceLocation key) implements IGraphNode { - - public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - ResourceLocation.CODEC.fieldOf("upgrade").forGetter(RoomUpgradeGraphNode::key) - ).apply(i, RoomUpgradeGraphNode::new)); - - @Override - public IGraphNodeType getType() { - return Graph.ROOM_UPGRADE_NODE.get(); - } -} diff --git a/src/main/java/dev/compactmods/machines/util/CompactStructureGenerator.java b/src/main/java/dev/compactmods/machines/util/CompactStructureGenerator.java deleted file mode 100644 index 8e6c5d92..00000000 --- a/src/main/java/dev/compactmods/machines/util/CompactStructureGenerator.java +++ /dev/null @@ -1,98 +0,0 @@ -package dev.compactmods.machines.util; - -import dev.compactmods.machines.api.room.RoomSize; -import dev.compactmods.machines.wall.Walls; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.phys.AABB; - -import java.util.Arrays; - -public class CompactStructureGenerator { - - public static AABB getWallBounds(RoomSize size, BlockPos cubeCenter, Direction wall) { - int s = size.getInternalSize() / 2; - - BlockPos start; - AABB wallBounds; - - boolean horiz = wall.getAxis().getPlane() == Direction.Plane.HORIZONTAL; - if (horiz) { - start = cubeCenter - .below(s) - .relative(wall, s + 1); - - wallBounds = new AABB(start, start) - .expandTowards(0, (s * 2) + 1, 0); - } else { - start = cubeCenter.relative(wall, s + 1); - - wallBounds = new AABB(start, start) - .inflate(s + 1, 0, s + 1); - } - - switch (wall) { - case NORTH: - case SOUTH: - wallBounds = wallBounds.inflate(s + 1, 0, 0); - break; - - case WEST: - case EAST: - wallBounds = wallBounds.inflate(0, 0, s + 1); - break; - } - - return wallBounds; - } - /** - * Generates a wall or platform in a given direction. - * - * @param world - * @param size - * @param cubeCenter - * @param wallDirection - */ - public static void generateCompactWall(LevelAccessor world, RoomSize size, BlockPos cubeCenter, Direction wallDirection) { - final var unbreakableWall = Walls.BLOCK_SOLID_WALL.get().defaultBlockState(); - final var wallBounds = getWallBounds(size, cubeCenter, wallDirection); - - BlockPos.betweenClosedStream(wallBounds) - .filter(world::isEmptyBlock) - .map(BlockPos::immutable) - .forEach(p -> world.setBlock(p, unbreakableWall, 7)); - } - - /** - * Generates a machine "internal" structure in a world via a machine size and a central point. - * - * @param world - * @param size - * @param center - */ - public static void generateCompactStructure(LevelAccessor world, RoomSize size, BlockPos center) { - int s = size.getInternalSize() / 2; - - BlockPos floorCenter = center.relative(Direction.DOWN, s); - BlockPos machineTopCenter = center.relative(Direction.UP, s); - - AABB floorBlocks = new AABB(floorCenter, floorCenter) - .inflate(s, 0, s); - AABB machineInternal = new AABB(machineTopCenter, floorCenter) - .inflate(s, 0, s); - - - boolean anyAir = BlockPos.betweenClosedStream(floorBlocks).anyMatch(world::isEmptyBlock); - - if (anyAir) { // Generate the walls - Arrays.stream(Direction.values()) - .forEach(d -> generateCompactWall(world, size, center, d)); - - BlockPos.betweenClosedStream(machineInternal) - .forEach(p -> world.setBlock(p, Blocks.AIR.defaultBlockState(), 7)); - - } - } -} diff --git a/src/main/java/dev/compactmods/machines/util/DimensionUtil.java b/src/main/java/dev/compactmods/machines/util/DimensionUtil.java deleted file mode 100644 index 2ed5942a..00000000 --- a/src/main/java/dev/compactmods/machines/util/DimensionUtil.java +++ /dev/null @@ -1,128 +0,0 @@ -package dev.compactmods.machines.util; - -import com.mojang.serialization.JsonOps; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.api.dimension.CompactDimension; -import net.minecraft.core.Registry; -import net.minecraft.resources.RegistryOps; -import net.minecraft.resources.RegistryResourceAccess; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.storage.LevelResource; -import net.minecraftforge.fml.loading.FMLEnvironment; - -import java.io.IOException; -import java.nio.file.Files; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; - -public class DimensionUtil { - - @SuppressWarnings("deprecation") // because we call the forge internal method server#markWorldsDirty - public static void createAndRegisterWorldAndDimension(final MinecraftServer server) { - final var map = server.forgeGetWorldMap(); - - // get everything we need to create the dimension and the dimension - final ServerLevel overworld = server.getLevel(Level.OVERWORLD); - - // dimension keys have a 1:1 relationship with dimension keys, they have the same IDs as well - final ResourceKey dimensionKey = ResourceKey.create(Registry.LEVEL_STEM_REGISTRY, CompactDimension.LEVEL_KEY.location()); - - final var serverResources = server.getResourceManager(); - - // only back up dimension.dat in production - if (FMLEnvironment.production && !doLevelFileBackup(server)) return; - - var reg = server.registryAccess(); - var cmDimType = reg.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY) - .get(CompactDimension.DIM_TYPE_KEY); - - var ops = RegistryOps.create(JsonOps.INSTANCE, reg); - - var resourceAccess = RegistryResourceAccess.forResourceManager(serverResources); - var dims = resourceAccess.listResources(Registry.DIMENSION_REGISTRY); - - // TODO - Revisit -// resourceAccess.getResource(Registration.COMPACT_DIMENSION).ifPresent(lev -> { -// var parsed = lev.parseElement(JsonOps.INSTANCE, LevelStem.CODEC); -// -// var stem = parsed.result().orElseThrow().value(); -// -// // the int in create() here is radius of chunks to watch, 11 is what the server uses when it initializes worlds -// final ChunkProgressListener chunkProgressListener = server.progressListenerFactory.create(11); -// final Executor executor = server.executor; -// final LevelStorageSource.LevelStorageAccess anvilConverter = server.storageSource; -// final WorldData worldData = server.getWorldData(); -// final WorldGenSettings worldGenSettings = worldData.worldGenSettings(); -// final DerivedLevelData derivedLevelData = new DerivedLevelData(worldData, worldData.overworldData()); -// -// // now we have everything we need to create the dimension and the dimension -// // this is the same order server init creates levels: -// // the dimensions are already registered when levels are created, we'll do that first -// // then instantiate dimension, add border listener, add to map, fire world load event -// -// // register the actual dimension -// if (worldGenSettings.dimensions() instanceof MappedRegistry stems) { -// stems.unfreeze(); -// Registry.register(stems, dimensionKey, stem); -// stems.freeze(); -// } else { -// CompactMachines.LOGGER.fatal("Failed to re-register compact machines dimension; registry was not the expected class type."); -// return; -// } -// -// // create the world instance -// final ServerLevel newWorld = new ServerLevel( -// server, -// executor, -// anvilConverter, -// derivedLevelData, -// Registration.COMPACT_DIMENSION, -// Holder.direct(cmDimType), -// chunkProgressListener, -// stem.generator(), -// worldGenSettings.isDebug(), -// net.minecraft.world.level.biome.BiomeManager.obfuscateSeed(worldGenSettings.seed()), -// ImmutableList.of(), // "special spawn list" -// false // "tick time", true for overworld, always false for nether, end, and json dimensions -// ); -// -// /* -// add world border listener, for parity with json dimensions -// the vanilla behaviour is that world borders exist in every dimension simultaneously with the same size and position -// these border listeners are automatically added to the overworld as worlds are loaded, so we should do that here too -// TODO if world-specific world borders are ever added, change it here too -// */ -// overworld.getWorldBorder().addListener(new BorderChangeListener.DelegateBorderChangeListener(newWorld.getWorldBorder())); -// -// // register dimension -// map.put(Registration.COMPACT_DIMENSION, newWorld); -// -// // update forge's world cache so the new dimension can be ticked -// server.markWorldsDirty(); -// -// // fire world load event -// MinecraftForge.EVENT_BUS.post(new LevelEvent.Load(newWorld)); -// }); - } - - public static boolean doLevelFileBackup(MinecraftServer server) { - var levelRoot = server.getWorldPath(LevelResource.ROOT); - var levelFile = server.getWorldPath(LevelResource.LEVEL_DATA_FILE); - - var formatter = DateTimeFormatter.ofPattern("'cm4-dimension-'yyyyMMdd-HHmmss'.dat'"); - var timestamp = formatter.format(ZonedDateTime.now()); - try { - Files.copy(levelFile, levelRoot.resolve(timestamp)); - } catch (IOException e) { - CompactMachines.LOGGER.error("Failed to backup dimension.dat file before modification; canceling register dim attempt."); - return false; - } - - return true; - } - -} diff --git a/src/main/java/dev/compactmods/machines/util/LocationUtil.java b/src/main/java/dev/compactmods/machines/util/LocationUtil.java deleted file mode 100644 index ad7b66d9..00000000 --- a/src/main/java/dev/compactmods/machines/util/LocationUtil.java +++ /dev/null @@ -1,19 +0,0 @@ -package dev.compactmods.machines.util; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.phys.Vec3; - -public class LocationUtil { - - public static Vec3 blockPosToVector(BlockPos pos) { - return new Vec3( - pos.getX() + 0.5f, - pos.getY(), - pos.getZ() + 0.5f - ); - } - - public static BlockPos vectorToBlockPos(Vec3 position) { - return new BlockPos(position.x, position.y, position.z); - } -} diff --git a/src/main/java/dev/compactmods/machines/util/MathUtil.java b/src/main/java/dev/compactmods/machines/util/MathUtil.java deleted file mode 100644 index f266d1ed..00000000 --- a/src/main/java/dev/compactmods/machines/util/MathUtil.java +++ /dev/null @@ -1,70 +0,0 @@ -package dev.compactmods.machines.util; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.core.Vec3i; - -public class MathUtil { - /** - * - * @param i - * @return - */ - public static Vec3i getRegionPositionByIndex(int i) { - // From SO, https://stackoverflow.com/a/41141648 - int index = i + 1; - // wth - int s = (int) Math.ceil(Math.sqrt(index)) + (int) ((Math.ceil(Math.sqrt(index)) % 2 + 1) % 2); - int ringIndex = 0; - int p = 1; - if (s > 1) { - ringIndex = i - (s - 2) * (s - 2); - p = s * s - (s - 2) * (s - 2); - } - - int ri = (ringIndex + (s / 2)) % p; - - int x = 0; - if (s > 1) { - if (ri < (p / 4)) x = ri; - else { - if (ri <= (p / 4 * 2 - 1)) x = p / 4; - else { - if (ri <= (p / 4 * 3)) x = (p / 4 * 3) - ri; - else x = 0; - } - } - } - - int y = 0; - if (s > 1) - y = ri < (p / 4) ? 0 : - (ri <= (p / 4 * 2 - 1) ? (ri - (p / 4)) : - (ri <= (p / 4 * 3) ? (p / 4) : - (p - ri))); - - x -= s / 2; - y -= s / 2; - - return new Vec3i(x, 0, y); - } - - public static BlockPos getCenterWithY(ChunkPos chunk, int y) { - return chunk.getWorldPosition() - .offset(new BlockPos(8, y, 8)); - } - - public static BlockPos getCenterWithY(Vec3i regionIndex, int y) { - ChunkPos chunk = new ChunkPos( - regionIndex.getX() * 64, - regionIndex.getZ() * 64); - - return getCenterWithY(chunk, y); - } - - public static ChunkPos getChunkForRoomIndex(int roomIndex) { - Vec3i region = getRegionPositionByIndex(roomIndex); - BlockPos roomCenter = getCenterWithY(region, 0); - return new ChunkPos(roomCenter); - } -} diff --git a/src/main/java/dev/compactmods/machines/util/PlayerUtil.java b/src/main/java/dev/compactmods/machines/util/PlayerUtil.java deleted file mode 100644 index b8a30ab1..00000000 --- a/src/main/java/dev/compactmods/machines/util/PlayerUtil.java +++ /dev/null @@ -1,155 +0,0 @@ -package dev.compactmods.machines.util; - -import com.mojang.authlib.GameProfile; -import dev.compactmods.machines.CompactMachines; -import dev.compactmods.machines.advancement.AdvancementTriggers; -import dev.compactmods.machines.api.core.Messages; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.api.room.IRoomHistory; -import dev.compactmods.machines.api.room.history.IRoomHistoryItem; -import dev.compactmods.machines.dimension.MissingDimensionException; -import dev.compactmods.machines.i18n.TranslationUtil; -import dev.compactmods.machines.location.PreciseDimensionalPosition; -import dev.compactmods.machines.location.SimpleTeleporter; -import dev.compactmods.machines.machine.CompactMachineBlockEntity; -import dev.compactmods.machines.room.RoomCapabilities; -import dev.compactmods.machines.room.Rooms; -import dev.compactmods.machines.room.exceptions.NonexistentRoomException; -import dev.compactmods.machines.room.history.PlayerRoomHistoryItem; -import net.minecraft.core.BlockPos; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.util.LazyOptional; - -import javax.annotation.Nonnull; -import java.util.Optional; -import java.util.UUID; - -public abstract class PlayerUtil { - public static Optional getProfileByUUID(LevelAccessor world, UUID uuid) { - Player player = world.getPlayerByUUID(uuid); - if (player == null) - return Optional.empty(); - - GameProfile profile = player.getGameProfile(); - return Optional.of(profile); - } - - public static void teleportPlayerIntoMachine(Level machineLevel, Player player, BlockPos machinePos) throws MissingDimensionException { - MinecraftServer serv = machineLevel.getServer(); - - ServerLevel compactWorld = serv.getLevel(CompactDimension.LEVEL_KEY); - if (compactWorld == null) { - throw new MissingDimensionException("Compact dimension not found; player attempted to enter machine."); - } - - if (machineLevel.getBlockEntity(machinePos) instanceof CompactMachineBlockEntity tile) { - final var targetRoom = tile.getConnectedRoom(); - boolean grantAdvancement = targetRoom.isEmpty(); - - targetRoom.ifPresent(room -> { - if (player.level.dimension().equals(CompactDimension.LEVEL_KEY) && player.chunkPosition().equals(room)) { - if (player instanceof ServerPlayer sp) { - AdvancementTriggers.RECURSIVE_ROOMS.trigger(sp); - } - - return; - } - - try { - final var entry = PreciseDimensionalPosition.fromPlayer(player); - - teleportPlayerIntoRoom(serv, player, room, grantAdvancement); - - // Mark the player as inside the machine, set external spawn, and yeet - player.getCapability(RoomCapabilities.ROOM_HISTORY).ifPresent(hist -> { - hist.addHistory(new PlayerRoomHistoryItem(entry, tile.getLevelPosition())); - }); - } catch (MissingDimensionException | NonexistentRoomException e) { - CompactMachines.LOGGER.fatal("Critical error; could not enter a freshly-created room instance.", e); - } - }); - } - } - - public static void teleportPlayerIntoRoom(MinecraftServer serv, Player player, ChunkPos room, boolean grantAdvancement) throws MissingDimensionException, NonexistentRoomException { - final var compactDim = serv.getLevel(CompactDimension.LEVEL_KEY); - final var spawn = Rooms.getSpawn(serv, room); - final var roomSize = Rooms.sizeOf(serv, room); - - if (spawn == null) { - CompactMachines.LOGGER.error("Room %s could not load spawn info.".formatted(room)); - return; - } - - serv.submitAsync(() -> { - Vec3 sp = spawn.getExactPosition(); - Vec3 sr = spawn.getRotation().orElse(new Vec3(player.xRotO, player.yRotO, 0)); - - if (player instanceof ServerPlayer servPlayer) { - servPlayer.changeDimension(compactDim, SimpleTeleporter.to(sp)); - - if (grantAdvancement) - AdvancementTriggers.getTriggerForMachineClaim(roomSize).trigger(servPlayer); - } - }); - } - - public static void teleportPlayerOutOfMachine(ServerLevel world, @Nonnull ServerPlayer serverPlayer) { - - MinecraftServer serv = world.getServer(); - - final LazyOptional history = serverPlayer.getCapability(RoomCapabilities.ROOM_HISTORY); - - if (!history.isPresent()) { - howDidYouGetThere(serverPlayer); - return; - } - - history.ifPresent(hist -> { - if (hist.hasHistory()) { - final IRoomHistoryItem prevArea = hist.pop(); - - var spawnPoint = prevArea.getEntryLocation(); - - final var level = spawnPoint.level(serv); - - Vec3 worldPos, entryRot; - worldPos = spawnPoint.getExactPosition(); - entryRot = spawnPoint.getRotation().orElse(Vec3.ZERO); - - serverPlayer.changeDimension(level, SimpleTeleporter.to(worldPos)); - } else { - howDidYouGetThere(serverPlayer); - - hist.clear(); - teleportPlayerToRespawnOrOverworld(serv, serverPlayer); - } - }); - } - - public static void howDidYouGetThere(@Nonnull ServerPlayer serverPlayer) { - AdvancementTriggers.HOW_DID_YOU_GET_HERE.trigger(serverPlayer); - - serverPlayer.displayClientMessage( - TranslationUtil.message(Messages.HOW_DID_YOU_GET_HERE), - true - ); - } - - public static void teleportPlayerToRespawnOrOverworld(MinecraftServer serv, @Nonnull ServerPlayer player) { - ServerLevel level = Optional.ofNullable(serv.getLevel(player.getRespawnDimension())).orElse(serv.overworld()); - Vec3 worldPos = LocationUtil.blockPosToVector(level.getSharedSpawnPos()); - - if (player.getRespawnPosition() != null) - worldPos = LocationUtil.blockPosToVector(player.getRespawnPosition()); - - player.changeDimension(level, SimpleTeleporter.to(worldPos)); - } -} diff --git a/src/main/java/dev/compactmods/machines/wall/BreakableWallBlock.java b/src/main/java/dev/compactmods/machines/wall/BreakableWallBlock.java deleted file mode 100644 index a3e2e71f..00000000 --- a/src/main/java/dev/compactmods/machines/wall/BreakableWallBlock.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.compactmods.machines.wall; - -import net.minecraft.world.level.block.Block; - -import net.minecraft.world.level.block.state.BlockBehaviour.Properties; - -public class BreakableWallBlock extends Block { - public BreakableWallBlock(Properties props) { - super(props); - } -} diff --git a/src/main/java/dev/compactmods/machines/wall/ItemBlockWall.java b/src/main/java/dev/compactmods/machines/wall/ItemBlockWall.java deleted file mode 100644 index 2ca5e4e2..00000000 --- a/src/main/java/dev/compactmods/machines/wall/ItemBlockWall.java +++ /dev/null @@ -1,43 +0,0 @@ -package dev.compactmods.machines.wall; - -import dev.compactmods.machines.api.core.Tooltips; -import dev.compactmods.machines.i18n.TranslationUtil; -import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; - -import javax.annotation.Nullable; -import java.util.List; - -public class ItemBlockWall extends BlockItem { - - public ItemBlockWall(Block blockIn, Properties builder) { - super(blockIn, builder); - } - - @Override - public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List tooltip, TooltipFlag flagIn) { - super.appendHoverText(stack, worldIn, tooltip, flagIn); - - if (stack.getItem() == Walls.ITEM_SOLID_WALL.get()) { - MutableComponent text; - if (Screen.hasShiftDown()) { - text = TranslationUtil.tooltip(Tooltips.Details.SOLID_WALL) - .withStyle(ChatFormatting.DARK_RED); - } else { - text = TranslationUtil.tooltip(Tooltips.HINT_HOLD_SHIFT) - .withStyle(ChatFormatting.DARK_GRAY) - .withStyle(ChatFormatting.ITALIC); - } - - tooltip.add(text); - } - - } -} diff --git a/src/main/java/dev/compactmods/machines/wall/SolidWallBlock.java b/src/main/java/dev/compactmods/machines/wall/SolidWallBlock.java deleted file mode 100644 index 1402656f..00000000 --- a/src/main/java/dev/compactmods/machines/wall/SolidWallBlock.java +++ /dev/null @@ -1,19 +0,0 @@ -package dev.compactmods.machines.wall; - -import dev.compactmods.machines.config.ServerConfig; -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.SpawnPlacements; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.state.BlockState; - -public class SolidWallBlock extends ProtectedWallBlock { - public SolidWallBlock(Properties props) { - super(props); - } - - @Override - public boolean isValidSpawn(BlockState state, BlockGetter world, BlockPos pos, SpawnPlacements.Type type, EntityType entityType) { - return pos.getY() == ServerConfig.MACHINE_FLOOR_Y.get(); - } -} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml deleted file mode 100644 index e5704f56..00000000 --- a/src/main/resources/META-INF/mods.toml +++ /dev/null @@ -1,55 +0,0 @@ -# This is an example mods.toml file. It contains the data relating to the loading mods. -# There are several mandatory fields (#mandatory), and many more that are optional (#optional). -# The overall format is standard TOML format, v0.5.0. -# Note that there are a couple of TOML lists in this file. -# Find more information on toml format here: https://github.com/toml-lang/toml -# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml -modLoader="javafml" #mandatory -# A version range to match for said mod loader - for regular FML @Mod it will be the forge version -loaderVersion="[42,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. -# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. -# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="MIT" - -# A list of mods - how many allowed here is determined by the individual mod loader -[[mods]] #mandatory - modId="compactmachines" - version="${file.jarVersion}" - displayName="Compact Machines 5" - authors="Davenonymous, RobotGryphon" #optional - description="It's all so tiny!" - - ## OPTIONAL INFO ## - - # A URL to refer people to when problems occur with this mod - issueTrackerURL="https://github.com/CompactMods/CompactMachines/issues" - - # A URL to query for updates for this mod. See the JSON update specification - #updateJSONURL="http://myurl.me/" #optional - - # A URL for the "homepage" for this mod, displayed in the mod UI - # displayURL="http://example.com/" #optional - - # A file name (in the root of the mod JAR) containing a logo for display - # logoFile="examplemod.png" #optional - -# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. -[[dependencies.compactmachines]] #optional - # the modid of the dependency - modId="forge" #mandatory - # Does this dependency have to exist - if not, ordering below must be specified - mandatory=true #mandatory - # The version range of the dependency - versionRange="[42,)" #mandatory - # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory - ordering="NONE" - # Side this dependency is applied on - BOTH, CLIENT or SERVER - side="BOTH" - -# Here's another dependency -[[dependencies.compactmachines]] - modId="minecraft" - mandatory=true - versionRange="[1.19.1,)" - ordering="NONE" - side="BOTH" diff --git a/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_giant.png b/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_giant.png deleted file mode 100644 index f9b9f799..00000000 Binary files a/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_giant.png and /dev/null differ diff --git a/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_maximum.png b/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_maximum.png deleted file mode 100644 index d4103bc0..00000000 Binary files a/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_maximum.png and /dev/null differ diff --git a/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_normal.png b/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_normal.png deleted file mode 100644 index c976efff..00000000 Binary files a/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_normal.png and /dev/null differ diff --git a/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_small.png b/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_small.png deleted file mode 100644 index 66313d61..00000000 Binary files a/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_small.png and /dev/null differ diff --git a/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_tiny.png b/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_tiny.png deleted file mode 100644 index ba22215b..00000000 Binary files a/src/main/resources/assets/compactmachines/textures/block/machine/e x/machine_tiny.png and /dev/null differ diff --git a/src/tunnels/java/dev/compactmods/machines/tunnel/definitions/UnknownTunnel.java b/src/tunnels/java/dev/compactmods/machines/tunnel/definitions/UnknownTunnel.java deleted file mode 100644 index 46b60710..00000000 --- a/src/tunnels/java/dev/compactmods/machines/tunnel/definitions/UnknownTunnel.java +++ /dev/null @@ -1,12 +0,0 @@ -package dev.compactmods.machines.tunnel.definitions; - -import dev.compactmods.machines.api.tunnels.TunnelDefinition; - -public class UnknownTunnel implements TunnelDefinition { - - @Override - public int ringColor() { - return NO_INDICATOR_COLOR; - } - -} diff --git a/tunnels/definitions/RedstoneInTunnelDefinition.java b/tunnels/definitions/RedstoneInTunnelDefinition.java deleted file mode 100644 index f5e66e3c..00000000 --- a/tunnels/definitions/RedstoneInTunnelDefinition.java +++ /dev/null @@ -1,51 +0,0 @@ -package dev.compactmods.machines.tunnel.definitions; - -import dev.compactmods.machines.api.location.IDimensionalPosition; -import dev.compactmods.machines.api.tunnels.EnumTunnelSide; -import dev.compactmods.machines.api.tunnels.ITunnelConnectionInfo; -import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import dev.compactmods.machines.teleportation.DimensionalPosition; -import dev.compactmods.machines.api.tunnels.redstone.IRedstoneReaderTunnel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.LevelReader; -import net.minecraft.server.level.ServerLevel; - -import java.awt.*; -import java.util.Optional; - -public class RedstoneInTunnelDefinition extends TunnelDefinition implements IRedstoneReaderTunnel { - - @Override - public int getTunnelRingColor() { - return new Color(167, 38, 38).getRGB(); - } - - @Override - public int getTunnelIndicatorColor() { - return Color.blue.getRGB(); - // return Color.ORANGE.darker().getRGB(); - } - - @Override - public int getPowerLevel(ITunnelConnectionInfo connectionInfo) { - LevelReader connectedWorld = connectionInfo.getConnectedWorld(EnumTunnelSide.OUTSIDE).orElse(null); - if (connectedWorld instanceof ServerLevel) { - IDimensionalPosition pos = connectionInfo.getConnectedPosition(EnumTunnelSide.OUTSIDE).orElse(null); - if (pos == null) - return 0; - - Optional state = connectionInfo.getConnectedState(EnumTunnelSide.OUTSIDE); - if (!state.isPresent()) return 0; - - int weak = state.get().getSignal( - connectedWorld, - pos.getBlockPosition(), - connectionInfo.getConnectedSide(EnumTunnelSide.OUTSIDE)); - - return weak; - } - - return 0; - } -} - diff --git a/tunnels/definitions/RedstoneOutTunnelDefinition.java b/tunnels/definitions/RedstoneOutTunnelDefinition.java deleted file mode 100644 index 2e2643bc..00000000 --- a/tunnels/definitions/RedstoneOutTunnelDefinition.java +++ /dev/null @@ -1,24 +0,0 @@ -package dev.compactmods.machines.tunnel.definitions; - -import dev.compactmods.machines.api.tunnels.ITunnelConnectionInfo; -import dev.compactmods.machines.api.tunnels.TunnelDefinition; -import dev.compactmods.machines.api.tunnels.redstone.IRedstoneWriterTunnel; - -import java.awt.Color; - -public class RedstoneOutTunnelDefinition extends TunnelDefinition implements IRedstoneWriterTunnel { - @Override - public int getStrongPower(ITunnelConnectionInfo connectionInfo) { - return 0; - } - - @Override - public int getWeakPower(ITunnelConnectionInfo connectionInfo) { - return 0; - } - - @Override - public int getTunnelRingColor() { - return new Color(167, 38, 38).getRGB(); - } -}