├── .circleci └── config.yml ├── .github └── workflows │ ├── curseforge.yml │ ├── nightly.yml │ └── publish.yml ├── .gitignore ├── CHANGELOG.md ├── Jenkinsfile ├── LICENSE ├── README.md ├── build.gradle ├── common ├── build.gradle ├── gradle.properties ├── logs │ └── latest.log └── src │ └── main │ ├── java │ └── tesseract │ │ ├── FluidPlatformUtils.java │ │ ├── Tesseract.java │ │ ├── TesseractCapUtils.java │ │ ├── TesseractConfig.java │ │ ├── TesseractGraphWrappers.java │ │ ├── TesseractPlatformUtils.java │ │ ├── api │ │ ├── ConnectionType.java │ │ ├── Consumer.java │ │ ├── Controller.java │ │ ├── GraphWrapper.java │ │ ├── IConnectable.java │ │ ├── ITickingController.java │ │ ├── Transaction.java │ │ ├── capability │ │ │ ├── ITransactionModifier.java │ │ │ ├── TesseractBaseCapability.java │ │ │ ├── TesseractFluidCapability.java │ │ │ ├── TesseractGTCapability.java │ │ │ ├── TesseractItemCapability.java │ │ │ └── TesseractRFCapability.java │ │ ├── context │ │ │ └── TesseractItemContext.java │ │ ├── fluid │ │ │ ├── FluidConsumer.java │ │ │ ├── FluidContainerHandler.java │ │ │ ├── FluidController.java │ │ │ ├── FluidStatus.java │ │ │ ├── FluidTransaction.java │ │ │ ├── IFluidEvent.java │ │ │ ├── IFluidNode.java │ │ │ ├── IFluidPipe.java │ │ │ └── PipeFluidHolder.java │ │ ├── gt │ │ │ ├── GTConsumer.java │ │ │ ├── GTController.java │ │ │ ├── GTHolder.java │ │ │ ├── GTStatus.java │ │ │ ├── GTTransaction.java │ │ │ ├── IEnergyHandler.java │ │ │ ├── IEnergyHandlerItem.java │ │ │ ├── IEnergyHandlerTile.java │ │ │ ├── IEnergyItem.java │ │ │ ├── IGTCable.java │ │ │ ├── IGTEvent.java │ │ │ └── IGTNode.java │ │ ├── heat │ │ │ ├── HeatController.java │ │ │ ├── HeatTransaction.java │ │ │ ├── IHeatHandler.java │ │ │ ├── IHeatNode.java │ │ │ └── IHeatPipe.java │ │ ├── item │ │ │ ├── ContainerItemHandler.java │ │ │ ├── ExtendedItemContainer.java │ │ │ ├── IItemNode.java │ │ │ ├── IItemPipe.java │ │ │ ├── ItemConsumer.java │ │ │ ├── ItemController.java │ │ │ ├── ItemTransaction.java │ │ │ └── PlatformItemHandler.java │ │ ├── rf │ │ │ ├── IRFCable.java │ │ │ ├── IRFNode.java │ │ │ ├── RFConsumer.java │ │ │ ├── RFController.java │ │ │ └── RFTransaction.java │ │ └── wrapper │ │ │ ├── ItemStackWrapper.java │ │ │ └── ItemTileWrapper.java │ │ ├── controller │ │ ├── Energy.java │ │ ├── Fluid.java │ │ └── Utils.java │ │ ├── graph │ │ ├── Cache.java │ │ ├── Connectivity.java │ │ ├── Graph.java │ │ ├── Grid.java │ │ ├── Group.java │ │ ├── INode.java │ │ ├── NodeCache.java │ │ ├── Path.java │ │ ├── TestBench.java │ │ └── traverse │ │ │ ├── ASFinder.java │ │ │ ├── BFDivider.java │ │ │ └── BFSearcher.java │ │ └── util │ │ ├── CID.java │ │ ├── ItemHandlerUtils.java │ │ ├── Node.java │ │ ├── Pos.java │ │ └── SetUtil.java │ └── resources │ ├── assets │ └── tesseractapi │ │ ├── Thumbs.db │ │ └── icon.png │ └── pack.mcmeta ├── fabric ├── build.gradle ├── gradle.properties └── src │ └── main │ ├── java │ └── tesseract │ │ ├── api │ │ └── fabric │ │ │ ├── TesseractLookups.java │ │ │ ├── TileListeners.java │ │ │ └── wrapper │ │ │ ├── ContainerItemContextWrapper.java │ │ │ ├── EnergyMoveableWrapper.java │ │ │ ├── EnergyStackWrapper.java │ │ │ ├── EnergyTileWrapper.java │ │ │ ├── ExtendedContainerWrapper.java │ │ │ ├── FabricPlatformItemHandler.java │ │ │ ├── FluidContainerWrapper.java │ │ │ ├── FluidTileWrapper.java │ │ │ ├── IEnergyHandlerMoveable.java │ │ │ ├── IEnergyHandlerStorage.java │ │ │ ├── IEnergyMoveableTiers.java │ │ │ ├── ItemStorageWrapper.java │ │ │ └── RFWrapper.java │ │ ├── fabric │ │ ├── FluidPlatformUtilsImpl.java │ │ ├── TesseractCapUtilsImpl.java │ │ ├── TesseractImpl.java │ │ ├── TesseractPlatformUtilsImpl.java │ │ └── TesseractPreLoad.java │ │ └── mixin │ │ └── fabric │ │ ├── BlockEntityMixin.java │ │ ├── FabricBlockEnergyContainerAccessor.java │ │ ├── FabricBlockFluidContainerAccessor.java │ │ ├── IEnergyHandlerMixin.java │ │ ├── SimpleItemEnergyStorageImplMixin.java │ │ ├── TesseractMixinPlugin.java │ │ └── mi │ │ ├── AbstractStorageMachineBEMixin.java │ │ └── IEnergyHandlerMixin.java │ └── resources │ ├── META-INF │ └── services │ │ ├── tesseract.TesseractCapUtils │ │ └── tesseract.TesseractPlatformUtils │ ├── fabric.mod.json │ └── tesseract-fabric.mixins.json ├── forge ├── build.gradle ├── gradle.properties ├── logs │ ├── debug.log │ └── latest.log └── src │ └── main │ ├── java │ └── tesseract │ │ ├── api │ │ └── forge │ │ │ ├── Provider.java │ │ │ ├── TesseractCaps.java │ │ │ └── wrapper │ │ │ ├── CauldronWrapper.java │ │ │ ├── EnergyStackWrapper.java │ │ │ ├── EnergyTileWrapper.java │ │ │ ├── ExtendedContainerWrapper.java │ │ │ ├── FluidTileWrapper.java │ │ │ ├── ForgePlatformItemHandler.java │ │ │ ├── IEnergyHandlerStorage.java │ │ │ ├── ItemHandlerWrapper.java │ │ │ └── RFWrapper.java │ │ ├── forge │ │ ├── FluidPlatformUtilsImpl.java │ │ ├── TesseractCapUtilsImpl.java │ │ ├── TesseractImpl.java │ │ └── TesseractPlatformUtilsImpl.java │ │ └── mixin │ │ └── forge │ │ └── IEnergyHandlerMixin.java │ └── resources │ ├── META-INF │ ├── mods.toml │ └── services │ │ ├── tesseract.TesseractCapUtils │ │ └── tesseract.TesseractPlatformUtils │ └── tesseract-forge.mixins.json ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml ├── settings.gradle └── version ├── build.gradle ├── gradle.properties └── version.properties /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | # specify the version you desire here 6 | - image: circleci/openjdk:8-jdk 7 | 8 | working_directory: ~/repo 9 | 10 | environment: 11 | # Customize the JVM maximum heap limit 12 | JVM_OPTS: -Xmx3200m 13 | TERM: dumb 14 | 15 | steps: 16 | - checkout 17 | - run: 18 | name: Pull Submodules 19 | command: git submodule update --init --recursive 20 | 21 | # Download and cache dependencies 22 | - restore_cache: 23 | keys: 24 | - v1-dependencies-{{ checksum "build.gradle" }} 25 | # fallback to using the latest cache if no exact match is found 26 | - v1-dependencies- 27 | 28 | - run: bash gradlew dependencies 29 | 30 | - save_cache: 31 | paths: 32 | - ~/.gradle 33 | key: v1-dependencies-{{ checksum "build.gradle" }} 34 | 35 | # Build & Test it 36 | - run: bash gradlew test -------------------------------------------------------------------------------- /.github/workflows/curseforge.yml: -------------------------------------------------------------------------------- 1 | name: Publish To Curseforge 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | fabric: 6 | type: boolean 7 | description: Publish fabric jar 8 | default: true 9 | forge: 10 | type: boolean 11 | description: Publish forge jar 12 | default: true 13 | jobs: 14 | curseforge: 15 | strategy: 16 | matrix: 17 | # Use these Java versions 18 | java: [17] 19 | # and run on both Linux and Windows 20 | os: [ubuntu-20.04] 21 | runs-on: ${{ matrix.os }} 22 | steps: 23 | - name: Checkout Tesseract 24 | uses: actions/checkout@v2 25 | - name: Fetch tags 26 | run: git fetch --tags 27 | - name: Validate Gradle wrapper 28 | uses: gradle/wrapper-validation-action@v1 29 | - name: Setup JDK ${{ matrix.java }} 30 | uses: actions/setup-java@v1 31 | with: 32 | java-version: ${{ matrix.java }} 33 | - name: Make Gradle wrapper executable 34 | if: ${{ runner.os != 'Windows' }} 35 | run: chmod +x ./gradlew 36 | - name: Build 37 | run: ./gradlew build --stacktrace 38 | env: 39 | MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} 40 | MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} 41 | GITHUB_RELEASE: true 42 | - name: Publish forge jar to curseforge 43 | if: ${{ github.event.inputs.forge }} 44 | uses: Kir-Antipov/mc-publish@v3.2 45 | with: 46 | # You don't need this section if you don't want to publish 47 | # your assets to CurseForge 48 | curseforge-id: 462718 49 | curseforge-token: ${{ secrets.CURSEFORGE_API_TOKEN }} 50 | name: "" 51 | version-type: beta 52 | changelog-file: CHANGELOG.md 53 | files-primary: forge/build/libs/!(*-@(dev-shadow|sources|javadoc)).jar 54 | files-secondary: forge/build/libs/*-@(dev-shadow|sources|javadoc).jar 55 | - name: Publish fabric jar to curseforge 56 | if: ${{ github.event.inputs.fabric }} 57 | uses: Kir-Antipov/mc-publish@v3.2 58 | with: 59 | # You don't need this section if you don't want to publish 60 | # your assets to CurseForge 61 | curseforge-id: 462718 62 | curseforge-token: ${{ secrets.CURSEFORGE_API_TOKEN }} 63 | name: "" 64 | version-type: beta 65 | changelog-file: CHANGELOG.md 66 | files-primary: fabric/build/libs/!(*-@(dev-shadow|sources|javadoc)).jar 67 | files-secondary: fabric/build/libs/*-@(dev-shadow|sources|javadoc).jar 68 | -------------------------------------------------------------------------------- /.github/workflows/nightly.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | # This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created 6 | # For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle 7 | 8 | name: TesseractAPI Nightly 9 | on: 10 | push: 11 | branches: 12 | - '*' 13 | pull_request: 14 | branches: 15 | - 'dev**' 16 | jobs: 17 | build: 18 | 19 | runs-on: ubuntu-latest 20 | permissions: 21 | contents: read 22 | packages: write 23 | 24 | steps: 25 | - uses: actions/checkout@v2 26 | - name: Set up JDK 17 27 | uses: actions/setup-java@v2 28 | with: 29 | java-version: '17' 30 | distribution: 'adopt' 31 | server-id: github # Value of the distributionManagement/repository/id field of the pom.xml 32 | settings-path: ${{ github.workspace }} # location for the settings.xml file 33 | - name: Setup Gradle Dependencies Cache 34 | uses: actions/cache@v4 35 | with: 36 | path: ~/.gradle/caches 37 | ~/.gradle/wrapper 38 | key: ${{ runner.os }}-gradle-caches-${{ hashFiles('**/*.properties') }} 39 | - name: Build with Gradle 40 | run: ./gradlew build --stacktrace 41 | # The USERNAME and TOKEN need to correspond to the credential environment variables used in 42 | # the publishing section of your build.gradle 43 | - name: Upload Forge Artifact 44 | uses: actions/upload-artifact@v4 45 | with: 46 | name: TesseractAPI Forge JAR 47 | path: forge/build/libs 48 | env: 49 | USERNAME: ${{ github.actor }} 50 | TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | - name: Upload Fabric Artifact 52 | uses: actions/upload-artifact@v4 53 | with: 54 | name: TesseractAPI Fabric JAR 55 | path: fabric/build/libs 56 | env: 57 | USERNAME: ${{ github.actor }} 58 | TOKEN: ${{ secrets.GITHUB_TOKEN }} 59 | - name: Cleanup Gradle Cache 60 | # Remove some files from the Gradle cache, so they aren't cached by GitHub Actions. 61 | # Restoring these files from a GitHub Actions cache might cause problems for future builds. 62 | run: | 63 | rm -f ~/.gradle/caches/modules-2/modules-2.lock 64 | rm -f ~/.gradle/caches/modules-2/gc.properties 65 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Artifacts 2 | on: 3 | workflow_dispatch: 4 | jobs: 5 | release: 6 | strategy: 7 | matrix: 8 | # Use these Java versions 9 | java: [17] 10 | # and run on both Linux and Windows 11 | os: [ubuntu-20.04] 12 | runs-on: ${{ matrix.os }} 13 | steps: 14 | - name: Checkout Tesseract 15 | uses: actions/checkout@v2 16 | - name: Fetch tags 17 | run: git fetch --tags 18 | - name: Validate Gradle wrapper 19 | uses: gradle/wrapper-validation-action@v1 20 | - name: Setup JDK ${{ matrix.java }} 21 | uses: actions/setup-java@v1 22 | with: 23 | java-version: ${{ matrix.java }} 24 | - name: Make Gradle wrapper executable 25 | if: ${{ runner.os != 'Windows' }} 26 | run: chmod +x ./gradlew 27 | - name: Build & Publish 28 | run: ./gradlew build publish --stacktrace 29 | env: 30 | MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} 31 | MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} 32 | GITHUB_RELEASE: true 33 | - name: Upload Forge Artifact 34 | uses: actions/upload-artifact@v4 35 | with: 36 | name: Antimatter-forge-nightly-${{ steps.vars.outputs.sha_short }} 37 | path: forge/build/libs 38 | env: 39 | USERNAME: ${{ github.actor }} 40 | TOKEN: ${{ secrets.GITHUB_TOKEN }} 41 | - name: Upload Fabric Artifact 42 | uses: actions/upload-artifact@v4 43 | with: 44 | name: Antimatter-fabric-nightly-${{ steps.vars.outputs.sha_short }} 45 | path: fabric/build/libs 46 | env: 47 | USERNAME: ${{ github.actor }} 48 | TOKEN: ${{ secrets.GITHUB_TOKEN }} 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # eclipse 2 | bin 3 | *.launch 4 | .settings 5 | .metadata 6 | .classpath 7 | .project 8 | 9 | # idea 10 | out 11 | *.ipr 12 | *.iws 13 | *.iml 14 | .idea 15 | 16 | # gradle 17 | build 18 | .gradle 19 | 20 | # other 21 | eclipse 22 | run 23 | .cache 24 | 25 | # Files from Forge MDK 26 | forge*changelog.txt 27 | 28 | .vscode 29 | mcmodsrepo/ 30 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | - Changed to Carbon config 2 | - Refactored energy a bit 3 | - changed fluid and item systems to use botarium 4 | - added graph system for rf, uses botarium energy system 5 | - Made IItemPipe have stepsize 6 | - to see the rest of the changes see the commits [here](https://github.com/GregTech-Intergalactical/TesseractAPI/compare/b3bf1c71d7069d7a186658d9104b34c3fa8812c8...0.2.2-1.18.2) -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | tools { 4 | jdk "jdk-21" // valid options are: "jdk-8", "jdk-16", "jdk-17" or "jdk-21", choose which one you need 5 | } 6 | stages { 7 | stage('Clean') { 8 | steps { 9 | echo 'Cleaning Project' 10 | sh 'chmod +x gradlew' 11 | sh './gradlew clean' 12 | } 13 | } 14 | stage('Build & Publish') { 15 | steps { 16 | echo 'Building & Publishing' 17 | sh './gradlew build publish' 18 | } 19 | } 20 | } 21 | post { 22 | always { 23 | discordSend( 24 | webhookURL: "https://discord.com/api/webhooks/1313642177083216073/H8EnQ65JusCjpqGTqLXDZI1BYBe4ArLJn3xSjEOWthg4Nwa7ZFSHu1SYag8fU4v4DB8k", 25 | thumbnail: "https://raw.githubusercontent.com/GT-Reimagined/gt-reimagined.github.io/refs/heads/main/icon.png", 26 | title: "Tesseract API ${TAG_NAME} #${BUILD_NUMBER}", 27 | link: env.BUILD_URL, 28 | result: currentBuild.currentResult, 29 | description: "Build: [${BUILD_NUMBER}](${env.BUILD_URL})\nStatus: ${currentBuild.currentResult}" 30 | ) 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Tesseract](https://nerdist.com/wp-content/uploads/2019/03/tumblr_o9pm5bI1Kc1sbtt2jo3_540.gif) 2 | 3 | # Tesseract: 3D Network Graph Library for Java 4 | 5 | This API is for the General purpose of building graphs consisting of nodes and connectors that are divided into groups and grids. 6 | Groups are sets of nodes and connectors that are located next to each other and may not necessarily have a connection. 7 | Grids are already sets of connectors connected to each other which can be several in a group. 8 | 9 | ![Graph](https://www.mathworks.com/help/examples/matlab/win64/AdjustGraphPlotPropertiesExample_05.png) 10 | 11 | Its main purpose is to help create systems for exchanging information between nodes with simplified calculations. 12 | The library also allows you to create controllers for each group that will be responsible for the logic. 13 | The API is written without using additional libraries other than FastUtils. 14 | 15 | ## Artifacts 16 | 17 | Currently, two artifacts classes has been defined: 18 | * `tesseract-fabric` which includes (path: `$projectDir/fabric`): 19 | * *default* is the mod for fabric only, 20 | * `dev-shadow` is same as `jar` but not obfuscated, made to run in development environments, 21 | * `sources` is the source code. 22 | * `tesseract-forge` which includes (path: `$projectDir/forge`): 23 | * *default* is the mod for Forge only, 24 | * `dev-shadow` is same as `jar` but not obfuscated, made to run in development environments, 25 | * `sources` is the source code. 26 | 27 | The common submodule has no use, cause some parts of the api had to be separated into their respective forge and fabric versions 28 | 29 | ## Building 30 | 31 | It's as simple as running: 32 | ``` 33 | ./gradlew build 34 | ``` 35 | 36 | Then you will find full mod in the right `build/libs` directories. 37 | 38 | ### Install as a dependency 39 | 40 | Use this in your `build.gradle` 41 | ```groovy 42 | repositories { 43 | maven { 44 | url = 'https://jitpack.io' 45 | } 46 | } 47 | 48 | dependencies { 49 | //Tag can be a commit hash, a github release tag, or (branch name)-SNAPSHOT 50 | //forge 51 | implementation 'com.github.GregTech-Intergalactical.TesseractAPI:TesseractAPI-forge:Tag' 52 | //forge 53 | implementation 'com.github.GregTech-Intergalactical.TesseractAPI:TesseractAPI-fabric:Tag' 54 | } 55 | ``` 56 | 57 | ### Publishing to a maven repository 58 | 59 | First you'll need a repository ([files.axelandre42.ovh/maven](https://files.axelandre42.ovh/maven/) is reserved to official releases). 60 | 61 | Then set your environment variables: 62 | * `MAVEN_URL` Maven Repository URL. 63 | * `MAVEN_USERNAME` Your username on the repository. 64 | * `MAVEN_PASSWORD` Your password on the repository. 65 | 66 | And finally run: `./gradlew publish` 67 | 68 | ## Version management 69 | 70 | Use the `bumpMajor`, `bumpMinor` and `bumpRevision` to increment version. 71 | 72 | If the project is build from CI, it will append the build number automatically. 73 | 74 | Otherwise it'll try to get the Git short revision ID. 75 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "maven-publish" 3 | id "idea" 4 | id "fabric-loom" version "1.7-SNAPSHOT" apply false 5 | id "net.neoforged.moddev.legacyforge" version "2.0.58-beta" apply false 6 | } 7 | 8 | def isGITHU_ACTION = System.getenv("GITHUB_ACTION") 9 | def gitHash() { 10 | String hash = System.getenv("GITHUB_SHA") 11 | if (hash != null) return hash.substring(0,8) 12 | return "" 13 | } 14 | 15 | subprojects { 16 | apply plugin: "maven-publish" 17 | apply plugin: "java" 18 | apply plugin: "idea" 19 | group = rootProject.maven_group 20 | version = "${project.mod_version}-${rootProject.minecraft_version}" 21 | java.toolchain.languageVersion = JavaLanguageVersion.of(17) 22 | apply from: 'https://raw.githubusercontent.com/GregTech-Intergalactical/GradleSripts/main/repositories.gradle' 23 | 24 | java { 25 | withSourcesJar() 26 | } 27 | 28 | tasks.withType(JavaCompile).configureEach { 29 | it.options.encoding = 'UTF-8' 30 | } 31 | 32 | if (isGITHU_ACTION) { 33 | version = version + "-" + gitHash() 34 | println("In CI mode") 35 | } 36 | } -------------------------------------------------------------------------------- /common/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "fabric-loom" 3 | } 4 | archivesBaseName = "${project.tesseract_archive_base_name}-common" 5 | 6 | dependencies{ 7 | minecraft "com.mojang:minecraft:${project.minecraft_version}" 8 | mappings loom.layered() { 9 | officialMojangMappings() 10 | parchment("org.parchmentmc.data:parchment-${project.minecraft_version}:${project.mappings_version}@zip") 11 | } 12 | //compileOnly("com.electronwill.night-config:toml:${rootProject.nightconfig_version}") 13 | //compileOnly("com.electronwill.night-config:core:${rootProject.nightconfig_version}") 14 | modImplementation("earth.terrarium:botarium-fabric-${project.minecraft_version}:${project.botarium_version}") 15 | implementation 'com.github.Carbon-Config-Project:CarbonConfigLib:1.3.0' 16 | } 17 | 18 | publishing { 19 | publications { 20 | mavenJava(org.gradle.api.publish.maven.MavenPublication) { 21 | from components.java 22 | } 23 | } 24 | 25 | repositories { 26 | def isCI = System.getenv("CI") 27 | if (isCI) { 28 | maven { 29 | url System.getenv("local_maven_url") 30 | } 31 | } else { 32 | mavenLocal() 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /common/gradle.properties: -------------------------------------------------------------------------------- 1 | mod_version=0.2.4.1 2 | fabric.loom.dontRemap=true -------------------------------------------------------------------------------- /common/logs/latest.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregTech-Intergalactical/TesseractAPI/5a162d42f3cb6761dd6ebf05aea7374965d467eb/common/logs/latest.log -------------------------------------------------------------------------------- /common/src/main/java/tesseract/Tesseract.java: -------------------------------------------------------------------------------- 1 | package tesseract; 2 | 3 | import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; 4 | import net.minecraft.world.level.LevelAccessor; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | 8 | import java.util.Set; 9 | 10 | 11 | public class Tesseract { 12 | 13 | protected final static Set firstTick = new ObjectOpenHashSet<>(); 14 | 15 | public static final String API_ID = "tesseractapi"; 16 | public static final String API_NAME = "Tesseract API"; 17 | public static final String VERSION = "0.0.1"; 18 | public static final String DEPENDS = ""; 19 | 20 | public static boolean TEST = false; 21 | 22 | public static final Logger LOGGER = LogManager.getLogger(API_ID); 23 | 24 | 25 | 26 | public static final int HEALTH_CHECK_TIME = 1000; 27 | 28 | public static void init() { 29 | TesseractGraphWrappers.init(); 30 | TesseractConfig.createConfig(); 31 | } 32 | 33 | public Tesseract() { 34 | } 35 | 36 | public static boolean hadFirstTick(LevelAccessor world) { 37 | return TEST || firstTick.contains(world); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/TesseractCapUtils.java: -------------------------------------------------------------------------------- 1 | package tesseract; 2 | 3 | import earth.terrarium.botarium.common.fluid.base.PlatformFluidHandler; 4 | import net.minecraft.core.BlockPos; 5 | import net.minecraft.core.Direction; 6 | import net.minecraft.world.item.ItemStack; 7 | import net.minecraft.world.level.Level; 8 | import net.minecraft.world.level.block.entity.BlockEntity; 9 | import tesseract.api.fluid.IFluidNode; 10 | import tesseract.api.gt.IEnergyHandler; 11 | import tesseract.api.gt.IEnergyHandlerItem; 12 | import tesseract.api.heat.IHeatHandler; 13 | import tesseract.api.item.IItemNode; 14 | import tesseract.api.item.PlatformItemHandler; 15 | 16 | import java.util.Optional; 17 | import java.util.ServiceLoader; 18 | 19 | public interface TesseractCapUtils { 20 | TesseractCapUtils INSTANCE = ServiceLoader.load(TesseractCapUtils.class).findFirst().orElseThrow(() -> new IllegalStateException("No implementation of TesseractCapUtils found")); 21 | //public static final TesseractCapUtils INSTANCE = new TesseractCapUtils(); 22 | Optional getEnergyHandlerItem(ItemStack stack); 23 | 24 | Optional getWrappedEnergyHandlerItem(ItemStack stack); 25 | 26 | 27 | Optional getEnergyHandler(BlockEntity entity, Direction side); 28 | 29 | 30 | Optional getHeatHandler(BlockEntity entity, Direction side); 31 | 32 | 33 | Optional getItemHandler(BlockEntity entity, Direction side); 34 | 35 | 36 | Optional getFluidHandler(Level level, BlockPos pos, Direction side); 37 | 38 | 39 | IFluidNode getFluidNode(Level level, long pos, Direction capSide, Runnable capCallback); 40 | 41 | 42 | IItemNode getItemNode(Level level, long pos, Direction capSide, Runnable capCallback); 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/TesseractConfig.java: -------------------------------------------------------------------------------- 1 | package tesseract; 2 | 3 | import carbonconfiglib.config.Config; 4 | import carbonconfiglib.config.ConfigEntry; 5 | import carbonconfiglib.config.ConfigHandler; 6 | import carbonconfiglib.config.ConfigSection; 7 | 8 | public class TesseractConfig { 9 | 10 | public static ConfigEntry.DoubleValue EU_TO_FE_RATIO, EU_TO_TRE_RATIO; 11 | public static ConfigEntry.BoolValue ENABLE_FE_OR_TRE_INPUT, ENABLE_MI_COMPAT; 12 | 13 | public static ConfigHandler CONFIG; 14 | 15 | public static void createConfig(){ 16 | Config config = new Config(Tesseract.API_ID); 17 | ConfigSection section = config.add("general"); 18 | EU_TO_FE_RATIO = section.addDouble("eu_to_fe_ratio", 4.0, "The ratio of the eu to the fe energy converting - Default: (1.0 EU = 4.0 FE)").setMin(Double.MIN_VALUE); 19 | EU_TO_TRE_RATIO = section.addDouble("eu_to_tre_ratio", 1.0, "The ratio of the eu to the tre energy converting - Default: (1.0 EU = 1.0 TRE)").setMin(Double.MIN_VALUE); 20 | ENABLE_FE_OR_TRE_INPUT = section.addBool("enable_fe_or_tre_input", !TesseractPlatformUtils.INSTANCE.isForge(), "Enables EU Machines and cables being able to input FE or TRE(Tech Reborn Energy),", 21 | "Please do not enable on forge unless you have balanced the fe compat to not be broken af due to power creep. - Default: false on forge, true on fabric"); 22 | ENABLE_MI_COMPAT = section.addBool("enabled_mi_compat", true, "Enables Tesseract EU having compat with MI energy. - Default: true"); 23 | CONFIG = TesseractPlatformUtils.INSTANCE.createConfig(config); 24 | CONFIG.register(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/TesseractGraphWrappers.java: -------------------------------------------------------------------------------- 1 | package tesseract; 2 | 3 | import tesseract.api.GraphWrapper; 4 | import tesseract.api.fluid.FluidTransaction; 5 | import tesseract.api.fluid.IFluidNode; 6 | import tesseract.api.fluid.IFluidPipe; 7 | import tesseract.api.gt.GTTransaction; 8 | import tesseract.api.gt.IGTCable; 9 | import tesseract.api.gt.IGTNode; 10 | import tesseract.api.heat.HeatController; 11 | import tesseract.api.heat.HeatTransaction; 12 | import tesseract.api.heat.IHeatNode; 13 | import tesseract.api.heat.IHeatPipe; 14 | import tesseract.api.item.IItemNode; 15 | import tesseract.api.item.IItemPipe; 16 | import tesseract.api.item.ItemController; 17 | import tesseract.api.item.ItemTransaction; 18 | import tesseract.api.rf.IRFCable; 19 | import tesseract.api.rf.IRFNode; 20 | import tesseract.api.rf.RFController; 21 | import tesseract.api.rf.RFTransaction; 22 | import tesseract.controller.Energy; 23 | import tesseract.controller.Fluid; 24 | import tesseract.graph.INode; 25 | 26 | public class TesseractGraphWrappers { 27 | public static final GraphWrapper HEAT_CONTROLLER = new GraphWrapper<>(HeatController::new, IHeatNode.GETTER); 28 | public static final GraphWrapper FLUID = new GraphWrapper<>(Fluid::new, IFluidNode.GETTER); 29 | public static final GraphWrapper ITEM = new GraphWrapper<>(ItemController::new, IItemNode.GETTER); 30 | 31 | public static final GraphWrapper RF = new GraphWrapper<>(RFController::new, IRFNode.GETTER); 32 | public static long dropletMultiplier = TesseractPlatformUtils.INSTANCE.isForge() ? 1L : 81L; 33 | //public static GraphWrapper FE_ENERGY = new GraphWrapper<>(RFController::new); 34 | public static GraphWrapper GT_ENERGY = new GraphWrapper<>(Energy::new, IGTNode.GT_GETTER); 35 | 36 | public static void init(){} 37 | } 38 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/TesseractPlatformUtils.java: -------------------------------------------------------------------------------- 1 | package tesseract; 2 | 3 | import carbonconfiglib.config.Config; 4 | import carbonconfiglib.config.ConfigHandler; 5 | import net.minecraft.core.Direction; 6 | import net.minecraft.world.item.ItemStack; 7 | import net.minecraft.world.level.Level; 8 | import tesseract.api.gt.IGTNode; 9 | import tesseract.api.heat.IHeatNode; 10 | import tesseract.api.rf.IRFNode; 11 | import tesseract.graph.INode; 12 | 13 | import java.util.ServiceLoader; 14 | 15 | public interface TesseractPlatformUtils { 16 | TesseractPlatformUtils INSTANCE = ServiceLoader.load(TesseractPlatformUtils.class).findFirst().orElseThrow(() -> new IllegalStateException("No implementation of TesseractPlatformUtils found")); 17 | 18 | 19 | IGTNode getGTNode(Level level, long pos, Direction direction, Runnable invalidate); 20 | 21 | IRFNode getRFNode(Level level, long pos, Direction direction, Runnable invalidate); 22 | 23 | IHeatNode getHeatNode(Level level, long pos, Direction direction, Runnable invalidate); 24 | 25 | boolean isFeCap(Class cap); 26 | 27 | 28 | boolean isForge(); 29 | 30 | ConfigHandler createConfig(Config config); 31 | 32 | boolean areCapsCompatible(ItemStack a, ItemStack b); 33 | } 34 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/ConnectionType.java: -------------------------------------------------------------------------------- 1 | package tesseract.api; 2 | 3 | /** 4 | * Enumerator used for classification of connections between producer/consumer. 5 | */ 6 | public enum ConnectionType { 7 | INVALID, 8 | ADJACENT, 9 | SINGLE, 10 | VARIATE, 11 | } -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/Consumer.java: -------------------------------------------------------------------------------- 1 | package tesseract.api; 2 | 3 | import it.unimi.dsi.fastutil.longs.Long2ObjectMap; 4 | import it.unimi.dsi.fastutil.longs.Long2ObjectMaps; 5 | import tesseract.graph.Path; 6 | 7 | import java.util.Comparator; 8 | 9 | import static java.lang.Integer.compare; 10 | 11 | /** 12 | * A class that acts as a wrapper for a node component. 13 | */ 14 | abstract public class Consumer { 15 | 16 | protected final N node; 17 | protected final ConnectionType connection; 18 | 19 | protected Long2ObjectMap full = Long2ObjectMaps.emptyMap(); 20 | protected Long2ObjectMap cross = Long2ObjectMaps.emptyMap(); 21 | protected int distance; 22 | 23 | // Way of the sorting by the priority level and the distance to the node 24 | public static final Comparator> COMPARATOR = (t1, t2) -> (t1.getPriority() == 0 && t2.getPriority() == 0) ? compare(t1.getDistance(), t2.getDistance()) : compare(t2.getPriority(), t1.getPriority()); 25 | 26 | /** 27 | * Creates instance of the node. 28 | * 29 | * @param node The node instance. 30 | * @param path The path information. 31 | */ 32 | protected Consumer(N node, N producer, Path path) { 33 | this.node = node; 34 | 35 | if (path != null) { 36 | full = path.getFull(); 37 | cross = path.getCross(); 38 | } 39 | int fullSize = full.size(); 40 | int crossSize = cross.size(); 41 | 42 | if (crossSize == 0) { 43 | connection = (fullSize == 0) ? ConnectionType.ADJACENT : ConnectionType.SINGLE; 44 | } else { 45 | connection = ConnectionType.VARIATE; 46 | } 47 | } 48 | 49 | /** 50 | * Initialize all connectors of the full path. 51 | */ 52 | public void init() { 53 | if (full != null) { 54 | distance = full.size(); 55 | for (var tuple : full.long2ObjectEntrySet()) { 56 | onConnectorCatch(tuple.getLongKey(), tuple.getValue()); 57 | } 58 | } 59 | 60 | } 61 | 62 | /** 63 | * @return Gets the node ref. 64 | */ 65 | public N getNode() { 66 | return node; 67 | } 68 | 69 | 70 | /** 71 | * @return Gets the total distance from to the given consumer. 72 | */ 73 | public int getDistance() { 74 | return distance; 75 | } 76 | 77 | /** 78 | * @return Gets the connection type. 79 | */ 80 | public ConnectionType getConnection() { 81 | return connection; 82 | } 83 | 84 | /** 85 | * @return Gets the cross path of connectors. 86 | */ 87 | public Long2ObjectMap getCross() { 88 | return cross; 89 | } 90 | /** 91 | * @return Gets the full path of connectors. 92 | */ 93 | public Long2ObjectMap getFull() { 94 | return full; 95 | } 96 | 97 | /** 98 | * Executes when constructor find a connector instance in the provided path. 99 | * 100 | * @param connector The connector object. 101 | */ 102 | protected abstract void onConnectorCatch(long connectorPos, C connector); 103 | 104 | /** 105 | * @return Returns the priority of this node as a number. 106 | */ 107 | protected abstract int getPriority(); 108 | } 109 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/Controller.java: -------------------------------------------------------------------------------- 1 | package tesseract.api; 2 | 3 | import net.minecraft.world.level.Level; 4 | import tesseract.graph.Graph; 5 | import tesseract.graph.Group; 6 | import tesseract.graph.INode; 7 | 8 | 9 | /** 10 | * Class acts as a controller in the group of some components. 11 | */ 12 | abstract public class Controller implements ITickingController { 13 | 14 | protected int tick; 15 | protected final Level dim; 16 | protected Group group; 17 | protected final Graph.INodeGetter getter; 18 | 19 | /** 20 | * Creates instance of the controller. 21 | * 22 | * @param supplier The world. 23 | */ 24 | protected Controller(Level supplier, Graph.INodeGetter getter) { 25 | this.dim = supplier; 26 | this.getter = getter; 27 | } 28 | 29 | /** 30 | * Sets the group for the controller. 31 | * 32 | * @param container The group this controller handles. 33 | */ 34 | public Controller set(INode container) { 35 | this.group = (Group) container; 36 | return this; 37 | } 38 | 39 | /** 40 | * Executes on the tick updates. 41 | */ 42 | @Override 43 | public void tick() { 44 | tick++; 45 | if (tick % 20 == 0) { 46 | onFrame(); 47 | } 48 | } 49 | /** 50 | * Frame handler, which executes each second. 51 | */ 52 | protected abstract void onFrame(); 53 | 54 | @Override 55 | public Level getWorld() { 56 | return this.dim; 57 | } 58 | } -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/IConnectable.java: -------------------------------------------------------------------------------- 1 | package tesseract.api; 2 | 3 | import net.minecraft.core.Direction; 4 | 5 | /** 6 | * A simple interface for representing connectable objects. 7 | */ 8 | public interface IConnectable { 9 | 10 | /** 11 | * @param direction The direction vector. 12 | * @return True if connect to the direction, false otherwise. 13 | */ 14 | boolean connects(Direction direction); 15 | 16 | boolean validate(Direction dir); 17 | } 18 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/ITickingController.java: -------------------------------------------------------------------------------- 1 | package tesseract.api; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.world.level.Level; 5 | import org.jetbrains.annotations.NotNull; 6 | import tesseract.api.capability.ITransactionModifier; 7 | import tesseract.graph.INode; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Interface abstracting ticking behaviour for the groups in the graph. 13 | */ 14 | public interface ITickingController { 15 | 16 | /** 17 | * Server tick handler. 18 | */ 19 | void tick(); 20 | 21 | /** 22 | * Notify the controller about group structure change. 23 | */ 24 | void change(); 25 | 26 | /** 27 | * Creates new controller for split group. 28 | * 29 | * @param group New group. 30 | * @return New controller for the group. 31 | */ 32 | ITickingController clone(INode group); 33 | 34 | /** 35 | * @return To get simple things like a some information. 36 | */ 37 | void getInfo(long pos, @NotNull List list); 38 | 39 | /** 40 | * Core method of Tesseract. Inserts an object into this pipe. 41 | * @param producerPos the position of the producer 42 | * @param side the side at which the object was inserted into the pipe. 43 | * @param transaction the transaction object. 44 | */ 45 | void insert(long producerPos, Direction side, T transaction, ITransactionModifier modifier); 46 | 47 | /** 48 | * Returns the active world for this ticking controller. 49 | * 50 | * @return the world object. 51 | */ 52 | Level getWorld(); 53 | } 54 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/Transaction.java: -------------------------------------------------------------------------------- 1 | package tesseract.api; 2 | 3 | import it.unimi.dsi.fastutil.objects.ObjectArrayList; 4 | 5 | import java.util.Iterator; 6 | import java.util.List; 7 | import java.util.function.Consumer; 8 | 9 | public abstract class Transaction { 10 | private final ObjectArrayList> onCommit; 11 | private final ObjectArrayList transmitted; 12 | private final Consumer consumer; 13 | private boolean committed; 14 | 15 | public Transaction(final Consumer consumed) { 16 | this.transmitted = new ObjectArrayList<>(1); 17 | this.onCommit = new ObjectArrayList<>(1); 18 | this.consumer = consumed; 19 | this.committed = false; 20 | } 21 | 22 | protected T addData(T t) { 23 | if (committed) return t; 24 | this.transmitted.add(t); 25 | return t; 26 | } 27 | 28 | public T getLast() { 29 | if (transmitted.size() == 0) throw new IllegalStateException("call to Transaction::getLast without data"); 30 | return transmitted.get(transmitted.size()-1); 31 | } 32 | 33 | public Iterable getOffset(int j) { 34 | return () ->{ 35 | Iterator t = this.transmitted.iterator(); 36 | for (int i = 0; i < j; i++) { 37 | t.next(); 38 | } 39 | return t; 40 | }; 41 | } 42 | 43 | public List getData() { 44 | return transmitted; 45 | } 46 | 47 | public boolean commitSuccessfull() { 48 | return this.committed && this.transmitted.size() > 0; 49 | } 50 | 51 | public void onCommit(Consumer consumer) { 52 | if (committed) return; 53 | this.onCommit.ensureCapacity(transmitted.size()); 54 | this.onCommit.add(transmitted.size() - 1, consumer); 55 | } 56 | 57 | public void withCallbackBefore(int offset, Consumer consumer) { 58 | for (int i = offset; i < this.onCommit.size(); i++) { 59 | var value = this.onCommit.get(i); 60 | this.onCommit.add(i, consumer.andThen(value)); 61 | } 62 | } 63 | 64 | public void withCallbackAfter(int offset, Consumer consumer) { 65 | for (int i = offset; i < this.onCommit.size(); i++) { 66 | var value = this.onCommit.get(i); 67 | this.onCommit.add(i, value.andThen(consumer)); 68 | } 69 | } 70 | public void commit() { 71 | if (committed) return; 72 | for (int i = 0; i < transmitted.size(); i++) { 73 | if (onCommit.get(i) != null) { 74 | onCommit.get(i).accept(transmitted.get(i)); 75 | } 76 | this.consumer.accept(transmitted.get(i)); 77 | } 78 | committed = true; 79 | } 80 | 81 | public abstract boolean isValid(); 82 | 83 | public abstract boolean canContinue(); 84 | 85 | } 86 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/capability/ITransactionModifier.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.capability; 2 | 3 | import net.minecraft.core.Direction; 4 | 5 | @FunctionalInterface 6 | public interface ITransactionModifier { 7 | boolean modify(Object stack, Direction side, boolean input, boolean simulate); 8 | 9 | ITransactionModifier EMPTY = (a,b,c,d) -> false; 10 | } 11 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/capability/TesseractBaseCapability.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.capability; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.world.level.block.entity.BlockEntity; 5 | import tesseract.api.IConnectable; 6 | 7 | public abstract class TesseractBaseCapability { 8 | public final T tile; 9 | public final Direction side; 10 | public final boolean isNode; 11 | public final ITransactionModifier callback; 12 | protected boolean isSending; 13 | 14 | public TesseractBaseCapability(T tile, Direction side, boolean isNode, ITransactionModifier callback) { 15 | this.tile = tile; 16 | this.side = side; 17 | this.isNode = isNode; 18 | this.callback = callback; 19 | this.isSending = false; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/capability/TesseractRFCapability.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.capability; 2 | 3 | import earth.terrarium.botarium.common.energy.base.EnergySnapshot; 4 | import earth.terrarium.botarium.common.energy.util.EnergyHooks; 5 | import net.minecraft.core.BlockPos; 6 | import net.minecraft.core.Direction; 7 | import net.minecraft.nbt.CompoundTag; 8 | import net.minecraft.world.level.block.entity.BlockEntity; 9 | import tesseract.TesseractGraphWrappers; 10 | import tesseract.api.rf.IRFCable; 11 | import tesseract.api.rf.IRFNode; 12 | import tesseract.api.rf.RFTransaction; 13 | import tesseract.graph.Graph; 14 | import tesseract.util.Pos; 15 | 16 | public class TesseractRFCapability extends TesseractBaseCapability implements IRFNode { 17 | private RFTransaction old; 18 | public TesseractRFCapability(T tile, Direction side, boolean isNode, ITransactionModifier callback) { 19 | super(tile, side, isNode, callback); 20 | } 21 | 22 | @Override 23 | public boolean canInput(Direction direction) { 24 | return true; 25 | } 26 | 27 | @Override 28 | public boolean canOutput(Direction direction) { 29 | return true; 30 | } 31 | 32 | @Override 33 | public long insertEnergy(long maxAmount, boolean simulate) { 34 | if (this.isSending) return 0; 35 | this.isSending = true; 36 | if (!simulate) { 37 | if (old == null) return 0; 38 | old.commit(); 39 | } else { 40 | long pos = tile.getBlockPos().asLong(); 41 | RFTransaction transaction = new RFTransaction(maxAmount, a -> {}); 42 | if (!this.isNode) { 43 | TesseractGraphWrappers.RF.getController(tile.getLevel(), pos).insert(pos, side, transaction, callback); 44 | } else { 45 | transferAroundPipe(transaction, pos); 46 | } 47 | this.old = transaction; 48 | } 49 | this.isSending = false; 50 | return maxAmount - old.rf; 51 | } 52 | 53 | private void transferAroundPipe(RFTransaction transaction, long pos) { 54 | for (Direction dir : Graph.DIRECTIONS) { 55 | if (dir == this.side || !this.tile.connects(dir)) continue; 56 | BlockEntity otherTile = tile.getLevel().getBlockEntity(BlockPos.of(Pos.offset(pos, dir))); 57 | if (otherTile != null) { 58 | long rf = transaction.rf; 59 | if (this.callback.modify(rf, dir, false, true) || this.callback.modify(rf, side, true, true)) continue; 60 | //Check the handler. 61 | var cap = EnergyHooks.safeGetBlockEnergyManager(otherTile, dir.getOpposite()); 62 | if (cap.isEmpty()) continue; 63 | //Perform insertion, and add to the transaction. 64 | var handler = cap.get(); 65 | long amount = handler.insert(rf, true); 66 | if (amount > 0) { 67 | transaction.addData(rf, a -> { 68 | if (this.callback.modify(a, dir, false, true) || this.callback.modify(a, side, true, true)) return; 69 | handler.insert(a, false); 70 | }); 71 | } 72 | if (transaction.rf == 0) break; 73 | } 74 | } 75 | } 76 | 77 | @Override 78 | public long extractEnergy(long maxAmount, boolean simulate) { 79 | return 0; 80 | } 81 | 82 | @Override 83 | public void setEnergy(long energy) { 84 | 85 | } 86 | 87 | @Override 88 | public long getStoredEnergy() { 89 | return 0; 90 | } 91 | 92 | @Override 93 | public long getMaxCapacity() { 94 | return 0; 95 | } 96 | 97 | @Override 98 | public long maxInsert() { 99 | return 0; 100 | } 101 | 102 | @Override 103 | public long maxExtract() { 104 | return 0; 105 | } 106 | 107 | @Override 108 | public boolean allowsInsertion() { 109 | return true; 110 | } 111 | 112 | @Override 113 | public boolean allowsExtraction() { 114 | return true; 115 | } 116 | 117 | @Override 118 | public EnergySnapshot createSnapshot() { 119 | return null; 120 | } 121 | 122 | @Override 123 | public void deserialize(CompoundTag nbt) { 124 | 125 | } 126 | 127 | @Override 128 | public CompoundTag serialize(CompoundTag nbt) { 129 | return null; 130 | } 131 | 132 | @Override 133 | public void clearContent() { 134 | 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/context/TesseractItemContext.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.context; 2 | 3 | import net.minecraft.nbt.CompoundTag; 4 | import net.minecraft.world.item.Item; 5 | import net.minecraft.world.item.ItemStack; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | public interface TesseractItemContext { 9 | Item getItem(); 10 | 11 | @NotNull 12 | CompoundTag getTag(); 13 | 14 | int getCount(); 15 | 16 | void setItemStack(ItemStack stack); 17 | 18 | default ItemStack getItemStack(){ 19 | ItemStack stack = new ItemStack(getItem(), getCount()); 20 | stack.setTag(getTag()); 21 | return stack; 22 | } 23 | 24 | default CompoundTag getOrCreateTagElement(String key) { 25 | if (this.getTag().contains(key, 10)) { 26 | return this.getTag().getCompound(key); 27 | } else { 28 | CompoundTag compoundTag = new CompoundTag(); 29 | this.getTag().put(key, compoundTag); 30 | return compoundTag; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/fluid/FluidConsumer.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fluid; 2 | 3 | import earth.terrarium.botarium.common.fluid.base.FluidHolder; 4 | import net.minecraft.core.Direction; 5 | import tesseract.api.ConnectionType; 6 | import tesseract.api.Consumer; 7 | import tesseract.graph.Path; 8 | 9 | 10 | /** 11 | * A class that acts as a container for a fluid consumer. 12 | */ 13 | public class FluidConsumer extends Consumer { 14 | 15 | private int isProof = 1; 16 | private int minCapacity = Integer.MAX_VALUE; 17 | 18 | public long getMinPressure() { 19 | return minPressure; 20 | } 21 | 22 | private long minPressure = Long.MAX_VALUE; 23 | private int minTemperature = Integer.MAX_VALUE; 24 | public final Direction input; 25 | 26 | public long lowestPipePosition = -1; 27 | 28 | /** 29 | * Creates instance of the consumer. 30 | * 31 | * @param consumer The consumer node. 32 | * @param path The path information. 33 | * @param dir The added direction. 34 | */ 35 | public FluidConsumer(IFluidNode consumer,IFluidNode producer, Path path, Direction dir) { 36 | super(consumer,producer, path); 37 | init(); 38 | this.input = dir; 39 | } 40 | 41 | /** 42 | * Adds fluid to the node. Returns amount of fluid that was filled. 43 | * 44 | * @param data FluidData attempting to fill the tank. 45 | * @param simulate If true, the fill will only be simulated. 46 | * @return Amount of fluid that was accepted (or would be, if simulated) by the tank. 47 | */ 48 | public long insert(FluidHolder data, boolean simulate) { 49 | return node.insertFluid(data, simulate); 50 | } 51 | 52 | /** 53 | * @param fluid The Fluid to be queried. 54 | * @return If the tank can hold the fluid (EVER, not at the time of query). 55 | */ 56 | public boolean canHold(FluidHolder fluid) { 57 | return node.canInput(fluid, input); 58 | } 59 | 60 | /** 61 | * @return Returns the priority of this node as a number. 62 | */ 63 | public int getPriority() { 64 | return node.getPriority(input); 65 | } 66 | 67 | /** 68 | * @param temperature The current temperature. 69 | * @param isGas True if current liquid is in a gas state. 70 | * @return Checks that the consumer is able to receive fluid. 71 | */ 72 | public boolean canHandle(int temperature, boolean isGas) { 73 | return minTemperature >= temperature /*&& minPressure >= pressure */ && isProof == (isGas ? 1 : 0); 74 | } 75 | 76 | @Override 77 | protected void onConnectorCatch(long pos, IFluidPipe pipe) { 78 | isProof = Math.min(isProof, pipe.isGasProof() ? 1 : 0); 79 | minTemperature = Math.min(minTemperature, pipe.getTemperature()); 80 | minCapacity = Math.min(minCapacity, pipe.getCapacity()); 81 | if (pipe.getPressure() < minPressure && connection == ConnectionType.SINGLE) { 82 | lowestPipePosition = this.getFull().long2ObjectEntrySet().stream().filter(t -> t.getValue() == pipe).findFirst().get().getLongKey(); 83 | } 84 | minPressure = Math.min(minPressure, pipe.getPressureInDroplets()); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/fluid/FluidContainerHandler.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fluid; 2 | 3 | import earth.terrarium.botarium.common.fluid.base.FluidContainer; 4 | import earth.terrarium.botarium.common.fluid.base.FluidHolder; 5 | import earth.terrarium.botarium.common.fluid.base.PlatformFluidHandler; 6 | 7 | import java.util.List; 8 | 9 | public interface FluidContainerHandler extends PlatformFluidHandler { 10 | FluidContainer getFluidContainer(); 11 | @Override 12 | default long insertFluid(FluidHolder fluid, boolean simulate) { 13 | return getFluidContainer().insertFluid(fluid, simulate); 14 | } 15 | 16 | @Override 17 | default FluidHolder extractFluid(FluidHolder fluid, boolean simulate) { 18 | return getFluidContainer().extractFluid(fluid, simulate); 19 | } 20 | 21 | @Override 22 | default int getTankAmount() { 23 | return getFluidContainer().getSize(); 24 | } 25 | 26 | @Override 27 | default FluidHolder getFluidInTank(int tank) { 28 | return getFluidContainer().getFluids().get(tank); 29 | } 30 | 31 | @Override 32 | default List getFluidTanks() { 33 | return getFluidContainer().getFluids(); 34 | } 35 | 36 | @Override 37 | default long getTankCapacity(int tank) { 38 | return getFluidContainer().getTankCapacity(tank); 39 | } 40 | 41 | @Override 42 | default boolean supportsInsertion() { 43 | return getFluidContainer().allowsInsertion(); 44 | } 45 | 46 | @Override 47 | default boolean supportsExtraction() { 48 | return getFluidContainer().allowsExtraction(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/fluid/FluidStatus.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fluid; 2 | 3 | /** 4 | * Enumerator used for classification of events for node/pipes. 5 | */ 6 | public enum FluidStatus { 7 | SUCCESS, 8 | 9 | FAIL_TEMP, 10 | FAIL_LEAK, 11 | FAIL_PRESSURE, 12 | FAIL_CAPACITY, 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/fluid/FluidTransaction.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fluid; 2 | 3 | 4 | import earth.terrarium.botarium.common.fluid.base.FluidHolder; 5 | import tesseract.api.Transaction; 6 | 7 | import java.util.function.Consumer; 8 | 9 | public class FluidTransaction extends Transaction { 10 | 11 | public final FluidHolder stack; 12 | 13 | public FluidTransaction(FluidHolder stack, Consumer consumer) { 14 | super(consumer); 15 | this.stack = stack; 16 | } 17 | 18 | public void addData(FluidHolder stack, Consumer consumer) { 19 | this.addData(stack); 20 | this.stack.setAmount(this.stack.getFluidAmount() - stack.getFluidAmount()); 21 | this.onCommit(consumer); 22 | } 23 | 24 | @Override 25 | public boolean isValid() { 26 | return stack.getFluidAmount() > 0; 27 | } 28 | 29 | @Override 30 | public boolean canContinue() { 31 | return false; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/fluid/IFluidEvent.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fluid; 2 | 3 | import earth.terrarium.botarium.common.fluid.base.FluidHolder; 4 | import net.minecraft.world.level.Level; 5 | 6 | /** 7 | * Interface for handling a fluid events. (Controller will handle them) 8 | */ 9 | public interface IFluidEvent { 10 | 11 | /** 12 | * Executes when the cable trying to transport higher amount of pressure than can. 13 | * 14 | * @param world The world. 15 | * @param pos The pipe position. 16 | * @param pressure The current pressure. 17 | */ 18 | default void onPipeOverPressure(Level world, long pos, long pressure, FluidHolder fluid) { 19 | //NOOP 20 | } 21 | 22 | /** 23 | * Executes when the cable trying to transport higher amount of liquids than can. 24 | * 25 | * @param world The world. 26 | * @param pos The pipe position. 27 | * @param capacity The current capacity. 28 | */ 29 | default void onPipeOverCapacity(Level world, long pos, long capacity, FluidHolder fluid) { 30 | //NOOP 31 | } 32 | 33 | /** 34 | * Executes when the cable trying to transport higher amount of temperature than can. 35 | * 36 | * @param world The world. 37 | * @param pos The pipe position. 38 | * @param temperature The current temperature. 39 | */ 40 | default void onPipeOverTemp(Level world, long pos, int temperature) { 41 | //NOOP 42 | } 43 | 44 | /** 45 | * Executes when the pipe trying to transport gas that can leak. 46 | * Returns resulting fluid stack 47 | * 48 | * @param world The world. 49 | * @param pos The pipe position. 50 | * @param fluid FluidData holding the Fluid to be queried. 51 | */ 52 | default FluidHolder onPipeGasLeak(Level world, long pos, FluidHolder fluid) { 53 | return fluid; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/fluid/IFluidNode.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fluid; 2 | 3 | import earth.terrarium.botarium.common.fluid.base.FluidContainer; 4 | import earth.terrarium.botarium.common.fluid.base.FluidHolder; 5 | import earth.terrarium.botarium.common.fluid.utils.FluidHooks; 6 | import net.minecraft.core.Direction; 7 | import tesseract.TesseractCapUtils; 8 | import tesseract.api.GraphWrapper; 9 | 10 | /** 11 | * An fluid node is the unit of interaction with fluid inventories. 12 | *

13 | * This interface represents a Fluid Tank. IT IS NOT REQUIRED but is provided for convenience. 14 | * You are free to handle Fluids in any way that you wish - this is simply an easy default way. 15 | * DO NOT ASSUME that these objects are used internally in all cases. 16 | *

17 | */ 18 | public interface IFluidNode extends FluidContainer { 19 | /** 20 | * @param direction Direction to the proceed. 21 | * @return Returns the priority of this node as a number. 22 | */ 23 | int getPriority(Direction direction); 24 | 25 | /** 26 | * Used to determine if this storage can receive fluid. 27 | * 28 | * @return If this is false, then any calls to receiveEnergy will return 0. 29 | */ 30 | boolean canInput(Direction direction); 31 | 32 | /** 33 | * Used to determine which sides can output fluid (if any). 34 | * 35 | * @param direction Direction to the output. 36 | * @return Returns true if the given direction is output side. 37 | */ 38 | boolean canOutput(Direction direction); 39 | 40 | /** 41 | * Used to determine which fluids and at which direction can be consumed. 42 | * 43 | * @param fluid The Fluid to be queried. 44 | * @param direction Direction to the input. 45 | * @return If the tank can input the fluid (EVER, not at the time of query). 46 | */ 47 | boolean canInput(FluidHolder fluid, Direction direction); 48 | 49 | /** 50 | * Drains from the input tanks rather than output tanks. Useful for recipes. 51 | * 52 | * @param stack stack to drain. 53 | * @param simulate execute/simulate 54 | * @return the drained stack 55 | */ 56 | default FluidHolder drainInput(FluidHolder stack, boolean simulate) { 57 | return extractFluid(stack, simulate); 58 | } 59 | 60 | default FluidHolder extractFluid(long toExtract, boolean simulate) { 61 | for (int i = 0; i < getSize(); i++) { 62 | FluidHolder fluid = extractFluid(getFluidInTank(i), simulate); 63 | if (!fluid.isEmpty()) return fluid; 64 | } 65 | return FluidHooks.emptyFluid(); 66 | } 67 | 68 | default boolean isFluidValid(int tank, FluidHolder stack) { return true; } 69 | 70 | default FluidHolder getFluidInTank(int tank){ 71 | return getFluids().get(tank); 72 | } 73 | 74 | GraphWrapper.ICapabilityGetter GETTER = (TesseractCapUtils.INSTANCE::getFluidNode); 75 | } 76 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/fluid/IFluidPipe.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fluid; 2 | 3 | import earth.terrarium.botarium.common.fluid.base.FluidHolder; 4 | import tesseract.api.IConnectable; 5 | 6 | /** 7 | * A fluid pipe is the unit of interaction with fluid inventories. 8 | */ 9 | public interface IFluidPipe extends IConnectable { 10 | 11 | /** 12 | * Returns the maximum amount of packets that this fluid component will permit to pass through or be received in a single tick. 13 | * 14 | * @return A positive integer representing the maximum packets, zero or negative indicates that this component accepts no fluid. 15 | */ 16 | int getCapacity(); 17 | 18 | /** 19 | * Returns the maximum amount of pressure that this fluid component will permit to pass through or be received in a single tick. 20 | * 21 | * @return A positive integer representing the maximum amount, zero or negative indicates that this component accepts no fluid. 22 | */ 23 | long getPressure(); 24 | 25 | /** 26 | * Version of {@link #getPressure} that returns a max pressure but in fabric's droplets unit of fluid measurement. 1 mb = 81 droplets 27 | * 28 | * @return A positive long representing the maximum amount, zero or negative indicates that this component accepts no fluid. 29 | */ 30 | default long getPressureInDroplets(){ 31 | return getPressure(); 32 | } 33 | 34 | /** 35 | * Returns the maximum temperature that this fluid component will permit to pass through or be received in a single packet. 36 | * 37 | * @return A positive integer representing the maximum accepted temp, zero or negative indicates that this component accepts no fluid. 38 | */ 39 | int getTemperature(); 40 | 41 | /** 42 | * @return Checks that the pipe can handle gases. 43 | */ 44 | boolean isGasProof(); 45 | 46 | PipeFluidHolder getHolder(); 47 | 48 | /** 49 | * @param stack The current stack. 50 | * @param temperature The current temperature. 51 | * @param isGas True if current liquid is in a gas state. 52 | * @return Checks that the pipe is able to handle single packet. 53 | */ 54 | default FluidStatus getHandler(FluidHolder stack, int temperature, boolean isGas) { 55 | PipeFluidHolder holder = getHolder(); 56 | if (getTemperature() < temperature) return FluidStatus.FAIL_TEMP; 57 | else if (!isGasProof() && isGas) return FluidStatus.FAIL_LEAK; 58 | else if (!holder.allowFluid(stack.getFluid())) return FluidStatus.FAIL_CAPACITY; 59 | return FluidStatus.SUCCESS; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/fluid/PipeFluidHolder.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fluid; 2 | 3 | 4 | import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; 5 | import net.minecraft.resources.ResourceLocation; 6 | import net.minecraft.world.level.material.Fluid; 7 | import tesseract.FluidPlatformUtils; 8 | 9 | import java.util.Set; 10 | 11 | /** 12 | * A class that acts as holder of the fluid that has passed thought pipes. 13 | */ 14 | public class PipeFluidHolder { 15 | 16 | private long pressureAvailable; 17 | public long tickPressure; 18 | public final int maxCapacity; 19 | private final Set fluids = new ObjectOpenHashSet<>(); 20 | 21 | /** 22 | * Creates instance of the holder. 23 | * 24 | * @param pipe The pipe connector. 25 | */ 26 | public PipeFluidHolder(IFluidPipe pipe) { 27 | this.maxCapacity = pipe.getCapacity(); 28 | this.tickPressure = pipe.getPressureInDroplets(); 29 | 30 | this.pressureAvailable = tickPressure * 20L; 31 | } 32 | 33 | public void tick(long time) { 34 | pressureAvailable = Math.min(pressureAvailable + tickPressure, tickPressure * 20); 35 | this.fluids.removeIf(t -> time - t.timeAdded >= 20); 36 | } 37 | 38 | /** 39 | * Uses up a part of this pipe and adds the fluid to the set. 40 | * @param pressure The added pressure. 41 | * @param fluid The fluid type. 42 | */ 43 | public void use(long pressure, Fluid fluid, long currentTime) { 44 | this.pressureAvailable -= pressure; 45 | SetHolder holder = new SetHolder(fluid, currentTime); 46 | fluids.remove(holder); 47 | fluids.add(holder); 48 | } 49 | 50 | /** 51 | * @return Gets the current available pressure. If 0 then no liquid can be sent 52 | */ 53 | public long getPressureAvailable() { 54 | return pressureAvailable; 55 | } 56 | 57 | /** 58 | * @return Gets a current capacity. 59 | */ 60 | public int getCapacity() { 61 | return fluids.size(); 62 | } 63 | 64 | /** 65 | * @return Checks that the holder is not able to handle pressure. 66 | */ 67 | public boolean isOverPressure() { 68 | return pressureAvailable < 0; 69 | } 70 | 71 | /** 72 | * @return Checks that the holder is not able to handle pressure. 73 | */ 74 | public boolean isOverCapacity() { 75 | return maxCapacity < fluids.size(); 76 | } 77 | 78 | public boolean allowFluid(Fluid fluid) { 79 | SetHolder holder = new SetHolder(fluid, 0); 80 | if (fluids.contains(holder)) { 81 | return true; 82 | } 83 | return maxCapacity > fluids.size(); 84 | } 85 | 86 | public Set getFluids() { 87 | return fluids; 88 | } 89 | 90 | public void clear() { 91 | this.fluids.clear(); 92 | this.pressureAvailable = tickPressure*20; 93 | } 94 | 95 | public static class SetHolder { 96 | public final Fluid fluid; 97 | public long timeAdded; 98 | 99 | public SetHolder(final Fluid fluid, long added) { 100 | this.fluid = fluid; 101 | this.timeAdded = added; 102 | } 103 | 104 | @Override 105 | public int hashCode() { 106 | return FluidPlatformUtils.INSTANCE.getFluidId(fluid).hashCode(); 107 | } 108 | 109 | @Override 110 | public boolean equals(Object obj) { 111 | ResourceLocation compare = FluidPlatformUtils.INSTANCE.getFluidId(fluid); 112 | if (obj instanceof SetHolder s) { 113 | return FluidPlatformUtils.INSTANCE.getFluidId(s.fluid).equals(compare); 114 | } 115 | if (obj instanceof Fluid f) { 116 | return FluidPlatformUtils.INSTANCE.getFluidId(f).equals(compare); 117 | } 118 | if (obj instanceof earth.terrarium.botarium.common.fluid.base.FluidHolder s) { 119 | return FluidPlatformUtils.INSTANCE.getFluidId(s.getFluid()).equals(compare); 120 | } 121 | if (obj instanceof ResourceLocation r) { 122 | return r.equals(compare); 123 | } 124 | return false; 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/gt/GTHolder.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.gt; 2 | 3 | /** 4 | * A class that imitates a holder of the packets that has passed thought cables. 5 | */ 6 | public class GTHolder { 7 | 8 | /** 9 | * Creates long with the packed holder. 10 | * 11 | * @param cable The cable connector. 12 | * @param amperage The initial amperage. 13 | */ 14 | public static long create(IGTCable cable, long amperage) { 15 | return (long) cable.getAmps() << 32 | amperage; 16 | } 17 | 18 | /** 19 | * Adds a new amperage. 20 | * 21 | * @param holder The long with the packed holder. 22 | * @param amperage The added amperage. 23 | */ 24 | public static long add(long holder, long amperage) { 25 | return (long) getMaxAmperage(holder) << 32 | getAmperage(holder) + amperage; 26 | } 27 | 28 | /** 29 | * @param holder The long with the packed holder. 30 | * @return Gets a current amperage. 31 | */ 32 | public static int getAmperage(long holder) { 33 | return (int) (holder); 34 | } 35 | 36 | /** 37 | * @param holder The long with the packed holder. 38 | * @return Gets a maximum amperage. 39 | */ 40 | public static int getMaxAmperage(long holder) { 41 | return (int) (holder >> 32); 42 | } 43 | 44 | /** 45 | * @param holder The long with the packed holder. 46 | * @return Checks that the holder is not able to handle it. 47 | */ 48 | public static boolean isOverAmperage(long holder) { 49 | return getMaxAmperage(holder) < getAmperage(holder); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/gt/GTStatus.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.gt; 2 | 3 | /** 4 | * Enumerator used for classification of events for node/cable. 5 | */ 6 | public enum GTStatus { 7 | SUCCESS, 8 | 9 | FAIL_VOLTAGE, 10 | FAIL_AMPERAGE 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/gt/GTTransaction.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.gt; 2 | 3 | import tesseract.api.Transaction; 4 | 5 | import java.util.function.Consumer; 6 | 7 | public class GTTransaction extends Transaction { 8 | 9 | public final long voltage; 10 | public long eu; 11 | 12 | public GTTransaction(long voltage, Consumer consumer) { 13 | super(consumer); 14 | this.voltage = voltage; 15 | this.eu = voltage; 16 | } 17 | 18 | 19 | @Override 20 | public boolean isValid() { 21 | return this.eu > 0; 22 | } 23 | 24 | @Override 25 | public boolean canContinue() { 26 | return eu > 0; 27 | } 28 | 29 | 30 | 31 | public TransferData addData(long eu, long consumedEu, double loss, Consumer data) { 32 | eu = Math.min(eu, this.eu); 33 | TransferData dat = this.addData(new TransferData(this, eu, this.voltage).setLoss(loss)); 34 | this.eu -= Math.min(this.eu, consumedEu); 35 | this.onCommit(data); 36 | return dat; 37 | } 38 | 39 | public static class TransferData { 40 | private final long voltage; 41 | private long eu; 42 | private double loss; 43 | public final GTTransaction transaction; 44 | 45 | public TransferData(GTTransaction transaction, long eu, long voltage) { 46 | this.voltage = voltage; 47 | this.loss = 0; 48 | this.eu = eu; 49 | this.transaction = transaction; 50 | } 51 | 52 | public long getEnergy(long amps, boolean input) { 53 | return input ? (voltage - Math.round(loss)) * amps : voltage * amps; 54 | } 55 | 56 | public double getLoss() { 57 | return loss; 58 | } 59 | 60 | public TransferData setLoss(double loss) { 61 | this.loss = Math.min(this.voltage, loss); 62 | return this; 63 | } 64 | 65 | public long getEu() { 66 | return eu; 67 | } 68 | 69 | public long drainEu(long eu) { 70 | this.eu -= eu; 71 | return eu; 72 | } 73 | 74 | @Override 75 | public String toString() { 76 | return "Transmit eu: " + this.eu + " voltage: " + this.voltage + " loss: " + this.loss; 77 | } 78 | 79 | public long getVoltage() { 80 | return voltage; 81 | } 82 | 83 | public GTTransaction getTransaction() { 84 | return transaction; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/gt/IEnergyHandler.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.gt; 2 | 3 | 4 | import earth.terrarium.botarium.util.Serializable; 5 | 6 | public interface IEnergyHandler extends IGTNode, Serializable { 7 | } 8 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/gt/IEnergyHandlerItem.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.gt; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import tesseract.api.context.TesseractItemContext; 5 | 6 | public interface IEnergyHandlerItem extends IEnergyHandler{ 7 | void setCapacity(long capacity); 8 | 9 | void setEnergy(long energy); 10 | 11 | @NotNull 12 | TesseractItemContext getContainer(); 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/gt/IEnergyHandlerTile.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.gt; 2 | 3 | import net.minecraft.core.Direction; 4 | 5 | public interface IEnergyHandlerTile { 6 | IEnergyHandler getEnergyHandler(Direction side); 7 | } 8 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/gt/IEnergyItem.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.gt; 2 | 3 | import tesseract.api.context.TesseractItemContext; 4 | 5 | public interface IEnergyItem { 6 | IEnergyHandlerItem createEnergyHandler(TesseractItemContext context); 7 | 8 | default boolean canCreate(TesseractItemContext context){ 9 | return true; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/gt/IGTCable.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.gt; 2 | 3 | import tesseract.api.IConnectable; 4 | 5 | /** 6 | * An electric cable is the unit of interaction with electric inventories. 7 | */ 8 | public interface IGTCable extends IConnectable { 9 | 10 | /** 11 | * Returns the energy that this electrical component will permit to lost through or be received in a single tick. 12 | * 13 | * @return A positive double representing the loss energy per block, zero or negative indicates that this component doesn't have a loss. Note: partial amounts will round up to the nearest int when it reaches its destination 14 | */ 15 | double getLoss(); 16 | 17 | /** 18 | * Returns the maximum amount of packets that this electrical component will permit to pass through or be received in a single tick. 19 | * 20 | * @return A positive integer representing the maximum packets, zero or negative indicates that this component accepts no energy. 21 | */ 22 | int getAmps(); 23 | 24 | /** 25 | * Returns the maximum energy that this electrical component will permit to pass through or be received in a single packet. 26 | * 27 | * @return A positive integer representing the maximum accepted energy, zero or negative indicates that this component accepts no energy. 28 | */ 29 | long getVoltage(); 30 | 31 | /** 32 | * 33 | * @return if the cable is insulated 34 | */ 35 | boolean insulated(); 36 | 37 | /** 38 | * @param voltage The current voltage. 39 | * @param amperage The current amperage. 40 | * @return Checks that the cable is able to handle single packet. 41 | */ 42 | default GTStatus getHandler(long voltage, long amperage) { 43 | if (getVoltage() < voltage) return GTStatus.FAIL_VOLTAGE; 44 | else if (getAmps() < amperage) return GTStatus.FAIL_AMPERAGE; 45 | return GTStatus.SUCCESS; 46 | } 47 | 48 | long getHolder(); 49 | 50 | void setHolder(long holder); 51 | } 52 | 53 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/gt/IGTEvent.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.gt; 2 | 3 | import net.minecraft.world.level.Level; 4 | 5 | /** 6 | * Interface for handling an electric events. (Controller will handle them) 7 | */ 8 | public interface IGTEvent { 9 | 10 | /** 11 | * Executes when the node trying to receive higher amount of voltage than can. 12 | * 13 | * @param dim The dimension id. 14 | * @param pos The node position. 15 | * @param voltage The current voltage. 16 | */ 17 | default void onNodeOverVoltage(Level world, long pos, long voltage) { 18 | //NOOP 19 | } 20 | 21 | /** 22 | * Executes when the cable trying to transport higher amount of voltage than can. 23 | * 24 | * @param dim The dimension id. 25 | * @param pos The cable position. 26 | * @param voltage The current voltage. 27 | */ 28 | default void onCableOverVoltage(Level world, long pos, long voltage) { 29 | //NOOP 30 | } 31 | 32 | /** 33 | * Executes when the cable trying to transport higher amount of amperage than can. 34 | * 35 | * @param dim The dimension id. 36 | * @param pos The cable position. 37 | * @param amperage The current amperage. 38 | */ 39 | default void onCableOverAmperage(Level world, long pos, long amperage) { 40 | //NOOP 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/heat/HeatController.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.heat; 2 | 3 | import it.unimi.dsi.fastutil.longs.Long2IntMap; 4 | import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; 5 | import it.unimi.dsi.fastutil.longs.Long2ObjectMap; 6 | import net.minecraft.core.Direction; 7 | import net.minecraft.world.level.Level; 8 | import org.jetbrains.annotations.NotNull; 9 | import tesseract.api.Controller; 10 | import tesseract.api.ITickingController; 11 | import tesseract.api.capability.ITransactionModifier; 12 | import tesseract.graph.Cache; 13 | import tesseract.graph.Graph; 14 | import tesseract.graph.INode; 15 | import tesseract.graph.NodeCache; 16 | import tesseract.util.Pos; 17 | 18 | import java.util.List; 19 | 20 | public class HeatController extends Controller { 21 | 22 | private final Long2IntMap previousTemperature = new Long2IntOpenHashMap(); 23 | private final Long2IntMap currentTemperature = new Long2IntOpenHashMap(); 24 | private final Long2IntMap connectedCount = new Long2IntOpenHashMap(); 25 | 26 | /** 27 | * Creates instance of the controller. 28 | * 29 | * @param supplier The world. 30 | * @param getter the getter for nodes. 31 | */ 32 | public HeatController(Level supplier, Graph.INodeGetter getter) { 33 | super(supplier, getter); 34 | previousTemperature.defaultReturnValue(-1); 35 | currentTemperature.defaultReturnValue(-1); 36 | connectedCount.defaultReturnValue(1); 37 | } 38 | 39 | @Override 40 | protected void onFrame() { 41 | for (Long2ObjectMap.Entry> entry : this.group.connectorsEntries()) { 42 | /*long pos = entry.getLongKey(); 43 | IHeatPipe value = entry.getValue().value(); 44 | final int counts = connectedCount.get(pos); 45 | value.update(true); 46 | if (counts == 0) { 47 | HeatTransaction transaction = value.extract(); 48 | transaction.addData(transaction.available(), -1, a -> {}); 49 | transaction.commit(); 50 | continue; 51 | }*/ 52 | /*Connectivity.connectivityFor(value, dir -> { 53 | IHeatHandler.HeatTransaction transaction = value.extract(); 54 | if (!transaction.isValid()) return; 55 | transaction.limitHeat(value.temperatureCoefficient() / counts); 56 | transfer(pos, dir,transaction); 57 | transaction.addData(transaction.available(), -1, a -> {}); 58 | transaction.commit(); 59 | });*/ 60 | 61 | //Transfer q to both directions. 62 | } 63 | } 64 | 65 | @Override 66 | public void change() { 67 | connectedCount.clear(); 68 | for (Long2ObjectMap.Entry> entry : this.group.connectorsEntries()) { 69 | long pos = entry.getLongKey(); 70 | IHeatPipe value = entry.getValue().value(); 71 | int count = 0; 72 | for (Direction dir : Direction.values()) { 73 | if (value.validate(dir)) count++; 74 | } 75 | connectedCount.put(pos, count); 76 | } 77 | } 78 | 79 | @Override 80 | public void tick() { 81 | super.tick(); 82 | } 83 | 84 | @Override 85 | public ITickingController clone(INode group) { 86 | return new HeatController(this.dim, this.getter).set(group); 87 | } 88 | 89 | @Override 90 | public void getInfo(long pos, @NotNull List list) { 91 | 92 | } 93 | 94 | @Override 95 | public void insert(long producerPos, Direction side, HeatTransaction transaction, ITransactionModifier modifier) { 96 | 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/heat/HeatTransaction.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.heat; 2 | 3 | import tesseract.api.Transaction; 4 | 5 | import java.util.function.Consumer; 6 | 7 | public class HeatTransaction extends Transaction { 8 | 9 | private int heatSize; 10 | private int temperature; 11 | private int usedHeat; 12 | 13 | public HeatTransaction(int heatSize, int temperature, Consumer con) { 14 | super(con); 15 | this.heatSize = heatSize; 16 | this.temperature = temperature; 17 | } 18 | 19 | public void limitHeat(int heat) { 20 | this.heatSize = Math.min(heat, heatSize); 21 | this.heatSize = Math.max(heatSize, 0); 22 | } 23 | 24 | public int getTemperature() { 25 | return temperature; 26 | } 27 | 28 | public HeatTransaction ignoreTemperature() { 29 | this.temperature = -1; 30 | return this; 31 | } 32 | 33 | @Override 34 | public boolean isValid() { 35 | return heatSize > 0 && this.temperature > 0; 36 | } 37 | 38 | @Override 39 | public boolean canContinue() { 40 | return usedHeat < heatSize; 41 | } 42 | 43 | public int available() { 44 | return heatSize - usedHeat; 45 | } 46 | 47 | public int getUsedHeat() { 48 | return usedHeat; 49 | } 50 | 51 | public void addData(int heatAmount, int temperature, Consumer consumer) { 52 | if (heatAmount == 0) return; 53 | if (temperature > this.temperature && this.temperature != -1 && temperature != -1) return; 54 | this.usedHeat += heatAmount; 55 | this.addData(heatAmount); 56 | this.onCommit(consumer); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/heat/IHeatHandler.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.heat; 2 | 3 | 4 | import earth.terrarium.botarium.util.Serializable; 5 | 6 | public interface IHeatHandler extends IHeatNode, Serializable { 7 | } 8 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/heat/IHeatNode.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.heat; 2 | 3 | import net.minecraft.core.Direction; 4 | import tesseract.TesseractPlatformUtils; 5 | import tesseract.api.GraphWrapper; 6 | 7 | public interface IHeatNode { 8 | int insert(int heat, boolean simulate); 9 | 10 | int extract(int heat, boolean simulate); 11 | 12 | int getHeat(); 13 | int getHeatCap(); 14 | void update(boolean active); 15 | 16 | /** 17 | * Gets if this storage can have heat extracted. 18 | * 19 | * @return If this is false, then any calls to extract will return 0. 20 | */ 21 | boolean canOutput(); 22 | 23 | /** 24 | * Used to determine if this storage can receive heat. 25 | * 26 | * @return If this is false, then any calls to insert will return 0. 27 | */ 28 | boolean canInput(); 29 | 30 | /** 31 | * Used to determine if this storage can receive heat in the given direction. 32 | * 33 | * @param direction the direction. 34 | * @return If this is false, then any calls to insert will return 0. 35 | */ 36 | boolean canInput(Direction direction); 37 | 38 | /** 39 | * Used to determine which sides can output heat (if any). 40 | * 41 | * @param direction Direction to the output. 42 | * @return Returns true if the given direction is output side. 43 | */ 44 | boolean canOutput(Direction direction); 45 | 46 | /** 47 | * @return The maximum amount of heat that can be inserted into the container at a time. 48 | */ 49 | long getMaxInsert(); 50 | 51 | /** 52 | * @return The maximum amount of heat that can be extracted from the container at a time. 53 | */ 54 | long getMaxExtract(); 55 | 56 | default int getTemperature() { 57 | return getHeat() / 100; 58 | } 59 | 60 | GraphWrapper.ICapabilityGetter GETTER = TesseractPlatformUtils.INSTANCE::getHeatNode; 61 | } 62 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/heat/IHeatPipe.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.heat; 2 | 3 | 4 | import tesseract.api.IConnectable; 5 | 6 | public interface IHeatPipe extends IConnectable { 7 | 8 | /** 9 | * Returns the heat coefficient of this heat pipes material, q = -k*delta => k 10 | * @return the value. 11 | */ 12 | int temperatureCoefficient(); 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/item/ContainerItemHandler.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.item; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public interface ContainerItemHandler extends PlatformItemHandler { 7 | ExtendedItemContainer getContainer(); 8 | 9 | @Override 10 | default void setStackInSlot(int slot, @NotNull ItemStack stack){ 11 | getContainer().setItem(slot, stack); 12 | } 13 | 14 | @Override 15 | default @NotNull ItemStack getStackInSlot(int slot){ 16 | return getContainer().getItem(slot); 17 | } 18 | 19 | @Override 20 | default int getSlots(){ 21 | return getContainer().getContainerSize(); 22 | } 23 | 24 | @Override 25 | default @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate){ 26 | return getContainer().insertItem(slot, stack, simulate); 27 | } 28 | 29 | @Override 30 | default @NotNull ItemStack extractItem(int slot, @NotNull int amount, boolean simulate){ 31 | return getContainer().extractItem(slot, amount, simulate); 32 | } 33 | 34 | @Override 35 | default int getSlotLimit(int slot){ 36 | return getContainer().getSlotLimit(slot); 37 | } 38 | 39 | @Override 40 | default boolean isItemValid(int slot, @NotNull ItemStack stack){ 41 | return getContainer().canPlaceItem(slot, stack); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/item/ExtendedItemContainer.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.item; 2 | 3 | import earth.terrarium.botarium.common.item.SerializableContainer; 4 | import net.minecraft.world.Container; 5 | import net.minecraft.world.entity.player.Player; 6 | import net.minecraft.world.item.ItemStack; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | public interface ExtendedItemContainer extends SerializableContainer, ContainerItemHandler { 10 | 11 | @Override 12 | default ExtendedItemContainer getContainer(){ 13 | return this; 14 | } 15 | 16 | /** 17 | *

18 | * Inserts an ItemStack into the given slot and return the remainder. 19 | * The ItemStack should not be modified in this function! 20 | *

21 | * 22 | * @param slot Slot to insert into. 23 | * @param stack ItemStack to insert. This must not be modified by the item handler. 24 | * @param simulate If true, the insertion is only simulated 25 | * @return The remaining ItemStack that was not inserted (if the entire stack is accepted, then return an empty ItemStack). 26 | * May be the same as the input ItemStack if unchanged, otherwise a new ItemStack. 27 | * The returned ItemStack can be safely modified after. 28 | **/ 29 | @NotNull 30 | ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate); 31 | 32 | /** 33 | * Extracts an ItemStack from the given slot. 34 | *

35 | * The returned value must be empty if nothing is extracted, 36 | * otherwise its stack size must be less than or equal to {@code amount} and {@link ItemStack#getMaxStackSize()}. 37 | *

38 | * 39 | * @param slot Slot to extract from. 40 | * @param amount Amount to extract (may be greater than the current stack's max limit) 41 | * @param simulate If true, the extraction is only simulated 42 | * @return ItemStack extracted from the slot, must be empty if nothing can be extracted. 43 | * The returned ItemStack can be safely modified after, so item handlers should return a new or copied stack. 44 | **/ 45 | @NotNull 46 | ItemStack extractItem(int slot, int amount, boolean simulate); 47 | 48 | /** 49 | * Retrieves the maximum stack size allowed to exist in the given slot. 50 | * 51 | * @param slot Slot to query. 52 | * @return The maximum stack size allowed in the slot. 53 | */ 54 | int getSlotLimit(int slot); 55 | 56 | //Container overrides 57 | 58 | @Override 59 | default ItemStack removeItem(int index, int count){ 60 | return extractItem(index, count, false); 61 | } 62 | 63 | @Override 64 | default ItemStack removeItemNoUpdate(int index) { 65 | return removeItem(index, getItem(index).getCount()); 66 | } 67 | 68 | @Override 69 | default boolean isEmpty(){ 70 | boolean hasStack = false; 71 | for (int i = 0; i < getContainerSize(); i++) { 72 | ItemStack stack = getItem(i); 73 | if (!stack.isEmpty()) hasStack = true; 74 | }; 75 | return !hasStack; 76 | } 77 | 78 | @Override 79 | default boolean stillValid(Player player){ 80 | return true; 81 | } 82 | 83 | @Override 84 | default void setChanged(){ 85 | 86 | } 87 | 88 | @Override 89 | default void clearContent(){ 90 | for (int i = 0; i < getContainerSize(); i++) { 91 | this.removeItem(i, getItem(i).getCount()); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/item/IItemNode.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.item; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.world.item.ItemStack; 5 | import tesseract.TesseractCapUtils; 6 | import tesseract.api.GraphWrapper; 7 | 8 | 9 | /** 10 | * An item node is the unit of interaction with item inventories. 11 | *

12 | * This interface represents an Item Storage. IT IS NOT REQUIRED but is provided for convenience. 13 | * You are free to handle Items in any way that you wish - this is simply an easy default way. 14 | * DO NOT ASSUME that these objects are used internally in all cases. 15 | *

16 | */ 17 | public interface IItemNode extends ExtendedItemContainer { 18 | 19 | /** 20 | * @param direction Direction to the proceed. 21 | * @return Returns the priority of this node as a number. 22 | */ 23 | int getPriority(Direction direction); 24 | 25 | /** 26 | * @param slot The slot index. 27 | * @return It returns True if the slot has no items else it returns false. 28 | */ 29 | boolean isEmpty(int slot); 30 | 31 | /** 32 | * Gets if this storage can have item extracted. 33 | * 34 | * @return If this is false, then any calls to extractEnergy will return 0. 35 | */ 36 | boolean canOutput(); 37 | 38 | /** 39 | * Used to determine if this storage can receive item. 40 | * 41 | * @return If this is false, then any calls to receiveEnergy will return 0. 42 | */ 43 | boolean canInput(); 44 | 45 | /** 46 | * Used to determine if this storage can receive item. 47 | * 48 | * @return If this is false, then any calls to receiveEnergy will return 0. 49 | */ 50 | boolean canInput(Direction direction); 51 | 52 | /** 53 | * Used to determine which sides can output item (if any). 54 | * 55 | * @param direction Direction to the output. 56 | * @return Returns true if the given direction is output side. 57 | */ 58 | boolean canOutput(Direction direction); 59 | 60 | /** 61 | * Used to determine which items and at which direction can be consumed. 62 | * 63 | * @param item The Item to be queried. 64 | * @param direction Direction to the input. 65 | * @return If the storage can input the item (EVER, not at the time of query). 66 | */ 67 | default boolean canInput(ItemStack item, Direction direction) { 68 | return true; 69 | } 70 | 71 | GraphWrapper.ICapabilityGetter GETTER = (TesseractCapUtils.INSTANCE::getItemNode); 72 | } 73 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/item/IItemPipe.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.item; 2 | 3 | import tesseract.api.IConnectable; 4 | /** 5 | * A item pipe is the unit of interaction with item inventories. 6 | */ 7 | public interface IItemPipe extends IConnectable { 8 | 9 | /** 10 | * Returns the maximum amount of items that this item component will permit to pass through or be received in a single tick. 11 | * 12 | * @return A positive integer representing the maximum packets, zero or negative indicates that this component accepts no items. 13 | */ 14 | int getCapacity(); 15 | 16 | int getStepsize(); 17 | 18 | int getHolder(); 19 | 20 | void setHolder(int holder); 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/item/ItemConsumer.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.item; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.world.item.ItemStack; 5 | import tesseract.api.Consumer; 6 | import tesseract.graph.Path; 7 | 8 | 9 | /** 10 | * A class that acts as a container for a item consumer. 11 | */ 12 | public class ItemConsumer extends Consumer { 13 | 14 | private int minCapacity = Integer.MAX_VALUE; 15 | private final Direction input; 16 | 17 | /** 18 | * Creates instance of the consumer. 19 | * 20 | * @param consumer The consumer node. 21 | * @param path The path information. 22 | * @param dir The input direction. 23 | */ 24 | public ItemConsumer(IItemNode consumer,IItemNode producer, Path path, Direction dir) { 25 | super(consumer,producer, path); 26 | init(); 27 | input = dir; 28 | } 29 | 30 | /** 31 | * Inserts an item into an available slot and return the remainder. 32 | * 33 | * @param stack ItemData to insert. This must not be modified by the item handler. 34 | * @param simulate If true, the insertion is only simulated 35 | * @return The remaining ItemStack that was not inserted (if the entire stack is accepted, then return an empty ItemStack). 36 | * May be the same as the input ItemStack if unchanged, otherwise a new ItemStack. 37 | * The returned ItemStack can be safely modified after. 38 | **/ 39 | public int insert(ItemStack stack, boolean simulate) { 40 | int count = stack.getCount(); 41 | for (int i = 0; i < node.getContainerSize(); i++) { 42 | ItemStack inserted = node.insertItem(i, stack, simulate); 43 | if (inserted.getCount() < stack.getCount()) { 44 | return inserted.getCount(); 45 | } 46 | } 47 | return count; 48 | } 49 | 50 | /** 51 | * @param item The Item to be queried. 52 | * @return If the storage can hold the item (EVER, not at the time of query). 53 | */ 54 | public boolean canAccept(ItemStack item) { 55 | return node.canInput(item, input); 56 | } 57 | 58 | /** 59 | * @return Returns the priority of this node as a number. 60 | */ 61 | public int getPriority() { 62 | return node.getPriority(input); 63 | } 64 | 65 | /** 66 | * @return Checks that the min capacity on the path. 67 | */ 68 | public int getMinCapacity() { 69 | return minCapacity; 70 | } 71 | 72 | @Override 73 | protected void onConnectorCatch(long pos, IItemPipe pipe) { 74 | minCapacity = Math.min(minCapacity, pipe.getCapacity()); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/item/ItemTransaction.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.item; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | import tesseract.api.Transaction; 5 | 6 | import java.util.function.Consumer; 7 | 8 | public class ItemTransaction extends Transaction { 9 | 10 | public final ItemStack stack; 11 | 12 | public ItemTransaction(ItemStack stack, Consumer consumer) { 13 | super(consumer); 14 | this.stack = stack.copy(); 15 | } 16 | 17 | @Override 18 | public boolean isValid() { 19 | return !stack.isEmpty(); 20 | } 21 | 22 | public void addData(ItemStack count, Consumer consumer) { 23 | this.stack.setCount(this.stack.getCount() - count.getCount()); 24 | this.addData(count); 25 | this.onCommit(consumer); 26 | } 27 | 28 | public void addData(int count, Consumer consumer) { 29 | var st = this.stack.copy(); 30 | st.setCount(count); 31 | addData(st, consumer); 32 | } 33 | 34 | @Override 35 | public boolean canContinue() { 36 | return !stack.isEmpty(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/rf/IRFCable.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.rf; 2 | 3 | import tesseract.api.IConnectable; 4 | 5 | /** 6 | * A flux cable is the unit of interaction with electric inventories. 7 | */ 8 | public interface IRFCable extends IConnectable { 9 | 10 | /** 11 | * Returns the maximum amount of energy that this item component will permit to pass through or be received in a single tick. 12 | * 13 | * @return A positive integer representing the maximum packets, zero or negative indicates that this component accepts no energy. 14 | */ 15 | long getCapacity(); 16 | } -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/rf/IRFNode.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.rf; 2 | 3 | import earth.terrarium.botarium.common.energy.base.EnergyContainer; 4 | import earth.terrarium.botarium.util.Updatable; 5 | import net.minecraft.core.Direction; 6 | import net.minecraft.world.level.block.entity.BlockEntity; 7 | import tesseract.TesseractPlatformUtils; 8 | import tesseract.api.GraphWrapper; 9 | import tesseract.api.gt.IGTNode; 10 | import tesseract.graph.INode; 11 | 12 | /** 13 | * A flux node is the unit of interaction with flux inventories. 14 | *

15 | * Derived from the Redstone Flux power system designed by King Lemming and originally utilized in Thermal Expansion and related mods. 16 | * Created with consent and permission of King Lemming and Team CoFH. Released with permission under LGPL 2.1 when bundled with Forge. 17 | *

18 | */ 19 | public interface IRFNode extends EnergyContainer, Updatable { 20 | 21 | /** 22 | * Used to determine if this storage can receive energy in the given direction. 23 | * 24 | * @param direction the direction. 25 | * @return If this is false, then any calls to receiveEnergy will return 0. 26 | */ 27 | boolean canInput(Direction direction); 28 | 29 | /** 30 | * Used to determine which sides can output energy (if any). 31 | * 32 | * @param direction Direction to the output. 33 | * @return Returns true if the given direction is output side. 34 | */ 35 | boolean canOutput(Direction direction); 36 | 37 | @Override 38 | default void update(BlockEntity object) { 39 | 40 | } 41 | 42 | GraphWrapper.ICapabilityGetter GETTER = TesseractPlatformUtils.INSTANCE::getRFNode; 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/rf/RFConsumer.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.rf; 2 | 3 | import tesseract.api.Consumer; 4 | import tesseract.graph.Path; 5 | 6 | import java.util.Comparator; 7 | 8 | import static java.lang.Integer.compare; 9 | 10 | /** 11 | * A class that acts as a container for a item consumer. 12 | */ 13 | public class RFConsumer extends Consumer { 14 | 15 | private long minCapacity = Long.MAX_VALUE; 16 | 17 | // Way of the sorting by the distance to the node 18 | @SuppressWarnings("ComparatorCombinators") 19 | public static final Comparator COMPARATOR = (t1, t2) -> compare(t1.getDistance(), t2.getDistance()); 20 | 21 | /** 22 | * Creates instance of the consumer. 23 | * 24 | * @param consumer The consumer node. 25 | * @param path The path information. 26 | */ 27 | protected RFConsumer(IRFNode consumer, IRFNode producer, Path path) { 28 | super(consumer, producer, path); 29 | init(); 30 | } 31 | 32 | /** 33 | * Adds energy to the node. Returns quantity of energy that was accepted. 34 | * 35 | * @param maxReceive Amount of energy to be inserted. 36 | * @param simulate If true, the insertion will only be simulated. 37 | * @return Amount of energy that was (or would have been, if simulated) accepted by the storage. 38 | */ 39 | public long insert(long maxReceive, boolean simulate) { 40 | return node.insertEnergy(maxReceive, simulate); 41 | } 42 | 43 | /** 44 | * @return Returns the priority of this node as a number. 45 | */ 46 | public int getPriority() { 47 | return 0; 48 | } 49 | 50 | /** 51 | * @return Checks that the min capacity on the path. 52 | */ 53 | public long getMinCapacity() { 54 | return minCapacity; 55 | } 56 | 57 | @Override 58 | protected void onConnectorCatch(long pos, IRFCable cable) { 59 | minCapacity = Math.min(minCapacity, cable.getCapacity()); 60 | } 61 | } -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/rf/RFTransaction.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.rf; 2 | 3 | import tesseract.api.Transaction; 4 | 5 | import java.util.function.Consumer; 6 | 7 | public class RFTransaction extends Transaction { 8 | public long rf; 9 | public RFTransaction(long rf, Consumer consumed) { 10 | super(consumed); 11 | this.rf = rf; 12 | } 13 | 14 | public void addData(long rf, Consumer consumer){ 15 | this.addData(rf); 16 | this.rf -= rf; 17 | this.onCommit(consumer); 18 | } 19 | 20 | @Override 21 | public boolean isValid() { 22 | return rf > 0; 23 | } 24 | 25 | @Override 26 | public boolean canContinue() { 27 | return rf > 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/api/wrapper/ItemStackWrapper.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.wrapper; 2 | 3 | import net.minecraft.nbt.CompoundTag; 4 | import net.minecraft.world.item.Item; 5 | import net.minecraft.world.item.ItemStack; 6 | import org.jetbrains.annotations.NotNull; 7 | import tesseract.api.context.TesseractItemContext; 8 | 9 | public class ItemStackWrapper implements TesseractItemContext { 10 | private ItemStack stack; 11 | public ItemStackWrapper(ItemStack stack){ 12 | this.stack = stack; 13 | } 14 | 15 | @Override 16 | public Item getItem() { 17 | return stack.getItem(); 18 | } 19 | 20 | @Override 21 | public @NotNull CompoundTag getTag() { 22 | return stack.getOrCreateTag(); 23 | } 24 | 25 | @Override 26 | public int getCount() { 27 | return stack.getCount(); 28 | } 29 | 30 | @Override 31 | public void setItemStack(ItemStack stack) { 32 | 33 | } 34 | 35 | @Override 36 | public ItemStack getItemStack() { 37 | return stack; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/controller/Energy.java: -------------------------------------------------------------------------------- 1 | package tesseract.controller; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.world.level.Explosion; 5 | import net.minecraft.world.level.Level; 6 | import tesseract.api.ITickingController; 7 | import tesseract.api.gt.GTController; 8 | import tesseract.api.gt.IGTNode; 9 | import tesseract.graph.Graph; 10 | import tesseract.graph.INode; 11 | 12 | public class Energy extends GTController { 13 | 14 | /** 15 | * Creates instance of the tesseract.controller. 16 | * 17 | * @param dim The dimension id. 18 | */ 19 | public Energy(Level dim, Graph.INodeGetter node) { 20 | super(dim, node); 21 | } 22 | 23 | @Override 24 | public void onNodeOverVoltage(Level w, long pos, long voltage) { 25 | Utils.createExplosion(w, BlockPos.of(pos), 4.0F, Explosion.BlockInteraction.BREAK); 26 | } 27 | 28 | @Override 29 | public void onCableOverAmperage(Level w, long pos, long amperage) { 30 | Utils.createFireAround(w, BlockPos.of(pos)); 31 | } 32 | 33 | @Override 34 | public void onCableOverVoltage(Level w, long pos, long voltage) { 35 | Utils.createFireAround(w, BlockPos.of(pos)); 36 | } 37 | 38 | @Override 39 | public ITickingController clone(INode group) { 40 | return new Energy(dim, getter).set(group); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/controller/Fluid.java: -------------------------------------------------------------------------------- 1 | package tesseract.controller; 2 | 3 | import earth.terrarium.botarium.common.fluid.base.FluidHolder; 4 | import net.minecraft.core.BlockPos; 5 | import net.minecraft.sounds.SoundEvents; 6 | import net.minecraft.sounds.SoundSource; 7 | import net.minecraft.world.level.Explosion; 8 | import net.minecraft.world.level.Level; 9 | import net.minecraft.world.level.block.Blocks; 10 | import net.minecraft.world.level.material.Fluids; 11 | import org.jetbrains.annotations.NotNull; 12 | import tesseract.FluidPlatformUtils; 13 | import tesseract.api.ITickingController; 14 | import tesseract.api.fluid.FluidController; 15 | import tesseract.api.fluid.IFluidNode; 16 | import tesseract.api.gt.GTController; 17 | import tesseract.graph.Graph; 18 | import tesseract.graph.INode; 19 | 20 | 21 | // TODO: Make explosions depend on pressure, capacity, temperature 22 | public class Fluid extends FluidController { 23 | 24 | private long lastGasLeakSound = 0; 25 | private static final int GAS_WAIT_TIME = 40; 26 | 27 | /** 28 | * Creates instance of the tesseract.controller. 29 | * 30 | * @param dim The dimension id. 31 | */ 32 | public Fluid(Level dim, Graph.INodeGetter get) { 33 | super(dim, get); 34 | } 35 | 36 | @Override 37 | public void onPipeOverPressure(Level w, long pos, long pressure, FluidHolder fluid) { 38 | Utils.createExplosion(w, BlockPos.of(pos), 4.0F, Explosion.BlockInteraction.BREAK); 39 | } 40 | 41 | @Override 42 | public void onPipeOverCapacity(Level w, long pos, long capacity, FluidHolder fluid) { 43 | Utils.createExplosion(w, BlockPos.of(pos), 1.0F, Explosion.BlockInteraction.NONE); 44 | } 45 | 46 | @Override 47 | public void onPipeOverTemp(Level w, long pos, int temperature) { 48 | w.setBlockAndUpdate(BlockPos.of(pos), temperature >= FluidPlatformUtils.INSTANCE.getFluidTemperature(Fluids.LAVA) ? Blocks.LAVA.defaultBlockState() : Blocks.FIRE.defaultBlockState()); 49 | } 50 | 51 | @Override 52 | public FluidHolder onPipeGasLeak(Level world, long pos, @NotNull FluidHolder fluid) { 53 | if (fluid.isEmpty()) return fluid; 54 | FluidHolder stack = fluid.copyHolder(); 55 | stack.setAmount((int) ((double) stack.getFluidAmount() * PIPE_LEAK)); 56 | if ((world.getGameTime() - lastGasLeakSound) > GAS_WAIT_TIME) { 57 | world.playSound(null, BlockPos.of(pos), SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); 58 | lastGasLeakSound = world.getGameTime(); 59 | } 60 | return stack; 61 | } 62 | 63 | @Override 64 | public ITickingController clone(INode group) { 65 | return new Fluid(dim, getter).set(group); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/controller/Utils.java: -------------------------------------------------------------------------------- 1 | package tesseract.controller; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.core.Direction; 5 | import net.minecraft.core.particles.ParticleTypes; 6 | import net.minecraft.server.level.ServerLevel; 7 | import net.minecraft.world.level.Explosion; 8 | import net.minecraft.world.level.Level; 9 | import net.minecraft.world.level.block.Blocks; 10 | 11 | public class Utils { 12 | 13 | public static void createExplosion(Level world, BlockPos pos, float explosionRadius, Explosion.BlockInteraction modeIn) { 14 | if (world instanceof ServerLevel) { 15 | ServerLevel w = (ServerLevel) world; 16 | w.explode(null, pos.getX(), pos.getY() + 0.0625D, pos.getZ(), explosionRadius, true, modeIn); 17 | w.sendParticles(ParticleTypes.SMOKE, pos.getX(), pos.getY() + 0.5D, pos.getZ(), 1, 0, 0, 0, 0.0D); 18 | } 19 | } 20 | 21 | public static void createFireAround(Level world, BlockPos pos) { 22 | boolean fired = false; 23 | for (Direction side : Direction.values()) { 24 | BlockPos offset = pos.relative(side); 25 | if (world.getBlockState(offset) == Blocks.AIR.defaultBlockState()) { 26 | world.setBlockAndUpdate(offset, Blocks.FIRE.defaultBlockState()); 27 | fired = true; 28 | } 29 | } 30 | if (!fired) world.setBlockAndUpdate(pos, Blocks.FIRE.defaultBlockState()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/graph/Cache.java: -------------------------------------------------------------------------------- 1 | package tesseract.graph; 2 | 3 | import net.minecraft.core.Direction; 4 | import tesseract.api.IConnectable; 5 | 6 | /** 7 | * The Cache is a class that should work with connections. 8 | */ 9 | public class Cache { 10 | 11 | private final byte connectivity; 12 | private final T value; 13 | 14 | /** 15 | * Creates a cache instance. 16 | */ 17 | public Cache(T value) { 18 | this.value = value; 19 | this.connectivity = Connectivity.of(value); 20 | } 21 | 22 | public static Cache of(T value) { 23 | return new Cache<>(value); 24 | } 25 | 26 | /** 27 | * @param direction The direction index. 28 | * @return True when connect, false otherwise. 29 | */ 30 | public boolean connects(Direction direction) { 31 | return Connectivity.has(connectivity, direction.get3DDataValue()); 32 | } 33 | 34 | /** 35 | * @return Gets the connection state. 36 | */ 37 | public byte connectivity() { 38 | return connectivity; 39 | } 40 | 41 | /** 42 | * @return Gets the cache. 43 | */ 44 | public T value() { 45 | return value; 46 | } 47 | 48 | @Override 49 | public boolean equals(Object obj) { 50 | return obj instanceof Cache && ((Cache) obj).value == this.value; 51 | } 52 | 53 | @Override 54 | public int hashCode() { 55 | return value.hashCode(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/graph/Connectivity.java: -------------------------------------------------------------------------------- 1 | package tesseract.graph; 2 | 3 | import net.minecraft.core.Direction; 4 | import tesseract.api.IConnectable; 5 | 6 | 7 | /** 8 | * A class that acts as a controller for a connectivity of the connectables. 9 | */ 10 | public class Connectivity { 11 | 12 | /** 13 | * Initialize connectivity for a given instance. 14 | * 15 | * @param connectable The given instance. 16 | * @return Gets the connectivity for instance. 17 | */ 18 | public static byte of(IConnectable connectable) { 19 | byte connectivity = 0; 20 | 21 | for (Direction direction : Direction.values()) { 22 | if (connectable.connects(direction)) { 23 | connectivity = Connectivity.set(connectivity, direction.get3DDataValue()); 24 | } 25 | } 26 | 27 | return connectivity; 28 | } 29 | 30 | /** 31 | * Bitwise set operation. 32 | * 33 | * @param connectivity The provided state. 34 | * @param side The side index. {@see tesseract.util.Dir} 35 | * @return Connectivity state for a connection. 36 | */ 37 | public static byte set(byte connectivity, int side) { 38 | return (byte) (connectivity | (1 << side)); 39 | } 40 | 41 | /** 42 | * Bitwise clear operation. 43 | * 44 | * @param connectivity The provided state. 45 | * @param side The side index. {@see tesseract.util.Dir} 46 | * @return Connectivity state for a connection. 47 | */ 48 | public static byte clear(byte connectivity, int side) { 49 | return (byte) (connectivity & ~(1 << side)); 50 | } 51 | 52 | /** 53 | * Bitwise toggle operation. 54 | * 55 | * @param connectivity The provided state. 56 | * @param side The side index. {@see tesseract.util.Dir} 57 | * @return Connectivity state for a connection. 58 | */ 59 | public static byte toggle(byte connectivity, int side) { 60 | return (byte) (connectivity ^ (1 << side)); 61 | } 62 | 63 | /** 64 | * Bitwise check operation. 65 | * 66 | * @param connectivity The provided state. 67 | * @param side The side index. {@see tesseract.util.Dir} 68 | * @return True if a connection is exist, false otherwise. 69 | */ 70 | public static boolean has(byte connectivity, int side) { 71 | return (connectivity & (1 << side)) > 0; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/graph/INode.java: -------------------------------------------------------------------------------- 1 | package tesseract.graph; 2 | 3 | import net.minecraft.core.Direction; 4 | 5 | /** 6 | * A simple interface for representing objects that contain groups of positions that are connected in various ways. 7 | * Used by traversal classes in order to determine how they may move from one element to the next. 8 | */ 9 | public interface INode { 10 | 11 | /** 12 | * Tests whether this container contains the specified position. 13 | * 14 | * @param pos The position that the container may potentially contain. 15 | * @return Whether the container contains the specified position. 16 | */ 17 | boolean contains(long pos); 18 | 19 | /** 20 | * Tests whether adjacent positions are linked. 21 | * 22 | * @param from The starting position. 23 | * @param towards The face on the starting position. 24 | * @param to The target position, must be equal to from.offset(towards). 25 | * @return Whether the positions are linked. If a position is not contained within this container, returns false. 26 | */ 27 | boolean linked(long from, Direction towards, long to); 28 | 29 | /** 30 | * Tests whether the given position can link on the given side. 31 | * 32 | * @param pos The starting position, which must exist in the container. 33 | * @param towards The face on the starting position. 34 | * @return Whether the position would connect on the given side, returns false if the position is not within this container. 35 | */ 36 | boolean connects(long pos, Direction towards); 37 | } 38 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/graph/NodeCache.java: -------------------------------------------------------------------------------- 1 | package tesseract.graph; 2 | 3 | import net.minecraft.core.Direction; 4 | import tesseract.api.IConnectable; 5 | import tesseract.graph.Graph.INodeGetter; 6 | 7 | import java.util.EnumMap; 8 | import java.util.Map; 9 | import java.util.function.Consumer; 10 | import java.util.function.Predicate; 11 | 12 | /** 13 | A NodeCache handles updating its internal capabilites, caching the relevant capabilities 14 | from nearby tiles, hence why it is more complicated than a regular Cache. 15 | **/ 16 | public class NodeCache implements IConnectable { 17 | 18 | private final EnumMap value; 19 | public final INodeGetter getter; 20 | private final Predicate validator; 21 | private final Consumer callback; 22 | public final long pos; 23 | 24 | /** 25 | * Creates a cache instance. 26 | */ 27 | public NodeCache(long pos, INodeGetter getter, Predicate validator, 28 | Consumer callback) { 29 | this.value = new EnumMap<>(Direction.class); 30 | this.getter = getter; 31 | this.pos = pos; 32 | this.validator = validator; 33 | this.callback = callback; 34 | for (Direction d : Graph.DIRECTIONS) { 35 | updateSide(d); 36 | } 37 | } 38 | 39 | public static NodeCache of(long pos, T value) { 40 | return new NodeCache<>(pos, value); 41 | } 42 | 43 | public NodeCache(long pos, T value) { 44 | this.value = new EnumMap<>(Direction.class); 45 | this.getter = null; 46 | this.pos = pos; 47 | this.validator = null; 48 | this.callback = null; 49 | for (Direction d : Graph.DIRECTIONS) { 50 | this.value.put(d, value); 51 | } 52 | } 53 | 54 | public boolean connects(Direction side) { 55 | return value.get(side) != null; 56 | } 57 | 58 | public boolean updateSide(Direction side) { 59 | if (getter == null) 60 | return true; 61 | var rec = new CapabilityRecord(side, pos); 62 | if (validator != null & !validator.test(rec)) { 63 | value.remove(side); 64 | return false; 65 | } 66 | // if we have this key it means the capability is still valid. 67 | if (this.value.containsKey(side)) 68 | return true; 69 | T t = getter.get(pos, side, () -> callback.accept(rec)); 70 | if (t == null) { 71 | this.value.remove(side); 72 | return false; 73 | } 74 | this.value.put(side, t); 75 | return true; 76 | } 77 | 78 | public boolean clearSide(Direction side) { 79 | value.remove(side); 80 | return capCount() > 0; 81 | } 82 | 83 | public T value(Direction side) { 84 | return value.get(side); 85 | } 86 | 87 | public Iterable> values() { 88 | return value.entrySet(); 89 | } 90 | 91 | public int capCount() { 92 | return value.size(); 93 | } 94 | 95 | @Override 96 | public boolean validate(Direction dir) { 97 | return false; 98 | } 99 | 100 | public record CapabilityRecord(Direction direction, long position) { 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/graph/Path.java: -------------------------------------------------------------------------------- 1 | package tesseract.graph; 2 | 3 | import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; 4 | import it.unimi.dsi.fastutil.longs.Long2ObjectMap; 5 | import tesseract.api.IConnectable; 6 | import tesseract.util.Node; 7 | 8 | import java.util.Deque; 9 | 10 | /** 11 | * The Path is a class that should work with paths for grids. 12 | */ 13 | public class Path { 14 | 15 | private final Node origin; 16 | private final Node target; 17 | private final Long2ObjectMap full = new Long2ObjectLinkedOpenHashMap<>(); 18 | private final Long2ObjectMap cross = new Long2ObjectLinkedOpenHashMap<>(); 19 | 20 | 21 | /** 22 | * Creates a path instance. 23 | * 24 | * @param connectors The connectors array. 25 | * @param path The path queue. 26 | */ 27 | protected Path(Long2ObjectMap> connectors, Deque path) { 28 | origin = path.pollLast(); 29 | target = path.pollFirst(); 30 | Node node; 31 | while (!path.isEmpty()) { 32 | node = path.removeLast(); 33 | long pos = node.asLong(); 34 | 35 | Cache cache = connectors.get(pos); 36 | if (cache != null) { 37 | C cable = cache.value(); 38 | full.put(pos, cable); 39 | if (node.isCrossroad()) { 40 | cross.put(pos, cable); 41 | } 42 | } 43 | } 44 | } 45 | 46 | /** 47 | * @return Gets the origin position. 48 | */ 49 | public Node origin() { 50 | return origin; 51 | } 52 | 53 | /** 54 | * @return Gets the target position. 55 | */ 56 | public Node target() { 57 | return target; 58 | } 59 | 60 | /** 61 | * @return Gets the full connectors path. 62 | */ 63 | public Long2ObjectMap getFull() { 64 | return full; 65 | } 66 | 67 | /** 68 | * @return Gets the crossroad connectors path. 69 | */ 70 | public Long2ObjectMap getCross() { 71 | return cross; 72 | } 73 | 74 | /** 75 | * @return Checks that the path is empty. 76 | */ 77 | public boolean isEmpty() { 78 | return (origin == null || target == null); 79 | } 80 | } -------------------------------------------------------------------------------- /common/src/main/java/tesseract/graph/traverse/BFDivider.java: -------------------------------------------------------------------------------- 1 | package tesseract.graph.traverse; 2 | 3 | import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; 4 | import it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet; 5 | import it.unimi.dsi.fastutil.longs.LongSet; 6 | import tesseract.graph.INode; 7 | 8 | import java.util.ConcurrentModificationException; 9 | import java.util.function.Consumer; 10 | 11 | /** 12 | * Extension of BFSearcher that helps with dividing up node containers. The BFDivider class executes enough breadth first 13 | * search operations in order to split up a previously connected set of nodes into divided groups of connected nodes. 14 | */ 15 | public class BFDivider { 16 | 17 | private final BFSearcher searcher; 18 | private final Long2IntOpenHashMap roots = new Long2IntOpenHashMap(); 19 | private final LongLinkedOpenHashSet lookup = new LongLinkedOpenHashSet(); 20 | 21 | /** 22 | * Creates a reusable BFDivider instance that will devides the provided container. 23 | * 24 | * @param container The container to use for devides operations. 25 | */ 26 | public BFDivider(INode container) { 27 | searcher = new BFSearcher(container); 28 | roots.defaultReturnValue(Integer.MAX_VALUE); 29 | } 30 | 31 | /** 32 | * Executes the divide operation with the given parameters. 33 | * 34 | * @param removed This function is called once, allowing the caller to provide a list of removed positions. When executing 35 | * breadth first search operations, these positions will not be traversed, making it possible to truly 36 | * remove them from the node contained being searched after divide is complete. 37 | * @param rootProvider Like the previous parameter, this allows the caller to provide a list of positions. However, 38 | * these positions will be used as positions to initiate the search operations from - usually, 39 | * they will be the neighbors of all items in the removed set. 40 | * @param split An acceptor of the sets of divided positions. Each set contains a set of positions determined to be 41 | * connected by the node container. 42 | * @return The index in the sequence of split position sets corresponding to the largest set of positions, ie. a 43 | * return value of 0 indicates that the first returned set was the largest. 44 | */ 45 | public int divide(Consumer removed, Consumer rootProvider, Consumer split) { 46 | if (!lookup.isEmpty() || !roots.isEmpty()) { 47 | throw new ConcurrentModificationException("Attempted to run concurrent divide operations on the same BFDivider instance"); 48 | } 49 | 50 | rootProvider.accept(lookup); 51 | 52 | int bestCount = 0; 53 | int bestColor = 0; 54 | int currentColor = 0; 55 | 56 | try { 57 | for (long root : lookup) { 58 | // Check if this root has already been colored. 59 | int existingColor = roots.get(root); 60 | 61 | if (existingColor != roots.defaultReturnValue()) { 62 | // Already colored! No point in doing it again. 63 | continue; 64 | } 65 | 66 | final int color = currentColor++; 67 | roots.put(root, color); 68 | 69 | LongSet found = new LongLinkedOpenHashSet(); 70 | 71 | searcher.search(root, reached -> { 72 | if (lookup.contains(reached)) { 73 | roots.put(reached, color); 74 | } 75 | 76 | found.add(reached); 77 | }, removed); 78 | 79 | if (found.size() > bestCount) { 80 | bestCount = found.size(); 81 | bestColor = color; 82 | } 83 | 84 | split.accept(found); 85 | } 86 | } finally { 87 | // Clean up the open/closed sets 88 | lookup.clear(); 89 | roots.clear(); 90 | } 91 | 92 | return bestColor; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/graph/traverse/BFSearcher.java: -------------------------------------------------------------------------------- 1 | package tesseract.graph.traverse; 2 | 3 | import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue; 4 | import it.unimi.dsi.fastutil.longs.LongOpenHashSet; 5 | import it.unimi.dsi.fastutil.longs.LongPriorityQueue; 6 | import it.unimi.dsi.fastutil.longs.LongSet; 7 | import net.minecraft.core.Direction; 8 | import tesseract.graph.Graph; 9 | import tesseract.graph.INode; 10 | import tesseract.util.Pos; 11 | 12 | import java.util.ConcurrentModificationException; 13 | import java.util.function.Consumer; 14 | import java.util.function.LongConsumer; 15 | 16 | /** 17 | * Breadth-first searcher implementation for determining connectivity within a graph, used for graph splitting upon node removal. 18 | *

19 | * The BFSearcher implementation allows for reducing allocations by reusing the allocated HashSets, however, the Pos 20 | * allocations cannot currently be elided - there will be one allocation for each reached node. 21 | *

22 | * Due to the above behavior, it is not safe to use BFSearcher from multiple threads. If two search operations happen 23 | * concurrently from different threads, then they will conflict, mixing results between each operation. 24 | */ 25 | public class BFSearcher { 26 | 27 | private final INode container; 28 | private final LongPriorityQueue open = new LongArrayFIFOQueue(); 29 | private final LongOpenHashSet closed = new LongOpenHashSet(); 30 | 31 | /** 32 | * Creates a reusable BFSearcher instance that will search the provided container. 33 | * 34 | * @param container The container to use for search operations. 35 | */ 36 | public BFSearcher(INode container) { 37 | this.container = container; 38 | } 39 | 40 | /** 41 | * Begins a search operation from the specified start position. The searcher will report each new reached position 42 | * to the provided consumer. As a result of the algorithm, each reported position is guaranteed to be connected to 43 | * an existing position, or in the case of the first reported position, it will be identical to from. 44 | * 45 | * @param from The start position of the search operation. This will be the first position reported to the consumer. 46 | * @param reached The receiver of the discovered positions 47 | * @param excluder A function that can add values to the closed set prior to the search operation. 48 | * They will not be reported or traversed; null is interpreted to mean no exclusions. 49 | */ 50 | public void search(long from, LongConsumer reached, Consumer excluder) { 51 | if (!closed.isEmpty() || !open.isEmpty()) { 52 | throw new ConcurrentModificationException("Attempted to run concurrent search operations on the same BFSearcher instance"); 53 | } 54 | 55 | // Exclude all of the provided positions 56 | if (excluder != null) { 57 | excluder.accept(closed); 58 | } 59 | 60 | try { 61 | if (!container.contains(from)) { 62 | return; 63 | } 64 | 65 | open.enqueue(from); 66 | 67 | while (!open.isEmpty()) { 68 | // Pick a position 69 | long current = open.dequeueLong(); 70 | 71 | if (closed.contains(current)) { 72 | // I don't think this should happen, but it works as a sanity check. 73 | // This can happen if the starting point was excluded. 74 | continue; 75 | } 76 | 77 | // Process the position 78 | closed.add(current); 79 | reached.accept(current); 80 | 81 | Pos position = new Pos(current); 82 | // Discover new nodes 83 | for (Direction direction : Graph.DIRECTIONS) { 84 | long pos = position.offset(direction).asLong(); 85 | 86 | if (closed.contains(pos)) { 87 | // Already seen, prevent infinite loops. 88 | continue; 89 | } 90 | 91 | if (container.linked(current, direction, pos)) { 92 | // Note: this allocates a new position 93 | open.enqueue(pos); 94 | } 95 | } 96 | } 97 | } finally { 98 | // Clean up the open/closed sets 99 | open.clear(); 100 | closed.clear(); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/util/CID.java: -------------------------------------------------------------------------------- 1 | package tesseract.util; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | * @link https://gist.github.com/icella/d4011b6808fc549c538c0310528d9e94 7 | */ 8 | public class CID { 9 | 10 | public static final int INVALID = Integer.MAX_VALUE; 11 | public static final int DEFAULT = Integer.MIN_VALUE; 12 | 13 | /** 14 | * Used to create an unique id by incrementation. 15 | */ 16 | private static final AtomicInteger ATOMIC = new AtomicInteger(DEFAULT); 17 | 18 | /** 19 | * @return Increments id and return. 20 | */ 21 | public static int nextId() { 22 | return ATOMIC.getAndIncrement(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/util/ItemHandlerUtils.java: -------------------------------------------------------------------------------- 1 | package tesseract.util; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | import org.jetbrains.annotations.NotNull; 5 | import tesseract.TesseractPlatformUtils; 6 | import tesseract.api.item.PlatformItemHandler; 7 | 8 | 9 | public class ItemHandlerUtils { 10 | @NotNull 11 | public static ItemStack insertItem(PlatformItemHandler dest, @NotNull ItemStack stack, boolean simulate) { 12 | if (dest == null || stack.isEmpty()) 13 | return stack; 14 | for (int i = 0; i < dest.getSlots(); i++) { 15 | stack = dest.insertItem(i, stack, simulate); 16 | if (stack.isEmpty()) { 17 | return ItemStack.EMPTY; 18 | } 19 | } 20 | return stack; 21 | } 22 | 23 | 24 | public static boolean canItemStacksStack(@NotNull ItemStack a, @NotNull ItemStack b) { 25 | if (a.isEmpty() || !a.sameItem(b) || a.hasTag() != b.hasTag()) 26 | return false; 27 | return (!a.hasTag() || a.getTag().equals(b.getTag())) && areCapsCompatible(a, b); 28 | } 29 | 30 | private static boolean areCapsCompatible(ItemStack a, ItemStack b){ 31 | return TesseractPlatformUtils.INSTANCE.areCapsCompatible(a, b); 32 | } 33 | 34 | public static ItemStack copyStackWithSize(@NotNull ItemStack itemStack, int size) { 35 | if (size == 0) return ItemStack.EMPTY; 36 | ItemStack copy = itemStack.copy(); 37 | copy.setCount(size); 38 | return copy; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /common/src/main/java/tesseract/util/Node.java: -------------------------------------------------------------------------------- 1 | package tesseract.util; 2 | 3 | import net.minecraft.core.Direction; 4 | 5 | /** 6 | * The Node is a pretty straightforward class resembling regular nodes. 7 | */ 8 | public class Node extends Pos { 9 | 10 | private Node parent; 11 | private Direction direction; 12 | private int cost, heuristic, function; 13 | private boolean valid; 14 | private boolean crossroad; 15 | 16 | /** 17 | * Creates a node instance. 18 | * 19 | * @param pos The position to duplicate. 20 | * @param direction The direction to the parent. 21 | */ 22 | public Node(Pos pos, Direction direction) { 23 | super(pos); 24 | setDirection(direction); 25 | } 26 | 27 | /** 28 | * Creates a node instance. 29 | * 30 | * @param value The compressed position. 31 | * @param direction The direction to the parent. 32 | */ 33 | public Node(long value, Direction direction) { 34 | super(value); 35 | setDirection(direction); 36 | } 37 | 38 | /** 39 | * Creates a node instance. 40 | * 41 | * @param value The compressed position. 42 | * @param valid The validity state. 43 | */ 44 | public Node(long value, boolean valid) { 45 | super(value); 46 | setValid(valid); 47 | } 48 | 49 | /** 50 | * @return Gets the cost. 51 | */ 52 | public int getCost() { 53 | return cost; 54 | } 55 | 56 | /** 57 | * Sets the cost. 58 | * 59 | * @param cost The cost value. 60 | */ 61 | public void setCost(int cost) { 62 | this.cost = cost; 63 | } 64 | 65 | /** 66 | * @return Gets the heuristic. 67 | */ 68 | public int getHeuristic() { 69 | return heuristic; 70 | } 71 | 72 | /** 73 | * Sets the heuristic. 74 | * 75 | * @param heuristic The heuristic value. 76 | */ 77 | public void setHeuristic(int heuristic) { 78 | this.heuristic = heuristic; 79 | } 80 | 81 | /** 82 | * @return Gets the function. 83 | */ 84 | public int getFunction() { 85 | return function; 86 | } 87 | 88 | /** 89 | * Sets the function. 90 | * 91 | * @param function The function value. 92 | */ 93 | public void setFunction(int function) { 94 | this.function = function; 95 | } 96 | 97 | /** 98 | * @return Gets the parent node. 99 | */ 100 | public Node getParent() { 101 | return parent; 102 | } 103 | 104 | /** 105 | * Sets the parent node. 106 | * 107 | * @param parent The parent node. 108 | */ 109 | public void setParent(Node parent) { 110 | this.parent = parent; 111 | } 112 | 113 | /** 114 | * @return Gets the direction to the parent node. 115 | */ 116 | public Direction getDirection() { 117 | return direction; 118 | } 119 | 120 | /** 121 | * Sets the direction to the parent node. 122 | * 123 | * @param direction The direction. 124 | */ 125 | public void setDirection(Direction direction) { 126 | this.direction = direction; 127 | } 128 | 129 | /** 130 | * @return Is the node valid? 131 | */ 132 | public boolean isValid() { 133 | return valid; 134 | } 135 | 136 | /** 137 | * Sets the valid state. 138 | * 139 | * @param valid True or false. 140 | */ 141 | public void setValid(boolean valid) { 142 | this.valid = valid; 143 | } 144 | 145 | /** 146 | * @return Is the node cross? 147 | */ 148 | public boolean isCrossroad() { 149 | return crossroad; 150 | } 151 | 152 | /** 153 | * Sets the cross state. 154 | * 155 | * @param crossroad True or false. 156 | */ 157 | public void setCrossroad(boolean crossroad) { 158 | this.crossroad = crossroad; 159 | } 160 | 161 | /** 162 | * @return Calculates the heuristic distance. 163 | */ 164 | public int heuristic(Node dest) { 165 | return distanceTo(dest); 166 | } 167 | 168 | /** 169 | * @param dest Calculates the heuristic to the node. 170 | * @return The distance value. 171 | */ 172 | public int distanceTo(Node dest) { 173 | return Math.abs(x - dest.x) + Math.abs(y - dest.y) + Math.abs(z - dest.z); 174 | } 175 | 176 | @Override 177 | public String toString() { 178 | return super.toString() + " [Cost: " + cost + " | Heuristic: " + heuristic + " | Function: " + function + "]"; 179 | } 180 | } -------------------------------------------------------------------------------- /common/src/main/java/tesseract/util/SetUtil.java: -------------------------------------------------------------------------------- 1 | package tesseract.util; 2 | 3 | import it.unimi.dsi.fastutil.longs.LongOpenHashSet; 4 | import it.unimi.dsi.fastutil.longs.LongSet; 5 | import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; 6 | 7 | import java.util.Set; 8 | import java.util.function.LongPredicate; 9 | import java.util.function.Predicate; 10 | 11 | public class SetUtil { 12 | 13 | public static Set union(Set first, Set second) { 14 | Set set = new ObjectOpenHashSet<>(first); 15 | set.addAll(second); 16 | return set; 17 | } 18 | 19 | public static Set union(Set first, Set second, Predicate keep) { 20 | Set set = new ObjectOpenHashSet<>(first); 21 | second.forEach(t -> { 22 | if (keep.test(t)) set.add(t); 23 | }); 24 | return set; 25 | } 26 | 27 | public static LongSet union(LongSet first, LongSet second, LongPredicate keep) { 28 | LongSet set = new LongOpenHashSet(first); 29 | second.forEach(t -> { 30 | if (keep.test(t)) set.add(t); 31 | }); 32 | return set; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /common/src/main/resources/assets/tesseractapi/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregTech-Intergalactical/TesseractAPI/5a162d42f3cb6761dd6ebf05aea7374965d467eb/common/src/main/resources/assets/tesseractapi/Thumbs.db -------------------------------------------------------------------------------- /common/src/main/resources/assets/tesseractapi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregTech-Intergalactical/TesseractAPI/5a162d42f3cb6761dd6ebf05aea7374965d467eb/common/src/main/resources/assets/tesseractapi/icon.png -------------------------------------------------------------------------------- /common/src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "Tesseract API resources", 4 | "pack_format": 8 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /fabric/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "fabric-loom" 3 | } 4 | 5 | archivesBaseName = "${project.tesseract_archive_base_name}-fabric" 6 | 7 | sourceSets { 8 | test { 9 | compileClasspath += main.compileClasspath 10 | runtimeClasspath += main.runtimeClasspath 11 | } 12 | } 13 | 14 | loom { 15 | runs { 16 | testClient { 17 | client() 18 | ideConfigGenerated project.rootProject == project 19 | name = "Testmod Client" 20 | source sourceSets.test 21 | } 22 | testServer { 23 | server() 24 | ideConfigGenerated project.rootProject == project 25 | name = "Testmod Server" 26 | source sourceSets.test 27 | } 28 | } 29 | } 30 | 31 | repositories { 32 | maven { url = "https://mvn.devos.one/snapshots/" } 33 | maven { 34 | url "https://cursemaven.com" 35 | } 36 | } 37 | 38 | dependencies { 39 | minecraft "com.mojang:minecraft:${project.minecraft_version}" 40 | mappings loom.layered() { 41 | officialMojangMappings() 42 | parchment("org.parchmentmc.data:parchment-${project.minecraft_version}:${project.mappings_version}@zip") 43 | } 44 | modImplementation "net.fabricmc:fabric-loader:${project.fabric_loader_version}" 45 | modApi "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" 46 | compileOnly(project(":tesseract-common")) 47 | 48 | modApi(include("teamreborn:energy:${project.energy_version}")) { 49 | transitive = false 50 | } 51 | modImplementation(include("earth.terrarium:botarium-fabric-${project.minecraft_version}:${project.botarium_version}")) 52 | modCompileOnly("curse.maven:modern_industrialization-405388:${project.modern_industrialization_file}") 53 | modImplementation(include("maven.modrinth:carbon-config:${project.carbon_config_fabric_version}")) 54 | } 55 | 56 | processResources { 57 | from project(":tesseract-common").sourceSets.main.resources 58 | inputs.property "version", project.mod_version 59 | 60 | filesMatching("fabric.mod.json") { 61 | expand "version": project.mod_version 62 | } 63 | } 64 | 65 | tasks.named('compileJava', JavaCompile) { 66 | source(project(":tesseract-common").sourceSets.main.allSource) 67 | } 68 | 69 | sourcesJar { 70 | from(project(':tesseract-common').sourceSets.main.allSource) 71 | } 72 | 73 | publishing { 74 | publications { 75 | mavenJava(org.gradle.api.publish.maven.MavenPublication) { 76 | from components.java 77 | } 78 | } 79 | 80 | repositories { 81 | def isCI = System.getenv("CI") 82 | if (isCI) { 83 | maven { 84 | url System.getenv("local_maven_url") 85 | } 86 | } else { 87 | mavenLocal() 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /fabric/gradle.properties: -------------------------------------------------------------------------------- 1 | energy_version=2.2.0 2 | 3 | mod_version=0.2.4.1 4 | modern_industrialization_file=3866891 -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/api/fabric/TesseractLookups.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fabric; 2 | 3 | 4 | import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup; 5 | import net.fabricmc.fabric.api.lookup.v1.item.ItemApiLookup; 6 | import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext; 7 | import net.minecraft.core.Direction; 8 | import net.minecraft.resources.ResourceLocation; 9 | import tesseract.api.gt.IEnergyHandler; 10 | import tesseract.api.gt.IEnergyHandlerItem; 11 | import tesseract.api.heat.IHeatHandler; 12 | 13 | public class TesseractLookups { 14 | 15 | public static final BlockApiLookup ENERGY_HANDLER_SIDED = 16 | BlockApiLookup.get(new ResourceLocation("tesseractapi:sided_gt_energy"), IEnergyHandler.class, Direction.class); 17 | 18 | public static final ItemApiLookup ENERGY_HANDLER_ITEM = 19 | ItemApiLookup.get(new ResourceLocation("tesseractapi:gt_energy"), IEnergyHandlerItem.class, ContainerItemContext.class); 20 | 21 | public static final BlockApiLookup HEAT_HANDLER_SIDED = 22 | BlockApiLookup.get(new ResourceLocation("tesseractapi:sided_heat"), IHeatHandler.class, Direction.class); 23 | } 24 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/api/fabric/TileListeners.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fabric; 2 | 3 | public interface TileListeners { 4 | default void addListener(Runnable listener){ 5 | 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/api/fabric/wrapper/ContainerItemContextWrapper.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fabric.wrapper; 2 | 3 | import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext; 4 | import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; 5 | import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; 6 | import net.minecraft.nbt.CompoundTag; 7 | import net.minecraft.world.item.Item; 8 | import net.minecraft.world.item.ItemStack; 9 | import org.jetbrains.annotations.NotNull; 10 | import tesseract.api.context.TesseractItemContext; 11 | 12 | public class ContainerItemContextWrapper implements TesseractItemContext { 13 | private final ContainerItemContext context; 14 | public ContainerItemContextWrapper(ContainerItemContext context){ 15 | this.context = context; 16 | 17 | } 18 | 19 | @Override 20 | public @NotNull CompoundTag getTag() { 21 | if (context.getItemVariant().isBlank()) return new CompoundTag(); 22 | CompoundTag tag = context.getItemVariant().getNbt(); 23 | if (tag == null){ 24 | ItemStack stack = context.getItemVariant().toStack((int) context.getAmount()); 25 | stack.setTag(new CompoundTag()); 26 | setItemStack(stack); 27 | } 28 | return context.getItemVariant().getNbt(); 29 | } 30 | 31 | @Override 32 | public Item getItem() { 33 | return context.getItemVariant().getItem(); 34 | } 35 | 36 | @Override 37 | public int getCount() { 38 | return (int) context.getAmount(); 39 | } 40 | 41 | @Override 42 | public void setItemStack(ItemStack stack) { 43 | try(Transaction transaction = Transaction.openOuter()) { 44 | context.exchange(ItemVariant.of(stack), stack.getCount(), transaction); 45 | transaction.commit(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/api/fabric/wrapper/EnergyMoveableWrapper.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fabric.wrapper; 2 | 3 | import aztech.modern_industrialization.api.energy.CableTier; 4 | import aztech.modern_industrialization.api.energy.EnergyExtractable; 5 | import aztech.modern_industrialization.api.energy.EnergyInsertable; 6 | import aztech.modern_industrialization.api.energy.EnergyMoveable; 7 | import aztech.modern_industrialization.compat.megane.holder.EnergyComponentHolder; 8 | import aztech.modern_industrialization.util.Simulation; 9 | import net.minecraft.core.Direction; 10 | import net.minecraft.nbt.CompoundTag; 11 | import net.minecraft.world.level.block.entity.BlockEntity; 12 | import tesseract.api.gt.GTConsumer; 13 | import tesseract.api.gt.GTTransaction; 14 | import tesseract.api.gt.IEnergyHandler; 15 | 16 | public class EnergyMoveableWrapper implements IEnergyHandler { 17 | private final BlockEntity blockEntity; 18 | private final EnergyMoveable storage; 19 | 20 | private final GTConsumer.State state = new GTConsumer.State(this); 21 | 22 | public EnergyMoveableWrapper(BlockEntity blockEntity, EnergyMoveable storage) { 23 | this.storage = storage; 24 | this.blockEntity = blockEntity; 25 | } 26 | 27 | @Override 28 | public long extractEu(long voltage, boolean simulate) { 29 | if (storage instanceof EnergyExtractable extractable && extractable.canExtract(getTier(voltage))){ 30 | return extractable.extractEnergy(voltage, simulate ? Simulation.SIMULATE : Simulation.ACT); 31 | } 32 | return 0; 33 | } 34 | 35 | @Override 36 | public long insertEu(long voltage, boolean simulate) { 37 | if (storage instanceof EnergyInsertable insertable && insertable.canInsert(getTier(voltage))){ 38 | return insertable.insertEnergy(voltage, simulate ? Simulation.SIMULATE : Simulation.ACT); 39 | } 40 | return 0; 41 | } 42 | 43 | public CableTier getTier(long tier){ 44 | if (tier <= 32){ 45 | return CableTier.LV; 46 | } else if (tier <= 128){ 47 | return CableTier.MV; 48 | } else if (tier <= 1024){ 49 | return CableTier.HV; 50 | } else if (tier < 8192){ 51 | return CableTier.EV; 52 | } 53 | return CableTier.SUPERCONDUCTOR; 54 | } 55 | 56 | @Override 57 | public long getEnergy() { 58 | if (blockEntity instanceof EnergyComponentHolder holder){ 59 | return holder.getEnergyComponent().getEu(); 60 | } 61 | return 0; 62 | } 63 | 64 | @Override 65 | public long getCapacity() { 66 | if (blockEntity instanceof EnergyComponentHolder holder){ 67 | return holder.getEnergyComponent().getCapacity(); 68 | } 69 | return 0; 70 | } 71 | 72 | @Override 73 | public long getOutputAmperage() { 74 | return 1; 75 | } 76 | 77 | @Override 78 | public long getOutputVoltage() { 79 | if (blockEntity instanceof IEnergyMoveableTiers tiers) return tiers.getOutputVoltage(); 80 | return 32; 81 | } 82 | 83 | @Override 84 | public long getInputAmperage() { 85 | return 1; 86 | } 87 | 88 | @Override 89 | public long getInputVoltage() { 90 | if (blockEntity instanceof IEnergyMoveableTiers tiers) return tiers.getInputVoltage(); 91 | return 32; 92 | } 93 | 94 | @Override 95 | public boolean canOutput() { 96 | return storage instanceof EnergyExtractable; 97 | } 98 | 99 | @Override 100 | public boolean canInput() { 101 | return storage instanceof EnergyInsertable; 102 | } 103 | 104 | @Override 105 | public boolean canInput(Direction dir) { 106 | return canInput(); 107 | } 108 | 109 | @Override 110 | public boolean canOutput(Direction direction) { 111 | return canOutput(); 112 | } 113 | 114 | @Override 115 | public GTConsumer.State getState() { 116 | return state; 117 | } 118 | 119 | @Override 120 | public void tesseractTick() { 121 | getState().onTick(); 122 | } 123 | 124 | @Override 125 | public CompoundTag serialize(CompoundTag tag) { 126 | return null; 127 | } 128 | 129 | @Override 130 | public void deserialize(CompoundTag nbt) { 131 | 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/api/fabric/wrapper/EnergyTileWrapper.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fabric.wrapper; 2 | 3 | import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; 4 | import net.minecraft.core.Direction; 5 | import net.minecraft.nbt.CompoundTag; 6 | import net.minecraft.world.level.block.entity.BlockEntity; 7 | import team.reborn.energy.api.EnergyStorage; 8 | import team.reborn.energy.api.base.SimpleSidedEnergyContainer; 9 | import tesseract.TesseractConfig; 10 | import tesseract.api.gt.GTConsumer; 11 | import tesseract.api.gt.GTTransaction; 12 | import tesseract.api.gt.IEnergyHandler; 13 | 14 | public class EnergyTileWrapper implements IEnergyHandler { 15 | 16 | private final BlockEntity tile; 17 | private final EnergyStorage storage; 18 | 19 | private final GTConsumer.State state = new GTConsumer.State(this); 20 | 21 | public EnergyTileWrapper(BlockEntity tile, EnergyStorage storage) { 22 | this.tile = tile; 23 | this.storage = storage; 24 | } 25 | 26 | @Override 27 | public long insertEu(long voltage, boolean simulate) { 28 | try(Transaction transaction = Transaction.openOuter()) { 29 | long inserted = (long) (storage.insert((long) (voltage * TesseractConfig.EU_TO_TRE_RATIO.get()), transaction) / TesseractConfig.EU_TO_TRE_RATIO.get()); 30 | if (!simulate) transaction.commit(); 31 | return inserted; 32 | } 33 | 34 | } 35 | 36 | @Override 37 | public long extractEu(long voltage, boolean simulate) { 38 | try(Transaction transaction = Transaction.openOuter()) { 39 | long inserted = (long) (storage.extract((long) (voltage * TesseractConfig.EU_TO_TRE_RATIO.get()), transaction) / TesseractConfig.EU_TO_TRE_RATIO.get()); 40 | if (!simulate) transaction.commit(); 41 | return inserted; 42 | } 43 | } 44 | 45 | @Override 46 | public long getEnergy() { 47 | return (long) (storage.getAmount() / TesseractConfig.EU_TO_TRE_RATIO.get()); 48 | } 49 | 50 | @Override 51 | public long getCapacity() { 52 | return (long) (storage.getCapacity() / TesseractConfig.EU_TO_TRE_RATIO.get()); 53 | } 54 | 55 | @Override 56 | public long getOutputAmperage() { 57 | return 1; 58 | } 59 | 60 | @Override 61 | public long getOutputVoltage() { 62 | if (storage instanceof SimpleSidedEnergyContainer limitingEnergyStorage){ 63 | return limitingEnergyStorage.getMaxExtract(null); 64 | } 65 | return 32; 66 | } 67 | 68 | @Override 69 | public long getInputAmperage() { 70 | return 16; 71 | } 72 | 73 | @Override 74 | public long getInputVoltage() { 75 | if (storage instanceof SimpleSidedEnergyContainer limitingEnergyStorage){ 76 | return limitingEnergyStorage.getMaxInsert(null); 77 | } 78 | return 8192; 79 | } 80 | 81 | @Override 82 | public long availableAmpsInput(long voltage) { 83 | long added = 0; 84 | try(Transaction transaction = Transaction.openOuter()) { 85 | added = storage.insert((long) (voltage * TesseractConfig.EU_TO_TRE_RATIO.get()), transaction); 86 | } 87 | if (added == voltage * TesseractConfig.EU_TO_TRE_RATIO.get()) return 1; 88 | return 0; 89 | } 90 | 91 | @Override 92 | public boolean canOutput() { 93 | return TesseractConfig.ENABLE_FE_OR_TRE_INPUT.get() && storage.supportsExtraction(); 94 | } 95 | 96 | @Override 97 | public boolean canInput() { 98 | return storage.supportsInsertion(); 99 | } 100 | 101 | @Override 102 | public boolean canInput(Direction dir) { 103 | return canInput(); 104 | } 105 | 106 | @Override 107 | public boolean canOutput(Direction direction) { 108 | return canOutput(); 109 | } 110 | 111 | @Override 112 | public GTConsumer.State getState() { 113 | return state; 114 | } 115 | 116 | @Override 117 | public void tesseractTick() { 118 | getState().onTick(); 119 | } 120 | 121 | @Override 122 | public CompoundTag serialize(CompoundTag tag) { 123 | return null; 124 | } 125 | 126 | @Override 127 | public void deserialize(CompoundTag nbt) { 128 | 129 | } 130 | } -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/api/fabric/wrapper/ExtendedContainerWrapper.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fabric.wrapper; 2 | 3 | import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; 4 | import net.fabricmc.fabric.api.transfer.v1.storage.Storage; 5 | import net.fabricmc.fabric.api.transfer.v1.storage.StorageView; 6 | import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext; 7 | import net.minecraft.world.item.ItemStack; 8 | import tesseract.api.item.ExtendedItemContainer; 9 | 10 | import java.util.Collections; 11 | import java.util.Iterator; 12 | import java.util.stream.IntStream; 13 | 14 | public record ExtendedContainerWrapper(ExtendedItemContainer container) implements Storage { 15 | @Override 16 | public long insert(ItemVariant resource, long maxAmount, TransactionContext transaction) { 17 | ItemStack stackToInsert = resource.toStack((int) maxAmount); 18 | ItemStack copyToInsert = stackToInsert.copy(); 19 | for (int i = 0; i < container.getContainerSize(); i++) { 20 | copyToInsert = container.insertItem(i, copyToInsert, true); 21 | if (copyToInsert.isEmpty()) break; 22 | } 23 | transaction.addCloseCallback((t, r) -> { 24 | if (r.wasCommitted()){ 25 | ItemStack copy = stackToInsert.copy(); 26 | for (int i = 0; i < container.getContainerSize(); i++) { 27 | copy = container.insertItem(i, copy, false); 28 | if (copy.isEmpty()) break; 29 | } 30 | } 31 | }); 32 | return maxAmount - copyToInsert.getCount(); 33 | } 34 | 35 | @Override 36 | public long extract(ItemVariant resource, long maxAmount, TransactionContext transaction) { 37 | int toExtract = (int) maxAmount; 38 | for (int i = 0; i < container.getContainerSize(); i++) { 39 | if (toExtract <= 0) break; 40 | ItemStack extract = container.extractItem(i, toExtract, true); 41 | if (extract.isEmpty() || !resource.matches(extract)) continue; 42 | toExtract -= extract.getCount(); 43 | } 44 | transaction.addCloseCallback((transaction1, result) -> { 45 | int toExtractAmount = (int) maxAmount; 46 | for (int i = 0; i < container.getContainerSize(); i++) { 47 | if (toExtractAmount <= 0) break; 48 | ItemStack extract = container.extractItem(i, toExtractAmount, true); 49 | if (extract.isEmpty() || !resource.matches(extract)) continue; 50 | container.extractItem(i, toExtractAmount, false); 51 | toExtractAmount -= extract.getCount(); 52 | } 53 | }); 54 | return maxAmount - toExtract; 55 | } 56 | 57 | @Override 58 | public Iterator> iterator(TransactionContext transaction) { 59 | return IntStream.range(0, container.getContainerSize()).mapToObj(i -> container.getItem(i)).map(StackStorageView::new).iterator(); 60 | } 61 | 62 | record StackStorageView(ItemStack stack) implements StorageView{ 63 | 64 | @Override 65 | public long extract(ItemVariant resource, long maxAmount, TransactionContext transaction) { 66 | if (!resource.matches(stack)) return 0; 67 | int maxExtract = Math.min(stack.getCount(), (int) maxAmount); 68 | transaction.addCloseCallback((transaction1, result) -> { 69 | if (result.wasCommitted()) stack.shrink(maxExtract); 70 | }); 71 | return maxExtract; 72 | } 73 | 74 | @Override 75 | public boolean isResourceBlank() { 76 | return stack.isEmpty(); 77 | } 78 | 79 | @Override 80 | public ItemVariant getResource() { 81 | return ItemVariant.of(stack); 82 | } 83 | 84 | @Override 85 | public long getAmount() { 86 | return stack.getCount(); 87 | } 88 | 89 | @Override 90 | public long getCapacity() { 91 | return stack.getMaxStackSize(); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/api/fabric/wrapper/FluidContainerWrapper.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fabric.wrapper; 2 | 3 | 4 | import earth.terrarium.botarium.common.fluid.base.FluidContainer; 5 | import earth.terrarium.botarium.common.fluid.base.FluidHolder; 6 | import earth.terrarium.botarium.common.fluid.base.FluidSnapshot; 7 | import net.minecraft.core.Direction; 8 | import net.minecraft.nbt.CompoundTag; 9 | import tesseract.api.fluid.IFluidNode; 10 | 11 | import java.util.List; 12 | 13 | public record FluidContainerWrapper(FluidContainer container) implements IFluidNode { 14 | @Override 15 | public int getPriority(Direction direction) { 16 | return 0; 17 | } 18 | 19 | @Override 20 | public boolean canInput(Direction direction) { 21 | return container.allowsInsertion(); 22 | } 23 | 24 | @Override 25 | public boolean canOutput(Direction direction) { 26 | return container.allowsExtraction(); 27 | } 28 | 29 | @Override 30 | public boolean canInput(FluidHolder fluid, Direction direction) { 31 | return container.allowsInsertion(); 32 | } 33 | 34 | @Override 35 | public long insertFluid(FluidHolder fluid, boolean simulate) { 36 | return container.insertFluid(fluid, simulate); 37 | } 38 | 39 | @Override 40 | public FluidHolder extractFluid(FluidHolder fluid, boolean simulate) { 41 | return container.extractFluid(fluid, simulate); 42 | } 43 | 44 | @Override 45 | public void setFluid(int slot, FluidHolder fluid) { 46 | container.setFluid(slot, fluid); 47 | } 48 | 49 | @Override 50 | public List getFluids() { 51 | return container.getFluids(); 52 | } 53 | 54 | @Override 55 | public int getSize() { 56 | return container.getSize(); 57 | } 58 | 59 | @Override 60 | public boolean isEmpty() { 61 | return container.isEmpty(); 62 | } 63 | 64 | @Override 65 | public FluidContainer copy() { 66 | return container.copy(); 67 | } 68 | 69 | @Override 70 | public long getTankCapacity(int tankSlot) { 71 | return container.getTankCapacity(tankSlot); 72 | } 73 | 74 | @Override 75 | public void fromContainer(FluidContainer container) { 76 | container.fromContainer(container); 77 | } 78 | 79 | @Override 80 | public long extractFromSlot(FluidHolder fluidHolder, FluidHolder toInsert, Runnable snapshot) { 81 | return container.extractFromSlot(fluidHolder, toInsert, snapshot); 82 | } 83 | 84 | @Override 85 | public boolean allowsInsertion() { 86 | return container.allowsInsertion(); 87 | } 88 | 89 | @Override 90 | public boolean allowsExtraction() { 91 | return container.allowsExtraction(); 92 | } 93 | 94 | @Override 95 | public FluidSnapshot createSnapshot() { 96 | return container.createSnapshot(); 97 | } 98 | 99 | @Override 100 | public void deserialize(CompoundTag nbt) { 101 | container.deserialize(nbt); 102 | } 103 | 104 | @Override 105 | public CompoundTag serialize(CompoundTag nbt) { 106 | return container.serialize(nbt); 107 | } 108 | 109 | @Override 110 | public void clearContent() { 111 | container.clearContent(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/api/fabric/wrapper/IEnergyHandlerMoveable.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fabric.wrapper; 2 | 3 | import aztech.modern_industrialization.api.energy.CableTier; 4 | import aztech.modern_industrialization.api.energy.EnergyExtractable; 5 | import aztech.modern_industrialization.api.energy.EnergyInsertable; 6 | import aztech.modern_industrialization.util.Simulation; 7 | import tesseract.TesseractConfig; 8 | import tesseract.api.gt.GTTransaction; 9 | import tesseract.api.gt.IEnergyHandler; 10 | 11 | public interface IEnergyHandlerMoveable extends EnergyExtractable, EnergyInsertable { 12 | @Override 13 | default long extractEnergy(long maxExtract, Simulation simulation){ 14 | long euToInsert = (long) (maxExtract / TesseractConfig.EU_TO_TRE_RATIO.get()); 15 | return getEnergyHandler().extractEu(euToInsert, simulation.isSimulating()); 16 | } 17 | 18 | 19 | @Override 20 | default long insertEnergy(long maxInsert, Simulation simulation){ 21 | long euToInsert = (long) (maxInsert / TesseractConfig.EU_TO_TRE_RATIO.get()); 22 | long inserted = getEnergyHandler().insertEu(euToInsert, simulation.isSimulating()); 23 | return (long) (inserted * TesseractConfig.EU_TO_TRE_RATIO.get()); 24 | } 25 | 26 | @Override 27 | default boolean canExtract(CableTier cableTier){ 28 | return getEnergyHandler().canOutput(); 29 | } 30 | 31 | 32 | @Override 33 | default boolean canInsert(CableTier cableTier){ 34 | return getEnergyHandler().canInput(); 35 | } 36 | 37 | IEnergyHandler getEnergyHandler(); 38 | } 39 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/api/fabric/wrapper/IEnergyHandlerStorage.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fabric.wrapper; 2 | 3 | import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext; 4 | import team.reborn.energy.api.EnergyStorage; 5 | import tesseract.TesseractConfig; 6 | import tesseract.api.gt.GTTransaction; 7 | import tesseract.api.gt.IEnergyHandler; 8 | 9 | public interface IEnergyHandlerStorage extends EnergyStorage { 10 | /** 11 | * Team Reborn EnergyStorage Implementations 12 | **/ 13 | @Override 14 | default long insert(long maxReceive, TransactionContext context) { 15 | long euToInsert = (long) (maxReceive / TesseractConfig.EU_TO_TRE_RATIO.get()); 16 | long inserted = getEnergyHandler().insertEu(euToInsert, true); 17 | context.addCloseCallback((t, r) -> { 18 | if (r.wasCommitted()){ 19 | getEnergyHandler().insertEu(inserted, false); 20 | } 21 | }); 22 | return (long) (inserted * TesseractConfig.EU_TO_TRE_RATIO.get()); 23 | } 24 | 25 | @Override 26 | default long extract(long maxExtract, TransactionContext context) { 27 | long euToExtract = (long) (maxExtract / TesseractConfig.EU_TO_TRE_RATIO.get()); 28 | long extracted = getEnergyHandler().extractEu(euToExtract, true); 29 | context.addCloseCallback((t, r) -> { 30 | if (r.wasCommitted()){ 31 | getEnergyHandler().extractEu(euToExtract, false); 32 | } 33 | }); 34 | return extracted; 35 | } 36 | 37 | @Override 38 | default long getAmount() { 39 | return (long) (getEnergyHandler().getEnergy() * TesseractConfig.EU_TO_TRE_RATIO.get()); 40 | } 41 | 42 | @Override 43 | default long getCapacity() { 44 | return (long) (getEnergyHandler().getCapacity() * TesseractConfig.EU_TO_TRE_RATIO.get()); 45 | } 46 | 47 | @Override 48 | default boolean supportsInsertion() { 49 | return TesseractConfig.ENABLE_FE_OR_TRE_INPUT.get() && getEnergyHandler().canInput(); 50 | } 51 | 52 | @Override 53 | default boolean supportsExtraction() { 54 | return getEnergyHandler().canOutput(); 55 | } 56 | 57 | IEnergyHandler getEnergyHandler(); 58 | } 59 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/api/fabric/wrapper/IEnergyMoveableTiers.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fabric.wrapper; 2 | 3 | public interface IEnergyMoveableTiers { 4 | long getOutputVoltage(); 5 | 6 | long getInputVoltage(); 7 | } 8 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/api/fabric/wrapper/RFWrapper.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.fabric.wrapper; 2 | 3 | import earth.terrarium.botarium.common.energy.base.EnergySnapshot; 4 | import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; 5 | import net.minecraft.core.Direction; 6 | import net.minecraft.nbt.CompoundTag; 7 | import team.reborn.energy.api.EnergyStorage; 8 | import tesseract.api.rf.IRFNode; 9 | 10 | public record RFWrapper(EnergyStorage storage) implements IRFNode { 11 | @Override 12 | public long extractEnergy(long amount, boolean simulate) { 13 | try (Transaction txn = Transaction.openOuter()) { 14 | long extract = storage.extract(amount, txn); 15 | if(simulate) txn.abort(); 16 | return extract; 17 | } 18 | } 19 | 20 | @Override 21 | public long insertEnergy(long amount, boolean simulate) { 22 | try (Transaction txn = Transaction.openOuter()) { 23 | long insert = storage.insert(amount, txn); 24 | if(simulate) txn.abort(); 25 | return insert; 26 | } 27 | } 28 | 29 | @Override 30 | public void setEnergy(long energy) { 31 | 32 | } 33 | 34 | @Override 35 | public long getStoredEnergy() { 36 | return storage.getAmount(); 37 | } 38 | 39 | @Override 40 | public long getMaxCapacity() { 41 | return storage.getCapacity(); 42 | } 43 | 44 | @Override 45 | public long maxInsert() { 46 | return Long.MAX_VALUE; 47 | } 48 | 49 | @Override 50 | public long maxExtract() { 51 | return Long.MAX_VALUE; 52 | } 53 | 54 | @Override 55 | public boolean allowsInsertion() { 56 | return storage.supportsInsertion(); 57 | } 58 | 59 | @Override 60 | public boolean allowsExtraction() { 61 | return storage.supportsExtraction(); 62 | } 63 | 64 | @Override 65 | public EnergySnapshot createSnapshot() { 66 | return null; 67 | } 68 | 69 | @Override 70 | public void deserialize(CompoundTag nbt) { 71 | 72 | } 73 | 74 | @Override 75 | public CompoundTag serialize(CompoundTag nbt) { 76 | return null; 77 | } 78 | 79 | @Override 80 | public boolean canInput(Direction direction) { 81 | return storage.supportsInsertion(); 82 | } 83 | 84 | @Override 85 | public boolean canOutput(Direction direction) { 86 | return storage.supportsExtraction(); 87 | } 88 | 89 | @Override 90 | public void clearContent() { 91 | 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/fabric/FluidPlatformUtilsImpl.java: -------------------------------------------------------------------------------- 1 | package tesseract.fabric; 2 | 3 | import earth.terrarium.botarium.common.fluid.base.FluidHolder; 4 | import net.fabricmc.api.EnvType; 5 | import net.fabricmc.fabric.api.client.render.fluid.v1.SimpleFluidRenderHandler; 6 | import net.fabricmc.fabric.api.transfer.v1.client.fluid.FluidVariantRendering; 7 | import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; 8 | import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariantAttributes; 9 | import net.fabricmc.loader.api.FabricLoader; 10 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 11 | import net.minecraft.core.Registry; 12 | import net.minecraft.network.chat.Component; 13 | import net.minecraft.resources.ResourceLocation; 14 | import net.minecraft.sounds.SoundEvent; 15 | import net.minecraft.world.level.material.Fluid; 16 | import tesseract.FluidPlatformUtils; 17 | 18 | public class FluidPlatformUtilsImpl extends FluidPlatformUtils { 19 | 20 | public ResourceLocation getStillTexture(Fluid fluid){ 21 | if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { 22 | FluidVariant variant = FluidVariant.of(fluid); 23 | TextureAtlasSprite[] sprites = FluidVariantRendering.getSprites(variant); 24 | 25 | return sprites[0] == null ? SimpleFluidRenderHandler.WATER_STILL : sprites[0].getName(); 26 | } 27 | return new ResourceLocation("block/water_still"); 28 | } 29 | 30 | public ResourceLocation getFlowingTexture(Fluid fluid){ 31 | if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { 32 | FluidVariant variant = FluidVariant.of(fluid); 33 | TextureAtlasSprite[] sprites = FluidVariantRendering.getSprites(variant); 34 | 35 | return sprites[1] == null ? SimpleFluidRenderHandler.WATER_STILL : sprites[1].getName(); 36 | } 37 | return new ResourceLocation("block/water_still"); 38 | } 39 | public ResourceLocation getFluidId(Fluid fluid){ 40 | return Registry.FLUID.getKey(fluid); 41 | } 42 | 43 | public int getFluidTemperature(Fluid fluid){ 44 | return FluidVariantAttributes.getTemperature(FluidVariant.of(fluid)); 45 | } 46 | 47 | public int getFluidDensity(Fluid fluid){ 48 | //cause fabric sucks and doesn't have a good fluid api 49 | return 1000; 50 | } 51 | 52 | public boolean isFluidGaseous(Fluid fluid){ 53 | return FluidVariantAttributes.isLighterThanAir(FluidVariant.of(fluid)); 54 | } 55 | 56 | public int getFluidColor(Fluid fluid){ 57 | if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { 58 | return FluidVariantRendering.getColor(FluidVariant.of(fluid)); 59 | } 60 | return -1; 61 | } 62 | 63 | public SoundEvent getFluidSound(Fluid fluid, boolean fill){ 64 | return fill ? FluidVariantAttributes.getFillSound(FluidVariant.of(fluid)) : FluidVariantAttributes.getEmptySound(FluidVariant.of(fluid)); 65 | } 66 | 67 | public Component getFluidDisplayName(FluidHolder fluid){ 68 | return FluidVariantAttributes.getName(FluidVariant.of(fluid.getFluid(), fluid.getCompound())); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/fabric/TesseractPlatformUtilsImpl.java: -------------------------------------------------------------------------------- 1 | package tesseract.fabric; 2 | 3 | 4 | import carbonconfiglib.CarbonConfig; 5 | import carbonconfiglib.config.Config; 6 | import carbonconfiglib.config.ConfigHandler; 7 | import earth.terrarium.botarium.common.energy.base.EnergyAttachment; 8 | import earth.terrarium.botarium.common.energy.base.EnergyContainer; 9 | import net.minecraft.core.BlockPos; 10 | import net.minecraft.core.Direction; 11 | import net.minecraft.world.item.ItemStack; 12 | import net.minecraft.world.level.Level; 13 | import net.minecraft.world.level.block.entity.BlockEntity; 14 | import team.reborn.energy.api.EnergyStorage; 15 | import tesseract.Tesseract; 16 | import tesseract.TesseractCapUtils; 17 | import tesseract.TesseractPlatformUtils; 18 | import tesseract.api.fabric.TileListeners; 19 | import tesseract.api.fabric.wrapper.RFWrapper; 20 | import tesseract.api.gt.IEnergyHandler; 21 | import tesseract.api.gt.IGTNode; 22 | import tesseract.api.heat.IHeatHandler; 23 | import tesseract.api.heat.IHeatNode; 24 | import tesseract.api.rf.IRFNode; 25 | import tesseract.mixin.fabric.FabricBlockEnergyContainerAccessor; 26 | 27 | import java.util.Optional; 28 | 29 | @SuppressWarnings("UnstableApiUsage") 30 | public class TesseractPlatformUtilsImpl implements TesseractPlatformUtils { 31 | @Override 32 | public IGTNode getGTNode(Level level, long pos, Direction direction, Runnable invalidate){ 33 | BlockEntity tile = level.getBlockEntity(BlockPos.of(pos)); 34 | Optional capability = TesseractCapUtils.INSTANCE.getEnergyHandler(tile, direction); 35 | if (capability.isPresent()) { 36 | if (invalidate != null) ((TileListeners)tile).addListener(() -> invalidate.run()); 37 | return capability.get(); 38 | } 39 | return null; 40 | } 41 | 42 | @Override 43 | public IRFNode getRFNode(Level level, long pos, Direction capSide, Runnable capCallback){ 44 | BlockEntity tile = level.getBlockEntity(BlockPos.of(pos)); 45 | if (tile == null) { 46 | return null; 47 | } 48 | if(tile instanceof EnergyAttachment attachment && attachment.getEnergyHolderType() == BlockEntity.class) { 49 | EnergyContainer container = attachment.getEnergyStorage(tile).getContainer(capSide); 50 | if (container instanceof IRFNode node) { 51 | if (capCallback != null) ((TileListeners)tile).addListener(capCallback); 52 | return node; 53 | } 54 | } 55 | EnergyStorage storage = EnergyStorage.SIDED.find(tile.getLevel(), tile.getBlockPos(), tile.getBlockState(), tile, capSide); 56 | if (storage != null){ 57 | if (capCallback != null) ((TileListeners)tile).addListener(capCallback); 58 | if (storage instanceof FabricBlockEnergyContainerAccessor container && container.getContainer() instanceof IRFNode node){ 59 | return node; 60 | } 61 | return storage instanceof IRFNode node ? node : new RFWrapper(storage); 62 | } 63 | return null; 64 | } 65 | 66 | @Override 67 | public IHeatNode getHeatNode(Level level, long pos, Direction direction, Runnable invalidate){ 68 | BlockEntity tile = level.getBlockEntity(BlockPos.of(pos)); 69 | if (tile == null) return null; 70 | Optional capability = TesseractCapUtils.INSTANCE.getHeatHandler(tile, direction); 71 | if (capability.isPresent()) { 72 | if (invalidate != null) ((TileListeners)tile).addListener(invalidate); 73 | return capability.get(); 74 | } 75 | return null; 76 | } 77 | 78 | @Override 79 | public boolean isFeCap(Class cap){ 80 | return false; 81 | } 82 | 83 | @Override 84 | public boolean isForge(){ 85 | return false; 86 | } 87 | 88 | @Override 89 | public ConfigHandler createConfig(Config config){ 90 | return CarbonConfig.createConfig(Tesseract.API_ID, config); 91 | } 92 | 93 | @Override 94 | public boolean areCapsCompatible(ItemStack a, ItemStack b){ 95 | return true; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/fabric/TesseractPreLoad.java: -------------------------------------------------------------------------------- 1 | package tesseract.fabric; 2 | 3 | import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint; 4 | import tesseract.FluidPlatformUtils; 5 | 6 | public class TesseractPreLoad implements PreLaunchEntrypoint { 7 | @Override 8 | public void onPreLaunch() { 9 | FluidPlatformUtils.INSTANCE = new FluidPlatformUtilsImpl(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/mixin/fabric/BlockEntityMixin.java: -------------------------------------------------------------------------------- 1 | package tesseract.mixin.fabric; 2 | 3 | import it.unimi.dsi.fastutil.objects.ObjectArrayList; 4 | import net.minecraft.world.level.block.entity.BlockEntity; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.Unique; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | import tesseract.api.fabric.TileListeners; 11 | 12 | import java.util.List; 13 | 14 | @Mixin(BlockEntity.class) 15 | public class BlockEntityMixin implements TileListeners { 16 | @Unique 17 | List listeners = new ObjectArrayList<>(); 18 | 19 | @Override 20 | public void addListener(Runnable listener) { 21 | listeners.add(listener); 22 | } 23 | 24 | @Inject(method = "setRemoved", at = @At("TAIL")) 25 | public void runListeners(CallbackInfo ci) { 26 | listeners.forEach(Runnable::run); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/mixin/fabric/FabricBlockEnergyContainerAccessor.java: -------------------------------------------------------------------------------- 1 | package tesseract.mixin.fabric; 2 | 3 | import earth.terrarium.botarium.common.energy.base.EnergyContainer; 4 | import earth.terrarium.botarium.fabric.energy.FabricBlockEnergyContainer; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.gen.Accessor; 7 | 8 | @Mixin(value = FabricBlockEnergyContainer.class, remap = false) 9 | public interface FabricBlockEnergyContainerAccessor { 10 | @Accessor 11 | EnergyContainer getContainer(); 12 | } 13 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/mixin/fabric/FabricBlockFluidContainerAccessor.java: -------------------------------------------------------------------------------- 1 | package tesseract.mixin.fabric; 2 | 3 | import earth.terrarium.botarium.common.fluid.base.FluidContainer; 4 | import earth.terrarium.botarium.fabric.fluid.storage.FabricBlockFluidContainer; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.gen.Accessor; 7 | 8 | @Mixin(value = FabricBlockFluidContainer.class, remap = false) 9 | public interface FabricBlockFluidContainerAccessor { 10 | 11 | @Accessor 12 | FluidContainer getContainer(); 13 | } 14 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/mixin/fabric/IEnergyHandlerMixin.java: -------------------------------------------------------------------------------- 1 | package tesseract.mixin.fabric; 2 | 3 | import org.spongepowered.asm.mixin.Mixin; 4 | import tesseract.api.fabric.wrapper.IEnergyHandlerStorage; 5 | import tesseract.api.gt.IEnergyHandler; 6 | 7 | @Mixin(IEnergyHandler.class) 8 | public interface IEnergyHandlerMixin extends IEnergyHandlerStorage { 9 | @Override 10 | default IEnergyHandler getEnergyHandler(){ 11 | return (IEnergyHandler) this; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/mixin/fabric/TesseractMixinPlugin.java: -------------------------------------------------------------------------------- 1 | package tesseract.mixin.fabric; 2 | 3 | import net.fabricmc.loader.api.FabricLoader; 4 | import org.objectweb.asm.tree.ClassNode; 5 | import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; 6 | import org.spongepowered.asm.mixin.extensibility.IMixinInfo; 7 | import tesseract.TesseractConfig; 8 | 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | public class TesseractMixinPlugin implements IMixinConfigPlugin { 13 | @Override 14 | public void onLoad(String mixinPackage) { 15 | 16 | } 17 | 18 | @Override 19 | public String getRefMapperConfig() { 20 | return null; 21 | } 22 | 23 | @Override 24 | public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { 25 | return !mixinClassName.contains(".mi.") || (FabricLoader.getInstance().isModLoaded("modern_industrialization") && TesseractConfig.ENABLE_MI_COMPAT.get()); 26 | } 27 | 28 | @Override 29 | public void acceptTargets(Set myTargets, Set otherTargets) { 30 | 31 | } 32 | 33 | @Override 34 | public List getMixins() { 35 | return null; 36 | } 37 | 38 | @Override 39 | public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { 40 | 41 | } 42 | 43 | @Override 44 | public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/mixin/fabric/mi/AbstractStorageMachineBEMixin.java: -------------------------------------------------------------------------------- 1 | package tesseract.mixin.fabric.mi; 2 | 3 | import aztech.modern_industrialization.api.energy.CableTier; 4 | import aztech.modern_industrialization.machines.blockentities.AbstractStorageMachineBlockEntity; 5 | import org.spongepowered.asm.mixin.Final; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Shadow; 8 | import tesseract.api.fabric.wrapper.IEnergyMoveableTiers; 9 | 10 | @Mixin(value = AbstractStorageMachineBlockEntity.class, remap = false) 11 | public class AbstractStorageMachineBEMixin implements IEnergyMoveableTiers { 12 | @Shadow @Final protected CableTier to; 13 | 14 | @Shadow @Final protected CableTier from; 15 | 16 | @Override 17 | public long getOutputVoltage() { 18 | return to.getEu(); 19 | } 20 | 21 | @Override 22 | public long getInputVoltage() { 23 | return from.getEu(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /fabric/src/main/java/tesseract/mixin/fabric/mi/IEnergyHandlerMixin.java: -------------------------------------------------------------------------------- 1 | package tesseract.mixin.fabric.mi; 2 | 3 | import org.spongepowered.asm.mixin.Mixin; 4 | import tesseract.api.fabric.wrapper.IEnergyHandlerMoveable; 5 | import tesseract.api.gt.IEnergyHandler; 6 | 7 | @Mixin(IEnergyHandler.class) 8 | public interface IEnergyHandlerMixin extends IEnergyHandlerMoveable { 9 | } 10 | -------------------------------------------------------------------------------- /fabric/src/main/resources/META-INF/services/tesseract.TesseractCapUtils: -------------------------------------------------------------------------------- 1 | tesseract.fabric.TesseractCapUtilsImpl -------------------------------------------------------------------------------- /fabric/src/main/resources/META-INF/services/tesseract.TesseractPlatformUtils: -------------------------------------------------------------------------------- 1 | tesseract.fabric.TesseractPlatformUtilsImpl -------------------------------------------------------------------------------- /fabric/src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "tesseractapi", 4 | "version": "${version}", 5 | "name": "Tesseract API", 6 | "description": "Powerful framework for energy, item, and fluid transport", 7 | "authors": [ 8 | "coderbot16", 9 | "qubka", 10 | "repolainen", 11 | "mitchej123", 12 | "Muramasa", 13 | "Trinsdar" 14 | ], 15 | "contact": { 16 | "sources": "https://github.com/GregTech-Intergalactical/TesseractAPI" 17 | }, 18 | "mixins": [ 19 | "tesseract-fabric.mixins.json" 20 | ], 21 | "license": "LGPL-3.0-only", 22 | "icon": "assets/tesseractapi/icon.png", 23 | "environment": "*", 24 | "entrypoints": { 25 | "main": [ 26 | "tesseract.fabric.TesseractImpl" 27 | ], 28 | "preLaunch" : [ 29 | "tesseract.fabric.TesseractPreLoad" 30 | ] 31 | }, 32 | "depends": { 33 | "fabricloader": ">=0.4.0", 34 | "fabric": "*", 35 | "minecraft": "1.18.2" 36 | }, 37 | "custom": { 38 | "mc-publish": { 39 | "curseforge": 462718 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /fabric/src/main/resources/tesseract-fabric.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "package": "tesseract.mixin.fabric", 4 | "compatibilityLevel": "JAVA_17", 5 | "plugin": "tesseract.mixin.fabric.TesseractMixinPlugin", 6 | "mixins": [ 7 | "BlockEntityMixin", 8 | "FabricBlockEnergyContainerAccessor", 9 | "FabricBlockFluidContainerAccessor", 10 | "IEnergyHandlerMixin", 11 | "SimpleItemEnergyStorageImplMixin", 12 | "mi.AbstractStorageMachineBEMixin", 13 | "mi.IEnergyHandlerMixin" 14 | ], 15 | "minVersion": "0.8" 16 | } -------------------------------------------------------------------------------- /forge/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "net.neoforged.moddev.legacyforge" 3 | } 4 | archivesBaseName = "${project.tesseract_archive_base_name}-forge" 5 | 6 | neoForge { 7 | version = "${project.minecraft_version}-${project.forge_version}" 8 | def at = project(':tesseract-common').file('src/main/resources/META-INF/accesstransformer.cfg') 9 | if (at.exists()) { 10 | accessTransformers.add(at.absolutePath) 11 | } 12 | parchment { 13 | minecraftVersion = project.minecraft_version 14 | mappingsVersion = project.mappings_version 15 | } 16 | runs { 17 | client { 18 | client() 19 | } 20 | data { 21 | data() 22 | } 23 | server { 24 | server() 25 | } 26 | } 27 | mods { 28 | "${project.mod_id}" { 29 | sourceSet sourceSets.main 30 | } 31 | } 32 | } 33 | 34 | mixin { 35 | add sourceSets.main, "tesseract.refmap.json" 36 | config "tesseract-forge.mixins.json" 37 | } 38 | 39 | dependencies { 40 | annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' 41 | implementation("org.jetbrains:annotations:26.0.1") 42 | modImplementation("earth.terrarium:botarium-forge-${project.minecraft_version}:${project.botarium_version}") 43 | compileOnly(project(":tesseract-common")) 44 | testImplementation('junit:junit:4.13.1') 45 | modImplementation("maven.modrinth:carbon-config:${project.carbon_config_forge_version}") 46 | jarJar("earth.terrarium:botarium-forge-${project.minecraft_version}:${project.botarium_version}") 47 | jarJar("maven.modrinth:carbon-config:${project.carbon_config_forge_version}") 48 | } 49 | 50 | tasks.named('compileJava', JavaCompile) { 51 | source(project(":tesseract-common").sourceSets.main.allSource) 52 | } 53 | 54 | processResources { 55 | from project(":tesseract-common").sourceSets.main.resources 56 | inputs.property "version", project.mod_version 57 | 58 | filesMatching("META-INF/mods.toml") { 59 | expand "version": project.mod_version 60 | } 61 | } 62 | 63 | sourcesJar { 64 | from(project(':tesseract-common').sourceSets.main.allSource) 65 | } 66 | 67 | tasks.named('jar', Jar).configure { 68 | manifest { 69 | attributes([ 70 | 'Specification-Title' : mod_id, 71 | 'Specification-Vendor' : "GregTech-Intergalactical", 72 | 'Specification-Version' : '1', // We are version 1 of ourselves 73 | 'Implementation-Title' : project.name, 74 | 'Implementation-Version' : project.version, 75 | 'Implementation-Vendor' : "GregTech-Intergalactical", 76 | 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), 77 | "MixinConfigs" : "tesseract-forge.mixins.json" 78 | ]) 79 | } 80 | } 81 | 82 | publishing { 83 | publications { 84 | mavenJava(org.gradle.api.publish.maven.MavenPublication) { 85 | from components.java 86 | } 87 | } 88 | 89 | repositories { 90 | def isCI = System.getenv("CI") 91 | if (isCI) { 92 | maven { 93 | url System.getenv("local_maven_url") 94 | } 95 | } else { 96 | mavenLocal() 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /forge/gradle.properties: -------------------------------------------------------------------------------- 1 | loom.platform=forge 2 | 3 | mod_version=0.2.4.1 4 | mod_id=tesseractapi -------------------------------------------------------------------------------- /forge/logs/debug.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregTech-Intergalactical/TesseractAPI/5a162d42f3cb6761dd6ebf05aea7374965d467eb/forge/logs/debug.log -------------------------------------------------------------------------------- /forge/logs/latest.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregTech-Intergalactical/TesseractAPI/5a162d42f3cb6761dd6ebf05aea7374965d467eb/forge/logs/latest.log -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/api/forge/Provider.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.forge; 2 | 3 | import earth.terrarium.botarium.util.Serializable; 4 | import net.minecraft.core.Direction; 5 | import net.minecraft.nbt.CompoundTag; 6 | import net.minecraft.nbt.Tag; 7 | import net.minecraftforge.common.capabilities.Capability; 8 | import net.minecraftforge.common.capabilities.ICapabilityProvider; 9 | import net.minecraftforge.common.util.INBTSerializable; 10 | import net.minecraftforge.common.util.LazyOptional; 11 | import net.minecraftforge.common.util.NonNullSupplier; 12 | 13 | public class Provider implements ICapabilityProvider, INBTSerializable { 14 | private final LazyOptional optional; 15 | private final Capability capability; 16 | 17 | public Provider(Capability capability, NonNullSupplier supplier) { 18 | this.optional = LazyOptional.of(supplier); 19 | this.capability = capability; 20 | } 21 | 22 | @Override 23 | public LazyOptional getCapability(Capability cap, Direction side) { 24 | return cap == capability ? optional.cast() : LazyOptional.empty(); 25 | } 26 | 27 | @Override 28 | public Tag serializeNBT() { 29 | return optional.map(t -> { 30 | if (t instanceof INBTSerializable it){ 31 | return it.serializeNBT(); 32 | } else if (t instanceof Serializable it){ 33 | return it.serialize(new CompoundTag()); 34 | } 35 | return new CompoundTag(); 36 | }).orElse(new CompoundTag()); 37 | } 38 | 39 | @Override 40 | public void deserializeNBT(Tag nbt) { 41 | optional.ifPresent(t -> { 42 | if (t instanceof INBTSerializable it){ 43 | it.deserializeNBT(nbt); 44 | } else if (t instanceof Serializable it && nbt instanceof CompoundTag tag){ 45 | it.deserialize(tag); 46 | } 47 | }); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/api/forge/TesseractCaps.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.forge; 2 | 3 | import net.minecraftforge.common.capabilities.Capability; 4 | import net.minecraftforge.common.capabilities.CapabilityManager; 5 | import net.minecraftforge.common.capabilities.CapabilityToken; 6 | import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; 7 | import net.minecraftforge.eventbus.api.SubscribeEvent; 8 | import net.minecraftforge.fml.common.Mod; 9 | import tesseract.Tesseract; 10 | import tesseract.api.gt.IEnergyHandler; 11 | import tesseract.api.gt.IEnergyHandlerItem; 12 | import tesseract.api.heat.IHeatHandler; 13 | 14 | @Mod.EventBusSubscriber(modid = Tesseract.API_ID) 15 | public class TesseractCaps { 16 | public static final Capability ENERGY_HANDLER_CAPABILITY = CapabilityManager.get(new CapabilityToken<>(){}); 17 | public static final Capability ENERGY_HANDLER_CAPABILITY_ITEM = CapabilityManager.get(new CapabilityToken<>(){}); 18 | public static final Capability HEAT_CAPABILITY = CapabilityManager.get(new CapabilityToken<>(){}); 19 | 20 | @SubscribeEvent 21 | public static void register(RegisterCapabilitiesEvent ev) { 22 | ev.register(IEnergyHandler.class); 23 | ev.register(IEnergyHandlerItem.class); 24 | ev.register(IHeatHandler.class); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/api/forge/wrapper/EnergyStackWrapper.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.forge.wrapper; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.nbt.CompoundTag; 5 | import net.minecraft.world.item.ItemStack; 6 | import net.minecraftforge.energy.IEnergyStorage; 7 | import org.jetbrains.annotations.NotNull; 8 | import tesseract.TesseractConfig; 9 | import tesseract.api.context.TesseractItemContext; 10 | import tesseract.api.gt.GTConsumer; 11 | import tesseract.api.gt.IEnergyHandlerItem; 12 | import tesseract.api.wrapper.ItemStackWrapper; 13 | 14 | public class EnergyStackWrapper implements IEnergyHandlerItem { 15 | private final ItemStack stack; 16 | private final IEnergyStorage storage; 17 | 18 | private final GTConsumer.State state = new GTConsumer.State(this); 19 | 20 | public EnergyStackWrapper(ItemStack stack, IEnergyStorage storage) { 21 | this.stack = stack; 22 | this.storage = storage; 23 | } 24 | 25 | @Override 26 | public long insertEu(long voltage, boolean simulate) { 27 | return (long) (storage.receiveEnergy((int) (voltage * TesseractConfig.EU_TO_FE_RATIO.get()), simulate) / TesseractConfig.EU_TO_FE_RATIO.get()); 28 | } 29 | 30 | @Override 31 | public long extractEu(long voltage, boolean simulate) { 32 | return (long) (storage.extractEnergy((int) (voltage * TesseractConfig.EU_TO_FE_RATIO.get()), simulate) / TesseractConfig.EU_TO_FE_RATIO.get()); 33 | } 34 | 35 | @Override 36 | public long getEnergy() { 37 | return (long) (storage.getEnergyStored() / TesseractConfig.EU_TO_FE_RATIO.get()); 38 | } 39 | 40 | @Override 41 | public long getCapacity() { 42 | return (long) (storage.getMaxEnergyStored() / TesseractConfig.EU_TO_FE_RATIO.get()); 43 | } 44 | 45 | @Override 46 | public long getOutputAmperage() { 47 | return 1; 48 | } 49 | 50 | @Override 51 | public long getOutputVoltage() { 52 | return 32; 53 | } 54 | 55 | @Override 56 | public long getInputAmperage() { 57 | return 1; 58 | } 59 | 60 | @Override 61 | public long getInputVoltage() { 62 | return 32; 63 | } 64 | 65 | @Override 66 | public long availableAmpsInput(long voltage) { 67 | if (!canInput()) return 0; 68 | int inserted = storage.receiveEnergy((int) (voltage * TesseractConfig.EU_TO_FE_RATIO.get()), false); 69 | return inserted == voltage ? 1 : 0; 70 | } 71 | 72 | @Override 73 | public boolean canOutput() { 74 | return TesseractConfig.ENABLE_FE_OR_TRE_INPUT.get() && storage.canExtract(); 75 | } 76 | 77 | @Override 78 | public boolean canInput() { 79 | return storage.canReceive(); 80 | } 81 | 82 | @Override 83 | public boolean canInput(Direction dir) { 84 | return canInput(); 85 | } 86 | 87 | @Override 88 | public boolean canOutput(Direction direction) { 89 | return canOutput(); 90 | } 91 | 92 | @Override 93 | public GTConsumer.State getState() { 94 | return state; 95 | } 96 | 97 | @Override 98 | public void tesseractTick() { 99 | getState().onTick(); 100 | } 101 | 102 | @Override 103 | public CompoundTag serialize(CompoundTag tag) { 104 | return null; 105 | } 106 | 107 | @Override 108 | public void deserialize(CompoundTag arg) { 109 | 110 | } 111 | 112 | @Override 113 | public void setCapacity(long capacity) { 114 | 115 | } 116 | 117 | @Override 118 | public void setEnergy(long energy) { 119 | 120 | } 121 | 122 | @Override 123 | public @NotNull TesseractItemContext getContainer() { 124 | return new ItemStackWrapper(this.stack); 125 | } 126 | } -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/api/forge/wrapper/EnergyTileWrapper.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.forge.wrapper; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.nbt.CompoundTag; 5 | import net.minecraft.world.level.block.entity.BlockEntity; 6 | import net.minecraftforge.energy.IEnergyStorage; 7 | import tesseract.TesseractConfig; 8 | import tesseract.api.Transaction; 9 | import tesseract.api.gt.GTConsumer; 10 | import tesseract.api.gt.GTTransaction; 11 | import tesseract.api.gt.IEnergyHandler; 12 | 13 | public class EnergyTileWrapper implements IEnergyHandler { 14 | 15 | private final BlockEntity tile; 16 | private final IEnergyStorage storage; 17 | 18 | private final GTConsumer.State state = new GTConsumer.State(this); 19 | 20 | public EnergyTileWrapper(BlockEntity tile, IEnergyStorage storage) { 21 | this.tile = tile; 22 | this.storage = storage; 23 | } 24 | 25 | @Override 26 | public long insertEu(long voltage, boolean simulate) { 27 | return (long) (storage.receiveEnergy((int) (voltage * TesseractConfig.EU_TO_FE_RATIO.get()), simulate) / TesseractConfig.EU_TO_FE_RATIO.get()); 28 | 29 | } 30 | 31 | @Override 32 | public long extractEu(long voltage, boolean simulate) { 33 | return (long) (storage.extractEnergy((int) (voltage * TesseractConfig.EU_TO_FE_RATIO.get()), simulate) / TesseractConfig.EU_TO_FE_RATIO.get()); 34 | } 35 | 36 | @Override 37 | public long getEnergy() { 38 | return (long) (storage.getEnergyStored() / TesseractConfig.EU_TO_FE_RATIO.get()); 39 | } 40 | 41 | @Override 42 | public long getCapacity() { 43 | return (long) (storage.getMaxEnergyStored() / TesseractConfig.EU_TO_FE_RATIO.get()); 44 | } 45 | 46 | @Override 47 | public long availableAmpsInput(long voltage) { 48 | if (!canInput()) return 0; 49 | int inserted = storage.receiveEnergy((int) (voltage * TesseractConfig.EU_TO_FE_RATIO.get()), false); 50 | return inserted == voltage ? 1 : 0; 51 | } 52 | 53 | @Override 54 | public long getOutputAmperage() { 55 | return 1; 56 | } 57 | 58 | @Override 59 | public long getOutputVoltage() { 60 | return 32; 61 | } 62 | 63 | @Override 64 | public long getInputAmperage() { 65 | return 16; 66 | } 67 | 68 | @Override 69 | public long getInputVoltage() { 70 | return 32; 71 | } 72 | 73 | @Override 74 | public boolean canOutput() { 75 | return TesseractConfig.ENABLE_FE_OR_TRE_INPUT.get() && storage.canExtract(); 76 | } 77 | 78 | @Override 79 | public boolean canInput() { 80 | return storage.canReceive(); 81 | } 82 | 83 | @Override 84 | public boolean canInput(Direction dir) { 85 | return canInput(); 86 | } 87 | 88 | @Override 89 | public boolean canOutput(Direction direction) { 90 | return canOutput(); 91 | } 92 | 93 | @Override 94 | public GTConsumer.State getState() { 95 | return state; 96 | } 97 | 98 | @Override 99 | public void tesseractTick() { 100 | getState().onTick(); 101 | } 102 | 103 | @Override 104 | public CompoundTag serialize(CompoundTag tag) { 105 | return null; 106 | } 107 | 108 | @Override 109 | public void deserialize(CompoundTag arg) { 110 | 111 | } 112 | } -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/api/forge/wrapper/ExtendedContainerWrapper.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.forge.wrapper; 2 | 3 | import net.minecraft.world.Container; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraftforge.items.wrapper.InvWrapper; 6 | import org.jetbrains.annotations.NotNull; 7 | import tesseract.api.item.ExtendedItemContainer; 8 | 9 | public class ExtendedContainerWrapper extends InvWrapper { 10 | public ExtendedContainerWrapper(ExtendedItemContainer inv) { 11 | super(inv); 12 | } 13 | 14 | @NotNull 15 | @Override 16 | public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { 17 | return ((ExtendedItemContainer)getInv()).insertItem(slot, stack, simulate); 18 | } 19 | 20 | @NotNull 21 | @Override 22 | public ItemStack extractItem(int slot, int amount, boolean simulate) { 23 | return ((ExtendedItemContainer)getInv()).extractItem(slot, amount, simulate); 24 | } 25 | 26 | @Override 27 | public int getSlotLimit(int slot) { 28 | return ((ExtendedItemContainer)getInv()).getSlotLimit(slot); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/api/forge/wrapper/ForgePlatformItemHandler.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.forge.wrapper; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | import net.minecraftforge.items.IItemHandler; 5 | import net.minecraftforge.items.IItemHandlerModifiable; 6 | import org.jetbrains.annotations.NotNull; 7 | import tesseract.api.item.PlatformItemHandler; 8 | 9 | public record ForgePlatformItemHandler(IItemHandler handler) implements PlatformItemHandler { 10 | @Override 11 | public int getSlots() { 12 | return handler.getSlots(); 13 | } 14 | 15 | @Override 16 | public void setStackInSlot(int slot, @NotNull ItemStack stack) { 17 | if (handler instanceof IItemHandlerModifiable modifiable) modifiable.setStackInSlot(slot, stack); 18 | } 19 | 20 | @Override 21 | public @NotNull ItemStack getStackInSlot(int slot) { 22 | return handler.getStackInSlot(slot); 23 | } 24 | 25 | @Override 26 | public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { 27 | return handler.insertItem(slot, stack, simulate); 28 | } 29 | 30 | @Override 31 | public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { 32 | return handler.extractItem(slot, amount, simulate); 33 | } 34 | 35 | @Override 36 | public int getSlotLimit(int slot) { 37 | return handler.getSlotLimit(slot); 38 | } 39 | 40 | @Override 41 | public boolean isItemValid(int slot, @NotNull ItemStack stack) { 42 | return handler.isItemValid(slot, stack); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/api/forge/wrapper/IEnergyHandlerStorage.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.forge.wrapper; 2 | 3 | import net.minecraftforge.energy.IEnergyStorage; 4 | import tesseract.TesseractConfig; 5 | import tesseract.api.gt.GTTransaction; 6 | import tesseract.api.gt.IEnergyHandler; 7 | 8 | public interface IEnergyHandlerStorage extends IEnergyStorage { 9 | /** 10 | * Forge IEnergyStorage Implementations 11 | **/ 12 | @Override 13 | default int receiveEnergy(int maxReceive, boolean simulate) { 14 | long euToInsert = (long) (maxReceive / TesseractConfig.EU_TO_FE_RATIO.get()); 15 | long inserted = getEnergyHandler().insertEu(euToInsert, simulate); 16 | return (int) (inserted * TesseractConfig.EU_TO_FE_RATIO.get()); 17 | } 18 | 19 | @Override 20 | default int extractEnergy(int maxExtract, boolean simulate) { 21 | long euToInsert = (long) (maxExtract / TesseractConfig.EU_TO_FE_RATIO.get()); 22 | return Math.toIntExact(getEnergyHandler().extractEu(euToInsert, simulate)); 23 | } 24 | 25 | @Override 26 | default int getEnergyStored() { 27 | long energy = (long) (getEnergyHandler().getEnergy() * TesseractConfig.EU_TO_FE_RATIO.get()); 28 | return energy > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) energy; 29 | } 30 | 31 | @Override 32 | default int getMaxEnergyStored() { 33 | long capacity = (long) (getEnergyHandler().getCapacity() * TesseractConfig.EU_TO_FE_RATIO.get()); 34 | return capacity > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) capacity; 35 | } 36 | 37 | @Override 38 | default boolean canReceive() { 39 | return TesseractConfig.ENABLE_FE_OR_TRE_INPUT.get() && getEnergyHandler().canInput(); 40 | } 41 | 42 | @Override 43 | default boolean canExtract() { 44 | return getEnergyHandler().canOutput(); 45 | } 46 | 47 | IEnergyHandler getEnergyHandler(); 48 | } 49 | -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/api/forge/wrapper/ItemHandlerWrapper.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.forge.wrapper; 2 | 3 | import net.minecraft.core.Direction; 4 | import net.minecraft.nbt.CompoundTag; 5 | import net.minecraft.world.entity.player.Player; 6 | import net.minecraft.world.item.ItemStack; 7 | import net.minecraft.world.level.block.entity.BlockEntity; 8 | import net.minecraftforge.items.IItemHandler; 9 | import net.minecraftforge.items.IItemHandlerModifiable; 10 | import org.jetbrains.annotations.NotNull; 11 | import tesseract.api.item.IItemNode; 12 | 13 | public record ItemHandlerWrapper(IItemHandler handler) implements IItemNode { 14 | 15 | @Override 16 | public int getPriority(Direction direction) { 17 | return 0; 18 | } 19 | 20 | @Override 21 | public boolean isEmpty(int slot) { 22 | return handler.getStackInSlot(slot).isEmpty(); 23 | } 24 | 25 | @Override 26 | public boolean canOutput() { 27 | return handler != null; 28 | } 29 | 30 | @Override 31 | public boolean canInput() { 32 | return handler != null; 33 | } 34 | 35 | @Override 36 | public boolean canInput(Direction direction) { 37 | return handler != null; 38 | } 39 | 40 | @Override 41 | public boolean canOutput(Direction direction) { 42 | return handler != null; 43 | } 44 | 45 | @Override 46 | public int getContainerSize() { 47 | return handler.getSlots(); 48 | } 49 | 50 | @NotNull 51 | @Override 52 | public ItemStack getItem(int slot) { 53 | return handler.getStackInSlot(slot); 54 | } 55 | 56 | @Override 57 | public void setItem(int index, ItemStack stack) { 58 | if (handler instanceof IItemHandlerModifiable modifiable) modifiable.setStackInSlot(index, stack); 59 | } 60 | 61 | @NotNull 62 | @Override 63 | public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { 64 | return handler.insertItem(slot, stack, simulate); 65 | } 66 | 67 | @NotNull 68 | @Override 69 | public ItemStack extractItem(int slot, int amount, boolean simulate) { 70 | return handler.extractItem(slot, amount, simulate); 71 | } 72 | 73 | @Override 74 | public int getSlotLimit(int slot) { 75 | return handler.getSlotLimit(slot); 76 | } 77 | 78 | @Override 79 | public boolean canPlaceItem(int slot, @NotNull ItemStack stack) { 80 | return handler.isItemValid(slot, stack); 81 | } 82 | 83 | @Override 84 | public void deserialize(CompoundTag nbt) { 85 | 86 | } 87 | 88 | @Override 89 | public CompoundTag serialize(CompoundTag nbt) { 90 | return null; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/api/forge/wrapper/RFWrapper.java: -------------------------------------------------------------------------------- 1 | package tesseract.api.forge.wrapper; 2 | 3 | import earth.terrarium.botarium.common.energy.base.EnergySnapshot; 4 | import net.minecraft.core.Direction; 5 | import net.minecraft.nbt.CompoundTag; 6 | import net.minecraftforge.energy.IEnergyStorage; 7 | import tesseract.api.rf.IRFNode; 8 | 9 | public record RFWrapper(IEnergyStorage storage) implements IRFNode { 10 | 11 | @Override 12 | public long insertEnergy(long maxAmount, boolean simulate) { 13 | return storage.receiveEnergy((int) maxAmount, simulate); 14 | } 15 | 16 | @Override 17 | public long extractEnergy(long maxAmount, boolean simulate) { 18 | return storage.extractEnergy((int) maxAmount, simulate); 19 | } 20 | 21 | @Override 22 | public void setEnergy(long energy) { 23 | storage.extractEnergy(storage.getEnergyStored(), false); 24 | storage.receiveEnergy((int) energy, false); 25 | } 26 | 27 | @Override 28 | public long getStoredEnergy() { 29 | return storage.getEnergyStored(); 30 | } 31 | 32 | @Override 33 | public long getMaxCapacity() { 34 | return storage.getMaxEnergyStored(); 35 | } 36 | 37 | @Override 38 | public long maxInsert() { 39 | return Integer.MAX_VALUE; 40 | } 41 | 42 | @Override 43 | public long maxExtract() { 44 | return Integer.MAX_VALUE; 45 | } 46 | 47 | @Override 48 | public boolean allowsInsertion() { 49 | return storage.canReceive(); 50 | } 51 | 52 | @Override 53 | public boolean allowsExtraction() { 54 | return storage.canExtract(); 55 | } 56 | 57 | @Override 58 | public EnergySnapshot createSnapshot() { 59 | return null; 60 | } 61 | 62 | @Override 63 | public void deserialize(CompoundTag nbt) { 64 | 65 | } 66 | 67 | @Override 68 | public CompoundTag serialize(CompoundTag nbt) { 69 | return null; 70 | } 71 | 72 | @Override 73 | public boolean canInput(Direction direction) { 74 | return allowsInsertion(); 75 | } 76 | 77 | @Override 78 | public boolean canOutput(Direction direction) { 79 | return allowsExtraction(); 80 | } 81 | 82 | @Override 83 | public void clearContent() { 84 | storage.extractEnergy(storage.getEnergyStored(), false); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/forge/FluidPlatformUtilsImpl.java: -------------------------------------------------------------------------------- 1 | package tesseract.forge; 2 | 3 | import earth.terrarium.botarium.common.fluid.base.FluidHolder; 4 | import earth.terrarium.botarium.forge.fluid.ForgeFluidHolder; 5 | import net.minecraft.network.chat.Component; 6 | import net.minecraft.resources.ResourceLocation; 7 | import net.minecraft.sounds.SoundEvent; 8 | import net.minecraft.world.level.material.Fluid; 9 | import tesseract.FluidPlatformUtils; 10 | 11 | public class FluidPlatformUtilsImpl extends FluidPlatformUtils { 12 | 13 | public ResourceLocation getStillTexture(Fluid fluid){ 14 | return fluid.getAttributes().getStillTexture(); 15 | } 16 | 17 | public ResourceLocation getFlowingTexture(Fluid fluid){ 18 | return fluid.getAttributes().getFlowingTexture(); 19 | } 20 | public ResourceLocation getFluidId(Fluid fluid){ 21 | return fluid.getRegistryName(); 22 | } 23 | 24 | public int getFluidTemperature(Fluid fluid){ 25 | return fluid.getAttributes().getTemperature(); 26 | } 27 | 28 | public int getFluidDensity(Fluid fluid){ 29 | return fluid.getAttributes().getDensity(); 30 | } 31 | 32 | public boolean isFluidGaseous(Fluid fluid){ 33 | return fluid.getAttributes().isGaseous(); 34 | } 35 | 36 | public int getFluidColor(Fluid fluid){ 37 | return fluid.getAttributes().getColor(); 38 | } 39 | 40 | public SoundEvent getFluidSound(Fluid fluid, boolean fill){ 41 | return fill ? fluid.getAttributes().getFillSound() : fluid.getAttributes().getEmptySound(); 42 | } 43 | 44 | public Component getFluidDisplayName(FluidHolder fluid){ 45 | return fluid.getFluid().getAttributes().getDisplayName(ForgeFluidHolder.toStack(fluid)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/forge/TesseractImpl.java: -------------------------------------------------------------------------------- 1 | package tesseract.forge; 2 | 3 | import carbonconfiglib.CarbonConfig; 4 | import carbonconfiglib.config.Config; 5 | import carbonconfiglib.config.ConfigHandler; 6 | import net.minecraft.resources.ResourceLocation; 7 | import net.minecraft.world.item.ItemStack; 8 | import net.minecraft.world.level.Level; 9 | import net.minecraftforge.common.MinecraftForge; 10 | import net.minecraftforge.event.AttachCapabilitiesEvent; 11 | import net.minecraftforge.event.TickEvent; 12 | import net.minecraftforge.event.server.ServerStoppedEvent; 13 | import net.minecraftforge.event.world.WorldEvent; 14 | import net.minecraftforge.fml.common.Mod; 15 | import tesseract.FluidPlatformUtils; 16 | import tesseract.Tesseract; 17 | import tesseract.api.GraphWrapper; 18 | import tesseract.api.context.TesseractItemContext; 19 | import tesseract.api.forge.Provider; 20 | import tesseract.api.forge.TesseractCaps; 21 | import tesseract.api.wrapper.ItemStackWrapper; 22 | import tesseract.api.gt.GTTransaction; 23 | import tesseract.api.gt.IEnergyItem; 24 | import tesseract.api.gt.IGTCable; 25 | import tesseract.api.gt.IGTNode; 26 | import tesseract.controller.Energy; 27 | 28 | @Mod(Tesseract.API_ID) 29 | public class TesseractImpl extends Tesseract { 30 | //public static GraphWrapper FE_ENERGY = new GraphWrapper<>(FEController::new); 31 | public static GraphWrapper GT_ENERGY = new GraphWrapper<>(Energy::new, IGTNode.GT_GETTER); 32 | 33 | public TesseractImpl() { 34 | FluidPlatformUtils.INSTANCE = new FluidPlatformUtilsImpl(); 35 | Tesseract.init(); 36 | MinecraftForge.EVENT_BUS.addListener(this::serverStoppedEvent); 37 | MinecraftForge.EVENT_BUS.addListener(this::worldUnloadEvent); 38 | MinecraftForge.EVENT_BUS.addListener(this::onServerTick); 39 | MinecraftForge.EVENT_BUS.addGenericListener(ItemStack.class, this::onAttachCapabilitiesEventItemStack); 40 | } 41 | 42 | public void onAttachCapabilitiesEventItemStack(AttachCapabilitiesEvent event){ 43 | if (event.getObject().getItem() instanceof IEnergyItem energyItem){ 44 | TesseractItemContext context = new ItemStackWrapper(event.getObject()); 45 | event.addCapability(new ResourceLocation(Tesseract.API_ID, "energy_items"), new Provider<>(TesseractCaps.ENERGY_HANDLER_CAPABILITY_ITEM, energyItem.canCreate(context) ? () -> energyItem.createEnergyHandler(context) : null)); 46 | } 47 | } 48 | 49 | public static GraphWrapper getGT_ENERGY(){ 50 | return GT_ENERGY; 51 | } 52 | 53 | public void serverStoppedEvent(ServerStoppedEvent e) { 54 | firstTick.clear(); 55 | //FE_ENERGY.clear(); 56 | GraphWrapper.getWrappers().forEach(GraphWrapper::clear); 57 | } 58 | 59 | public void worldUnloadEvent(WorldEvent.Unload e) { 60 | if (!(e.getWorld() instanceof Level) || ((Level) e.getWorld()).isClientSide) return; 61 | //FE_ENERGY.removeWorld((World) e.getWorld()); 62 | GraphWrapper.getWrappers().forEach(g -> g.removeWorld((Level)e.getWorld())); 63 | firstTick.remove(e.getWorld()); 64 | } 65 | 66 | public void onServerTick(TickEvent.WorldTickEvent event) { 67 | if (event.side.isClient()) return; 68 | Level dim = event.world; 69 | if (!hadFirstTick(dim)) { 70 | firstTick.add(event.world); 71 | GraphWrapper.getWrappers().forEach(t -> t.onFirstTick(dim)); 72 | } 73 | if (event.phase == TickEvent.Phase.START) { 74 | GraphWrapper.getWrappers().forEach(t -> t.tick(dim)); 75 | } 76 | if (Tesseract.HEALTH_CHECK_TIME > 0 && event.world.getGameTime() % Tesseract.HEALTH_CHECK_TIME == 0) { 77 | GraphWrapper.getWrappers().forEach(GraphWrapper::healthCheck); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/forge/TesseractPlatformUtilsImpl.java: -------------------------------------------------------------------------------- 1 | package tesseract.forge; 2 | 3 | import carbonconfiglib.CarbonConfig; 4 | import carbonconfiglib.config.Config; 5 | import carbonconfiglib.config.ConfigHandler; 6 | import earth.terrarium.botarium.common.energy.base.EnergyContainer; 7 | import earth.terrarium.botarium.forge.energy.ForgeEnergyContainer; 8 | import net.minecraft.core.BlockPos; 9 | import net.minecraft.core.Direction; 10 | import net.minecraft.world.item.ItemStack; 11 | import net.minecraft.world.level.Level; 12 | import net.minecraft.world.level.block.entity.BlockEntity; 13 | import net.minecraftforge.common.util.LazyOptional; 14 | import net.minecraftforge.energy.CapabilityEnergy; 15 | import net.minecraftforge.energy.IEnergyStorage; 16 | import tesseract.TesseractCapUtils; 17 | import tesseract.TesseractPlatformUtils; 18 | import tesseract.api.forge.TesseractCaps; 19 | import tesseract.api.forge.wrapper.RFWrapper; 20 | import tesseract.api.gt.IEnergyHandler; 21 | import tesseract.api.gt.IGTNode; 22 | import tesseract.api.heat.IHeatHandler; 23 | import tesseract.api.heat.IHeatNode; 24 | import tesseract.api.rf.IRFNode; 25 | 26 | import java.util.Optional; 27 | 28 | public class TesseractPlatformUtilsImpl implements TesseractPlatformUtils { 29 | @Override 30 | public IGTNode getGTNode(Level level, long pos, Direction direction, Runnable invalidate){ 31 | BlockEntity tile = level.getBlockEntity(BlockPos.of(pos)); 32 | LazyOptional capability = TesseractCapUtils.INSTANCE.getEnergyHandler(tile, direction).map(e -> LazyOptional.of(() -> e)).orElse(LazyOptional.empty()); 33 | if (capability.isPresent()) { 34 | if (invalidate != null )capability.addListener(o -> invalidate.run()); 35 | return capability.resolve().get(); 36 | } 37 | return null; 38 | } 39 | 40 | @Override 41 | public IRFNode getRFNode(Level level, long pos, Direction capSide, Runnable capCallback){ 42 | BlockEntity tile = level.getBlockEntity(BlockPos.of(pos)); 43 | if (tile == null) { 44 | return null; 45 | } 46 | LazyOptional capability = tile.getCapability(CapabilityEnergy.ENERGY, capSide); 47 | if (capability.isPresent()) { 48 | if (capCallback != null) capability.addListener(o -> capCallback.run()); 49 | IEnergyStorage handler = capability.map(f -> f).orElse(null); 50 | if (handler instanceof ForgeEnergyContainer container){ 51 | EnergyContainer container1 = container.container().getContainer(capSide); 52 | if (container1 instanceof IRFNode node) return node; 53 | } 54 | return handler instanceof IRFNode node ? node : new RFWrapper(handler); 55 | } else { 56 | return null; 57 | } 58 | } 59 | 60 | @Override 61 | public IHeatNode getHeatNode(Level level, long pos, Direction direction, Runnable invalidate){ 62 | BlockEntity tile = level.getBlockEntity(BlockPos.of(pos)); 63 | if (tile == null) return null; 64 | LazyOptional capability = tile.getCapability(TesseractCaps.HEAT_CAPABILITY, direction); 65 | if (capability.isPresent()) { 66 | if (invalidate != null) capability.addListener(t -> invalidate.run()); 67 | return capability.resolve().get(); 68 | } 69 | return null; 70 | } 71 | 72 | @Override 73 | public boolean isFeCap(Class cap){ 74 | return cap == IEnergyStorage.class; 75 | } 76 | 77 | @Override 78 | public boolean isForge(){ 79 | return true; 80 | } 81 | 82 | @Override 83 | public ConfigHandler createConfig(Config config){ 84 | return CarbonConfig.CONFIGS.createConfig(config); 85 | } 86 | 87 | @Override 88 | public boolean areCapsCompatible(ItemStack a, ItemStack b){ 89 | return a.areCapsCompatible(b); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /forge/src/main/java/tesseract/mixin/forge/IEnergyHandlerMixin.java: -------------------------------------------------------------------------------- 1 | package tesseract.mixin.forge; 2 | 3 | import org.spongepowered.asm.mixin.Mixin; 4 | import tesseract.api.forge.wrapper.IEnergyHandlerStorage; 5 | import tesseract.api.gt.IEnergyHandler; 6 | 7 | @Mixin(value = IEnergyHandler.class, remap = false) 8 | public interface IEnergyHandlerMixin extends IEnergyHandlerStorage { 9 | @Override 10 | default IEnergyHandler getEnergyHandler(){ 11 | return (IEnergyHandler) this; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/mods.toml: -------------------------------------------------------------------------------- 1 | modLoader="javafml" 2 | loaderVersion="[39,)" 3 | issueTrackerURL="https://github.com/GregTech-Intergalactical/TesseractAPI/issues" 4 | license="LGPL-v3" 5 | 6 | [[mods]] 7 | modId="tesseractapi" 8 | version="${version}" 9 | displayName="TesseractAPI" 10 | #updateJSONURL="http://myurl.me/" 11 | displayURL="https://github.com/GregTech-Intergalactical/TesseractAPI" 12 | #logoFile="icon.png" 13 | authors="coderbot16, qubka, repolainen, mitchej123, Muramasa, abbe, Trinsdar" 14 | credits="Rongmario - cheerleading from the side" 15 | description='''Powerful framework for energy, item, and fluid transport''' 16 | [custom.mc-publish] 17 | curseforge=462718 18 | [[dependencies.tesseractapi]] 19 | modId="forge" 20 | mandatory=true 21 | versionRange="[40.2.3,)" 22 | ordering="NONE" 23 | side="BOTH" 24 | [[dependencies.tesseractapi]] 25 | modId="minecraft" 26 | mandatory=true 27 | versionRange="[1.18.2,]" 28 | ordering="NONE" 29 | side="BOTH" -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/services/tesseract.TesseractCapUtils: -------------------------------------------------------------------------------- 1 | tesseract.forge.TesseractCapUtilsImpl -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/services/tesseract.TesseractPlatformUtils: -------------------------------------------------------------------------------- 1 | tesseract.forge.TesseractPlatformUtilsImpl -------------------------------------------------------------------------------- /forge/src/main/resources/tesseract-forge.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "package": "tesseract.mixin.forge", 4 | "compatibilityLevel": "JAVA_17", 5 | "mixins": [ 6 | "IEnergyHandlerMixin" 7 | ], 8 | "minVersion": "0.8", 9 | "refmap" : "tesseract.refmap.json" 10 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Sets default memory used for gradle commands. Can be overridden by user or command line properties. 2 | # This is required to provide enough memory for the Minecraft decompilation process. 3 | org.gradle.jvmargs=-Xmx3G 4 | org.gradle.daemon=false 5 | org.gradle.parallel=true 6 | 7 | mod_version=0.1 8 | mod_id=tesseractapi 9 | 10 | mappings_version=2022.03.13 11 | minecraft_version=1.18.2 12 | forge_version=40.2.4 13 | 14 | fabric_api_version=0.76.0+1.18.2 15 | fabric_transfer_api_version=1.6.+ 16 | fabric_loader_version=0.14.6 17 | parchment_version=2021.12.19 18 | 19 | energy_version=2.3.0 20 | nightconfig_version=3.6.5 21 | rei_version=7.0.346 22 | botarium_version=2.0.5 23 | carbon_config_fabric_version=ec9yfAHJ 24 | carbon_config_forge_version=L3ipBBnb 25 | 26 | maven_group=org.gt-reimagined 27 | tesseract_archive_base_name=TesseractAPI 28 | 29 | 30 | modid=TesseractAPI 31 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregTech-Intergalactical/TesseractAPI/5a162d42f3cb6761dd6ebf05aea7374965d467eb/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - sdk install java 17.0.1-open 3 | - sdk use java 17.0.1-open 4 | jdk: 5 | - openjdk17 -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { url "https://maven.fabricmc.net/" } 4 | maven { 5 | name = 'parchment' 6 | url = 'https://maven.parchmentmc.org' 7 | } 8 | maven { 9 | name = 'Sponge Snapshots' 10 | url = 'https://repo.spongepowered.org/repository/maven-public/' 11 | } 12 | maven { url('https://maven.minecraftforge.net')} 13 | maven { url "https://maven.neoforged.net/" } 14 | maven { 15 | url = "https://maven.wagyourtail.xyz/releases" 16 | } 17 | maven { 18 | url = "https://maven.wagyourtail.xyz/snapshots" 19 | } 20 | gradlePluginPortal() 21 | } 22 | } 23 | 24 | include("tesseract-common") 25 | include("tesseract-fabric") 26 | include("tesseract-forge") 27 | 28 | project(':tesseract-common').setProjectDir(new File("common")) 29 | project(':tesseract-forge').setProjectDir(new File("forge")) 30 | project(':tesseract-fabric').setProjectDir(new File("fabric")) 31 | 32 | rootProject.name = "${modid}" 33 | 34 | -------------------------------------------------------------------------------- /version/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.ajoberstar.grgit' version '3.0.0' 3 | } 4 | 5 | def loadProperties(String filename) { 6 | def properties = new Properties() 7 | def file = new File(project.projectDir, filename); 8 | if (file.exists()) { 9 | properties.load(new FileReader(file)) 10 | } 11 | return properties 12 | } 13 | 14 | def storeProperties(Properties properties, String filename, String comment) { 15 | def file = new File(project.projectDir, filename); 16 | if (!file.exists()) { 17 | file.createNewFile() 18 | } 19 | properties.store(new FileWriter(file), comment) 20 | } 21 | 22 | def getVersionAppendage() { 23 | if (System.env.VERSION_APPENDICE) { 24 | return System.env.VERSION_APPENDICE 25 | } 26 | 27 | if (System.env.TRAVIS) { 28 | return "." + System.env.TRAVIS_BUILD_NUMBER 29 | } 30 | 31 | if (useGitRef && grgit) { 32 | return "-" + grgit.head().abbreviatedId 33 | } 34 | 35 | return '-unknown' 36 | } 37 | 38 | def getVersion() { 39 | def versionProperties = loadProperties(versionFile) 40 | def major = versionProperties.getProperty('version.major', '0') 41 | def minor = versionProperties.getProperty('version.minor', '0') 42 | def revision = versionProperties.getProperty('version.revision', '0') 43 | 44 | return major + '.' + minor + '.' + revision// + getVersionAppendage() 45 | } 46 | 47 | def printVersion() { 48 | println("****************************************") 49 | printf("* Current version: %-19s *%n", rootProject.version) 50 | println("****************************************") 51 | } 52 | 53 | task bumpMajor { 54 | doLast { 55 | def versionProperties = loadProperties(versionFile) 56 | def major = Integer.parseInt(versionProperties.getProperty('version.major', '0')) 57 | versionProperties.setProperty('version.major', Integer.toString(major + 1)) 58 | versionProperties.setProperty('version.minor', '0') 59 | versionProperties.setProperty('version.revision', '0') 60 | storeProperties(versionProperties, versionFile, 'Version file') 61 | } 62 | } 63 | 64 | task bumpMinor { 65 | doLast { 66 | def versionProperties = loadProperties(versionFile) 67 | def major = Integer.parseInt(versionProperties.getProperty('version.minor', '0')) 68 | versionProperties.setProperty('version.minor', Integer.toString(major + 1)) 69 | versionProperties.setProperty('version.revision', '0') 70 | storeProperties(versionProperties, versionFile, 'Version file') 71 | } 72 | } 73 | 74 | task bumpRevision { 75 | doLast { 76 | def versionProperties = loadProperties(versionFile) 77 | def major = Integer.parseInt(versionProperties.getProperty('version.revision', '0')) 78 | versionProperties.setProperty('version.revision', Integer.toString(major + 1)) 79 | storeProperties(versionProperties, versionFile, 'Version file') 80 | } 81 | } 82 | 83 | version = getVersion() 84 | rootProject.version = version 85 | 86 | printVersion() 87 | -------------------------------------------------------------------------------- /version/gradle.properties: -------------------------------------------------------------------------------- 1 | versionFile=version.properties 2 | useGitRef=true -------------------------------------------------------------------------------- /version/version.properties: -------------------------------------------------------------------------------- 1 | #Version file 2 | #Thu Aug 20 21:15:01 CEST 2020 3 | version.revision=1 4 | version.minor=0 5 | version.major=0 6 | --------------------------------------------------------------------------------