diff --git a/core-api/src/main/java/dev/compactmods/machines/api/room/CompactRoomGenerator.java b/core-api/src/main/java/dev/compactmods/machines/api/room/CompactRoomGenerator.java index d389a1cf..c86a4ef3 100644 --- a/core-api/src/main/java/dev/compactmods/machines/api/room/CompactRoomGenerator.java +++ b/core-api/src/main/java/dev/compactmods/machines/api/room/CompactRoomGenerator.java @@ -1,113 +1,114 @@ -package dev.compactmods.machines.api.room; - -import dev.compactmods.machines.api.WallConstants; -import dev.compactmods.machines.api.room.spatial.IRoomBoundaries; -import dev.compactmods.machines.api.util.AABBAligner; -import dev.compactmods.machines.api.util.AABBHelper; -import dev.compactmods.machines.api.util.BlockSpaceUtil; -import dev.compactmods.machines.api.util.VectorUtils; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Vec3i; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import org.joml.Vector3d; - -public class CompactRoomGenerator { - - /** - * Generates a wall or platform in a given direction. - * Uses the solid wall block. - * - * @param world - * @param outerBounds - * @param wallDirection - * @since 3.0.0 - */ - public static void generateCompactWall(LevelAccessor world, AABB outerBounds, Direction wallDirection, BlockState block) { - AABB wallBounds = BlockSpaceUtil.getWallBounds(outerBounds, wallDirection); - BlockSpaceUtil.blocksInside(wallBounds).forEach(wallBlock -> { - world.setBlock(wallBlock, block, Block.UPDATE_ALL); - }); - } - - /** - * Generates a machine "internal" structure in a world via a machine size and a central point. - * - * @param world - * @param outerBounds Outer dimensions of the room. - */ - public static void generateRoom(LevelAccessor world, AABB outerBounds) { - final var block = BuiltInRegistries.BLOCK.get(WallConstants.SOLID_WALL); - if (block != null) { - final var solidWall = block.defaultBlockState(); - generateRoom(world, outerBounds, solidWall); - } - } - - /** - * Generates a machine structure in a world via machine boundaries and a wall block. - * - * @param world - * @param outerBounds Outer dimensions of the room. - * @param block Block to use for walls. - */ - public static void generateRoom(LevelAccessor world, AABB outerBounds, BlockState block) { - - // Generate the walls - for (final var dir : Direction.values()) - generateCompactWall(world, outerBounds, dir, block); - - // Clear out the inside of the room - AABB machineInternal = outerBounds.deflate(1); - BlockSpaceUtil.blocksInside(machineInternal) - .forEach(p -> world.setBlock(p, Blocks.AIR.defaultBlockState(), 7)); - } - - public static void populateStructure(ServerLevel level, ResourceLocation template, AABB roomInnerBounds, RoomStructureInfo.RoomStructurePlacement placement) { - level.getStructureManager().get(template).ifPresent(tem -> { - - Vector3d templateSize = VectorUtils.convert3d(tem.getSize()); - - if (!AABBHelper.fitsInside(roomInnerBounds, templateSize)) { - // skip: structure too large to place in room - return; - } - - var placementSettings = new StructurePlaceSettings() - .setRotation(Rotation.NONE) - .setMirror(Mirror.NONE); - - AABB placementBounds = null; - final AABBAligner aligner = AABBAligner.create(roomInnerBounds, templateSize); - switch (placement) { - case CENTERED -> placementBounds = aligner - .center(roomInnerBounds.getCenter()) - .align(); - - case CENTERED_CEILING -> placementBounds = aligner - .boundedDirection(Direction.UP) - .align(); - - case CENTERED_FLOOR -> placementBounds = aligner - .boundedDirection(Direction.DOWN) - .align(); - } - - if(placementBounds != null) { - BlockPos placeAt = BlockPos.containing(AABBHelper.minCorner(placementBounds)); - tem.placeInWorld(level, placeAt, placeAt, placementSettings, level.random, Block.UPDATE_ALL); - } - }); - } -} +package dev.compactmods.machines.api.room; + +import dev.compactmods.machines.api.WallConstants; +import dev.compactmods.machines.api.room.spatial.IRoomBoundaries; +import dev.compactmods.machines.api.util.AABBAligner; +import dev.compactmods.machines.api.util.AABBHelper; +import dev.compactmods.machines.api.util.BlockSpaceUtil; +import dev.compactmods.machines.api.util.VectorUtils; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Vec3i; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; + +public class CompactRoomGenerator { + + /** + * Generates a wall or platform in a given direction. + * Uses the solid wall block. + * + * @param world + * @param outerBounds + * @param wallDirection + * @since 3.0.0 + */ + public static void generateCompactWall(LevelAccessor world, AABB outerBounds, Direction wallDirection, BlockState block) { + AABB wallBounds = BlockSpaceUtil.getWallBounds(outerBounds, wallDirection); + BlockSpaceUtil.blocksInside(wallBounds).forEach(wallBlock -> { + world.setBlock(wallBlock, block, Block.UPDATE_ALL); + }); + } + + /** + * Generates a machine "internal" structure in a world via a machine size and a central point. + * + * @param world + * @param outerBounds Outer dimensions of the room. + */ + public static void generateRoom(LevelAccessor world, AABB outerBounds) { + final var block = BuiltInRegistries.BLOCK.get(WallConstants.SOLID_WALL); + if (block != null) { + final var solidWall = block.defaultBlockState(); + generateRoom(world, outerBounds, solidWall); + } + } + + /** + * Generates a machine structure in a world via machine boundaries and a wall block. + * + * @param world + * @param outerBounds Outer dimensions of the room. + * @param block Block to use for walls. + */ + public static void generateRoom(LevelAccessor world, AABB outerBounds, BlockState block) { + + // Generate the walls + for (final var dir : Direction.values()) + generateCompactWall(world, outerBounds, dir, block); + + // Clear out the inside of the room + AABB machineInternal = outerBounds.deflate(1); + BlockSpaceUtil.blocksInside(machineInternal) + .forEach(p -> world.setBlock(p, Blocks.AIR.defaultBlockState(), 7)); + } + + public static void populateStructure(ServerLevel level, ResourceLocation template, AABB roomInnerBounds, RoomStructureInfo.RoomStructurePlacement placement) { + level.getStructureManager().get(template).ifPresent(tem -> { + + Vector3d templateSize = VectorUtils.convert3d(tem.getSize()); + + if (!AABBHelper.fitsInside(roomInnerBounds, templateSize)) { + // skip: structure too large to place in room + return; + } + + var placementSettings = new StructurePlaceSettings() + .setRotation(Rotation.NONE) + .setMirror(Mirror.NONE); + + AABB placementBounds = null; + final AABBAligner aligner = AABBAligner.create(roomInnerBounds, templateSize); + switch (placement) { + case CENTERED -> placementBounds = aligner + .center(roomInnerBounds.getCenter()) + .align(); + + case CENTERED_CEILING -> placementBounds = aligner + .boundedDirection(Direction.UP) + .align(); + + case CENTERED_FLOOR -> placementBounds = aligner + .boundedDirection(Direction.DOWN) + .align(); + } + + if(placementBounds != null) { + BlockPos placeAt = BlockPos.containing(AABBHelper.minCorner(placementBounds)); + tem.placeInWorld(level, placeAt, placeAt, placementSettings, level.random, Block.UPDATE_ALL); + } + }); + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a79..e6441136 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 20db9ad5..a4413138 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index aeb74cbb..b740cf13 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -141,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -149,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -198,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f..7101f8e4 100755 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,92 +1,92 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/neoforge-main/build.gradle.kts b/neoforge-main/build.gradle.kts index 0680df63..81bdb866 100644 --- a/neoforge-main/build.gradle.kts +++ b/neoforge-main/build.gradle.kts @@ -1,262 +1,261 @@ -@file:Suppress("SpellCheckingInspection") - -import org.slf4j.event.Level -import java.text.SimpleDateFormat -import java.util.* - -var envVersion: String = System.getenv("VERSION") ?: "9.9.9" -if (envVersion.startsWith("v")) - envVersion = envVersion.trimStart('v') - -val modId: String = "compactmachines" -val isRelease: Boolean = (System.getenv("RELEASE") ?: "false").equals("true", true) - -val coreApi = project(":core-api") - -plugins { - java - id("idea") - id("eclipse") - id("maven-publish") - alias(neoforged.plugins.moddev) -} - -project.evaluationDependsOn(coreApi.path) - -base { - archivesName.set(modId) - group = "dev.compactmods.compactmachines" - version = envVersion -} - -java { - // toolchain.vendor.set(JvmVendorSpec.JETBRAINS) - toolchain.languageVersion.set(JavaLanguageVersion.of(21)) -} - -sourceSets.main { - java { - srcDir("src/main/java") - } - - resources { - srcDir("src/main/resources") - srcDir("src/generated/resources") - } -} - -sourceSets.test { - java { - srcDir("src/test/java") - } - - resources { - srcDir("src/test/resources") - } -} - -neoForge { - version = neoforged.versions.neoforge - accessTransformers.add("src/main/resources/META-INF/accesstransformer.cfg") - - this.mods.create(modId) { - modSourceSets.add(sourceSets.main) - modSourceSets.add(sourceSets.test) - this.dependency(coreApi) - } - - unitTest { - enable() - testedMod = mods.named(modId) - } - - runs { - // applies to all the run configs below - configureEach { - - logLevel.set(Level.DEBUG) - - sourceSet = project.sourceSets.main - - if (!System.getenv().containsKey("CI")) { - // JetBrains Runtime Hotswap - // jvmArgument("-XX:+AllowEnhancedClassRedefinition") - } - - additionalRuntimeClasspath.add(libraries.feather) - additionalRuntimeClasspath.add(libraries.jnanoid) - } - - create("client") { - client() - gameDirectory.set(file("runs/client")) - - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - systemProperty("forge.enabledGameTestNamespaces", modId) - - programArguments.addAll("--username", "Nano") - programArguments.addAll("--width", "1920") - programArguments.addAll("--height", "1080") - } - - create("server") { - server() - gameDirectory.set(file("runs/server")) - - systemProperty("forge.enabledGameTestNamespaces", modId) - programArgument("nogui") - - environment.put("CM_TEST_RESOURCES", file("src/test/resources").path) - - sourceSet = project.sourceSets.test - // sourceSets.add(project.sourceSets.test.get()) - } - - create("gameTestServer") { - type = "gameTestServer" - gameDirectory.set(file("runs/gametest")) - - systemProperty("forge.enabledGameTestNamespaces", modId) - environment.put("CM_TEST_RESOURCES", file("src/test/resources").path) - - sourceSet = project.sourceSets.test - // sourceSets.add(project.sourceSets.test.get()) - } - } -} - -repositories { - mavenLocal() - mavenCentral { - name = "Central" - content { - includeGroup("com.aventrix.jnanoid") - } - } - - maven("https://maven.pkg.github.com/compactmods/compactmachines-core") { - name = "Github PKG Core" - credentials { - username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR") - password = project.findProperty("gpr.token") as String? ?: System.getenv("GITHUB_TOKEN") - } - } - - maven("https://maven.blamejared.com/") { - // location of the maven that hosts JEI files since January 2023 - name = "Jared's maven" - } - - maven("https://www.cursemaven.com") { - content { - includeGroup("curse.maven") - } - } - - maven("https://modmaven.dev") { - // location of a maven mirror for JEI files, as a fallback - name = "ModMaven" - } -} - -dependencies { - // Core Projects and Libraries - this { - compileOnly(libraries.jnanoid) - jarJar(libraries.jnanoid) - - compileOnly(coreApi) - testCompileOnly(coreApi) - - compileOnly(libraries.feather) - jarJar(libraries.feather) { isTransitive = false } - } - - runtimeOnly(neoforged.testframework) - testImplementation(neoforged.testframework) - testImplementation("org.junit.jupiter:junit-jupiter:5.7.1") - testRuntimeOnly("org.junit.platform:junit-platform-launcher") - - // Mods -// compileOnly(mods.bundles.jei) -// compileOnly(mods.jade) -} - -tasks.withType { - useJUnitPlatform() -} - -tasks.withType { - duplicatesStrategy = DuplicatesStrategy.EXCLUDE -} - -tasks.withType { - options.encoding = "UTF-8" - options.compilerArgs.addAll(arrayOf("-Xmaxerrs", "9000")) -} - -tasks.withType { - - val gitVersion = providers.exec { - commandLine("git", "rev-parse", "HEAD") - }.standardOutput.asText.get() - - manifest { - val now = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(Date()) - attributes( - mapOf( - "Specification-Title" to "Compact Machines", - "Specification-Vendor" to "CompactMods", - "Specification-Version" to "2", - "Implementation-Title" to "Compact Machines", - "Implementation-Version" to archiveVersion, - "Implementation-Vendor" to "CompactMods", - "Implementation-Timestamp" to now, - "Minecraft-Version" to mojang.versions.minecraft.get(), - "NeoForge-Version" to neoforged.versions.neoforge.get(), - "Main-Commit" to gitVersion - ) - ) - } -} - -tasks.withType().configureEach { - var replaceProperties: Map = mapOf( - "minecraft_version" to mojang.versions.minecraft.get(), - "neo_version" to neoforged.versions.neoforge.get(), - "minecraft_version_range" to mojang.versions.minecraftRange.get(), - "neo_version_range" to neoforged.versions.neoforgeRange.get(), - "loader_version_range" to "[1,)", - "mod_id" to modId, - "mod_version" to envVersion - ) - - inputs.properties(replaceProperties) - filesMatching("META-INF/neoforge.mods.toml") { - expand(replaceProperties) - } -} - -tasks.jar { - from(sourceSets.main.get().output) - from(coreApi.sourceSets.main.get().output) -} - -val PACKAGES_URL = System.getenv("GH_PKG_URL") ?: "https://maven.pkg.github.com/compactmods/compactmachines" -publishing { - publications.register("compactmachines") { - artifactId = "$modId-neoforge" - from(components.getByName("java")) - } - - repositories { - // GitHub Packages - maven(PACKAGES_URL) { - name = "GitHubPackages" - credentials { - username = System.getenv("GITHUB_ACTOR") - password = System.getenv("GITHUB_TOKEN") - } - } - } +@file:Suppress("SpellCheckingInspection") + +import org.slf4j.event.Level +import java.text.SimpleDateFormat +import java.util.* + +var envVersion: String = System.getenv("VERSION") ?: "9.9.9" +if (envVersion.startsWith("v")) + envVersion = envVersion.trimStart('v') + +val modId: String = "compactmachines" +val isRelease: Boolean = (System.getenv("RELEASE") ?: "false").equals("true", true) + +val coreApi = project(":core-api") + +plugins { + java + id("idea") + id("eclipse") + id("maven-publish") + alias(neoforged.plugins.moddev) +} + +project.evaluationDependsOn(coreApi.path) + +base { + archivesName.set(modId) + group = "dev.compactmods.compactmachines" + version = envVersion +} + +java { + // toolchain.vendor.set(JvmVendorSpec.JETBRAINS) + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) +} + +sourceSets.main { + java { + srcDir("src/main/java") + } + + resources { + srcDir("src/main/resources") + srcDir("src/generated/resources") + } +} + +sourceSets.test { + java { + srcDir("src/test/java") + } + + resources { + srcDir("src/test/resources") + } +} + +neoForge { + version = neoforged.versions.neoforge + + this.mods.create(modId) { + modSourceSets.add(sourceSets.main) + modSourceSets.add(sourceSets.test) + this.dependency(coreApi) + } + + unitTest { + enable() + testedMod = mods.named(modId) + } + + runs { + // applies to all the run configs below + configureEach { + + logLevel.set(Level.DEBUG) + + sourceSet = project.sourceSets.main + + if (!System.getenv().containsKey("CI")) { + // JetBrains Runtime Hotswap + // jvmArgument("-XX:+AllowEnhancedClassRedefinition") + } + } + + create("client") { + client() + gameDirectory.set(file("runs/client")) + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + systemProperty("forge.enabledGameTestNamespaces", modId) + + programArguments.addAll("--username", "Nano") + programArguments.addAll("--width", "1920") + programArguments.addAll("--height", "1080") + } + + create("server") { + server() + gameDirectory.set(file("runs/server")) + + systemProperty("forge.enabledGameTestNamespaces", modId) + programArgument("nogui") + + environment.put("CM_TEST_RESOURCES", file("src/test/resources").path) + + sourceSet = project.sourceSets.test + // sourceSets.add(project.sourceSets.test.get()) + } + + create("gameTestServer") { + type = "gameTestServer" + gameDirectory.set(file("runs/gametest")) + + systemProperty("forge.enabledGameTestNamespaces", modId) + environment.put("CM_TEST_RESOURCES", file("src/test/resources").path) + + sourceSet = project.sourceSets.test + // sourceSets.add(project.sourceSets.test.get()) + } + } +} + +repositories { + mavenLocal() + mavenCentral { + name = "Central" + content { + includeGroup("com.aventrix.jnanoid") + } + } + + maven("https://maven.pkg.github.com/compactmods/compactmachines-core") { + name = "Github PKG Core" + credentials { + username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.token") as String? ?: System.getenv("GITHUB_TOKEN") + } + } + + maven("https://maven.blamejared.com/") { + // location of the maven that hosts JEI files since January 2023 + name = "Jared's maven" + } + + maven("https://www.cursemaven.com") { + content { + includeGroup("curse.maven") + } + } + + maven("https://modmaven.dev") { + // location of a maven mirror for JEI files, as a fallback + name = "ModMaven" + } +} + +dependencies { + // Core Projects and Libraries + this { + compileOnly(libraries.jnanoid) + jarJar(libraries.jnanoid) + + compileOnly(coreApi) + testCompileOnly(coreApi) + + compileOnly(libraries.feather) + jarJar(libraries.feather) { isTransitive = false } + } + + runtimeOnly(neoforged.testframework) + testImplementation(neoforged.testframework) + testImplementation("org.junit.jupiter:junit-jupiter:5.7.1") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + + additionalRuntimeClasspath(libraries.feather) + additionalRuntimeClasspath(libraries.jnanoid) + + // Mods +// compileOnly(mods.bundles.jei) +// compileOnly(mods.jade) +} + +tasks.withType { + useJUnitPlatform() +} + +tasks.withType { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE +} + +tasks.withType { + options.encoding = "UTF-8" + options.compilerArgs.addAll(arrayOf("-Xmaxerrs", "9000")) +} + +tasks.withType { + + val gitVersion = providers.exec { + commandLine("git", "rev-parse", "HEAD") + }.standardOutput.asText.get() + + manifest { + val now = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(Date()) + attributes( + mapOf( + "Specification-Title" to "Compact Machines", + "Specification-Vendor" to "CompactMods", + "Specification-Version" to "2", + "Implementation-Title" to "Compact Machines", + "Implementation-Version" to archiveVersion, + "Implementation-Vendor" to "CompactMods", + "Implementation-Timestamp" to now, + "Minecraft-Version" to mojang.versions.minecraft.get(), + "NeoForge-Version" to neoforged.versions.neoforge.get(), + "Main-Commit" to gitVersion + ) + ) + } +} + +tasks.withType().configureEach { + var replaceProperties: Map = mapOf( + "minecraft_version" to mojang.versions.minecraft.get(), + "neo_version" to neoforged.versions.neoforge.get(), + "minecraft_version_range" to mojang.versions.minecraftRange.get(), + "neo_version_range" to neoforged.versions.neoforgeRange.get(), + "loader_version_range" to "[1,)", + "mod_id" to modId, + "mod_version" to envVersion + ) + + inputs.properties(replaceProperties) + filesMatching("META-INF/neoforge.mods.toml") { + expand(replaceProperties) + } +} + +tasks.jar { + from(sourceSets.main.get().output) + from(coreApi.sourceSets.main.get().output) +} + +val PACKAGES_URL = System.getenv("GH_PKG_URL") ?: "https://maven.pkg.github.com/compactmods/compactmachines" +publishing { + publications.register("compactmachines") { + artifactId = "$modId-neoforge" + from(components.getByName("java")) + } + + repositories { + // GitHub Packages + maven(PACKAGES_URL) { + name = "GitHubPackages" + credentials { + username = System.getenv("GITHUB_ACTOR") + password = System.getenv("GITHUB_TOKEN") + } + } + } } \ No newline at end of file diff --git a/neoforge-main/src/main/java/dev/compactmods/machines/client/keybinds/room/RoomUpgradeUIMapping.java b/neoforge-main/src/main/java/dev/compactmods/machines/client/keybinds/room/RoomUpgradeUIMapping.java index f92c67e5..3a05ccf5 100644 --- a/neoforge-main/src/main/java/dev/compactmods/machines/client/keybinds/room/RoomUpgradeUIMapping.java +++ b/neoforge-main/src/main/java/dev/compactmods/machines/client/keybinds/room/RoomUpgradeUIMapping.java @@ -1,42 +1,42 @@ -package dev.compactmods.machines.client.keybinds.room; - -import com.mojang.blaze3d.platform.InputConstants; -import dev.compactmods.machines.api.CompactMachines; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.network.PlayerRequestedUpgradeUIPacket; -import dev.compactmods.machines.room.Rooms; -import net.minecraft.Util; -import net.minecraft.client.KeyMapping; -import net.minecraft.client.Minecraft; -import net.neoforged.neoforge.client.settings.IKeyConflictContext; -import net.neoforged.neoforge.network.PacketDistributor; - -public class RoomUpgradeUIMapping { - - public static final String CATEGORY = Util.makeDescriptionId("key.category", CompactMachines.modRL("general")); - public static final String NAME = Util.makeDescriptionId("key.mapping", CompactMachines.modRL("open_upgrade_screen")); - - public static final IKeyConflictContext CONFLICT_CONTEXT = new IKeyConflictContext() { - @Override - public boolean isActive() { - final var level = Minecraft.getInstance().level; - return level != null && level.dimension().equals(CompactDimension.LEVEL_KEY); - } - - @Override - public boolean conflicts(IKeyConflictContext other) { - return this == other; - } - }; - - public static final KeyMapping MAPPING = new KeyMapping(NAME, CONFLICT_CONTEXT, InputConstants.UNKNOWN, CATEGORY); - - public static void handle() { - final var level = Minecraft.getInstance().level; - final var player = Minecraft.getInstance().player; - if (level != null && level.dimension().equals(CompactDimension.LEVEL_KEY)) { - final var currentRoom = player.getData(Rooms.DataAttachments.CURRENT_ROOM_CODE); - PacketDistributor.sendToServer(new PlayerRequestedUpgradeUIPacket(currentRoom, true)); - } - } -} +package dev.compactmods.machines.client.keybinds.room; + +import com.mojang.blaze3d.platform.InputConstants; +import dev.compactmods.machines.api.CompactMachines; +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.network.PlayerRequestedUpgradeUIPacket; +import dev.compactmods.machines.room.Rooms; +import net.minecraft.Util; +import net.minecraft.client.KeyMapping; +import net.minecraft.client.Minecraft; +import net.neoforged.neoforge.client.settings.IKeyConflictContext; +import net.neoforged.neoforge.network.PacketDistributor; + +public class RoomUpgradeUIMapping { + + public static final String CATEGORY = Util.makeDescriptionId("key.category", CompactMachines.modRL("general")); + public static final String NAME = Util.makeDescriptionId("key.mapping", CompactMachines.modRL("open_upgrade_screen")); + + public static final IKeyConflictContext CONFLICT_CONTEXT = new IKeyConflictContext() { + @Override + public boolean isActive() { + final var level = Minecraft.getInstance().level; + return level != null && level.dimension().equals(CompactDimension.LEVEL_KEY); + } + + @Override + public boolean conflicts(IKeyConflictContext other) { + return this == other; + } + }; + + public static final KeyMapping MAPPING = new KeyMapping(NAME, CONFLICT_CONTEXT, InputConstants.UNKNOWN, CATEGORY); + + public static void handle() { + final var level = Minecraft.getInstance().level; + final var player = Minecraft.getInstance().player; + if (level != null && level.dimension().equals(CompactDimension.LEVEL_KEY)) { + final var currentRoom = player.getData(Rooms.DataAttachments.CURRENT_ROOM_CODE); +// PacketDistributor.sendToServer(new PlayerRequestedUpgradeUIPacket(currentRoom, true)); + } + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/machines/command/subcommand/CMEjectSubcommand.java b/neoforge-main/src/main/java/dev/compactmods/machines/command/subcommand/CMEjectSubcommand.java index a02a256a..f81c119f 100644 --- a/neoforge-main/src/main/java/dev/compactmods/machines/command/subcommand/CMEjectSubcommand.java +++ b/neoforge-main/src/main/java/dev/compactmods/machines/command/subcommand/CMEjectSubcommand.java @@ -1,47 +1,50 @@ -package dev.compactmods.machines.command.subcommand; - -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import dev.compactmods.machines.api.CompactMachines; -import dev.compactmods.machines.util.PlayerUtil; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.commands.arguments.EntityArgument; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; - -import java.util.Collection; - -public class CMEjectSubcommand { - public static ArgumentBuilder make() { - return Commands.literal("eject") - .executes(CMEjectSubcommand::execExecutingPlayer) - .then(Commands.argument("player", EntityArgument.player()) - .requires(cs -> cs.hasPermission(Commands.LEVEL_GAMEMASTERS)) - .executes(CMEjectSubcommand::execSpecificPlayer)); - } - - private static int execSpecificPlayer(CommandContext ctx) throws CommandSyntaxException { - Collection ent = EntityArgument.getPlayers(ctx, "player"); - ent.forEach(player -> { - // FIXME History player.getCapability(RoomCapabilities.ROOM_HISTORY).ifPresent(IRoomHistory::clear); - PlayerUtil.teleportPlayerToRespawnOrOverworld(ctx.getSource().getServer(), player); - }); - - return 0; - } - - private static int execExecutingPlayer(CommandContext ctx) throws CommandSyntaxException { - final ServerPlayer player = ctx.getSource().getPlayerOrException(); - final MinecraftServer server = ctx.getSource().getServer(); - - server.submitAsync(() -> { - CompactMachines.playerHistoryApi().entryPoints().clearHistory(player); - }); - - PlayerUtil.teleportPlayerToRespawnOrOverworld(ctx.getSource().getServer(), player); - - return 0; - } -} +package dev.compactmods.machines.command.subcommand; + +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import dev.compactmods.machines.api.CompactMachines; +import dev.compactmods.machines.util.PlayerUtil; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.commands.arguments.EntityArgument; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; + +import java.util.Collection; + +public class CMEjectSubcommand { + public static ArgumentBuilder make() { + return Commands.literal("eject") + .executes(CMEjectSubcommand::execExecutingPlayer) + .then(Commands.argument("player", EntityArgument.player()) + .requires(cs -> cs.hasPermission(Commands.LEVEL_GAMEMASTERS)) + .executes(CMEjectSubcommand::execSpecificPlayer)); + } + + private static int execSpecificPlayer(CommandContext ctx) throws CommandSyntaxException { + Collection ent = EntityArgument.getPlayers(ctx, "player"); + ent.forEach(player -> { + CompactMachines.playerHistoryApi() + .entryPoints() + .clearHistory(player); + + PlayerUtil.teleportPlayerToRespawnOrOverworld(ctx.getSource().getServer(), player); + }); + + return 0; + } + + private static int execExecutingPlayer(CommandContext ctx) throws CommandSyntaxException { + final ServerPlayer player = ctx.getSource().getPlayerOrException(); + final MinecraftServer server = ctx.getSource().getServer(); + + server.submitAsync(() -> { + CompactMachines.playerHistoryApi().entryPoints().clearHistory(player); + }); + + PlayerUtil.teleportPlayerToRespawnOrOverworld(ctx.getSource().getServer(), player); + + return 0; + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/machines/command/subcommand/CMUnbindSubcommand.java b/neoforge-main/src/main/java/dev/compactmods/machines/command/subcommand/CMUnbindSubcommand.java index b76a0123..ea198ec6 100644 --- a/neoforge-main/src/main/java/dev/compactmods/machines/command/subcommand/CMUnbindSubcommand.java +++ b/neoforge-main/src/main/java/dev/compactmods/machines/command/subcommand/CMUnbindSubcommand.java @@ -1,46 +1,48 @@ -package dev.compactmods.machines.command.subcommand; - -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import dev.compactmods.machines.LoggingUtil; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.api.machine.MachineTranslations; -import dev.compactmods.machines.config.ServerConfig; -import dev.compactmods.machines.machine.block.BoundCompactMachineBlockEntity; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.commands.arguments.coordinates.BlockPosArgument; - -public class CMUnbindSubcommand { - - public static LiteralArgumentBuilder make() { - final var subRoot = Commands.literal("unbind") - .requires(cs -> cs.hasPermission(ServerConfig.rebindLevel())); - - subRoot.then(Commands.argument("pos", BlockPosArgument.blockPos()) - .executes(CMUnbindSubcommand::doUnbind)); - - return subRoot; - } - - private static int doUnbind(CommandContext ctx) throws CommandSyntaxException { - final var server = ctx.getSource().getServer(); - final var level = ctx.getSource().getLevel(); - final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); - final var source = ctx.getSource(); - - if (compactDim == null) return -1; - - final var rebindingMachine = BlockPosArgument.getLoadedBlockPos(ctx, "pos"); - - if (!(level.getBlockEntity(rebindingMachine) instanceof BoundCompactMachineBlockEntity machine)) { - LoggingUtil.modLog().error("Refusing to rebind block at {}; block has invalid machine data.", rebindingMachine); - source.sendFailure(MachineTranslations.NOT_A_MACHINE_BLOCK.apply(rebindingMachine)); - return -1; - } - - machine.disconnect(); - return 0; - } -} +package dev.compactmods.machines.command.subcommand; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import dev.compactmods.machines.LoggingUtil; +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.machine.MachineTranslations; +import dev.compactmods.machines.config.ServerConfig; +import dev.compactmods.machines.machine.Machines; +import dev.compactmods.machines.machine.block.BoundCompactMachineBlockEntity; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.commands.arguments.coordinates.BlockPosArgument; +import net.minecraft.world.level.block.Block; + +public class CMUnbindSubcommand { + + public static LiteralArgumentBuilder make() { + final var subRoot = Commands.literal("unbind") + .requires(cs -> cs.hasPermission(ServerConfig.rebindLevel())); + + subRoot.then(Commands.argument("pos", BlockPosArgument.blockPos()) + .executes(CMUnbindSubcommand::doUnbind)); + + return subRoot; + } + + private static int doUnbind(CommandContext ctx) throws CommandSyntaxException { + final var server = ctx.getSource().getServer(); + final var level = ctx.getSource().getLevel(); + final var compactDim = server.getLevel(CompactDimension.LEVEL_KEY); + final var source = ctx.getSource(); + + if (compactDim == null) return -1; + + final var rebindingMachine = BlockPosArgument.getLoadedBlockPos(ctx, "pos"); + + if (!(level.getBlockEntity(rebindingMachine) instanceof BoundCompactMachineBlockEntity machine)) { + LoggingUtil.modLog().error("Refusing to rebind block at {}; block has invalid machine data.", rebindingMachine); + source.sendFailure(MachineTranslations.NOT_A_MACHINE_BLOCK.apply(rebindingMachine)); + return -1; + } + + level.setBlock(rebindingMachine, Machines.Blocks.UNBOUND_MACHINE.get().defaultBlockState(), Block.UPDATE_ALL); + return 0; + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/machines/dimension/WorldBorderFixer.java b/neoforge-main/src/main/java/dev/compactmods/machines/dimension/WorldBorderFixer.java index 0ed721d6..201123a7 100644 --- a/neoforge-main/src/main/java/dev/compactmods/machines/dimension/WorldBorderFixer.java +++ b/neoforge-main/src/main/java/dev/compactmods/machines/dimension/WorldBorderFixer.java @@ -1,68 +1,67 @@ -package dev.compactmods.machines.dimension; - -import dev.compactmods.machines.api.dimension.CompactDimension; -import net.minecraft.network.protocol.game.ClientboundInitializeBorderPacket; -import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.border.BorderChangeListener; -import net.minecraft.world.level.border.WorldBorder; -import net.neoforged.neoforge.common.NeoForge; -import net.neoforged.neoforge.event.entity.player.PlayerEvent; -import net.neoforged.neoforge.event.level.LevelEvent; - -import java.util.Collections; - -public class WorldBorderFixer { - - public static void registerEvents() { - NeoForge.EVENT_BUS.addListener(WorldBorderFixer::onWorldLoaded); - NeoForge.EVENT_BUS.addListener(WorldBorderFixer::onPlayerLogin); - NeoForge.EVENT_BUS.addListener(WorldBorderFixer::onPlayerDimChange); - } - - private static void onWorldLoaded(final LevelEvent.Load evt) { - if (evt.getLevel() instanceof ServerLevel compactDim && compactDim.dimension().equals(CompactDimension.LEVEL_KEY)) - WorldBorderFixer.sendWorldBorderListenerOverrides(compactDim.getServer(), compactDim); - } - - private static void onPlayerLogin(final PlayerEvent.PlayerLoggedInEvent evt) { - if (evt.getEntity() instanceof ServerPlayer sp && CompactDimension.isLevelCompact(sp.level())) - WorldBorderFixer.sendClientWorldBorderFix(sp); - } - - private static void onPlayerDimChange(final PlayerEvent.PlayerChangedDimensionEvent evt) { - if (evt.getTo().equals(CompactDimension.LEVEL_KEY) && evt.getEntity() instanceof ServerPlayer sp) - WorldBorderFixer.sendClientWorldBorderFix(sp); - } - - private static void sendWorldBorderListenerOverrides(MinecraftServer serv, ServerLevel compactDim) { - final var owBorder = serv.overworld().getWorldBorder(); - final var cwBorder = compactDim.getWorldBorder(); - - // Filter border listeners down to the compact world, then remove them from the OW listener list - final var listeners = Collections.emptySet(); - // TODO Fix World Border (AT issue) -// final var listeners = owBorder.listeners.stream() -// .filter(border -> border instanceof BorderChangeListener.DelegateBorderChangeListener) -// .map(BorderChangeListener.DelegateBorderChangeListener.class::cast) -// .filter(list -> list.worldBorder == cwBorder) -// .collect(Collectors.toSet()); - - for (var listener : listeners) - owBorder.removeListener(listener); - - // Fix set compact world border if it was loaded weirdly - cwBorder.setCenter(0, 0); - cwBorder.setSize(WorldBorder.MAX_SIZE); - - // Send update to all players - serv.getPlayerList().broadcastAll(new ClientboundSetBorderSizePacket(cwBorder), compactDim.dimension()); - } - - private static void sendClientWorldBorderFix(ServerPlayer player) { - // Send a fake world border to the player instead of the "real" one in overworld - player.connection.send(new ClientboundInitializeBorderPacket(new WorldBorder())); - } -} +package dev.compactmods.machines.dimension; + +import dev.compactmods.machines.api.dimension.CompactDimension; +import net.minecraft.network.protocol.game.ClientboundInitializeBorderPacket; +import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.border.BorderChangeListener; +import net.minecraft.world.level.border.WorldBorder; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.entity.player.PlayerEvent; +import net.neoforged.neoforge.event.level.LevelEvent; + +import java.util.Collections; +import java.util.stream.Collectors; + +public class WorldBorderFixer { + + public static void registerEvents() { + NeoForge.EVENT_BUS.addListener(WorldBorderFixer::onWorldLoaded); + NeoForge.EVENT_BUS.addListener(WorldBorderFixer::onPlayerLogin); + NeoForge.EVENT_BUS.addListener(WorldBorderFixer::onPlayerDimChange); + } + + private static void onWorldLoaded(final LevelEvent.Load evt) { + if (evt.getLevel() instanceof ServerLevel compactDim && compactDim.dimension().equals(CompactDimension.LEVEL_KEY)) + WorldBorderFixer.sendWorldBorderListenerOverrides(compactDim.getServer(), compactDim); + } + + private static void onPlayerLogin(final PlayerEvent.PlayerLoggedInEvent evt) { + if (evt.getEntity() instanceof ServerPlayer sp && CompactDimension.isLevelCompact(sp.level())) + WorldBorderFixer.sendClientWorldBorderFix(sp); + } + + private static void onPlayerDimChange(final PlayerEvent.PlayerChangedDimensionEvent evt) { + if (evt.getTo().equals(CompactDimension.LEVEL_KEY) && evt.getEntity() instanceof ServerPlayer sp) + WorldBorderFixer.sendClientWorldBorderFix(sp); + } + + private static void sendWorldBorderListenerOverrides(MinecraftServer serv, ServerLevel compactDim) { + final var owBorder = serv.overworld().getWorldBorder(); + final var cwBorder = compactDim.getWorldBorder(); + + // Filter border listeners down to the compact world, then remove them from the OW listener list + final var listeners = owBorder.listeners.stream() + .filter(border -> border instanceof BorderChangeListener.DelegateBorderChangeListener) + .map(BorderChangeListener.DelegateBorderChangeListener.class::cast) + .filter(list -> list.worldBorder == cwBorder) + .collect(Collectors.toSet()); + + for (var listener : listeners) + owBorder.removeListener(listener); + + // Fix set compact world border if it was loaded weirdly + cwBorder.setCenter(0, 0); + cwBorder.setSize(WorldBorder.MAX_SIZE); + + // Send update to all players + serv.getPlayerList().broadcastAll(new ClientboundSetBorderSizePacket(cwBorder), compactDim.dimension()); + } + + private static void sendClientWorldBorderFix(ServerPlayer player) { + // Send a fake world border to the player instead of the "real" one in overworld + player.connection.send(new ClientboundInitializeBorderPacket(new WorldBorder())); + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/machines/machine/Machines.java b/neoforge-main/src/main/java/dev/compactmods/machines/machine/Machines.java index 34c2b9e9..dfdce612 100644 --- a/neoforge-main/src/main/java/dev/compactmods/machines/machine/Machines.java +++ b/neoforge-main/src/main/java/dev/compactmods/machines/machine/Machines.java @@ -1,159 +1,164 @@ -package dev.compactmods.machines.machine; - -import dev.compactmods.machines.api.item.component.MachineComponents; -import dev.compactmods.machines.api.machine.MachineConstants; -import dev.compactmods.machines.api.room.RoomComponents; -import dev.compactmods.machines.api.room.RoomTemplate; -import dev.compactmods.machines.CMRegistries; -import dev.compactmods.machines.client.machine.MachinesClient; -import dev.compactmods.machines.machine.block.BoundCompactMachineBlock; -import dev.compactmods.machines.machine.block.BoundCompactMachineBlockEntity; -import dev.compactmods.machines.machine.block.UnboundCompactMachineBlock; -import dev.compactmods.machines.machine.block.UnboundCompactMachineEntity; -import dev.compactmods.machines.machine.item.BoundCompactMachineItem; -import dev.compactmods.machines.machine.item.UnboundCompactMachineItem; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderLookup; -import net.minecraft.core.component.DataComponentType; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.nbt.IntTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.fml.loading.FMLEnvironment; -import net.neoforged.neoforge.attachment.AttachmentType; -import net.neoforged.neoforge.attachment.IAttachmentHolder; -import net.neoforged.neoforge.attachment.IAttachmentSerializer; -import net.neoforged.neoforge.registries.DeferredBlock; -import net.neoforged.neoforge.registries.DeferredHolder; -import net.neoforged.neoforge.registries.DeferredItem; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Supplier; - -public interface Machines { - // TODO: Metal material replacement - BlockBehaviour.Properties MACHINE_BLOCK_PROPS = BlockBehaviour.Properties - .of() - .strength(8.0F, 20.0F) - .requiresCorrectToolForDrops(); - - Supplier MACHINE_ITEM_PROPS = Item.Properties::new; - - interface Blocks { - DeferredBlock UNBOUND_MACHINE = CMRegistries.BLOCKS.register("new_machine", () -> - new UnboundCompactMachineBlock(MACHINE_BLOCK_PROPS)); - - DeferredBlock BOUND_MACHINE = CMRegistries.BLOCKS.register("machine", () -> - new BoundCompactMachineBlock(MACHINE_BLOCK_PROPS)); - - static void prepare() { - } - } - - interface Items { - DeferredItem BOUND_MACHINE = CMRegistries.ITEMS.register("machine", - () -> new BoundCompactMachineItem(MACHINE_ITEM_PROPS.get())); - - DeferredItem UNBOUND_MACHINE = CMRegistries.ITEMS.register("new_machine", - () -> new UnboundCompactMachineItem(MACHINE_ITEM_PROPS.get())); - - static void prepare() { - } - - static ItemStack unbound() { - return unboundColored(0xFFFFFFFF); - } - - static ItemStack unboundColored(int color) { - final var stack = UNBOUND_MACHINE.toStack(); - stack.set(Machines.DataComponents.MACHINE_COLOR, color); - return stack; - } - - static ItemStack boundToRoom(String roomCode) { - return boundToRoom(roomCode, 0xFFFFFFFF); - } - - static ItemStack boundToRoom(String roomCode, int color) { - ItemStack stack = BOUND_MACHINE.toStack(); - stack.set(Machines.DataComponents.BOUND_ROOM_CODE, roomCode); - stack.set(Machines.DataComponents.MACHINE_COLOR, color); - return stack; - } - - static ItemStack forNewRoom(ResourceLocation templateID, RoomTemplate template) { - final var stack = UNBOUND_MACHINE.toStack(); - stack.set(Machines.DataComponents.ROOM_TEMPLATE_ID, templateID); - stack.set(Machines.DataComponents.ROOM_TEMPLATE, template); - stack.set(Machines.DataComponents.MACHINE_COLOR, template.defaultMachineColor().rgb()); - return stack; - } - } - - interface BlockEntities { - - DeferredHolder, BlockEntityType> UNBOUND_MACHINE = CMRegistries.BLOCK_ENTITIES.register(MachineConstants.UNBOUND_MACHINE_ENTITY.getPath(), () -> - BlockEntityType.Builder.of(UnboundCompactMachineEntity::new, Blocks.UNBOUND_MACHINE.get()) - .build(null)); - - DeferredHolder, BlockEntityType> MACHINE = CMRegistries.BLOCK_ENTITIES.register(MachineConstants.BOUND_MACHINE_ENTITY.getPath(), () -> - BlockEntityType.Builder.of(BoundCompactMachineBlockEntity::new, Blocks.BOUND_MACHINE.get()) - .build(null)); - - static void prepare() { - } - } - - interface DataComponents { - DeferredHolder, DataComponentType> BOUND_ROOM_CODE = CMRegistries.DATA_COMPONENTS - .registerComponentType("room_code", MachineComponents.BOUND_ROOM_CODE); - - DeferredHolder, DataComponentType> MACHINE_COLOR = CMRegistries.DATA_COMPONENTS - .registerComponentType("machine_color", MachineComponents.MACHINE_COLOR); - - DeferredHolder, DataComponentType> ROOM_TEMPLATE_ID = CMRegistries.DATA_COMPONENTS - .registerComponentType("room_template_id", MachineComponents.ROOM_TEMPLATE_ID); - - DeferredHolder, DataComponentType> ROOM_TEMPLATE = CMRegistries.DATA_COMPONENTS - .registerComponentType("room_template", RoomComponents.ROOM_TEMPLATE); - - static void prepare() { - } - } - - interface Attachments { - Supplier> MACHINE_COLOR = CMRegistries.ATTACHMENT_TYPES.register("machine_color", () -> AttachmentType - .builder(() -> 0xFFFFFFFF) - .serialize(new IAttachmentSerializer() { - @Override - public Integer read(IAttachmentHolder holder, IntTag tag, HolderLookup.Provider provider) { - return tag.getAsInt(); - } - - @Override - public @Nullable IntTag write(Integer attachment, HolderLookup.Provider provider) { - return IntTag.valueOf(attachment); - } - }) - .build()); - - static void prepare() { - } - } - - static void prepare() { - Blocks.prepare(); - Items.prepare(); - BlockEntities.prepare(); - DataComponents.prepare(); - Attachments.prepare(); - } - - static void registerEvents(IEventBus modBus) { - - } -} +package dev.compactmods.machines.machine; + +import dev.compactmods.machines.api.item.component.MachineComponents; +import dev.compactmods.machines.api.machine.MachineConstants; +import dev.compactmods.machines.api.room.RoomComponents; +import dev.compactmods.machines.api.room.RoomTemplate; +import dev.compactmods.machines.CMRegistries; +import dev.compactmods.machines.client.machine.MachinesClient; +import dev.compactmods.machines.machine.block.BoundCompactMachineBlock; +import dev.compactmods.machines.machine.block.BoundCompactMachineBlockEntity; +import dev.compactmods.machines.machine.block.UnboundCompactMachineBlock; +import dev.compactmods.machines.machine.block.UnboundCompactMachineEntity; +import dev.compactmods.machines.machine.item.BoundCompactMachineItem; +import dev.compactmods.machines.machine.item.UnboundCompactMachineItem; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.IntTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; +import net.minecraft.world.level.material.PushReaction; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.neoforge.attachment.AttachmentType; +import net.neoforged.neoforge.attachment.IAttachmentHolder; +import net.neoforged.neoforge.attachment.IAttachmentSerializer; +import net.neoforged.neoforge.registries.DeferredBlock; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredItem; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +public interface Machines { + BlockBehaviour.Properties MACHINE_BLOCK_PROPS = BlockBehaviour.Properties + .of() + .instrument(NoteBlockInstrument.COW_BELL) + .pushReaction(PushReaction.IGNORE) + .sound(SoundType.METAL) + .strength(8.0F, 20.0F) + .requiresCorrectToolForDrops(); + + Supplier MACHINE_ITEM_PROPS = Item.Properties::new; + + interface Blocks { + DeferredBlock UNBOUND_MACHINE = CMRegistries.BLOCKS.register("new_machine", () -> + new UnboundCompactMachineBlock(MACHINE_BLOCK_PROPS)); + + DeferredBlock BOUND_MACHINE = CMRegistries.BLOCKS.register("machine", () -> + new BoundCompactMachineBlock(MACHINE_BLOCK_PROPS)); + + static void prepare() { + } + } + + interface Items { + DeferredItem BOUND_MACHINE = CMRegistries.ITEMS.register("machine", + () -> new BoundCompactMachineItem(MACHINE_ITEM_PROPS.get())); + + DeferredItem UNBOUND_MACHINE = CMRegistries.ITEMS.register("new_machine", + () -> new UnboundCompactMachineItem(MACHINE_ITEM_PROPS.get())); + + static void prepare() { + } + + static ItemStack unbound() { + return unboundColored(0xFFFFFFFF); + } + + static ItemStack unboundColored(int color) { + final var stack = UNBOUND_MACHINE.toStack(); + stack.set(Machines.DataComponents.MACHINE_COLOR, color); + return stack; + } + + static ItemStack boundToRoom(String roomCode) { + return boundToRoom(roomCode, 0xFFFFFFFF); + } + + static ItemStack boundToRoom(String roomCode, int color) { + ItemStack stack = BOUND_MACHINE.toStack(); + stack.set(Machines.DataComponents.BOUND_ROOM_CODE, roomCode); + stack.set(Machines.DataComponents.MACHINE_COLOR, color); + return stack; + } + + static ItemStack forNewRoom(ResourceLocation templateID, RoomTemplate template) { + final var stack = UNBOUND_MACHINE.toStack(); + stack.set(Machines.DataComponents.ROOM_TEMPLATE_ID, templateID); + stack.set(Machines.DataComponents.ROOM_TEMPLATE, template); + stack.set(Machines.DataComponents.MACHINE_COLOR, template.defaultMachineColor().rgb()); + return stack; + } + } + + interface BlockEntities { + + DeferredHolder, BlockEntityType> UNBOUND_MACHINE = CMRegistries.BLOCK_ENTITIES.register(MachineConstants.UNBOUND_MACHINE_ENTITY.getPath(), () -> + BlockEntityType.Builder.of(UnboundCompactMachineEntity::new, Blocks.UNBOUND_MACHINE.get()) + .build(null)); + + DeferredHolder, BlockEntityType> MACHINE = CMRegistries.BLOCK_ENTITIES.register(MachineConstants.BOUND_MACHINE_ENTITY.getPath(), () -> + BlockEntityType.Builder.of(BoundCompactMachineBlockEntity::new, Blocks.BOUND_MACHINE.get()) + .build(null)); + + static void prepare() { + } + } + + interface DataComponents { + DeferredHolder, DataComponentType> BOUND_ROOM_CODE = CMRegistries.DATA_COMPONENTS + .registerComponentType("room_code", MachineComponents.BOUND_ROOM_CODE); + + DeferredHolder, DataComponentType> MACHINE_COLOR = CMRegistries.DATA_COMPONENTS + .registerComponentType("machine_color", MachineComponents.MACHINE_COLOR); + + DeferredHolder, DataComponentType> ROOM_TEMPLATE_ID = CMRegistries.DATA_COMPONENTS + .registerComponentType("room_template_id", MachineComponents.ROOM_TEMPLATE_ID); + + DeferredHolder, DataComponentType> ROOM_TEMPLATE = CMRegistries.DATA_COMPONENTS + .registerComponentType("room_template", RoomComponents.ROOM_TEMPLATE); + + static void prepare() { + } + } + + interface Attachments { + Supplier> MACHINE_COLOR = CMRegistries.ATTACHMENT_TYPES.register("machine_color", () -> AttachmentType + .builder(() -> 0xFFFFFFFF) + .serialize(new IAttachmentSerializer() { + @Override + public Integer read(IAttachmentHolder holder, IntTag tag, HolderLookup.Provider provider) { + return tag.getAsInt(); + } + + @Override + public @Nullable IntTag write(Integer attachment, HolderLookup.Provider provider) { + return IntTag.valueOf(attachment); + } + }) + .build()); + + static void prepare() { + } + } + + static void prepare() { + Blocks.prepare(); + Items.prepare(); + BlockEntities.prepare(); + DataComponents.prepare(); + Attachments.prepare(); + } + + static void registerEvents(IEventBus modBus) { + + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/machines/machine/block/BoundCompactMachineBlock.java b/neoforge-main/src/main/java/dev/compactmods/machines/machine/block/BoundCompactMachineBlock.java index 64667086..b37c3ae0 100644 --- a/neoforge-main/src/main/java/dev/compactmods/machines/machine/block/BoundCompactMachineBlock.java +++ b/neoforge-main/src/main/java/dev/compactmods/machines/machine/block/BoundCompactMachineBlock.java @@ -1,143 +1,142 @@ -package dev.compactmods.machines.machine.block; - -import dev.compactmods.machines.LoggingUtil; -import dev.compactmods.machines.api.CompactMachines; -import dev.compactmods.machines.api.shrinking.PSDTags; -import dev.compactmods.machines.machine.config.EnumMachinePlayersBreakHandling; -import dev.compactmods.machines.config.ServerConfig; -import dev.compactmods.machines.machine.Machines; -import dev.compactmods.machines.room.RoomHelper; -import dev.compactmods.machines.room.Rooms; -import dev.compactmods.machines.room.ui.preview.MachineRoomMenu; -import net.minecraft.core.BlockPos; -import net.minecraft.core.GlobalPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.ItemInteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.DyeItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.HitResult; -import net.neoforged.neoforge.common.util.FakePlayer; -import net.neoforged.neoforge.event.EventHooks; -import org.jetbrains.annotations.Nullable; - -import java.util.Optional; -import java.util.UUID; - -public class BoundCompactMachineBlock extends CompactMachineBlock implements EntityBlock { - public BoundCompactMachineBlock(Properties props) { - super(props); - } - - @Override - public ItemStack getCloneItemStack(BlockState state, HitResult target, LevelReader level, BlockPos pos, Player player) { - try { - if (level.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity be) { - return Machines.Items.boundToRoom(be.connectedRoom(), be.getData(Machines.Attachments.MACHINE_COLOR)); - } - - return Machines.Items.unbound(); - } - - catch(Exception ex) { - LoggingUtil.modLog().warn("Warning: tried to pick block on a bound machine that does not have a room bound.", ex); - return Machines.Items.unbound(); - } - } - - @Override - public float getDestroyProgress(BlockState state, Player player, BlockGetter level, BlockPos pos) { - int baseSpeedForge = EventHooks.doPlayerHarvestCheck(player, state, level, pos) ? 30 : 100; - float normalHardness = player.getDigSpeed(state, pos) / baseSpeedForge; - - if (level.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity bound) { - boolean hasPlayers = bound.hasPlayersInside(); - - // If there are players inside, check config for break handling - if (hasPlayers) { - EnumMachinePlayersBreakHandling hand = ServerConfig.MACHINE_PLAYER_BREAK_HANDLING.get(); - switch (hand) { - case UNBREAKABLE: - return 0; - - case OWNER: - Optional ownerUUID = bound.getOwnerUUID(); - return ownerUUID - .map(uuid -> player.getUUID() == uuid ? normalHardness : 0) - .orElse(normalHardness); - - case ANYONE: - return normalHardness; - } - } - - // No players inside - let anyone break it - return normalHardness; - } else { - return normalHardness; - } - } - - @Nullable - @Override - public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { - return new BoundCompactMachineBlockEntity(pos, state); - } - - @Override - protected ItemInteractionResult useItemOn(ItemStack mainItem, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { - if (mainItem.getItem() instanceof DyeItem dye && !level.isClientSide && level instanceof ServerLevel sl) { - return tryDyingMachine(sl, pos, player, dye, mainItem); - } - - if (mainItem.is(PSDTags.ITEM) - && player instanceof ServerPlayer sp - && level.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity tile) { - - // Try to teleport player into room - RoomHelper.teleportPlayerIntoMachine(level, sp, tile.getLevelPosition(), tile.connectedRoom()); - return ItemInteractionResult.SUCCESS; - } - - return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; - } - - @Override - protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) { - // All other items, open preview screen - if (!level.isClientSide && !(player instanceof FakePlayer)) { - level.getBlockEntity(pos, Machines.BlockEntities.MACHINE.get()).ifPresent(machine -> { - final var roomCode = machine.connectedRoom(); - CompactMachines.room(roomCode).ifPresent(inst -> { - if (player instanceof ServerPlayer sp) { - sp.setData(Rooms.DataAttachments.OPEN_MACHINE_POS, machine.getLevelPosition()); - sp.openMenu(MachineRoomMenu.provider(sp.server, inst), (buf) -> { - buf.writeJsonWithCodec(GlobalPos.CODEC, machine.getLevelPosition()); - buf.writeUtf(roomCode); - buf.writeOptional(Optional.empty(), FriendlyByteBuf::writeUtf); - }); - } - }); - }); - } - - return InteractionResult.sidedSuccess(level.isClientSide); - } - - @Override - public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pMovedByPiston) { - super.onRemove(pState, pLevel, pPos, pNewState, pMovedByPiston); - // TODO: Remove machine from room graph - } -} +package dev.compactmods.machines.machine.block; + +import dev.compactmods.machines.LoggingUtil; +import dev.compactmods.machines.api.CompactMachines; +import dev.compactmods.machines.api.shrinking.PSDTags; +import dev.compactmods.machines.machine.config.EnumMachinePlayersBreakHandling; +import dev.compactmods.machines.config.ServerConfig; +import dev.compactmods.machines.machine.Machines; +import dev.compactmods.machines.room.RoomHelper; +import dev.compactmods.machines.room.Rooms; +import dev.compactmods.machines.room.ui.preview.MachineRoomMenu; +import net.minecraft.core.BlockPos; +import net.minecraft.core.GlobalPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.DyeItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.neoforged.neoforge.common.util.FakePlayer; +import net.neoforged.neoforge.event.EventHooks; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; +import java.util.UUID; + +public class BoundCompactMachineBlock extends CompactMachineBlock implements EntityBlock { + public BoundCompactMachineBlock(Properties props) { + super(props); + } + + @Override + public ItemStack getCloneItemStack(BlockState state, HitResult target, LevelReader level, BlockPos pos, Player player) { + try { + if (level.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity be) { + return Machines.Items.boundToRoom(be.connectedRoom(), be.getData(Machines.Attachments.MACHINE_COLOR)); + } + + return Machines.Items.unbound(); + } + + catch(Exception ex) { + LoggingUtil.modLog().warn("Warning: tried to pick block on a bound machine that does not have a room bound.", ex); + return Machines.Items.unbound(); + } + } + + @Override + public float getDestroyProgress(BlockState state, Player player, BlockGetter level, BlockPos pos) { + int baseSpeedForge = EventHooks.doPlayerHarvestCheck(player, state, level, pos) ? 30 : 100; + float normalHardness = player.getDigSpeed(state, pos) / baseSpeedForge; + + if (level.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity bound) { + boolean hasPlayers = bound.hasPlayersInside(); + + // If there are players inside, check config for break handling + if (hasPlayers) { + EnumMachinePlayersBreakHandling hand = ServerConfig.MACHINE_PLAYER_BREAK_HANDLING.get(); + switch (hand) { + case UNBREAKABLE: + return 0; + + case OWNER: + Optional ownerUUID = bound.getOwnerUUID(); + return ownerUUID + .map(uuid -> player.getUUID() == uuid ? normalHardness : 0) + .orElse(normalHardness); + + case ANYONE: + return normalHardness; + } + } + + // No players inside - let anyone break it + return normalHardness; + } else { + return normalHardness; + } + } + + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new BoundCompactMachineBlockEntity(pos, state); + } + + @Override + protected ItemInteractionResult useItemOn(ItemStack mainItem, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { + if (mainItem.getItem() instanceof DyeItem dye && !level.isClientSide && level instanceof ServerLevel sl) { + return tryDyingMachine(sl, pos, player, dye, mainItem); + } + + if (mainItem.is(PSDTags.ITEM) + && player instanceof ServerPlayer sp + && level.getBlockEntity(pos) instanceof BoundCompactMachineBlockEntity tile) { + + // Try to teleport player into room + RoomHelper.teleportPlayerIntoMachine(level, sp, tile.getLevelPosition(), tile.connectedRoom()); + return ItemInteractionResult.SUCCESS; + } + + return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + } + + @Override + protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) { + // All other items, open preview screen + if (!level.isClientSide && !(player instanceof FakePlayer)) { + level.getBlockEntity(pos, Machines.BlockEntities.MACHINE.get()).ifPresent(machine -> { + final var roomCode = machine.connectedRoom(); + CompactMachines.room(roomCode).ifPresent(inst -> { + if (player instanceof ServerPlayer sp) { + sp.setData(Rooms.DataAttachments.OPEN_MACHINE_POS, machine.getLevelPosition()); + sp.openMenu(MachineRoomMenu.provider(sp.server, inst), (buf) -> { + buf.writeJsonWithCodec(GlobalPos.CODEC, machine.getLevelPosition()); + buf.writeUtf(roomCode); + buf.writeOptional(Optional.empty(), FriendlyByteBuf::writeUtf); + }); + } + }); + }); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pMovedByPiston) { + super.onRemove(pState, pLevel, pPos, pNewState, pMovedByPiston); + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/machines/machine/block/BoundCompactMachineBlockEntity.java b/neoforge-main/src/main/java/dev/compactmods/machines/machine/block/BoundCompactMachineBlockEntity.java index c577f7e8..57594c56 100644 --- a/neoforge-main/src/main/java/dev/compactmods/machines/machine/block/BoundCompactMachineBlockEntity.java +++ b/neoforge-main/src/main/java/dev/compactmods/machines/machine/block/BoundCompactMachineBlockEntity.java @@ -1,155 +1,140 @@ -package dev.compactmods.machines.machine.block; - -import dev.compactmods.machines.api.CompactMachines; -import dev.compactmods.machines.api.machine.block.IBoundCompactMachineBlockEntity; -import dev.compactmods.machines.machine.Machines; -import net.minecraft.core.BlockPos; -import net.minecraft.core.GlobalPos; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.item.DyeColor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Optional; -import java.util.UUID; - -public class BoundCompactMachineBlockEntity extends BlockEntity implements IBoundCompactMachineBlockEntity { - - protected UUID owner; - private String roomCode; - - @Nullable - private Component customName; - - public BoundCompactMachineBlockEntity(BlockPos pos, BlockState state) { - super(Machines.BlockEntities.MACHINE.get(), pos, state); - } - - @Override - protected void loadAdditional(CompoundTag nbt, HolderLookup.Provider holders) { - super.loadAdditional(nbt, holders); - if (nbt.contains(NBT_ROOM_CODE)) { - this.roomCode = nbt.getString(NBT_ROOM_CODE); - } - - if (nbt.contains(NBT_OWNER)) { - owner = nbt.getUUID(NBT_OWNER); - } else { - owner = null; - } - } - - @Override - protected void saveAdditional(@NotNull CompoundTag nbt, HolderLookup.Provider holders) { - super.saveAdditional(nbt, holders); - - if (owner != null) { - nbt.putUUID(NBT_OWNER, this.owner); - } - - if (roomCode != null) - nbt.putString(NBT_ROOM_CODE, roomCode); - } - - @Override - public CompoundTag getUpdateTag(HolderLookup.Provider provider) { - var data = super.getUpdateTag(provider); - saveAdditional(data, provider); - - if (this.roomCode != null) { - // data.putString(ROOM_POS_NBT, room); - data.putString(NBT_ROOM_CODE, roomCode); - } - - if (this.owner != null) - data.putUUID("owner", this.owner); - - return data; - } - - @Override - public void handleUpdateTag(CompoundTag tag, HolderLookup.Provider provider) { - super.handleUpdateTag(tag, provider); - - if (tag.contains(NBT_ROOM_CODE)) - this.roomCode = tag.getString(NBT_ROOM_CODE); - - if (tag.contains("players")) { - CompoundTag players = tag.getCompound("players"); - // playerData = CompactMachinePlayerData.fromNBT(players); - - } - - if (tag.contains("owner")) - owner = tag.getUUID("owner"); - } - - public Optional getOwnerUUID() { - return Optional.ofNullable(this.owner); - } - - public void setOwner(UUID owner) { - this.owner = owner; - } - - public boolean hasPlayersInside() { - // TODO - return false; - } - - public GlobalPos getLevelPosition() { - return GlobalPos.of(level.dimension(), worldPosition); - } - - public void setConnectedRoom(String roomCode) { - if (level instanceof ServerLevel sl) { - // FIXME: Register machine location in room's connection graph -// final var dimMachines = DimensionMachineGraph.forDimension(sl); -// if (this.roomCode != null) { -// dimMachines.unregisterMachine(worldPosition); -// } -// -// dimMachines.register(worldPosition, roomCode); - this.roomCode = roomCode; - - CompactMachines.room(roomCode).ifPresentOrElse(inst -> { - this.setData(Machines.Attachments.MACHINE_COLOR, inst.defaultMachineColor()); - }, - () -> { - this.setData(Machines.Attachments.MACHINE_COLOR, DyeColor.WHITE.getTextColor()); - }); - - this.setChanged(); - } - } - - public void disconnect() { - if (level instanceof ServerLevel sl) { - // FIXME: Room machine graph unregister -// final var dimMachines = DimensionMachineGraph.forDimension(sl); -// dimMachines.unregisterMachine(worldPosition); - - sl.setBlock(worldPosition, Machines.Blocks.UNBOUND_MACHINE.get().defaultBlockState(), Block.UPDATE_ALL); - } - } - - @NotNull - public String connectedRoom() { - return roomCode; - } - - public Optional getCustomName() { - return Optional.ofNullable(customName); - } - - public void setCustomName(Component customName) { - this.customName = customName; - this.setChanged(); - } -} +package dev.compactmods.machines.machine.block; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import dev.compactmods.machines.api.CompactMachines; +import dev.compactmods.machines.api.machine.block.IBoundCompactMachineBlockEntity; +import dev.compactmods.machines.machine.Machines; +import net.minecraft.core.BlockPos; +import net.minecraft.core.GlobalPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; +import java.util.UUID; + +public class BoundCompactMachineBlockEntity extends BlockEntity implements IBoundCompactMachineBlockEntity { + + protected UUID owner; + private String roomCode; + + @Nullable + private Component customName; + + public BoundCompactMachineBlockEntity(BlockPos pos, BlockState state) { + super(Machines.BlockEntities.MACHINE.get(), pos, state); + } + + @Override + protected void loadAdditional(CompoundTag nbt, HolderLookup.Provider holders) { + super.loadAdditional(nbt, holders); + if (nbt.contains(NBT_ROOM_CODE)) { + this.roomCode = nbt.getString(NBT_ROOM_CODE); + } + + if (nbt.contains(NBT_OWNER)) { + owner = nbt.getUUID(NBT_OWNER); + } else { + owner = null; + } + } + + @Override + protected void saveAdditional(@NotNull CompoundTag nbt, HolderLookup.Provider holders) { + super.saveAdditional(nbt, holders); + + if (owner != null) { + nbt.putUUID(NBT_OWNER, this.owner); + } + + if (roomCode != null) + nbt.putString(NBT_ROOM_CODE, roomCode); + } + + @Override + public CompoundTag getUpdateTag(HolderLookup.Provider provider) { + var data = super.getUpdateTag(provider); + saveAdditional(data, provider); + + if (this.roomCode != null) { + // data.putString(ROOM_POS_NBT, room); + data.putString(NBT_ROOM_CODE, roomCode); + } + + if (this.owner != null) + data.putUUID("owner", this.owner); + + return data; + } + + @Override + public void handleUpdateTag(CompoundTag tag, HolderLookup.Provider provider) { + super.handleUpdateTag(tag, provider); + + if (tag.contains(NBT_ROOM_CODE)) + this.roomCode = tag.getString(NBT_ROOM_CODE); + + if (tag.contains("players")) { + CompoundTag players = tag.getCompound("players"); + // playerData = CompactMachinePlayerData.fromNBT(players); + + } + + if (tag.contains("owner")) + owner = tag.getUUID("owner"); + } + + public Optional getOwnerUUID() { + return Optional.ofNullable(this.owner); + } + + public void setOwner(UUID owner) { + this.owner = owner; + } + + public boolean hasPlayersInside() { + // TODO + return false; + } + + public GlobalPos getLevelPosition() { + return GlobalPos.of(level.dimension(), worldPosition); + } + + public void setConnectedRoom(String roomCode) { + if (level != null && !level.isClientSide()) { + this.roomCode = roomCode; + + CompactMachines.room(roomCode).ifPresentOrElse(inst -> { + this.setData(Machines.Attachments.MACHINE_COLOR, inst.defaultMachineColor()); + }, + () -> { + this.setData(Machines.Attachments.MACHINE_COLOR, DyeColor.WHITE.getTextColor()); + }); + + this.setChanged(); + } + } + + @NotNull + public String connectedRoom() { + return roomCode; + } + + public Optional getCustomName() { + return Optional.ofNullable(customName); + } + + public void setCustomName(Component customName) { + this.customName = customName; + this.setChanged(); + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/machines/network/CMNetworks.java b/neoforge-main/src/main/java/dev/compactmods/machines/network/CMNetworks.java index 3b290a1e..4f697024 100644 --- a/neoforge-main/src/main/java/dev/compactmods/machines/network/CMNetworks.java +++ b/neoforge-main/src/main/java/dev/compactmods/machines/network/CMNetworks.java @@ -1,25 +1,25 @@ -package dev.compactmods.machines.network; - -import dev.compactmods.machines.network.machine.MachineColorSyncPacket; -import net.minecraft.network.codec.StreamCodec; -import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; -import net.neoforged.neoforge.network.registration.PayloadRegistrar; - -public class CMNetworks { - - public static void onPacketRegistration(final RegisterPayloadHandlersEvent payloads) { - final PayloadRegistrar main = payloads.registrar("6.0.0"); - - main.playToServer(PlayerRequestedTeleportPacket.TYPE, PlayerRequestedTeleportPacket.STREAM_CODEC, PlayerRequestedTeleportPacket.HANDLER); - - main.playToClient(SyncRoomMetadataPacket.TYPE, SyncRoomMetadataPacket.STREAM_CODEC, SyncRoomMetadataPacket.HANDLER); - - main.playToServer(PlayerRequestedLeavePacket.TYPE, StreamCodec.unit(new PlayerRequestedLeavePacket()), PlayerRequestedLeavePacket.HANDLER); - - main.playToServer(PlayerRequestedRoomUIPacket.TYPE, PlayerRequestedRoomUIPacket.STREAM_CODEC, PlayerRequestedRoomUIPacket.HANDLER); - - main.playToServer(PlayerRequestedUpgradeUIPacket.TYPE, PlayerRequestedUpgradeUIPacket.STREAM_CODEC, PlayerRequestedUpgradeUIPacket.HANDLER); - - main.playToClient(MachineColorSyncPacket.TYPE, MachineColorSyncPacket.STREAM_CODEC, MachineColorSyncPacket.HANDLER); - } -} +package dev.compactmods.machines.network; + +import dev.compactmods.machines.network.machine.MachineColorSyncPacket; +import net.minecraft.network.codec.StreamCodec; +import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; +import net.neoforged.neoforge.network.registration.PayloadRegistrar; + +public class CMNetworks { + + public static void onPacketRegistration(final RegisterPayloadHandlersEvent payloads) { + final PayloadRegistrar main = payloads.registrar("6.0.0"); + + main.playToServer(PlayerRequestedTeleportPacket.TYPE, PlayerRequestedTeleportPacket.STREAM_CODEC, PlayerRequestedTeleportPacket.HANDLER); + + main.playToClient(SyncRoomMetadataPacket.TYPE, SyncRoomMetadataPacket.STREAM_CODEC, SyncRoomMetadataPacket.HANDLER); + + main.playToServer(PlayerRequestedLeavePacket.TYPE, StreamCodec.unit(new PlayerRequestedLeavePacket()), PlayerRequestedLeavePacket.HANDLER); + + main.playToServer(PlayerRequestedRoomUIPacket.TYPE, PlayerRequestedRoomUIPacket.STREAM_CODEC, PlayerRequestedRoomUIPacket.HANDLER); + + // TODO Upgrades main.playToServer(PlayerRequestedUpgradeUIPacket.TYPE, PlayerRequestedUpgradeUIPacket.STREAM_CODEC, PlayerRequestedUpgradeUIPacket.HANDLER); + + main.playToClient(MachineColorSyncPacket.TYPE, MachineColorSyncPacket.STREAM_CODEC, MachineColorSyncPacket.HANDLER); + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/machines/room/RoomRegistrar.java b/neoforge-main/src/main/java/dev/compactmods/machines/room/RoomRegistrar.java index c157ff05..dcf161dc 100644 --- a/neoforge-main/src/main/java/dev/compactmods/machines/room/RoomRegistrar.java +++ b/neoforge-main/src/main/java/dev/compactmods/machines/room/RoomRegistrar.java @@ -1,129 +1,130 @@ -package dev.compactmods.machines.room; - -import com.mojang.serialization.Codec; -import dev.compactmods.machines.api.CompactMachines; -import dev.compactmods.machines.api.room.data.CMRoomDataLocations; -import dev.compactmods.machines.data.CMDataFile; -import dev.compactmods.machines.api.room.RoomInstance; -import dev.compactmods.machines.api.room.RoomTemplate; -import dev.compactmods.machines.api.room.registration.IRoomRegistrar; -import dev.compactmods.machines.api.room.registration.IRoomBuilder; -import dev.compactmods.feather.MemoryGraph; -import dev.compactmods.machines.api.util.AABBAligner; -import dev.compactmods.machines.data.CodecHolder; -import dev.compactmods.machines.room.graph.node.RoomRegistrationNode; -import dev.compactmods.machines.util.MathUtil; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.phys.AABB; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; - -import java.nio.file.Path; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.function.Consumer; -import java.util.stream.Stream; - -public class RoomRegistrar implements IRoomRegistrar, CodecHolder, CMDataFile { - - public static final Logger LOGS = LogManager.getLogger(); - - public static final Codec CODEC = RoomRegistrationNode.CODEC.listOf() - .fieldOf("rooms") - .xmap(RoomRegistrar::new, (RoomRegistrar x) -> List.copyOf(x.registrationNodes.values())) - .codec(); - private final MemoryGraph graph; - private final Map registrationNodes; - - public RoomRegistrar() { - this.graph = new MemoryGraph(); - this.registrationNodes = new HashMap<>(); - } - - private RoomRegistrar(List regNodes) { - this(); - regNodes.forEach(this::registerDirty); - } - - @Override - public IRoomBuilder builder() { - return new NewRoomBuilder(); - } - - @Override - public AABB getNextBoundaries(RoomTemplate template) { - final var region = MathUtil.getRegionPositionByIndex(registrationNodes.size()); - final var floor = MathUtil.getCenterWithY(region, 0); - - return AABBAligner.floor(template.getZeroBoundaries().move(floor), 0); - } - - @Override - public RoomInstance createNew(RoomTemplate template, UUID owner, Consumer override) { - final var inst = IRoomRegistrar.super.createNew(template, owner, override); - - var node = new RoomRegistrationNode(UUID.randomUUID(), new RoomRegistrationNode.Data(inst)); - this.registrationNodes.put(inst.code(), node); - this.graph.addNode(node); - - CompactMachines.roomApi().chunkManager().calculateChunks(inst.code(), node); - - return inst; - } - - @Override - public boolean isRegistered(String room) { - return registrationNodes.containsKey(room); - } - - @Override - public Optional get(String room) { - final var regNode = registrationNodes.get(room); - if (regNode == null) - return Optional.empty(); - - RoomInstance inst = makeRoomInstance(regNode); - return Optional.of(inst); - } - - @NotNull - private static RoomInstance makeRoomInstance(RoomRegistrationNode regNode) { - return new RoomInstance(regNode.code(), regNode.defaultMachineColor(), regNode); - } - - @Override - public long count() { - return registrationNodes.size(); - } - - @Override - public Stream allRoomCodes() { - return registrationNodes.keySet().stream(); - } - - @Override - public Stream allRooms() { - return registrationNodes.values() - .stream() - .map(RoomRegistrar::makeRoomInstance); - } - - private void registerDirty(RoomRegistrationNode node) { - registrationNodes.putIfAbsent(node.code(), node); - graph.addNode(node); - } - - @Override - public Path getDataLocation(MinecraftServer server) { - return CMRoomDataLocations.REGISTRATION_DATA.apply(server); - } - - @Override - public Codec codec() { - return CODEC; - } -} +package dev.compactmods.machines.room; + +import com.mojang.serialization.Codec; +import dev.compactmods.machines.api.CompactMachines; +import dev.compactmods.machines.api.room.data.CMRoomDataLocations; +import dev.compactmods.machines.data.CMDataFile; +import dev.compactmods.machines.api.room.RoomInstance; +import dev.compactmods.machines.api.room.RoomTemplate; +import dev.compactmods.machines.api.room.registration.IRoomRegistrar; +import dev.compactmods.machines.api.room.registration.IRoomBuilder; +import dev.compactmods.feather.MemoryGraph; +import dev.compactmods.machines.api.util.AABBAligner; +import dev.compactmods.machines.data.CodecHolder; +import dev.compactmods.machines.room.graph.node.RoomRegistrationNode; +import dev.compactmods.machines.util.MathUtil; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.phys.AABB; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.NotNull; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.stream.Stream; + +public class RoomRegistrar implements IRoomRegistrar, CodecHolder, CMDataFile { + + public static final Logger LOGS = LogManager.getLogger(); + + public static final Codec CODEC = RoomRegistrationNode.CODEC.listOf() + .fieldOf("rooms") + .xmap(RoomRegistrar::new, (RoomRegistrar x) -> List.copyOf(x.registrationNodes.values())) + .codec(); + + private final MemoryGraph graph; + private final Map registrationNodes; + + public RoomRegistrar() { + this.graph = new MemoryGraph(); + this.registrationNodes = new HashMap<>(); + } + + private RoomRegistrar(List regNodes) { + this(); + regNodes.forEach(this::registerDirty); + } + + @Override + public IRoomBuilder builder() { + return new NewRoomBuilder(); + } + + @Override + public AABB getNextBoundaries(RoomTemplate template) { + final var region = MathUtil.getRegionPositionByIndex(registrationNodes.size()); + final var floor = MathUtil.getCenterWithY(region, 0); + + return AABBAligner.floor(template.getZeroBoundaries().move(floor), 0); + } + + @Override + public RoomInstance createNew(RoomTemplate template, UUID owner, Consumer override) { + final var inst = IRoomRegistrar.super.createNew(template, owner, override); + + var node = new RoomRegistrationNode(UUID.randomUUID(), new RoomRegistrationNode.Data(inst)); + this.registrationNodes.put(inst.code(), node); + this.graph.addNode(node); + + CompactMachines.roomApi().chunkManager().calculateChunks(inst.code(), node); + + return inst; + } + + @Override + public boolean isRegistered(String room) { + return registrationNodes.containsKey(room); + } + + @Override + public Optional get(String room) { + final var regNode = registrationNodes.get(room); + if (regNode == null) + return Optional.empty(); + + RoomInstance inst = makeRoomInstance(regNode); + return Optional.of(inst); + } + + @NotNull + private static RoomInstance makeRoomInstance(RoomRegistrationNode regNode) { + return new RoomInstance(regNode.code(), regNode.defaultMachineColor(), regNode); + } + + @Override + public long count() { + return registrationNodes.size(); + } + + @Override + public Stream allRoomCodes() { + return registrationNodes.keySet().stream(); + } + + @Override + public Stream allRooms() { + return registrationNodes.values() + .stream() + .map(RoomRegistrar::makeRoomInstance); + } + + private void registerDirty(RoomRegistrationNode node) { + registrationNodes.putIfAbsent(node.code(), node); + graph.addNode(node); + } + + @Override + public Path getDataLocation(MinecraftServer server) { + return CMRoomDataLocations.REGISTRATION_DATA.apply(server); + } + + @Override + public Codec codec() { + return CODEC; + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/machines/room/ui/preview/MachineRoomScreen.java b/neoforge-main/src/main/java/dev/compactmods/machines/room/ui/preview/MachineRoomScreen.java index 1882e5cc..0a9e43ca 100644 --- a/neoforge-main/src/main/java/dev/compactmods/machines/room/ui/preview/MachineRoomScreen.java +++ b/neoforge-main/src/main/java/dev/compactmods/machines/room/ui/preview/MachineRoomScreen.java @@ -1,274 +1,274 @@ -package dev.compactmods.machines.room.ui.preview; - -import dev.compactmods.machines.api.CompactMachines; -import dev.compactmods.machines.client.render.NineSliceRenderer; -import dev.compactmods.machines.client.widget.ImageButtonBuilder; -import dev.compactmods.machines.network.PlayerRequestedTeleportPacket; -import dev.compactmods.machines.network.PlayerRequestedUpgradeUIPacket; -import dev.compactmods.machines.shrinking.Shrinking; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.components.ImageButton; -import net.minecraft.client.gui.components.WidgetSprites; -import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; -import net.minecraft.core.GlobalPos; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.ItemStack; -import net.neoforged.neoforge.network.PacketDistributor; - -public class MachineRoomScreen extends AbstractContainerScreen { - - private final Inventory inv; - protected double rotateX = 45.0f; - protected double rotateY = 20.0f; - - private ImageButton psdButton; - - public MachineRoomScreen(MachineRoomMenu menu, Inventory inv, Component title) { - super(menu, inv, title); - this.imageWidth = 248; - this.imageHeight = 239; - this.titleLabelY = 5; - this.inv = inv; - - // Send packet to server for block data - // RoomNetworkHandler.CHANNEL.sendToServer(new PlayerStartedRoomTrackingPacket(menu.getRoom())); - // updateBlockRender(); - } - - @Override - protected void init() { - super.init(); - - final var psdBtnSprites = new WidgetSprites( - CompactMachines.modRL("personal_shrinking_device"), - CompactMachines.modRL("personal_shrinking_device_disabled"), - CompactMachines.modRL("personal_shrinking_device_highlighted"), - CompactMachines.modRL("personal_shrinking_device_disabled")); - - this.psdButton = ImageButtonBuilder.button(psdBtnSprites) - .size(12, 12) - .location(leftPos + imageWidth - 12, topPos + 212) - .onPress(btn -> { - var room = menu.getRoom(); - PacketDistributor.sendToServer(new PlayerRequestedTeleportPacket(menu.getMachine(), room)); - }).build(); - - addRenderableWidget(psdButton); - - final var upgradeBtnSprites = new WidgetSprites( - CompactMachines.modRL("upgrade_btn"), - CompactMachines.modRL("upgrade_btn") - ); - - var upgradeScreenBtn = ImageButtonBuilder.button(upgradeBtnSprites) - .size(12, 12) - .location(leftPos + imageWidth - 24, topPos + 212) - .onPress(btn -> { - PacketDistributor.sendToServer(new PlayerRequestedUpgradeUIPacket(menu.getRoom(), false)); - }).build(); - - addRenderableWidget(upgradeScreenBtn); - } - - @Override - protected void renderBg(GuiGraphics graphics, float v, int i, int i1) { - var backgroundRenderer = NineSliceRenderer.builder(CompactMachines.modRL("textures/gui/psd_screen_9slice.png")) - .area(0, 0, 248, 210) - .uv(32, 32) - .sliceSize(4, 4) - .textureSize(32, 32) - .build(); - - final var pose = graphics.pose(); - - pose.pushPose(); - pose.translate(leftPos, topPos, 0); - backgroundRenderer.render(graphics); - pose.popPose(); - } - - public void updateBlockRender() { - var struct = menu.getBlocks(); -// this.renderer = new RenderingLevel(struct); - } - - private boolean hasPsdItem() { - final var inInv = inv.contains(new ItemStack(Shrinking.PERSONAL_SHRINKING_DEVICE.get())); -// if (ModList.get().isLoaded("curios") && CuriosCompat.hasPsdCurio(inv.player)) -// return true; - - return inInv; - } - - @Override - protected void containerTick() { - super.containerTick(); - psdButton.active = this.inv.player.isCreative() || hasPsdItem(); - } - - @Override - public boolean mouseDragged(double mx, double my, int mButton, double dx, double dy) { - var s = super.mouseDragged(mx, my, mButton, dx, dy); - if (!s) return false; - - rotateX += dx; - rotateY += dy; - return true; - } - - @Override - protected void renderLabels(GuiGraphics graphics, int p_282681_, int p_283686_) { - final var pose = graphics.pose(); - pose.pushPose(); - pose.translate(0, 0, 500); - - pose.translate(this.imageWidth / 2f, 0, 0); - - var p = Component.literal(menu.getRoomName()); - graphics.drawCenteredString(font, p, 0, this.titleLabelY, 0xFFFFFFFF); - - var room = menu.getRoom(); - var rt = Component.literal(room); - pose.scale(0.7f, 0.7f, 0.7f); - graphics.drawCenteredString(font, rt, 0, this.titleLabelY + font.lineHeight + 7, 0xFFDEDEDE); - pose.popPose(); - } - - @Override - public void render(GuiGraphics graphics, int pMouseX, int pMouseY, float pPartialTick) { - super.render(graphics, pMouseX, pMouseY, pPartialTick); - - final var pose = graphics.pose(); - pose.pushPose(); - pose.translate(leftPos, topPos, 0); - pose.translate(this.imageWidth / 2f, 0, 0); - - graphics.drawCenteredString(font, Component.literal("Room preview broken for a bit"), 0, 100, 0xFFCCCCCC); - - pose.popPose(); - } - - @Override - public void onClose() { - super.onClose(); - } - - // @Override -// public void render(PoseStack pose, int mouseX, int mouseY, float partial) { -// this.renderBackground(pose); -// super.render(pose, mouseX, mouseY, partial); -// -// var buffer = SuperRenderTypeBuffer.getInstance(); -// -// RenderSystem.enableBlend(); -// RenderSystem.enableDepthTest(); -// RenderSystem.backupProjectionMatrix(); -// -// // has to be outside of MS transforms, important for vertex sorting -// Matrix4f matrix4f = new Matrix4f(RenderSystem.getProjectionMatrix()); -// matrix4f.multiplyWithTranslation(0, 0, 800); -// RenderSystem.setProjectionMatrix(matrix4f); -// -// PoseStack.Pose lastEntryBeforeTry = pose.last(); -// -// var cam = minecraft.cameraEntity; -// -// if (this.menu.loadingBlocks) { -// pose.pushPose(); -// Screen.drawCenteredString(pose, font, "Loading preview...", 0, this.titleLabelY + font.lineHeight + 2, 0xFFCCCCCC); -// pose.popPose(); -// } else { -// try { -// pose.pushPose(); -// pose.translate(0, 0, -800); -// -// final var blockRenderer = Minecraft.getInstance().getBlockRenderer(); -// final var beRenderer = Minecraft.getInstance().getBlockEntityRenderDispatcher(); -// -// var struct = menu.getBlocks(); -// -// pose.pushPose(); -// { -// // pose.translate(s, s, s); -// -// pose.translate(getGuiLeft() + (getXSize() / 2d), getGuiTop() + 135, 150); -// -// float zoom = switch (struct.getSize().getX()) { -// case 3 -> 23.5f; -// case 5 -> 19.5f; -// case 7 -> 15.5f; -// case 9 -> 14.5f; -// case 11 -> 11.5f; -// case 13 -> 10.5f; -// default -> 10.5f; -// }; -// -// pose.scale(zoom, -zoom, zoom); -// -// pose.mulPose(Vector3f.XP.rotationDegrees((float) rotateY)); -// pose.mulPose(Vector3f.YP.rotationDegrees((float) rotateX)); -// -// final var tSize = struct.getSize(); -// final float s = tSize.getX() / 2f; -// pose.translate(-s, -s + 1, -s); -// -// final var transformer = new TransformingVertexBuilder(buffer, RenderTypes.WALLS); -// -// var bb = struct.getBoundingBox(new StructurePlaceSettings(), BlockPos.ZERO); -// -// var as = new ArmorStand(renderer, 0, 0, 0); -// minecraft.cameraEntity = as; -// -// BlockPos.betweenClosedStream(bb).forEach(pos -> { -// pose.pushPose(); -// { -// pose.translate(pos.getX(), pos.getY(), pos.getZ()); -// -// final var state = renderer.getBlockState(pos); -// transformer.setOverlay(OverlayTexture.RED_OVERLAY_V); -// -// ModelData modelData = ModelData.EMPTY; -// if (state.hasBlockEntity()) { -// final var be = renderer.getBlockEntity(pos); -// if (be != null) { -// modelData = be.getModelData(); -// final var ber = beRenderer.getRenderer(be); -// if (ber != null) { -// ber.render(be, 1f, pose, buffer, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY); -// } -// } -// } -// -// try { -// pose.pushPose(); -// -// for (var type : blockRenderer.getBlockModel(state).getRenderTypes(state, minecraft.level.random, modelData)) { -// blockRenderer.renderBatched(state, pos, renderer, pose, buffer.getBuffer(type), true, renderer.random, modelData, type); -// } -// -// pose.popPose(); -// } catch (Exception e) { -// } -// } -// pose.popPose(); -// }); -// } -// pose.popPose(); -// pose.popPose(); -// } catch (Exception e) { -// while (lastEntryBeforeTry != pose.last()) -// pose.popPose(); -// } -// -// minecraft.cameraEntity = cam; -// -// buffer.draw(); -// RenderSystem.restoreProjectionMatrix(); -// } -// } - - public GlobalPos getMachine() { - return menu.getMachine(); - } -} +package dev.compactmods.machines.room.ui.preview; + +import dev.compactmods.machines.api.CompactMachines; +import dev.compactmods.machines.client.render.NineSliceRenderer; +import dev.compactmods.machines.client.widget.ImageButtonBuilder; +import dev.compactmods.machines.network.PlayerRequestedTeleportPacket; +import dev.compactmods.machines.network.PlayerRequestedUpgradeUIPacket; +import dev.compactmods.machines.shrinking.Shrinking; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.ImageButton; +import net.minecraft.client.gui.components.WidgetSprites; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.core.GlobalPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.network.PacketDistributor; + +public class MachineRoomScreen extends AbstractContainerScreen { + + private final Inventory inv; + protected double rotateX = 45.0f; + protected double rotateY = 20.0f; + + private ImageButton psdButton; + + public MachineRoomScreen(MachineRoomMenu menu, Inventory inv, Component title) { + super(menu, inv, title); + this.imageWidth = 248; + this.imageHeight = 239; + this.titleLabelY = 5; + this.inv = inv; + + // Send packet to server for block data + // RoomNetworkHandler.CHANNEL.sendToServer(new PlayerStartedRoomTrackingPacket(menu.getRoom())); + // updateBlockRender(); + } + + @Override + protected void init() { + super.init(); + + final var psdBtnSprites = new WidgetSprites( + CompactMachines.modRL("personal_shrinking_device"), + CompactMachines.modRL("personal_shrinking_device_disabled"), + CompactMachines.modRL("personal_shrinking_device_highlighted"), + CompactMachines.modRL("personal_shrinking_device_disabled")); + + this.psdButton = ImageButtonBuilder.button(psdBtnSprites) + .size(12, 12) + .location(leftPos + imageWidth - 12, topPos + 212) + .onPress(btn -> { + var room = menu.getRoom(); + PacketDistributor.sendToServer(new PlayerRequestedTeleportPacket(menu.getMachine(), room)); + }).build(); + + addRenderableWidget(psdButton); + + final var upgradeBtnSprites = new WidgetSprites( + CompactMachines.modRL("upgrade_btn"), + CompactMachines.modRL("upgrade_btn") + ); + + var upgradeScreenBtn = ImageButtonBuilder.button(upgradeBtnSprites) + .size(12, 12) + .location(leftPos + imageWidth - 24, topPos + 212) + .onPress(btn -> { + PacketDistributor.sendToServer(new PlayerRequestedUpgradeUIPacket(menu.getRoom(), false)); + }).build(); + +// addRenderableWidget(upgradeScreenBtn); + } + + @Override + protected void renderBg(GuiGraphics graphics, float v, int i, int i1) { + var backgroundRenderer = NineSliceRenderer.builder(CompactMachines.modRL("textures/gui/psd_screen_9slice.png")) + .area(0, 0, 248, 210) + .uv(32, 32) + .sliceSize(4, 4) + .textureSize(32, 32) + .build(); + + final var pose = graphics.pose(); + + pose.pushPose(); + pose.translate(leftPos, topPos, 0); + backgroundRenderer.render(graphics); + pose.popPose(); + } + + public void updateBlockRender() { + var struct = menu.getBlocks(); +// this.renderer = new RenderingLevel(struct); + } + + private boolean hasPsdItem() { + final var inInv = inv.contains(new ItemStack(Shrinking.PERSONAL_SHRINKING_DEVICE.get())); +// if (ModList.get().isLoaded("curios") && CuriosCompat.hasPsdCurio(inv.player)) +// return true; + + return inInv; + } + + @Override + protected void containerTick() { + super.containerTick(); + psdButton.active = this.inv.player.isCreative() || hasPsdItem(); + } + + @Override + public boolean mouseDragged(double mx, double my, int mButton, double dx, double dy) { + var s = super.mouseDragged(mx, my, mButton, dx, dy); + if (!s) return false; + + rotateX += dx; + rotateY += dy; + return true; + } + + @Override + protected void renderLabels(GuiGraphics graphics, int p_282681_, int p_283686_) { + final var pose = graphics.pose(); + pose.pushPose(); + pose.translate(0, 0, 500); + + pose.translate(this.imageWidth / 2f, 0, 0); + + var p = Component.literal(menu.getRoomName()); + graphics.drawCenteredString(font, p, 0, this.titleLabelY, 0xFFFFFFFF); + + var room = menu.getRoom(); + var rt = Component.literal(room); + pose.scale(0.7f, 0.7f, 0.7f); + graphics.drawCenteredString(font, rt, 0, this.titleLabelY + font.lineHeight + 7, 0xFFDEDEDE); + pose.popPose(); + } + + @Override + public void render(GuiGraphics graphics, int pMouseX, int pMouseY, float pPartialTick) { + super.render(graphics, pMouseX, pMouseY, pPartialTick); + + final var pose = graphics.pose(); + pose.pushPose(); + pose.translate(leftPos, topPos, 0); + pose.translate(this.imageWidth / 2f, 0, 0); + + graphics.drawCenteredString(font, Component.literal("Room preview broken for a bit"), 0, 100, 0xFFCCCCCC); + + pose.popPose(); + } + + @Override + public void onClose() { + super.onClose(); + } + + // @Override +// public void render(PoseStack pose, int mouseX, int mouseY, float partial) { +// this.renderBackground(pose); +// super.render(pose, mouseX, mouseY, partial); +// +// var buffer = SuperRenderTypeBuffer.getInstance(); +// +// RenderSystem.enableBlend(); +// RenderSystem.enableDepthTest(); +// RenderSystem.backupProjectionMatrix(); +// +// // has to be outside of MS transforms, important for vertex sorting +// Matrix4f matrix4f = new Matrix4f(RenderSystem.getProjectionMatrix()); +// matrix4f.multiplyWithTranslation(0, 0, 800); +// RenderSystem.setProjectionMatrix(matrix4f); +// +// PoseStack.Pose lastEntryBeforeTry = pose.last(); +// +// var cam = minecraft.cameraEntity; +// +// if (this.menu.loadingBlocks) { +// pose.pushPose(); +// Screen.drawCenteredString(pose, font, "Loading preview...", 0, this.titleLabelY + font.lineHeight + 2, 0xFFCCCCCC); +// pose.popPose(); +// } else { +// try { +// pose.pushPose(); +// pose.translate(0, 0, -800); +// +// final var blockRenderer = Minecraft.getInstance().getBlockRenderer(); +// final var beRenderer = Minecraft.getInstance().getBlockEntityRenderDispatcher(); +// +// var struct = menu.getBlocks(); +// +// pose.pushPose(); +// { +// // pose.translate(s, s, s); +// +// pose.translate(getGuiLeft() + (getXSize() / 2d), getGuiTop() + 135, 150); +// +// float zoom = switch (struct.getSize().getX()) { +// case 3 -> 23.5f; +// case 5 -> 19.5f; +// case 7 -> 15.5f; +// case 9 -> 14.5f; +// case 11 -> 11.5f; +// case 13 -> 10.5f; +// default -> 10.5f; +// }; +// +// pose.scale(zoom, -zoom, zoom); +// +// pose.mulPose(Vector3f.XP.rotationDegrees((float) rotateY)); +// pose.mulPose(Vector3f.YP.rotationDegrees((float) rotateX)); +// +// final var tSize = struct.getSize(); +// final float s = tSize.getX() / 2f; +// pose.translate(-s, -s + 1, -s); +// +// final var transformer = new TransformingVertexBuilder(buffer, RenderTypes.WALLS); +// +// var bb = struct.getBoundingBox(new StructurePlaceSettings(), BlockPos.ZERO); +// +// var as = new ArmorStand(renderer, 0, 0, 0); +// minecraft.cameraEntity = as; +// +// BlockPos.betweenClosedStream(bb).forEach(pos -> { +// pose.pushPose(); +// { +// pose.translate(pos.getX(), pos.getY(), pos.getZ()); +// +// final var state = renderer.getBlockState(pos); +// transformer.setOverlay(OverlayTexture.RED_OVERLAY_V); +// +// ModelData modelData = ModelData.EMPTY; +// if (state.hasBlockEntity()) { +// final var be = renderer.getBlockEntity(pos); +// if (be != null) { +// modelData = be.getModelData(); +// final var ber = beRenderer.getRenderer(be); +// if (ber != null) { +// ber.render(be, 1f, pose, buffer, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY); +// } +// } +// } +// +// try { +// pose.pushPose(); +// +// for (var type : blockRenderer.getBlockModel(state).getRenderTypes(state, minecraft.level.random, modelData)) { +// blockRenderer.renderBatched(state, pos, renderer, pose, buffer.getBuffer(type), true, renderer.random, modelData, type); +// } +// +// pose.popPose(); +// } catch (Exception e) { +// } +// } +// pose.popPose(); +// }); +// } +// pose.popPose(); +// pose.popPose(); +// } catch (Exception e) { +// while (lastEntryBeforeTry != pose.last()) +// pose.popPose(); +// } +// +// minecraft.cameraEntity = cam; +// +// buffer.draw(); +// RenderSystem.restoreProjectionMatrix(); +// } +// } + + public GlobalPos getMachine() { + return menu.getMachine(); + } +} diff --git a/neoforge-main/src/main/java/dev/compactmods/machines/room/upgrade/RoomUpgradeEventHandlers.java b/neoforge-main/src/main/java/dev/compactmods/machines/room/upgrade/RoomUpgradeEventHandlers.java index 8915c4b5..1b71bf09 100644 --- a/neoforge-main/src/main/java/dev/compactmods/machines/room/upgrade/RoomUpgradeEventHandlers.java +++ b/neoforge-main/src/main/java/dev/compactmods/machines/room/upgrade/RoomUpgradeEventHandlers.java @@ -1,57 +1,58 @@ -package dev.compactmods.machines.room.upgrade; - -import dev.compactmods.machines.api.CompactMachines; -import dev.compactmods.machines.api.dimension.CompactDimension; -import dev.compactmods.machines.api.room.upgrade.events.lifecycle.UpgradeTickedEventListener; -import dev.compactmods.machines.room.Rooms; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent; -import net.neoforged.neoforge.event.tick.LevelTickEvent; - -import java.util.function.Consumer; -import java.util.stream.Collectors; - -public class RoomUpgradeEventHandlers { - - public static void onLevelTick(LevelTickEvent.Post postTick) { - if (postTick.getLevel() instanceof ServerLevel serverLevel && CompactDimension.isLevelCompact(serverLevel)) { - final var rooms = CompactMachines.roomApi() - .registrar() - .allRooms() - .collect(Collectors.toUnmodifiableSet()); - - for (var room : rooms) { - CompactMachines.existingRoomData(room.code()) - .flatMap(rd -> rd.getExistingData(Rooms.DataAttachments.UPGRADE_INV)) - .ifPresent(appliedUpgrades -> { - final var upgradeStacks = appliedUpgrades.items() - .collect(Collectors.toUnmodifiableSet()); - - for (final var upgradeStack : upgradeStacks) { - final var upgrades = upgradeStack.get(RoomUpgrades.UPGRADE_LIST_COMPONENT); - upgrades.upgrades().stream() - .flatMap(ru -> ru.gatherEvents().filter(UpgradeTickedEventListener.class::isInstance)) - .map(UpgradeTickedEventListener.class::cast) - .forEach(ticker -> { - ticker.handle(serverLevel, room, upgradeStack); - }); - } - }); - } - } - } - - public static void onTooltips(ItemTooltipEvent evt) { - Item.TooltipContext ctx = evt.getContext(); - Consumer tooltips = evt.getToolTip()::add; - TooltipFlag flags = evt.getFlags(); - - ItemStack stack = evt.getItemStack(); - - stack.addToTooltip(RoomUpgrades.UPGRADE_LIST_COMPONENT, ctx, tooltips, flags); - } -} +package dev.compactmods.machines.room.upgrade; + +import dev.compactmods.machines.api.CompactMachines; +import dev.compactmods.machines.api.dimension.CompactDimension; +import dev.compactmods.machines.api.room.upgrade.events.lifecycle.UpgradeTickedEventListener; +import dev.compactmods.machines.room.Rooms; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent; +import net.neoforged.neoforge.event.tick.LevelTickEvent; + +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public class RoomUpgradeEventHandlers { + + public static void onLevelTick(LevelTickEvent.Post postTick) { + if (postTick.getLevel() instanceof ServerLevel serverLevel && CompactDimension.isLevelCompact(serverLevel)) { + final var rooms = CompactMachines.roomApi() + .registrar() + .allRooms() + .collect(Collectors.toUnmodifiableSet()); + + for (var room : rooms) { + CompactMachines.existingRoomData(room.code()) + .flatMap(rd -> rd.getExistingData(Rooms.DataAttachments.UPGRADE_INV)) + .ifPresent(appliedUpgrades -> { + final var upgradeStacks = appliedUpgrades.items() + .collect(Collectors.toUnmodifiableSet()); + + for (final var upgradeStack : upgradeStacks) { + final var upgrades = upgradeStack.get(RoomUpgrades.UPGRADE_LIST_COMPONENT); + upgrades.upgrades() + .stream() + .flatMap(ru -> ru.gatherEvents().filter(UpgradeTickedEventListener.class::isInstance)) + .map(UpgradeTickedEventListener.class::cast) + .forEach(ticker -> { + ticker.handle(serverLevel, room, upgradeStack); + }); + } + }); + } + } + } + + public static void onTooltips(ItemTooltipEvent evt) { + Item.TooltipContext ctx = evt.getContext(); + Consumer tooltips = evt.getToolTip()::add; + TooltipFlag flags = evt.getFlags(); + + ItemStack stack = evt.getItemStack(); + + stack.addToTooltip(RoomUpgrades.UPGRADE_LIST_COMPONENT, ctx, tooltips, flags); + } +} diff --git a/neoforge-main/src/test/java/dev/compactmods/machines/test/junit/AABBHelperTests.java b/neoforge-main/src/test/java/dev/compactmods/machines/test/junit/AABBHelperTests.java index 1776c303..0a7b8c8e 100644 --- a/neoforge-main/src/test/java/dev/compactmods/machines/test/junit/AABBHelperTests.java +++ b/neoforge-main/src/test/java/dev/compactmods/machines/test/junit/AABBHelperTests.java @@ -1,112 +1,128 @@ -package dev.compactmods.machines.test.junit; - - -import com.google.common.math.DoubleMath; -import dev.compactmods.machines.api.util.AABBAligner; -import dev.compactmods.machines.api.util.AABBHelper; -import dev.compactmods.machines.util.RandomSourceUtil; -import net.minecraft.core.Direction; -import net.minecraft.util.RandomSource; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.neoforged.testframework.junit.EphemeralTestServerProvider; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DynamicTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestFactory; -import org.junit.jupiter.api.extension.ExtendWith; - -import java.util.Collection; -import java.util.stream.Stream; - -@ExtendWith(EphemeralTestServerProvider.class) -public class AABBHelperTests { - - @Test - public void canFloorToY0() { - // Source minY = 5 - AABB before = AABB.ofSize(new Vec3(0, 7.5, 0), 5, 5, 5); - - // Align to Y-0 - final var after = AABBAligner.floor(before, 0); - - Assertions.assertEquals(5, before.minY, "Before was modified in-place rather than immutably moved."); - Assertions.assertEquals(0, after.minY, "After y level should be zero. (was: %s)".formatted(after.minY)); - Assertions.assertEquals(5, after.getYsize(), "AABB size was modified; should have remained the same."); - } - - @Test - public void canFloorToAnotherAABB() { - // Source minY = 5 - AABB before = AABB.ofSize(Vec3.ZERO.relative(Direction.UP, 7.5), 5, 5, 5); - - // Target minY = 1 (bounds are Y 1-11) - AABB bounds = AABB.ofSize(Vec3.ZERO.relative(Direction.UP, 6), 10, 10, 10); - - // Align to Y-0 - final var after = AABBAligner.floor(before, bounds); - - Assertions.assertEquals(5, before.minY, "Before was modified in-place rather than immutably moved."); - Assertions.assertEquals(1, after.minY, "After y level should be 1. (was: %s)".formatted(after.minY)); - - Assertions.assertEquals(5, after.getYsize(), "AABB size was modified; should have remained the same."); - } - - @Test - public void normalizeToZero() { - AABB before = AABB.ofSize(Vec3.ZERO.relative(Direction.UP, 7.5), 5, 5, 5); - - // Align to Y-0 - final var after = AABBHelper.normalize(before); - - Assertions.assertEquals(5, before.minY, "Before was modified in-place rather than immutably moved."); - - Assertions.assertEquals(0, after.minX, "After x level was not zero (was: %s)".formatted(after.minX)); - Assertions.assertEquals(0, after.minY, "After y level was not zero (was: %s)".formatted(after.minY)); - Assertions.assertEquals(0, after.minZ, "After z level was not zero (was: %s)".formatted(after.minZ)); - - Assertions.assertEquals(5, after.getYsize(), "AABB size was modified; should have remained the same."); - } - - @TestFactory - public static Collection normalizeBoundaryTests() { - final var random = RandomSource.create(); - return Stream.concat( - RandomSourceUtil.randomVec3Stream(random).limit(10), - - // Ensure at least one negative and one positive bound are part of the test - Stream.of( - Vec3.ZERO.subtract(-3, -2, 5), - Vec3.ZERO.add(2, 5, 1) - ) - ).map(randomOffset -> DynamicTest.dynamicTest( - "normalize_boundaries_%s".formatted(randomOffset.hashCode()), - () -> normalizeIntoBoundaries(randomOffset) - )) - .toList(); - } - - private static void assertVec3Equals(Vec3 actual, Vec3 expected) { - Assertions.assertTrue(DoubleMath.fuzzyEquals(actual.x, expected.x, 0.001), - "X did not match expected value (was: %s; expected: %s)".formatted(actual.x, expected.x)); - - Assertions.assertTrue(DoubleMath.fuzzyEquals(actual.y, expected.y, 0.001), - "Y did not match expected value (was: %s; expected: %s)".formatted(actual.y, expected.y)); - - Assertions.assertTrue(DoubleMath.fuzzyEquals(actual.z, expected.z, 0.001), - "Z did not match expected value (was: %s; expected: %s)".formatted(actual.z, expected.z)); - } - - public static void normalizeIntoBoundaries(Vec3 randomOffset) { - AABB before = AABB.ofSize(Vec3.ZERO.relative(Direction.UP, 7.5), 5, 5, 5); - AABB bounds = AABB.ofSize(randomOffset, 5, 5, 5); - - final var after = AABBHelper.normalizeWithin(before, bounds); - - Assertions.assertEquals(5, before.minY, "Before was modified in-place rather than immutably moved."); - - assertVec3Equals(AABBHelper.minCorner(after), AABBHelper.minCorner(bounds)); - - Assertions.assertEquals(5, after.getYsize(), "AABB size was modified; should have remained the same."); - } -} +package dev.compactmods.machines.test.junit; + + +import com.google.common.base.Predicates; +import com.google.common.math.DoubleMath; +import dev.compactmods.machines.api.util.AABBAligner; +import dev.compactmods.machines.api.util.AABBHelper; +import dev.compactmods.machines.util.RandomSourceUtil; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.neoforged.neoforge.items.ItemStackHandler; +import net.neoforged.testframework.junit.EphemeralTestServerProvider; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestFactory; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.util.Collection; +import java.util.function.Predicate; +import java.util.stream.Stream; + +@ExtendWith(EphemeralTestServerProvider.class) +public class AABBHelperTests { + + private static class MyThing extends ItemStackHandler { + public MyThing(final int size) { + super(size); + } + + boolean isEmpty() { + return stacks.stream().allMatch(ItemStack::isEmpty); + } + } + + @Test + public void canFloorToY0() { + Predicate empty = Predicates.not(MyThing::isEmpty); + + // Source minY = 5 + AABB before = AABB.ofSize(new Vec3(0, 7.5, 0), 5, 5, 5); + + // Align to Y-0 + final var after = AABBAligner.floor(before, 0); + + Assertions.assertEquals(5, before.minY, "Before was modified in-place rather than immutably moved."); + Assertions.assertEquals(0, after.minY, "After y level should be zero. (was: %s)".formatted(after.minY)); + Assertions.assertEquals(5, after.getYsize(), "AABB size was modified; should have remained the same."); + } + + @Test + public void canFloorToAnotherAABB() { + // Source minY = 5 + AABB before = AABB.ofSize(Vec3.ZERO.relative(Direction.UP, 7.5), 5, 5, 5); + + // Target minY = 1 (bounds are Y 1-11) + AABB bounds = AABB.ofSize(Vec3.ZERO.relative(Direction.UP, 6), 10, 10, 10); + + // Align to Y-0 + final var after = AABBAligner.floor(before, bounds); + + Assertions.assertEquals(5, before.minY, "Before was modified in-place rather than immutably moved."); + Assertions.assertEquals(1, after.minY, "After y level should be 1. (was: %s)".formatted(after.minY)); + + Assertions.assertEquals(5, after.getYsize(), "AABB size was modified; should have remained the same."); + } + + @Test + public void normalizeToZero() { + AABB before = AABB.ofSize(Vec3.ZERO.relative(Direction.UP, 7.5), 5, 5, 5); + + // Align to Y-0 + final var after = AABBHelper.normalize(before); + + Assertions.assertEquals(5, before.minY, "Before was modified in-place rather than immutably moved."); + + Assertions.assertEquals(0, after.minX, "After x level was not zero (was: %s)".formatted(after.minX)); + Assertions.assertEquals(0, after.minY, "After y level was not zero (was: %s)".formatted(after.minY)); + Assertions.assertEquals(0, after.minZ, "After z level was not zero (was: %s)".formatted(after.minZ)); + + Assertions.assertEquals(5, after.getYsize(), "AABB size was modified; should have remained the same."); + } + + @TestFactory + public static Collection normalizeBoundaryTests() { + final var random = RandomSource.create(); + return Stream.concat( + RandomSourceUtil.randomVec3Stream(random).limit(10), + + // Ensure at least one negative and one positive bound are part of the test + Stream.of( + Vec3.ZERO.subtract(-3, -2, 5), + Vec3.ZERO.add(2, 5, 1) + ) + ).map(randomOffset -> DynamicTest.dynamicTest( + "normalize_boundaries_%s".formatted(randomOffset.hashCode()), + () -> normalizeIntoBoundaries(randomOffset) + )) + .toList(); + } + + private static void assertVec3Equals(Vec3 actual, Vec3 expected) { + Assertions.assertTrue(DoubleMath.fuzzyEquals(actual.x, expected.x, 0.001), + "X did not match expected value (was: %s; expected: %s)".formatted(actual.x, expected.x)); + + Assertions.assertTrue(DoubleMath.fuzzyEquals(actual.y, expected.y, 0.001), + "Y did not match expected value (was: %s; expected: %s)".formatted(actual.y, expected.y)); + + Assertions.assertTrue(DoubleMath.fuzzyEquals(actual.z, expected.z, 0.001), + "Z did not match expected value (was: %s; expected: %s)".formatted(actual.z, expected.z)); + } + + public static void normalizeIntoBoundaries(Vec3 randomOffset) { + AABB before = AABB.ofSize(Vec3.ZERO.relative(Direction.UP, 7.5), 5, 5, 5); + AABB bounds = AABB.ofSize(randomOffset, 5, 5, 5); + + final var after = AABBHelper.normalizeWithin(before, bounds); + + Assertions.assertEquals(5, before.minY, "Before was modified in-place rather than immutably moved."); + + assertVec3Equals(AABBHelper.minCorner(after), AABBHelper.minCorner(bounds)); + + Assertions.assertEquals(5, after.getYsize(), "AABB size was modified; should have remained the same."); + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index fe9198aa..5c428ccb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,91 +1,91 @@ -rootProject.name = "Compact Machines 21.0" - -dependencyResolutionManagement { - versionCatalogs.create("neoforged") { - version("mdg", "0.1.105") - version("neoforge", "21.0.21-beta") - version("neogradle", "7.0.145") - version("neoforgeRange") { - require("[21.0,22)") - prefer("21.0.2-beta") - } - - plugin("moddev", "net.neoforged.moddev") - .versionRef("mdg") - - plugin("userdev", "net.neoforged.gradle.userdev") - .versionRef("neogradle") - - library("neoforge", "net.neoforged", "neoforge") - .versionRef("neoforge") - - library("testframework", "net.neoforged", "testframework") - .versionRef("neoforge") - - bundle("neoforge", listOf("neoforge", "testframework")) - } - - versionCatalogs.create("mojang") { - version("minecraft", "1.20.6") - version("minecraftRange") { - this.require("[1.21, 1.21.1)") - this.prefer("1.21") - } - } - - versionCatalogs.create("libraries") { - library("feather", "dev.compactmods", "feather") - .versionRef("feather") - - library("jnanoid", "com.aventrix.jnanoid", "jnanoid") - .versionRef("jnanoid") - - version("feather", "[0.1.8, 2.0)") - version("jnanoid", "[2.0.0, 3)") - - version("parchment-mc", "1.20.6") - version("parchment", "2024.05.01") - } - - versionCatalogs.create("mods") { - this.library("jei-common", "mezz.jei", "jei-1.20.4-common-api").versionRef("jei") - this.library("jei-neo", "mezz.jei", "jei-1.20.4-neoforge-api").versionRef("jei"); - this.bundle("jei", listOf("jei-common", "jei-neo")) - this.version("jei", "17.3.0.49") - - this.library("jade", "curse.maven", "jade-324717").version("5109393") - } -} - -pluginManagement { - plugins { - id("idea") - id("eclipse") - id("maven-publish") - } - - repositories { - mavenLocal() - mavenCentral() - gradlePluginPortal() - - // maven("https://maven.architectury.dev/") - -// maven("https://maven.parchmentmc.org") { -// name = "ParchmentMC" -// } - - maven("https://maven.neoforged.net/releases") { - name = "NeoForged" - } - } -} - -plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version ("0.8.0") -} - -include(":core-api") -include(":neoforge-main") -include(":neoforge-datagen") - +rootProject.name = "Compact Machines 21.0" + +dependencyResolutionManagement { + versionCatalogs.create("neoforged") { + version("mdg", "1.0.13") + version("neoforge", "21.0.109-beta") + version("neogradle", "7.0.145") + version("neoforgeRange") { + require("[21.0,22)") + prefer("21.0.2-beta") + } + + plugin("moddev", "net.neoforged.moddev") + .versionRef("mdg") + + plugin("userdev", "net.neoforged.gradle.userdev") + .versionRef("neogradle") + + library("neoforge", "net.neoforged", "neoforge") + .versionRef("neoforge") + + library("testframework", "net.neoforged", "testframework") + .versionRef("neoforge") + + bundle("neoforge", listOf("neoforge", "testframework")) + } + + versionCatalogs.create("mojang") { + version("minecraft", "1.20.6") + version("minecraftRange") { + this.require("[1.21, 1.21.1)") + this.prefer("1.21") + } + } + + versionCatalogs.create("libraries") { + library("feather", "dev.compactmods", "feather") + .versionRef("feather") + + library("jnanoid", "com.aventrix.jnanoid", "jnanoid") + .versionRef("jnanoid") + + version("feather", "[0.1.8, 2.0)") + version("jnanoid", "[2.0.0, 3)") + + version("parchment-mc", "1.20.6") + version("parchment", "2024.05.01") + } + + versionCatalogs.create("mods") { + this.library("jei-common", "mezz.jei", "jei-1.20.4-common-api").versionRef("jei") + this.library("jei-neo", "mezz.jei", "jei-1.20.4-neoforge-api").versionRef("jei"); + this.bundle("jei", listOf("jei-common", "jei-neo")) + this.version("jei", "17.3.0.49") + + this.library("jade", "curse.maven", "jade-324717").version("5109393") + } +} + +pluginManagement { + plugins { + id("idea") + id("eclipse") + id("maven-publish") + } + + repositories { + mavenLocal() + mavenCentral() + gradlePluginPortal() + + // maven("https://maven.architectury.dev/") + +// maven("https://maven.parchmentmc.org") { +// name = "ParchmentMC" +// } + + maven("https://maven.neoforged.net/releases") { + name = "NeoForged" + } + } +} + +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version ("0.8.0") +} + +include(":core-api") +include(":neoforge-main") +include(":neoforge-datagen") +